channels_picker.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. package chat
  2. import (
  3. "log/slog"
  4. "strings"
  5. "github.com/ayn2op/discordo/internal/config"
  6. "github.com/ayn2op/discordo/internal/ui"
  7. "github.com/ayn2op/discordo/pkg/picker"
  8. "github.com/ayn2op/tview"
  9. "github.com/diamondburned/arikawa/v3/discord"
  10. )
  11. type channelsPicker struct {
  12. *picker.Picker
  13. chatView *View
  14. }
  15. func newChannelsPicker(cfg *config.Config, chatView *View) *channelsPicker {
  16. cp := &channelsPicker{picker.New(), chatView}
  17. cp.Box = ui.ConfigureBox(tview.NewBox(), &cfg.Theme)
  18. // When a child of tview.Flex is focused, tview.Flex itself is not reported as focused. Instead, the focused child (picker) is considered focused. Therefore, we manually set the active border style on the picker to ensure it displays the correct focused appearance.
  19. cp.
  20. SetBlurFunc(nil).
  21. SetFocusFunc(nil).
  22. SetBorderSet(cfg.Theme.Border.ActiveSet.BorderSet).
  23. SetBorderStyle(cfg.Theme.Border.ActiveStyle.Style).
  24. SetTitleStyle(cfg.Theme.Title.ActiveStyle.Style).
  25. SetFooterStyle(cfg.Theme.Footer.ActiveStyle.Style)
  26. cp.SetSelectedFunc(cp.onSelected)
  27. cp.SetTitle("Channels")
  28. cp.SetScrollBarVisibility(cfg.Theme.ScrollBar.Visibility.ScrollBarVisibility)
  29. cp.SetScrollBar(tview.NewScrollBar().
  30. SetTrackStyle(cfg.Theme.ScrollBar.TrackStyle.Style).
  31. SetThumbStyle(cfg.Theme.ScrollBar.ThumbStyle.Style).
  32. SetGlyphSet(cfg.Theme.ScrollBar.GlyphSet.GlyphSet))
  33. cp.SetKeyMap(&picker.KeyMap{
  34. Cancel: cfg.Keybinds.Picker.Cancel,
  35. Up: cfg.Keybinds.Picker.Up,
  36. Down: cfg.Keybinds.Picker.Down,
  37. Top: cfg.Keybinds.Picker.Top,
  38. Bottom: cfg.Keybinds.Picker.Bottom,
  39. Select: cfg.Keybinds.Picker.Select,
  40. })
  41. return cp
  42. }
  43. func (cp *channelsPicker) onSelected(item picker.Item) {
  44. channelID, ok := item.Reference.(discord.ChannelID)
  45. if !ok || !channelID.IsValid() {
  46. return
  47. }
  48. channel, err := cp.chatView.state.Cabinet.Channel(channelID)
  49. if err != nil {
  50. slog.Error("failed to get channel from state", "err", err, "channel_id", channelID)
  51. return
  52. }
  53. node := cp.chatView.guildsTree.findNodeByChannelID(channel.ID)
  54. if node == nil {
  55. slog.Error("failed to locate channel in tree", "channel_id", channel.ID)
  56. return
  57. }
  58. cp.chatView.guildsTree.expandPathToNode(node)
  59. cp.chatView.guildsTree.SetCurrentNode(node)
  60. if channel.Type != discord.GuildCategory {
  61. cp.chatView.guildsTree.onSelected(node)
  62. }
  63. cp.chatView.closePicker()
  64. cp.chatView.focusMessageInput()
  65. }
  66. func (cp *channelsPicker) update() {
  67. cp.ClearItems()
  68. state := cp.chatView.state
  69. privateChannels, err := state.Cabinet.PrivateChannels()
  70. if err != nil {
  71. slog.Error("failed to get private channels from state", "err", err)
  72. return
  73. }
  74. ui.SortPrivateChannels(privateChannels)
  75. for _, channel := range privateChannels {
  76. cp.addChannel(nil, channel)
  77. }
  78. guilds, err := state.Cabinet.Guilds()
  79. if err != nil {
  80. slog.Error("failed to get guilds from state", "err", err)
  81. return
  82. }
  83. for _, guild := range guilds {
  84. channels, err := state.Cabinet.Channels(guild.ID)
  85. if err != nil {
  86. slog.Error("failed to get channels from state", "err", err, "guild_id", guild.ID)
  87. continue
  88. }
  89. for _, channel := range channels {
  90. cp.addChannel(&guild, channel)
  91. }
  92. }
  93. cp.Update()
  94. }
  95. func (cp *channelsPicker) addChannel(guild *discord.Guild, channel discord.Channel) {
  96. var b strings.Builder
  97. b.WriteString(ui.ChannelToString(channel, cp.chatView.cfg.Icons))
  98. if guild != nil {
  99. b.WriteString(" - ")
  100. b.WriteString(guild.Name)
  101. }
  102. name := b.String()
  103. cp.AddItem(picker.Item{Text: name, FilterText: name, Reference: channel.ID})
  104. }