fix: cancel stale completion frames
ci / gitleaks (push) Successful in 6s
ci / docker (push) Successful in 3m29s

This commit is contained in:
2026-09-09 09:56:05 +08:00
parent 17005b0a50
commit c4e0683b6b
2 changed files with 12 additions and 6 deletions
+11 -6
View File
@@ -1,6 +1,7 @@
type CompletionId = string type CompletionId = string
type CompletionTimer = number type CompletionTimer = number
type CompletionFrame = number
export function createCompletionPulse( export function createCompletionPulse(
activate: (id: CompletionId) => void, activate: (id: CompletionId) => void,
@@ -8,19 +9,23 @@ export function createCompletionPulse(
duration = 420, duration = 420,
) { ) {
const timers = new Map<CompletionId, CompletionTimer>() const timers = new Map<CompletionId, CompletionTimer>()
const frames = new Map<CompletionId, CompletionFrame>()
return (id: CompletionId) => { return (id: CompletionId) => {
const previous = timers.get(id) const previousTimer = timers.get(id)
if (previous !== undefined) { if (previousTimer !== undefined) window.clearTimeout(previousTimer)
window.clearTimeout(previous) const previousFrame = frames.get(id)
deactivate(id) if (previousFrame !== undefined) window.cancelAnimationFrame(previousFrame)
} deactivate(id)
window.requestAnimationFrame(() => {
const frame = window.requestAnimationFrame(() => {
frames.delete(id)
activate(id) activate(id)
timers.set(id, window.setTimeout(() => { timers.set(id, window.setTimeout(() => {
deactivate(id) deactivate(id)
timers.delete(id) timers.delete(id)
}, duration)) }, duration))
}) })
frames.set(id, frame)
} }
} }
+1
View File
@@ -64,6 +64,7 @@ describe('completion feedback motion', () => {
const active = new Set<string>() const active = new Set<string>()
const pulse = createCompletionPulse((id) => active.add(id), (id) => active.delete(id), 420) const pulse = createCompletionPulse((id) => active.add(id), (id) => active.delete(id), 420)
pulse('item-1') pulse('item-1')
pulse('item-1')
vi.advanceTimersByTime(16) vi.advanceTimersByTime(16)
expect(active.has('item-1')).toBe(true) expect(active.has('item-1')).toBe(true)
vi.advanceTimersByTime(200) vi.advanceTimersByTime(200)