@@ -9,6 +9,18 @@ import (
99 "github.com/erroneousboat/slack-term/service"
1010)
1111
12+ const (
13+ IconOnline = "●"
14+ IconOffline = "○"
15+ IconChannel = "#"
16+ IconGroup = "☰"
17+ IconIM = "●"
18+ IconNotification = "🞷"
19+
20+ PresenceAway = "away"
21+ PresenceActive = "active"
22+ )
23+
1224// Channels is the definition of a Channels component
1325type Channels struct {
1426 List * termui.List
@@ -31,6 +43,7 @@ func CreateChannels(svc *service.SlackService, inputHeight int) *Channels {
3143 channels .CursorPosition = channels .List .InnerBounds ().Min .Y
3244
3345 channels .GetChannels (svc )
46+ channels .SetPresenceForIMChannels (svc )
3447
3548 return channels
3649}
@@ -115,7 +128,23 @@ func (c *Channels) SetY(y int) {
115128// GetChannels will get all available channels from the SlackService
116129func (c * Channels ) GetChannels (svc * service.SlackService ) {
117130 for _ , slackChan := range svc .GetChannels () {
118- c .List .Items = append (c .List .Items , fmt .Sprintf (" %s" , slackChan .Name ))
131+ label := setChannelLabel (slackChan , false )
132+ c .List .Items = append (c .List .Items , label )
133+
134+ }
135+ }
136+
137+ // SetPresenceForIMChannels this will set the correct icon for
138+ // IM channels for when they're online of away
139+ func (c * Channels ) SetPresenceForIMChannels (svc * service.SlackService ) {
140+ for _ , slackChan := range svc .GetChannels () {
141+ if slackChan .Type == service .ChannelTypeIM {
142+ presence , err := svc .GetUserPresence (slackChan .UserID )
143+ if err != nil {
144+ continue
145+ }
146+ c .SetPresence (svc , slackChan .UserID , presence )
147+ }
119148 }
120149}
121150
@@ -166,6 +195,7 @@ func (c *Channels) MoveCursorBottom() {
166195
167196// ScrollUp enables us to scroll through the channel list when it overflows
168197func (c * Channels ) ScrollUp () {
198+ // Is cursor at the top of the channel view?
169199 if c .CursorPosition == c .List .InnerBounds ().Min .Y {
170200 if c .Offset > 0 {
171201 c .Offset --
@@ -177,6 +207,7 @@ func (c *Channels) ScrollUp() {
177207
178208// ScrollDown enables us to scroll through the channel list when it overflows
179209func (c * Channels ) ScrollDown () {
210+ // Is the cursor at the bottom of the channel view?
180211 if c .CursorPosition == c .List .InnerBounds ().Max .Y - 1 {
181212 if c .Offset < len (c .List .Items )- 1 {
182213 c .Offset ++
@@ -186,41 +217,138 @@ func (c *Channels) ScrollDown() {
186217 }
187218}
188219
189- // NewMessage will be called when a new message arrives and will
190- // render an asterisk in front of the channel name
191- func (c * Channels ) NewMessage (svc * service.SlackService , channelID string ) {
192- var index int
220+ // Search will search through the channels to find a channel,
221+ // when a match has been found the selected channel will then
222+ // be the channel that has been found
223+ func (c * Channels ) Search (term string ) {
224+ for i , item := range c .List .Items {
225+ if strings .Contains (item , term ) {
226+
227+ // The new position
228+ newPos := i
229+
230+ // Is the new position in range of the current view?
231+ minRange := c .Offset
232+ maxRange := c .Offset + (c .List .InnerBounds ().Max .Y - 2 )
233+
234+ if newPos < minRange {
235+ // newPos is above, we need to scroll up.
236+ c .SetSelectedChannel (i )
237+
238+ // How much do we need to scroll to get it into range?
239+ c .Offset = c .Offset - (minRange - newPos )
240+ } else if newPos > maxRange {
241+ // newPos is below, we need to scroll down
242+ c .SetSelectedChannel (i )
243+
244+ // How much do we need to scroll to get it into range?
245+ c .Offset = c .Offset + (newPos - maxRange )
246+ } else {
247+ // newPos is inside range
248+ c .SetSelectedChannel (i )
249+ }
250+
251+ // Set cursor to correct position
252+ c .CursorPosition = (newPos - c .Offset ) + 1
253+
254+ break
255+ }
256+ }
257+ }
193258
259+ // SetNotification will be called when a new message arrives and will
260+ // render an notification icon in front of the channel name
261+ func (c * Channels ) SetNotification (svc * service.SlackService , channelID string ) {
194262 // Get the correct Channel from svc.Channels
263+ var index int
195264 for i , channel := range svc .Channels {
196265 if channelID == channel .ID {
197266 index = i
198267 break
199268 }
200269 }
201270
202- if ! strings .Contains (c .List .Items [index ], "*" ) {
271+ if ! strings .Contains (c .List .Items [index ], IconNotification ) {
203272 // The order of svc.Channels relates to the order of
204273 // List.Items, index will be the index of the channel
205- c .List .Items [index ] = fmt .Sprintf ("* %s" , strings .TrimSpace (c .List .Items [index ]))
274+ c .List .Items [index ] = fmt .Sprintf (
275+ "%s %s" , IconNotification , strings .TrimSpace (c .List .Items [index ]),
276+ )
206277 }
207278
208279 // Play terminal bell sound
209280 fmt .Print ("\a " )
210281}
211282
212- // ClearNewMessageIndicator will remove the asterisk in front of a channel that
213- // received a new message. This will happen as one will move up or down the
214- // cursor for Channels
283+ // ClearNewMessageIndicator will remove the notification icon in front of
284+ // a channel that received a new message. This will happen as one will
285+ // move up or down the cursor for Channels
215286func (c * Channels ) ClearNewMessageIndicator () {
216- channelName := strings .Split (c .List .Items [c .SelectedChannel ], "* " )
287+ channelName := strings .Split (
288+ c .List .Items [c .SelectedChannel ],
289+ fmt .Sprintf ("%s " , IconNotification ),
290+ )
291+
217292 if len (channelName ) > 1 {
218293 c .List .Items [c .SelectedChannel ] = fmt .Sprintf (" %s" , channelName [1 ])
219294 } else {
220295 c .List .Items [c .SelectedChannel ] = channelName [0 ]
221296 }
222297}
223298
299+ // SetReadMark will send the ReadMark event on the service
224300func (c * Channels ) SetReadMark (svc * service.SlackService ) {
225301 svc .SetChannelReadMark (svc .SlackChannels [c .SelectedChannel ])
226302}
303+
304+ // SetPresence will set the correct icon for a IM Channel
305+ func (c * Channels ) SetPresence (svc * service.SlackService , userID string , presence string ) {
306+ // Get the correct Channel from svc.Channels
307+ var index int
308+ for i , channel := range svc .Channels {
309+ if userID == channel .UserID {
310+ index = i
311+ break
312+ }
313+ }
314+
315+ switch presence {
316+ case PresenceActive :
317+ c .List .Items [index ] = strings .Replace (
318+ c .List .Items [index ], IconOffline , IconOnline , 1 ,
319+ )
320+ case PresenceAway :
321+ c .List .Items [index ] = strings .Replace (
322+ c .List .Items [index ], IconOnline , IconOffline , 1 ,
323+ )
324+ default :
325+ c .List .Items [index ] = strings .Replace (
326+ c .List .Items [index ], IconOnline , IconOffline , 1 ,
327+ )
328+ }
329+
330+ }
331+
332+ // setChannelLabel will set the label of the channel, meaning, how it
333+ // is displayed on screen. Based on the type, different icons are
334+ // shown, as well as an optional notification icon.
335+ func setChannelLabel (channel service.Channel , notification bool ) string {
336+ var prefix string
337+ if notification {
338+ prefix = IconNotification
339+ } else {
340+ prefix = " "
341+ }
342+
343+ var label string
344+ switch channel .Type {
345+ case service .ChannelTypeChannel :
346+ label = fmt .Sprintf ("%s %s %s" , prefix , IconChannel , channel .Name )
347+ case service .ChannelTypeGroup :
348+ label = fmt .Sprintf ("%s %s %s" , prefix , IconGroup , channel .Name )
349+ case service .ChannelTypeIM :
350+ label = fmt .Sprintf ("%s %s %s" , prefix , IconIM , channel .Name )
351+ }
352+
353+ return label
354+ }
0 commit comments