feat: 样式调整+markdown渲染
This commit is contained in:
parent
6e83165e96
commit
e20aa93e44
@ -339,6 +339,17 @@ export default function TabLayout() {
|
|||||||
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* 设置页面 */}
|
||||||
|
<Tabs.Screen
|
||||||
|
name="setting"
|
||||||
|
options={{
|
||||||
|
title: 'setting',
|
||||||
|
tabBarButton: () => null, // 隐藏底部标签栏
|
||||||
|
headerShown: false, // 隐藏导航栏
|
||||||
|
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Tabs >
|
</Tabs >
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,10 +2,12 @@ import { fetchApi } from "@/lib/server-api-util";
|
|||||||
import { Policy } from "@/types/personal-info";
|
import { Policy } from "@/types/personal-info";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { ScrollView, StyleSheet, Text, TouchableOpacity, View } from "react-native";
|
import { ScrollView, StyleSheet, Text, TouchableOpacity, View } from "react-native";
|
||||||
import RenderHtml from 'react-native-render-html';
|
import Markdown from 'react-native-markdown-display';
|
||||||
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||||
|
|
||||||
const PrivacyPolicy = () => {
|
const PrivacyPolicy = () => {
|
||||||
const [article, setArticle] = useState<Policy>({} as Policy);
|
const [article, setArticle] = useState<Policy>({} as Policy);
|
||||||
|
const insets = useSafeAreaInsets();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadArticle = async () => {
|
const loadArticle = async () => {
|
||||||
fetchApi<Policy>(`/system-config/policy/privacy_policy`).then((res: any) => {
|
fetchApi<Policy>(`/system-config/policy/privacy_policy`).then((res: any) => {
|
||||||
@ -26,7 +28,7 @@ const PrivacyPolicy = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.centeredView}>
|
<View style={[styles.centeredView, { paddingTop: insets.top, marginBottom: insets.bottom }]}>
|
||||||
<View style={styles.modalView}>
|
<View style={styles.modalView}>
|
||||||
<View style={styles.modalHeader}>
|
<View style={styles.modalHeader}>
|
||||||
<Text style={{ opacity: 0 }}>Settings</Text>
|
<Text style={{ opacity: 0 }}>Settings</Text>
|
||||||
@ -36,14 +38,9 @@ const PrivacyPolicy = () => {
|
|||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
<ScrollView style={styles.modalContent} showsVerticalScrollIndicator={false}>
|
<ScrollView style={styles.modalContent} showsVerticalScrollIndicator={false}>
|
||||||
<RenderHtml
|
<Markdown>
|
||||||
source={{ html: article.content }}
|
{article.content}
|
||||||
tagsStyles={{
|
</Markdown>
|
||||||
p: { fontSize: 16, lineHeight: 24 },
|
|
||||||
strong: { fontWeight: 'bold' },
|
|
||||||
em: { fontStyle: 'italic' },
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
@ -86,6 +83,7 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
modalContent: {
|
modalContent: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
paddingHorizontal: 8
|
||||||
},
|
},
|
||||||
modalText: {
|
modalText: {
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { ThemedText } from '@/components/ThemedText';
|
|||||||
import { fetchApi } from '@/lib/server-api-util';
|
import { fetchApi } from '@/lib/server-api-util';
|
||||||
import { useLocalSearchParams, useRouter } from "expo-router";
|
import { useLocalSearchParams, useRouter } from "expo-router";
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { Image, StyleSheet, TouchableOpacity, View } from 'react-native';
|
import { Image, ScrollView, StyleSheet, TouchableOpacity, View } from 'react-native';
|
||||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||||
|
|
||||||
export default function Rights() {
|
export default function Rights() {
|
||||||
@ -43,59 +43,79 @@ export default function Rights() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[styles.container, { paddingTop: insets.top, paddingBottom: insets.bottom }]}>
|
<View style={{ flex: 1 }}>
|
||||||
{/* 导航栏 */}
|
<ScrollView style={[styles.container, { paddingTop: insets.top, paddingBottom: insets.bottom + 80 }]}>
|
||||||
<View
|
{/* 导航栏 */}
|
||||||
style={styles.header}
|
<View
|
||||||
>
|
style={styles.header}
|
||||||
<TouchableOpacity onPress={() => { router.push('/owner') }} style={{ padding: 16 }}>
|
>
|
||||||
<ReturnArrowSvg />
|
<TouchableOpacity onPress={() => { router.push('/owner') }} style={{ padding: 16 }}>
|
||||||
</TouchableOpacity>
|
<ReturnArrowSvg />
|
||||||
<ThemedText style={styles.headerTitle}>
|
</TouchableOpacity>
|
||||||
Subscription
|
<ThemedText style={styles.headerTitle}>
|
||||||
</ThemedText>
|
Subscription
|
||||||
<ThemedText className='opacity-0'>123</ThemedText>
|
</ThemedText>
|
||||||
</View>
|
<ThemedText className='opacity-0'>123</ThemedText>
|
||||||
{/* 会员卡 */}
|
</View>
|
||||||
<View style={styles.card}>
|
{/* 会员卡 */}
|
||||||
{userType === 'normal' ? (
|
<View style={styles.card}>
|
||||||
<Image source={require('@/assets/images/png/owner/normal.png')} style={{ height: 150, objectFit: 'cover', width: '100%' }} />
|
{userType === 'normal' ? (
|
||||||
) : (
|
<Image source={require('@/assets/images/png/owner/normal.png')} style={{ height: 150, objectFit: 'cover', width: '100%' }} />
|
||||||
<Image source={require('@/assets/images/png/owner/pro.png')} style={{ height: 150, objectFit: 'cover', width: '100%' }} />
|
) : (
|
||||||
)}
|
<Image source={require('@/assets/images/png/owner/pro.png')} style={{ height: 150, objectFit: 'cover', width: '100%' }} />
|
||||||
<View style={styles.cardContent}>
|
)}
|
||||||
<View style={styles.cardinfo}>
|
<View style={styles.cardContent}>
|
||||||
<ThemedText style={styles.cardTitle}>
|
<View style={styles.cardinfo}>
|
||||||
Purchase
|
<ThemedText style={styles.cardTitle}>
|
||||||
</ThemedText>
|
Purchase
|
||||||
<View style={styles.cardPoints}>
|
</ThemedText>
|
||||||
<StarSvg />
|
<View style={styles.cardPoints}>
|
||||||
<ThemedText style={styles.cardPointsText}>{credit}</ThemedText>
|
<StarSvg />
|
||||||
|
<ThemedText style={styles.cardPointsText}>{credit}</ThemedText>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
|
||||||
|
|
||||||
{/* 会员信息 */}
|
{/* 会员信息 */}
|
||||||
<View style={styles.info}>
|
<View style={styles.info}>
|
||||||
{/* 切换按钮 */}
|
{/* 切换按钮 */}
|
||||||
<View style={styles.switchButton}>
|
<View style={styles.switchButton}>
|
||||||
<TouchableOpacity onPress={() => { setUserType("normal") }} style={[styles.switchButtonItem, { backgroundColor: userType === 'normal' ? "#FFB645" : "#fff", borderColor: userType === 'normal' ? "#FFB645" : "#E2793F" }]}>
|
<TouchableOpacity
|
||||||
<ThemedText style={{ color: userType === 'normal' ? "#fff" : "#E2793F" }}>Free</ThemedText>
|
onPress={() => { setUserType("normal") }}
|
||||||
</TouchableOpacity>
|
style={[styles.switchButtonItem, { backgroundColor: userType === 'normal' ? "#FFB645" : "#fff", borderColor: userType === 'normal' ? "#FFB645" : "#E2793F" }]}
|
||||||
<TouchableOpacity onPress={() => { setUserType("premium") }} style={[styles.switchButtonItem, { backgroundColor: userType === 'premium' ? "#E2793F" : "#fff", borderColor: userType === 'premium' ? "#E2793F" : "#E2793F" }]}>
|
>
|
||||||
<ThemedText style={{ color: userType === 'premium' ? "#fff" : "#E2793F" }}> Pro</ThemedText>
|
<ThemedText style={{ color: userType === 'normal' ? "#fff" : "#E2793F" }}>Free</ThemedText>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={() => { setUserType("premium") }}
|
||||||
|
style={[styles.switchButtonItem, { backgroundColor: userType === 'premium' ? "#E2793F" : "#fff", borderColor: userType === 'premium' ? "#E2793F" : "#E2793F" }]}
|
||||||
|
>
|
||||||
|
<ThemedText style={{ color: userType === 'premium' ? "#fff" : "#E2793F" }}>Pro</ThemedText>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
{/* 普通权益 */}
|
||||||
|
<Normal setUserType={setUserType} style={{ display: userType === 'normal' ? "flex" : "none" }} />
|
||||||
|
{/* 会员权益 */}
|
||||||
|
<Premium setPayType={setPayType} setShowTerms={setShowTerms} payType={payType} premiumPay={premiumPay} loading={loading} style={{ display: userType === 'normal' ? "none" : "flex" }} />
|
||||||
</View>
|
</View>
|
||||||
{/* 普通权益 */}
|
{/* 会员权益信息 */}
|
||||||
<Normal setUserType={setUserType} style={{ display: userType === 'normal' ? "flex" : "none" }} />
|
<View style={{ flex: 1, marginBottom: 80 }}>
|
||||||
{/* 会员权益 */}
|
<ProRights style={{ display: userType === 'normal' ? "none" : "flex" }} />
|
||||||
<Premium setPayType={setPayType} setShowTerms={setShowTerms} payType={payType} premiumPay={premiumPay} loading={loading} style={{ display: userType === 'normal' ? "none" : "flex" }} />
|
</View>
|
||||||
</View>
|
</ScrollView>
|
||||||
{/* 会员权益信息 */}
|
|
||||||
<ProRights style={{ display: userType === 'normal' ? "none" : "flex" }} />
|
|
||||||
{/* 付费按钮 */}
|
{/* 付费按钮 */}
|
||||||
<View style={{ padding: 16, position: 'absolute', bottom: 0, left: 0, right: 0, display: userType === 'normal' ? "none" : "flex" }}>
|
<View style={{
|
||||||
|
padding: 16,
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
borderTopWidth: 1,
|
||||||
|
borderTopColor: '#eee',
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
display: userType === 'normal' ? "none" : "flex"
|
||||||
|
}}>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={styles.goPay}
|
style={styles.goPay}
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
@ -153,13 +173,14 @@ const styles = StyleSheet.create({
|
|||||||
marginVertical: 16,
|
marginVertical: 16,
|
||||||
padding: 16,
|
padding: 16,
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
shadowColor: "#000",
|
backgroundColor: '#fff',
|
||||||
|
shadowColor: '#000',
|
||||||
shadowOffset: {
|
shadowOffset: {
|
||||||
width: 0,
|
width: 0,
|
||||||
height: 2,
|
height: 2,
|
||||||
},
|
},
|
||||||
shadowOpacity: 0.25,
|
shadowOpacity: 0.25,
|
||||||
shadowRadius: 3.84,
|
shadowRadius: 5,
|
||||||
elevation: 5,
|
elevation: 5,
|
||||||
},
|
},
|
||||||
container: {
|
container: {
|
||||||
@ -216,6 +237,7 @@ const styles = StyleSheet.create({
|
|||||||
cardPointsText: {
|
cardPointsText: {
|
||||||
fontSize: 32,
|
fontSize: 32,
|
||||||
fontWeight: '700',
|
fontWeight: '700',
|
||||||
color: '#4C320C'
|
color: '#4C320C',
|
||||||
|
lineHeight: 32
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
495
app/(tabs)/setting.tsx
Normal file
495
app/(tabs)/setting.tsx
Normal file
@ -0,0 +1,495 @@
|
|||||||
|
import DeleteSvg from '@/assets/icons/svg/delete.svg';
|
||||||
|
import LogoutSvg from '@/assets/icons/svg/logout.svg';
|
||||||
|
import ReturnArrowSvg from '@/assets/icons/svg/returnArrow.svg';
|
||||||
|
import RightArrowSvg from '@/assets/icons/svg/rightArrow.svg';
|
||||||
|
import DeleteModal from '@/components/owner/delete';
|
||||||
|
import LcensesModal from '@/components/owner/qualification/lcenses';
|
||||||
|
import PrivacyModal from '@/components/owner/qualification/privacy';
|
||||||
|
import CustomSwitch from '@/components/owner/switch';
|
||||||
|
import UserInfo from '@/components/owner/userInfo';
|
||||||
|
import { checkNotificationPermission, getLocationPermission, getPermissions, requestLocationPermission, requestMediaLibraryPermission, requestNotificationPermission, reverseGeocode } from '@/components/owner/utils';
|
||||||
|
import { ThemedText } from '@/components/ThemedText';
|
||||||
|
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, Pressable, ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
||||||
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||||
|
|
||||||
|
const Setting = (props: { modalVisible: boolean, setModalVisible: (visible: boolean) => void, userInfo: User }) => {
|
||||||
|
const { modalVisible, setModalVisible, userInfo } = props;
|
||||||
|
const insets = useSafeAreaInsets();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [modalType, setModalType] = useState<'ai' | 'terms' | 'privacy' | 'user'>('ai');
|
||||||
|
// 协议弹窗
|
||||||
|
const [privacyModalVisible, setPrivacyModalVisible] = useState(false);
|
||||||
|
// 许可证弹窗
|
||||||
|
const [lcensesModalVisible, setLcensesModalVisible] = useState(false);
|
||||||
|
|
||||||
|
// 删除弹窗
|
||||||
|
const [deleteModalVisible, setDeleteModalVisible] = useState(false);
|
||||||
|
const { logout } = useAuth();
|
||||||
|
const router = useRouter();
|
||||||
|
// 打开设置
|
||||||
|
const openAppSettings = () => {
|
||||||
|
Linking.openSettings();
|
||||||
|
};
|
||||||
|
// 通知消息权限开关
|
||||||
|
const [notificationsEnabled, setNotificationsEnabled] = useState(false);
|
||||||
|
const toggleNotifications = async () => {
|
||||||
|
if (notificationsEnabled) {
|
||||||
|
// 引导去设置关闭权限
|
||||||
|
openAppSettings()
|
||||||
|
} else {
|
||||||
|
requestNotificationPermission()
|
||||||
|
.then((granted: boolean | ((prevState: boolean) => boolean)) => {
|
||||||
|
setNotificationsEnabled(granted);
|
||||||
|
});
|
||||||
|
setModalVisible(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 相册权限
|
||||||
|
const [albumEnabled, setAlbumEnabled] = useState(false);
|
||||||
|
const toggleAlbum = async () => {
|
||||||
|
if (albumEnabled) {
|
||||||
|
// 引导去设置关闭权限
|
||||||
|
openAppSettings()
|
||||||
|
} else {
|
||||||
|
requestMediaLibraryPermission()
|
||||||
|
.then((granted: boolean | ((prevState: boolean) => boolean)) => {
|
||||||
|
setAlbumEnabled(granted);
|
||||||
|
});
|
||||||
|
setModalVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 位置权限
|
||||||
|
const [locationEnabled, setLocationEnabled] = useState(false);
|
||||||
|
// 位置权限更改
|
||||||
|
const toggleLocation = async () => {
|
||||||
|
if (locationEnabled) {
|
||||||
|
// 如果权限已开启,点击则引导用户去设置关闭
|
||||||
|
openAppSettings();
|
||||||
|
} else {
|
||||||
|
requestLocationPermission()
|
||||||
|
.then((granted: boolean | ((prevState: boolean) => boolean)) => {
|
||||||
|
setLocationEnabled(granted);
|
||||||
|
});
|
||||||
|
setModalVisible(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 正在获取位置信息
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
// 动画开启
|
||||||
|
const [isRefreshing, setIsRefreshing] = useState(false);
|
||||||
|
|
||||||
|
// 当前位置状态
|
||||||
|
const [currentLocation, setCurrentLocation] = useState<Address>({} as Address);
|
||||||
|
|
||||||
|
// 获取当前位置
|
||||||
|
const getCurrentLocation = async () => {
|
||||||
|
setIsLoading(true);
|
||||||
|
setIsRefreshing(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. 首先检查当前权限状态 -- 获取当前的位置权限
|
||||||
|
let currentStatus = await getLocationPermission();
|
||||||
|
console.log('当前权限状态:', currentStatus);
|
||||||
|
|
||||||
|
// 2. 如果没有权限,则跳过获取位置
|
||||||
|
if (!currentStatus) {
|
||||||
|
console.log('没有权限,跳过获取位置')
|
||||||
|
return;
|
||||||
|
// 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. 更新位置状态
|
||||||
|
if (address) {
|
||||||
|
setCurrentLocation(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: boolean | ((prevState: boolean) => boolean)) => {
|
||||||
|
console.log('位置权限:', res);
|
||||||
|
setLocationEnabled(res);
|
||||||
|
})
|
||||||
|
// 媒体库权限
|
||||||
|
getPermissions().then((res: boolean | ((prevState: boolean) => boolean)) => {
|
||||||
|
console.log('媒体库权限:', res);
|
||||||
|
setAlbumEnabled(res);
|
||||||
|
})
|
||||||
|
// 通知权限
|
||||||
|
checkNotificationPermission().then((res: boolean | ((prevState: boolean) => boolean)) => {
|
||||||
|
console.log('通知权限:', res);
|
||||||
|
setNotificationsEnabled(res);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [modalVisible])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={{ flex: 1, paddingTop: insets.top, marginBottom: insets.bottom }}>
|
||||||
|
<Pressable
|
||||||
|
style={styles.centeredView}
|
||||||
|
>
|
||||||
|
<Pressable
|
||||||
|
style={styles.modalView}
|
||||||
|
onPress={(e) => e.stopPropagation()}>
|
||||||
|
<View style={styles.modalHeader}>
|
||||||
|
<TouchableOpacity onPress={() => { router.push('/owner') }}>
|
||||||
|
<ReturnArrowSvg />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<Text style={styles.modalTitle}>{t('generalSetting.allTitle', { ns: 'personal' })}</Text>
|
||||||
|
<Text style={{ opacity: 0 }}>×</Text>
|
||||||
|
</View>
|
||||||
|
<ScrollView style={styles.modalContent} showsVerticalScrollIndicator={false}>
|
||||||
|
{/* 用户信息 */}
|
||||||
|
<UserInfo
|
||||||
|
userInfo={userInfo}
|
||||||
|
setModalVisible={setModalVisible}
|
||||||
|
modalVisible={modalVisible}
|
||||||
|
setCurrentLocation={setCurrentLocation}
|
||||||
|
getCurrentLocation={getCurrentLocation}
|
||||||
|
isLoading={isLoading}
|
||||||
|
isRefreshing={isRefreshing}
|
||||||
|
currentLocation={currentLocation}
|
||||||
|
/>
|
||||||
|
{/* 升级版本 */}
|
||||||
|
{/* <View style={{ marginTop: 16 }}>
|
||||||
|
<ThemedText style={{ marginLeft: 16, marginVertical: 8, color: '#AC7E35', fontSize: 14, fontWeight: '600' }}>{t('generalSetting.subscription', { ns: 'personal' })}</ThemedText>
|
||||||
|
<View style={styles.premium}>
|
||||||
|
<View>
|
||||||
|
<ThemedText style={styles.itemText}>{t('generalSetting.subscriptionTitle', { ns: 'personal' })}</ThemedText>
|
||||||
|
<ThemedText style={{ color: '#AC7E35', fontSize: 12 }}>{t('generalSetting.subscriptionText', { ns: 'personal' })}</ThemedText>
|
||||||
|
</View>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={styles.upgradeButton}
|
||||||
|
onPress={async () => {
|
||||||
|
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text style={styles.upgradeButtonText}>
|
||||||
|
{t('generalSetting.upgrade', { ns: 'personal' })}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View> */}
|
||||||
|
{/* 消息通知 */}
|
||||||
|
{/* <View style={{ marginTop: 16 }}>
|
||||||
|
<ThemedText style={{ marginLeft: 16, marginVertical: 8, color: '#AC7E35', fontSize: 14, fontWeight: '600' }}>{t('permission.pushNotification', { ns: 'personal' })}</ThemedText>
|
||||||
|
<View style={styles.premium}>
|
||||||
|
<View>
|
||||||
|
<ThemedText style={styles.itemText}>{t('permission.pushNotification', { ns: 'personal' })}</ThemedText>
|
||||||
|
</View>
|
||||||
|
<CustomSwitch
|
||||||
|
isEnabled={notificationsEnabled}
|
||||||
|
toggleSwitch={toggleNotifications}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View> */}
|
||||||
|
{/* 权限信息 */}
|
||||||
|
<View style={{ marginTop: 16 }}>
|
||||||
|
<ThemedText style={{ marginLeft: 16, marginVertical: 8, color: '#AC7E35', fontSize: 14, fontWeight: '600' }}>{t('permission.permissionManagement', { ns: 'personal' })}</ThemedText>
|
||||||
|
<View style={styles.content}>
|
||||||
|
{/* 相册权限 */}
|
||||||
|
<View style={styles.item}>
|
||||||
|
<ThemedText style={styles.itemText}>{t('permission.galleryAccess', { ns: 'personal' })}</ThemedText>
|
||||||
|
<CustomSwitch
|
||||||
|
isEnabled={albumEnabled}
|
||||||
|
toggleSwitch={toggleAlbum}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
{/* 分割线 */}
|
||||||
|
<Divider />
|
||||||
|
{/* 位置权限 */}
|
||||||
|
<View style={styles.item}>
|
||||||
|
<View>
|
||||||
|
<ThemedText style={styles.itemText}>{t('permission.locationPermission', { ns: 'personal' })}</ThemedText>
|
||||||
|
</View>
|
||||||
|
<CustomSwitch
|
||||||
|
isEnabled={locationEnabled}
|
||||||
|
toggleSwitch={toggleLocation}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<Divider />
|
||||||
|
<View style={styles.item}>
|
||||||
|
<View>
|
||||||
|
<ThemedText style={styles.itemText}>{t('permission.pushNotification', { ns: 'personal' })}</ThemedText>
|
||||||
|
</View>
|
||||||
|
<CustomSwitch
|
||||||
|
isEnabled={notificationsEnabled}
|
||||||
|
toggleSwitch={toggleNotifications}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
{/* 相册成片权限 */}
|
||||||
|
{/* <View style={styles.item}>
|
||||||
|
<View>
|
||||||
|
<ThemedText style={styles.itemText}>Opus Permission</ThemedText>
|
||||||
|
</View>
|
||||||
|
<CustomSwitch
|
||||||
|
isEnabled={albumEnabled}
|
||||||
|
toggleSwitch={toggleAlbum}
|
||||||
|
/>
|
||||||
|
</View> */}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
{/* 账号 */}
|
||||||
|
{/* <View style={{ marginTop: 16 }}>
|
||||||
|
<ThemedText style={{ marginLeft: 16, marginVertical: 8, color: '#AC7E35', fontSize: 14, fontWeight: '600' }}>Account</ThemedText>
|
||||||
|
<View style={styles.content}>
|
||||||
|
<View style={styles.item}>
|
||||||
|
<View>
|
||||||
|
<ThemedText style={styles.itemText}>Notifications</ThemedText>
|
||||||
|
</View>
|
||||||
|
<CustomSwitch
|
||||||
|
isEnabled={notificationsEnabled}
|
||||||
|
toggleSwitch={toggleNotifications}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<Divider />
|
||||||
|
<View style={styles.item}>
|
||||||
|
<ThemedText style={styles.itemText}>Delete Account</ThemedText>
|
||||||
|
<DeleteSvg />
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View> */}
|
||||||
|
{/* 协议 */}
|
||||||
|
<View style={{ marginTop: 16 }}>
|
||||||
|
<ThemedText style={{ marginLeft: 16, marginVertical: 8, color: '#AC7E35', fontSize: 14, fontWeight: '600' }}>{t('lcenses.title', { ns: 'personal' })}</ThemedText>
|
||||||
|
<View style={styles.content}>
|
||||||
|
<TouchableOpacity style={styles.item} onPress={() => { setModalType('privacy'); setPrivacyModalVisible(true) }} >
|
||||||
|
<ThemedText style={styles.itemText}>{t('lcenses.privacyPolicy', { ns: 'personal' })}</ThemedText>
|
||||||
|
<RightArrowSvg />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<Divider />
|
||||||
|
<TouchableOpacity style={styles.item} onPress={() => { setModalType('terms'); setPrivacyModalVisible(true) }} >
|
||||||
|
<ThemedText style={styles.itemText}>{t('lcenses.applyPermission', { ns: 'personal' })}</ThemedText>
|
||||||
|
<RightArrowSvg />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<Divider />
|
||||||
|
<TouchableOpacity style={styles.item} onPress={() => { setModalType('user'); setPrivacyModalVisible(true) }} >
|
||||||
|
<ThemedText style={styles.itemText}>{t('lcenses.userAgreement', { ns: 'personal' })}</ThemedText>
|
||||||
|
<RightArrowSvg />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<Divider />
|
||||||
|
<TouchableOpacity style={styles.item} onPress={() => { setModalType('ai'); setPrivacyModalVisible(true) }} >
|
||||||
|
<ThemedText style={styles.itemText}>{t('lcenses.aiPolicy', { ns: 'personal' })}</ThemedText>
|
||||||
|
<RightArrowSvg />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<Divider />
|
||||||
|
<TouchableOpacity style={styles.item} onPress={() => { setLcensesModalVisible(true) }} >
|
||||||
|
<ThemedText style={styles.itemText}>{t('lcenses.qualification', { ns: 'personal' })}</ThemedText>
|
||||||
|
<RightArrowSvg />
|
||||||
|
</TouchableOpacity>
|
||||||
|
<Divider />
|
||||||
|
<TouchableOpacity style={styles.item} onPress={() => Linking.openURL("https://beian.miit.gov.cn/")} >
|
||||||
|
<ThemedText style={styles.itemText}>{t('lcenses.ICP', { ns: 'personal' })}沪ICP备2023032876号-4</ThemedText>
|
||||||
|
<RightArrowSvg />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
{/* 其他信息 */}
|
||||||
|
<View style={{ marginTop: 16 }}>
|
||||||
|
<ThemedText style={{ marginLeft: 16, marginVertical: 8, color: '#AC7E35', fontSize: 14, fontWeight: '600' }}>{t('generalSetting.otherInformation', { ns: 'personal' })}</ThemedText>
|
||||||
|
<View style={styles.content}>
|
||||||
|
<TouchableOpacity style={styles.item} onPress={() => Linking.openURL("https://work.weixin.qq.com/kfid/kfca0ac87f4e05e8bfd")} >
|
||||||
|
<ThemedText style={styles.itemText}>{t('generalSetting.contactUs', { ns: 'personal' })}</ThemedText>
|
||||||
|
{/* <RightArrowSvg /> */}
|
||||||
|
</TouchableOpacity>
|
||||||
|
<Divider />
|
||||||
|
<View style={styles.item}>
|
||||||
|
<ThemedText style={styles.itemText}>{t('generalSetting.version', { ns: 'personal' })}</ThemedText>
|
||||||
|
<ThemedText style={styles.itemText}>{"0.5.0"}</ThemedText>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
{/* 退出 */}
|
||||||
|
<TouchableOpacity style={[styles.premium, { marginVertical: 8 }]} onPress={handleLogout}>
|
||||||
|
<ThemedText style={{ color: '#E2793F', fontSize: 14, fontWeight: '600' }}>{t('generalSetting.logout', { ns: 'personal' })}</ThemedText>
|
||||||
|
<LogoutSvg />
|
||||||
|
</TouchableOpacity>
|
||||||
|
{/* 注销账号 */}
|
||||||
|
<TouchableOpacity style={[styles.premium, { marginVertical: 8 }]} onPress={() => setDeleteModalVisible(true)}>
|
||||||
|
<ThemedText style={{ color: '#E2793F', fontSize: 14, fontWeight: '600' }}>{t('generalSetting.deleteAccount', { ns: 'personal' })}</ThemedText>
|
||||||
|
<DeleteSvg />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</ScrollView>
|
||||||
|
</Pressable>
|
||||||
|
</Pressable>
|
||||||
|
<PrivacyModal modalVisible={privacyModalVisible} setModalVisible={setPrivacyModalVisible} type={modalType} />
|
||||||
|
<LcensesModal modalVisible={lcensesModalVisible} setModalVisible={setLcensesModalVisible} />
|
||||||
|
<DeleteModal modalVisible={deleteModalVisible} setModalVisible={setDeleteModalVisible} setSettingModalVisible={setModalVisible} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
centeredView: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
backgroundColor: 'rgba(0,0,0,0.5)',
|
||||||
|
},
|
||||||
|
modalView: {
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
backgroundColor: 'white',
|
||||||
|
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 (
|
||||||
|
<View className='w-full h-[1px] bg-[#B5977F]'></View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default Setting;
|
||||||
@ -11,10 +11,9 @@ interface CategoryProps {
|
|||||||
const AlbumComponent = ({ setModalVisible, style }: CategoryProps) => {
|
const AlbumComponent = ({ setModalVisible, style }: CategoryProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[styles.container, style]}>
|
<View style={[styles.container, style]}>
|
||||||
<TouchableOpacity style={{ flex: 3 }} onPress={() => { router.push("/download") }}>
|
<TouchableOpacity style={{ flex: 3 }}>
|
||||||
<ThemedText style={styles.text}>{t('generalSetting.album', { ns: 'personal' })}</ThemedText>
|
<ThemedText style={styles.text}>{t('generalSetting.album', { ns: 'personal' })}</ThemedText>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity style={{ flex: 3 }}>
|
<TouchableOpacity style={{ flex: 3 }}>
|
||||||
@ -22,7 +21,8 @@ const AlbumComponent = ({ setModalVisible, style }: CategoryProps) => {
|
|||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
setModalVisible(true);
|
// setModalVisible(true);
|
||||||
|
router.push('/setting');
|
||||||
}}
|
}}
|
||||||
activeOpacity={0.7}
|
activeOpacity={0.7}
|
||||||
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
|
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import BlackStarSvg from '@/assets/icons/svg/blackStar.svg';
|
import BlackStarSvg from '@/assets/icons/svg/blackStar.svg';
|
||||||
import { ThemedText } from "@/components/ThemedText";
|
import { ThemedText } from "@/components/ThemedText";
|
||||||
import { StyleProp, StyleSheet, TouchableOpacity, View, ViewStyle } from "react-native";
|
import { ScrollView, StyleProp, StyleSheet, TouchableOpacity, View, ViewStyle } from "react-native";
|
||||||
import { ScrollView } from 'react-native-gesture-handler';
|
|
||||||
import { maxDiscountProduct } from './utils';
|
import { maxDiscountProduct } from './utils';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -65,7 +64,7 @@ const Premium = (props: Props) => {
|
|||||||
<ThemedText style={[styles.titleText, { fontSize: 16 }]}>
|
<ThemedText style={[styles.titleText, { fontSize: 16 }]}>
|
||||||
{item.product_code?.split('_')[item.product_code?.split('_')?.length - 1]}
|
{item.product_code?.split('_')[item.product_code?.split('_')?.length - 1]}
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
<ThemedText style={[styles.titleText, { fontSize: 32 }]}>
|
<ThemedText style={[styles.titleText, { fontSize: 32, lineHeight: 32 }]}>
|
||||||
$ {item.unit_price.amount}
|
$ {item.unit_price.amount}
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
||||||
@ -104,22 +103,9 @@ const styles = StyleSheet.create({
|
|||||||
borderColor: "#FFB645",
|
borderColor: "#FFB645",
|
||||||
borderWidth: 2,
|
borderWidth: 2,
|
||||||
borderRadius: 24,
|
borderRadius: 24,
|
||||||
width: "48%",
|
width: 200,
|
||||||
paddingBottom: 16
|
paddingBottom: 16
|
||||||
},
|
},
|
||||||
quarterly: {
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
gap: 20,
|
|
||||||
borderColor: "#FAF9F6",
|
|
||||||
borderWidth: 2,
|
|
||||||
borderRadius: 24,
|
|
||||||
width: "48%",
|
|
||||||
paddingBottom: 16,
|
|
||||||
height: "100%",
|
|
||||||
},
|
|
||||||
title: {
|
title: {
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
|
|||||||
78
package-lock.json
generated
78
package-lock.json
generated
@ -57,6 +57,7 @@
|
|||||||
"react-native": "0.79.5",
|
"react-native": "0.79.5",
|
||||||
"react-native-gesture-handler": "~2.24.0",
|
"react-native-gesture-handler": "~2.24.0",
|
||||||
"react-native-linear-gradient": "^2.8.3",
|
"react-native-linear-gradient": "^2.8.3",
|
||||||
|
"react-native-markdown-display": "^7.0.2",
|
||||||
"react-native-modal": "^14.0.0-rc.1",
|
"react-native-modal": "^14.0.0-rc.1",
|
||||||
"react-native-picker-select": "^9.3.1",
|
"react-native-picker-select": "^9.3.1",
|
||||||
"react-native-progress": "^5.0.1",
|
"react-native-progress": "^5.0.1",
|
||||||
@ -12471,6 +12472,15 @@
|
|||||||
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
|
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/linkify-it": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"uc.micro": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/locate-path": {
|
"node_modules/locate-path": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
||||||
@ -12704,6 +12714,37 @@
|
|||||||
"tmpl": "1.0.5"
|
"tmpl": "1.0.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/markdown-it": {
|
||||||
|
"version": "10.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz",
|
||||||
|
"integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"argparse": "^1.0.7",
|
||||||
|
"entities": "~2.0.0",
|
||||||
|
"linkify-it": "^2.0.0",
|
||||||
|
"mdurl": "^1.0.1",
|
||||||
|
"uc.micro": "^1.0.5"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"markdown-it": "bin/markdown-it.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/markdown-it/node_modules/argparse": {
|
||||||
|
"version": "1.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||||
|
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"sprintf-js": "~1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/markdown-it/node_modules/entities": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==",
|
||||||
|
"license": "BSD-2-Clause"
|
||||||
|
},
|
||||||
"node_modules/marky": {
|
"node_modules/marky": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/marky/-/marky-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/marky/-/marky-1.3.0.tgz",
|
||||||
@ -12725,6 +12766,12 @@
|
|||||||
"integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==",
|
"integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==",
|
||||||
"license": "CC0-1.0"
|
"license": "CC0-1.0"
|
||||||
},
|
},
|
||||||
|
"node_modules/mdurl": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/memoize-one": {
|
"node_modules/memoize-one": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
|
||||||
@ -14964,6 +15011,15 @@
|
|||||||
"react-native": "*"
|
"react-native": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-native-fit-image": {
|
||||||
|
"version": "1.5.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-fit-image/-/react-native-fit-image-1.5.5.tgz",
|
||||||
|
"integrity": "sha512-Wl3Vq2DQzxgsWKuW4USfck9zS7YzhvLNPpkwUUCF90bL32e1a0zOVQ3WsJILJOwzmPdHfzZmWasiiAUNBkhNkg==",
|
||||||
|
"license": "Beerware",
|
||||||
|
"dependencies": {
|
||||||
|
"prop-types": "^15.5.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-native-gesture-handler": {
|
"node_modules/react-native-gesture-handler": {
|
||||||
"version": "2.24.0",
|
"version": "2.24.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.24.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.24.0.tgz",
|
||||||
@ -14999,6 +15055,22 @@
|
|||||||
"react-native": "*"
|
"react-native": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-native-markdown-display": {
|
||||||
|
"version": "7.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-markdown-display/-/react-native-markdown-display-7.0.2.tgz",
|
||||||
|
"integrity": "sha512-Mn4wotMvMfLAwbX/huMLt202W5DsdpMO/kblk+6eUs55S57VVNni1gzZCh5qpznYLjIQELNh50VIozEfY6fvaQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"css-to-react-native": "^3.0.0",
|
||||||
|
"markdown-it": "^10.0.0",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
|
"react-native-fit-image": "^1.5.5"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.2.0",
|
||||||
|
"react-native": ">=0.50.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-native-modal": {
|
"node_modules/react-native-modal": {
|
||||||
"version": "14.0.0-rc.1",
|
"version": "14.0.0-rc.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-modal/-/react-native-modal-14.0.0-rc.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-modal/-/react-native-modal-14.0.0-rc.1.tgz",
|
||||||
@ -17510,6 +17582,12 @@
|
|||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/uc.micro": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/unbox-primitive": {
|
"node_modules/unbox-primitive": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
|
||||||
|
|||||||
@ -63,6 +63,7 @@
|
|||||||
"react-native": "0.79.5",
|
"react-native": "0.79.5",
|
||||||
"react-native-gesture-handler": "~2.24.0",
|
"react-native-gesture-handler": "~2.24.0",
|
||||||
"react-native-linear-gradient": "^2.8.3",
|
"react-native-linear-gradient": "^2.8.3",
|
||||||
|
"react-native-markdown-display": "^7.0.2",
|
||||||
"react-native-modal": "^14.0.0-rc.1",
|
"react-native-modal": "^14.0.0-rc.1",
|
||||||
"react-native-picker-select": "^9.3.1",
|
"react-native-picker-select": "^9.3.1",
|
||||||
"react-native-progress": "^5.0.1",
|
"react-native-progress": "^5.0.1",
|
||||||
@ -75,10 +76,10 @@
|
|||||||
"react-native-svg": "^15.11.2",
|
"react-native-svg": "^15.11.2",
|
||||||
"react-native-toast-message": "^2.3.0",
|
"react-native-toast-message": "^2.3.0",
|
||||||
"react-native-uuid": "^2.0.3",
|
"react-native-uuid": "^2.0.3",
|
||||||
|
"react-native-view-shot": "4.0.3",
|
||||||
"react-native-web": "~0.20.0",
|
"react-native-web": "~0.20.0",
|
||||||
"react-native-webview": "13.13.5",
|
"react-native-webview": "13.13.5",
|
||||||
"react-redux": "^9.2.0",
|
"react-redux": "^9.2.0"
|
||||||
"react-native-view-shot": "4.0.3"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.25.2",
|
"@babel/core": "^7.25.2",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user