e6956aa001
- React frontend with route-level code splitting - Backend rebranded from Baihu to TaskPool - DB brand migration script and local compatibility
52 lines
1.2 KiB
TypeScript
52 lines
1.2 KiB
TypeScript
export type ToastType = 'success' | 'error' | 'info' | 'warning'
|
|
|
|
export interface ToastItem {
|
|
id: number
|
|
type: ToastType
|
|
message: string
|
|
duration: number
|
|
}
|
|
|
|
type Listener = (items: ToastItem[]) => void
|
|
|
|
let seq = 1
|
|
let items: ToastItem[] = []
|
|
const listeners = new Set<Listener>()
|
|
|
|
function emit() {
|
|
listeners.forEach((fn) => fn([...items]))
|
|
}
|
|
|
|
function push(type: ToastType, message: string, duration = 3000) {
|
|
const id = seq++
|
|
const item: ToastItem = { id, type, message, duration }
|
|
items = [...items, item]
|
|
emit()
|
|
if (duration > 0) {
|
|
window.setTimeout(() => {
|
|
dismiss(id)
|
|
}, duration)
|
|
}
|
|
return id
|
|
}
|
|
|
|
export function dismiss(id: number) {
|
|
items = items.filter((t) => t.id !== id)
|
|
emit()
|
|
}
|
|
|
|
export function subscribeToast(listener: Listener) {
|
|
listeners.add(listener)
|
|
listener([...items])
|
|
return () => {
|
|
listeners.delete(listener)
|
|
}
|
|
}
|
|
|
|
export const toast = {
|
|
success: (message: string, duration?: number) => push('success', message, duration),
|
|
error: (message: string, duration?: number) => push('error', message, duration ?? 4000),
|
|
info: (message: string, duration?: number) => push('info', message, duration),
|
|
warning: (message: string, duration?: number) => push('warning', message, duration),
|
|
}
|