Merge remote-tracking branch 'origin/main' into feat/demo-repos
CI / Checks (pull_request) Successful in 22s
PR title / Conventional title (pull_request) Successful in 2s

# Conflicts:
#	README.md
This commit is contained in:
keb committed 2026-10-11 23:28:14 +02:00
commit 5cff381fc3
12 files changed
+72 -285

No files matched your search

+1 -1
View File
@@ -55,7 +55,7 @@ func (p *Provider) Details(ctx context.Context, c provider.Container) ([]provide
}
return out, nil
}
if last, ok := git("log", "-1", "--format=%h · %ar · %an: %s", "--", rel); ok && last != "" {
if last, ok := git("log", "-1", "--format=%h · %ar", "--", rel); ok && last != "" {
out = append(out, provider.Attr{Label: "last commit", Value: last})
}
return out, nil
+1 -1
View File
@@ -505,7 +505,7 @@ func TestFileDetails(t *testing.T) {
d := details("secrets/app.yaml")
if d["encryption"].Value != "sops · age" || d["keys"].Value != "age age1xxxx" || d["git"].Value != "tracked" ||
!strings.Contains(d["last commit"].Value, "t: files") || d["encrypted"].Value == "" {
!strings.HasSuffix(d["last commit"].Value, " ago") || strings.Contains(d["last commit"].Value, ":") || d["encrypted"].Value == "" {
t.Errorf("sops yaml: %+v", d)
}
if d := details("prod.env"); d["keys"].Value != "age age1xxxx" {
+4 -1
View File
@@ -489,7 +489,7 @@ func (m *Model) setVersions(items []provider.Object) {
}
func (m Model) Init() tea.Cmd {
cmds := []tea.Cmd{m.sourcesCmd(), m.spin.Tick, m.checkClipboard()}
cmds := []tea.Cmd{m.sourcesCmd(), m.spin.Tick, m.checkClipboard(), tea.RequestBackgroundColor}
if m.cachePath != "" || m.placeDir != "" {
cmds = append(cmds, tea.Tick(persistEvery, func(time.Time) tea.Msg { return persistTickMsg{} }))
}
@@ -514,6 +514,9 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmds []tea.Cmd
switch msg := msg.(type) {
case tea.BackgroundColorMsg:
m.st = m.st.OnBackground(msg.Color, msg.IsDark())
return m, nil
case tea.WindowSizeMsg:
m.w, m.h = msg.Width, msg.Height
+31 -2
View File
@@ -3,6 +3,8 @@
package styles
import (
"image/color"
"charm.land/lipgloss/v2"
"git.kebcloud.no/keb/lazysecrets/internal/provider"
@@ -32,6 +34,10 @@ type Styles struct {
KindAzure lipgloss.Style
KindDatabricks lipgloss.Style
KindRepo lipgloss.Style
// themed marks the selection colours as set by the theme, so
// OnBackground leaves them.
themed, themedBlurred bool
}
func Default() Styles {
@@ -43,9 +49,12 @@ func Default() Styles {
TitleBlurred: lipgloss.NewStyle(),
Footer: lipgloss.NewStyle().Faint(true),
// A background rather than reverse, so the row keeps its colours.
// A background rather than reverse, so the row keeps its colours;
// in every pane, so each shows what's selected in it. The focused
// pane's is bold too. Palette 8 until the terminal says what its
// background is (OnBackground).
Selected: lipgloss.NewStyle().Background(lipgloss.BrightBlack).Bold(true),
SelectedBlurred: lipgloss.NewStyle().Bold(true),
SelectedBlurred: lipgloss.NewStyle().Background(lipgloss.BrightBlack),
Muted: lipgloss.NewStyle().Faint(true),
Error: lipgloss.NewStyle().Foreground(lipgloss.Red),
Notice: lipgloss.NewStyle().Foreground(lipgloss.Green),
@@ -74,3 +83,23 @@ func (s Styles) Kind(k provider.Kind) lipgloss.Style {
}
return s.KindAzure
}
// OnBackground shades the selection colours from the terminal's
// background, a little lighter on a dark one and darker on a light one:
// a quiet band that keeps the row's colours readable, where palette 8 is
// often too bright. Colours the theme sets are kept.
func (s Styles) OnBackground(bg color.Color, dark bool) Styles {
shade := func(p float64) color.Color {
if dark {
return lipgloss.Lighten(bg, p)
}
return lipgloss.Darken(bg, p)
}
if !s.themed {
s.Selected = s.Selected.Background(shade(0.09))
}
if !s.themedBlurred {
s.SelectedBlurred = s.SelectedBlurred.Background(shade(0.05))
}
return s
}
+2
View File
@@ -70,8 +70,10 @@ func FromTheme(theme map[string][]string) (Styles, color.Color, error) {
st.BorderBlurred = v.fg(lipgloss.NewStyle())
case "selectedLineBgColor":
st.Selected = v.bg(lipgloss.NewStyle()).Bold(true)
st.themed = true
case "inactiveViewSelectedLineBgColor":
st.SelectedBlurred = v.bg(lipgloss.NewStyle()).Bold(true)
st.themedBlurred = true
case "defaultFgColor":
fg = v.color
case "optionsTextColor":
+30
View File
@@ -1,6 +1,7 @@
package styles
import (
"fmt"
"strings"
"testing"
@@ -62,3 +63,32 @@ func TestEmptyThemeIsDefault(t *testing.T) {
t.Errorf("empty theme: %v %v reverse=%v bg=%v", err, fg, st.Selected.GetReverse(), st.Selected.GetBackground())
}
}
func TestOnBackground(t *testing.T) {
hex := func(c any) string {
r, g, b, _ := c.(interface{ RGBA() (r, g, b, a uint32) }).RGBA()
return fmt.Sprintf("#%02x%02x%02x", r>>8, g>>8, b>>8)
}
st := Default().OnBackground(lipgloss.Color("#282c34"), true)
if got := hex(st.Selected.GetBackground()); got != "#3e424a" {
t.Errorf("dark: selected %s", got)
}
if got := hex(st.SelectedBlurred.GetBackground()); got != "#343840" {
t.Errorf("dark: blurred %s", got)
}
if got := hex(Default().OnBackground(lipgloss.Color("#ffffff"), false).Selected.GetBackground()); got != "#e8e8e8" {
t.Errorf("light: selected %s", got)
}
themed, _, err := FromTheme(map[string][]string{"selectedLineBgColor": {"#2d3f76"}})
if err != nil {
t.Fatal(err)
}
st = themed.OnBackground(lipgloss.Color("#282c34"), true)
if got := hex(st.Selected.GetBackground()); got != "#2d3f76" {
t.Errorf("themed: selected %s (want the theme's)", got)
}
if got := hex(st.SelectedBlurred.GetBackground()); got != "#343840" {
t.Errorf("themed: blurred %s (not themed: shaded)", got)
}
}