diff --git a/TODO.md b/TODO.md index 82b806e..0d6fe41 100644 --- a/TODO.md +++ b/TODO.md @@ -12,6 +12,10 @@ Bugs: through RTM in the selected channel - [x] uncovering usernames takes too long, should find a better way test without uncovering, if that is the problem +- [ ] GetMessages for a channel doesn't have to load messages based on height + of chat pane (y). Because message will sometimes span more than one + line and we're able to scroll. Only figure out how many messages you + want to load. - [ ] GetMessages for a channel can result in `json: cannot unmarshal number into Go value of type string` https://github.com/nlopes/slack/issues/92 - [ ] docs at exported functions @@ -20,6 +24,6 @@ Features: - [x] channel name in chat pane - [x] new message indicator +- [x] scrolling in chat pane - [ ] group channels, im channels -- [ ] scrolling in chat pane - [ ] scrolling in channel pane diff --git a/src/components/channels.go b/src/components/channels.go index ae7bc1c..fc1ffcd 100644 --- a/src/components/channels.go +++ b/src/components/channels.go @@ -140,9 +140,11 @@ func (c *Channels) NewMessage(channelID string) { } } - // The order of SlackChannels relates to the order of - // List.Items, index will be the index of the channel - c.List.Items[index] = fmt.Sprintf("* %s", strings.TrimSpace(c.List.Items[index])) + if !strings.Contains(c.List.Items[index], "*") { + // The order of SlackChannels relates to the order of + // List.Items, index will be the index of the channel + c.List.Items[index] = fmt.Sprintf("* %s", strings.TrimSpace(c.List.Items[index])) + } // Play terminal bell sound fmt.Print("\a") diff --git a/src/components/chat.go b/src/components/chat.go index dbdf44e..362e8ef 100644 --- a/src/components/chat.go +++ b/src/components/chat.go @@ -10,12 +10,14 @@ import ( type Chat struct { List *termui.List SelectedChannel string + Offset int } // CreateChat is the constructor for the Chat struct func CreateChat(svc *service.SlackService, inputHeight int, selectedChannel SlackChannel) *Chat { chat := &Chat{ - List: termui.NewList(), + List: termui.NewList(), + Offset: 0, } chat.List.Height = termui.TermHeight() - inputHeight @@ -68,14 +70,16 @@ func (c *Chat) Buffer() termui.Buffer { lines = append(lines, line) // We will print lines bottom up, it will loop over the lines - // backwards and for every line it'll set the cell in that line + // backwards and for every line it'll set the cell in that line. + // Offset is the number which allows us to begin printing the + // line above the last line. buf := c.List.Buffer() linesHeight := len(lines) paneMinY := c.List.InnerBounds().Min.Y paneMaxY := c.List.InnerBounds().Max.Y currentY := paneMaxY - 1 - for i := linesHeight - 1; i >= 0; i-- { + for i := (linesHeight - 1) - c.Offset; i >= 0; i-- { if currentY < paneMinY { break } @@ -152,10 +156,37 @@ func (c *Chat) ClearMessages() { c.List.Items = []string{} } +// ScrollUp will render the chat messages based on the Offset of the Chat +// pane. +// +// Offset is 0 when scrolled down. (we loop backwards over the array, so we +// start with rendering last item in the list at the maximum y of the Chat +// pane). Increasing the Offset will thus result in substracting the offset +// from the len(Chat.List.Items). func (c *Chat) ScrollUp() { + c.Offset = c.Offset + 10 + + // Protect overscrolling + if c.Offset > len(c.List.Items)-1 { + c.Offset = len(c.List.Items) - 1 + } } -func (c *Chat) ScrollDown() {} +// ScrollDown will render the chat messages based on the Offset of the Chat +// pane. +// +// Offset is 0 when scrolled down. (we loop backwards over the array, so we +// start with rendering last item in the list at the maximum y of the Chat +// pane). Increasing the Offset will thus result in substracting the offset +// from the len(Chat.List.Items). +func (c *Chat) ScrollDown() { + c.Offset = c.Offset - 10 + + // Protect overscrolling + if c.Offset < 0 { + c.Offset = 0 + } +} // SetBorderLabel will set Label of the Chat pane to the specified string func (c *Chat) SetBorderLabel(label string) { diff --git a/src/handlers/event.go b/src/handlers/event.go index 6782e3e..a4196eb 100644 --- a/src/handlers/event.go +++ b/src/handlers/event.go @@ -33,6 +33,10 @@ func anyKeyHandler(ctx *context.AppContext) func(termui.Event) { case "i": actionInsertMode(ctx) return + case "": + actionScrollUpChat(ctx) + case "": + actionScrollDownChat(ctx) } } else if ctx.Mode == context.InsertMode { switch key { @@ -89,6 +93,8 @@ func incomingMessageHandler(ctx *context.AppContext) { if ev.Channel == ctx.View.Channels.SlackChannels[ctx.View.Channels.SelectedChannel].ID { ctx.View.Chat.AddMessage(m) termui.Render(ctx.View.Chat) + + // TODO: set Chat.Offset to 0? } // Set new message indicator for channel @@ -202,3 +208,13 @@ func actionNewMessage(ctx *context.AppContext, channelID string) { ctx.View.Channels.NewMessage(channelID) termui.Render(ctx.View.Channels) } + +func actionScrollUpChat(ctx *context.AppContext) { + ctx.View.Chat.ScrollUp() + termui.Render(ctx.View.Chat) +} + +func actionScrollDownChat(ctx *context.AppContext) { + ctx.View.Chat.ScrollDown() + termui.Render(ctx.View.Chat) +}