guilds.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. package ui
  2. import (
  3. "sort"
  4. dsc "github.com/diamondburned/arikawa/v3/discord"
  5. "github.com/rivo/tview"
  6. )
  7. type GuildsTree struct {
  8. *tview.TreeView
  9. app *App
  10. }
  11. func NewGuildsTree(app *App) *GuildsTree {
  12. gt := &GuildsTree{
  13. TreeView: tview.NewTreeView(),
  14. app: app,
  15. }
  16. rootNode := tview.NewTreeNode("")
  17. rootNode.AddChild(tview.NewTreeNode("Direct Messages"))
  18. gt.SetRoot(rootNode)
  19. gt.SetTopLevel(1)
  20. gt.SetSelectedFunc(gt.onSelected)
  21. gt.SetTitle("Guilds")
  22. gt.SetTitleAlign(tview.AlignLeft)
  23. gt.SetBorder(true)
  24. gt.SetBorderPadding(0, 0, 1, 1)
  25. return gt
  26. }
  27. func (gt *GuildsTree) onSelected(node *tview.TreeNode) {
  28. gt.app.SelectedChannel = nil
  29. gt.app.SelectedMessage = -1
  30. rootNode := gt.app.ChannelsTree.GetRoot()
  31. rootNode.ClearChildren()
  32. gt.app.MessagesTextView.
  33. Highlight().
  34. Clear().
  35. SetTitle("")
  36. gt.app.MessageInputField.SetText("")
  37. // If the selected node has children (guild folder), expand the selected node if it is collapsed, otherwise collapse.
  38. if len(node.GetChildren()) != 0 {
  39. node.SetExpanded(!node.IsExpanded())
  40. return
  41. }
  42. ref := node.GetReference()
  43. // If the reference of the selected node is nil, it must be the direct messages node.
  44. if ref == nil {
  45. cs, err := gt.app.State.Cabinet.PrivateChannels()
  46. if err != nil {
  47. return
  48. }
  49. sort.Slice(cs, func(i, j int) bool {
  50. return cs[i].LastMessageID > cs[j].LastMessageID
  51. })
  52. for _, c := range cs {
  53. channelNode := tview.NewTreeNode(c.Name)
  54. channelNode.SetReference(c.ID)
  55. rootNode.AddChild(channelNode)
  56. }
  57. } else { // Guild
  58. cs, err := gt.app.State.Cabinet.Channels(ref.(dsc.GuildID))
  59. if err != nil {
  60. return
  61. }
  62. sort.Slice(cs, func(i, j int) bool {
  63. return cs[i].Position < cs[j].Position
  64. })
  65. for _, c := range cs {
  66. if (c.Type == dsc.GuildText || c.Type == dsc.GuildNews) && (!c.ParentID.IsValid()) {
  67. channelNode := tview.NewTreeNode(channelToString(c))
  68. channelNode.SetReference(c.ID)
  69. rootNode.AddChild(channelNode)
  70. }
  71. }
  72. CATEGORY:
  73. for _, c := range cs {
  74. if c.Type == dsc.GuildCategory {
  75. for _, nestedChannel := range cs {
  76. if nestedChannel.ParentID == c.ID {
  77. channelNode := tview.NewTreeNode(c.Name)
  78. channelNode.SetReference(c.ID)
  79. rootNode.AddChild(channelNode)
  80. continue CATEGORY
  81. }
  82. }
  83. channelNode := tview.NewTreeNode(channelToString(c))
  84. channelNode.SetReference(c.ID)
  85. rootNode.AddChild(channelNode)
  86. }
  87. }
  88. for _, c := range cs {
  89. if (c.Type == dsc.GuildText || c.Type == dsc.GuildNews) && (c.ParentID.IsValid()) {
  90. var parentNode *tview.TreeNode
  91. rootNode.Walk(func(node, _ *tview.TreeNode) bool {
  92. if node.GetReference() == c.ParentID {
  93. parentNode = node
  94. return false
  95. }
  96. return true
  97. })
  98. if parentNode != nil {
  99. channelNode := tview.NewTreeNode(channelToString(c))
  100. channelNode.SetReference(c.ID)
  101. parentNode.AddChild(channelNode)
  102. }
  103. }
  104. }
  105. }
  106. gt.app.ChannelsTree.SetCurrentNode(rootNode)
  107. gt.app.SetFocus(gt.app.ChannelsTree)
  108. }