Fix bugs where messages arrive multiple times
MODIFY
internal/ui/window.go
internal/ui/window.go
@@ -11,6 +11,10 @@ import (
"github.com/rivo/tview"
)
+const (
+ updateInterval = 100 * time.Millisecond
+)
+
type Window struct {
app *tview.Application
messageContainer *tview.Table
@@ -19,9 +23,9 @@ type Window struct {
messageInput *tview.InputField
channelRootNode *tview.TreeNode
+ killCurrentUpdateThread *chan bool
session *discordgo.Session
- lastMessageID *string
shownMessages []*discordgo.Message
selectedGuild *discordgo.UserGuild
selectedChannel *discordgo.Channel
@@ -99,9 +103,9 @@ func NewWindow(discord *discordgo.Session) (*Window, error) {
//of always the same one.
channelToConnectTo := channel
newNode.SetSelectedFunc(func() {
- window.ClearMessages()
-
window.selectedChannel = channelToConnectTo
+
+ window.ClearMessages()
discordError := window.LoadChannel(channelToConnectTo)
if discordError != nil {
log.Fatalf("Error loading messages (%s).", discordError.Error())
@@ -112,56 +116,7 @@ func NewWindow(discord *discordgo.Session) (*Window, error) {
}
}
- go func() {
- users, discordError := discord.GuildMembers(guild.ID, "", 1000)
-
- //TODO Handle error
- if discordError != nil {
- return
- }
-
- app.QueueUpdateDraw(func() {
- window.userRootNode.ClearChildren()
-
- roles, _ := discord.GuildRoles(guild.ID)
- roleNodes := make(map[string]*tview.TreeNode)
-
- sort.Slice(roles, func(a, b int) bool {
- return roles[a].Position > roles[b].Position
- })
-
- for _, role := range roles {
- if role.Hoist {
- roleNode := tview.NewTreeNode(role.Name)
- roleNodes[role.ID] = roleNode
- window.userRootNode.AddChild(roleNode)
- }
- }
-
- USER:
- for _, user := range users {
-
- var nameToUse string
- if user.Nick != "" {
- nameToUse = user.Nick
- } else {
- nameToUse = user.User.Username
- }
-
- userNode := tview.NewTreeNode(nameToUse)
-
- for _, userRole := range user.Roles {
- roleNode, exists := roleNodes[userRole]
- if exists {
- roleNode.AddChild(userNode)
- continue USER
- }
- }
-
- window.userRootNode.AddChild(userNode)
- }
- })
- }()
+ go window.UpdateUsersForGuild(guild)
break
}
}
@@ -185,35 +140,6 @@ func NewWindow(discord *discordgo.Session) (*Window, error) {
messageContainer.SetBorder(true)
messageContainer.SetSelectable(true, false)
- messageTick := time.NewTicker(250 * time.Millisecond)
- go func() {
- for {
- select {
- case <-messageTick.C:
- if window.selectedChannel != nil {
- var messages []*discordgo.Message
- var discordError error
- if window.lastMessageID != nil {
- messages, discordError = discord.ChannelMessages(window.selectedChannel.ID, 100, "", *window.lastMessageID, "")
- }
-
- //TODO Handle properly
- if discordError != nil {
- continue
- }
-
- if messages == nil || len(messages) == 0 {
- continue
- }
-
- window.lastMessageID = &messages[len(messages)-1].ID
-
- window.AddMessages(messages)
- }
- }
- }
- }()
-
window.messageInput = tview.NewInputField()
window.messageInput.SetBorder(true)
window.messageInput.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
@@ -294,17 +220,16 @@ func (window *Window) ClearMessages() {
}
func (window *Window) LoadChannel(channel *discordgo.Channel) error {
+ if window.killCurrentUpdateThread != nil {
+ *window.killCurrentUpdateThread <- true
+ }
+
messages, discordError := window.session.ChannelMessages(channel.ID, 100, "", "", "")
if discordError != nil {
return discordError
}
- if messages == nil || len(messages) == 0 {
- return nil
- }
-
- window.lastMessageID = &messages[0].ID
-
+ if messages != nil && len(messages) > 0 {
//HACK: Reversing them, as they are sorted anyway.
msgAmount := len(messages)
for i := 0; i < msgAmount/2; i++ {
@@ -313,14 +238,48 @@ func (window *Window) LoadChannel(channel *discordgo.Channel) error {
}
window.AddMessages(messages)
+ }
+
+ updateTicker := time.NewTicker(updateInterval)
+ go func() {
+ killChan := make(chan bool)
+ window.killCurrentUpdateThread = &killChan
+ for {
+ select {
+ case <-*window.killCurrentUpdateThread:
+ return
+
+ case <-updateTicker.C:
+ window.LoadMessagesInChannelAfter(channel)
+ }
+ }
+ }()
+
return nil
}
+func (window *Window) LoadMessagesInChannelAfter(channel *discordgo.Channel) {
+ lastMessageID := window.shownMessages[len(window.shownMessages)-1].ID
+ messages, discordError := window.session.ChannelMessages(channel.ID, 100, "", lastMessageID, "")
+
+ //TODO Handle
+ if discordError != nil {
+ return
+ }
+
+ if messages == nil || len(messages) == 0 {
+ return
+ }
+
+ window.AddMessages(messages)
+}
+
func (window *Window) AddMessages(messages []*discordgo.Message) {
window.shownMessages = append(window.shownMessages, messages...)
window.app.QueueUpdateDraw(func() {
for _, message := range messages {
+
rowIndex := window.messageContainer.GetRowCount()
time, parseError := message.Timestamp.Parse()
@@ -340,6 +299,57 @@ func (window *Window) AddMessages(messages []*discordgo.Message) {
})
}
+func (window *Window) UpdateUsersForGuild(guild *discordgo.UserGuild) {
+ users, discordError := window.session.GuildMembers(guild.ID, "", 1000)
+
+ //TODO Handle error
+ if discordError != nil {
+ return
+ }
+
+ window.app.QueueUpdateDraw(func() {
+ window.userRootNode.ClearChildren()
+
+ roles, _ := window.session.GuildRoles(guild.ID)
+ roleNodes := make(map[string]*tview.TreeNode)
+
+ sort.Slice(roles, func(a, b int) bool {
+ return roles[a].Position > roles[b].Position
+ })
+
+ for _, role := range roles {
+ if role.Hoist {
+ roleNode := tview.NewTreeNode(role.Name)
+ roleNodes[role.ID] = roleNode
+ window.userRootNode.AddChild(roleNode)
+ }
+ }
+
+ USER:
+ for _, user := range users {
+
+ var nameToUse string
+ if user.Nick != "" {
+ nameToUse = user.Nick
+ } else {
+ nameToUse = user.User.Username
+ }
+
+ userNode := tview.NewTreeNode(nameToUse)
+
+ for _, userRole := range user.Roles {
+ roleNode, exists := roleNodes[userRole]
+ if exists {
+ roleNode.AddChild(userNode)
+ continue USER
+ }
+ }
+
+ window.userRootNode.AddChild(userNode)
+ }
+ })
+}
+
//Run Shows the window optionally returning an error.
func (window *Window) Run() error {
return window.app.Run()

Fix bugs where messages arrive multiple times