Merge pull request 'feat(tui): always-visible capture bar with focus cycling' (#34) from feat/capture-first into main
Reviewed-on: #34
This commit was merged in pull request #34.
This commit is contained in:
+13
-3
@@ -7,21 +7,31 @@ func renderHelp(width, height int) string {
|
|||||||
title string
|
title string
|
||||||
binds [][2]string
|
binds [][2]string
|
||||||
}{
|
}{
|
||||||
|
{"Focus", [][2]string{
|
||||||
|
{"tab", "cycle focus: capture → list → detail"},
|
||||||
|
{"esc", "back / clear filter / to capture"},
|
||||||
|
{"a", "focus capture bar"},
|
||||||
|
}},
|
||||||
|
{"Capture Bar", [][2]string{
|
||||||
|
{"enter", "submit (or browse if empty)"},
|
||||||
|
{"?…", "search (type ?query)"},
|
||||||
|
{"-", "todo prefix"},
|
||||||
|
{"@", "event prefix"},
|
||||||
|
{"!", "reminder prefix"},
|
||||||
|
}},
|
||||||
{"Navigation", [][2]string{
|
{"Navigation", [][2]string{
|
||||||
{"j/k ↑/↓", "move cursor"},
|
{"j/k ↑/↓", "move cursor"},
|
||||||
{"g/G home/end", "top / bottom"},
|
{"g/G home/end", "top / bottom"},
|
||||||
{"pgup/pgdn", "page up / down"},
|
{"pgup/pgdn", "page up / down"},
|
||||||
{"enter", "view detail"},
|
{"enter", "view detail"},
|
||||||
{"esc", "back / clear filter"},
|
|
||||||
}},
|
}},
|
||||||
{"Views", [][2]string{
|
{"Views", [][2]string{
|
||||||
{"1", "stream view"},
|
{"1", "stream view"},
|
||||||
{"2", "cards view"},
|
{"2", "cards view"},
|
||||||
{"s", "cycle sort (cards)"},
|
{"s", "cycle sort (cards)"},
|
||||||
{"tab", "cycle intent (cards)"},
|
{"i", "cycle intent (cards)"},
|
||||||
}},
|
}},
|
||||||
{"Actions", [][2]string{
|
{"Actions", [][2]string{
|
||||||
{"a", "add entity (or ?query to search)"},
|
|
||||||
{"d", "delete (with confirm)"},
|
{"d", "delete (with confirm)"},
|
||||||
{"x", "toggle todo completion"},
|
{"x", "toggle todo completion"},
|
||||||
{"!", "toggle pin"},
|
{"!", "toggle pin"},
|
||||||
|
|||||||
+17
-47
@@ -19,7 +19,6 @@ type inputResult struct {
|
|||||||
|
|
||||||
type inputModel struct {
|
type inputModel struct {
|
||||||
ti textinput.Model
|
ti textinput.Model
|
||||||
active bool
|
|
||||||
preview *parse.Result
|
preview *parse.Result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,15 +30,8 @@ func newInputModel() inputModel {
|
|||||||
return inputModel{ti: ti}
|
return inputModel{ti: ti}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *inputModel) focus() {
|
func (i *inputModel) clearText() {
|
||||||
i.active = true
|
|
||||||
i.ti.Focus()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *inputModel) reset() {
|
|
||||||
i.active = false
|
|
||||||
i.ti.SetValue("")
|
i.ti.SetValue("")
|
||||||
i.ti.Blur()
|
|
||||||
i.preview = nil
|
i.preview = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,33 +93,21 @@ func (i inputModel) updateKey(msg tea.KeyMsg) inputModel {
|
|||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i inputModel) view(width int) string {
|
func (i inputModel) viewBar(width int, focused bool) string {
|
||||||
var b strings.Builder
|
tiView := i.ti.View()
|
||||||
label := "capture"
|
if focused {
|
||||||
prefix := "── "
|
return tiView
|
||||||
suffix := " "
|
|
||||||
dashCount := width - len(prefix) - len(label) - len(suffix)
|
|
||||||
if dashCount < 0 {
|
|
||||||
dashCount = 0
|
|
||||||
}
|
}
|
||||||
b.WriteString(drawerBorderStyle.Render(prefix) +
|
val := i.ti.Value()
|
||||||
hintDescStyle.Render(label) +
|
if val != "" {
|
||||||
drawerBorderStyle.Render(suffix+strings.Repeat("─", dashCount)))
|
return hintDescStyle.Render("› " + val)
|
||||||
b.WriteString("\n")
|
}
|
||||||
b.WriteString(i.ti.View())
|
return hintDescStyle.Render("› capture a thought…")
|
||||||
b.WriteString("\n")
|
|
||||||
b.WriteString(drawerHintsStyle.Render(renderHints([]hint{
|
|
||||||
{"enter", "submit"}, {"esc", "cancel"}, {"?", "search"},
|
|
||||||
{"-", "todo"}, {"@", "event"}, {"!", "reminder"},
|
|
||||||
})))
|
|
||||||
b.WriteString("\n")
|
|
||||||
b.WriteString(i.renderPreview(width))
|
|
||||||
return b.String()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i inputModel) renderPreview(width int) string {
|
func (i inputModel) previewText() string {
|
||||||
if i.preview == nil {
|
if i.preview == nil {
|
||||||
return drawerPreviewStyle.Render("")
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
p := i.preview
|
p := i.preview
|
||||||
@@ -140,7 +120,7 @@ func (i inputModel) renderPreview(width int) string {
|
|||||||
for _, t := range p.FilterTags {
|
for _, t := range p.FilterTags {
|
||||||
q += " #" + t
|
q += " #" + t
|
||||||
}
|
}
|
||||||
return drawerPreviewStyle.Render("search: " + q)
|
return "search: " + q
|
||||||
}
|
}
|
||||||
|
|
||||||
glyph := glyphForParsed(p.Glyph)
|
glyph := glyphForParsed(p.Glyph)
|
||||||
@@ -152,22 +132,16 @@ func (i inputModel) renderPreview(width int) string {
|
|||||||
var parts []string
|
var parts []string
|
||||||
parts = append(parts, glyph, body)
|
parts = append(parts, glyph, body)
|
||||||
for _, t := range p.Tags {
|
for _, t := range p.Tags {
|
||||||
parts = append(parts, tagStyle.Render("#"+t))
|
parts = append(parts, "#"+t)
|
||||||
}
|
}
|
||||||
if p.Pin {
|
if p.Pin {
|
||||||
parts = append(parts, pinnedStyle.Render("•"))
|
parts = append(parts, "•")
|
||||||
}
|
}
|
||||||
if p.CardSuffix != nil {
|
if p.CardSuffix != nil {
|
||||||
parts = append(parts, affordanceStyle.Render(*p.CardSuffix))
|
parts = append(parts, *p.CardSuffix)
|
||||||
}
|
}
|
||||||
|
|
||||||
line := strings.Join(parts, " ")
|
return strings.Join(parts, " ")
|
||||||
maxW := width - 4
|
|
||||||
if maxW > 0 && len(stripAnsi(line)) > maxW {
|
|
||||||
line = truncate(line, maxW)
|
|
||||||
}
|
|
||||||
|
|
||||||
return drawerPreviewStyle.Render(line)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func glyphForParsed(glyph string) string {
|
func glyphForParsed(glyph string) string {
|
||||||
@@ -182,7 +156,3 @@ func glyphForParsed(glyph string) string {
|
|||||||
return "—"
|
return "—"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func drawerLines() int {
|
|
||||||
return 3
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ type keyMap struct {
|
|||||||
Down key.Binding
|
Down key.Binding
|
||||||
Enter key.Binding
|
Enter key.Binding
|
||||||
Back key.Binding
|
Back key.Binding
|
||||||
Add key.Binding
|
Capture key.Binding
|
||||||
Delete key.Binding
|
Delete key.Binding
|
||||||
Quit key.Binding
|
Quit key.Binding
|
||||||
Help key.Binding
|
Help key.Binding
|
||||||
@@ -31,6 +31,7 @@ type keyMap struct {
|
|||||||
Fill key.Binding
|
Fill key.Binding
|
||||||
FocusLeft key.Binding
|
FocusLeft key.Binding
|
||||||
FocusRight key.Binding
|
FocusRight key.Binding
|
||||||
|
Tab key.Binding
|
||||||
}
|
}
|
||||||
|
|
||||||
var keys = keyMap{
|
var keys = keyMap{
|
||||||
@@ -38,7 +39,7 @@ var keys = keyMap{
|
|||||||
Down: key.NewBinding(key.WithKeys("down", "j"), key.WithHelp("↓/j", "down")),
|
Down: key.NewBinding(key.WithKeys("down", "j"), key.WithHelp("↓/j", "down")),
|
||||||
Enter: key.NewBinding(key.WithKeys("enter"), key.WithHelp("enter", "view")),
|
Enter: key.NewBinding(key.WithKeys("enter"), key.WithHelp("enter", "view")),
|
||||||
Back: key.NewBinding(key.WithKeys("esc"), key.WithHelp("esc", "back")),
|
Back: key.NewBinding(key.WithKeys("esc"), key.WithHelp("esc", "back")),
|
||||||
Add: key.NewBinding(key.WithKeys("a"), key.WithHelp("a", "add")),
|
Capture: key.NewBinding(key.WithKeys("a"), key.WithHelp("a", "capture")),
|
||||||
Delete: key.NewBinding(key.WithKeys("d"), key.WithHelp("d", "delete")),
|
Delete: key.NewBinding(key.WithKeys("d"), key.WithHelp("d", "delete")),
|
||||||
Quit: key.NewBinding(key.WithKeys("q", "ctrl+c"), key.WithHelp("q", "quit")),
|
Quit: key.NewBinding(key.WithKeys("q", "ctrl+c"), key.WithHelp("q", "quit")),
|
||||||
Help: key.NewBinding(key.WithKeys("?"), key.WithHelp("?", "help")),
|
Help: key.NewBinding(key.WithKeys("?"), key.WithHelp("?", "help")),
|
||||||
@@ -56,10 +57,11 @@ var keys = keyMap{
|
|||||||
Stream: key.NewBinding(key.WithKeys("1"), key.WithHelp("1", "stream")),
|
Stream: key.NewBinding(key.WithKeys("1"), key.WithHelp("1", "stream")),
|
||||||
Cards: key.NewBinding(key.WithKeys("2"), key.WithHelp("2", "cards")),
|
Cards: key.NewBinding(key.WithKeys("2"), key.WithHelp("2", "cards")),
|
||||||
Sort: key.NewBinding(key.WithKeys("s"), key.WithHelp("s", "sort")),
|
Sort: key.NewBinding(key.WithKeys("s"), key.WithHelp("s", "sort")),
|
||||||
Intent: key.NewBinding(key.WithKeys("tab"), key.WithHelp("tab", "intent")),
|
Intent: key.NewBinding(key.WithKeys("i"), key.WithHelp("i", "intent")),
|
||||||
Absorb: key.NewBinding(key.WithKeys("m"), key.WithHelp("m", "absorb")),
|
Absorb: key.NewBinding(key.WithKeys("m"), key.WithHelp("m", "absorb")),
|
||||||
Run: key.NewBinding(key.WithKeys("r"), key.WithHelp("r", "run checklist")),
|
Run: key.NewBinding(key.WithKeys("r"), key.WithHelp("r", "run checklist")),
|
||||||
Fill: key.NewBinding(key.WithKeys("f"), key.WithHelp("f", "fill template")),
|
Fill: key.NewBinding(key.WithKeys("f"), key.WithHelp("f", "fill template")),
|
||||||
FocusLeft: key.NewBinding(key.WithKeys("h"), key.WithHelp("h", "focus list")),
|
FocusLeft: key.NewBinding(key.WithKeys("h"), key.WithHelp("h", "focus list")),
|
||||||
FocusRight: key.NewBinding(key.WithKeys("l"), key.WithHelp("l", "focus detail")),
|
FocusRight: key.NewBinding(key.WithKeys("l"), key.WithHelp("l", "focus detail")),
|
||||||
|
Tab: key.NewBinding(key.WithKeys("tab"), key.WithHelp("tab", "focus cycle")),
|
||||||
}
|
}
|
||||||
|
|||||||
+91
-67
@@ -18,7 +18,6 @@ type viewState int
|
|||||||
const (
|
const (
|
||||||
stateList viewState = iota
|
stateList viewState = iota
|
||||||
stateDetail
|
stateDetail
|
||||||
stateInput
|
|
||||||
stateTagFilter
|
stateTagFilter
|
||||||
stateConfirm
|
stateConfirm
|
||||||
statePromote
|
statePromote
|
||||||
@@ -65,7 +64,8 @@ func (s cardsSort) next() cardsSort {
|
|||||||
type focusPane int
|
type focusPane int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
focusList focusPane = iota
|
focusCapture focusPane = iota
|
||||||
|
focusList
|
||||||
focusDetail
|
focusDetail
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -100,18 +100,30 @@ type model struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newModel(store *db.Store) model {
|
func newModel(store *db.Store) model {
|
||||||
|
inp := newInputModel()
|
||||||
|
inp.ti.Focus()
|
||||||
return model{
|
return model{
|
||||||
store: store,
|
store: store,
|
||||||
state: stateList,
|
state: stateList,
|
||||||
mode: modeStream,
|
mode: modeStream,
|
||||||
|
focus: focusCapture,
|
||||||
list: newListModel(),
|
list: newListModel(),
|
||||||
cards: newCardsModel(),
|
cards: newCardsModel(),
|
||||||
detail: newDetailModel(),
|
detail: newDetailModel(),
|
||||||
input: newInputModel(),
|
input: inp,
|
||||||
filter: newFilterModel(),
|
filter: newFilterModel(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *model) setFocus(f focusPane) tea.Cmd {
|
||||||
|
m.focus = f
|
||||||
|
if f == focusCapture {
|
||||||
|
return m.input.ti.Focus()
|
||||||
|
}
|
||||||
|
m.input.ti.Blur()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (m *model) setStatus(msg string) tea.Cmd {
|
func (m *model) setStatus(msg string) tea.Cmd {
|
||||||
m.statusSeq++
|
m.statusSeq++
|
||||||
m.status = msg
|
m.status = msg
|
||||||
@@ -119,7 +131,7 @@ func (m *model) setStatus(msg string) tea.Cmd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m model) Init() tea.Cmd {
|
func (m model) Init() tea.Cmd {
|
||||||
return loadEntities(m.store, m.listParams())
|
return tea.Batch(loadEntities(m.store, m.listParams()), m.input.ti.Focus())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m model) listParams() db.ListParams {
|
func (m model) listParams() db.ListParams {
|
||||||
@@ -192,9 +204,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
return m, nil
|
return m, nil
|
||||||
|
|
||||||
case entityCreatedMsg:
|
case entityCreatedMsg:
|
||||||
m.state = stateList
|
m.input.clearText()
|
||||||
m.input.reset()
|
|
||||||
m.recalcSizes()
|
|
||||||
return m, tea.Batch(loadEntities(m.store, m.listParams()), m.setStatus("created"))
|
return m, tea.Batch(loadEntities(m.store, m.listParams()), m.setStatus("created"))
|
||||||
|
|
||||||
case entityDeletedMsg:
|
case entityDeletedMsg:
|
||||||
@@ -268,8 +278,6 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
case tea.KeyMsg:
|
case tea.KeyMsg:
|
||||||
m.err = nil
|
m.err = nil
|
||||||
switch m.state {
|
switch m.state {
|
||||||
case stateInput:
|
|
||||||
return m.updateInput(msg)
|
|
||||||
case stateTagFilter:
|
case stateTagFilter:
|
||||||
return m.updateTagFilter(msg)
|
return m.updateTagFilter(msg)
|
||||||
case stateConfirm:
|
case stateConfirm:
|
||||||
@@ -281,6 +289,13 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
default:
|
default:
|
||||||
return m.updateKeys(msg)
|
return m.updateKeys(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
if m.focus == focusCapture {
|
||||||
|
var cmd tea.Cmd
|
||||||
|
m.input.ti, cmd = m.input.ti.Update(msg)
|
||||||
|
return m, cmd
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return m, nil
|
return m, nil
|
||||||
@@ -294,8 +309,58 @@ func (m model) updateKeys(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
|||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if msg.String() == "ctrl+c" {
|
||||||
|
return m, tea.Quit
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.focus == focusCapture {
|
||||||
|
return m.updateCapture(msg)
|
||||||
|
}
|
||||||
|
return m.updateBrowse(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m model) updateCapture(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
||||||
|
switch msg.String() {
|
||||||
|
case "enter":
|
||||||
|
val := m.input.ti.Value()
|
||||||
|
if val == "" {
|
||||||
|
cmd := m.setFocus(focusList)
|
||||||
|
return m, cmd
|
||||||
|
}
|
||||||
|
result := m.input.submit()
|
||||||
|
if result == nil {
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
if result.query {
|
||||||
|
m.searchQuery = result.body
|
||||||
|
m.searchTags = result.tags
|
||||||
|
m.input.clearText()
|
||||||
|
m.applySearch()
|
||||||
|
cmd := m.setFocus(focusList)
|
||||||
|
return m, cmd
|
||||||
|
}
|
||||||
|
if result.entity != nil {
|
||||||
|
return m, createEntity(m.store, result.entity)
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
case "esc", "tab":
|
||||||
|
cmd := m.setFocus(focusList)
|
||||||
|
return m, cmd
|
||||||
|
}
|
||||||
|
m.input = m.input.updateKey(msg)
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m model) updateBrowse(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
||||||
if m.splitDetail && m.state == stateList {
|
if m.splitDetail && m.state == stateList {
|
||||||
switch msg.String() {
|
switch msg.String() {
|
||||||
|
case "tab":
|
||||||
|
if m.focus == focusList {
|
||||||
|
m.focus = focusDetail
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
cmd := m.setFocus(focusCapture)
|
||||||
|
return m, cmd
|
||||||
case "l":
|
case "l":
|
||||||
if m.focus == focusList {
|
if m.focus == focusList {
|
||||||
m.focus = focusDetail
|
m.focus = focusDetail
|
||||||
@@ -311,9 +376,6 @@ func (m model) updateKeys(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
|||||||
m.focus = focusList
|
m.focus = focusList
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
m.splitDetail = false
|
|
||||||
m.recalcSizes()
|
|
||||||
return m, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.focus == focusDetail {
|
if m.focus == focusDetail {
|
||||||
@@ -380,9 +442,6 @@ func (m model) updateKeys(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch msg.String() {
|
switch msg.String() {
|
||||||
case "ctrl+c":
|
|
||||||
return m, tea.Quit
|
|
||||||
|
|
||||||
case "q":
|
case "q":
|
||||||
if m.state == stateList {
|
if m.state == stateList {
|
||||||
return m, tea.Quit
|
return m, tea.Quit
|
||||||
@@ -418,7 +477,7 @@ func (m model) updateKeys(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
|||||||
}
|
}
|
||||||
return m, nil
|
return m, nil
|
||||||
|
|
||||||
case "tab":
|
case "i":
|
||||||
if m.mode == modeCards && m.state == stateList {
|
if m.mode == modeCards && m.state == stateList {
|
||||||
m.cards.setIntent(m.cards.intent.next())
|
m.cards.setIntent(m.cards.intent.next())
|
||||||
if m.hasSearch() {
|
if m.hasSearch() {
|
||||||
@@ -428,12 +487,14 @@ func (m model) updateKeys(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
|||||||
}
|
}
|
||||||
return m, nil
|
return m, nil
|
||||||
|
|
||||||
|
case "tab":
|
||||||
|
cmd := m.setFocus(focusCapture)
|
||||||
|
return m, cmd
|
||||||
|
|
||||||
case "a":
|
case "a":
|
||||||
if m.state == stateList {
|
if m.state == stateList {
|
||||||
m.state = stateInput
|
cmd := m.setFocus(focusCapture)
|
||||||
m.input.focus()
|
return m, cmd
|
||||||
m.recalcSizes()
|
|
||||||
return m, m.input.ti.Focus()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case "esc":
|
case "esc":
|
||||||
@@ -488,6 +549,10 @@ func (m model) updateKeys(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
|||||||
m.status = ""
|
m.status = ""
|
||||||
return m, loadEntities(m.store, m.listParams())
|
return m, loadEntities(m.store, m.listParams())
|
||||||
}
|
}
|
||||||
|
if m.state == stateList {
|
||||||
|
cmd := m.setFocus(focusCapture)
|
||||||
|
return m, cmd
|
||||||
|
}
|
||||||
return m, nil
|
return m, nil
|
||||||
|
|
||||||
case "d":
|
case "d":
|
||||||
@@ -630,37 +695,6 @@ func (m model) updateKeys(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
|||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m model) updateInput(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
|
||||||
switch msg.String() {
|
|
||||||
case "esc":
|
|
||||||
m.state = stateList
|
|
||||||
m.input.reset()
|
|
||||||
m.recalcSizes()
|
|
||||||
return m, nil
|
|
||||||
case "enter":
|
|
||||||
result := m.input.submit()
|
|
||||||
if result == nil {
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
if result.query {
|
|
||||||
m.searchQuery = result.body
|
|
||||||
m.searchTags = result.tags
|
|
||||||
m.state = stateList
|
|
||||||
m.input.reset()
|
|
||||||
m.recalcSizes()
|
|
||||||
m.applySearch()
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
if result.entity != nil {
|
|
||||||
return m, createEntity(m.store, result.entity)
|
|
||||||
}
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
m.input = m.input.updateKey(msg)
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m model) updateTagFilter(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
func (m model) updateTagFilter(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
||||||
switch msg.String() {
|
switch msg.String() {
|
||||||
case "esc", "q":
|
case "esc", "q":
|
||||||
@@ -729,7 +763,7 @@ func (m model) View() string {
|
|||||||
|
|
||||||
var content string
|
var content string
|
||||||
switch m.state {
|
switch m.state {
|
||||||
case stateList, stateInput, stateConfirm:
|
case stateList, stateConfirm:
|
||||||
listContent := m.listContent()
|
listContent := m.listContent()
|
||||||
if m.splitDetail {
|
if m.splitDetail {
|
||||||
lw, rw := m.splitWidths()
|
lw, rw := m.splitWidths()
|
||||||
@@ -752,11 +786,12 @@ func (m model) View() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
header := m.headerView()
|
header := m.headerView()
|
||||||
footer := m.footerView()
|
captureBar := m.input.viewBar(m.width, m.focus == focusCapture)
|
||||||
|
statusLine := m.statusLine()
|
||||||
|
|
||||||
content = lipgloss.NewStyle().Width(m.width).Height(m.contentHeight()).Render(content)
|
content = lipgloss.NewStyle().Width(m.width).Height(m.contentHeight()).Render(content)
|
||||||
|
|
||||||
return header + "\n" + content + "\n" + footer
|
return header + "\n" + content + "\n" + captureBar + "\n" + statusLine
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m model) listContent() string {
|
func (m model) listContent() string {
|
||||||
@@ -806,11 +841,7 @@ func (m model) headerView() string {
|
|||||||
return header
|
return header
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m model) footerView() string {
|
func (m model) statusLine() string {
|
||||||
if m.state == stateInput {
|
|
||||||
return m.input.view(m.width)
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.state == stateConfirm {
|
if m.state == stateConfirm {
|
||||||
return renderConfirm(m.confirmID)
|
return renderConfirm(m.confirmID)
|
||||||
}
|
}
|
||||||
@@ -823,14 +854,7 @@ func (m model) footerView() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m model) contentHeight() int {
|
func (m model) contentHeight() int {
|
||||||
return m.height - 3 - m.drawerHeight()
|
return m.height - 4
|
||||||
}
|
|
||||||
|
|
||||||
func (m model) drawerHeight() int {
|
|
||||||
if m.state == stateInput {
|
|
||||||
return drawerLines()
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *model) recalcSizes() {
|
func (m *model) recalcSizes() {
|
||||||
|
|||||||
+15
-12
@@ -30,12 +30,10 @@ func renderTab(label, key string, active bool) string {
|
|||||||
func renderStatusBar(m model, width int) string {
|
func renderStatusBar(m model, width int) string {
|
||||||
var leftParts []string
|
var leftParts []string
|
||||||
|
|
||||||
if m.state == stateList {
|
|
||||||
leftParts = append(leftParts, renderTab("capture", "a", false))
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.status != "" {
|
if m.status != "" {
|
||||||
leftParts = append(leftParts, statusStyle.Render(m.status))
|
leftParts = append(leftParts, statusStyle.Render(m.status))
|
||||||
|
} else if preview := m.input.previewText(); m.focus == focusCapture && preview != "" {
|
||||||
|
leftParts = append(leftParts, drawerPreviewStyle.Render(preview))
|
||||||
} else {
|
} else {
|
||||||
leftParts = append(leftParts, statusStyle.Render(countText(m)))
|
leftParts = append(leftParts, statusStyle.Render(countText(m)))
|
||||||
}
|
}
|
||||||
@@ -76,8 +74,6 @@ func contextHints(m model) []hint {
|
|||||||
default:
|
default:
|
||||||
return []hint{{"p", "promote"}, {"D", "demote"}, {"c", "copy"}, {"e", "edit"}, {"r", "run"}, {"f", "fill"}, {"!", "pin"}, {"esc", "back"}}
|
return []hint{{"p", "promote"}, {"D", "demote"}, {"c", "copy"}, {"e", "edit"}, {"r", "run"}, {"f", "fill"}, {"!", "pin"}, {"esc", "back"}}
|
||||||
}
|
}
|
||||||
case stateInput:
|
|
||||||
return nil
|
|
||||||
case stateTagFilter:
|
case stateTagFilter:
|
||||||
return []hint{{"j/k", "nav"}, {"enter", "select"}, {"esc", "cancel"}}
|
return []hint{{"j/k", "nav"}, {"enter", "select"}, {"esc", "cancel"}}
|
||||||
case stateConfirm:
|
case stateConfirm:
|
||||||
@@ -86,16 +82,23 @@ func contextHints(m model) []hint {
|
|||||||
return []hint{{"j/k", "nav"}, {"enter", "select"}, {"esc", "cancel"}}
|
return []hint{{"j/k", "nav"}, {"enter", "select"}, {"esc", "cancel"}}
|
||||||
case stateAbsorb:
|
case stateAbsorb:
|
||||||
return []hint{{"j/k", "nav"}, {"enter", "absorb"}, {"esc", "cancel"}}
|
return []hint{{"j/k", "nav"}, {"enter", "absorb"}, {"esc", "cancel"}}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch m.focus {
|
||||||
|
case focusCapture:
|
||||||
|
return []hint{{"enter", "submit"}, {"esc", "browse"}, {"?…", "search"}, {"-", "todo"}, {"@", "event"}}
|
||||||
|
case focusDetail:
|
||||||
|
if m.splitDetail {
|
||||||
|
return []hint{{"h", "list"}, {"c", "copy"}, {"e", "edit"}, {"p", "promote"}, {"!", "pin"}, {"tab", "capture"}}
|
||||||
|
}
|
||||||
|
return []hint{{"c", "copy"}, {"e", "edit"}, {"p", "promote"}, {"!", "pin"}, {"esc", "back"}}
|
||||||
default:
|
default:
|
||||||
if m.splitDetail {
|
if m.splitDetail {
|
||||||
if m.focus == focusDetail {
|
return []hint{{"l", "detail"}, {"d", "del"}, {"#", "filter"}, {"tab", "capture"}, {"?", "help"}}
|
||||||
return []hint{{"h", "list"}, {"c", "copy"}, {"e", "edit"}, {"p", "promote"}, {"D", "demote"}, {"!", "pin"}, {"esc", "back"}}
|
|
||||||
}
|
|
||||||
return []hint{{"l", "detail"}, {"d", "del"}, {"#", "filter"}, {"esc", "close"}, {"?", "help"}, {"q", "quit"}}
|
|
||||||
}
|
}
|
||||||
if m.mode == modeCards {
|
if m.mode == modeCards {
|
||||||
return []hint{{"s", "sort"}, {"tab", "intent"}, {"?", "help"}, {"q", "quit"}}
|
return []hint{{"s", "sort"}, {"i", "intent"}, {"tab", "capture"}, {"?", "help"}}
|
||||||
}
|
}
|
||||||
return []hint{{"?", "search"}, {"m", "absorb"}, {"d", "del"}, {"#", "filter"}, {"?", "help"}, {"q", "quit"}}
|
return []hint{{"m", "absorb"}, {"d", "del"}, {"#", "filter"}, {"tab", "capture"}, {"?", "help"}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user