Add scrolling to chat pane

This commit is contained in:
erroneousboat 2016-09-30 16:36:41 +02:00
parent 5f06f4ce5c
commit e44a694daf
4 changed files with 61 additions and 8 deletions

View File

@ -12,6 +12,10 @@ Bugs:
through RTM in the selected channel through RTM in the selected channel
- [x] uncovering usernames takes too long, should find a better way - [x] uncovering usernames takes too long, should find a better way
test without uncovering, if that is the problem 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 - [ ] GetMessages for a channel can result in `json: cannot unmarshal number
into Go value of type string` https://github.com/nlopes/slack/issues/92 into Go value of type string` https://github.com/nlopes/slack/issues/92
- [ ] docs at exported functions - [ ] docs at exported functions
@ -20,6 +24,6 @@ Features:
- [x] channel name in chat pane - [x] channel name in chat pane
- [x] new message indicator - [x] new message indicator
- [x] scrolling in chat pane
- [ ] group channels, im channels - [ ] group channels, im channels
- [ ] scrolling in chat pane
- [ ] scrolling in channel pane - [ ] scrolling in channel pane

View File

@ -140,9 +140,11 @@ func (c *Channels) NewMessage(channelID string) {
} }
} }
// The order of SlackChannels relates to the order of if !strings.Contains(c.List.Items[index], "*") {
// List.Items, index will be the index of the channel // The order of SlackChannels relates to the order of
c.List.Items[index] = fmt.Sprintf("* %s", strings.TrimSpace(c.List.Items[index])) // 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 // Play terminal bell sound
fmt.Print("\a") fmt.Print("\a")

View File

@ -10,12 +10,14 @@ import (
type Chat struct { type Chat struct {
List *termui.List List *termui.List
SelectedChannel string SelectedChannel string
Offset int
} }
// CreateChat is the constructor for the Chat struct // CreateChat is the constructor for the Chat struct
func CreateChat(svc *service.SlackService, inputHeight int, selectedChannel SlackChannel) *Chat { func CreateChat(svc *service.SlackService, inputHeight int, selectedChannel SlackChannel) *Chat {
chat := &Chat{ chat := &Chat{
List: termui.NewList(), List: termui.NewList(),
Offset: 0,
} }
chat.List.Height = termui.TermHeight() - inputHeight chat.List.Height = termui.TermHeight() - inputHeight
@ -68,14 +70,16 @@ func (c *Chat) Buffer() termui.Buffer {
lines = append(lines, line) lines = append(lines, line)
// We will print lines bottom up, it will loop over the lines // 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() buf := c.List.Buffer()
linesHeight := len(lines) linesHeight := len(lines)
paneMinY := c.List.InnerBounds().Min.Y paneMinY := c.List.InnerBounds().Min.Y
paneMaxY := c.List.InnerBounds().Max.Y paneMaxY := c.List.InnerBounds().Max.Y
currentY := paneMaxY - 1 currentY := paneMaxY - 1
for i := linesHeight - 1; i >= 0; i-- { for i := (linesHeight - 1) - c.Offset; i >= 0; i-- {
if currentY < paneMinY { if currentY < paneMinY {
break break
} }
@ -152,10 +156,37 @@ func (c *Chat) ClearMessages() {
c.List.Items = []string{} 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() { 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 // SetBorderLabel will set Label of the Chat pane to the specified string
func (c *Chat) SetBorderLabel(label string) { func (c *Chat) SetBorderLabel(label string) {

View File

@ -33,6 +33,10 @@ func anyKeyHandler(ctx *context.AppContext) func(termui.Event) {
case "i": case "i":
actionInsertMode(ctx) actionInsertMode(ctx)
return return
case "<previous>":
actionScrollUpChat(ctx)
case "<next>":
actionScrollDownChat(ctx)
} }
} else if ctx.Mode == context.InsertMode { } else if ctx.Mode == context.InsertMode {
switch key { switch key {
@ -89,6 +93,8 @@ func incomingMessageHandler(ctx *context.AppContext) {
if ev.Channel == ctx.View.Channels.SlackChannels[ctx.View.Channels.SelectedChannel].ID { if ev.Channel == ctx.View.Channels.SlackChannels[ctx.View.Channels.SelectedChannel].ID {
ctx.View.Chat.AddMessage(m) ctx.View.Chat.AddMessage(m)
termui.Render(ctx.View.Chat) termui.Render(ctx.View.Chat)
// TODO: set Chat.Offset to 0?
} }
// Set new message indicator for channel // Set new message indicator for channel
@ -202,3 +208,13 @@ func actionNewMessage(ctx *context.AppContext, channelID string) {
ctx.View.Channels.NewMessage(channelID) ctx.View.Channels.NewMessage(channelID)
termui.Render(ctx.View.Channels) 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)
}