package handlers import ( "fmt" "strconv" "time" "github.com/gizak/termui" "github.com/nlopes/slack" "github.com/erroneousboat/slack-term/src/context" "github.com/erroneousboat/slack-term/src/views" ) func RegisterEventHandlers(ctx *context.AppContext) { termui.Handle("/sys/kbd/", anyKeyHandler(ctx)) termui.Handle("/sys/wnd/resize", resizeHandler(ctx)) termui.Handle("/timer/1s", timeHandler(ctx)) incomingMessageHandler(ctx) } func anyKeyHandler(ctx *context.AppContext) func(termui.Event) { return func(e termui.Event) { key := e.Data.(termui.EvtKbd).KeyStr if ctx.Mode == context.CommandMode { switch key { case "q": actionQuit() return case "j": actionMoveCursorDownChannels(ctx) return case "k": actionMoveCursorUpChannels(ctx) return case "i": actionInsertMode(ctx) return } } else if ctx.Mode == context.InsertMode { switch key { case "": actionCommandMode(ctx) return case "": actionSend(ctx) return case "": actionInput(ctx.View, " ") return case "": actionBackSpace(ctx.View) case "C-8": actionBackSpace(ctx.View) case "": actionMoveCursorRight(ctx.View) case "": actionMoveCursorLeft(ctx.View) default: actionInput(ctx.View, key) return } } } } func resizeHandler(ctx *context.AppContext) func(termui.Event) { return func(e termui.Event) { actionResize(ctx) } } func timeHandler(ctx *context.AppContext) func(termui.Event) { return func(e termui.Event) { } } // TODO: it'll always add the latest message func incomingMessageHandler(ctx *context.AppContext) { go func() { for { select { case msg := <-ctx.Service.RTM.IncomingEvents: switch ev := msg.Data.(type) { case *slack.MessageEvent: // TODO: refactor this to CreateMessage var name string user, err := ctx.Service.Client.GetUserInfo(ev.User) if err == nil { name = user.Name } else { name = "unknown" } // Parse the time we get from slack which is a Unix time float floatTime, err := strconv.ParseFloat(ev.Timestamp, 64) if err != nil { floatTime = 0.0 } intTime := int64(floatTime) m := fmt.Sprintf( "[%s] <%s> %s", time.Unix(intTime, 0).Format("15:04"), name, ev.Text, ) // Add message to the selected channel if ev.Channel == ctx.View.Channels.SlackChannels[ctx.View.Channels.SelectedChannel].ID { ctx.View.Chat.AddMessage(m) termui.Render(ctx.View.Chat) } } } } }() } // FIXME: resize only seems to work for width and resizing it too small // will cause termui to panic func actionResize(ctx *context.AppContext) { termui.Body.Width = termui.TermWidth() termui.Body.Align() termui.Render(termui.Body) } func actionInput(view *views.View, key string) { view.Input.Insert(key) termui.Render(view.Input) } func actionBackSpace(view *views.View) { view.Input.Remove() termui.Render(view.Input) } func actionMoveCursorRight(view *views.View) { view.Input.MoveCursorRight() termui.Render(view.Input) } func actionMoveCursorLeft(view *views.View) { view.Input.MoveCursorLeft() termui.Render(view.Input) } func actionSend(ctx *context.AppContext) { if !ctx.View.Input.IsEmpty() { ctx.View.Input.SendMessage( ctx.Service, ctx.View.Channels.SlackChannels[ctx.View.Channels.SelectedChannel].ID, ctx.View.Input.Text(), ) ctx.View.Input.Clear() ctx.View.Refresh() } } func actionQuit() { termui.StopLoop() } func actionInsertMode(ctx *context.AppContext) { ctx.Mode = context.InsertMode ctx.View.Mode.Par.Text = "INSERT" termui.Render(ctx.View.Mode) } func actionCommandMode(ctx *context.AppContext) { ctx.Mode = context.CommandMode ctx.View.Mode.Par.Text = "NORMAL" termui.Render(ctx.View.Mode) } func actionGetMessages(ctx *context.AppContext) { ctx.View.Chat.GetMessages( ctx.Service, ctx.View.Channels.SlackChannels[ctx.View.Channels.SelectedChannel].ID, ) termui.Render(ctx.View.Chat) } func actionGetChannels(ctx *context.AppContext) { ctx.View.Channels.GetChannels(ctx.Service) termui.Render(ctx.View.Channels) } func actionMoveCursorUpChannels(ctx *context.AppContext) { ctx.View.Channels.MoveCursorUp() ctx.View.Chat.GetMessages( ctx.Service, ctx.View.Channels.SlackChannels[ctx.View.Channels.SelectedChannel].ID, ) termui.Render(ctx.View.Channels) termui.Render(ctx.View.Chat) } func actionMoveCursorDownChannels(ctx *context.AppContext) { ctx.View.Channels.MoveCursorDown() ctx.View.Chat.GetMessages( ctx.Service, ctx.View.Channels.SlackChannels[ctx.View.Channels.SelectedChannel].ID, ) termui.Render(ctx.View.Channels) termui.Render(ctx.View.Chat) }