Files
lxc-streamutils/apps/overlay/src/effectQueue.ts
T
2026-08-19 12:30:30 -07:00

43 lines
1.4 KiB
TypeScript

import { useCallback, useState } from 'react'
type QueueItem = { id: string }
type EffectQueueState<T extends QueueItem> = {
active?: T
pending: T[]
}
export function enqueueEffect<T extends QueueItem>(
state: EffectQueueState<T>,
effect: T,
capacity: number,
): EffectQueueState<T> {
if (state.active?.id === effect.id || state.pending.some(item => item.id === effect.id)) {
return state
}
if (!state.active) return { active: effect, pending: state.pending }
const boundedCapacity = Number.isFinite(capacity) ? Math.max(1, Math.floor(capacity)) : 1
if (state.pending.length >= boundedCapacity) return state
return { ...state, pending: [...state.pending, effect] }
}
export function completeEffect<T extends QueueItem>(
state: EffectQueueState<T>,
activeId: string,
): EffectQueueState<T> {
if (state.active?.id !== activeId) return state
const [active, ...pending] = state.pending
return { active, pending }
}
export function useEffectQueue<T extends QueueItem>() {
const [state, setState] = useState<EffectQueueState<T>>({ pending: [] })
const enqueue = useCallback((effect: T, capacity: number) => {
setState(current => enqueueEffect(current, effect, capacity))
}, [])
const complete = useCallback((activeId: string) => {
setState(current => completeEffect(current, activeId))
}, [])
return { active: state.active, pendingCount: state.pending.length, enqueue, complete }
}