diff --git a/src/screens/message/components/ChatScreen/ChatHeader.tsx b/src/screens/message/components/ChatScreen/ChatHeader.tsx index 29fe64a..0f2ca7a 100644 --- a/src/screens/message/components/ChatScreen/ChatHeader.tsx +++ b/src/screens/message/components/ChatScreen/ChatHeader.tsx @@ -1,6 +1,7 @@ /** * 聊天头部组件 * 支持响应式布局(宽屏下显示更多信息) + * 支持动态主题颜色 */ import React, { useMemo } from 'react'; @@ -8,7 +9,7 @@ import { View, TouchableOpacity, StyleSheet } from 'react-native'; import { MaterialCommunityIcons } from '@expo/vector-icons'; import { Avatar, Text } from '../../../../components/common'; import { useAppColors, spacing } from '../../../../theme'; -import { useChatScreenStyles } from './styles'; +import { useChatScreenStyles, useChatDynamicStyles } from './styles'; import { useBreakpointGTE } from '../../../../hooks/useResponsive'; import { ChatHeaderProps } from './types'; @@ -26,6 +27,7 @@ export const ChatHeader: React.FC = ({ }) => { const colors = useAppColors(); const baseStyles = useChatScreenStyles(); + const dynamicStyles = useChatDynamicStyles(); // 响应式布局 // 使用 768px 作为大屏幕和小屏幕的分界线 @@ -33,6 +35,9 @@ export const ChatHeader: React.FC = ({ // 优先使用 props 传入的 isWideScreen,否则使用 hook const isWideScreen = propIsWideScreen !== undefined ? propIsWideScreen : isWideScreenHook; + // 动态图标颜色 - 使用主题色 + const iconColor = dynamicStyles.textPrimaryColor || colors.text.primary; + // 合并样式 const styles = useMemo(() => { return StyleSheet.create({ @@ -74,7 +79,7 @@ export const ChatHeader: React.FC = ({ - + @@ -130,7 +135,7 @@ export const ChatHeader: React.FC = ({ onPress={onGroupInfoPress} activeOpacity={0.7} > - + ) : ( = ({ onPress={onMorePress} activeOpacity={0.7} > - + )} diff --git a/src/screens/message/components/ChatScreen/ChatInput.tsx b/src/screens/message/components/ChatScreen/ChatInput.tsx index 2fececd..608d605 100644 --- a/src/screens/message/components/ChatScreen/ChatInput.tsx +++ b/src/screens/message/components/ChatScreen/ChatInput.tsx @@ -1,6 +1,7 @@ /** * 聊天输入框组件 * 支持响应式布局(宽屏下居中显示) + * 支持动态主题颜色 */ import React, { useMemo } from 'react'; @@ -8,7 +9,7 @@ import { View, TouchableOpacity, TextInput, ActivityIndicator, ScrollView, Style import { MaterialCommunityIcons } from '@expo/vector-icons'; import { Text } from '../../../../components/common'; import { useAppColors } from '../../../../theme'; -import { useChatScreenStyles } from './styles'; +import { useChatScreenStyles, useChatDynamicStyles } from './styles'; import { useBreakpointGTE } from '../../../../hooks/useResponsive'; import { ChatInputProps, GroupMessage, SenderInfo } from './types'; import { extractTextFromSegments } from '../../../../types/dto'; @@ -41,11 +42,18 @@ export const ChatInput: React.FC { const colors = useAppColors(); const styles = useChatScreenStyles(); + const dynamicStyles = useChatDynamicStyles(); const isDisabled = isGroupChat && isMuted; // 获取当前用户ID const currentUserId = currentUser?.id || ''; + // 动态颜色 + const textPrimary = dynamicStyles.textPrimaryColor || colors.chat.textPrimary; + const textSecondary = dynamicStyles.textSecondaryColor || colors.chat.textSecondary; + const textMuted = '#999'; // 禁用状态颜色 + const textDisabled = '#CCC'; // 完全禁用颜色 + // 响应式布局 const isWideScreen = useBreakpointGTE('lg'); @@ -91,7 +99,7 @@ export const ChatInput: React.FC - + ); @@ -157,7 +165,7 @@ export const ChatInput: React.FC @@ -165,7 +173,7 @@ export const ChatInput: React.FC s.fontSize); const messageRadius = useChatSettingsStore((s) => s.messageRadius); const themeIndex = useChatSettingsStore((s) => s.themeIndex); + const nightMode = useChatSettingsStore((s) => s.nightMode); const theme = CHAT_THEMES[themeIndex]; + const colors = useAppColors(); + + // 夜间模式优先:当开启夜间模式时,使用系统暗色,忽略主题设置 + // 判断是否为暗色模式:chat.nightMode 设置 或 系统暗色模式(背景色为暗色) + const isSystemDarkMode = (colors.chat.screen as string).startsWith('#0') || + (colors.chat.screen as string) === '#0A0A0A' || + (colors.chat.screen as string) === '#121212'; + const isNightMode = nightMode || isSystemDarkMode; return { fontSize, messageRadius, - // 气泡颜色 - outgoingBubbleColor: theme.bubble, + // 夜间模式时使用系统暗色,否则使用主题色 + outgoingBubbleColor: isNightMode ? colors.chat.bubbleOutgoing : theme.bubble, // 背景色 - chatBackgroundColor: theme.secondary, + chatBackgroundColor: isNightMode ? colors.chat.screen : theme.secondary, // 卡片/头部背景色 - cardBackgroundColor: theme.card, + cardBackgroundColor: isNightMode ? colors.chat.card : theme.card, // 输入框背景色 - inputBackgroundColor: theme.inputBg, + inputBackgroundColor: isNightMode ? colors.chat.surfaceRaised : theme.inputBg, // 面板背景色 - panelBackgroundColor: theme.panelBg, + panelBackgroundColor: isNightMode ? colors.chat.surfaceMuted : theme.panelBg, // 主要文字颜色 - textPrimaryColor: theme.textPrimary, + textPrimaryColor: isNightMode ? colors.chat.textPrimary : theme.textPrimary, // 次要文字颜色 - textSecondaryColor: theme.textSecondary, + textSecondaryColor: isNightMode ? colors.chat.textSecondary : theme.textSecondary, }; } diff --git a/src/screens/profile/AccountSecurityScreen.tsx b/src/screens/profile/AccountSecurityScreen.tsx index 63ccce5..c036ef2 100644 --- a/src/screens/profile/AccountSecurityScreen.tsx +++ b/src/screens/profile/AccountSecurityScreen.tsx @@ -190,8 +190,7 @@ export const AccountSecurityScreen: React.FC = () => { <> - - + 邮箱验证 @@ -206,7 +205,7 @@ export const AccountSecurityScreen: React.FC = () => { - + { - + { - - + 修改密码 - + { /> - + { - + { - + { const renderFontSizeSlider = () => ( 消息字号 - + { const renderRadiusSlider = () => ( 消息圆角 - + { const renderOtherSettings = () => ( 其他 - - - - - - - - 更改聊天壁纸 - + + + + - - - - - - - - - - 更改名称颜色 - MiMQy - + + 更改聊天壁纸 - - - + + + + + + + + + + + 更改名称颜色 + MiMQy + + + + ); // 渲染夜间模式开关 const renderNightMode = () => ( - - - - - - - 切换到夜间模式 + + + + - toggleNightMode()} - > - - + 切换到夜间模式 + toggleNightMode()} + > + + ); @@ -468,16 +464,14 @@ export const ChatSettingsScreen: React.FC = () => { // 渲染浏览其他主题 const renderBrowseThemes = () => ( - - - - - - - 浏览其他主题 + + + + - + 浏览其他主题 + ); diff --git a/src/screens/profile/EditProfileScreen.tsx b/src/screens/profile/EditProfileScreen.tsx index 5da8db4..f3bb610 100644 --- a/src/screens/profile/EditProfileScreen.tsx +++ b/src/screens/profile/EditProfileScreen.tsx @@ -42,7 +42,7 @@ function createEditProfileStyles(colors: AppColors) { return StyleSheet.create({ container: { flex: 1, - backgroundColor: colors.background.default, + backgroundColor: colors.background.paper, }, keyboardView: { flex: 1, @@ -58,7 +58,7 @@ function createEditProfileStyles(colors: AppColors) { coverContainer: { position: 'relative', overflow: 'hidden', - borderRadius: borderRadius.lg, + borderRadius: 14, }, coverTouchable: { width: '100%', @@ -112,7 +112,6 @@ function createEditProfileStyles(colors: AppColors) { marginTop: -50, borderRadius: borderRadius.xl, padding: spacing.lg, - ...shadows.md, }, avatarWrapper: { alignItems: 'center', @@ -204,15 +203,9 @@ function createEditProfileStyles(colors: AppColors) { // ===== 表单区域 ===== formCard: { - backgroundColor: colors.background.paper, - borderRadius: borderRadius.lg, + borderRadius: 14, padding: spacing.lg, marginBottom: spacing.lg, - shadowColor: colors.text.primary, - shadowOffset: { width: 0, height: 2 }, - shadowOpacity: 0.05, - shadowRadius: 8, - elevation: 2, maxWidth: CONTENT_MAX_WIDTH, alignSelf: 'center', width: '100%', @@ -228,7 +221,7 @@ function createEditProfileStyles(colors: AppColors) { width: 40, height: 40, borderRadius: borderRadius.md, - backgroundColor: colors.primary.light + '20', + backgroundColor: colors.background.default, justifyContent: 'center', alignItems: 'center', marginRight: spacing.md, @@ -267,14 +260,11 @@ function createEditProfileStyles(colors: AppColors) { marginTop: spacing.sm, }, saveButton: { + height: 50, backgroundColor: colors.primary.main, - borderRadius: borderRadius.lg, - paddingVertical: spacing.md, - shadowColor: colors.primary.main, - shadowOffset: { width: 0, height: 4 }, - shadowOpacity: 0.3, - shadowRadius: 8, - elevation: 4, + borderRadius: 14, + alignItems: 'center', + justifyContent: 'center', }, saveButtonDisabled: { opacity: 0.6, diff --git a/src/screens/profile/NotificationSettingsScreen.tsx b/src/screens/profile/NotificationSettingsScreen.tsx index 157d503..68bcc5d 100644 --- a/src/screens/profile/NotificationSettingsScreen.tsx +++ b/src/screens/profile/NotificationSettingsScreen.tsx @@ -13,7 +13,7 @@ import { } from 'react-native'; import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context'; import { MaterialCommunityIcons } from '@expo/vector-icons'; -import { spacing, borderRadius, useAppColors, type AppColors } from '../../theme'; +import { spacing, borderRadius, fontSizes, useAppColors, type AppColors } from '../../theme'; import { Text } from '../../components/common'; import { loadNotificationPreferences, @@ -122,43 +122,39 @@ export const NotificationSettingsScreen: React.FC = () => { {/* 消息通知设置 */} - - + 消息通知 - - {settings.map((item, index) => ( - - - - - - - - {item.title} - - {item.subtitle && ( - - {item.subtitle} - - )} - - ( + + + + - {index < settings.length - 1 && } + + + {item.title} + + {item.subtitle && ( + + {item.subtitle} + + )} + + - ))} - + + ))} {/* 提示信息 */} @@ -186,47 +182,40 @@ function createNotificationSettingsStyles(colors: AppColors) { return StyleSheet.create({ container: { flex: 1, - backgroundColor: colors.background.default, + backgroundColor: colors.background.paper, }, scrollContent: { - paddingVertical: spacing.md, + paddingVertical: spacing.lg, }, section: { - marginBottom: spacing.lg, + marginBottom: spacing['2xl'], }, sectionHeader: { - flexDirection: 'row', - alignItems: 'center', - paddingHorizontal: spacing.lg, + paddingHorizontal: spacing['2xl'], marginBottom: spacing.sm, - gap: spacing.xs, + marginTop: spacing.sm, }, sectionTitle: { fontWeight: '600', - }, - card: { - backgroundColor: colors.background.paper, - marginHorizontal: spacing.lg, - borderRadius: borderRadius.lg, - overflow: 'hidden', - maxWidth: CONTENT_MAX_WIDTH, - alignSelf: 'center', - width: '100%', + fontSize: fontSizes.sm, + color: colors.text.secondary, + textTransform: 'uppercase', + letterSpacing: 0.5, }, settingItem: { flexDirection: 'row', alignItems: 'center', - paddingVertical: spacing.md, - paddingHorizontal: spacing.md, + paddingVertical: 16, + paddingHorizontal: spacing['2xl'], + borderBottomWidth: StyleSheet.hairlineWidth, + borderBottomColor: colors.divider, }, iconContainer: { - width: 36, - height: 36, - borderRadius: borderRadius.md, - backgroundColor: colors.primary.light + '20', + width: 24, + height: 24, justifyContent: 'center', alignItems: 'center', - marginRight: spacing.md, + marginRight: spacing.lg, }, settingContent: { flex: 1, @@ -234,18 +223,14 @@ function createNotificationSettingsStyles(colors: AppColors) { subtitle: { marginTop: 2, }, - divider: { - height: 1, - backgroundColor: colors.divider, - marginLeft: 36 + spacing.md + spacing.md, - }, + divider: {}, tipContainer: { flexDirection: 'row', alignItems: 'flex-start', - marginHorizontal: spacing.lg, + marginHorizontal: spacing['2xl'], padding: spacing.md, - backgroundColor: colors.background.paper, - borderRadius: borderRadius.lg, + backgroundColor: colors.background.default, + borderRadius: 14, gap: spacing.sm, }, tipText: { diff --git a/src/screens/profile/SettingsScreen.tsx b/src/screens/profile/SettingsScreen.tsx index bfc9d0d..037dccd 100644 --- a/src/screens/profile/SettingsScreen.tsx +++ b/src/screens/profile/SettingsScreen.tsx @@ -82,50 +82,40 @@ function createSettingsStyles(colors: AppColors) { return StyleSheet.create({ container: { flex: 1, - backgroundColor: colors.background.default, + backgroundColor: colors.background.paper, }, scrollContent: { - paddingVertical: spacing.md, + paddingVertical: spacing.lg, }, groupContainer: { - marginBottom: spacing.lg, + marginBottom: spacing['2xl'], maxWidth: SETTINGS_CARD_MAX_WIDTH, alignSelf: 'center', width: '100%', }, groupHeader: { - flexDirection: 'row', - alignItems: 'center', - paddingHorizontal: spacing.lg, + paddingHorizontal: spacing['2xl'], marginBottom: spacing.sm, - gap: spacing.xs, + marginTop: spacing.sm, }, groupTitle: { fontWeight: '600', fontSize: fontSizes.sm, - }, - card: { - backgroundColor: colors.background.paper, - marginHorizontal: spacing.lg, - borderRadius: borderRadius.lg, - overflow: 'hidden', + color: colors.text.secondary, + textTransform: 'uppercase', + letterSpacing: 0.5, }, settingItem: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', - paddingVertical: spacing.md, - paddingHorizontal: spacing.md, - borderBottomWidth: 1, + paddingVertical: 16, + paddingHorizontal: spacing['2xl'], + borderBottomWidth: StyleSheet.hairlineWidth, borderBottomColor: colors.divider, }, - settingItemFirst: { - borderTopLeftRadius: borderRadius.lg, - borderTopRightRadius: borderRadius.lg, - }, + settingItemFirst: {}, settingItemLast: { - borderBottomLeftRadius: borderRadius.lg, - borderBottomRightRadius: borderRadius.lg, borderBottomWidth: 0, }, settingItemLeft: { @@ -134,17 +124,13 @@ function createSettingsStyles(colors: AppColors) { flex: 1, }, iconContainer: { - width: 36, - height: 36, - borderRadius: borderRadius.md, - backgroundColor: colors.primary.light + '20', + width: 24, + height: 24, justifyContent: 'center', alignItems: 'center', - marginRight: spacing.md, - }, - dangerIconContainer: { - backgroundColor: colors.error.light + '20', + marginRight: spacing.lg, }, + dangerIconContainer: {}, settingContent: { flex: 1, }, @@ -155,19 +141,19 @@ function createSettingsStyles(colors: AppColors) { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', - backgroundColor: colors.background.paper, - marginHorizontal: spacing.lg, - marginTop: spacing.sm, - marginBottom: spacing.lg, - paddingVertical: spacing.md, - borderRadius: borderRadius.lg, + marginTop: spacing.lg, + marginBottom: spacing['2xl'], + paddingVertical: 16, + marginHorizontal: spacing['2xl'], + borderRadius: 14, gap: spacing.sm, maxWidth: SETTINGS_CARD_MAX_WIDTH, alignSelf: 'center', width: '100%', + backgroundColor: colors.error.light + '20', }, logoutText: { - fontWeight: '500', + fontWeight: '600', }, footer: { alignItems: 'center', @@ -318,7 +304,6 @@ export const SettingsScreen: React.FC = () => { key={item.key} style={[ styles.settingItem, - index === 0 && styles.settingItemFirst, index === total - 1 && styles.settingItemLast, ]} onPress={() => (item.onPress ? item.onPress() : handleItemPress(item.key))} @@ -328,8 +313,8 @@ export const SettingsScreen: React.FC = () => { @@ -352,12 +337,11 @@ export const SettingsScreen: React.FC = () => { const renderGroup = (group: (typeof settingsGroups)[0]) => ( - - + {group.title} - + {group.items.map((item, index) => renderSettingItem(item, index, group.items.length))}