|
|
|
|
|
import { StyleSheet, ScrollView, TouchableOpacity, View, Text, useColorScheme as useSystemColorScheme } from 'react-native';
|
|
|
|
|
|
import { Stack } from 'expo-router';
|
|
|
|
|
|
import { useState, useEffect, useMemo } from 'react';
|
|
|
|
|
|
import { useTheme, useSettingsActions } from '@/stores';
|
|
|
|
|
|
import { useHaptics } from '@/hooks';
|
|
|
|
|
|
import Colors from '@/constants/Colors';
|
|
|
|
|
|
|
|
|
|
|
|
export default function ThemeTestScreen() {
|
|
|
|
|
|
const currentTheme = useTheme();
|
|
|
|
|
|
const { setTheme } = useSettingsActions();
|
|
|
|
|
|
const haptics = useHaptics();
|
|
|
|
|
|
const systemColorScheme = useSystemColorScheme();
|
|
|
|
|
|
|
|
|
|
|
|
// 强制重新渲染的状态
|
|
|
|
|
|
const [renderKey, setRenderKey] = useState(0);
|
|
|
|
|
|
|
|
|
|
|
|
// 直接计算实际应用的主题 - 不使用 useColorScheme hook
|
|
|
|
|
|
const actualTheme: 'light' | 'dark' = useMemo(() => {
|
|
|
|
|
|
return currentTheme === 'auto'
|
|
|
|
|
|
? (systemColorScheme === 'dark' ? 'dark' : 'light')
|
|
|
|
|
|
: currentTheme;
|
|
|
|
|
|
}, [currentTheme, systemColorScheme]);
|
|
|
|
|
|
|
|
|
|
|
|
// 使用 useMemo 确保颜色对象在主题改变时重新计算
|
|
|
|
|
|
const colors = useMemo(() => {
|
|
|
|
|
|
console.log('🎨 Recalculating colors for theme:', actualTheme);
|
|
|
|
|
|
return Colors[actualTheme] as Record<string, any>;
|
|
|
|
|
|
}, [actualTheme]);
|
|
|
|
|
|
|
|
|
|
|
|
// 监听主题变化
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
console.log('🎨 Theme changed:', { currentTheme, systemColorScheme, actualTheme, renderKey });
|
|
|
|
|
|
setRenderKey(prev => prev + 1);
|
|
|
|
|
|
}, [currentTheme, systemColorScheme, actualTheme]);
|
|
|
|
|
|
|
|
|
|
|
|
const handleThemeChange = (newTheme: 'light' | 'dark' | 'auto') => {
|
|
|
|
|
|
haptics.selection();
|
|
|
|
|
|
console.log('🎨 Changing theme to:', newTheme);
|
|
|
|
|
|
setTheme(newTheme);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<>
|
|
|
|
|
|
<Stack.Screen
|
|
|
|
|
|
options={{
|
|
|
|
|
|
title: '主题测试',
|
|
|
|
|
|
headerStyle: {
|
|
|
|
|
|
backgroundColor: colors.background,
|
|
|
|
|
|
},
|
|
|
|
|
|
headerTintColor: colors.text,
|
|
|
|
|
|
}}
|
|
|
|
|
|
/>
|
|
|
|
|
|
<ScrollView
|
|
|
|
|
|
style={[styles.container, { backgroundColor: colors.background }]}
|
|
|
|
|
|
>
|
|
|
|
|
|
{/* 主题信息 */}
|
|
|
|
|
|
<View style={[styles.section, { backgroundColor: colors.backgroundSecondary }]}>
|
|
|
|
|
|
<Text style={[styles.title, { color: colors.text }]}>
|
|
|
|
|
|
当前主题信息
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
<Text style={[styles.infoText, { color: colors.textSecondary }]}>
|
|
|
|
|
|
用户设置: {currentTheme}
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
<Text style={[styles.infoText, { color: colors.textSecondary }]}>
|
|
|
|
|
|
系统主题: {systemColorScheme || 'light'}
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
<Text style={[styles.infoText, { color: colors.textSecondary }]}>
|
|
|
|
|
|
实际应用: {actualTheme}
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
<Text style={[styles.infoText, { color: colors.textSecondary }]}>
|
|
|
|
|
|
渲染次数: {renderKey}
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
|
|
|
|
|
|
{/* 主题切换按钮 */}
|
|
|
|
|
|
<View style={[styles.section, { backgroundColor: colors.backgroundSecondary }]}>
|
|
|
|
|
|
<Text style={[styles.title, { color: colors.text }]}>
|
|
|
|
|
|
切换主题
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
<View style={styles.buttonRow}>
|
|
|
|
|
|
<TouchableOpacity
|
|
|
|
|
|
style={[
|
|
|
|
|
|
styles.themeButton,
|
|
|
|
|
|
{
|
|
|
|
|
|
backgroundColor: currentTheme === 'light' ? colors.primary : colors.backgroundTertiary,
|
|
|
|
|
|
borderColor: colors.border,
|
|
|
|
|
|
}
|
|
|
|
|
|
]}
|
|
|
|
|
|
onPress={() => handleThemeChange('light')}
|
|
|
|
|
|
>
|
|
|
|
|
|
<Text style={[
|
|
|
|
|
|
styles.buttonText,
|
|
|
|
|
|
{ color: currentTheme === 'light' ? '#fff' : colors.text }
|
|
|
|
|
|
]}>
|
|
|
|
|
|
☀️ 浅色
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
</TouchableOpacity>
|
|
|
|
|
|
|
|
|
|
|
|
<TouchableOpacity
|
|
|
|
|
|
style={[
|
|
|
|
|
|
styles.themeButton,
|
|
|
|
|
|
{
|
|
|
|
|
|
backgroundColor: currentTheme === 'dark' ? colors.primary : colors.backgroundTertiary,
|
|
|
|
|
|
borderColor: colors.border,
|
|
|
|
|
|
}
|
|
|
|
|
|
]}
|
|
|
|
|
|
onPress={() => handleThemeChange('dark')}
|
|
|
|
|
|
>
|
|
|
|
|
|
<Text style={[
|
|
|
|
|
|
styles.buttonText,
|
|
|
|
|
|
{ color: currentTheme === 'dark' ? '#fff' : colors.text }
|
|
|
|
|
|
]}>
|
|
|
|
|
|
🌙 深色
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
</TouchableOpacity>
|
|
|
|
|
|
|
|
|
|
|
|
<TouchableOpacity
|
|
|
|
|
|
style={[
|
|
|
|
|
|
styles.themeButton,
|
|
|
|
|
|
{
|
|
|
|
|
|
backgroundColor: currentTheme === 'auto' ? colors.primary : colors.backgroundTertiary,
|
|
|
|
|
|
borderColor: colors.border,
|
|
|
|
|
|
}
|
|
|
|
|
|
]}
|
|
|
|
|
|
onPress={() => handleThemeChange('auto')}
|
|
|
|
|
|
>
|
|
|
|
|
|
<Text style={[
|
|
|
|
|
|
styles.buttonText,
|
|
|
|
|
|
{ color: currentTheme === 'auto' ? '#fff' : colors.text }
|
|
|
|
|
|
]}>
|
|
|
|
|
|
🔄 自动
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
</TouchableOpacity>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
|
|
|
|
|
|
{/* 文本颜色展示 */}
|
|
|
|
|
|
<View style={[styles.section, { backgroundColor: colors.backgroundSecondary }]}>
|
|
|
|
|
|
<Text style={[styles.title, { color: colors.text }]}>
|
|
|
|
|
|
文本颜色
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
<Text style={[styles.colorText, { color: colors.text }]}>
|
|
|
|
|
|
Primary Text - {colors.text}
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
<Text style={[styles.colorText, { color: colors.textSecondary }]}>
|
|
|
|
|
|
Secondary Text - {colors.textSecondary}
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
<Text style={[styles.colorText, { color: colors.textTertiary }]}>
|
|
|
|
|
|
Tertiary Text - {colors.textTertiary}
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
|
|
|
|
|
|
{/* 背景颜色展示 */}
|
|
|
|
|
|
<View style={[styles.section, { backgroundColor: colors.backgroundSecondary }]}>
|
|
|
|
|
|
<Text style={[styles.title, { color: colors.text }]}>
|
|
|
|
|
|
背景颜色
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
<View style={[styles.colorBox, { backgroundColor: colors.background }]}>
|
|
|
|
|
|
<Text style={[styles.colorText, { color: colors.text }]}>
|
|
|
|
|
|
Primary Background - {colors.background}
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
<View style={[styles.colorBox, { backgroundColor: colors.backgroundSecondary, borderWidth: 1, borderColor: colors.border }]}>
|
|
|
|
|
|
<Text style={[styles.colorText, { color: colors.text }]}>
|
|
|
|
|
|
Secondary Background - {colors.backgroundSecondary}
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
<View style={[styles.colorBox, { backgroundColor: colors.backgroundTertiary }]}>
|
|
|
|
|
|
<Text style={[styles.colorText, { color: colors.text }]}>
|
|
|
|
|
|
Tertiary Background - {colors.backgroundTertiary}
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
|
|
|
|
|
|
{/* 主题颜色展示 */}
|
|
|
|
|
|
<View style={[styles.section, { backgroundColor: colors.backgroundSecondary }]}>
|
|
|
|
|
|
<Text style={[styles.title, { color: colors.text }]}>
|
|
|
|
|
|
主题颜色
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
<View style={styles.colorGrid}>
|
|
|
|
|
|
<View style={[styles.colorBox, { backgroundColor: colors.primary }]}>
|
|
|
|
|
|
<Text style={[styles.colorText, { color: '#fff' }]}>Primary - {colors.primary}</Text>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
<View style={[styles.colorBox, { backgroundColor: colors.secondary }]}>
|
|
|
|
|
|
<Text style={[styles.colorText, { color: '#fff' }]}>Secondary - {colors.secondary}</Text>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
<View style={[styles.colorBox, { backgroundColor: colors.success }]}>
|
|
|
|
|
|
<Text style={[styles.colorText, { color: '#fff' }]}>Success - {colors.success}</Text>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
<View style={[styles.colorBox, { backgroundColor: colors.warning }]}>
|
|
|
|
|
|
<Text style={[styles.colorText, { color: '#fff' }]}>Warning - {colors.warning}</Text>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
<View style={[styles.colorBox, { backgroundColor: colors.error }]}>
|
|
|
|
|
|
<Text style={[styles.colorText, { color: '#fff' }]}>Error - {colors.error}</Text>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
<View style={[styles.colorBox, { backgroundColor: colors.info }]}>
|
|
|
|
|
|
<Text style={[styles.colorText, { color: '#fff' }]}>Info - {colors.info}</Text>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
|
|
|
|
|
|
{/* UI 元素展示 */}
|
|
|
|
|
|
<View style={[styles.section, { backgroundColor: colors.backgroundSecondary }]}>
|
|
|
|
|
|
<Text style={[styles.title, { color: colors.text }]}>
|
|
|
|
|
|
UI 元素
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
<View style={[styles.card, { backgroundColor: colors.card, borderColor: colors.border }]}>
|
|
|
|
|
|
<Text style={[styles.cardText, { color: colors.text }]}>
|
|
|
|
|
|
这是一个卡片组件
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
<Text style={[styles.cardSubtext, { color: colors.textSecondary }]}>
|
|
|
|
|
|
卡片背景色: {colors.card}
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
|
|
|
|
|
|
<View style={[styles.input, { backgroundColor: colors.inputBackground, borderColor: colors.inputBorder }]}>
|
|
|
|
|
|
<Text style={[styles.inputText, { color: colors.textSecondary }]}>
|
|
|
|
|
|
输入框样式预览
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
|
|
|
|
|
|
<View style={[styles.separator, { backgroundColor: colors.separator }]} />
|
|
|
|
|
|
|
|
|
|
|
|
<TouchableOpacity style={[styles.button, { backgroundColor: colors.buttonPrimary }]}>
|
|
|
|
|
|
<Text style={[styles.buttonText, { color: '#fff' }]}>
|
|
|
|
|
|
按钮示例
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
</TouchableOpacity>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
</ScrollView>
|
|
|
|
|
|
</>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const styles = StyleSheet.create({
|
|
|
|
|
|
container: {
|
|
|
|
|
|
flex: 1,
|
|
|
|
|
|
},
|
|
|
|
|
|
section: {
|
|
|
|
|
|
margin: 16,
|
|
|
|
|
|
padding: 16,
|
|
|
|
|
|
borderRadius: 12,
|
|
|
|
|
|
},
|
|
|
|
|
|
title: {
|
|
|
|
|
|
fontSize: 20,
|
|
|
|
|
|
fontWeight: 'bold',
|
|
|
|
|
|
marginBottom: 16,
|
|
|
|
|
|
},
|
|
|
|
|
|
infoText: {
|
|
|
|
|
|
fontSize: 16,
|
|
|
|
|
|
marginBottom: 8,
|
|
|
|
|
|
},
|
|
|
|
|
|
buttonRow: {
|
|
|
|
|
|
flexDirection: 'row',
|
|
|
|
|
|
gap: 12,
|
|
|
|
|
|
},
|
|
|
|
|
|
themeButton: {
|
|
|
|
|
|
flex: 1,
|
|
|
|
|
|
paddingVertical: 12,
|
|
|
|
|
|
paddingHorizontal: 16,
|
|
|
|
|
|
borderRadius: 8,
|
|
|
|
|
|
borderWidth: 2,
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
},
|
|
|
|
|
|
buttonText: {
|
|
|
|
|
|
fontSize: 16,
|
|
|
|
|
|
fontWeight: '600',
|
|
|
|
|
|
},
|
|
|
|
|
|
colorText: {
|
|
|
|
|
|
fontSize: 14,
|
|
|
|
|
|
marginBottom: 8,
|
|
|
|
|
|
fontFamily: 'monospace',
|
|
|
|
|
|
},
|
|
|
|
|
|
colorBox: {
|
|
|
|
|
|
padding: 16,
|
|
|
|
|
|
borderRadius: 8,
|
|
|
|
|
|
marginBottom: 8,
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
},
|
|
|
|
|
|
colorGrid: {
|
|
|
|
|
|
gap: 8,
|
|
|
|
|
|
},
|
|
|
|
|
|
card: {
|
|
|
|
|
|
padding: 16,
|
|
|
|
|
|
borderRadius: 8,
|
|
|
|
|
|
borderWidth: 1,
|
|
|
|
|
|
marginBottom: 12,
|
|
|
|
|
|
},
|
|
|
|
|
|
cardText: {
|
|
|
|
|
|
fontSize: 16,
|
|
|
|
|
|
fontWeight: '600',
|
|
|
|
|
|
marginBottom: 4,
|
|
|
|
|
|
},
|
|
|
|
|
|
cardSubtext: {
|
|
|
|
|
|
fontSize: 12,
|
|
|
|
|
|
fontFamily: 'monospace',
|
|
|
|
|
|
},
|
|
|
|
|
|
input: {
|
|
|
|
|
|
padding: 12,
|
|
|
|
|
|
borderRadius: 8,
|
|
|
|
|
|
borderWidth: 1,
|
|
|
|
|
|
marginBottom: 12,
|
|
|
|
|
|
},
|
|
|
|
|
|
inputText: {
|
|
|
|
|
|
fontSize: 14,
|
|
|
|
|
|
},
|
|
|
|
|
|
separator: {
|
|
|
|
|
|
height: 1,
|
|
|
|
|
|
marginVertical: 12,
|
|
|
|
|
|
},
|
|
|
|
|
|
button: {
|
|
|
|
|
|
padding: 16,
|
|
|
|
|
|
borderRadius: 8,
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
|