Add time page
This commit is contained in:
@ -18,12 +18,25 @@ func (i Item) Title() string { return i.text }
|
||||
func (i Item) Description() string { return "" }
|
||||
func (i Item) FilterValue() string { return i.text }
|
||||
|
||||
// creationItem is a special item for creating new entries
|
||||
type creationItem struct {
|
||||
text string
|
||||
filter string
|
||||
}
|
||||
|
||||
func (i creationItem) Title() string { return i.text }
|
||||
func (i creationItem) Description() string { return "" }
|
||||
func (i creationItem) FilterValue() string { return i.filter }
|
||||
|
||||
type Picker struct {
|
||||
common *common.Common
|
||||
list list.Model
|
||||
itemProvider func() []list.Item
|
||||
onSelect func(list.Item) tea.Cmd
|
||||
onCreate func(string) tea.Cmd
|
||||
title string
|
||||
filterByDefault bool
|
||||
baseItems []list.Item
|
||||
}
|
||||
|
||||
type PickerOption func(*Picker)
|
||||
@ -34,10 +47,16 @@ func WithFilterByDefault(enabled bool) PickerOption {
|
||||
}
|
||||
}
|
||||
|
||||
func WithOnCreate(onCreate func(string) tea.Cmd) PickerOption {
|
||||
return func(p *Picker) {
|
||||
p.onCreate = onCreate
|
||||
}
|
||||
}
|
||||
|
||||
func New(
|
||||
c *common.Common,
|
||||
title string,
|
||||
items []list.Item,
|
||||
itemProvider func() []list.Item,
|
||||
onSelect func(list.Item) tea.Cmd,
|
||||
opts ...PickerOption,
|
||||
) *Picker {
|
||||
@ -45,7 +64,7 @@ func New(
|
||||
delegate.ShowDescription = false
|
||||
delegate.SetSpacing(0)
|
||||
|
||||
l := list.New(items, delegate, 0, 0)
|
||||
l := list.New([]list.Item{}, delegate, 0, 0)
|
||||
l.SetShowTitle(false)
|
||||
l.SetShowHelp(false)
|
||||
l.SetShowStatusBar(false)
|
||||
@ -58,10 +77,11 @@ func New(
|
||||
)
|
||||
|
||||
p := &Picker{
|
||||
common: c,
|
||||
list: l,
|
||||
onSelect: onSelect,
|
||||
title: title,
|
||||
common: c,
|
||||
list: l,
|
||||
itemProvider: itemProvider,
|
||||
onSelect: onSelect,
|
||||
title: title,
|
||||
}
|
||||
|
||||
if c.TW.GetConfig().Get("uda.tasksquire.picker.filter_by_default") == "yes" {
|
||||
@ -72,18 +92,43 @@ func New(
|
||||
opt(p)
|
||||
}
|
||||
|
||||
p.Refresh()
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *Picker) Refresh() tea.Cmd {
|
||||
p.baseItems = p.itemProvider()
|
||||
return p.updateListItems()
|
||||
}
|
||||
|
||||
func (p *Picker) updateListItems() tea.Cmd {
|
||||
items := p.baseItems
|
||||
filterVal := p.list.FilterValue()
|
||||
|
||||
if p.onCreate != nil && filterVal != "" {
|
||||
newItem := creationItem{
|
||||
text: "(new) " + filterVal,
|
||||
filter: filterVal,
|
||||
}
|
||||
newItems := make([]list.Item, len(items)+1)
|
||||
copy(newItems, items)
|
||||
newItems[len(items)] = newItem
|
||||
items = newItems
|
||||
}
|
||||
|
||||
return p.list.SetItems(items)
|
||||
}
|
||||
|
||||
func (p *Picker) SetSize(width, height int) {
|
||||
// We do NOT set common.SetSize here, as we are a sub-component.
|
||||
|
||||
|
||||
// Set list size. The parent is responsible for providing a reasonable size.
|
||||
// If this component is intended to fill a page, width/height will be large.
|
||||
// If it's a small embedded box, they will be small.
|
||||
// We apply a small margin for the title if needed, but for now we just pass through
|
||||
// minus a header gap if we render a title.
|
||||
|
||||
|
||||
headerHeight := 2 // Title + gap
|
||||
p.list.SetSize(width, height-headerHeight)
|
||||
}
|
||||
@ -107,7 +152,7 @@ func (p *Picker) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
if key.Matches(msg, p.common.Keymap.Ok) {
|
||||
items := p.list.VisibleItems()
|
||||
if len(items) == 1 {
|
||||
return p, p.onSelect(items[0])
|
||||
return p, p.handleSelect(items[0])
|
||||
}
|
||||
}
|
||||
break // Pass to list.Update
|
||||
@ -119,19 +164,39 @@ func (p *Picker) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
if selectedItem == nil {
|
||||
return p, nil
|
||||
}
|
||||
return p, p.onSelect(selectedItem)
|
||||
return p, p.handleSelect(selectedItem)
|
||||
}
|
||||
}
|
||||
|
||||
prevFilter := p.list.FilterValue()
|
||||
p.list, cmd = p.list.Update(msg)
|
||||
|
||||
if p.list.FilterValue() != prevFilter {
|
||||
updateCmd := p.updateListItems()
|
||||
return p, tea.Batch(cmd, updateCmd)
|
||||
}
|
||||
|
||||
return p, cmd
|
||||
}
|
||||
|
||||
func (p *Picker) handleSelect(item list.Item) tea.Cmd {
|
||||
if cItem, ok := item.(creationItem); ok {
|
||||
if p.onCreate != nil {
|
||||
return p.onCreate(cItem.filter)
|
||||
}
|
||||
}
|
||||
return p.onSelect(item)
|
||||
}
|
||||
|
||||
func (p *Picker) View() string {
|
||||
title := p.common.Styles.Form.Focused.Title.Render(p.title)
|
||||
return lipgloss.JoinVertical(lipgloss.Left, title, p.list.View())
|
||||
}
|
||||
|
||||
func (p *Picker) IsFiltering() bool {
|
||||
return p.list.FilterState() == list.Filtering
|
||||
}
|
||||
|
||||
// SelectItemByFilterValue selects the item with the given filter value
|
||||
func (p *Picker) SelectItemByFilterValue(filterValue string) {
|
||||
items := p.list.Items()
|
||||
@ -141,4 +206,4 @@ func (p *Picker) SelectItemByFilterValue(filterValue string) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user