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

@@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react';
import React, { useEffect, useMemo, useState } from 'react';
import {
View,
Text,
@@ -12,7 +12,7 @@ import { CameraView, useCameraPermissions } from 'expo-camera';
import { useRouter } from 'expo-router';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import * as hrefs from '../../navigation/hrefs';
import { colors, spacing, fontSizes, borderRadius } from '../../theme';
import { spacing, fontSizes, borderRadius, useAppColors, type AppColors } from '../../theme';
const { width, height } = Dimensions.get('window');
@@ -21,14 +21,130 @@ interface QRCodeScannerProps {
onClose: () => void;
}
function createQrScannerStyles(colors: AppColors) {
return StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#000',
},
camera: {
flex: 1,
},
overlay: {
flex: 1,
backgroundColor: 'rgba(0,0,0,0.5)',
},
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: spacing.md,
paddingTop: spacing.xl,
paddingBottom: spacing.md,
},
closeButton: {
padding: spacing.sm,
},
headerTitle: {
fontSize: fontSizes.lg,
fontWeight: '600',
color: '#fff',
},
placeholder: {
width: 40,
},
scanArea: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
scanFrame: {
width: width * 0.7,
height: width * 0.7,
position: 'relative',
},
corner: {
position: 'absolute',
width: 20,
height: 20,
borderColor: colors.primary.main,
borderWidth: 3,
},
topLeft: {
top: 0,
left: 0,
borderRightWidth: 0,
borderBottomWidth: 0,
},
topRight: {
top: 0,
right: 0,
borderLeftWidth: 0,
borderBottomWidth: 0,
},
bottomLeft: {
bottom: 0,
left: 0,
borderRightWidth: 0,
borderTopWidth: 0,
},
bottomRight: {
bottom: 0,
right: 0,
borderLeftWidth: 0,
borderTopWidth: 0,
},
scanText: {
marginTop: spacing.lg,
fontSize: fontSizes.md,
color: '#fff',
textAlign: 'center',
},
footer: {
padding: spacing.xl,
alignItems: 'center',
},
flashButton: {
padding: spacing.md,
backgroundColor: 'rgba(255,255,255,0.2)',
borderRadius: borderRadius.full,
},
permissionContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: spacing.xl,
},
permissionText: {
marginTop: spacing.lg,
fontSize: fontSizes.md,
color: 'rgba(255,255,255,0.72)',
textAlign: 'center',
},
permissionButton: {
marginTop: spacing.xl,
paddingVertical: spacing.md,
paddingHorizontal: spacing.xl,
backgroundColor: colors.primary.main,
borderRadius: borderRadius.md,
},
permissionButtonText: {
color: '#fff',
fontSize: fontSizes.md,
fontWeight: '600',
},
});
}
export const QRCodeScanner: React.FC<QRCodeScannerProps> = ({ visible, onClose }) => {
const router = useRouter();
const themeColors = useAppColors();
const styles = useMemo(() => createQrScannerStyles(themeColors), [themeColors]);
const [permission, requestPermission] = useCameraPermissions();
const [scanned, setScanned] = useState(false);
useEffect(() => {
if (visible) {
// 重置扫描状态,确保每次打开都能重新扫描
setScanned(false);
if (!permission?.granted) {
requestPermission();
@@ -39,16 +155,11 @@ export const QRCodeScanner: React.FC<QRCodeScannerProps> = ({ visible, onClose }
const handleBarCodeScanned = ({ type, data }: { type: string; data: string }) => {
if (scanned) return;
setScanned(true);
// 先关闭扫描界面,类似微信的做法
onClose();
// 解析二维码内容
// 格式: carrotbbs://qrcode/login?session_id=xxx
if (data.startsWith('carrotbbs://qrcode/login')) {
const sessionId = extractSessionId(data);
if (sessionId) {
// 跳转到确认页面
router.push(hrefs.hrefQrLoginConfirm(sessionId));
} else {
Alert.alert('无效的二维码', '无法识别该二维码');
@@ -79,7 +190,7 @@ export const QRCodeScanner: React.FC<QRCodeScannerProps> = ({ visible, onClose }
<View style={styles.placeholder} />
</View>
<View style={styles.permissionContainer}>
<MaterialCommunityIcons name="camera-off" size={64} color="#999" />
<MaterialCommunityIcons name="camera-off" size={64} color="rgba(255,255,255,0.5)" />
<Text style={styles.permissionText}></Text>
<TouchableOpacity style={styles.permissionButton} onPress={requestPermission}>
<Text style={styles.permissionButtonText}></Text>
@@ -132,117 +243,4 @@ export const QRCodeScanner: React.FC<QRCodeScannerProps> = ({ visible, onClose }
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#000',
},
camera: {
flex: 1,
},
overlay: {
flex: 1,
backgroundColor: 'rgba(0,0,0,0.5)',
},
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: spacing.md,
paddingTop: spacing.xl,
paddingBottom: spacing.md,
},
closeButton: {
padding: spacing.sm,
},
headerTitle: {
fontSize: fontSizes.lg,
fontWeight: '600',
color: '#fff',
},
placeholder: {
width: 40,
},
scanArea: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
scanFrame: {
width: width * 0.7,
height: width * 0.7,
position: 'relative',
},
corner: {
position: 'absolute',
width: 20,
height: 20,
borderColor: colors.primary.main,
borderWidth: 3,
},
topLeft: {
top: 0,
left: 0,
borderRightWidth: 0,
borderBottomWidth: 0,
},
topRight: {
top: 0,
right: 0,
borderLeftWidth: 0,
borderBottomWidth: 0,
},
bottomLeft: {
bottom: 0,
left: 0,
borderRightWidth: 0,
borderTopWidth: 0,
},
bottomRight: {
bottom: 0,
right: 0,
borderLeftWidth: 0,
borderTopWidth: 0,
},
scanText: {
marginTop: spacing.lg,
fontSize: fontSizes.md,
color: '#fff',
textAlign: 'center',
},
footer: {
padding: spacing.xl,
alignItems: 'center',
},
flashButton: {
padding: spacing.md,
backgroundColor: 'rgba(255,255,255,0.2)',
borderRadius: borderRadius.full,
},
permissionContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: spacing.xl,
},
permissionText: {
marginTop: spacing.lg,
fontSize: fontSizes.md,
color: '#666',
textAlign: 'center',
},
permissionButton: {
marginTop: spacing.xl,
paddingVertical: spacing.md,
paddingHorizontal: spacing.xl,
backgroundColor: colors.primary.main,
borderRadius: borderRadius.md,
},
permissionButtonText: {
color: '#fff',
fontSize: fontSizes.md,
fontWeight: '600',
},
});
export default QRCodeScanner;
export default QRCodeScanner;