diff --git a/internal/ui/chat/attachments_picker.go b/internal/ui/chat/attachments_picker.go index b71af88..8a18981 100644 --- a/internal/ui/chat/attachments_picker.go +++ b/internal/ui/chat/attachments_picker.go @@ -7,6 +7,7 @@ import ( "github.com/ayn2op/tview" "github.com/ayn2op/tview/help" "github.com/ayn2op/tview/keybind" + "github.com/gdamore/tcell/v3" ) type attachmentItem struct { @@ -39,8 +40,6 @@ func newAttachmentsPicker(cfg *config.Config, chatView *Model) *attachmentsPicke SetFooterStyle(cfg.Theme.Footer.ActiveStyle.Style) ap.SetTitle("Attachments") - ap.SetSelectedFunc(ap.onSelected) - ap.SetCancelFunc(ap.close) ap.SetKeyMap(&picker.KeyMap{ Cancel: cfg.Keybinds.Picker.Cancel.Keybind, Up: cfg.Keybinds.Picker.Up.Keybind, @@ -70,23 +69,32 @@ func (ap *attachmentsPicker) SetItems(items []attachmentItem) { ap.Update() } -func (ap *attachmentsPicker) onSelected(item picker.Item) { - index, ok := item.Reference.(int) - if !ok { - return - } - if index < 0 || index >= len(ap.items) { - return - } - ap.items[index].open() - ap.close() -} - func (ap *attachmentsPicker) close() { ap.chatView.RemoveLayer(attachmentsListLayerName) ap.chatView.app.SetFocus(ap.chatView.messagesList) } +func (ap *attachmentsPicker) HandleEvent(event tcell.Event) tview.Command { + switch event := event.(type) { + case *picker.SelectedEvent: + index, ok := event.Reference.(int) + if !ok { + return nil + } + if index < 0 || index >= len(ap.items) { + return nil + } + ap.items[index].open() + ap.close() + return nil + case *picker.CancelEvent: + ap.close() + return nil + } + + return ap.Picker.HandleEvent(event) +} + func (ap *attachmentsPicker) ShortHelp() []keybind.Keybind { cfg := ap.cfg.Keybinds.Picker return []keybind.Keybind{cfg.Up.Keybind, cfg.Down.Keybind, cfg.Select.Keybind, cfg.Cancel.Keybind} diff --git a/internal/ui/chat/channels_picker.go b/internal/ui/chat/channels_picker.go index 2ebb6f2..dda699c 100644 --- a/internal/ui/chat/channels_picker.go +++ b/internal/ui/chat/channels_picker.go @@ -11,6 +11,7 @@ import ( "github.com/ayn2op/tview/help" "github.com/ayn2op/tview/keybind" "github.com/diamondburned/arikawa/v3/discord" + "github.com/gdamore/tcell/v3" ) type channelsPicker struct { @@ -34,7 +35,6 @@ func newChannelsPicker(cfg *config.Config, chatView *Model) *channelsPicker { SetTitleStyle(cfg.Theme.Title.ActiveStyle.Style). SetFooterStyle(cfg.Theme.Footer.ActiveStyle.Style) - cp.SetSelectedFunc(cp.onSelected) cp.SetTitle("Channels") cp.SetScrollBarVisibility(cfg.Theme.ScrollBar.Visibility.ScrollBarVisibility) cp.SetScrollBar(tview.NewScrollBar(). @@ -52,31 +52,39 @@ func newChannelsPicker(cfg *config.Config, chatView *Model) *channelsPicker { return cp } -func (cp *channelsPicker) onSelected(item picker.Item) { - channelID, ok := item.Reference.(discord.ChannelID) - if !ok || !channelID.IsValid() { - return - } +func (cp *channelsPicker) HandleEvent(event tcell.Event) tview.Command { + switch event := event.(type) { + case *picker.SelectedEvent: + channelID, ok := event.Reference.(discord.ChannelID) + if !ok || !channelID.IsValid() { + return nil + } - channel, err := cp.chatView.state.Cabinet.Channel(channelID) - if err != nil { - slog.Error("failed to get channel from state", "err", err, "channel_id", channelID) - return - } + channel, err := cp.chatView.state.Cabinet.Channel(channelID) + if err != nil { + slog.Error("failed to get channel from state", "err", err, "channel_id", channelID) + return nil + } - node := cp.chatView.guildsTree.findNodeByChannelID(channel.ID) - if node == nil { - slog.Error("failed to locate channel in tree", "channel_id", channel.ID) - return - } + node := cp.chatView.guildsTree.findNodeByChannelID(channel.ID) + if node == nil { + slog.Error("failed to locate channel in tree", "channel_id", channel.ID) + return nil + } - cp.chatView.guildsTree.expandPathToNode(node) - cp.chatView.guildsTree.SetCurrentNode(node) - if channel.Type != discord.GuildCategory { - cp.chatView.guildsTree.onSelected(node) + cp.chatView.guildsTree.expandPathToNode(node) + cp.chatView.guildsTree.SetCurrentNode(node) + if channel.Type != discord.GuildCategory { + cp.chatView.guildsTree.onSelected(node) + } + cp.chatView.closePicker() + cp.chatView.focusMessageInput() + return nil + case *picker.CancelEvent: + cp.chatView.closePicker() + return nil } - cp.chatView.closePicker() - cp.chatView.focusMessageInput() + return cp.Picker.HandleEvent(event) } func (cp *channelsPicker) update() { diff --git a/internal/ui/chat/model.go b/internal/ui/chat/model.go index 0962869..e777f43 100644 --- a/internal/ui/chat/model.go +++ b/internal/ui/chat/model.go @@ -74,7 +74,6 @@ func NewModel(app *tview.Application, cfg *config.Config, token string) *Model { m.messagesList = newMessagesList(cfg, m) m.messageInput = newMessageInput(cfg, m) m.channelsPicker = newChannelsPicker(cfg, m) - m.channelsPicker.SetCancelFunc(m.closePicker) m.SetBackgroundLayerStyle(m.cfg.Theme.Dialog.BackgroundStyle.Style) m.buildLayout() diff --git a/pkg/picker/events.go b/pkg/picker/events.go new file mode 100644 index 0000000..24a2a93 --- /dev/null +++ b/pkg/picker/events.go @@ -0,0 +1,34 @@ +package picker + +import ( + "github.com/ayn2op/tview" + "github.com/gdamore/tcell/v3" +) + +type SelectedEvent struct { + tcell.EventTime + Item +} + +func newSelectedEvent(item Item) *SelectedEvent { + return &SelectedEvent{Item: item} +} + +func (p *Picker) _select() tview.Command { + index := p.list.Cursor() + if index >= 0 && index < len(p.filtered) { + item := p.filtered[index] + return func() tcell.Event { + return newSelectedEvent(item) + } + } + return nil +} + +type CancelEvent struct{ tcell.EventTime } + +func cancel() tview.Command { + return func() tcell.Event { + return &CancelEvent{} + } +} diff --git a/pkg/picker/picker.go b/pkg/picker/picker.go index 4defb50..88bcb3d 100644 --- a/pkg/picker/picker.go +++ b/pkg/picker/picker.go @@ -9,19 +9,15 @@ import ( "github.com/sahilm/fuzzy" ) -type ( - SelectedFunc func(item Item) - CancelFunc func() -) +// bottom border + value +const inputHeight = 2 type Picker struct { *flex.Model input *tview.InputField list *list.Model - onSelected SelectedFunc - onCancel CancelFunc - keyMap *KeyMap + keyMap *KeyMap items Items filtered Items @@ -49,8 +45,7 @@ func New() *Picker { p. SetDirection(flex.DirectionRow). - // bottom border + value - AddItem(p.input, 2, 0, true). + AddItem(p.input, inputHeight, 0, true). AddItem(p.list, 0, 1, false) p.Update() @@ -97,14 +92,6 @@ func (p *Picker) SetScrollBar(scrollBar *tview.ScrollBar) { p.list.SetScrollBar(scrollBar) } -func (p *Picker) SetSelectedFunc(onSelected SelectedFunc) { - p.onSelected = onSelected -} - -func (p *Picker) SetCancelFunc(onCancel CancelFunc) { - p.onCancel = onCancel -} - func (p *Picker) ClearInput() { p.input.SetText("") } @@ -128,15 +115,6 @@ func (p *Picker) Update() { p.onInputChanged("") } -func (p *Picker) onListSelected(index int) { - if p.onSelected != nil { - if index >= 0 && index < len(p.filtered) { - item := p.filtered[index] - p.onSelected(item) - } - } -} - func (p *Picker) onInputChanged(text string) { var fuzzied Items if text == "" { @@ -167,14 +145,11 @@ func (p *Picker) HandleEvent(event tcell.Event) tview.Command { case keybind.Matches(event, p.keyMap.Bottom): p.list.HandleEvent(tcell.NewEventKey(tcell.KeyEnd, "", tcell.ModNone)) return nil + case keybind.Matches(event, p.keyMap.Select): - p.onListSelected(p.list.Cursor()) - return nil + return p._select() case keybind.Matches(event, p.keyMap.Cancel): - if p.onCancel != nil { - p.onCancel() - } - return nil + return cancel() } }