channels_picker.go 3.2 KB

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