feat: share popups draw repos and files like everywhere else
repoLabel draws a repo, or a file in it, with pathLabel: the repo icon
and colour. The share popups use it for what's shared, where it's
from and where it's saved, and are titled for what's shared
("Share .env", "Share 2 env files"), the key picker too.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
3 files changed
+45
-22
No files matched your search
@@ -138,6 +138,12 @@ func (m Model) pathLabel(kind provider.Kind, path []string, account string) stri
|
||||
return label
|
||||
}
|
||||
|
||||
// repoLabel draws a repo, or a file in it, as everywhere else: the repo
|
||||
// icon and colour, "app / apps/api/.env".
|
||||
func (m Model) repoLabel(repo string, file ...string) string {
|
||||
return m.pathLabel(provider.KindRepo, append([]string{repo}, file...), "")
|
||||
}
|
||||
|
||||
// sourceMatches reports whether src is the subscription or workspace r
|
||||
// links to.
|
||||
func sourceMatches(r ref.Ref, src provider.Source) bool {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
@@ -109,14 +110,27 @@ func (m *Model) handleShareFiles(msg shareFilesMsg) tea.Cmd {
|
||||
return nil
|
||||
}
|
||||
|
||||
// shareTitle names the action: "Share .env", "Share 2 env files".
|
||||
func shareTitle(s sharing) string {
|
||||
if len(s.files) == 1 {
|
||||
return "Share " + path.Base(s.files[0].Path)
|
||||
}
|
||||
return "Share " + plural(len(s.files), "env file")
|
||||
}
|
||||
|
||||
// sharedFiles lists the files being shared, under what's happening.
|
||||
func (m *Model) sharedFiles(s sharing) []string {
|
||||
lines := []string{"Sharing " + plural(len(s.files), "env file") + " as an encrypted link:"}
|
||||
for _, f := range s.files {
|
||||
lines = append(lines, " "+m.repoLabel(s.repo.Name, f.Path))
|
||||
}
|
||||
return lines
|
||||
}
|
||||
|
||||
// confirmShare says what the link will hold before making it.
|
||||
func (m *Model) confirmShare(s sharing) {
|
||||
lines := []string{m.st.Muted.Render(plural(len(s.files), "env file") + " from " + s.repo.Name + ":")}
|
||||
for _, f := range s.files {
|
||||
lines = append(lines, " "+f.Path)
|
||||
}
|
||||
lines = append(lines, "", m.st.Muted.Render("encrypted with ")+m.refLabel(s.key))
|
||||
m.showMenu("Share as an encrypted link", lines, []option{
|
||||
lines := append(m.sharedFiles(s), "", m.st.Muted.Render("encrypted with ")+m.refLabel(s.key))
|
||||
m.showMenu(shareTitle(s), lines, []option{
|
||||
{key: "c", label: "Copy the link", run: func(m *Model) tea.Cmd { return m.seal(s) }},
|
||||
{key: "k", label: "Encrypt with another secret…", run: func(m *Model) tea.Cmd { return m.pickShareKey(s) }},
|
||||
})
|
||||
@@ -130,16 +144,10 @@ func (m *Model) pickShareKey(s sharing) tea.Cmd {
|
||||
m.confirmShare(s)
|
||||
return nil
|
||||
}
|
||||
m.search.pickTitle = "Encrypt with which secret?"
|
||||
what := s.files[0].Path
|
||||
if len(s.files) > 1 {
|
||||
what = plural(len(s.files), "env file")
|
||||
}
|
||||
m.search.pickLines = []string{
|
||||
"Sharing " + what + " from " + s.repo.Name + " as an encrypted link.",
|
||||
"Pick the secret to encrypt with: whoever can read it can open the link.",
|
||||
m.st.Muted.Render("Its value isn't shown or put in the link. share.key sets a default."),
|
||||
}
|
||||
m.search.pickTitle = shareTitle(s)
|
||||
m.search.pickLines = append(m.sharedFiles(s), "",
|
||||
"Pick the secret to encrypt them with: whoever can read it can open the link.",
|
||||
m.st.Muted.Render("Its value isn't shown or put in the link. share.key sets a default."))
|
||||
m.fillSearch(false)
|
||||
return tea.Batch(cmd, m.searchLoads())
|
||||
}
|
||||
@@ -213,10 +221,10 @@ func (m *Model) offerShare(r ref.Ref) tea.Cmd {
|
||||
}
|
||||
from := ""
|
||||
if s.Repo != "" {
|
||||
from = " from " + s.Repo
|
||||
from = m.st.Muted.Render(" from ") + m.repoLabel(s.Repo)
|
||||
}
|
||||
m.showMenu("Shared env files", []string{
|
||||
m.st.Muted.Render(plural(s.Files, "env file") + from),
|
||||
m.st.Muted.Render(plural(s.Files, "env file")) + from,
|
||||
m.st.Muted.Render("encrypted with ") + m.refLabel(s.Key),
|
||||
}, []option{
|
||||
{key: "o", label: "Decrypt them…", tip: "reads the secret, then asks before saving", run: func(m *Model) tea.Cmd { return m.openShare(s) }},
|
||||
@@ -302,10 +310,11 @@ func (m *Model) offerWrite(files []share.File, dir string) {
|
||||
var lines []string
|
||||
exist := 0
|
||||
for _, t := range targets {
|
||||
line := " " + t.Path + m.st.Muted.Render(" · new")
|
||||
file := " " + m.repoLabel(filepath.Base(dir), t.Path)
|
||||
line := file + m.st.Muted.Render(" · new")
|
||||
if t.Exists {
|
||||
exist++
|
||||
line = " " + t.Path + m.st.Muted.Render(" · replaces the one there")
|
||||
line = file + m.st.Muted.Render(" · replaces the one there")
|
||||
}
|
||||
if t.Exposed {
|
||||
line += m.st.Error.Render(" · not ignored by git")
|
||||
@@ -339,7 +348,7 @@ func (m *Model) offerWrite(files []share.File, dir string) {
|
||||
default:
|
||||
opts = append(opts,
|
||||
option{key: "w", label: fmt.Sprintf("Save all, replacing %d", exist), run: write(false)},
|
||||
option{key: "n", label: "Save only the new " + plural(len(targets)-exist, "file"), run: write(true)},
|
||||
option{key: "n", label: onlyNew(len(targets) - exist), run: write(true)},
|
||||
)
|
||||
}
|
||||
m.showMenu("Save the shared files", lines, opts)
|
||||
@@ -354,3 +363,11 @@ func expandHome(dir string) string {
|
||||
}
|
||||
return dir
|
||||
}
|
||||
|
||||
// onlyNew labels saving only the n files not there yet.
|
||||
func onlyNew(n int) string {
|
||||
if n == 1 {
|
||||
return "Save only the new one"
|
||||
}
|
||||
return fmt.Sprintf("Save only the %d new ones", n)
|
||||
}
|
||||
@@ -74,7 +74,7 @@ func shareFrom(t *testing.T, root string, paste bool) string {
|
||||
t.Errorf("not a secret: %s", o.label)
|
||||
}
|
||||
}
|
||||
if !strings.Contains(d.screen(), "Encrypt with which secret?") {
|
||||
if !strings.Contains(d.screen(), "Share 2 env files") && !strings.Contains(d.screen(), "Share .env") {
|
||||
t.Errorf("not titled as a picker:\n%s", d.screen())
|
||||
}
|
||||
d.keys("enter")
|
||||
|
||||
Reference in new issue
Block a user