fix(daemon): wake headless bar preview subscribers
- commit
- aecc277857f88507fcb7ce8124cc8e3bbac95cfa
- author
- brice · · 2026-07-12 07:24 UTC
- parent
- e3435a7
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
2 files · +16 -3
M internal/usecase/daemon/bar_refresh.go +4 -3
| @@ -309,7 +309,8 @@ func (d *Daemon) pokeSessionRender(sess *session) { | |||
| 309 | 309 | sess.mu.Lock() | |
| 310 | 310 | ac := sess.client | |
| 311 | 311 | sess.mu.Unlock() | |
| 312 | - | if ac != nil { | |
| 313 | - | d.invalidateRender(sess, ac, false, "bar_refresh.go") | |
| 314 | - | } | |
| 312 | + | // A headless session can still supply a picker preview to an attachment | |
| 313 | + | // owned by another session. Its coordinator fans this wake out to those | |
| 314 | + | // preview subscribers even though no primary attachment is bound. | |
| 315 | + | d.invalidateRender(sess, ac, false, "bar_refresh.go") | |
| 315 | 316 | } | |
| @@ -309,7 +309,8 @@ func (d *Daemon) pokeSessionRender(sess *session) { | |||||
| 309 | sess.mu.Lock() | 309 | sess.mu.Lock() | ||
| 310 | ac := sess.client | 310 | ac := sess.client | ||
| 311 | sess.mu.Unlock() | 311 | sess.mu.Unlock() | ||
| 312 | - | if ac != nil { | 312 | + | // A headless session can still supply a picker preview to an attachment |
| 313 | - | d.invalidateRender(sess, ac, false, "bar_refresh.go") | 313 | + | // owned by another session. Its coordinator fans this wake out to those |
| 314 | - | } | 314 | + | // preview subscribers even though no primary attachment is bound. |
| 315 | + | d.invalidateRender(sess, ac, false, "bar_refresh.go") | |||
| 315 | } | 316 | } | ||
M internal/usecase/daemon/bar_refresh_test.go +12 -0
| @@ -277,6 +277,18 @@ func TestBarScriptRunIgnoresStaleConfigVersion(t *testing.T) { | |||
| 277 | 277 | require.Empty(t, state.bottomRight) | |
| 278 | 278 | } | |
| 279 | 279 | ||
| 280 | + | func TestPokeSessionRenderWakesHeadlessPreviewCoordinator(t *testing.T) { | |
| 281 | + | d := newBarRefreshTestDaemon(nil, time.Second) | |
| 282 | + | sess := newBarRefreshTestSession() | |
| 283 | + | var invalidations int | |
| 284 | + | rc := newRenderCoordinator(renderCoordinatorOptions{onInvalidate: func(renderInvalidation) { invalidations++ }}) | |
| 285 | + | sess.installRenderCoordinator(rc) | |
| 286 | + | ||
| 287 | + | d.pokeSessionRender(sess) | |
| 288 | + | ||
| 289 | + | require.Equal(t, 1, invalidations) | |
| 290 | + | } | |
| 291 | + | ||
| 280 | 292 | func TestBarScriptRefreshIsPerSession(t *testing.T) { | |
| 281 | 293 | r := &fakeBarRunner{outs: []string{"top-a", "bottom-a", "top-b", "bottom-b"}} | |
| 282 | 294 | d := newBarRefreshTestDaemon(r, time.Second) | |
| @@ -277,6 +277,18 @@ func TestBarScriptRunIgnoresStaleConfigVersion(t *testing.T) { | |||||
| 277 | require.Empty(t, state.bottomRight) | 277 | require.Empty(t, state.bottomRight) | ||
| 278 | } | 278 | } | ||
| 279 | 279 | ||||
| 280 | + | func TestPokeSessionRenderWakesHeadlessPreviewCoordinator(t *testing.T) { | |||
| 281 | + | d := newBarRefreshTestDaemon(nil, time.Second) | |||
| 282 | + | sess := newBarRefreshTestSession() | |||
| 283 | + | var invalidations int | |||
| 284 | + | rc := newRenderCoordinator(renderCoordinatorOptions{onInvalidate: func(renderInvalidation) { invalidations++ }}) | |||
| 285 | + | sess.installRenderCoordinator(rc) | |||
| 286 | + | ||||
| 287 | + | d.pokeSessionRender(sess) | |||
| 288 | + | ||||
| 289 | + | require.Equal(t, 1, invalidations) | |||
| 290 | + | } | |||
| 291 | + | ||||
| 280 | func TestBarScriptRefreshIsPerSession(t *testing.T) { | 292 | func TestBarScriptRefreshIsPerSession(t *testing.T) { | ||
| 281 | r := &fakeBarRunner{outs: []string{"top-a", "bottom-a", "top-b", "bottom-b"}} | 293 | r := &fakeBarRunner{outs: []string{"top-a", "bottom-a", "top-b", "bottom-b"}} | ||
| 282 | d := newBarRefreshTestDaemon(r, time.Second) | 294 | d := newBarRefreshTestDaemon(r, time.Second) | ||