fix(core): fire statusChange in MonitorRegistry.reset()

The newly-added `setStatusChangeCallback` subscriber misses `reset()`,
so a `/clear` or session reset leaves stale monitor rows visible in the
combined Background tasks dialog until an unrelated register/settle
event happens. Both BackgroundShellRegistry and BackgroundTaskRegistry
already fire statusChange on their reset paths — Monitor was the
outlier.

Fix: fire `statusChange()` (no arg) after `monitors.clear()`, with an
early return when the registry is already empty so we don't notify on
a no-op reset. Two new tests cover both branches.
This commit is contained in:
Shaojin Wen 2026-05-02 23:20:26 +08:00
parent 7999b85330
commit f26b700c31
2 changed files with 24 additions and 0 deletions

View file

@ -664,5 +664,22 @@ describe('MonitorRegistry', () => {
).not.toThrow();
expect(registry.get('a')).toBeDefined();
});
it('fires once on reset() so dialog snapshots clear stale rows', () => {
registry.register(createEntry({ monitorId: 'a' }));
registry.register(createEntry({ monitorId: 'b' }));
const cb = vi.fn();
registry.setStatusChangeCallback(cb);
registry.reset();
expect(cb).toHaveBeenCalledTimes(1);
expect(registry.getAll()).toEqual([]);
});
it('reset() on an empty registry does not fire statusChange', () => {
const cb = vi.fn();
registry.setStatusChangeCallback(cb);
registry.reset();
expect(cb).not.toHaveBeenCalled();
});
});
});

View file

@ -250,6 +250,7 @@ export class MonitorRegistry {
}
reset(): void {
if (this.monitors.size === 0) return;
for (const entry of this.monitors.values()) {
this.clearIdleTimer(entry);
if (entry.status === 'running') {
@ -257,6 +258,12 @@ export class MonitorRegistry {
}
}
this.monitors.clear();
// Notify subscribers that the registry's contents changed wholesale
// — without this, the dialog snapshot in `useBackgroundTaskView`
// would keep rendering the now-cleared rows until an unrelated
// register/settle event happens. Mirrors BackgroundShellRegistry /
// BackgroundTaskRegistry's reset paths.
this.fireStatusChange();
}
// --- Internal helpers ---