| 87 | * A ToastQueue manages the order of toasts. |
| 88 | */ |
| 89 | export class ToastQueue<T> { |
| 90 | private queue: QueuedToast<T>[] = []; |
| 91 | private subscriptions: Set<() => void> = new Set(); |
| 92 | private maxVisibleToasts: number; |
| 93 | private wrapUpdate?: (fn: () => void, action: ToastAction) => void; |
| 94 | /** The currently visible toasts. */ |
| 95 | visibleToasts: QueuedToast<T>[] = []; |
| 96 | |
| 97 | constructor(options?: ToastStateProps) { |
| 98 | this.maxVisibleToasts = options?.maxVisibleToasts ?? Infinity; |
| 99 | this.wrapUpdate = options?.wrapUpdate; |
| 100 | } |
| 101 | |
| 102 | private runWithWrapUpdate(fn: () => void, action: ToastAction): void { |
| 103 | if (this.wrapUpdate) { |
| 104 | this.wrapUpdate(fn, action); |
| 105 | } else { |
| 106 | fn(); |
| 107 | } |
| 108 | } |
| 109 | |
| 110 | /** Subscribes to updates to the visible toasts. */ |
| 111 | subscribe(fn: () => void): () => void { |
| 112 | this.subscriptions.add(fn); |
| 113 | return () => this.subscriptions.delete(fn); |
| 114 | } |
| 115 | |
| 116 | /** Adds a new toast to the queue. */ |
| 117 | add(content: T, options: ToastOptions = {}): string { |
| 118 | let toastKey = '_' + Math.random().toString(36).slice(2); |
| 119 | let toast: QueuedToast<T> = { |
| 120 | ...options, |
| 121 | content, |
| 122 | key: toastKey, |
| 123 | timer: options.timeout ? new Timer(() => this.close(toastKey), options.timeout) : undefined |
| 124 | }; |
| 125 | |
| 126 | this.queue.unshift(toast); |
| 127 | |
| 128 | this.updateVisibleToasts('add'); |
| 129 | return toastKey; |
| 130 | } |
| 131 | |
| 132 | /** |
| 133 | * Closes a toast. |
| 134 | */ |
| 135 | close(key: string): void { |
| 136 | let index = this.queue.findIndex(t => t.key === key); |
| 137 | if (index >= 0) { |
| 138 | this.queue[index].onClose?.(); |
| 139 | this.queue.splice(index, 1); |
| 140 | } |
| 141 | |
| 142 | this.updateVisibleToasts('remove'); |
| 143 | } |
| 144 | |
| 145 | private updateVisibleToasts(action: ToastAction) { |
| 146 | this.visibleToasts = this.queue.slice(0, this.maxVisibleToasts); |
nothing calls this directly
no outgoing calls
no test coverage detected