feat: the logo on top of the status pane's rows
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
c129f22f5b
commit
66faafb9b9
5 files changed
+49
-2
No files matched your search
+2
-1
@@ -113,7 +113,8 @@ back. A value you reveal stays in view whichever pane you're in, until
|
||||
it's hidden.
|
||||
|
||||
On top, the status pane (`0`) shows the version, a newer release and how
|
||||
your accounts are doing. Focused, the right pane lists more: the version
|
||||
your accounts are doing. Focused, the right pane lists more under the
|
||||
logo (when there's room): the version
|
||||
and updates (`U`), each account (`L` on one that needs it signs in), the
|
||||
config, state and cache files (`e` opens one in your editor), and links
|
||||
to the docs, source, issues, releases and changelog (`o` opens one; on
|
||||
|
||||
@@ -1205,7 +1205,7 @@ func TestStatusPane(t *testing.T) {
|
||||
t.Fatalf("focus %v", d.m.focus)
|
||||
}
|
||||
scr := d.screen()
|
||||
for _, want := range []string{"version v0.1.0", "GPL-3.0-or-later", "Azure · 2 subscriptions", "Azure · admin · sign-in required",
|
||||
for _, want := range []string{logo[2], "version v0.1.0", "GPL-3.0-or-later", "Azure · 2 subscriptions", "Azure · admin · sign-in required",
|
||||
"/cfg/config.yaml", "/state/state.json", "lazysecrets/…/docs"} {
|
||||
if !strings.Contains(scr, want) {
|
||||
t.Errorf("missing %q:\n%s", want, scr)
|
||||
@@ -1231,6 +1231,11 @@ func TestStatusPane(t *testing.T) {
|
||||
if len(opened) != 1 || !strings.HasSuffix(opened[0], "/src/branch/main/docs") {
|
||||
t.Errorf("o opened %q", opened)
|
||||
}
|
||||
d.m.fields.SelectWhere(func(f panes.Field) bool { return f.Label == "version" })
|
||||
d.keys("o")
|
||||
if len(opened) != 2 || !strings.HasSuffix(opened[1], "/releases/tag/v0.1.0") {
|
||||
t.Errorf("o on the version opened %q", opened)
|
||||
}
|
||||
d.keys("shift+tab")
|
||||
if d.m.focus != paneStatus {
|
||||
t.Errorf("back to %v", d.m.focus)
|
||||
|
||||
@@ -49,6 +49,7 @@ func (m *Model) syncFields() tea.Cmd {
|
||||
m.fields.Hide()
|
||||
return nil
|
||||
}
|
||||
m.fields.Header = nil
|
||||
switch m.detailOf() {
|
||||
case paneSources:
|
||||
r, ok := m.sources.Selected()
|
||||
@@ -65,6 +66,7 @@ func (m *Model) syncFields() tea.Cmd {
|
||||
m.fields.Show("", nil)
|
||||
}
|
||||
case paneStatus:
|
||||
m.fields.Header = logo
|
||||
m.fields.Show("lazysecrets", m.statusFields())
|
||||
case paneContainers:
|
||||
if c, ok := m.containers.Selected(); ok {
|
||||
|
||||
@@ -16,6 +16,16 @@ import (
|
||||
// (0), the right pane has the rest: updates, each account, the files
|
||||
// lazysecrets uses, links, and the changelog.
|
||||
|
||||
// logo heads the status pane's rows.
|
||||
var logo = []string{
|
||||
` _ _`,
|
||||
`| | __ _ _____ _ ___ ___ ___ _ __ ___| |_ ___`,
|
||||
`| |/ _` + "`" + ` |_ / | | / __|/ _ \/ __| '__/ _ \ __/ __|`,
|
||||
`| | (_| |/ /| |_| \__ \ __/ (__| | | __/ |_\__ \`,
|
||||
`|_|\__,_/___|\__, |___/\___|\___|_| \___|\__|___/`,
|
||||
` |___/`,
|
||||
}
|
||||
|
||||
// statusH is the status pane's height: one line in a box.
|
||||
const statusH = 3
|
||||
|
||||
|
||||
@@ -34,6 +34,9 @@ type List[T any] struct {
|
||||
Empty string // shown when loaded with no items
|
||||
Loading bool
|
||||
Err error
|
||||
// Header lines (a logo) go above the items, when the pane has room
|
||||
// for them and there's no filter.
|
||||
Header []string
|
||||
|
||||
item Item[T]
|
||||
items []T
|
||||
@@ -159,9 +162,29 @@ func (l List[T]) rows() int {
|
||||
if l.filtering {
|
||||
r--
|
||||
}
|
||||
if l.headerShown() {
|
||||
r -= len(l.Header) + 1
|
||||
}
|
||||
return max(0, r)
|
||||
}
|
||||
|
||||
// headerMinRows is how many item rows the header leaves at least.
|
||||
const headerMinRows = 5
|
||||
|
||||
// headerShown reports whether Header fits: as wide as the pane allows,
|
||||
// leaving headerMinRows, a blank line under it, and no filter.
|
||||
func (l List[T]) headerShown() bool {
|
||||
if len(l.Header) == 0 || l.filtering || l.input.Value() != "" {
|
||||
return false
|
||||
}
|
||||
for _, line := range l.Header {
|
||||
if ansi.StringWidth(line) > l.w-3 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return l.h-2-len(l.Header)-1 >= headerMinRows
|
||||
}
|
||||
|
||||
// Filtering reports whether the filter input has focus.
|
||||
func (l List[T]) Filtering() bool { return l.filtering }
|
||||
|
||||
@@ -325,6 +348,12 @@ func (l List[T]) View(st styles.Styles, focused bool, spin string) string {
|
||||
if l.filtering {
|
||||
body = append(body, l.input.View())
|
||||
}
|
||||
if l.headerShown() {
|
||||
for _, line := range l.Header {
|
||||
body = append(body, st.Notice.Render(" "+line))
|
||||
}
|
||||
body = append(body, "")
|
||||
}
|
||||
|
||||
switch {
|
||||
case l.Loading && len(l.items) == 0:
|
||||
|
||||
Reference in new issue
Block a user