import React, { useState, useEffect } from 'react' import { View, Text, Switch, TouchableOpacity, StyleSheet, ScrollView, Alert } from 'react-native' import * as SecureStore from 'expo-secure-store' // eslint-disable-next-line @typescript-eslint/no-var-requires const Haptics = (() => { try { return require('expo-haptics') } catch { return null } })() import { COLORS } from '../../constants/Config' import { useTheme } from '../../contexts/ThemeContext' import { useFontScale } from '../../contexts/FontContext' export default function ThemeSettingsScreen() { const { isDark, toggleTheme } = useTheme() const { fontScale, setFontScale } = useFontScale() const [vibration, setVibration] = useState('short') const [colorBlind, setColorBlind] = useState('default') const [screenLock, setScreenLock] = useState(false) useEffect(() => { Promise.all([ SecureStore.getItemAsync('grd_vibration'), SecureStore.getItemAsync('grd_colorblind'), SecureStore.getItemAsync('grd_screen_lock'), ]).then(([v, c, l]) => { if (v) setVibration(v) if (c) setColorBlind(c) if (l) setScreenLock(l === 'true') }) }, []) const saveVibration = async (v: string) => { setVibration(v) await SecureStore.setItemAsync('grd_vibration', v) if (v !== 'none') await Haptics?.notificationAsync?.(Haptics?.NotificationFeedbackType?.Success) } const saveColorBlind = async (c: string) => { setColorBlind(c) await SecureStore.setItemAsync('grd_colorblind', c) Alert.alert('색맹 지원', `${c === 'default' ? '기본' : c === 'protanopia' ? '제1색맹' : '제2색맹'} 팔레트가 적용됐습니다.`) } const toggleScreenLock = async (v: boolean) => { setScreenLock(v) await SecureStore.setItemAsync('grd_screen_lock', String(v)) Alert.alert('화면 방향', v ? '세로 방향으로 고정됩니다.' : '자동 회전이 활성화됩니다.') } return ( {/* 다크모드 */} 테마 다크모드 {/* 글자 크기 */} 글자 크기 {([1.0, 1.2, 1.5] as const).map(scale => ( setFontScale(scale)}> {scale === 1.0 ? '작게 (기본)' : scale === 1.2 ? '보통' : '크게'} {fontScale === scale && } ))} {/* 진동 패턴 */} 진동 패턴 {[['none', '없음'], ['short', '짧게'], ['long', '길게']].map(([v, label]) => ( saveVibration(v)}> {label} {vibration === v && } ))} {/* 색맹 지원 */} 색맹 지원 팔레트 {[['default', '기본'], ['protanopia', '제1색맹 (적록)'], ['deuteranopia', '제2색맹 (녹적)']].map(([c, label]) => ( saveColorBlind(c)}> {label} {colorBlind === c && } ))} {/* 화면 방향 잠금 */} 화면 방향 세로 방향 잠금 ) } const s = StyleSheet.create({ container: { flex: 1, backgroundColor: COLORS.bg }, section: { fontSize: 13, fontWeight: '700', color: COLORS.muted, paddingHorizontal: 16, paddingTop: 20, paddingBottom: 6, textTransform: 'uppercase', letterSpacing: 1 }, row: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', backgroundColor: '#fff', paddingHorizontal: 16, paddingVertical: 14, borderBottomWidth: 1, borderBottomColor: COLORS.border }, label: { fontSize: 15, color: COLORS.text }, option: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', backgroundColor: '#fff', paddingHorizontal: 16, paddingVertical: 14, borderBottomWidth: 1, borderBottomColor: COLORS.border }, optionActive: { backgroundColor: COLORS.light }, optionText: { fontSize: 15, color: COLORS.text }, optionTextActive:{ color: COLORS.accent, fontWeight: '600' }, check: { fontSize: 16, color: COLORS.accent }, })