package filter import ( "fmt" "git.andreafazzi.eu/andrea/probo/pkg/store" "git.andreafazzi.eu/andrea/probo/pkg/store/file" "github.com/charmbracelet/bubbles/help" "github.com/charmbracelet/bubbles/key" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" "github.com/remogatto/sugarfoam/components/group" "github.com/remogatto/sugarfoam/components/header" "github.com/remogatto/sugarfoam/components/statusbar" "github.com/remogatto/sugarfoam/components/table" "github.com/remogatto/sugarfoam/components/textinput" "github.com/remogatto/sugarfoam/components/viewport" "github.com/remogatto/sugarfoam/layout" "github.com/remogatto/sugarfoam/layout/tiled" ) type Store interface { } type storeLoadedMsg struct { store file.FileStorer[store.Storable] } type FilterModel struct { // UI group *group.Model help help.Model statusBar *statusbar.Model // Layout document *layout.Layout // Key bindings bindings *keyBindings // Store store file.FileStorer[store.Storable] state int } type keyBindings struct { group *group.Model quit key.Binding } func (k *keyBindings) ShortHelp() []key.Binding { keys := make([]key.Binding, 0) current := k.group.Current() switch item := current.(type) { case *table.Model: keys = append( keys, item.KeyMap.LineUp, item.KeyMap.LineDown, ) } keys = append( keys, k.quit, ) return keys } func (k keyBindings) FullHelp() [][]key.Binding { return [][]key.Binding{ { k.quit, }, } } func newBindings(g *group.Model) *keyBindings { return &keyBindings{ group: g, quit: key.NewBinding( key.WithKeys("esc"), key.WithHelp("esc", "Quit app"), ), } } func New() *FilterModel { textinput := textinput.New( textinput.WithPlaceholder("Write your jq filter here..."), ) table := table.New() viewport := viewport.New() help := help.New() group := group.New( group.WithItems(textinput, viewport, table), group.WithLayout( layout.New( layout.WithStyles(&layout.Styles{Container: lipgloss.NewStyle().Padding(1, 0, 1, 0)}), layout.WithItem(textinput), layout.WithItem(tiled.New(viewport, table)), ), ), ) bindings := newBindings(group) statusBar := statusbar.New(bindings) header := header.New( header.WithContent( lipgloss.NewStyle(). Bold(true). Border(lipgloss.NormalBorder(), false, false, true, false). Render("Participants filter 👫"), ), ) document := layout.New( layout.WithStyles(&layout.Styles{Container: lipgloss.NewStyle().Margin(1)}), layout.WithItem(header), layout.WithItem(group), layout.WithItem(statusBar), ) return &FilterModel{ group: group, statusBar: statusBar, document: document, bindings: bindings, help: help, } } func (m *FilterModel) Init() tea.Cmd { var cmds []tea.Cmd cmds = append(cmds, m.group.Init(), loadParticipantStore()) m.group.Focus() return tea.Batch(cmds...) } func (m *FilterModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var cmds []tea.Cmd switch msg := msg.(type) { case tea.WindowSizeMsg: m.document.SetSize(msg.Width, msg.Height) case tea.KeyMsg: switch { case key.Matches(msg, m.bindings.quit): return m, tea.Quit } case storeLoadedMsg: m.handleStoreLoaded(msg) } cmds = m.handleState(msg, cmds) return m, tea.Batch(cmds...) } func (m *FilterModel) View() string { return m.document.View() } func (m *FilterModel) handleStoreLoaded(msg tea.Msg) { storeMsg := msg.(storeLoadedMsg) m.store = storeMsg.store m.state = FilterState } func (m *FilterModel) handleState(msg tea.Msg, cmds []tea.Cmd) []tea.Cmd { _, cmd := m.group.Update(msg) cmds = append(cmds, cmd) m.statusBar.SetContent( formats[FilterState][0], fmt.Sprintf(formats[FilterState][1], len(m.store.ReadAll())), formats[FilterState][2], ) return cmds } func loadParticipantStore() tea.Cmd { return func() tea.Msg { pStore, err := file.NewDefaultParticipantFileStore() if err != nil { panic(err) } return storeLoadedMsg{pStore} } }