mirror of https://github.com/Bios-Marcel/cordless
178 lines
4.7 KiB
Go
178 lines
4.7 KiB
Go
package ui
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/Bios-Marcel/cordless/readstate"
|
|
"github.com/Bios-Marcel/cordless/tview"
|
|
"github.com/Bios-Marcel/discordgo"
|
|
|
|
"github.com/Bios-Marcel/cordless/config"
|
|
"github.com/Bios-Marcel/cordless/ui/tviewutil"
|
|
)
|
|
|
|
// GuildList is the UI component to hold all user guilds and allow loading
|
|
// one of them.
|
|
type GuildList struct {
|
|
*tview.TreeView
|
|
onGuildSelect func(guildID string)
|
|
}
|
|
|
|
// NewGuildList creates and initializes a ready to use GuildList.
|
|
func NewGuildList(guilds []*discordgo.Guild) *GuildList {
|
|
guildList := &GuildList{
|
|
TreeView: tview.NewTreeView(),
|
|
}
|
|
|
|
guildList.
|
|
SetVimBindingsEnabled(config.Current.OnTypeInListBehaviour == config.DoNothingOnTypeInList).
|
|
SetCycleSelection(true).
|
|
SetTopLevel(1).
|
|
SetBorder(true).
|
|
SetIndicateOverflow(true)
|
|
|
|
root := tview.NewTreeNode("")
|
|
guildList.SetRoot(root)
|
|
guildList.SetTitle("Servers").SetTitleAlign(tview.AlignLeft)
|
|
guildList.SetSelectedFunc(func(node *tview.TreeNode) {
|
|
guildID, ok := node.GetReference().(string)
|
|
if ok && guildList.onGuildSelect != nil {
|
|
guildList.onGuildSelect(guildID)
|
|
}
|
|
})
|
|
|
|
for _, guild := range guilds {
|
|
//Guilds with an empty name are incomplete and we still have to wait
|
|
//for the respective GuildCreate event to be sent to us.
|
|
if guild.Name == "" {
|
|
continue
|
|
}
|
|
guildNode := tview.NewTreeNode(tviewutil.Escape(guild.Name))
|
|
guildNode.SetReference(guild.ID)
|
|
root.AddChild(guildNode)
|
|
|
|
guildList.updateNodeState(guild, guildNode, false)
|
|
|
|
guildNode.SetSelectable(true)
|
|
}
|
|
|
|
if len(root.GetChildren()) > 0 {
|
|
guildList.SetCurrentNode(root)
|
|
}
|
|
|
|
return guildList
|
|
}
|
|
|
|
// UpdateNodeStateByGuild updates the state of a guilds node accordingly
|
|
// to its readstate, unless the guild represented by that node is loaded.
|
|
func (g *GuildList) UpdateNodeStateByGuild(guild *discordgo.Guild, loaded bool) {
|
|
matchedNode := tviewutil.GetNodeByReference(guild.ID, g.TreeView)
|
|
if matchedNode != nil {
|
|
g.updateNodeState(guild, matchedNode, loaded)
|
|
}
|
|
}
|
|
|
|
func (g *GuildList) updateNodeState(guild *discordgo.Guild, node *tview.TreeNode, loaded bool) {
|
|
if loaded {
|
|
g.markNodeAsLoaded(node)
|
|
} else {
|
|
//Reset to avoid mistakes
|
|
if tview.IsVtxxx {
|
|
node.SetBlinking(false)
|
|
node.SetUnderline(false)
|
|
}
|
|
if !readstate.HasGuildBeenRead(guild.ID) {
|
|
if tview.IsVtxxx {
|
|
node.SetBlinking(true)
|
|
} else {
|
|
node.SetColor(config.GetTheme().AttentionColor)
|
|
}
|
|
} else {
|
|
node.SetColor(tview.Styles.PrimaryTextColor)
|
|
}
|
|
}
|
|
|
|
//Prefix order doesn't matter for now, as we never have more than one.
|
|
if readstate.HasGuildBeenMentioned(guild.ID) {
|
|
node.AddPrefix(mentionedIndicator)
|
|
} else {
|
|
node.RemovePrefix(mentionedIndicator)
|
|
}
|
|
}
|
|
|
|
// SetOnGuildSelect sets the handler for when a guild is selected.
|
|
func (g *GuildList) SetOnGuildSelect(handler func(guildID string)) {
|
|
g.onGuildSelect = handler
|
|
}
|
|
|
|
// RemoveGuild removes the node that refers to the given guildID.
|
|
func (g *GuildList) RemoveGuild(guildID string) {
|
|
children := g.GetRoot().GetChildren()
|
|
for index, node := range children {
|
|
if node.GetReference() == guildID {
|
|
g.GetRoot().SetChildren(append(children[:index], children[index+1:]...))
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
// AddGuild adds a new node that references the given guildID and shows the
|
|
// given name.
|
|
func (g *GuildList) AddGuild(guildID, name string) {
|
|
node := tview.NewTreeNode(tviewutil.Escape(name))
|
|
node.SetReference(guildID)
|
|
g.GetRoot().AddChild(node)
|
|
}
|
|
|
|
// UpdateName updates the name of the guild with the given ID.
|
|
func (g *GuildList) UpdateName(guildID, newName string) {
|
|
node := tviewutil.GetNodeByReference(guildID, g.TreeView)
|
|
if node != nil {
|
|
node.SetText(tviewutil.Escape(newName))
|
|
}
|
|
}
|
|
|
|
func (g *GuildList) setNotificationCount(count int) {
|
|
if count == 0 {
|
|
g.SetTitle("Servers")
|
|
} else {
|
|
g.SetTitle(fmt.Sprintf("Servers[%s](%d)", tviewutil.ColorToHex(config.GetTheme().AttentionColor), count))
|
|
}
|
|
}
|
|
|
|
func (g *GuildList) countUnreadGuilds() int {
|
|
var unreadCount int
|
|
for _, child := range g.GetRoot().GetChildren() {
|
|
if !readstate.HasGuildBeenRead((child.GetReference()).(string)) {
|
|
unreadCount++
|
|
}
|
|
}
|
|
|
|
return unreadCount
|
|
}
|
|
|
|
// UpdateUnreadGuildCount finds the number of guilds containing unread
|
|
// channels and updates the title accordingly.
|
|
func (g *GuildList) UpdateUnreadGuildCount() {
|
|
g.setNotificationCount(g.countUnreadGuilds())
|
|
}
|
|
|
|
// MarkAsLoaded selects the guild and marks it as loaded.
|
|
func (g *GuildList) MarkAsLoaded(guildID string) {
|
|
guildNode := tviewutil.GetNodeByReference(guildID, g.TreeView)
|
|
if guildNode != nil {
|
|
g.SetCurrentNode(guildNode)
|
|
g.markNodeAsLoaded(guildNode)
|
|
}
|
|
}
|
|
|
|
func (g *GuildList) markNodeAsLoaded(node *tview.TreeNode) {
|
|
node.SetBlinking(false)
|
|
if tview.IsVtxxx {
|
|
node.SetUnderline(true)
|
|
} else {
|
|
node.SetUnderline(false)
|
|
node.SetColor(tview.Styles.ContrastBackgroundColor)
|
|
}
|
|
}
|