Skip to content

Commit

Permalink
Merge branch 'threads'
Browse files Browse the repository at this point in the history
* threads:
  Update comment
  Update threads reply functionality
  Add reply to threads functionality
  Fix thread timestamp checking
  Fix pagination problem
  Update handling thread replies in event handler
  Update message event
  Implement new Message setup
  Start with thread support

Reference #91
  • Loading branch information
jpbruinsslot committed Mar 16, 2019
2 parents 68d91ba + 2434ba7 commit 112524d
Show file tree
Hide file tree
Showing 6 changed files with 430 additions and 210 deletions.
195 changes: 95 additions & 100 deletions components/chat.go
Expand Up @@ -12,58 +12,19 @@ import (
"github.com/erroneousboat/slack-term/config"
)

var (
COLORS = []string{
"fg-black",
"fg-red",
"fg-green",
"fg-yellow",
"fg-blue",
"fg-magenta",
"fg-cyan",
"fg-white",
}
)

type Message struct {
Time time.Time
Name string
Content string

StyleTime string
StyleName string
StyleText string

FormatTime string
}

func (m Message) colorizeName(styleName string) string {
if strings.Contains(styleName, "colorize") {
var sum int
for _, c := range m.Name {
sum = sum + int(c)
}

i := sum % len(COLORS)

return strings.Replace(m.StyleName, "colorize", COLORS[i], -1)
}

return styleName
}

// Chat is the definition of a Chat component
type Chat struct {
List *termui.List
Messages []Message
Messages map[string]Message
Offset int
}

// CreateChat is the constructor for the Chat struct
func CreateChatComponent(inputHeight int) *Chat {
chat := &Chat{
List: termui.NewList(),
Offset: 0,
List: termui.NewList(),
Messages: make(map[string]Message),
Offset: 0,
}

chat.List.Height = termui.TermHeight() - inputHeight
Expand All @@ -74,59 +35,8 @@ func CreateChatComponent(inputHeight int) *Chat {

// Buffer implements interface termui.Bufferer
func (c *Chat) Buffer() termui.Buffer {
// Build cells. We're building parts of the message individually, or else
// DefaultTxBuilder will interpret potential markdown usage in a message
// as well.
cells := make([]termui.Cell, 0)
for i, msg := range c.Messages {

// When msg.Time and msg.Name are empty (in the case of attachments)
// don't add the time and name parts.
if (msg.Time != time.Time{} && msg.Name != "") {
// Time
cells = append(cells, termui.DefaultTxBuilder.Build(
fmt.Sprintf(
"[[%s]](%s) ",
msg.Time.Format(msg.FormatTime),
msg.StyleTime,
),
termui.ColorDefault, termui.ColorDefault)...,
)

// Name
cells = append(cells, termui.DefaultTxBuilder.Build(
fmt.Sprintf("[<%s>](%s) ",
msg.Name,
msg.colorizeName(msg.StyleName),
),
termui.ColorDefault, termui.ColorDefault)...,
)
}

// Hack, in order to get the correct fg and bg attributes. This is
// because the readAttr function in termui is unexported.
txCells := termui.DefaultTxBuilder.Build(
fmt.Sprintf("[.](%s)", msg.StyleText),
termui.ColorDefault, termui.ColorDefault,
)

// Text
for _, r := range msg.Content {
cells = append(
cells,
termui.Cell{
Ch: r,
Fg: txCells[0].Fg,
Bg: txCells[0].Bg,
},
)
}

// Add a newline after every message
if i < len(c.Messages)-1 {
cells = append(cells, termui.Cell{Ch: '\n'})
}
}
// Convert Messages into termui.Cell
cells := c.MessagesToCells(c.Messages)

// We will create an array of Line structs, this allows us
// to more easily render the items in a list. We will range
Expand Down Expand Up @@ -262,17 +172,26 @@ func (c *Chat) SetMessages(messages []Message) {
// Reset offset first, when scrolling in view and changing channels we
// want the offset to be 0 when loading new messages
c.Offset = 0
c.Messages = messages
for _, msg := range messages {
c.Messages[msg.ID] = msg
}
}

// AddMessage adds a single message to Messages
func (c *Chat) AddMessage(message Message) {
c.Messages = append(c.Messages, message)
c.Messages[message.ID] = message
}

// AddReply adds a single reply to a parent thread, it also sets
// the thread separator
func (c *Chat) AddReply(parentID string, message Message) {
message.Thread = " "
c.Messages[parentID].Messages[message.ID] = message
}

// ClearMessages clear the c.Messages
func (c *Chat) ClearMessages() {
c.Messages = make([]Message, 0)
c.Messages = make(map[string]Message)
}

// ScrollUp will render the chat messages based on the Offset of the Chat
Expand Down Expand Up @@ -312,6 +231,80 @@ func (c *Chat) SetBorderLabel(channelName string) {
c.List.BorderLabel = channelName
}

// MessagesToCells is a wrapper around MessageToCells to use for a slice of
// of type Message
func (c *Chat) MessagesToCells(msgs map[string]Message) []termui.Cell {
cells := make([]termui.Cell, 0)
sortedMessages := SortMessages(msgs)

for i, msg := range sortedMessages {
cells = append(cells, c.MessageToCells(msg)...)

if len(msg.Messages) > 0 {
cells = append(cells, termui.Cell{Ch: '\n'})
cells = append(cells, c.MessagesToCells(msg.Messages)...)
}

// Add a newline after every message
if i < len(sortedMessages)-1 {
cells = append(cells, termui.Cell{Ch: '\n'})
}
}

return cells
}

// MessageToCells will convert a Message struct to termui.Cell
//
// We're building parts of the message individually, or else DefaultTxBuilder
// will interpret potential markdown usage in a message as well.
func (c *Chat) MessageToCells(msg Message) []termui.Cell {
cells := make([]termui.Cell, 0)

// When msg.Time and msg.Name are empty (in the case of attachments)
// don't add the time and name parts.
if (msg.Time != time.Time{} && msg.Name != "") {
// Time
cells = append(cells, termui.DefaultTxBuilder.Build(
msg.GetTime(),
termui.ColorDefault, termui.ColorDefault)...,
)

// Thread
cells = append(cells, termui.DefaultTxBuilder.Build(
msg.GetThread(),
termui.ColorDefault, termui.ColorDefault)...,
)

// Name
cells = append(cells, termui.DefaultTxBuilder.Build(
msg.GetName(),
termui.ColorDefault, termui.ColorDefault)...,
)
}

// Hack, in order to get the correct fg and bg attributes. This is
// because the readAttr function in termui is unexported.
txCells := termui.DefaultTxBuilder.Build(
msg.GetContent(),
termui.ColorDefault, termui.ColorDefault,
)

// Text
for _, r := range msg.Content {
cells = append(
cells,
termui.Cell{
Ch: r,
Fg: txCells[0].Fg,
Bg: txCells[0].Bg,
},
)
}

return cells
}

// Help shows the usage and key bindings in the chat pane
func (c *Chat) Help(usage string, cfg *config.Config) {
help := []Message{
Expand Down Expand Up @@ -348,5 +341,7 @@ func (c *Chat) Help(usage string, cfg *config.Config) {
help = append(help, Message{Content: ""})
}

c.Messages = help
for _, msg := range help {
c.Messages[msg.ID] = msg
}
}
95 changes: 95 additions & 0 deletions components/message.go
@@ -0,0 +1,95 @@
package components

import (
"fmt"
"sort"
"strings"
"time"
)

var (
COLORS = []string{
"fg-black",
"fg-red",
"fg-green",
"fg-yellow",
"fg-blue",
"fg-magenta",
"fg-cyan",
"fg-white",
}
)

type Message struct {
ID string
Messages map[string]Message

Time time.Time
Thread string
Name string
Content string

StyleTime string
StyleThread string
StyleName string
StyleText string

FormatTime string
}

func (m Message) GetTime() string {
return fmt.Sprintf(
"[[%s]](%s) ",
m.Time.Format(m.FormatTime),
m.StyleTime,
)
}

func (m Message) GetThread() string {
return fmt.Sprintf("[%s](%s)",
m.Thread,
m.StyleThread,
)
}

func (m Message) GetName() string {
return fmt.Sprintf("[<%s>](%s) ",
m.Name,
m.colorizeName(m.StyleName),
)
}

func (m Message) GetContent() string {
return fmt.Sprintf("[.](%s)", m.StyleText)
}

func (m Message) colorizeName(styleName string) string {
if strings.Contains(styleName, "colorize") {
var sum int
for _, c := range m.Name {
sum = sum + int(c)
}

i := sum % len(COLORS)

return strings.Replace(m.StyleName, "colorize", COLORS[i], -1)
}

return styleName
}

func SortMessages(msgs map[string]Message) []Message {
keys := make([]string, 0)
for k := range msgs {
keys = append(keys, k)
}

sort.Strings(keys)

sortedMessages := make([]Message, 0)
for _, k := range keys {
sortedMessages = append(sortedMessages, msgs[k])
}

return sortedMessages
}
1 change: 1 addition & 0 deletions config/config.go
Expand Up @@ -128,6 +128,7 @@ func getDefaultConfig() Config {
Message: Message{
Time: "",
TimeFormat: "15:04",
Thread: "fg-bold",
Name: "",
Text: "",
},
Expand Down
1 change: 1 addition & 0 deletions config/theme.go
Expand Up @@ -18,6 +18,7 @@ type View struct {
type Message struct {
Time string `json:"time"`
Name string `json:"name"`
Thread string `json:"thread"`
Text string `json:"text"`
TimeFormat string `json:"time_format"`
}
Expand Down

0 comments on commit 112524d

Please sign in to comment.