feat: the right pane describes what's selected in the pane you're in (#9)
The right pane kept showing the selected secret when you moved to Vaults or Sources. Now it follows focus: | focus | right pane | |---|---| | Sources | the account (group row), or the subscription / workspace / repo: name, note, ID / profile / path, host or remote, account, web page, vault count | | Vaults | the vault / scope / file: name, note, URI / backend / format, source, web page, counts of loaded secrets, keys, certificates | | Secrets | the secret, as before | | the right pane itself | what it described when you went in; `shift+tab` goes back there | All but the secret use the `Fields` pane (#7), so `j`/`k`, `/` and `y` work on them; `Detail` loses the error message it got in #4, which is now a red "problem" row in `Fields`. A value revealed from a left pane stays in view until hidden, so `space` from any pane still shows it. `tab` from a subscription goes to Vaults as before; only an account row skips to its details. This also changes the startup view: focus starts in Sources, so the right pane describes the first subscription instead of the first secret (golden output updated). Tests that read the secret pane focus Secrets first; a new test walks secret → vault → subscription → into the pane → back, and reveals from Sources. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Karl-Einar Bergstrøm <karl-einarb@outlook.com> Reviewed-on: #9
This commit was merged in pull request #9.
This commit is contained in:
1 parent
c8abc1dc95
commit
1c8d69d957
9 files changed
+232
-67
No files matched your search
@@ -46,7 +46,6 @@ type Detail struct {
|
||||
|
||||
versions []provider.Object // newest first; nil while unknown
|
||||
note string // the user's note on what's shown
|
||||
message string // shown instead of the hint when nothing is selected: an error
|
||||
|
||||
offset int
|
||||
w, h int
|
||||
@@ -72,10 +71,6 @@ func (d *Detail) Clear() {
|
||||
*d = Detail{Now: d.Now, Icons: d.Icons, RevealKey: d.RevealKey, VersionsKey: d.VersionsKey, CopyKey: d.CopyKey, w: d.w, h: d.h} // drops the note too
|
||||
}
|
||||
|
||||
// SetMessage sets what's shown instead of the hint when nothing is
|
||||
// selected, such as why an account has nothing to show; "" for the hint.
|
||||
func (d *Detail) SetMessage(s string) { d.message = s }
|
||||
|
||||
// SetDescribing marks extra metadata as being fetched.
|
||||
func (d *Detail) SetDescribing() { d.describing, d.describeErr = true, nil }
|
||||
|
||||
@@ -191,12 +186,6 @@ func (d Detail) lines(st styles.Styles) []string {
|
||||
muted := st.Muted.Render
|
||||
|
||||
if d.container == nil {
|
||||
if d.message != "" {
|
||||
for _, l := range strings.Split(ansi.Hardwrap(d.message, max(1, inner-2), true), "\n") {
|
||||
out = append(out, " "+st.Error.Render(l))
|
||||
}
|
||||
return out
|
||||
}
|
||||
return []string{muted(" Select a vault or scope to browse its secrets.")}
|
||||
}
|
||||
c := *d.container
|
||||
|
||||
+18
-12
@@ -15,13 +15,14 @@ import (
|
||||
// have Detail, for revealing and versions.
|
||||
type Fields struct {
|
||||
List[Field]
|
||||
shown bool
|
||||
}
|
||||
|
||||
// Field is a row: a value under a label. Info rows (loading, errors)
|
||||
// can't be copied.
|
||||
// can't be copied; Err ones are errors.
|
||||
type Field struct {
|
||||
Label, Value string
|
||||
Info bool
|
||||
Info, Err bool
|
||||
}
|
||||
|
||||
func NewFields() Fields {
|
||||
@@ -32,30 +33,35 @@ func NewFields() Fields {
|
||||
FilterExtra: func(f Field) string { return f.Label },
|
||||
Render: func(st styles.Styles, f Field, width int) string {
|
||||
value := f.Value
|
||||
if f.Info {
|
||||
switch {
|
||||
case f.Err:
|
||||
value = st.Error.Render(value)
|
||||
case f.Info:
|
||||
value = st.Muted.Render(value)
|
||||
}
|
||||
return ansi.Truncate(st.Label.Render(fmt.Sprintf("%-10s", f.Label))+" "+value, width, "…")
|
||||
},
|
||||
})
|
||||
l.Empty = "nothing to show"
|
||||
return Fields{l}
|
||||
return Fields{List: l}
|
||||
}
|
||||
|
||||
// Set shows fields under title. Another title (another account or vault)
|
||||
// starts over, without a filter.
|
||||
func (s *Fields) Set(title string, fields []Field) {
|
||||
// Show shows fields under title, instead of the secret pane. Another
|
||||
// title (another account or vault) starts over, without a filter.
|
||||
func (s *Fields) Show(title string, fields []Field) {
|
||||
if title != s.Title {
|
||||
s.Reset()
|
||||
s.Title = title
|
||||
}
|
||||
if len(fields) > 0 || len(s.Items()) > 0 {
|
||||
s.SetItems(fields)
|
||||
}
|
||||
s.shown = true
|
||||
s.SetItems(fields)
|
||||
}
|
||||
|
||||
// Shown reports whether there's anything to show.
|
||||
func (s Fields) Shown() bool { return len(s.Items()) > 0 }
|
||||
// Hide gives the fourth pane back to the secret pane.
|
||||
func (s *Fields) Hide() { s.shown = false }
|
||||
|
||||
// Shown reports whether the fourth pane shows Fields.
|
||||
func (s Fields) Shown() bool { return s.shown }
|
||||
|
||||
// Selected is the field under the cursor, unless it's an info row.
|
||||
func (s Fields) Selected() (Field, bool) {
|
||||
|
||||
Reference in new issue
Block a user