161 lines
4.0 KiB
TypeScript
161 lines
4.0 KiB
TypeScript
import React from 'react';
|
|
import { Image, Pressable, StyleSheet, Text, View, Platform, useWindowDimensions } from 'react-native';
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
import SheetModal from '@/components/ui/SheetModal';
|
|
|
|
import type { ThemeMode } from '@/src/storage/appStorage';
|
|
|
|
type Props = {
|
|
visible: boolean;
|
|
mode: ThemeMode;
|
|
onSelect: (mode: ThemeMode) => void;
|
|
onClose: () => void;
|
|
};
|
|
|
|
export default function ThemeModal({ visible, mode, onSelect, onClose }: Props) {
|
|
const { t } = useTranslation();
|
|
const { width, height } = useWindowDimensions();
|
|
const isTablet = Platform.OS === 'ios' && Math.min(width, height) >= 768;
|
|
|
|
return (
|
|
<SheetModal visible={visible} title={t('theme.title')} onClose={onClose} height={isTablet ? 560 : 360}>
|
|
<View style={styles.row}>
|
|
<ThemeCard
|
|
title={t('theme.scenery')}
|
|
selected={mode === 'scenery'}
|
|
onPress={() => onSelect('scenery')}
|
|
>
|
|
<Image
|
|
source={require('../../assets/images/theme/theme_landscape.png')}
|
|
resizeMode="cover"
|
|
style={styles.previewImage}
|
|
/>
|
|
</ThemeCard>
|
|
|
|
<ThemeCard
|
|
title={t('theme.color')}
|
|
selected={mode === 'color'}
|
|
onPress={() => onSelect('color')}
|
|
>
|
|
<Image
|
|
source={require('../../assets/images/theme/theme_color.png')}
|
|
resizeMode="cover"
|
|
style={styles.previewImage}
|
|
/>
|
|
</ThemeCard>
|
|
|
|
<ThemeCard
|
|
title={t('theme.suixin')}
|
|
selected={mode === 'suixin'}
|
|
onPress={() => onSelect('suixin')}
|
|
>
|
|
<Image
|
|
// 占位:一期复用纯色预览图,后续可替换为专用资源
|
|
source={require('../../assets/images/theme/theme_color.png')}
|
|
resizeMode="cover"
|
|
style={styles.previewImage}
|
|
/>
|
|
</ThemeCard>
|
|
</View>
|
|
</SheetModal>
|
|
);
|
|
}
|
|
|
|
function ThemeCard({
|
|
title,
|
|
selected,
|
|
onPress,
|
|
children,
|
|
}: {
|
|
title: string;
|
|
selected: boolean;
|
|
onPress: () => void;
|
|
children: React.ReactNode;
|
|
}) {
|
|
return (
|
|
<Pressable
|
|
onPress={onPress}
|
|
style={styles.cardContainer}
|
|
hitSlop={6}
|
|
>
|
|
<View style={[styles.previewWrapper, selected && styles.selectedWrapper]}>
|
|
<View style={styles.previewInner}>
|
|
{children}
|
|
{/* 文案展示在图片中心 */}
|
|
<View style={styles.textOverlay}>
|
|
<Text
|
|
style={[styles.overlayTitle, selected && styles.selectedOverlayTitle]}
|
|
numberOfLines={1}
|
|
adjustsFontSizeToFit
|
|
minimumFontScale={0.85}
|
|
>
|
|
{title}
|
|
</Text>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
</Pressable>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
row: {
|
|
flexDirection: 'row',
|
|
flexWrap: 'nowrap',
|
|
gap: 8,
|
|
paddingHorizontal: 0,
|
|
paddingBottom: 22,
|
|
paddingTop: 20,
|
|
justifyContent: 'space-between',
|
|
},
|
|
cardContainer: {
|
|
flex: 1,
|
|
minWidth: 0,
|
|
alignItems: 'stretch',
|
|
},
|
|
previewWrapper: {
|
|
width: '100%',
|
|
aspectRatio: 110 / 178,
|
|
borderRadius: 26,
|
|
padding: 6.5,
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
},
|
|
selectedWrapper: {
|
|
borderWidth: 4,
|
|
borderColor: '#E7837A',
|
|
borderRadius: 26,
|
|
},
|
|
previewInner: {
|
|
width: '100%',
|
|
height: '100%',
|
|
borderRadius: 21,
|
|
overflow: 'hidden',
|
|
backgroundColor: '#F5F5F5',
|
|
position: 'relative',
|
|
},
|
|
previewImage: {
|
|
width: '100%',
|
|
height: '100%',
|
|
},
|
|
textOverlay: {
|
|
...StyleSheet.absoluteFillObject,
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
backgroundColor: 'rgba(0,0,0,0.05)', // 轻微遮罩增加文字可读性
|
|
},
|
|
overlayTitle: {
|
|
color: '#FFFFFF',
|
|
fontSize: 15,
|
|
fontWeight: '700',
|
|
textAlign: 'center',
|
|
textShadowColor: 'rgba(0, 0, 0, 0.3)',
|
|
textShadowOffset: { width: 0, height: 1 },
|
|
textShadowRadius: 3,
|
|
},
|
|
selectedOverlayTitle: {
|
|
color: '#FFFFFF',
|
|
},
|
|
});
|