refactor(ui): adopt tview Change and Keybind APIs
This commit is contained in:
parent
2b651a1459
commit
9dc509e300
16 changed files with 163 additions and 80 deletions
2
go.mod
2
go.mod
|
|
@ -15,7 +15,7 @@ require (
|
|||
github.com/andybalholm/brotli v1.2.5
|
||||
github.com/ayn2op/arikawa/v3 v3.0.0-20260904042054-7df757872273
|
||||
github.com/ayn2op/ningen/v3 v3.0.1-0.20260904045623-5978c9be899f
|
||||
github.com/ayn2op/tview v0.0.0-20260928003911-758a51d24cad
|
||||
github.com/ayn2op/tview v0.0.0-20260928205525-fa36e0ece3f0
|
||||
github.com/bogdanfinn/fhttp v0.6.9
|
||||
github.com/bogdanfinn/tls-client v1.16.0
|
||||
github.com/gdamore/tcell/v3 v3.5.0
|
||||
|
|
|
|||
2
go.sum
2
go.sum
|
|
@ -164,3 +164,5 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
|||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
github.com/ayn2op/tview v0.0.0-20260928205525-fa36e0ece3f0 h1:mh5nA4XFDLYLmLs++EhN2X+6LODI0tTbRRQFp4Q4F/A=
|
||||
github.com/ayn2op/tview v0.0.0-20260928205525-fa36e0ece3f0/go.mod h1:oRPTSZgaEJPhv3dmmNvo6grBq/BemrLG3wFQLMTZJkY=
|
||||
|
|
|
|||
19
internal/config/help.go
Normal file
19
internal/config/help.go
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"github.com/ayn2op/tview/help"
|
||||
"github.com/ayn2op/tview/keybind"
|
||||
)
|
||||
|
||||
var _ help.KeyMap = PickerKeybinds{}
|
||||
|
||||
func (k PickerKeybinds) ShortHelp() []keybind.Keybind {
|
||||
return []keybind.Keybind{k.SelectUp.Keybind, k.SelectDown.Keybind, k.Select.Keybind, k.Cancel.Keybind}
|
||||
}
|
||||
|
||||
func (k PickerKeybinds) FullHelp() [][]keybind.Keybind {
|
||||
return [][]keybind.Keybind{
|
||||
{k.SelectUp.Keybind, k.SelectDown.Keybind, k.SelectTop.Keybind, k.SelectBottom.Keybind},
|
||||
{k.Select.Keybind, k.Cancel.Keybind},
|
||||
}
|
||||
}
|
||||
|
|
@ -24,15 +24,15 @@ func NewModel(cfg *config.Config) Model {
|
|||
|
||||
var _ tview.Model[Model] = Model{}
|
||||
|
||||
// actionMsg changes the picker.
|
||||
type actionMsg picker.Action
|
||||
// changeMsg changes the picker.
|
||||
type changeMsg picker.Change
|
||||
|
||||
func (Model) Init() tview.Cmd { return nil }
|
||||
|
||||
// View shows the picker in a box titled Attachments.
|
||||
func (m Model) View() tview.Element {
|
||||
p := ui.Picker(m.items, &m.searchState, m.cfg).
|
||||
OnAction(func(a picker.Action) tview.Msg { return actionMsg(a) }).
|
||||
OnChange(func(a picker.Change) tview.Msg { return changeMsg(a) }).
|
||||
OnSelect(func(item picker.Item) tview.Msg {
|
||||
action, ok := item.Reference.(tview.Cmd)
|
||||
if !ok {
|
||||
|
|
@ -54,8 +54,8 @@ func (m *Model) SetItems(items []Item) {
|
|||
}
|
||||
|
||||
func (m Model) Update(msg tview.Msg) (Model, tview.Cmd) {
|
||||
if msg, ok := msg.(actionMsg); ok {
|
||||
m.searchState.Perform(picker.Action(msg))
|
||||
if msg, ok := msg.(changeMsg); ok {
|
||||
m.searchState.Apply(picker.Change(msg))
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,15 +24,15 @@ func NewModel(cfg *config.Config) Model {
|
|||
|
||||
var _ tview.Model[Model] = Model{}
|
||||
|
||||
// actionMsg changes the picker.
|
||||
type actionMsg picker.Action
|
||||
// changeMsg changes the picker.
|
||||
type changeMsg picker.Change
|
||||
|
||||
func (Model) Init() tview.Cmd { return nil }
|
||||
|
||||
// View shows the picker in a box titled Channels.
|
||||
func (m Model) View() tview.Element {
|
||||
p := ui.Picker(m.items, &m.searchState, m.cfg).
|
||||
OnAction(func(a picker.Action) tview.Msg { return actionMsg(a) }).
|
||||
OnChange(func(a picker.Change) tview.Msg { return changeMsg(a) }).
|
||||
OnSelect(func(item picker.Item) tview.Msg {
|
||||
channelID, ok := item.Reference.(discord.ChannelID)
|
||||
if !ok || !channelID.IsValid() {
|
||||
|
|
@ -45,8 +45,8 @@ func (m Model) View() tview.Element {
|
|||
}
|
||||
|
||||
func (m Model) Update(msg tview.Msg) (Model, tview.Cmd) {
|
||||
if msg, ok := msg.(actionMsg); ok {
|
||||
m.searchState.Perform(picker.Action(msg))
|
||||
if msg, ok := msg.(changeMsg); ok {
|
||||
m.searchState.Apply(picker.Change(msg))
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ var mentionRegex = regexp.MustCompile("@[a-zA-Z0-9._]+")
|
|||
type Model struct {
|
||||
title, footer string
|
||||
editState textarea.EditState
|
||||
keybinds textarea.Keybinds
|
||||
placeholder string
|
||||
disabled bool
|
||||
|
||||
|
|
@ -88,7 +87,7 @@ type SentMsg struct{}
|
|||
type editorMsg string
|
||||
|
||||
// editMsg edits the composer's text.
|
||||
type editMsg textarea.Action
|
||||
type editMsg textarea.Change
|
||||
|
||||
var _ help.KeyMap = Model{}
|
||||
|
||||
|
|
@ -103,8 +102,6 @@ func NewModel(cfg *config.Config, state *ningen.State) Model {
|
|||
mentionsList: mentionslist.NewModel(cfg),
|
||||
height: 3,
|
||||
}
|
||||
c.keybinds = textarea.DefaultKeybinds()
|
||||
c.keybinds.Newline = cfg.Keybinds.Composer.Newline.Keybind
|
||||
return c
|
||||
}
|
||||
|
||||
|
|
@ -153,9 +150,9 @@ func (v view) Handle(msg tview.Msg, area tview.Rectangle) tview.Msg {
|
|||
func (c *Model) box(focused bool) box.Widget {
|
||||
text := textarea.New(&c.editState).
|
||||
Placeholder(c.placeholder).
|
||||
Keybinds(c.keybinds).
|
||||
Keybind(c.editAction).
|
||||
Focused(focused && !c.disabled).
|
||||
OnAction(func(a textarea.Action) tview.Msg { return editMsg(a) })
|
||||
OnChange(func(a textarea.Change) tview.Msg { return editMsg(a) })
|
||||
return ui.Box(text, &c.cfg.Theme, focused).Title(c.title).Footer(c.footer)
|
||||
}
|
||||
|
||||
|
|
@ -254,7 +251,7 @@ func (c *Model) update(msg tview.Msg) tview.Cmd {
|
|||
c.setText(string(msg))
|
||||
return nil
|
||||
case editMsg:
|
||||
c.editState.Perform(textarea.Action(msg))
|
||||
c.editState.Apply(textarea.Change(msg))
|
||||
c.resizeForContent()
|
||||
typingCmd := c.sendTyping()
|
||||
if c.cfg.AutocompleteLimit > 0 {
|
||||
|
|
@ -953,6 +950,15 @@ func (c *Model) canAttachFiles() bool {
|
|||
return c.channel != nil && c.state.HasPermissions(c.channel.ID, discord.PermissionAttachFiles)
|
||||
}
|
||||
|
||||
// editAction binds the configured newline key and textarea's other default keys.
|
||||
func (c Model) editAction(key tview.KeyMsg) (textarea.Action, bool) {
|
||||
if keybind.Matches(key, c.cfg.Keybinds.Composer.Newline.Keybind) {
|
||||
return textarea.ActionNewline, true
|
||||
}
|
||||
action, ok := textarea.DefaultKeybind(key)
|
||||
return action, ok && action != textarea.ActionNewline
|
||||
}
|
||||
|
||||
func (c Model) ShortHelp() []keybind.Keybind {
|
||||
if c.mentionsVisible {
|
||||
cfg := c.cfg.Keybinds.MentionsList
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ func (m *Model) CurrentNode() *tree.Node {
|
|||
}
|
||||
|
||||
// Msg moves or scrolls the tree.
|
||||
type Msg tree.Action
|
||||
type Msg tree.Change
|
||||
|
||||
// View shows the tree in a box titled Guilds.
|
||||
func (m Model) View(focused bool) tview.Element {
|
||||
|
|
@ -66,16 +66,9 @@ func (m Model) View(focused bool) tview.Element {
|
|||
Graphics(theme.GuildsTree.Graphics).
|
||||
GraphicsSet(set).
|
||||
GraphicsStyle(tcell.StyleDefault.Foreground(tcell.GetColor(theme.GuildsTree.GraphicsColor))).
|
||||
Keybinds(tree.Keybinds{
|
||||
Up: kbs.SelectUp.Keybind,
|
||||
Down: kbs.SelectDown.Keybind,
|
||||
Top: kbs.SelectTop.Keybind,
|
||||
Bottom: kbs.SelectBottom.Keybind,
|
||||
MoveToParent: kbs.MoveToParentNode.Keybind,
|
||||
Select: kbs.SelectCurrent.Keybind,
|
||||
}).
|
||||
Keybind(ui.TreeKeybind(kbs)).
|
||||
Focused(focused).
|
||||
OnAction(func(a tree.Action) tview.Msg { return Msg(a) })
|
||||
OnChange(func(a tree.Change) tview.Msg { return Msg(a) })
|
||||
return ui.Box(t, theme, focused).Title("Guilds")
|
||||
}
|
||||
|
||||
|
|
@ -356,7 +349,7 @@ func (m *Model) update(msg tview.Msg) tview.Cmd {
|
|||
case NavigateMsg:
|
||||
return m.navigate(msg.ChannelID)
|
||||
case Msg:
|
||||
m.selectionState.Perform(tree.Action(msg))
|
||||
m.selectionState.Apply(tree.Change(msg))
|
||||
return nil
|
||||
case tree.SelectedMsg:
|
||||
m.selectionState.SetCurrentNode(msg.Node)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package chat
|
||||
|
||||
import (
|
||||
"github.com/ayn2op/discordo/internal/ui"
|
||||
"github.com/ayn2op/tview/help"
|
||||
"github.com/ayn2op/tview/keybind"
|
||||
)
|
||||
|
|
@ -28,7 +27,7 @@ func (m Model) FullHelp() [][]keybind.Keybind {
|
|||
|
||||
func (m Model) activeKeyMap() help.KeyMap {
|
||||
if m.pickerOpen() {
|
||||
return ui.PickerKeybinds(m.cfg)
|
||||
return m.cfg.Keybinds.Picker
|
||||
}
|
||||
|
||||
switch m.focused {
|
||||
|
|
|
|||
|
|
@ -15,22 +15,14 @@ type Model struct {
|
|||
selectionState list.SelectionState
|
||||
items []Item
|
||||
entries []list.Item
|
||||
keybinds list.Keybinds
|
||||
}
|
||||
|
||||
// Msg moves the list.
|
||||
type Msg list.Action
|
||||
type Msg list.Change
|
||||
|
||||
func NewModel(cfg *config.Config) Model {
|
||||
m := Model{cfg: cfg, selectionState: list.NewSelectionState()}
|
||||
|
||||
kbs := cfg.Keybinds.MentionsList
|
||||
m.keybinds = list.Keybinds{
|
||||
SelectUp: kbs.SelectUp.Keybind,
|
||||
SelectDown: kbs.SelectDown.Keybind,
|
||||
SelectTop: kbs.SelectTop.Keybind,
|
||||
SelectBottom: kbs.SelectBottom.Keybind,
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
|
|
@ -46,15 +38,15 @@ func (Model) Init() tview.Cmd { return nil }
|
|||
func (m Model) listView() list.Widget {
|
||||
return list.New(&m.selectionState, len(m.entries), func(i int) list.Item { return m.entries[i] }).
|
||||
SelectedStyle(tcell.StyleDefault.Reverse(true)).
|
||||
Keybinds(m.keybinds).
|
||||
Keybind(ui.SelectionKeybind(m.cfg.Keybinds.MentionsList.SelectionKeybinds)).
|
||||
// The list is only shown while mentions are being completed, so it takes its keys first.
|
||||
Focused(true).
|
||||
OnAction(func(a list.Action) tview.Msg { return Msg(a) })
|
||||
OnChange(func(a list.Change) tview.Msg { return Msg(a) })
|
||||
}
|
||||
|
||||
func (m Model) Update(msg tview.Msg) (Model, tview.Cmd) {
|
||||
if msg, ok := msg.(Msg); ok {
|
||||
m.selectionState.Perform(list.Action(msg))
|
||||
m.selectionState.Apply(list.Change(msg))
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@ type Model struct {
|
|||
|
||||
scrollBar scrollbar.Widget
|
||||
scrollBarVisibility list.ScrollBarVisibility
|
||||
keybinds list.Keybinds
|
||||
|
||||
cfg *config.Config
|
||||
state *ningen.State
|
||||
|
|
@ -83,12 +82,6 @@ func NewModel(cfg *config.Config, state *ningen.State) Model {
|
|||
|
||||
ml.selectionState.SetTrackEnd(true)
|
||||
ml.selectionState.ScrollToEnd()
|
||||
ml.keybinds = list.Keybinds{
|
||||
ScrollUp: cfg.Keybinds.MessagesList.ScrollUp.Keybind,
|
||||
ScrollDown: cfg.Keybinds.MessagesList.ScrollDown.Keybind,
|
||||
ScrollTop: cfg.Keybinds.MessagesList.ScrollTop.Keybind,
|
||||
ScrollBottom: cfg.Keybinds.MessagesList.ScrollBottom.Keybind,
|
||||
}
|
||||
ml.scrollBarVisibility = cfg.Theme.ScrollBar.Visibility.ScrollBarVisibility
|
||||
ml.scrollBar = scrollbar.New().
|
||||
TrackStyle(cfg.Theme.ScrollBar.TrackStyle.Style).
|
||||
|
|
@ -99,7 +92,7 @@ func NewModel(cfg *config.Config, state *ningen.State) Model {
|
|||
}
|
||||
|
||||
// listMsg moves or scrolls the messages list.
|
||||
type listMsg list.Action
|
||||
type listMsg list.Change
|
||||
|
||||
// View shows the messages in a box titled with the channel and footed with who is typing.
|
||||
func (ml Model) View(focused bool) tview.Element {
|
||||
|
|
@ -110,9 +103,9 @@ func (ml *Model) listView(focused bool) list.Widget {
|
|||
return list.New(&ml.selectionState, len(ml.items), ml.buildItem).
|
||||
SelectedStyle(ml.cfg.Theme.MessagesList.SelectedMessageStyle.Style).
|
||||
ScrollBar(ml.scrollBar, ml.scrollBarVisibility).
|
||||
Keybinds(ml.keybinds).
|
||||
Keybind(ui.ScrollKeybind(ml.cfg.Keybinds.MessagesList.ScrollKeybinds)).
|
||||
Focused(focused).
|
||||
OnAction(func(a list.Action) tview.Msg { return listMsg(a) })
|
||||
OnChange(func(a list.Change) tview.Msg { return listMsg(a) })
|
||||
}
|
||||
|
||||
func (ml *Model) cursor() int {
|
||||
|
|
@ -903,7 +896,7 @@ func (ml *Model) update(msg tview.Msg) tview.Cmd {
|
|||
case attachmentActionMsg:
|
||||
return msg.Action
|
||||
case listMsg:
|
||||
ml.selectionState.Perform(list.Action(msg))
|
||||
ml.selectionState.Apply(list.Change(msg))
|
||||
ml.onRowCursorChanged(ml.cursor())
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
77
internal/ui/keybind.go
Normal file
77
internal/ui/keybind.go
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
package ui
|
||||
|
||||
import (
|
||||
"github.com/ayn2op/discordo/internal/config"
|
||||
"github.com/ayn2op/tview"
|
||||
"github.com/ayn2op/tview/keybind"
|
||||
"github.com/ayn2op/tview/list"
|
||||
"github.com/ayn2op/tview/picker"
|
||||
"github.com/ayn2op/tview/tree"
|
||||
)
|
||||
|
||||
// SelectionKeybind binds kbs to moving a list's selection.
|
||||
func SelectionKeybind(kbs config.SelectionKeybinds) func(tview.KeyMsg) (list.Action, bool) {
|
||||
return func(key tview.KeyMsg) (list.Action, bool) {
|
||||
switch {
|
||||
case keybind.Matches(key, kbs.SelectUp.Keybind):
|
||||
return list.ActionSelectUp, true
|
||||
case keybind.Matches(key, kbs.SelectDown.Keybind):
|
||||
return list.ActionSelectDown, true
|
||||
case keybind.Matches(key, kbs.SelectTop.Keybind):
|
||||
return list.ActionSelectTop, true
|
||||
case keybind.Matches(key, kbs.SelectBottom.Keybind):
|
||||
return list.ActionSelectBottom, true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
|
||||
// ScrollKeybind binds kbs to scrolling a list.
|
||||
func ScrollKeybind(kbs config.ScrollKeybinds) func(tview.KeyMsg) (list.Action, bool) {
|
||||
return func(key tview.KeyMsg) (list.Action, bool) {
|
||||
switch {
|
||||
case keybind.Matches(key, kbs.ScrollUp.Keybind):
|
||||
return list.ActionScrollUp, true
|
||||
case keybind.Matches(key, kbs.ScrollDown.Keybind):
|
||||
return list.ActionScrollDown, true
|
||||
case keybind.Matches(key, kbs.ScrollTop.Keybind):
|
||||
return list.ActionScrollTop, true
|
||||
case keybind.Matches(key, kbs.ScrollBottom.Keybind):
|
||||
return list.ActionScrollBottom, true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
|
||||
// TreeKeybind binds kbs to moving through a tree and selecting its nodes.
|
||||
func TreeKeybind(kbs config.GuildsTreeKeybinds) func(tview.KeyMsg) (tree.Action, bool) {
|
||||
return func(key tview.KeyMsg) (tree.Action, bool) {
|
||||
switch {
|
||||
case keybind.Matches(key, kbs.SelectUp.Keybind):
|
||||
return tree.ActionUp, true
|
||||
case keybind.Matches(key, kbs.SelectDown.Keybind):
|
||||
return tree.ActionDown, true
|
||||
case keybind.Matches(key, kbs.SelectTop.Keybind):
|
||||
return tree.ActionTop, true
|
||||
case keybind.Matches(key, kbs.SelectBottom.Keybind):
|
||||
return tree.ActionBottom, true
|
||||
case keybind.Matches(key, kbs.MoveToParentNode.Keybind):
|
||||
return tree.ActionMoveToParent, true
|
||||
case keybind.Matches(key, kbs.SelectCurrent.Keybind):
|
||||
return tree.ActionSelect, true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
|
||||
func pickerKeybind(kbs config.PickerKeybinds) func(tview.KeyMsg) (picker.Action, bool) {
|
||||
return func(key tview.KeyMsg) (picker.Action, bool) {
|
||||
switch {
|
||||
case keybind.Matches(key, kbs.Select.Keybind):
|
||||
return picker.ActionSelect, true
|
||||
case keybind.Matches(key, kbs.Cancel.Keybind):
|
||||
return picker.ActionCancel, true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
|
|
@ -32,7 +32,7 @@ type SubmitMsg struct{}
|
|||
|
||||
type editMsg struct {
|
||||
index int
|
||||
action textinput.Action
|
||||
change textinput.Change
|
||||
}
|
||||
|
||||
type nextMsg struct{}
|
||||
|
|
@ -56,7 +56,7 @@ func (m Model) Update(msg tview.Msg) (Model, tview.Cmd) {
|
|||
case editMsg:
|
||||
// Earlier copies of the model share the fields, so change a copy of them.
|
||||
m.fields = slices.Clone(m.fields)
|
||||
m.fields[msg.index].EditState.Perform(msg.action)
|
||||
m.fields[msg.index].EditState.Apply(msg.change)
|
||||
case nextMsg:
|
||||
m.focus = (m.focus + 1) % count
|
||||
case tview.KeyMsg:
|
||||
|
|
@ -81,7 +81,7 @@ func (m Model) View() tview.Element {
|
|||
input := textinput.New(&f.EditState).
|
||||
Mask(f.Mask).
|
||||
Focused(m.focus == i).
|
||||
OnAction(func(a textinput.Action) tview.Msg { return editMsg{index: i, action: a} }).
|
||||
OnChange(func(a textinput.Change) tview.Msg { return editMsg{index: i, change: a} }).
|
||||
OnSubmit(nextMsg{})
|
||||
layout = layout.Push(row.New(column.New(text.New(f.Label)).Width(tview.Fixed(labelWidth)), input).Height(tview.Fixed(1)))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,27 @@
|
|||
package login
|
||||
|
||||
import (
|
||||
"github.com/ayn2op/tview"
|
||||
"github.com/ayn2op/tview/help"
|
||||
"github.com/ayn2op/tview/keybind"
|
||||
"github.com/ayn2op/tview/tabs"
|
||||
)
|
||||
|
||||
var (
|
||||
previousTab = keybind.NewSingleKeybind("ctrl+h", "prev tab")
|
||||
nextTab = keybind.NewSingleKeybind("ctrl+l", "next tab")
|
||||
)
|
||||
|
||||
func tabAction(key tview.KeyMsg) (tabs.Action, bool) {
|
||||
switch {
|
||||
case keybind.Matches(key, previousTab):
|
||||
return tabs.ActionPrevious, true
|
||||
case keybind.Matches(key, nextTab):
|
||||
return tabs.ActionNext, true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
var _ help.KeyMap = Model{}
|
||||
|
||||
func (m Model) ShortHelp() []keybind.Keybind {
|
||||
|
|
@ -30,10 +47,10 @@ func (m Model) FullHelp() [][]keybind.Keybind {
|
|||
func (m Model) navHelp() []keybind.Keybind {
|
||||
var nav []keybind.Keybind
|
||||
if m.active > 0 {
|
||||
nav = append(nav, m.keybinds.Previous)
|
||||
nav = append(nav, previousTab)
|
||||
}
|
||||
if m.active < tabCount-1 {
|
||||
nav = append(nav, m.keybinds.Next)
|
||||
nav = append(nav, nextTab)
|
||||
}
|
||||
return nav
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ type Model struct {
|
|||
qr qr.Model
|
||||
token token.Model
|
||||
active tab
|
||||
keybinds tabs.Keybinds
|
||||
}
|
||||
|
||||
var _ tview.Model[Model] = Model{}
|
||||
|
|
@ -41,7 +40,6 @@ func NewModel(cfg *config.Config) Model {
|
|||
password: password.NewModel(),
|
||||
qr: qr.NewModel(),
|
||||
token: token.NewModel(),
|
||||
keybinds: tabs.DefaultKeybinds(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -75,7 +73,7 @@ func (m Model) View() tview.Element {
|
|||
t := tabs.New(m.password.Label(), m.qr.Label(), m.token.Label()).
|
||||
Active(int(m.active)).
|
||||
Content(content).
|
||||
Keybinds(m.keybinds).
|
||||
Keybind(tabAction).
|
||||
OnSelect(func(i int) tview.Msg { return selectTabMsg(i) })
|
||||
return ui.Box(t, &m.cfg.Theme, false)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ type Model struct {
|
|||
}
|
||||
|
||||
// scrollMsg scrolls the code.
|
||||
type scrollMsg textview.Action
|
||||
type scrollMsg textview.Change
|
||||
|
||||
// startMsg starts connecting to the Remote Auth Gateway.
|
||||
type startMsg struct{}
|
||||
|
|
@ -68,7 +68,7 @@ func (m *Model) update(msg tview.Msg) tview.Cmd {
|
|||
}
|
||||
return nil
|
||||
case scrollMsg:
|
||||
m.scrollState.Perform(textview.Action(msg))
|
||||
m.scrollState.Apply(textview.Change(msg))
|
||||
return nil
|
||||
|
||||
case connCreateMsg:
|
||||
|
|
@ -147,7 +147,7 @@ func (m Model) View() tview.Element {
|
|||
Alignment(tview.AlignmentCenter).
|
||||
Height(tview.Fixed(len(m.code))).
|
||||
Focused(true).
|
||||
OnAction(func(a textview.Action) tview.Msg { return scrollMsg(a) }),
|
||||
OnChange(func(a textview.Change) tview.Msg { return scrollMsg(a) }),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,21 +45,8 @@ func Picker(items picker.Items, searchState *picker.SearchState, cfg *config.Con
|
|||
Arrows(scrollbar.ArrowsBoth)
|
||||
return picker.New(items, searchState).
|
||||
ScrollBar(bar, cfg.Theme.ScrollBar.Visibility.ScrollBarVisibility).
|
||||
Keybinds(PickerKeybinds(cfg))
|
||||
}
|
||||
|
||||
// PickerKeybinds returns the configured picker keybinds.
|
||||
func PickerKeybinds(cfg *config.Config) picker.Keybinds {
|
||||
kbs := cfg.Keybinds.Picker
|
||||
return picker.Keybinds{
|
||||
Cancel: kbs.Cancel.Keybind,
|
||||
Select: kbs.Select.Keybind,
|
||||
|
||||
SelectUp: kbs.SelectUp.Keybind,
|
||||
SelectDown: kbs.SelectDown.Keybind,
|
||||
SelectTop: kbs.SelectTop.Keybind,
|
||||
SelectBottom: kbs.SelectBottom.Keybind,
|
||||
}
|
||||
Keybind(pickerKeybind(cfg.Keybinds.Picker)).
|
||||
ListKeybind(SelectionKeybind(cfg.Keybinds.Picker.SelectionKeybinds))
|
||||
}
|
||||
|
||||
// ChannelToString returns how channel is shown in the UI: an icon for its type and its name, or the recipients' names for a DM.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue