131 lines
3.2 KiB
TypeScript
131 lines
3.2 KiB
TypeScript
import React from 'react';
|
|
import {
|
|
Modal,
|
|
View,
|
|
Text,
|
|
TouchableOpacity,
|
|
StyleSheet,
|
|
Pressable,
|
|
Image,
|
|
} from 'react-native';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { LANGUAGES, saveLanguage } from '../i18n';
|
|
import pxToDp from '../helper/pxToDp';
|
|
|
|
interface LanguageModalProps {
|
|
visible: boolean;
|
|
onClose: () => void;
|
|
}
|
|
|
|
const LanguageModal: React.FC<LanguageModalProps> = ({ visible, onClose }) => {
|
|
const { t, i18n } = useTranslation();
|
|
const currentLanguage = i18n.language;
|
|
|
|
const handleLanguageSelect = async (languageKey: string) => {
|
|
await saveLanguage(languageKey);
|
|
i18n.changeLanguage(languageKey);
|
|
onClose();
|
|
};
|
|
|
|
return (
|
|
<Modal
|
|
visible={visible}
|
|
transparent
|
|
animationType="fade"
|
|
onRequestClose={onClose}
|
|
>
|
|
<Pressable style={styles.overlay} onPress={onClose}>
|
|
<Pressable
|
|
style={styles.modalContainer}
|
|
onPress={(e) => e.stopPropagation()}
|
|
>
|
|
{/* 标题栏 */}
|
|
<View style={styles.header}>
|
|
<Text style={styles.title}>{t('languageModal.title')}</Text>
|
|
<TouchableOpacity onPress={onClose} style={styles.closeButton}>
|
|
<Text style={styles.closeIcon}>✕</Text>
|
|
</TouchableOpacity>
|
|
</View>
|
|
|
|
{/* 语言列表 */}
|
|
<View style={styles.languageList}>
|
|
{LANGUAGES.map((language) => (
|
|
<TouchableOpacity
|
|
key={language.key}
|
|
style={styles.languageItem}
|
|
onPress={() => handleLanguageSelect(language.key)}
|
|
activeOpacity={0.7}
|
|
>
|
|
<Text style={styles.languageText}>{language.label}</Text>
|
|
{currentLanguage === language.key && (
|
|
<Text style={styles.checkmark}>✓</Text>
|
|
)}
|
|
</TouchableOpacity>
|
|
))}
|
|
</View>
|
|
</Pressable>
|
|
</Pressable>
|
|
</Modal>
|
|
);
|
|
};
|
|
|
|
const styles = StyleSheet.create({
|
|
overlay: {
|
|
flex: 1,
|
|
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
},
|
|
modalContainer: {
|
|
width: pxToDp(630),
|
|
backgroundColor: '#fff',
|
|
borderRadius: pxToDp(24),
|
|
overflow: 'hidden',
|
|
},
|
|
header: {
|
|
flexDirection: 'row',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
paddingVertical: pxToDp(32),
|
|
borderBottomWidth: pxToDp(1),
|
|
borderBottomColor: '#f0f0f0',
|
|
position: 'relative',
|
|
},
|
|
title: {
|
|
fontSize: pxToDp(32),
|
|
fontWeight: '600',
|
|
color: '#333',
|
|
},
|
|
closeButton: {
|
|
position: 'absolute',
|
|
right: pxToDp(32),
|
|
padding: pxToDp(8),
|
|
},
|
|
closeIcon: {
|
|
fontSize: pxToDp(40),
|
|
color: '#666',
|
|
fontWeight: '300',
|
|
},
|
|
languageList: {
|
|
paddingVertical: pxToDp(16),
|
|
},
|
|
languageItem: {
|
|
flexDirection: 'row',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center',
|
|
paddingHorizontal: pxToDp(40),
|
|
paddingVertical: pxToDp(32),
|
|
backgroundColor: '#fff',
|
|
},
|
|
languageText: {
|
|
fontSize: pxToDp(30),
|
|
color: '#333',
|
|
},
|
|
checkmark: {
|
|
fontSize: pxToDp(40),
|
|
color: '#FF6B35',
|
|
fontWeight: 'bold',
|
|
},
|
|
});
|
|
|
|
export default LanguageModal; |