package pages import ( "log/slog" "tasksquire/common" "tasksquire/components/picker" "github.com/charmbracelet/bubbles/key" "github.com/charmbracelet/bubbles/list" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" ) type ProjectPickerPage struct { common *common.Common picker *picker.Picker } func NewProjectPickerPage(common *common.Common, activeProject string) *ProjectPickerPage { p := &ProjectPickerPage{ common: common, } itemProvider := func() []list.Item { projects := common.TW.GetProjects() items := []list.Item{picker.NewItem("(none)")} for _, proj := range projects { items = append(items, picker.NewItem(proj)) } return items } onSelect := func(item list.Item) tea.Cmd { return func() tea.Msg { return projectSelectedMsg{item: item} } } // onCreate := func(name string) tea.Cmd { // return func() tea.Msg { return projectSelectedMsg{item: picker.NewItem(name)} } // } // p.picker = picker.New(common, "Projects", itemProvider, onSelect, picker.WithOnCreate(onCreate)) p.picker = picker.New(common, "Projects", itemProvider, onSelect) // Set active project if activeProject == "" { activeProject = "(none)" } p.picker.SelectItemByFilterValue(activeProject) p.SetSize(common.Width(), common.Height()) return p } func (p *ProjectPickerPage) SetSize(width, height int) { p.common.SetSize(width, height) // Set list size with some padding/limits to look like a picker listWidth := width - 4 if listWidth > 40 { listWidth = 40 } listHeight := height - 6 if listHeight > 20 { listHeight = 20 } p.picker.SetSize(listWidth, listHeight) } func (p *ProjectPickerPage) Init() tea.Cmd { return p.picker.Init() } type projectSelectedMsg struct { item list.Item } func (p *ProjectPickerPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var cmd tea.Cmd switch msg := msg.(type) { case tea.WindowSizeMsg: p.SetSize(msg.Width, msg.Height) case projectSelectedMsg: proj := msg.item.FilterValue() // Use FilterValue (text) if proj == "(none)" { proj = "" } model, err := p.common.PopPage() if err != nil { slog.Error("page stack empty") return nil, tea.Quit } return model, func() tea.Msg { return UpdateProjectMsg(proj) } case tea.KeyMsg: if !p.picker.IsFiltering() { switch { case key.Matches(msg, p.common.Keymap.Back): model, err := p.common.PopPage() if err != nil { slog.Error("page stack empty") return nil, tea.Quit } return model, BackCmd } } } _, cmd = p.picker.Update(msg) return p, cmd } func (p *ProjectPickerPage) View() string { width := p.common.Width() - 4 if width > 40 { width = 40 } content := p.picker.View() styledContent := lipgloss.NewStyle().Width(width).Render(content) return lipgloss.Place( p.common.Width(), p.common.Height(), lipgloss.Center, lipgloss.Center, p.common.Styles.Base.Render(styledContent), ) } func (p *ProjectPickerPage) updateProjectCmd() tea.Msg { return nil } type UpdateProjectMsg string