feat: a list from the cache says how old it is while it reloads
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
9b0329e9da
commit
4d6db97d54
4 files changed
+60
-2
No files matched your search
@@ -456,6 +456,8 @@ func New(providers []provider.Provider, opts Options) Model {
|
||||
m.loadCacheFile()
|
||||
if len(m.sourceResults) > 0 {
|
||||
m.rebuildSources()
|
||||
m.sources.Loading = true // reloading what the file had
|
||||
m.sources.Age = m.cachedAge(m.oldestSources())
|
||||
}
|
||||
}
|
||||
if m.placeDir != "" && opts.Open == nil {
|
||||
@@ -1154,6 +1156,7 @@ func (m *Model) showContainers(src provider.Source, key string) tea.Cmd {
|
||||
return nil
|
||||
}
|
||||
m.containers.Refresh()
|
||||
m.containers.Age = m.cachedAge(e.at)
|
||||
return m.loadContainers(src, key)
|
||||
}
|
||||
|
||||
@@ -1170,6 +1173,7 @@ func (m *Model) showObjects(c provider.Container, key string) tea.Cmd {
|
||||
return nil
|
||||
}
|
||||
m.secrets.Refresh()
|
||||
m.secrets.Age = m.cachedAge(e.at)
|
||||
return m.loadObjects(c, m.objType, key)
|
||||
}
|
||||
|
||||
@@ -1299,6 +1303,26 @@ func (m *Model) detailStale() bool {
|
||||
return hasSecret || shown != m.containers.SelectedID()
|
||||
}
|
||||
|
||||
// cachedAge is how old a list loaded at at is, if it's older than
|
||||
// cacheTTL: the panes say it while it reloads.
|
||||
func (m Model) cachedAge(at time.Time) string {
|
||||
if d := m.now().Sub(at); d >= cacheTTL {
|
||||
return ago(d)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// oldestSources is when the oldest of the cached Sources lists loaded.
|
||||
func (m Model) oldestSources() time.Time {
|
||||
var oldest time.Time
|
||||
for _, at := range m.sourcesAt {
|
||||
if oldest.IsZero() || at.Before(oldest) {
|
||||
oldest = at
|
||||
}
|
||||
}
|
||||
return oldest
|
||||
}
|
||||
|
||||
func (m *Model) handleSources(msg sourcesMsg) tea.Cmd {
|
||||
if msg.gen != m.sourcesGen {
|
||||
return nil
|
||||
|
||||
@@ -39,6 +39,9 @@ func TestCacheFileShowsLastRunAtOnce(t *testing.T) {
|
||||
// Next run, with a backend too slow to answer during the test: the
|
||||
// lists show from the file, and the cursor is where it was.
|
||||
d2 := newDriverOpts(t, Options{CacheFile: file}, fake.Azure(time.Minute))
|
||||
if strings.Contains(d2.screen(), "cached") {
|
||||
t.Errorf("a fresh cache said its age:\n%s", d2.screen())
|
||||
}
|
||||
d2.keys("2")
|
||||
if _, v, _ := d2.selected(); v != vault {
|
||||
t.Errorf("vaults from the cache: selected %q, want %q\n%s", v, vault, d2.screen())
|
||||
@@ -49,6 +52,29 @@ func TestCacheFileShowsLastRunAtOnce(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Lists from an older cache say how old they are while they reload.
|
||||
func TestCacheFileSaysItsAge(t *testing.T) {
|
||||
t.Parallel()
|
||||
file := filepath.Join(t.TempDir(), "cache.json")
|
||||
d := newDriverOpts(t, Options{CacheFile: file}, fake.Azure(0))
|
||||
d.keys("3")
|
||||
at := time.Now().Add(-3 * time.Hour)
|
||||
for k, e := range d.m.cache.containers {
|
||||
d.m.cache.containers[k] = entry[[]provider.Container]{e.value, at}
|
||||
}
|
||||
for id := range d.m.sourcesAt {
|
||||
d.m.sourcesAt[id] = at
|
||||
}
|
||||
if err := d.m.Persist(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
d2 := newDriverOpts(t, Options{CacheFile: file}, fake.Azure(time.Minute))
|
||||
d2.keys("2")
|
||||
if n := strings.Count(d2.screen(), "cached 3h ago"); n != 2 {
|
||||
t.Errorf("Sources and Vaults should say they're from 3h ago (%d do):\n%s", n, d2.screen())
|
||||
}
|
||||
}
|
||||
|
||||
func TestCacheFileDropsOldAndSignedOut(t *testing.T) {
|
||||
t.Parallel()
|
||||
file := filepath.Join(t.TempDir(), "cache.json")
|
||||
|
||||
@@ -34,6 +34,9 @@ type List[T any] struct {
|
||||
Empty string // shown when loaded with no items
|
||||
Loading bool
|
||||
Err error
|
||||
// Age says how old the items are ("2h ago") while they reload, by
|
||||
// the counter.
|
||||
Age string
|
||||
|
||||
item Item[T]
|
||||
items []T
|
||||
@@ -88,6 +91,7 @@ func (l *List[T]) SetError(err error) {
|
||||
func (l *List[T]) Refresh() {
|
||||
l.Loading = true
|
||||
l.Err = nil
|
||||
l.Age = ""
|
||||
}
|
||||
|
||||
func (l *List[T]) SetLoading() {
|
||||
@@ -369,6 +373,9 @@ func (l List[T]) View(st styles.Styles, focused bool, spin string) string {
|
||||
if len(l.visible) > 0 {
|
||||
counter = fmt.Sprintf("%d of %d", l.cursor+1, len(l.visible))
|
||||
}
|
||||
if l.Loading && l.Age != "" && len(l.items) > 0 {
|
||||
counter = "cached " + l.Age + " · " + counter
|
||||
}
|
||||
return BoxCounted(st, title, "", counter, body, l.w, l.h, focused)
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user