search_picker.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. // search_picker.go implements a fuzzy search overlay for messages in the
  2. // current channel. Opened via the search keybind, it lets users filter
  3. // messages by author name and content, then jump to the selected message.
  4. package chat
  5. import (
  6. "github.com/ayn2op/discordo/internal/config"
  7. "github.com/ayn2op/tview"
  8. "github.com/ayn2op/tview/help"
  9. "github.com/ayn2op/tview/keybind"
  10. "github.com/ayn2op/tview/picker"
  11. )
  12. const searchPickerLayerName = "searchPicker"
  13. type searchPicker struct {
  14. *picker.Model
  15. chatView *Model
  16. browseMode bool
  17. }
  18. var _ help.KeyMap = (*searchPicker)(nil)
  19. func newSearchPicker(cfg *config.Config, chatView *Model) *searchPicker {
  20. sp := &searchPicker{Model: picker.NewModel(), chatView: chatView}
  21. ConfigurePicker(sp.Model, cfg, "Search")
  22. return sp
  23. }
  24. // resetBrowse starts the search picker in input mode so users can type a query immediately.
  25. func (sp *searchPicker) resetBrowse() { sp.browseMode = false }
  26. func (sp *searchPicker) HandleEvent(event tview.Event) tview.Command {
  27. switch event := event.(type) {
  28. case *tview.KeyEvent:
  29. if cmd, handled := pickerBrowseHandleKey(event, &sp.browseMode, sp.Model, func() { sp.chatView.closeSearch() }); handled {
  30. return cmd
  31. }
  32. case *picker.SelectedEvent:
  33. messageIndex, ok := event.Reference.(int)
  34. if !ok {
  35. return nil
  36. }
  37. sp.chatView.closeSearch()
  38. sp.chatView.messagesList.SetCursor(messageIndex)
  39. return tview.SetFocus(sp.chatView.messagesList)
  40. case *picker.CancelEvent:
  41. sp.chatView.closeSearch()
  42. return nil
  43. }
  44. return sp.Model.HandleEvent(event)
  45. }
  46. func (sp *searchPicker) update() {
  47. messages := sp.chatView.messagesList.messages
  48. items := make(picker.Items, 0, len(messages))
  49. for i, msg := range messages {
  50. text := msg.Author.DisplayOrUsername() + ": " + msg.Content
  51. if len(text) > 120 {
  52. text = text[:120] + "..."
  53. }
  54. items = append(items, picker.Item{
  55. Text: text,
  56. FilterText: msg.Author.DisplayOrUsername() + " " + msg.Content,
  57. Reference: i,
  58. })
  59. }
  60. sp.Model.SetItems(items)
  61. }
  62. func (sp *searchPicker) ShortHelp() []keybind.Keybind {
  63. return pickerShortHelp(sp.chatView.cfg.Keybinds.Picker)
  64. }
  65. func (sp *searchPicker) FullHelp() [][]keybind.Keybind {
  66. return pickerFullHelp(sp.chatView.cfg.Keybinds.Picker)
  67. }