From 8d65b60e692f92da0dbee44fed19578b5e88c856 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl-Einar=20Bergstr=C3=B8m?= Date: Tue, 13 Oct 2026 12:42:33 +0200 Subject: [PATCH] feat: the key picker has its own border in the share popup Co-Authored-By: Claude Opus 5.5 (1M context) --- internal/ui/app/searchview.go | 33 ++++++++++++++++++++++++++------- internal/ui/app/sharefiles.go | 12 +++++++----- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/internal/ui/app/searchview.go b/internal/ui/app/searchview.go index ff07ab0..d9d6bd6 100644 --- a/internal/ui/app/searchview.go +++ b/internal/ui/app/searchview.go @@ -56,9 +56,11 @@ type searchView struct { // pick, if set, makes Go to a picker of secrets, for title: it lists // secrets only, and enter gives the selected one's link to pick // instead of going there. - pick func(m *Model, r ref.Ref) tea.Cmd - pickTitle string - pickLines []string // what picking does, above the input + pick func(m *Model, r ref.Ref) tea.Cmd + pickTitle string // the popup's + pickLines []string // what picking is for, above the picker + pickHeading string // the picker's title, on its border + pickHelp []string // inside it, above the tabs // loaded are the scopes a search has loaded since the popup opened: // typing loads the scope once, so lists that fail aren't asked for @@ -658,7 +660,15 @@ func (m Model) searchViewBox() string { v := m.search focused := !m.termBlurred w := searchWidth(m.w) + popupW := w + if v.pick != nil { + w -= 4 // inside the picker's border, in the popup + } listH := max(5, min(m.h-10, 14)) + if v.pick != nil { + // What it's for, the help, the tabs and a border more. + listH = max(5, min(m.h-10-len(v.pickLines)-len(v.pickHelp)-5, 14)) + } srcW := 10 for _, o := range v.scopes { @@ -753,7 +763,7 @@ func (m Model) searchViewBox() string { ts := panes.TitleStyle(m.st, focused) var body []string if v.pick != nil { - for _, l := range v.pickLines { + for _, l := range v.pickHelp { body = append(body, " "+l) } body = append(body, "", " "+m.goToTabs(ts)) @@ -789,10 +799,19 @@ func (m Model) searchViewBox() string { // Tabs in the title, the current one underlined, like the panes; a // picker has its own title, and the tabs over the input. head := ts.Render(goToTitle+" ") + m.goToTabs(ts) - if v.pick != nil { - head = ts.Render(v.pickTitle) + if v.pick == nil { + return panes.Box(m.st, head, foot, body, w, len(body)+2, focused) } - return panes.Box(m.st, head, foot, body, w, len(body)+2, focused) + // A picker: in its own border, under what it's for. + var outer []string + for _, l := range v.pickLines { + outer = append(outer, " "+l) + } + outer = append(outer, "") + for _, l := range strings.Split(panes.Box(m.st, ts.Render(v.pickHeading), "", body, w, len(body)+2, focused), "\n") { + outer = append(outer, " "+l) + } + return panes.Box(m.st, ts.Render(v.pickTitle), foot, outer, popupW, len(outer)+2, focused) } // selectLabel names what enter does with the selected entry. diff --git a/internal/ui/app/sharefiles.go b/internal/ui/app/sharefiles.go index b538457..0d247bc 100644 --- a/internal/ui/app/sharefiles.go +++ b/internal/ui/app/sharefiles.go @@ -15,7 +15,6 @@ import ( "git.kebcloud.no/keb/lazysecrets/internal/provider" "git.kebcloud.no/keb/lazysecrets/internal/ref" "git.kebcloud.no/keb/lazysecrets/internal/share" - "git.kebcloud.no/keb/lazysecrets/internal/ui/panes" ) // Sharing env files as an encrypted lazysecrets://share link (package @@ -146,10 +145,13 @@ func (m *Model) pickShareKey(s sharing) tea.Cmd { return m.seal(s) // the picker showed what's shared } m.search.pickTitle = shareTitle(s) - m.search.pickLines = append(m.sharedFiles(s), "", - panes.TitleStyle(m.st, true).Render("Pick a secret to encrypt with"), - m.st.Muted.Render("The recipient needs read access to it to decrypt the files. Its value isn't"), - m.st.Muted.Render("shown or put in the link. share.key sets one for a repo, or for all.")) + m.search.pickLines = m.sharedFiles(s) + m.search.pickHeading = "Pick a secret to encrypt with" + m.search.pickHelp = []string{ + m.st.Muted.Render("The recipient needs read access to it to decrypt the files. Its value"), + m.st.Muted.Render("isn't shown or put in the link. share.key sets one for a repo, or for all."), + } + m.search.input.SetWidth(searchWidth(m.w) - 10) // inside the picker's border m.fillSearch(false) return tea.Batch(cmd, m.searchLoads()) }