- 在 package.json 和 package-lock.json 中新增 @sentry/react-native、react-native-device-info 和 react-native-purchases 依赖 - 更新统计页面,替换 CircularRing 组件为 FitnessRingsCard,增强健身数据展示 - 在布局文件中引入 ToastProvider,优化用户通知体验 - 新增 SuccessToast 组件,提供全局成功提示功能 - 更新健康数据获取逻辑,支持健身圆环数据的提取 - 优化多个组件的样式和交互,提升用户体验
107 lines
2.6 KiB
TypeScript
107 lines
2.6 KiB
TypeScript
import SuccessToast from '@/components/ui/SuccessToast';
|
||
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: '#DF42D0', // 主题色
|
||
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;
|
||
} |