channels_tree.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. package ui
  2. import (
  3. "github.com/diamondburned/arikawa/v3/discord"
  4. "github.com/rivo/tview"
  5. )
  6. type ChannelsTree struct {
  7. *tview.TreeView
  8. app *App
  9. SelectedChannel *discord.Channel
  10. }
  11. func NewChannelsTree(app *App) *ChannelsTree {
  12. ct := &ChannelsTree{
  13. TreeView: tview.NewTreeView(),
  14. app: app,
  15. }
  16. ct.SetRoot(tview.NewTreeNode(""))
  17. ct.SetTopLevel(1)
  18. ct.SetSelectedFunc(ct.onSelected)
  19. ct.SetTitle("Channels")
  20. ct.SetTitleAlign(tview.AlignLeft)
  21. ct.SetBorder(true)
  22. ct.SetBorderPadding(0, 0, 1, 1)
  23. return ct
  24. }
  25. func (ct *ChannelsTree) onSelected(node *tview.TreeNode) {
  26. ct.SelectedChannel = nil
  27. ct.app.MessagesPanel.SelectedMessage = -1
  28. ct.app.MessagesPanel.
  29. Highlight().
  30. Clear().
  31. SetTitle("")
  32. ct.app.MessageInputField.SetText("")
  33. ref := node.GetReference()
  34. c, err := ct.app.State.Cabinet.Channel(ref.(discord.ChannelID))
  35. if err != nil {
  36. return
  37. }
  38. // If the channel is a category channel, expand the selected node if it is collapsed, otherwise collapse.
  39. if c.Type == discord.GuildCategory {
  40. node.SetExpanded(!node.IsExpanded())
  41. return
  42. }
  43. ct.SelectedChannel = c
  44. ct.app.SetFocus(ct.app.MessageInputField)
  45. title := channelToString(*c)
  46. if c.Topic != "" {
  47. title += " - " + parseMarkdown(c.Topic)
  48. }
  49. ct.app.MessagesPanel.SetTitle(title)
  50. go func() {
  51. // The returned slice will be sorted from latest to oldest.
  52. ms, err := ct.app.State.Messages(c.ID, ct.app.Config.MessagesLimit)
  53. if err != nil {
  54. return
  55. }
  56. for i := len(ms) - 1; i >= 0; i-- {
  57. _, err = ct.app.MessagesPanel.Write(buildMessage(ct.app, ms[i]))
  58. if err != nil {
  59. return
  60. }
  61. }
  62. ct.app.MessagesPanel.ScrollToEnd()
  63. }()
  64. }
  65. func (ct *ChannelsTree) createChannelNode(c discord.Channel) *tview.TreeNode {
  66. channelNode := tview.NewTreeNode(channelToString(c))
  67. channelNode.SetReference(c.ID)
  68. return channelNode
  69. }
  70. func (ct *ChannelsTree) createOrphanChannelNodes(rootNode *tview.TreeNode, cs []discord.Channel) {
  71. for _, c := range cs {
  72. if (c.Type == discord.GuildText || c.Type == discord.GuildNews) && (!c.ParentID.IsValid()) {
  73. rootNode.AddChild(ct.createChannelNode(c))
  74. }
  75. }
  76. }
  77. func (ct *ChannelsTree) createCategoryChannelNodes(rootNode *tview.TreeNode, cs []discord.Channel) {
  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. rootNode.AddChild(ct.createChannelNode(c))
  84. continue CATEGORY
  85. }
  86. }
  87. rootNode.AddChild(ct.createChannelNode(c))
  88. }
  89. }
  90. }
  91. func (ct *ChannelsTree) createChildrenChannelNodes(rootNode *tview.TreeNode, cs []discord.Channel) {
  92. for _, c := range cs {
  93. if (c.Type == discord.GuildText || c.Type == discord.GuildNews) && (c.ParentID.IsValid()) {
  94. var parentNode *tview.TreeNode
  95. rootNode.Walk(func(node, _ *tview.TreeNode) bool {
  96. if node.GetReference() == c.ParentID {
  97. parentNode = node
  98. return false
  99. }
  100. return true
  101. })
  102. if parentNode != nil {
  103. parentNode.AddChild(ct.createChannelNode(c))
  104. }
  105. }
  106. }
  107. }