feat(Theme): enhance theming and UI consistency across components
All checks were successful
Frontend CI / build-and-push-web (push) Successful in 8m15s
Frontend CI / ota-android (push) Successful in 10m56s
Frontend CI / build-android-apk (push) Successful in 1h3m22s

- Updated app.json to set userInterfaceStyle to automatic for improved theme adaptability.
- Refactored layout components to utilize useAppColors for dynamic theming, ensuring consistent color usage.
- Introduced SystemChrome component to manage system UI background color based on theme.
- Enhanced TabsLayout, ProfileStackLayout, and other components to leverage new theming structure.
- Improved QRCodeScanner, SearchBar, and CommentItem styles to align with the updated theme system.
- Consolidated styles in SystemMessageItem and TabBar for better maintainability and visual coherence.
This commit is contained in:
lafay
2026-03-25 05:16:54 +08:00
parent 90d834695f
commit 4ee3079b9f
86 changed files with 6777 additions and 5890 deletions

View File

@@ -4,7 +4,7 @@
* 支持响应式布局
*/
import React, { useState } from 'react';
import React, { useState, useMemo } from 'react';
import {
View,
StyleSheet,
@@ -19,7 +19,7 @@ import { SafeAreaView } from 'react-native-safe-area-context';
import { useRouter } from 'expo-router';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import * as ImagePicker from 'expo-image-picker';
import { colors, spacing, fontSizes, borderRadius, shadows } from '../../theme';
import { spacing, fontSizes, borderRadius, shadows, useAppColors, type AppColors } from '../../theme';
import { groupService } from '../../services/groupService';
import { uploadService } from '../../services/uploadService';
import { Avatar, Text, Button, Loading } from '../../components/common';
@@ -27,6 +27,8 @@ import { User } from '../../types';
import MutualFollowSelectorModal from './components/MutualFollowSelectorModal';
const CreateGroupScreen: React.FC = () => {
const colors = useAppColors();
const styles = useMemo(() => createCreateGroupStyles(colors), [colors]);
const router = useRouter();
// 表单状态
@@ -310,171 +312,173 @@ const CreateGroupScreen: React.FC = () => {
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: colors.background.default,
},
scrollView: {
flex: 1,
},
scrollContent: {
padding: spacing.lg,
paddingBottom: spacing.xl,
},
// 头部区域样式
headerSection: {
flexDirection: 'row',
alignItems: 'flex-start',
marginBottom: spacing.xl,
},
avatarContainer: {
marginRight: spacing.lg,
},
avatarWrapper: {
position: 'relative',
},
avatarImage: {
width: 80,
height: 80,
borderRadius: 40,
},
avatarPlaceholder: {
justifyContent: 'center',
alignItems: 'center',
backgroundColor: colors.background.default,
borderRadius: 40,
},
avatarBadge: {
position: 'absolute',
bottom: 0,
right: 0,
backgroundColor: colors.primary.main,
width: 28,
height: 28,
borderRadius: 14,
justifyContent: 'center',
alignItems: 'center',
borderWidth: 2,
borderColor: colors.background.paper,
},
nameInputContainer: {
flex: 1,
paddingTop: spacing.sm,
},
inputLabel: {
marginBottom: spacing.sm,
fontWeight: '600',
},
nameInput: {
backgroundColor: colors.background.paper,
borderRadius: borderRadius.lg,
paddingHorizontal: spacing.md,
paddingVertical: spacing.md,
fontSize: fontSizes.lg,
color: colors.text.primary,
borderWidth: 1,
borderColor: colors.divider,
},
charCount: {
textAlign: 'right',
marginTop: spacing.xs,
},
// 区域样式
section: {
marginBottom: spacing.xl,
},
sectionHeader: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: spacing.sm,
},
sectionTitle: {
fontWeight: '600',
marginBottom: spacing.sm,
},
// 文本域样式
textAreaContainer: {
backgroundColor: colors.background.paper,
borderRadius: borderRadius.lg,
borderWidth: 1,
borderColor: colors.divider,
padding: spacing.md,
},
textArea: {
minHeight: 100,
fontSize: fontSizes.md,
color: colors.text.primary,
lineHeight: 22,
},
textAreaCharCount: {
textAlign: 'right',
marginTop: spacing.sm,
},
// 已选成员样式
selectedMembersList: {
paddingVertical: spacing.sm,
},
selectedMemberItem: {
alignItems: 'center',
marginRight: spacing.lg,
width: 64,
},
removeMemberButton: {
position: 'absolute',
top: -4,
right: 4,
},
removeIconContainer: {
backgroundColor: colors.text.secondary,
borderRadius: 10,
width: 20,
height: 20,
justifyContent: 'center',
alignItems: 'center',
borderWidth: 2,
borderColor: colors.background.paper,
},
selectedMemberName: {
marginTop: spacing.xs,
textAlign: 'center',
width: '100%',
},
// 邀请按钮样式
inviteButton: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: colors.background.paper,
borderRadius: borderRadius.lg,
padding: spacing.md,
marginBottom: spacing.xl,
...shadows.sm,
},
inviteIconContainer: {
width: 48,
height: 48,
borderRadius: borderRadius.lg,
backgroundColor: colors.primary.light + '20',
justifyContent: 'center',
alignItems: 'center',
marginRight: spacing.md,
},
inviteTextContainer: {
flex: 1,
},
inviteTitle: {
fontWeight: '600',
marginBottom: 2,
},
// 底部按钮样式
footer: {
padding: spacing.lg,
paddingBottom: spacing.xl,
backgroundColor: colors.background.paper,
borderTopWidth: 1,
borderTopColor: colors.divider,
},
});
function createCreateGroupStyles(colors: AppColors) {
return StyleSheet.create({
container: {
flex: 1,
backgroundColor: colors.background.default,
},
scrollView: {
flex: 1,
},
scrollContent: {
padding: spacing.lg,
paddingBottom: spacing.xl,
},
// 头部区域样式
headerSection: {
flexDirection: 'row',
alignItems: 'flex-start',
marginBottom: spacing.xl,
},
avatarContainer: {
marginRight: spacing.lg,
},
avatarWrapper: {
position: 'relative',
},
avatarImage: {
width: 80,
height: 80,
borderRadius: 40,
},
avatarPlaceholder: {
justifyContent: 'center',
alignItems: 'center',
backgroundColor: colors.background.default,
borderRadius: 40,
},
avatarBadge: {
position: 'absolute',
bottom: 0,
right: 0,
backgroundColor: colors.primary.main,
width: 28,
height: 28,
borderRadius: 14,
justifyContent: 'center',
alignItems: 'center',
borderWidth: 2,
borderColor: colors.background.paper,
},
nameInputContainer: {
flex: 1,
paddingTop: spacing.sm,
},
inputLabel: {
marginBottom: spacing.sm,
fontWeight: '600',
},
nameInput: {
backgroundColor: colors.background.paper,
borderRadius: borderRadius.lg,
paddingHorizontal: spacing.md,
paddingVertical: spacing.md,
fontSize: fontSizes.lg,
color: colors.text.primary,
borderWidth: 1,
borderColor: colors.divider,
},
charCount: {
textAlign: 'right',
marginTop: spacing.xs,
},
// 区域样式
section: {
marginBottom: spacing.xl,
},
sectionHeader: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: spacing.sm,
},
sectionTitle: {
fontWeight: '600',
marginBottom: spacing.sm,
},
// 文本域样式
textAreaContainer: {
backgroundColor: colors.background.paper,
borderRadius: borderRadius.lg,
borderWidth: 1,
borderColor: colors.divider,
padding: spacing.md,
},
textArea: {
minHeight: 100,
fontSize: fontSizes.md,
color: colors.text.primary,
lineHeight: 22,
},
textAreaCharCount: {
textAlign: 'right',
marginTop: spacing.sm,
},
// 已选成员样式
selectedMembersList: {
paddingVertical: spacing.sm,
},
selectedMemberItem: {
alignItems: 'center',
marginRight: spacing.lg,
width: 64,
},
removeMemberButton: {
position: 'absolute',
top: -4,
right: 4,
},
removeIconContainer: {
backgroundColor: colors.text.secondary,
borderRadius: 10,
width: 20,
height: 20,
justifyContent: 'center',
alignItems: 'center',
borderWidth: 2,
borderColor: colors.background.paper,
},
selectedMemberName: {
marginTop: spacing.xs,
textAlign: 'center',
width: '100%',
},
// 邀请按钮样式
inviteButton: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: colors.background.paper,
borderRadius: borderRadius.lg,
padding: spacing.md,
marginBottom: spacing.xl,
...shadows.sm,
},
inviteIconContainer: {
width: 48,
height: 48,
borderRadius: borderRadius.lg,
backgroundColor: colors.primary.light + '20',
justifyContent: 'center',
alignItems: 'center',
marginRight: spacing.md,
},
inviteTextContainer: {
flex: 1,
},
inviteTitle: {
fontWeight: '600',
marginBottom: 2,
},
// 底部按钮样式
footer: {
padding: spacing.lg,
paddingBottom: spacing.xl,
backgroundColor: colors.background.paper,
borderTopWidth: 1,
borderTopColor: colors.divider,
},
});
}
export default CreateGroupScreen;