Skip to content

Commit

Permalink
Merge branch 'v0.2.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
jpbruinsslot committed Jul 31, 2017
2 parents 6fdaaba + 8440d01 commit f759bb1
Show file tree
Hide file tree
Showing 9 changed files with 1,903 additions and 64 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ Getting started
"C-8": "backspace",
"<delete>": "delete",
"<space>": "space"
},
"search": {
"<left>": "cursor-left",
"<right>": "cursor-right",
"<escape>": "clear-input",
"<enter>": "clear-input",
"<backspace>": "backspace",
"C-8": "backspace",
"<delete>": "delete",
"<space>": "space"
}
}
}
Expand All @@ -79,6 +89,7 @@ Default Key Mapping
| mode | key | action |
|---------|-----------|----------------------------|
| command | `i` | insert mode |
| command | `/` | search mode |
| command | `k` | move channel cursor up |
| command | `j` | move channel cursor down |
| command | `g` | move channel cursor top |
Expand All @@ -95,3 +106,5 @@ Default Key Mapping
| insert | `right` | move input cursor right |
| insert | `enter` | send message |
| insert | `esc` | command mode |
| search | `esc` | command mode |
| search | `enter` | command mode |
150 changes: 139 additions & 11 deletions components/channels.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@ import (
"github.com/erroneousboat/slack-term/service"
)

const (
IconOnline = "●"
IconOffline = "○"
IconChannel = "#"
IconGroup = "☰"
IconIM = "●"
IconNotification = "🞷"

PresenceAway = "away"
PresenceActive = "active"
)

