feat: 更新依赖项并优化组件结构
- 在 package.json 和 package-lock.json 中新增 @sentry/react-native、react-native-device-info 和 react-native-purchases 依赖 - 更新统计页面,替换 CircularRing 组件为 FitnessRingsCard,增强健身数据展示 - 在布局文件中引入 ToastProvider,优化用户通知体验 - 新增 SuccessToast 组件,提供全局成功提示功能 - 更新健康数据获取逻辑,支持健身圆环数据的提取 - 优化多个组件的样式和交互,提升用户体验
This commit is contained in:
107
contexts/ToastContext.tsx
Normal file
107
contexts/ToastContext.tsx
Normal file
@@ -0,0 +1,107 @@
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user