channels_picker.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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/tview"
  8. "github.com/ayn2op/tview/help"
  9. "github.com/ayn2op/tview/keybind"
  10. "github.com/ayn2op/tview/picker"
  11. "github.com/diamondburned/arikawa/v3/discord"
  12. )
  13. type channelsPicker struct {
  14. *picker.Model
  15. chatView *Model
  16. browseMode bool
  17. }
  18. var _ help.KeyMap = (*channelsPicker)(nil)
  19. func newChannelsPicker(cfg *config.Config, chatView *Model) *channelsPicker {
  20. cp := &channelsPicker{Model: picker.NewModel(), chatView: chatView}
  21. ConfigurePicker(cp.Model, cfg, "Channels")
  22. return cp
  23. }
  24. func (cp *channelsPicker) resetBrowse() { cp.browseMode = false }
  25. func (cp *channelsPicker) HandleEvent(event tview.Event) tview.Command {
  26. switch event := event.(type) {
  27. case *tview.KeyEvent:
  28. if cmd, handled := pickerBrowseHandleKey(event, &cp.browseMode, cp.Model, func() { cp.chatView.closePicker() }); handled {
  29. return cmd
  30. }
  31. case *picker.SelectedEvent:
  32. channelID, ok := event.Reference.(discord.ChannelID)
  33. if !ok || !channelID.IsValid() {
  34. return nil
  35. }
  36. channel, err := cp.chatView.state.Cabinet.Channel(channelID)
  37. if err != nil {
  38. slog.Error("failed to get channel from state", "err", err, "channel_id", channelID)
  39. return nil
  40. }
  41. node := cp.chatView.guildsTree.findNodeByChannelID(channel.ID)
  42. if node == nil {
  43. slog.Error("failed to locate channel in tree", "channel_id", channel.ID)
  44. return nil
  45. }
  46. cp.chatView.guildsTree.expandPathToNode(node)
  47. cp.chatView.guildsTree.SetCurrentNode(node)
  48. var selectCmd tview.Command
  49. if channel.Type != discord.GuildCategory {
  50. selectCmd = cp.chatView.guildsTree.onSelected(node)
  51. }
  52. cp.chatView.closePicker()
  53. return selectCmd
  54. case *picker.CancelEvent:
  55. cp.chatView.closePicker()
  56. return nil
  57. }
  58. return cp.Model.HandleEvent(event)
  59. }
  60. func (cp *channelsPicker) update() {
  61. var items picker.Items
  62. state := cp.chatView.state
  63. privateChannels, err := state.Cabinet.PrivateChannels()
  64. if err != nil {
  65. slog.Error("failed to get private channels from state", "err", err)
  66. return
  67. }
  68. ui.SortPrivateChannels(privateChannels)
  69. for _, channel := range privateChannels {
  70. items = append(items, cp.channelItem(nil, channel))
  71. }
  72. guilds, err := state.Cabinet.Guilds()
  73. if err != nil {
  74. slog.Error("failed to get guilds from state", "err", err)
  75. return
  76. }
  77. for _, guild := range guilds {
  78. channels, err := state.Cabinet.Channels(guild.ID)
  79. if err != nil {
  80. slog.Error("failed to get channels from state", "err", err, "guild_id", guild.ID)
  81. continue
  82. }
  83. for _, channel := range channels {
  84. items = append(items, cp.channelItem(&guild, channel))
  85. }
  86. }
  87. cp.Model.SetItems(items)
  88. }
  89. func (cp *channelsPicker) channelItem(guild *discord.Guild, channel discord.Channel) picker.Item {
  90. var b strings.Builder
  91. b.WriteString(ui.ChannelToString(channel, cp.chatView.cfg.Icons, cp.chatView.state))
  92. if guild != nil {
  93. b.WriteString(" - ")
  94. b.WriteString(guild.Name)
  95. }
  96. name := b.String()
  97. return picker.Item{Text: name, FilterText: name, Reference: channel.ID}
  98. }
  99. func (cp *channelsPicker) ShortHelp() []keybind.Keybind {
  100. cfg := cp.chatView.cfg.Keybinds.Picker
  101. return []keybind.Keybind{cfg.Up.Keybind, cfg.Down.Keybind, cfg.Select.Keybind, cfg.Cancel.Keybind}
  102. }
  103. func (cp *channelsPicker) FullHelp() [][]keybind.Keybind {
  104. cfg := cp.chatView.cfg.Keybinds.Picker
  105. return [][]keybind.Keybind{
  106. {cfg.Up.Keybind, cfg.Down.Keybind, cfg.Top.Keybind, cfg.Bottom.Keybind},
  107. {cfg.Select.Keybind, cfg.Cancel.Keybind},
  108. }
  109. }