// Channels is the definition of a Channels component
type Channels struct {
List *termui.List
Expand All @@ -31,6 +43,7 @@ func CreateChannels(svc *service.SlackService, inputHeight int) *Channels {
channels.CursorPosition = channels.List.InnerBounds().Min.Y

channels.GetChannels(svc)
channels.SetPresenceForIMChannels(svc)

return channels
}
Expand Down Expand Up @@ -115,7 +128,23 @@ func (c *Channels) SetY(y int) {
// GetChannels will get all available channels from the SlackService
func (c *Channels) GetChannels(svc *service.SlackService) {
for _, slackChan := range svc.GetChannels() {
c.List.Items = append(c.List.Items, fmt.Sprintf(" %s", slackChan.Name))
label := setChannelLabel(slackChan, false)
c.List.Items = append(c.List.Items, label)

}
}

// SetPresenceForIMChannels this will set the correct icon for
// IM channels for when they're online of away
func (c *Channels) SetPresenceForIMChannels(svc *service.SlackService) {
for _, slackChan := range svc.GetChannels() {
if slackChan.Type == service.ChannelTypeIM {
presence, err := svc.GetUserPresence(slackChan.UserID)
if err != nil {
continue
}
c.SetPresence(svc, slackChan.UserID, presence)
}
}
}

Expand Down Expand Up @@ -166,6 +195,7 @@ func (c *Channels) MoveCursorBottom() {

// ScrollUp enables us to scroll through the channel list when it overflows
func (c *Channels) ScrollUp() {
// Is cursor at the top of the channel view?
if c.CursorPosition == c.List.InnerBounds().Min.Y {
if c.Offset > 0 {
c.Offset--
Expand All @@ -177,6 +207,7 @@ func (c *Channels) ScrollUp() {

// ScrollDown enables us to scroll through the channel list when it overflows
func (c *Channels) ScrollDown() {
// Is the cursor at the bottom of the channel view?
if c.CursorPosition == c.List.InnerBounds().Max.Y-1 {
if c.Offset < len(c.List.Items)-1 {
c.Offset++
Expand All @@ -186,41 +217,138 @@ func (c *Channels) ScrollDown() {
}
}

// 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
// Search will search through the channels to find a channel,
// when a match has been found the selected channel will then
// be the channel that has been found
func (c *Channels) Search(term string) {
for i, item := range c.List.Items {
if strings.Contains(item, term) {

// The new position
newPos := i

// Is the new position in range of the current view?
minRange := c.Offset
maxRange := c.Offset + (c.List.InnerBounds().Max.Y - 2)

if newPos < minRange {
// newPos is above, we need to scroll up.
c.SetSelectedChannel(i)

// How much do we need to scroll to get it into range?
c.Offset = c.Offset - (minRange - newPos)
} else if newPos > maxRange {
// newPos is below, we need to scroll down
c.SetSelectedChannel(i)

// How much do we need to scroll to get it into range?
c.Offset = c.Offset + (newPos - maxRange)
} else {
// newPos is inside range
c.SetSelectedChannel(i)
}

// Set cursor to correct position
c.CursorPosition = (newPos - c.Offset) + 1

break
}
}
}

// SetNotification will be called when a new message arrives and will
// render an notification icon in front of the channel name
func (c *Channels) SetNotification(svc *service.SlackService, channelID string) {
// Get the correct Channel from svc.Channels
var index int
for i, channel := range svc.Channels {
if channelID == channel.ID {
index = i
break
}
}

if !strings.Contains(c.List.Items[index], "*") {
if !strings.Contains(c.List.Items[index], IconNotification) {
// 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]))
c.List.Items[index] = fmt.Sprintf(
"%s %s", IconNotification, strings.TrimSpace(c.List.Items[index]),
)
}

// Play terminal bell sound
fmt.Print("\a")
}

// ClearNewMessageIndicator will remove the asterisk in front of a channel that
// received a new message. This will happen as one will move up or down the
// cursor for Channels
// ClearNewMessageIndicator will remove the notification icon in front of
// a channel that received a new message. This will happen as one will
// move up or down the cursor for Channels
func (c *Channels) ClearNewMessageIndicator() {
channelName := strings.Split(c.List.Items[c.SelectedChannel], "* ")
channelName := strings.Split(
c.List.Items[c.SelectedChannel],
fmt.Sprintf("%s ", IconNotification),
)

if len(channelName) > 1 {
c.List.Items[c.SelectedChannel] = fmt.Sprintf(" %s", channelName[1])
} else {
c.List.Items[c.SelectedChannel] = channelName[0]
}
}

// SetReadMark will send the ReadMark event on the service
func (c *Channels) SetReadMark(svc *service.SlackService) {
svc.SetChannelReadMark(svc.SlackChannels[c.SelectedChannel])
}

// SetPresence will set the correct icon for a IM Channel
func (c *Channels) SetPresence(svc *service.SlackService, userID string, presence string) {
// Get the correct Channel from svc.Channels
var index int
for i, channel := range svc.Channels {
if userID == channel.UserID {
index = i
break
}
}

switch presence {
case PresenceActive:
c.List.Items[index] = strings.Replace(
c.List.Items[index], IconOffline, IconOnline, 1,
)
case PresenceAway:
c.List.Items[index] = strings.Replace(
c.List.Items[index], IconOnline, IconOffline, 1,
)
default:
c.List.Items[index] = strings.Replace(
c.List.Items[index], IconOnline, IconOffline, 1,
)
}

}

// setChannelLabel will set the label of the channel, meaning, how it
// is displayed on screen. Based on the type, different icons are
// shown, as well as an optional notification icon.
func setChannelLabel(channel service.Channel, notification bool) string {
var prefix string
if notification {
prefix = IconNotification
} else {
prefix = " "
}

var label string
switch channel.Type {
case service.ChannelTypeChannel:
label = fmt.Sprintf("%s %s %s", prefix, IconChannel, channel.Name)
case service.ChannelTypeGroup:
label = fmt.Sprintf("%s %s %s", prefix, IconGroup, channel.Name)
case service.ChannelTypeIM:
label = fmt.Sprintf("%s %s %s", prefix, IconIM, channel.Name)
}

return label
}
11 changes: 11 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func NewConfig(filepath string) (*Config, error) {
KeyMap: map[string]keyMapping{
"command": {
"i": "mode-insert",
"/": "mode-search",
"k": "channel-up",
"j": "channel-down",
"g": "channel-top",
Expand All @@ -51,6 +52,16 @@ func NewConfig(filepath string) (*Config, error) {
"<delete>": "delete",
"<space>": "space",
},
"search": {
"<left>": "cursor-left",
"<right>": "cursor-right",
"<escape>": "clear-input",
"<enter>": "clear-input",
"<backspace>": "backspace",
"C-8": "backspace",
"<delete>": "delete",
"<space>": "space",
},
},
}

Expand Down
Loading

0 comments on commit f759bb1

Please sign in to comment.