dynamo-browse/internal/dynamo-browse/ui/teamodels/relselector/listmdl.go
Leon Mika 5d95d44a97
Added the rel-picker which can quickly goto related tables
* New rel-picker that can be opened using Shift+O and allows for quickly going to related tables.
2024-03-03 09:20:28 +11:00

133 lines
3.7 KiB
Go

package relselector
import (
"strings"
"github.com/charmbracelet/bubbles/key"
"github.com/charmbracelet/bubbles/list"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/lmika/dynamo-browse/internal/common/sliceutils"
"github.com/lmika/dynamo-browse/internal/common/ui/events"
"github.com/lmika/dynamo-browse/internal/dynamo-browse/controllers"
"github.com/lmika/dynamo-browse/internal/dynamo-browse/models/relitems"
"github.com/lmika/dynamo-browse/internal/dynamo-browse/ui/teamodels/layout"
"github.com/lmika/dynamo-browse/internal/dynamo-browse/ui/teamodels/utils"
)
var (
frameColor = lipgloss.Color("63")
frameStyle = lipgloss.NewStyle().
Foreground(frameColor)
style = lipgloss.NewStyle().
BorderStyle(lipgloss.NormalBorder()).
BorderForeground(frameColor)
keyEsc = key.NewBinding(key.WithKeys(tea.KeyEsc.String()))
keyEnter = key.NewBinding(key.WithKeys(tea.KeyEnter.String()))
)
type listModel struct {
event controllers.ShowRelatedItemsOverlay
list list.Model
height int
}
func newListModel() *listModel {
items := []list.Item{}
delegate := list.NewDefaultDelegate()
delegate.ShowDescription = false
delegate.Styles.SelectedTitle = lipgloss.NewStyle().
Border(lipgloss.NormalBorder(), false, false, false, true).
BorderForeground(lipgloss.Color("#2c5fb7")).
Foreground(lipgloss.Color("#2c5fb7")).
Padding(0, 0, 0, 1)
delegate.Styles.SelectedDesc = lipgloss.NewStyle().
Border(lipgloss.NormalBorder(), false, false, false, true).
BorderForeground(lipgloss.Color("#2c5fb7")).
Foreground(lipgloss.Color("#5277b7")).
Padding(0, 0, 0, 1)
list := list.New(items, delegate, overlayWidth, overlayHeight-4)
list.KeyMap.CursorUp = key.NewBinding(
key.WithKeys("up", "i"),
key.WithHelp("↑/i", "up"),
)
list.KeyMap.CursorDown = key.NewBinding(
key.WithKeys("down", "k"),
key.WithHelp("↓/k", "down"),
)
list.KeyMap.PrevPage = key.NewBinding(
key.WithKeys("left", "j", "pgup", "b", "u"),
key.WithHelp("←/j/pgup", "prev page"),
)
list.KeyMap.NextPage = key.NewBinding(
key.WithKeys("right", "l", "pgdown", "f", "d"),
key.WithHelp("→/l/pgdn", "next page"),
)
list.SetShowTitle(false)
list.SetShowHelp(false)
//list.DisableQuitKeybindings()
return &listModel{
list: list,
}
}
func (m *listModel) Init() tea.Cmd {
return nil
}
func (m *listModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cc utils.CmdCollector
switch msg := msg.(type) {
case tea.KeyMsg:
switch {
case key.Matches(msg, keyEnter):
if onSel := m.event.OnSelected; onSel != nil {
cc.Add(events.SetTeaMessage(onSel(m.event.Items[m.list.Index()])))
}
return m, events.SetTeaMessage(controllers.HideColumnOverlay{})
case key.Matches(msg, keyEsc):
return m, events.SetTeaMessage(controllers.HideColumnOverlay{})
default:
m.list = cc.Collect(m.list.Update(msg)).(list.Model)
}
default:
m.list = cc.Collect(m.list.Update(msg)).(list.Model)
}
return m, cc.Cmd()
}
func (m *listModel) View() string {
innerView := lipgloss.JoinVertical(
lipgloss.Top,
lipgloss.PlaceHorizontal(overlayWidth-2, lipgloss.Center, "Related Items"),
frameStyle.Render(strings.Repeat(lipgloss.NormalBorder().Top, overlayWidth-2)),
m.list.View(),
)
view := style.Width(overlayWidth - 2).Height(m.height - 2).Render(innerView)
return view
}
func (m *listModel) Resize(w, h int) layout.ResizingModel {
return m
}
func (m *listModel) setItems(event controllers.ShowRelatedItemsOverlay, newHeight int) {
listItems := sliceutils.Map(event.Items, func(item relitems.RelatedItem) list.Item {
return relItemModel{name: item.Name}
})
m.event = event
m.list.SetItems(listItems)
m.list.Select(0)
m.list.SetHeight(newHeight - 4)
m.height = newHeight
}