Make scrollable channel pane
This commit is contained in:
parent
e71602c214
commit
aa7830ce35
8
TODO.md
8
TODO.md
@ -19,12 +19,14 @@ Bugs:
|
||||
- [ ] 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
|
||||
- [ ] incoming message event.go probably need a type switch
|
||||
- [ ] set channel on start
|
||||
|
||||
Features:
|
||||
|
||||
- [x] channel name in chat pane
|
||||
- [x] new message indicator
|
||||
- [x] scrolling in chat pane
|
||||
- [ ] group channels, im channels
|
||||
- [ ] incomming message event.go probably need a type switch
|
||||
- [ ] scrolling in channel pane
|
||||
- [x] group channels, im channels
|
||||
- [x] scrolling in channel pane
|
||||
- [ ] remove unsubscribed or closed channels/groups/im
|
||||
|
@ -11,13 +11,11 @@ import (
|
||||
type Channels struct {
|
||||
List *termui.List
|
||||
SelectedChannel int
|
||||
Offset int
|
||||
CursorPosition int
|
||||
}
|
||||
|
||||
type SlackChannel struct {
|
||||
Name string
|
||||
ID string
|
||||
}
|
||||
|
||||
// CreateChannels is the constructor for the Channels component
|
||||
func CreateChannels(svc *service.SlackService, inputHeight int) *Channels {
|
||||
channels := &Channels{
|
||||
List: termui.NewList(),
|
||||
@ -27,6 +25,8 @@ func CreateChannels(svc *service.SlackService, inputHeight int) *Channels {
|
||||
channels.List.Height = termui.TermHeight() - inputHeight
|
||||
|
||||
channels.SelectedChannel = 0
|
||||
channels.Offset = 0
|
||||
channels.CursorPosition = channels.List.InnerBounds().Min.Y
|
||||
|
||||
channels.GetChannels(svc)
|
||||
|
||||
@ -37,9 +37,16 @@ func CreateChannels(svc *service.SlackService, inputHeight int) *Channels {
|
||||
func (c *Channels) Buffer() termui.Buffer {
|
||||
buf := c.List.Buffer()
|
||||
|
||||
for y, item := range c.List.Items {
|
||||
for i, item := range c.List.Items[c.Offset:] {
|
||||
|
||||
y := c.List.InnerBounds().Min.Y + i
|
||||
|
||||
if y > c.List.InnerBounds().Max.Y-1 {
|
||||
break
|
||||
}
|
||||
|
||||
var cells []termui.Cell
|
||||
if y == c.SelectedChannel {
|
||||
if y == c.CursorPosition {
|
||||
cells = termui.DefaultTxBuilder.Build(
|
||||
item, termui.ColorBlack, termui.ColorWhite)
|
||||
} else {
|
||||
@ -52,13 +59,23 @@ func (c *Channels) Buffer() termui.Buffer {
|
||||
x := 0
|
||||
for _, cell := range cells {
|
||||
width := cell.Width()
|
||||
buf.Set(
|
||||
c.List.InnerBounds().Min.X+x,
|
||||
c.List.InnerBounds().Min.Y+y,
|
||||
cell,
|
||||
)
|
||||
buf.Set(c.List.InnerBounds().Min.X+x, y, cell)
|
||||
x += width
|
||||
}
|
||||
|
||||
// When not at the end of the pane fill it up empty characters
|
||||
for x < c.List.InnerBounds().Max.X-1 {
|
||||
if y == c.CursorPosition {
|
||||
buf.Set(x+1, y,
|
||||
termui.Cell{
|
||||
Ch: ' ', Fg: termui.ColorBlack, Bg: termui.ColorWhite,
|
||||
},
|
||||
)
|
||||
} else {
|
||||
buf.Set(x+1, y, termui.Cell{Ch: ' '})
|
||||
}
|
||||
x++
|
||||
}
|
||||
}
|
||||
|
||||
return buf
|
||||
@ -85,9 +102,6 @@ func (c *Channels) SetY(y int) {
|
||||
}
|
||||
|
||||
// GetChannels will get all available channels from the SlackService
|
||||
// and add them to the List as well as to the SlackChannels, this is done
|
||||
// to better relate the ID and name given to Channels, for Chat.GetMessages.
|
||||
// See event.go actionChangeChannel for more explanation
|
||||
func (c *Channels) GetChannels(svc *service.SlackService) {
|
||||
for _, slackChan := range svc.GetChannels() {
|
||||
c.List.Items = append(c.List.Items, fmt.Sprintf(" %s", slackChan.Name))
|
||||
@ -103,6 +117,7 @@ func (c *Channels) SetSelectedChannel(index int) {
|
||||
func (c *Channels) MoveCursorUp() {
|
||||
if c.SelectedChannel > 0 {
|
||||
c.SetSelectedChannel(c.SelectedChannel - 1)
|
||||
c.ScrollUp()
|
||||
c.ClearNewMessageIndicator()
|
||||
}
|
||||
}
|
||||
@ -111,16 +126,37 @@ func (c *Channels) MoveCursorUp() {
|
||||
func (c *Channels) MoveCursorDown() {
|
||||
if c.SelectedChannel < len(c.List.Items)-1 {
|
||||
c.SetSelectedChannel(c.SelectedChannel + 1)
|
||||
c.ScrollDown()
|
||||
c.ClearNewMessageIndicator()
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Channels) ScrollUp() {
|
||||
if c.CursorPosition == c.List.InnerBounds().Min.Y {
|
||||
if c.Offset > 0 {
|
||||
c.Offset--
|
||||
}
|
||||
} else {
|
||||
c.CursorPosition--
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Channels) ScrollDown() {
|
||||
if c.CursorPosition == c.List.InnerBounds().Max.Y-1 {
|
||||
if c.Offset < len(c.List.Items)-1 {
|
||||
c.Offset++
|
||||
}
|
||||
} else {
|
||||
c.CursorPosition++
|
||||
}
|
||||
}
|
||||
|
||||
// NewMessage will be called when a new message arrives and will
|
||||
// render an asterisk in front of the channel name
|
||||
func (c *Channels) NewMessage(svc *service.SlackService, channelID string) {
|
||||
var index int
|
||||
|
||||
// Get the correct Channel from SlackChannels
|
||||
// Get the correct Channel from svc.Channels
|
||||
for i, channel := range svc.Channels {
|
||||
if channelID == channel.ID {
|
||||
index = i
|
||||
@ -129,7 +165,7 @@ func (c *Channels) NewMessage(svc *service.SlackService, channelID string) {
|
||||
}
|
||||
|
||||
if !strings.Contains(c.List.Items[index], "*") {
|
||||
// The order of SlackChannels relates to the order of
|
||||
// The order of svc.Channels 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]))
|
||||
}
|
||||
|
@ -94,10 +94,14 @@ func incomingMessageHandler(ctx *context.AppContext) {
|
||||
ctx.View.Chat.AddMessage(m)
|
||||
termui.Render(ctx.View.Chat)
|
||||
|
||||
// TODO: set Chat.Offset to 0?
|
||||
// TODO: set Chat.Offset to 0, to automatically scroll
|
||||
// down?
|
||||
}
|
||||
|
||||
// Set new message indicator for channel
|
||||
// Set new message indicator for channel, I'm leaving
|
||||
// this here because I also want to be notified when
|
||||
// I'm currently in a channel but not in the terminal
|
||||
// window (tmux)
|
||||
actionNewMessage(ctx, ev.Channel)
|
||||
}
|
||||
}
|
||||
|
@ -55,14 +55,14 @@ func (s *SlackService) GetChannels() []Channel {
|
||||
|
||||
// TODO: json: cannot unmarshal number into Go value of type string, GetMessages
|
||||
// Groups
|
||||
// slackGroups, err := s.Client.GetGroups(true)
|
||||
// if err != nil {
|
||||
// chans = append(chans, Channel{})
|
||||
// }
|
||||
// for _, grp := range slackGroups {
|
||||
// s.SlackChannels = append(s.SlackChannels, grp)
|
||||
// chans = append(chans, Channel{grp.ID, grp.Name})
|
||||
// }
|
||||
slackGroups, err := s.Client.GetGroups(true)
|
||||
if err != nil {
|
||||
chans = append(chans, Channel{})
|
||||
}
|
||||
for _, grp := range slackGroups {
|
||||
s.SlackChannels = append(s.SlackChannels, grp)
|
||||
chans = append(chans, Channel{grp.ID, grp.Name})
|
||||
}
|
||||
|
||||
// IM
|
||||
slackIM, err := s.Client.GetIMChannels()
|
||||
@ -71,7 +71,13 @@ func (s *SlackService) GetChannels() []Channel {
|
||||
}
|
||||
for _, im := range slackIM {
|
||||
s.SlackChannels = append(s.SlackChannels, im)
|
||||
chans = append(chans, Channel{im.ID, im.User})
|
||||
|
||||
// Uncover name
|
||||
name, ok := s.UserCache[im.User]
|
||||
if !ok {
|
||||
name = im.User
|
||||
}
|
||||
chans = append(chans, Channel{im.ID, name})
|
||||
}
|
||||
|
||||
s.Channels = chans
|
||||
|
Loading…
Reference in New Issue
Block a user