mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-29 22:06:38 +08:00
63 lines
1.5 KiB
TypeScript
63 lines
1.5 KiB
TypeScript
'use client';
|
|
|
|
import {
|
|
createContext,
|
|
useCallback,
|
|
useContext,
|
|
useRef,
|
|
useState,
|
|
} from 'react';
|
|
|
|
interface BellRingContextType {
|
|
isRinging: boolean;
|
|
triggerRing: () => void;
|
|
}
|
|
|
|
const BellRingContext = createContext<BellRingContextType | undefined>(
|
|
undefined,
|
|
);
|
|
|
|
/**
|
|
* 铃铛响铃动画上下文提供者
|
|
* 用于在 toast 通知时触发顶栏铃铛的响铃动画
|
|
*/
|
|
export function BellRingProvider({ children }: { children: React.ReactNode }) {
|
|
const [isRinging, setIsRinging] = useState(false);
|
|
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
|
|
const triggerRing = useCallback(() => {
|
|
// 如果正在响铃,立即重新开始动画
|
|
if (timeoutRef.current) {
|
|
clearTimeout(timeoutRef.current);
|
|
}
|
|
setIsRinging(false);
|
|
requestAnimationFrame(() => {
|
|
requestAnimationFrame(() => {
|
|
setIsRinging(true);
|
|
timeoutRef.current = setTimeout(() => {
|
|
setIsRinging(false);
|
|
timeoutRef.current = null;
|
|
}, 600);
|
|
});
|
|
});
|
|
}, []);
|
|
|
|
return (
|
|
<BellRingContext.Provider value={{ isRinging, triggerRing }}>
|
|
{children}
|
|
</BellRingContext.Provider>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 使用铃铛响铃动画的 Hook
|
|
* @returns {{ isRinging: boolean, triggerRing: () => void }}
|
|
*/
|
|
export function useBellRing() {
|
|
const context = useContext(BellRingContext);
|
|
if (context === undefined) {
|
|
throw new Error('useBellRing must be used within a BellRingProvider');
|
|
}
|
|
return context;
|
|
}
|