feat: a chosen folder saves at once, and the prompt stays until it has
CI / Checks (pull_request) Successful in 40s
PR title / Conventional title (pull_request) Successful in 2s

Choosing where to save a share link's files saves them right away,
unless one would replace a file there, which still asks. The folder
prompt stays open until they're written: a folder that isn't there,
or a save that fails, is said under it in red, to fix the path. Its
footer says "enter save", and a file git doesn't ignore is named in
the status line after saving.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kebandClaude Opus 5.5 committed 2026-10-13 13:35:01 +02:00
1 parent 0757898d61
commit 25dbb38842
3 files changed
+98 -33

No files matched your search

+19 -4
View File
@@ -1,9 +1,11 @@
package app
import (
"cmp"
"fmt"
"slices"
"strings"
"unicode"
"unicode/utf8"
"charm.land/bubbles/v2/key"
@@ -54,9 +56,13 @@ type modal struct {
options []option
cursor int
// A text input instead of options; submit runs on enter.
input *textinput.Model
submit func(m *Model, text string) tea.Cmd
// A text input instead of options; submit runs on enter (named
// submitLabel in the footer; "open" if empty). err says why the last
// one wasn't taken, under the input.
input *textinput.Model
submit func(m *Model, text string) tea.Cmd
submitLabel string
err string
// A filter over the options: typing narrows them (all holds them
// all), so moving uses arrows or ctrl+j/k.
@@ -260,7 +266,10 @@ func (m Model) modalView() string {
foot := footer(move(km.MenuUp, km.MenuDown), hint(km.MenuSelect, "select"), hint(km.MenuClose, "dismiss"))
if p.input != nil {
body = append(body, " "+p.input.View())
foot = footer(hint(km.PopupSelect, "open"), hint(km.PopupClose, "cancel"))
if p.err != "" {
body = append(body, "", " "+m.st.Error.Render("✗ "+capitalize(p.err)))
}
foot = footer(hint(km.PopupSelect, cmp.Or(p.submitLabel, "open")), hint(km.PopupClose, "cancel"))
}
// Size from all options, not the ones shown or the cursor's, so the
@@ -407,3 +416,9 @@ func (m Model) overlay(base string) string {
lipgloss.NewLayer(box).X(x).Y(y).Z(1),
).Render()
}
// capitalize upper-cases the first letter of a message.
func capitalize(s string) string {
r, n := utf8.DecodeRuneInString(s)
return string(unicode.ToUpper(r)) + s[n:]
}