Readstate now properly synced between devices
MODIFY
readstate/readmarkers.go
readstate/readmarkers.go
@@ -39,6 +39,24 @@ func ClearReadStateFor(channelID string) {
timerMutex.Unlock()
}
+// UpdateReadLocal can be used to locally update the data without sending
+// anything to the Discord API. The update will only be applied if the new
+// message ID is greater than the old one.
+func UpdateReadLocal(channelID string, lastMessageID string) bool {
+ parsed, parseError := strconv.ParseUint(lastMessageID, 10, 64)
+ if parseError != nil {
+ return false
+ }
+
+ old, isPresent := data[channelID]
+ if !isPresent || old < parsed {
+ data[channelID] = parsed
+ return true
+ }
+
+ return false
+}
+
// UpdateRead tells the discord server that a channel has been read. If the
// channel has already been read and this method was called needlessly, then
// this will be a No-OP.

MODIFY
ui/channeltree.go
ui/channeltree.go
@@ -259,6 +259,23 @@ func (channelTree *ChannelTree) MarkChannelAsUnread(channelID string) {
})
}
+// MarkChannelAsRead marks a channel as read if it's not loaded already.
+func (channelTree *ChannelTree) MarkChannelAsRead(channelID string) {
+ channelTree.GetRoot().Walk(func(node, parent *tview.TreeNode) bool {
+ referenceChannelID, ok := node.GetReference().(string)
+ if ok && referenceChannelID == channelID {
+ if channelTree.channelStates[node] != channelLoaded {
+ channelTree.channelStates[node] = channelRead
+ node.SetColor(tcell.ColorWhite)
+ }
+
+ return false
+ }
+
+ return true
+ })
+}
+
// MarkChannelAsMentioned marks a channel as mentioned.
func (channelTree *ChannelTree) MarkChannelAsMentioned(channelID string) {
channelTree.GetRoot().Walk(func(node, parent *tview.TreeNode) bool {

MODIFY
ui/privatechats.go
ui/privatechats.go
@@ -213,6 +213,22 @@ func (privateList *PrivateChatList) MarkChannelAsUnread(channel *discordgo.Chann
}
}
+// MarkChannelAsRead marks a channel as read if it isn't loaded already
+func (privateList *PrivateChatList) MarkChannelAsRead(channelID string) {
+ for _, node := range privateList.chatsNode.GetChildren() {
+ referenceChannelID, ok := node.GetReference().(string)
+ if ok && referenceChannelID == channelID {
+ if privateList.privateChannelStates[node] != loaded {
+ privateList.privateChannelStates[node] = read
+ node.SetColor(tcell.ColorWhite)
+ }
+ break
+ }
+ }
+}
+
+// ReorderChannelList resorts the list of private chats according to their last
+// message times.
func (privateList *PrivateChatList) ReorderChannelList() {
children := privateList.chatsNode.GetChildren()
sort.Slice(children, func(a, b int) bool {

MODIFY
ui/window.go
ui/window.go
@@ -793,6 +793,19 @@ func NewWindow(doRestart chan bool, app *tview.Application, session *discordgo.S
})
}
+ window.session.AddHandler(func(s *discordgo.Session, event *discordgo.MessageAck) {
+ if readstate.UpdateReadLocal(event.ChannelID, event.MessageID) {
+ channel, stateError := s.State.Channel(event.ChannelID)
+ if stateError == nil && event.MessageID == channel.LastMessageID {
+ if window.selectedGuild != nil && channel.GuildID == window.selectedGuild.ID {
+ window.channelTree.MarkChannelAsRead(channel.ID)
+ } else if channel.GuildID == "" {
+ window.privateList.MarkChannelAsRead(channel.ID)
+ }
+ }
+ }
+ })
+
window.commandView.SetInputCaptureForInput(func(event *tcell.EventKey) *tcell.EventKey {
if event.Modifiers() == tcell.ModAlt {
if event.Key() == tcell.KeyUp {

Readstate now properly synced between devices