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:
parent
d159421013
commit
14f93ee1c0
3 changed files with 82 additions and 40 deletions
50
discord.go
50
discord.go
|
|
@ -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 {
|
||||
|
|
|
|||
12
renderer.go
12
renderer.go
|
|
@ -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
60
ui.go
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue