import LogoutSvg from '@/assets/icons/svg/logout.svg'; import RightArrowSvg from '@/assets/icons/svg/rightArrow.svg'; import { useAuth } from '@/contexts/auth-context'; import { fetchApi } from '@/lib/server-api-util'; import { Address, User } from '@/types/user'; import * as Location from 'expo-location'; import { useRouter } from 'expo-router'; import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Linking, Modal, Pressable, ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; import { ThemedText } from '../ThemedText'; import LcensesModal from './qualification/lcenses'; import PrivacyModal from './qualification/privacy'; import CustomSwitch from './switch'; import UserInfo from './userInfo'; import { checkNotificationPermission, getLocationPermission, getPermissions, requestLocationPermission, requestMediaLibraryPermission, requestNotificationPermission, reverseGeocode } from './utils'; const SettingModal = (props: { modalVisible: boolean, setModalVisible: (visible: boolean) => void, userInfo: User }) => { const { modalVisible, setModalVisible, userInfo } = props; const { t } = useTranslation(); const [modalType, setModalType] = useState<'ai' | 'terms' | 'privacy' | 'user'>('ai'); // 协议弹窗 const [privacyModalVisible, setPrivacyModalVisible] = useState(false); // 许可证弹窗 const [lcensesModalVisible, setLcensesModalVisible] = useState(false); const { logout } = useAuth(); const router = useRouter(); // 打开设置 const openAppSettings = () => { Linking.openSettings(); }; // 通知消息权限开关 const [notificationsEnabled, setNotificationsEnabled] = useState(false); const toggleNotifications = () => { if (notificationsEnabled) { // 引导去设置关闭权限 openAppSettings() } else { console.log('请求通知权限'); requestNotificationPermission().then((res) => { setNotificationsEnabled(res as boolean); }) } }; // 相册权限 const [albumEnabled, setAlbumEnabled] = useState(false); const toggleAlbum = () => { if (albumEnabled) { // 引导去设置关闭权限 openAppSettings() } else { requestMediaLibraryPermission().then((res) => { setAlbumEnabled(res as boolean); }) } } // 位置权限 const [locationEnabled, setLocationEnabled] = useState(false); // 位置权限更改 const toggleLocation = async () => { if (locationEnabled) { // 引导去设置关闭权限 openAppSettings() } else { requestLocationPermission().then((res) => { setLocationEnabled(res as boolean); }) } }; // 正在获取位置信息 const [isLoading, setIsLoading] = useState(false); // 动画开启 const [isRefreshing, setIsRefreshing] = useState(false); // 当前位置状态 const [currentLocation, setCurrentLocation] = useState
({} as Address); // 获取当前位置 const getCurrentLocation = async () => { setIsLoading(true); setIsRefreshing(true); try { // 1. 首先检查当前权限状态 -- 获取当前的位置权限 let currentStatus = await getLocationPermission(); console.log('当前权限状态:', currentStatus); // 2. 如果没有权限,则请求权限 if (!currentStatus) { const newStatus = await requestLocationPermission(); setLocationEnabled(newStatus); currentStatus = newStatus; if (!currentStatus) { alert('需要位置权限才能继续'); return; } } // 3. 确保位置服务已启用 const isEnabled = await Location.hasServicesEnabledAsync(); if (!isEnabled) { alert('请先启用位置服务'); return; } console.log('位置服务已启用'); // 4. 获取当前位置 const location = await Location.getCurrentPositionAsync({ accuracy: Location.Accuracy.High, // 使用高精度 timeInterval: 10000, // 可选:最大等待时间(毫秒) }); console.log('位置:', location); // 地理位置逆编码 const address = await reverseGeocode(location.coords.latitude, location.coords.longitude); // 5. 更新位置状态 setCurrentLocation(address as Address); return location; } catch (error: any) { if (error.code === 'PERMISSION_DENIED' || error.code === 'PERMISSION_DENIED_ERROR') { alert('位置权限被拒绝,请在设置中启用位置服务'); } else if (error.code === 'TIMEOUT') { alert('获取位置超时,请检查网络和位置服务'); } else { alert(`无法获取您的位置: ${error.message || '未知错误'}`); } throw error; // 重新抛出错误以便上层处理 } finally { setIsLoading(false); setIsRefreshing(false); } }; // 退出登录 const handleLogout = () => { fetchApi("/iam/logout", { method: "POST", headers: { "Content-Type": "application/json", }, }) .then(async (res) => { await logout(); setModalVisible(false); router.replace('/login'); }) .catch(() => { console.error("jwt has expired."); }); }; // 检查是否有权限 useEffect(() => { if (modalVisible) { // 位置权限 getLocationPermission().then((res) => { setLocationEnabled(res); }) // 媒体库权限 getPermissions().then((res) => { setAlbumEnabled(res); }) // 通知权限 checkNotificationPermission().then((res) => { console.log('通知权限:', res); setNotificationsEnabled(res); }) } }, [modalVisible]) return ( { setModalVisible(!modalVisible); }}> setModalVisible(false)}> e.stopPropagation()}> Settings {t('generalSetting.allTitle', { ns: 'personal' })} setModalVisible(false)}> × {/* 用户信息 */} {/* 升级版本 */} {/* {t('generalSetting.subscription', { ns: 'personal' })} {t('generalSetting.subscriptionTitle', { ns: 'personal' })} {t('generalSetting.subscriptionText', { ns: 'personal' })} { }} > {t('generalSetting.upgrade', { ns: 'personal' })} */} {/* 消息通知 */} {/* {t('permission.pushNotification', { ns: 'personal' })} {t('permission.pushNotification', { ns: 'personal' })} */} {/* 权限信息 */} {t('permission.permissionManagement', { ns: 'personal' })} {/* 相册权限 */} {t('permission.galleryAccess', { ns: 'personal' })} {/* 分割线 */} {/* 位置权限 */} {t('permission.locationPermission', { ns: 'personal' })} {t('permission.pushNotification', { ns: 'personal' })} {/* 相册成片权限 */} {/* Opus Permission */} {/* 账号 */} {/* Account Notifications Delete Account */} {/* 协议 */} {t('lcenses.title', { ns: 'personal' })} { setModalType('privacy'); setPrivacyModalVisible(true) }} > {t('lcenses.privacyPolicy', { ns: 'personal' })} { setModalType('terms'); setPrivacyModalVisible(true) }} > {t('lcenses.applyPermission', { ns: 'personal' })} { setModalType('user'); setPrivacyModalVisible(true) }} > {t('lcenses.userAgreement', { ns: 'personal' })} { setModalType('ai'); setPrivacyModalVisible(true) }} > {t('lcenses.aiPolicy', { ns: 'personal' })} { setLcensesModalVisible(true) }} > {t('lcenses.qualification', { ns: 'personal' })} Linking.openURL("https://beian.miit.gov.cn/")} > {t('lcenses.ICP', { ns: 'personal' })}沪ICP备2023032876号-4 {/* 其他信息 */} {t('generalSetting.otherInformation', { ns: 'personal' })} Linking.openURL("https://work.weixin.qq.com/kfid/kfca0ac87f4e05e8bfd")} > {t('generalSetting.contactUs', { ns: 'personal' })} {/* */} {t('generalSetting.version', { ns: 'personal' })} {"0.5.0"} {/* 退出 */} {t('generalSetting.logout', { ns: 'personal' })} {/* 协议弹窗 */} {/* 许可证弹窗 */} {/* 通知 */} {/* */} ); }; const styles = StyleSheet.create({ centeredView: { flex: 1, justifyContent: 'flex-end', backgroundColor: 'rgba(0,0,0,0.5)', }, modalView: { width: '100%', height: '80%', backgroundColor: 'white', borderTopLeftRadius: 20, borderTopRightRadius: 20, paddingHorizontal: 16, }, modalHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20, }, modalTitle: { fontSize: 20, fontWeight: 'bold', color: '#4C320C', }, closeButton: { fontSize: 28, color: '#4C320C', padding: 10, }, modalContent: { flex: 1, }, modalText: { fontSize: 16, color: '#4C320C', }, premium: { backgroundColor: "#FAF9F6", padding: 16, borderRadius: 24, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', }, content: { flex: 1, flexDirection: 'column', gap: 4, backgroundColor: '#FAF9F6', borderRadius: 24, paddingVertical: 8 }, item: { paddingHorizontal: 16, paddingVertical: 8, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', }, itemText: { fontSize: 14, fontWeight: '600', color: '#4C320C', }, upgradeButton: { backgroundColor: '#E2793F', borderRadius: 20, paddingHorizontal: 16, paddingVertical: 8, }, upgradeButtonText: { color: '#fff', fontSize: 14, fontWeight: "600" }, switchContainer: { width: 50, height: 30, borderRadius: 15, justifyContent: 'center', paddingHorizontal: 2, }, switchOn: { backgroundColor: '#E2793F', alignItems: 'flex-end', }, switchOff: { backgroundColor: '#E5E5E5', alignItems: 'flex-start', }, switchCircle: { width: 26, height: 26, borderRadius: 13, }, switchCircleOn: { backgroundColor: 'white', }, switchCircleOff: { backgroundColor: '#A5A5A5', }, }); const Divider = () => { return ( ) } export default SettingModal;