guilds_tree.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "sort"
  6. "github.com/diamondburned/arikawa/v3/discord"
  7. "github.com/rivo/tview"
  8. )
  9. type GuildsTree struct {
  10. *tview.TreeView
  11. root *tview.TreeNode
  12. }
  13. func newGuildsTree() *GuildsTree {
  14. gt := &GuildsTree{
  15. TreeView: tview.NewTreeView(),
  16. root: tview.NewTreeNode(""),
  17. }
  18. gt.SetGraphics(cfg.Theme.GuildsTree.Graphics)
  19. gt.SetRoot(gt.root)
  20. gt.SetTopLevel(1)
  21. gt.SetSelectedFunc(gt.onSelected)
  22. gt.SetBorder(cfg.Theme.GuildsTree.Border)
  23. padding := cfg.Theme.GuildsTree.BorderPadding
  24. gt.SetBorderPadding(padding[0], padding[1], padding[2], padding[3])
  25. return gt
  26. }
  27. func (gt *GuildsTree) newGuildFromID(n *tview.TreeNode, gid discord.GuildID) error {
  28. g, err := discordState.Cabinet.Guild(gid)
  29. if err != nil {
  30. return err
  31. }
  32. gn := tview.NewTreeNode(g.Name)
  33. gn.SetReference(g.ID)
  34. n.AddChild(gn)
  35. return nil
  36. }
  37. func (gt *GuildsTree) newChannel(n *tview.TreeNode, c discord.Channel) {
  38. cn := tview.NewTreeNode(gt.channelToString(c))
  39. cn.SetReference(c.ID)
  40. n.AddChild(cn)
  41. }
  42. func (gt *GuildsTree) channelToString(c discord.Channel) string {
  43. switch c.Type {
  44. case discord.GuildText:
  45. return "#" + c.Name
  46. case discord.GuildVoice:
  47. return "v-" + c.Name
  48. case discord.GuildNews:
  49. return "n-" + c.Name
  50. case discord.GuildStore:
  51. return "s-" + c.Name
  52. default:
  53. return c.Name
  54. }
  55. }
  56. func (gt *GuildsTree) onSelected(n *tview.TreeNode) {
  57. if len(n.GetChildren()) != 0 {
  58. n.SetExpanded(!n.IsExpanded())
  59. return
  60. }
  61. switch ref := n.GetReference().(type) {
  62. case discord.GuildID:
  63. cs, err := discordState.Cabinet.Channels(ref)
  64. if err != nil {
  65. log.Println(err)
  66. return
  67. }
  68. sort.Slice(cs, func(i, j int) bool {
  69. return cs[i].Position < cs[j].Position
  70. })
  71. // Orphan (top-level) channels
  72. for _, c := range cs {
  73. if c.Type != discord.GuildCategory && !c.ParentID.IsValid() {
  74. gt.newChannel(n, c)
  75. }
  76. }
  77. // Category channels
  78. CATEGORY:
  79. for _, c := range cs {
  80. if c.Type == discord.GuildCategory {
  81. for _, nestedChannel := range cs {
  82. if nestedChannel.ParentID == c.ID {
  83. gt.newChannel(n, c)
  84. continue CATEGORY
  85. }
  86. }
  87. gt.newChannel(n, c)
  88. }
  89. }
  90. // Children (category-bound) channels
  91. for _, c := range cs {
  92. if c.Type != discord.GuildCategory && c.ParentID.IsValid() {
  93. var parent *tview.TreeNode
  94. n.Walk(func(node, _ *tview.TreeNode) bool {
  95. if node.GetReference() == c.ParentID {
  96. parent = node
  97. return false
  98. }
  99. return true
  100. })
  101. if parent != nil {
  102. gt.newChannel(parent, c)
  103. }
  104. }
  105. }
  106. case discord.ChannelID:
  107. messagesText.Clear()
  108. c, err := discordState.Cabinet.Channel(ref)
  109. if err != nil {
  110. log.Println(err)
  111. return
  112. }
  113. ms, err := discordState.Messages(ref, cfg.MessagesLimit)
  114. if err != nil {
  115. log.Println(err)
  116. return
  117. }
  118. for i := len(ms) - 1; i >= 0; i-- {
  119. if messagesText.newMessage(&ms[i]); err != nil {
  120. fmt.Println(err)
  121. continue
  122. }
  123. }
  124. messagesText.SetTitle(gt.channelToString(*c))
  125. app.SetFocus(messagesText)
  126. }
  127. }