package tui import ( "sevenkeys/constants" "sevenkeys/figlet" "sevenkeys/tui/searchui" "sevenkeys/tui/updateui" "strings" "github.com/charmbracelet/bubbles/help" "github.com/charmbracelet/bubbles/key" tea "github.com/charmbracelet/bubbletea" ) type sessionState int const ( homeView sessionState = iota updateView searchView ) type homeKeyMappings struct { Update key.Binding SearchCriteria key.Binding Search key.Binding StorageOptions key.Binding Find key.Binding Quit key.Binding } func (k homeKeyMappings) ShortHelp() []key.Binding { return []key.Binding{k.Update, k.SearchCriteria, k.Search, k.StorageOptions, k.Find, k.Quit} } func (k homeKeyMappings) FullHelp() [][]key.Binding { return [][]key.Binding{ {k.Update, k.SearchCriteria, k.Search}, {k.StorageOptions, k.Find, k.Quit}, } } type MainModel struct { state sessionState updateModel tea.Model searchModel tea.Model help help.Model keyMappings homeKeyMappings } func NewMainModel() MainModel { help := help.New() help.ShortSeparator = help.FullSeparator updateModel := updateui.NewUpdateModel() searchModel := searchui.NewSearchModel() keyMappings := homeKeyMappings{ Update: key.NewBinding( key.WithKeys("u"), key.WithHelp("u", "update database"), ), SearchCriteria: key.NewBinding( key.WithKeys("c"), key.WithHelp("c", "card printing search criteria"), ), Search: key.NewBinding( key.WithKeys("s"), key.WithHelp("s", "card printing search"), ), StorageOptions: key.NewBinding( key.WithKeys("o"), key.WithHelp("o", "card storage options"), ), Find: key.NewBinding( key.WithKeys("f"), key.WithHelp("f", "find in storage"), ), Quit: key.NewBinding( key.WithKeys("ctrl+c", "q"), key.WithHelp("q", "quit program"), ), } return MainModel{ state: homeView, updateModel: updateModel, searchModel: searchModel, help: help, keyMappings: keyMappings, } } func (m MainModel) Init() tea.Cmd { return nil } func renderHomeScreen(m MainModel) string { var ui string // Display splash screen ui += figlet.SprintMsgSlant("SEVENKEYS", "center") ui += figlet.SprintMsgTerm("the ultimate Magic: the Gathering trading card storage system", "center") // Display help ui += strings.Repeat("\n", constants.WindowHeight-8) // TODO: Avoid hardcoding height somehow ui += m.help.View(m.keyMappings) return ui } func (m MainModel) View() string { var ui string if constants.WindowWidth <= 0 { return ui } switch m.state { case homeView: ui += renderHomeScreen(m) break case updateView: ui += m.updateModel.View() break case searchView: ui += m.searchModel.View() break } return ui } func (m MainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var cmd tea.Cmd var cmds []tea.Cmd switch msg := msg.(type) { case tea.WindowSizeMsg: constants.WindowHeight = msg.Height constants.WindowWidth = msg.Width m.help.Width = msg.Width case tea.KeyMsg: switch { case key.Matches(msg, m.keyMappings.Quit): return m, tea.Quit } case updateui.BackMsg: m.state = homeView } switch m.state { case homeView: switch msg := msg.(type) { case tea.KeyMsg: switch { case key.Matches(msg, m.keyMappings.Update): m.state = updateView case key.Matches(msg, m.keyMappings.Search): m.state = searchView } } case updateView: newUpdate, newCmd := m.updateModel.Update(msg) newUpdateModel, ok := newUpdate.(updateui.Model) if !ok { panic("Could not perform assertion on updateui.Model") } m.updateModel = newUpdateModel cmd = newCmd case searchView: newSearch, newCmd := m.searchModel.Update(msg) newSearchModel, ok := newSearch.(searchui.Model) if !ok { panic("Could not perform assertion on searchui.Model") } m.searchModel = newSearchModel cmd = newCmd } cmds = append(cmds, cmd) return m, tea.Batch(cmds...) }