guilds.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package ui
  2. import (
  3. "sort"
  4. "github.com/ayntgl/astatine"
  5. "github.com/ayntgl/discordo/discord"
  6. "github.com/gdamore/tcell/v2"
  7. "github.com/rivo/tview"
  8. )
  9. type GuildsList struct {
  10. *tview.List
  11. app *App
  12. }
  13. func NewGuildsList(app *App) *GuildsList {
  14. gl := &GuildsList{
  15. List: tview.NewList(),
  16. app: app,
  17. }
  18. gl.AddItem("Direct Messages", "", 0, nil)
  19. gl.ShowSecondaryText(false)
  20. gl.SetTitle("Guilds")
  21. gl.SetTitleAlign(tview.AlignLeft)
  22. gl.SetBorder(true)
  23. gl.SetBorderPadding(0, 0, 1, 1)
  24. gl.SetSelectedFunc(gl.onSelected)
  25. gl.SetInputCapture(gl.onInputCapture)
  26. return gl
  27. }
  28. func (gl *GuildsList) onInputCapture(e *tcell.EventKey) *tcell.EventKey {
  29. i := gl.List.GetCurrentItem()
  30. switch e.Rune() {
  31. case 'g': // Home.
  32. i = 0
  33. case 'G': // End.
  34. i = gl.List.GetItemCount() - 1
  35. case 'j': // Down.
  36. i++
  37. case 'k': // Up.
  38. i--
  39. if i < 0 {
  40. i = 0
  41. }
  42. default:
  43. return e
  44. }
  45. gl.List.SetCurrentItem(i)
  46. return nil
  47. }
  48. func (gl *GuildsList) onSelected(idx int, mainText string, secondaryText string, shortcut rune) {
  49. rootTreeNode := gl.app.ChannelsTreeView.GetRoot()
  50. rootTreeNode.ClearChildren()
  51. gl.app.SelectedMessage = -1
  52. gl.app.MessagesTextView.
  53. Highlight().
  54. Clear()
  55. gl.app.MessageInputField.SetText("")
  56. if mainText == "Direct Messages" {
  57. cs := gl.app.Session.State.PrivateChannels
  58. sort.Slice(cs, func(i, j int) bool {
  59. return cs[i].LastMessageID > cs[j].LastMessageID
  60. })
  61. for _, c := range cs {
  62. channelTreeNode := tview.NewTreeNode(discord.ChannelToString(c)).
  63. SetReference(c.ID)
  64. rootTreeNode.AddChild(channelTreeNode)
  65. }
  66. } else { // Guild
  67. // Decrement the index of the selected item by one since the first item in the list is always "Direct Messages".
  68. cs := gl.app.Session.State.Guilds[idx-1].Channels
  69. sort.Slice(cs, func(i, j int) bool {
  70. return cs[i].Position < cs[j].Position
  71. })
  72. for _, c := range cs {
  73. if (c.Type == astatine.ChannelTypeGuildText || c.Type == astatine.ChannelTypeGuildNews) && (c.ParentID == "") {
  74. channelTreeNode := tview.NewTreeNode(discord.ChannelToString(c)).
  75. SetReference(c.ID)
  76. rootTreeNode.AddChild(channelTreeNode)
  77. }
  78. }
  79. CATEGORY:
  80. for _, c := range cs {
  81. if c.Type == astatine.ChannelTypeGuildCategory {
  82. for _, nestedChannel := range cs {
  83. if nestedChannel.ParentID == c.ID {
  84. channelTreeNode := tview.NewTreeNode(c.Name).
  85. SetReference(c.ID)
  86. rootTreeNode.AddChild(channelTreeNode)
  87. continue CATEGORY
  88. }
  89. }
  90. channelTreeNode := tview.NewTreeNode(c.Name).
  91. SetReference(c.ID)
  92. rootTreeNode.AddChild(channelTreeNode)
  93. }
  94. }
  95. for _, c := range cs {
  96. if (c.Type == astatine.ChannelTypeGuildText || c.Type == astatine.ChannelTypeGuildNews) && (c.ParentID != "") {
  97. var parentTreeNode *tview.TreeNode
  98. rootTreeNode.Walk(func(node, _ *tview.TreeNode) bool {
  99. if node.GetReference() == c.ParentID {
  100. parentTreeNode = node
  101. return false
  102. }
  103. return true
  104. })
  105. if parentTreeNode != nil {
  106. channelTreeNode := tview.NewTreeNode(discord.ChannelToString(c)).
  107. SetReference(c.ID)
  108. parentTreeNode.AddChild(channelTreeNode)
  109. }
  110. }
  111. }
  112. }
  113. gl.app.ChannelsTreeView.SetCurrentNode(rootTreeNode)
  114. gl.app.SetFocus(gl.app.ChannelsTreeView)
  115. }