mirror of
https://github.com/charmbracelet/glow
synced 2025-01-05 16:48:46 +00:00
Make stash note editing and deletion independent of main state
This commit is contained in:
parent
15494e99b4
commit
7fabcea06d
3 changed files with 46 additions and 35 deletions
72
ui/stash.go
72
ui/stash.go
|
@ -43,13 +43,11 @@ type filteredMarkdownMsg []*markdown
|
||||||
|
|
||||||
// MODEL
|
// MODEL
|
||||||
|
|
||||||
type stashState int
|
type stashViewState int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
stashStateReady stashState = iota
|
stashStateReady stashViewState = iota
|
||||||
stashStatePromptDelete
|
|
||||||
stashStateLoadingDocument
|
stashStateLoadingDocument
|
||||||
stashStateSettingNote
|
|
||||||
stashStateShowingError
|
stashStateShowingError
|
||||||
stashStateShowNews
|
stashStateShowNews
|
||||||
)
|
)
|
||||||
|
@ -62,10 +60,19 @@ const (
|
||||||
filterApplied // a filter is applied and user is not editing filter
|
filterApplied // a filter is applied and user is not editing filter
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type selectionState int
|
||||||
|
|
||||||
|
const (
|
||||||
|
selectionIdle = iota
|
||||||
|
selectionSettingNote
|
||||||
|
selectionPromptingDelete
|
||||||
|
)
|
||||||
|
|
||||||
type stashModel struct {
|
type stashModel struct {
|
||||||
general *general
|
general *general
|
||||||
state stashState
|
state stashViewState
|
||||||
filterState filterState
|
filterState filterState
|
||||||
|
selectionState selectionState
|
||||||
err error
|
err error
|
||||||
spinner spinner.Model
|
spinner spinner.Model
|
||||||
noteInput textinput.Model
|
noteInput textinput.Model
|
||||||
|
@ -153,7 +160,7 @@ func (m stashModel) isFiltering() bool {
|
||||||
func (m stashModel) shouldUpdateFilter() bool {
|
func (m stashModel) shouldUpdateFilter() bool {
|
||||||
// If we're in the middle of setting a note don't update the filter so that
|
// If we're in the middle of setting a note don't update the filter so that
|
||||||
// the focus won't jump around.
|
// the focus won't jump around.
|
||||||
return m.isFiltering() && m.state != stashStateSettingNote
|
return m.isFiltering() && m.selectionState != selectionSettingNote
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the total paginator pages according to the amount of markdowns for the
|
// Sets the total paginator pages according to the amount of markdowns for the
|
||||||
|
@ -518,14 +525,19 @@ func (m stashModel) update(msg tea.Msg) (stashModel, tea.Cmd) {
|
||||||
return m, tea.Batch(cmds...)
|
return m, tea.Batch(cmds...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch m.selectionState {
|
||||||
|
case selectionSettingNote:
|
||||||
|
cmds = append(cmds, m.handleNoteInput(msg))
|
||||||
|
return m, tea.Batch(cmds...)
|
||||||
|
case selectionPromptingDelete:
|
||||||
|
cmds = append(cmds, m.handleDeleteConfirmation(msg))
|
||||||
|
return m, tea.Batch(cmds...)
|
||||||
|
}
|
||||||
|
|
||||||
// Updates per the current state
|
// Updates per the current state
|
||||||
switch m.state {
|
switch m.state {
|
||||||
case stashStateReady, stashStateShowNews:
|
case stashStateReady, stashStateShowNews:
|
||||||
cmds = append(cmds, m.handleDocumentBrowsing(msg))
|
cmds = append(cmds, m.handleDocumentBrowsing(msg))
|
||||||
case stashStatePromptDelete:
|
|
||||||
cmds = append(cmds, m.handleDeleteConfirmation(msg))
|
|
||||||
case stashStateSettingNote:
|
|
||||||
cmds = append(cmds, m.handleNoteInput(msg))
|
|
||||||
case stashStateShowingError:
|
case stashStateShowingError:
|
||||||
// Any key exists the error view
|
// Any key exists the error view
|
||||||
if _, ok := msg.(tea.KeyMsg); ok {
|
if _, ok := msg.(tea.KeyMsg); ok {
|
||||||
|
@ -607,11 +619,11 @@ func (m *stashModel) handleDocumentBrowsing(msg tea.Msg) tea.Cmd {
|
||||||
|
|
||||||
md := m.selectedMarkdown()
|
md := m.selectedMarkdown()
|
||||||
isUserMarkdown := md.markdownType == StashedDocument || md.markdownType == ConvertedDocument
|
isUserMarkdown := md.markdownType == StashedDocument || md.markdownType == ConvertedDocument
|
||||||
isSettingNote := m.state == stashStateSettingNote
|
isSettingNote := m.selectionState == selectionSettingNote
|
||||||
isPromptingDelete := m.state == stashStatePromptDelete
|
isPromptingDelete := m.selectionState == selectionPromptingDelete
|
||||||
|
|
||||||
if isUserMarkdown && !isSettingNote && !isPromptingDelete {
|
if isUserMarkdown && !isSettingNote && !isPromptingDelete {
|
||||||
m.state = stashStateSettingNote
|
m.selectionState = selectionSettingNote
|
||||||
m.noteInput.SetValue(md.Note)
|
m.noteInput.SetValue(md.Note)
|
||||||
m.noteInput.CursorEnd()
|
m.noteInput.CursorEnd()
|
||||||
return textinput.Blink
|
return textinput.Blink
|
||||||
|
@ -672,16 +684,16 @@ func (m *stashModel) handleDocumentBrowsing(msg tea.Msg) tea.Cmd {
|
||||||
case "x":
|
case "x":
|
||||||
m.hideStatusMessage()
|
m.hideStatusMessage()
|
||||||
|
|
||||||
if pages == 0 {
|
validState := m.state == stashStateReady &&
|
||||||
|
m.selectionState == selectionIdle
|
||||||
|
|
||||||
|
if pages == 0 && !validState {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
t := m.selectedMarkdown().markdownType
|
t := m.selectedMarkdown().markdownType
|
||||||
isUserMarkdown := t == StashedDocument || t == ConvertedDocument
|
if t == StashedDocument || t == ConvertedDocument {
|
||||||
isValidState := m.state != stashStateSettingNote
|
m.selectionState = selectionPromptingDelete
|
||||||
|
|
||||||
if isUserMarkdown && isValidState {
|
|
||||||
m.state = stashStatePromptDelete
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show errors
|
// Show errors
|
||||||
|
@ -735,7 +747,7 @@ func (m *stashModel) handleDeleteConfirmation(msg tea.Msg) tea.Cmd {
|
||||||
|
|
||||||
// Confirm deletion
|
// Confirm deletion
|
||||||
case "y":
|
case "y":
|
||||||
if m.state != stashStatePromptDelete {
|
if m.selectionState != selectionPromptingDelete {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -762,14 +774,14 @@ func (m *stashModel) handleDeleteConfirmation(msg tea.Msg) tea.Cmd {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update pagination
|
m.selectionState = selectionIdle
|
||||||
m.setTotalPages()
|
m.setTotalPages()
|
||||||
|
|
||||||
return deleteStashedItem(m.general.cc, smd.ID)
|
return deleteStashedItem(m.general.cc, smd.ID)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Any other keys cancels deletion
|
// Any other keys cancels deletion
|
||||||
m.state = stashStateReady
|
m.selectionState = selectionIdle
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -847,7 +859,7 @@ func (m *stashModel) handleNoteInput(msg tea.Msg) tea.Cmd {
|
||||||
case "esc":
|
case "esc":
|
||||||
// Cancel note
|
// Cancel note
|
||||||
m.noteInput.Reset()
|
m.noteInput.Reset()
|
||||||
m.state = stashStateReady
|
m.selectionState = selectionIdle
|
||||||
case "enter":
|
case "enter":
|
||||||
// Set new note
|
// Set new note
|
||||||
md := m.selectedMarkdown()
|
md := m.selectedMarkdown()
|
||||||
|
@ -855,7 +867,7 @@ func (m *stashModel) handleNoteInput(msg tea.Msg) tea.Cmd {
|
||||||
cmd := saveDocumentNote(m.general.cc, md.ID, newNote)
|
cmd := saveDocumentNote(m.general.cc, md.ID, newNote)
|
||||||
md.Note = newNote
|
md.Note = newNote
|
||||||
m.noteInput.Reset()
|
m.noteInput.Reset()
|
||||||
m.state = stashStateReady
|
m.selectionState = selectionIdle
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -881,7 +893,7 @@ func (m stashModel) view() string {
|
||||||
return errorView(m.err, false)
|
return errorView(m.err, false)
|
||||||
case stashStateLoadingDocument:
|
case stashStateLoadingDocument:
|
||||||
s += " " + m.spinner.View() + " Loading document..."
|
s += " " + m.spinner.View() + " Loading document..."
|
||||||
case stashStateReady, stashStateSettingNote, stashStatePromptDelete, stashStateShowNews:
|
case stashStateReady, stashStateShowNews:
|
||||||
|
|
||||||
loadingIndicator := " "
|
loadingIndicator := " "
|
||||||
if !m.localOnly() && (!m.loadingDone() || m.loadingFromNetwork || m.spinner.Visible()) {
|
if !m.localOnly() && (!m.loadingDone() || m.loadingFromNetwork || m.spinner.Visible()) {
|
||||||
|
@ -900,10 +912,10 @@ func (m stashModel) view() string {
|
||||||
if m.showStatusMessage {
|
if m.showStatusMessage {
|
||||||
header = greenFg(m.statusMessage)
|
header = greenFg(m.statusMessage)
|
||||||
} else {
|
} else {
|
||||||
switch m.state {
|
switch m.selectionState {
|
||||||
case stashStatePromptDelete:
|
case selectionPromptingDelete:
|
||||||
header = redFg("Delete this item from your stash? ") + faintRedFg("(y/N)")
|
header = redFg("Delete this item from your stash? ") + faintRedFg("(y/N)")
|
||||||
case stashStateSettingNote:
|
case selectionSettingNote:
|
||||||
header = yellowFg("Set the memo for this item?")
|
header = yellowFg("Set the memo for this item?")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1068,9 +1080,9 @@ func stashHelpView(m stashModel) string {
|
||||||
isLocal = md != nil && md.markdownType == LocalDocument
|
isLocal = md != nil && md.markdownType == LocalDocument
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.state == stashStateSettingNote {
|
if m.selectionState == selectionSettingNote {
|
||||||
h = append(h, "enter: confirm", "esc: cancel")
|
h = append(h, "enter: confirm", "esc: cancel")
|
||||||
} else if m.state == stashStatePromptDelete {
|
} else if m.selectionState == selectionPromptingDelete {
|
||||||
h = append(h, "y: delete", "n: cancel")
|
h = append(h, "y: delete", "n: cancel")
|
||||||
} else if m.filterState == filtering && numDocs == 1 {
|
} else if m.filterState == filtering && numDocs == 1 {
|
||||||
h = append(h, "enter: open", "esc: cancel")
|
h = append(h, "enter: open", "esc: cancel")
|
||||||
|
|
|
@ -55,13 +55,13 @@ func stashItemView(b *strings.Builder, m stashModel, index int, md *markdown) {
|
||||||
if isSelected && !isFiltering || singleFilteredItem {
|
if isSelected && !isFiltering || singleFilteredItem {
|
||||||
// Selected item
|
// Selected item
|
||||||
|
|
||||||
switch m.state {
|
switch m.selectionState {
|
||||||
case stashStatePromptDelete:
|
case selectionPromptingDelete:
|
||||||
gutter = faintRedFg(verticalLine)
|
gutter = faintRedFg(verticalLine)
|
||||||
icon = faintRedFg(icon)
|
icon = faintRedFg(icon)
|
||||||
title = redFg(title)
|
title = redFg(title)
|
||||||
date = faintRedFg(date)
|
date = faintRedFg(date)
|
||||||
case stashStateSettingNote:
|
case selectionSettingNote:
|
||||||
gutter = dullYellowFg(verticalLine)
|
gutter = dullYellowFg(verticalLine)
|
||||||
icon = ""
|
icon = ""
|
||||||
title = m.noteInput.View()
|
title = m.noteInput.View()
|
||||||
|
|
3
ui/ui.go
3
ui/ui.go
|
@ -256,8 +256,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
|
||||||
// Send q/esc through in these cases
|
// Send q/esc through in these cases
|
||||||
switch m.stash.state {
|
switch m.stash.state {
|
||||||
case stashStateSettingNote, stashStatePromptDelete,
|
case stashStateShowingError, stashStateShowNews:
|
||||||
stashStateShowingError, stashStateShowNews:
|
|
||||||
|
|
||||||
// Q also quits glow when displaying only newsitems. Esc
|
// Q also quits glow when displaying only newsitems. Esc
|
||||||
// still passes through.
|
// still passes through.
|
||||||
|
|
Loading…
Reference in a new issue