feat: mark unread channels (#65)

* feat: distinguish unread messages, channels, and guilds

* feat: add UI acknowledgement functionality

* fix: return if tree node by reference not found

* feat: mark pre-unread messages with bold tag
This commit is contained in:
ayntgl 2021-10-01 22:25:11 +04:00 • committed by GitHub
parent d159421013
commit 14f93ee1c0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 82 additions and 40 deletions

View file

@ -48,7 +48,15 @@ func onSessionReady(_ *discordgo.Session, r *discordgo.Ready) {
})
for _, c := range r.PrivateChannels {
cn := tview.NewTreeNode(generateChannelRepr(c)).SetReference(c.ID)
var tag string
if isUnread(c) {
tag = "[::b]"
} else {
tag = "[::d]"
}
cn := tview.NewTreeNode(tag + generateChannelRepr(c) + "[::-]").
SetReference(c.ID)
dmNode.AddChild(cn)
}
@ -89,12 +97,27 @@ func onSessionReady(_ *discordgo.Session, r *discordgo.Ready) {
channelsTree.SetCurrentNode(n)
}
func onSessionMessageCreate(_ *discordgo.Session, m *discordgo.MessageCreate) {
if selectedChannel == nil {
selectedChannel = &discordgo.Channel{ID: ""}
func isUnread(c *discordgo.Channel) bool {
if c.LastMessageID == "" {
return false
}
if selectedChannel.ID != m.ChannelID {
for _, rs := range session.State.ReadState {
if c.ID == rs.ID {
return c.LastMessageID != rs.LastMessageID
}
}
return false
}
func onSessionMessageCreate(_ *discordgo.Session, m *discordgo.MessageCreate) {
c, err := session.State.Channel(m.ChannelID)
if err != nil {
return
}
if selectedChannel == nil || selectedChannel.ID != m.ChannelID {
if conf.Notifications {
for _, u := range m.Mentions {
if u.ID == session.State.User.ID {
@ -102,10 +125,6 @@ func onSessionMessageCreate(_ *discordgo.Session, m *discordgo.MessageCreate) {
if err != nil {
return
}
c, err := session.State.Channel(m.ChannelID)
if err != nil {
return
}
go beeep.Alert(fmt.Sprintf("%s (#%s)", g.Name, c.Name), m.ContentWithMentionsReplaced(), "")
return
@ -113,11 +132,16 @@ func onSessionMessageCreate(_ *discordgo.Session, m *discordgo.MessageCreate) {
}
}
return
cn := getTreeNodeByReference(c.ID)
if cn == nil {
return
}
cn.SetText("[::b]" + generateChannelRepr(c) + "[::-]")
app.Draw()
} else {
selectedChannel.Messages = append(selectedChannel.Messages, m.Message)
renderMessage(m.Message)
}
selectedChannel.Messages = append(selectedChannel.Messages, m.Message)
renderMessage(m.Message)
}
type loginResponse struct {

View file

@ -13,18 +13,6 @@ var italicRegex = regexp.MustCompile(`(?m)\*(.*?)\*`)
var underlineRegex = regexp.MustCompile(`(?m)__(.*?)__`)
var strikeThroughRegex = regexp.MustCompile(`(?m)~~(.*?)~~`)
func renderMessages(cID string) {
ms, err := session.ChannelMessages(cID, conf.GetMessagesLimit, "", "", "")
if err != nil {
return
}
for i := len(ms) - 1; i >= 0; i-- {
selectedChannel.Messages = append(selectedChannel.Messages, ms[i])
renderMessage(ms[i])
}
}
func renderMessage(m *discordgo.Message) {
var b strings.Builder

60
ui.go
View file

@ -62,7 +62,7 @@ func onChannelsTreeSelected(n *tview.TreeNode) {
// Unhighlight the already-highlighted regions.
messagesTextView.Highlight()
if len(n.GetChildren()) != 0 {
if len(n.GetChildren()) != 0 || n.GetText() == "Direct Messages" {
n.SetExpanded(!n.IsExpanded())
} else {
cID := n.GetReference().(string)
@ -86,18 +86,28 @@ func onChannelsTreeSelected(n *tview.TreeNode) {
messagesTextView.SetTitle(generateChannelRepr(c))
}
if strings.HasPrefix(n.GetText(), "[::b]") {
n.SetText("[::d]" + generateChannelRepr(c) + "[::-]")
}
messagesTextView.Clear()
go renderMessages(c.ID)
ms, err := session.ChannelMessages(cID, conf.GetMessagesLimit, "", "", "")
if err != nil {
return
}
for i := len(ms) - 1; i >= 0; i-- {
selectedChannel.Messages = append(selectedChannel.Messages, ms[i])
go renderMessage(ms[i])
}
if len(ms) != 0 && isUnread(c) {
go session.ChannelMessageAck(c.ID, c.LastMessageID, "")
}
}
}
func newTextChannelTreeNode(c *discordgo.Channel) *tview.TreeNode {
n := tview.NewTreeNode("[::d]" + generateChannelRepr(c) + "[::-]").
SetReference(c.ID)
return n
}
func createTopLevelChannelsTreeNodes(
n *tview.TreeNode,
cs []*discordgo.Channel,
@ -105,11 +115,20 @@ func createTopLevelChannelsTreeNodes(
for _, c := range cs {
if (c.Type == discordgo.ChannelTypeGuildText || c.Type == discordgo.ChannelTypeGuildNews) &&
(c.ParentID == "") {
if p, err := session.State.UserChannelPermissions(session.State.User.ID, c.ID); err != nil || p&discordgo.PermissionViewChannel != discordgo.PermissionViewChannel {
p, err := session.State.UserChannelPermissions(session.State.User.ID, c.ID)
if err != nil || p&discordgo.PermissionViewChannel != discordgo.PermissionViewChannel {
continue
}
cn := newTextChannelTreeNode(c)
var tag string
if isUnread(c) {
tag = "[::b]"
} else {
tag = "[::d]"
}
cn := tview.NewTreeNode(tag + generateChannelRepr(c) + "[::-]").
SetReference(c.ID)
n.AddChild(cn)
continue
}
@ -123,7 +142,8 @@ func createCategoryChannelsTreeNodes(
CategoryLoop:
for _, c := range cs {
if c.Type == discordgo.ChannelTypeGuildCategory {
if p, err := session.State.UserChannelPermissions(session.State.User.ID, c.ID); err != nil || p&discordgo.PermissionViewChannel != discordgo.PermissionViewChannel {
p, err := session.State.UserChannelPermissions(session.State.User.ID, c.ID)
if err != nil || p&discordgo.PermissionViewChannel != discordgo.PermissionViewChannel {
continue
}
@ -147,12 +167,22 @@ func createSecondLevelChannelsTreeNodes(cs []*discordgo.Channel) {
for _, c := range cs {
if (c.Type == discordgo.ChannelTypeGuildText || c.Type == discordgo.ChannelTypeGuildNews) &&
(c.ParentID != "") {
if p, err := session.State.UserChannelPermissions(session.State.User.ID, c.ID); err != nil || p&discordgo.PermissionViewChannel != discordgo.PermissionViewChannel {
p, err := session.State.UserChannelPermissions(session.State.User.ID, c.ID)
if err != nil || p&discordgo.PermissionViewChannel != discordgo.PermissionViewChannel {
continue
}
if pn := getTreeNodeByReference(c.ParentID); pn != nil {
cn := newTextChannelTreeNode(c)
var tag string
if isUnread(c) {
tag = "[::b]"
} else {
tag = "[::d]"
}
pn := getTreeNodeByReference(c.ParentID)
if pn != nil {
cn := tview.NewTreeNode(tag + generateChannelRepr(c) + "[::-]").
SetReference(c.ID)
pn.AddChild(cn)
}
}