108 lines
2.7 KiB
TypeScript
108 lines
2.7 KiB
TypeScript
import SuccessToast from '@/components/ui/SuccessToast';
|
||
import { Colors } from '@/constants/Colors';
|
||
import { setToastRef } from '@/utils/toast.utils';
|
||
import React, { createContext, useContext, useEffect, useRef, useState } from 'react';
|
||
|
||
interface ToastConfig {
|
||
message: string;
|
||
duration?: number;
|
||
backgroundColor?: string;
|
||
textColor?: string;
|
||
icon?: string;
|
||
}
|
||
|
||
export interface ToastContextType {
|
||
showToast: (config: ToastConfig) => void;
|
||
showSuccess: (message: string, duration?: number) => void;
|
||
showError: (message: string, duration?: number) => void;
|
||
showWarning: (message: string, duration?: number) => void;
|
||
}
|
||
|
||
const ToastContext = createContext<ToastContextType | undefined>(undefined);
|
||
|
||
export function ToastProvider({ children }: { children: React.ReactNode }) {
|
||
const [visible, setVisible] = useState(false);
|
||
const [config, setConfig] = useState<ToastConfig>({ message: '' });
|
||
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||
|
||
const showToast = (toastConfig: ToastConfig) => {
|
||
// 如果已有Toast显示,先隐藏
|
||
if (visible) {
|
||
setVisible(false);
|
||
// 短暂延迟后显示新Toast
|
||
setTimeout(() => {
|
||
setConfig(toastConfig);
|
||
setVisible(true);
|
||
}, 100);
|
||
} else {
|
||
setConfig(toastConfig);
|
||
setVisible(true);
|
||
}
|
||
};
|
||
|
||
const showSuccess = (message: string, duration?: number) => {
|
||
showToast({
|
||
message,
|
||
duration,
|
||
backgroundColor: Colors.light.primary, // 主题色
|
||
icon: '✓',
|
||
});
|
||
};
|
||
|
||
const showError = (message: string, duration?: number) => {
|
||
showToast({
|
||
message,
|
||
duration,
|
||
backgroundColor: '#f44336', // 红色
|
||
icon: '✕',
|
||
});
|
||
};
|
||
|
||
const showWarning = (message: string, duration?: number) => {
|
||
showToast({
|
||
message,
|
||
duration,
|
||
backgroundColor: '#ff9800', // 橙色
|
||
icon: '⚠',
|
||
});
|
||
};
|
||
|
||
const handleHide = () => {
|
||
setVisible(false);
|
||
};
|
||
|
||
const value: ToastContextType = {
|
||
showToast,
|
||
showSuccess,
|
||
showError,
|
||
showWarning,
|
||
};
|
||
|
||
// 设置全局引用
|
||
useEffect(() => {
|
||
setToastRef(value);
|
||
}, [value]);
|
||
|
||
return (
|
||
<ToastContext.Provider value={value}>
|
||
{children}
|
||
<SuccessToast
|
||
visible={visible}
|
||
message={config.message}
|
||
duration={config.duration}
|
||
backgroundColor={config.backgroundColor}
|
||
textColor={config.textColor}
|
||
icon={config.icon}
|
||
onHide={handleHide}
|
||
/>
|
||
</ToastContext.Provider>
|
||
);
|
||
}
|
||
|
||
export function useToast(): ToastContextType {
|
||
const context = useContext(ToastContext);
|
||
if (context === undefined) {
|
||
throw new Error('useToast must be used within a ToastProvider');
|
||
}
|
||
return context;
|
||
} |