feat: userInfo
This commit is contained in:
parent
006db2af07
commit
521a4d0a51
@ -16,7 +16,7 @@ import { fetchApi } from '@/lib/server-api-util';
|
|||||||
import { CountData, UserInfoDetails } from '@/types/user';
|
import { CountData, UserInfoDetails } from '@/types/user';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ScrollView, StyleSheet, View } from 'react-native';
|
import { FlatList, ScrollView, StyleSheet, View } from 'react-native';
|
||||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||||
export default function OwnerPage() {
|
export default function OwnerPage() {
|
||||||
const insets = useSafeAreaInsets();
|
const insets = useSafeAreaInsets();
|
||||||
@ -59,10 +59,13 @@ export default function OwnerPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[styles.container, { paddingTop: insets.top }]}>
|
<View style={[styles.container, { paddingTop: insets.top }]}>
|
||||||
<ScrollView
|
<FlatList
|
||||||
|
data={[]} // 空数据,因为我们只需要渲染一次
|
||||||
|
renderItem={null} // 不需要渲染项目
|
||||||
|
contentContainerStyle={styles.contentContainer}
|
||||||
showsVerticalScrollIndicator={false}
|
showsVerticalScrollIndicator={false}
|
||||||
contentContainerStyle={{ flexGrow: 1, gap: 16, marginHorizontal: 16 }}
|
ListHeaderComponent={
|
||||||
>
|
<View style={{ gap: 16 }}>
|
||||||
{/* 用户信息 */}
|
{/* 用户信息 */}
|
||||||
<UserInfo userInfo={userInfoDetails} />
|
<UserInfo userInfo={userInfoDetails} />
|
||||||
|
|
||||||
@ -104,9 +107,9 @@ export default function OwnerPage() {
|
|||||||
|
|
||||||
{/* 排行榜 */}
|
{/* 排行榜 */}
|
||||||
<Ranking data={userInfoDetails.title_rankings} />
|
<Ranking data={userInfoDetails.title_rankings} />
|
||||||
|
</View>
|
||||||
</ScrollView>
|
}
|
||||||
|
/>
|
||||||
{/* 设置弹窗 */}
|
{/* 设置弹窗 */}
|
||||||
<SettingModal modalVisible={modalVisible} setModalVisible={setModalVisible} userInfo={userInfoDetails.user_info} />
|
<SettingModal modalVisible={modalVisible} setModalVisible={setModalVisible} userInfo={userInfoDetails.user_info} />
|
||||||
|
|
||||||
@ -122,6 +125,9 @@ const styles = StyleSheet.create({
|
|||||||
backgroundColor: 'white',
|
backgroundColor: 'white',
|
||||||
paddingBottom: 86,
|
paddingBottom: 86,
|
||||||
},
|
},
|
||||||
|
contentContainer: {
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
},
|
||||||
resourceContainer: {
|
resourceContainer: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
gap: 16
|
gap: 16
|
||||||
|
|||||||
38
components/copy.tsx
Normal file
38
components/copy.tsx
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import Ionicons from '@expo/vector-icons/Ionicons';
|
||||||
|
import * as Clipboard from 'expo-clipboard';
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { StyleSheet, TouchableOpacity } from 'react-native';
|
||||||
|
|
||||||
|
const CopyButton = ({ textToCopy }: { textToCopy: string }) => {
|
||||||
|
const [isCopied, setIsCopied] = useState(false);
|
||||||
|
|
||||||
|
const handleCopy = async () => {
|
||||||
|
await Clipboard.setStringAsync(textToCopy);
|
||||||
|
setIsCopied(true);
|
||||||
|
setTimeout(() => setIsCopied(false), 2000);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TouchableOpacity onPress={handleCopy} style={styles.button}>
|
||||||
|
{isCopied ? (
|
||||||
|
<Ionicons name="checkmark-circle" size={12} color="#FFB645" />
|
||||||
|
) : (
|
||||||
|
<Ionicons name="copy-outline" size={12} color="#333" />
|
||||||
|
)}
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
button: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
padding: 4,
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
marginLeft: 8,
|
||||||
|
fontSize: 16,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default CopyButton;
|
||||||
@ -7,6 +7,7 @@ import { useAuth } from "../../contexts/auth-context";
|
|||||||
import { fetchApi } from "../../lib/server-api-util";
|
import { fetchApi } from "../../lib/server-api-util";
|
||||||
import { User } from "../../types/user";
|
import { User } from "../../types/user";
|
||||||
import { ThemedText } from "../ThemedText";
|
import { ThemedText } from "../ThemedText";
|
||||||
|
import PrivacyModal from "../owner/qualification/privacy";
|
||||||
|
|
||||||
interface LoginProps {
|
interface LoginProps {
|
||||||
updateUrlParam: (status: string, value: string) => void;
|
updateUrlParam: (status: string, value: string) => void;
|
||||||
@ -25,7 +26,9 @@ const SignUp = ({ updateUrlParam, setError, setShowPassword, showPassword }: Log
|
|||||||
const [passwordsMatch, setPasswordsMatch] = useState(true);
|
const [passwordsMatch, setPasswordsMatch] = useState(true);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [checked, setChecked] = useState(false);
|
const [checked, setChecked] = useState(false);
|
||||||
|
const [modalType, setModalType] = useState<'ai' | 'terms' | 'privacy' | 'user'>('ai');
|
||||||
|
// 协议弹窗
|
||||||
|
const [privacyModalVisible, setPrivacyModalVisible] = useState(false);
|
||||||
// 从 URL 参数中获取 task_id 和 steps
|
// 从 URL 参数中获取 task_id 和 steps
|
||||||
const params = useLocalSearchParams<{ task_id?: string; steps?: string }>();
|
const params = useLocalSearchParams<{ task_id?: string; steps?: string }>();
|
||||||
const taskId = params.task_id;
|
const taskId = params.task_id;
|
||||||
@ -263,10 +266,10 @@ const SignUp = ({ updateUrlParam, setError, setShowPassword, showPassword }: Log
|
|||||||
<ThemedText className="text-sm !text-textPrimary">
|
<ThemedText className="text-sm !text-textPrimary">
|
||||||
{t("auth.telLogin.agree", { ns: 'login' })}
|
{t("auth.telLogin.agree", { ns: 'login' })}
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
<TouchableOpacity onPress={() => router.push({
|
<TouchableOpacity onPress={() => {
|
||||||
pathname: '/agreement',
|
setModalType('terms');
|
||||||
params: { type: 'service' }
|
setPrivacyModalVisible(true);
|
||||||
} as any)}>
|
}}>
|
||||||
<ThemedText className="text-sm !text-[#E2793F]">
|
<ThemedText className="text-sm !text-[#E2793F]">
|
||||||
{t("auth.telLogin.terms", { ns: 'login' })}
|
{t("auth.telLogin.terms", { ns: 'login' })}
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
@ -274,10 +277,10 @@ const SignUp = ({ updateUrlParam, setError, setShowPassword, showPassword }: Log
|
|||||||
<ThemedText className="text-sm !text-textPrimary">
|
<ThemedText className="text-sm !text-textPrimary">
|
||||||
{t("auth.telLogin.and", { ns: 'login' })}
|
{t("auth.telLogin.and", { ns: 'login' })}
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
<TouchableOpacity onPress={() => router.push({
|
<TouchableOpacity onPress={() => {
|
||||||
pathname: '/agreement',
|
setModalType('privacy');
|
||||||
params: { type: 'privacy' }
|
setPrivacyModalVisible(true);
|
||||||
} as any)}>
|
}}>
|
||||||
<ThemedText className="text-sm !text-[#E2793F]">
|
<ThemedText className="text-sm !text-[#E2793F]">
|
||||||
{t("auth.telLogin.privacyPolicy", { ns: 'login' })}
|
{t("auth.telLogin.privacyPolicy", { ns: 'login' })}
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
@ -285,14 +288,25 @@ const SignUp = ({ updateUrlParam, setError, setShowPassword, showPassword }: Log
|
|||||||
<ThemedText className="text-sm !text-textPrimary">
|
<ThemedText className="text-sm !text-textPrimary">
|
||||||
{t("auth.telLogin.and", { ns: 'login' })}
|
{t("auth.telLogin.and", { ns: 'login' })}
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
<TouchableOpacity onPress={() => router.push({
|
<TouchableOpacity onPress={() => {
|
||||||
pathname: '/agreement',
|
setModalType('user');
|
||||||
params: { type: 'user' }
|
setPrivacyModalVisible(true);
|
||||||
} as any)}>
|
}}>
|
||||||
<ThemedText className="text-sm !text-[#E2793F]">
|
<ThemedText className="text-sm !text-[#E2793F]">
|
||||||
{t("auth.telLogin.userAgreement", { ns: 'login' })}
|
{t("auth.telLogin.userAgreement", { ns: 'login' })}
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
<ThemedText className="text-sm !text-textPrimary">
|
||||||
|
{t("auth.telLogin.and", { ns: 'login' })}
|
||||||
|
</ThemedText>
|
||||||
|
<TouchableOpacity onPress={() => {
|
||||||
|
setModalType('ai');
|
||||||
|
setPrivacyModalVisible(true);
|
||||||
|
}}>
|
||||||
|
<ThemedText className="text-sm !text-[#E2793F]">
|
||||||
|
{t("auth.telLogin.aiAgreement", { ns: 'login' })}
|
||||||
|
</ThemedText>
|
||||||
|
</TouchableOpacity>
|
||||||
<ThemedText className="text-sm !text-textPrimary">
|
<ThemedText className="text-sm !text-textPrimary">
|
||||||
{t("auth.telLogin.agreement", { ns: 'login' })}
|
{t("auth.telLogin.agreement", { ns: 'login' })}
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
@ -319,6 +333,9 @@ const SignUp = ({ updateUrlParam, setError, setShowPassword, showPassword }: Log
|
|||||||
</ThemedText>
|
</ThemedText>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
{/* 协议弹窗 */}
|
||||||
|
<PrivacyModal modalVisible={privacyModalVisible} setModalVisible={setPrivacyModalVisible} type={modalType} />
|
||||||
</View>
|
</View>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { fetchApi } from '@/lib/server-api-util';
|
import { fetchApi } from '@/lib/server-api-util';
|
||||||
import { Policy } from '@/types/personal-info';
|
import { Policy } from '@/types/personal-info';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { Modal, Pressable, ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
import { Modal, ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
||||||
import RenderHtml from 'react-native-render-html';
|
import RenderHtml from 'react-native-render-html';
|
||||||
|
|
||||||
const PrivacyModal = (props: { modalVisible: boolean, setModalVisible: (visible: boolean) => void, type: string }) => {
|
const PrivacyModal = (props: { modalVisible: boolean, setModalVisible: (visible: boolean) => void, type: string }) => {
|
||||||
@ -62,12 +62,8 @@ const PrivacyModal = (props: { modalVisible: boolean, setModalVisible: (visible:
|
|||||||
onRequestClose={() => {
|
onRequestClose={() => {
|
||||||
setModalVisible(!modalVisible);
|
setModalVisible(!modalVisible);
|
||||||
}}>
|
}}>
|
||||||
<Pressable
|
<View style={styles.centeredView}>
|
||||||
style={styles.centeredView}
|
<View style={styles.modalView}>
|
||||||
onPress={() => setModalVisible(false)}>
|
|
||||||
<Pressable
|
|
||||||
style={styles.modalView}
|
|
||||||
onPress={(e) => e.stopPropagation()}>
|
|
||||||
<View style={styles.modalHeader}>
|
<View style={styles.modalHeader}>
|
||||||
<Text style={{ opacity: 0 }}>Settings</Text>
|
<Text style={{ opacity: 0 }}>Settings</Text>
|
||||||
<Text style={styles.modalTitle}>{type === 'ai' ? 'AI Policy' : type === 'terms' ? 'Terms of Service' : type === 'privacy' ? 'Privacy Policy' : 'User Agreement'}</Text>
|
<Text style={styles.modalTitle}>{type === 'ai' ? 'AI Policy' : type === 'terms' ? 'Terms of Service' : type === 'privacy' ? 'Privacy Policy' : 'User Agreement'}</Text>
|
||||||
@ -85,9 +81,8 @@ const PrivacyModal = (props: { modalVisible: boolean, setModalVisible: (visible:
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</Pressable>
|
</View>
|
||||||
</Pressable>
|
</View>
|
||||||
|
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,25 +1,26 @@
|
|||||||
import UserSvg from '@/assets/icons/svg/ataver.svg';
|
import UserSvg from '@/assets/icons/svg/ataver.svg';
|
||||||
import { ThemedText } from '@/components/ThemedText';
|
import { ThemedText } from '@/components/ThemedText';
|
||||||
import { UserInfoDetails } from '@/types/user';
|
import { UserInfoDetails } from '@/types/user';
|
||||||
// import { Image } from 'expo-image';
|
import { useState } from 'react';
|
||||||
import { Image, ScrollView, View } from 'react-native';
|
import { Image, ScrollView, View } from 'react-native';
|
||||||
export default function UserInfo({ userInfo }: { userInfo: UserInfoDetails }) {
|
export default function UserInfo({ userInfo }: { userInfo: UserInfoDetails }) {
|
||||||
|
// 添加状态来跟踪图片加载状态
|
||||||
|
const [imageError, setImageError] = useState(false);
|
||||||
return (
|
return (
|
||||||
<View className='flex flex-row items-center mt-[1rem] gap-[1rem]'>
|
<View className='flex flex-row justify-between items-center mt-[1rem] gap-[1rem] w-full'>
|
||||||
{/* 用户名 */}
|
{/* 用户名 */}
|
||||||
<View className='flex flex-col gap-4 w-[68vw]'>
|
<View className='flex flex-col gap-4 w-[75%]'>
|
||||||
<View className='flex flex-row items-center justify-between w-full'>
|
<View className='flex flex-row items-center justify-between w-full'>
|
||||||
<View className='flex flex-row items-center gap-2'>
|
<View className='flex flex-row items-center gap-2 w-full'>
|
||||||
<ThemedText
|
<ThemedText
|
||||||
className='max-w-[36vw] !text-textSecondary !font-semibold !text-2xl'
|
className='max-w-[80%] !text-textSecondary !font-semibold !text-2xl'
|
||||||
numberOfLines={1} // 限制为1行
|
numberOfLines={1} // 限制为1行
|
||||||
ellipsizeMode="tail"
|
ellipsizeMode="tail"
|
||||||
>
|
>
|
||||||
{userInfo?.user_info?.nickname}
|
{userInfo?.user_info?.nickname}
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
<ScrollView
|
<ScrollView
|
||||||
className='max-w-[26vw] '
|
className='max-w-[20%]'
|
||||||
horizontal // 水平滚动
|
horizontal // 水平滚动
|
||||||
showsHorizontalScrollIndicator={false} // 隐藏滚动条
|
showsHorizontalScrollIndicator={false} // 隐藏滚动条
|
||||||
contentContainerStyle={{
|
contentContainerStyle={{
|
||||||
@ -40,8 +41,9 @@ export default function UserInfo({ userInfo }: { userInfo: UserInfoDetails }) {
|
|||||||
</ScrollView>
|
</ScrollView>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
<View>
|
||||||
<ScrollView
|
<ScrollView
|
||||||
className='max-w-[68vw]'
|
className='max-w-[85%]'
|
||||||
horizontal // 水平滚动
|
horizontal // 水平滚动
|
||||||
showsHorizontalScrollIndicator={false} // 隐藏滚动条
|
showsHorizontalScrollIndicator={false} // 隐藏滚动条
|
||||||
contentContainerStyle={{
|
contentContainerStyle={{
|
||||||
@ -49,20 +51,29 @@ export default function UserInfo({ userInfo }: { userInfo: UserInfoDetails }) {
|
|||||||
gap: 8 // 间距
|
gap: 8 // 间距
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ThemedText style={{ color: '#AC7E35', fontSize: 12, fontWeight: '600' }}>User ID:{userInfo?.user_info?.user_id}</ThemedText>
|
<ThemedText style={{ color: '#AC7E35', fontSize: 12, fontWeight: '600' }}>User ID: {userInfo?.user_info?.user_id}</ThemedText>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
{/* <CopyButton textToCopy={userInfo?.user_info?.user_id || ""} /> */}
|
||||||
|
</View>
|
||||||
|
|
||||||
</View>
|
</View>
|
||||||
{/* 头像 */}
|
{/* 头像 */}
|
||||||
<View>
|
<View className='w-auto'>
|
||||||
{userInfo?.user_info?.avatar_file_url
|
{userInfo?.user_info?.avatar_file_url && !imageError ? (
|
||||||
?
|
|
||||||
<Image
|
<Image
|
||||||
source={{ uri: userInfo?.user_info?.avatar_file_url }}
|
source={{ uri: userInfo.user_info.avatar_file_url }}
|
||||||
style={{ width: 80, height: 80, borderRadius: 40 }}
|
style={{ width: 80, height: 80, borderRadius: 40 }}
|
||||||
|
onError={() => {
|
||||||
|
console.log('图片加载失败:', userInfo.user_info.avatar_file_url);
|
||||||
|
setImageError(true);
|
||||||
|
}}
|
||||||
|
onLoad={() => {
|
||||||
|
console.log('图片加载成功');
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
:
|
) : (
|
||||||
<UserSvg width={80} height={80} />
|
<UserSvg width={80} height={80} />
|
||||||
}
|
)}
|
||||||
</View>
|
</View>
|
||||||
</View >
|
</View >
|
||||||
);
|
);
|
||||||
|
|||||||
@ -48,7 +48,8 @@
|
|||||||
"codeVaild": "The code you entered is invalid",
|
"codeVaild": "The code you entered is invalid",
|
||||||
"sendAgain": "Did’nt receive a code?",
|
"sendAgain": "Did’nt receive a code?",
|
||||||
"resend": "Resend",
|
"resend": "Resend",
|
||||||
"goBack": "Go Back"
|
"goBack": "Go Back",
|
||||||
|
"aiAgreement": "AI Function Usage Norms"
|
||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"title": "Log in",
|
"title": "Log in",
|
||||||
|
|||||||
@ -48,7 +48,8 @@
|
|||||||
"codeValid": "您输入的验证码无效",
|
"codeValid": "您输入的验证码无效",
|
||||||
"sendAgain": "没有收到验证码?",
|
"sendAgain": "没有收到验证码?",
|
||||||
"resend": "重新发送",
|
"resend": "重新发送",
|
||||||
"goBack": "返回"
|
"goBack": "返回",
|
||||||
|
"aiAgreement": "《AI功能使用规范》"
|
||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"title": "登录",
|
"title": "登录",
|
||||||
|
|||||||
45
package-lock.json
generated
45
package-lock.json
generated
@ -18,6 +18,7 @@
|
|||||||
"expo-audio": "~0.4.7",
|
"expo-audio": "~0.4.7",
|
||||||
"expo-background-fetch": "^13.1.6",
|
"expo-background-fetch": "^13.1.6",
|
||||||
"expo-blur": "~14.1.5",
|
"expo-blur": "~14.1.5",
|
||||||
|
"expo-clipboard": "~7.1.5",
|
||||||
"expo-constants": "~17.1.6",
|
"expo-constants": "~17.1.6",
|
||||||
"expo-dev-client": "~5.2.1",
|
"expo-dev-client": "~5.2.1",
|
||||||
"expo-device": "~7.1.4",
|
"expo-device": "~7.1.4",
|
||||||
@ -3360,18 +3361,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@react-native-async-storage/async-storage": {
|
|
||||||
"version": "2.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-2.2.0.tgz",
|
|
||||||
"integrity": "sha512-gvRvjR5JAaUZF8tv2Kcq/Gbt3JHwbKFYfmb445rhOj6NUMx3qPLixmDx5pZAyb9at1bYvJ4/eTUipU5aki45xw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"merge-options": "^3.0.4"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"react-native": "^0.0.0-0 || >=0.65 <1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@react-native-picker/picker": {
|
"node_modules/@react-native-picker/picker": {
|
||||||
"version": "2.11.1",
|
"version": "2.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/@react-native-picker/picker/-/picker-2.11.1.tgz",
|
"resolved": "https://registry.npmjs.org/@react-native-picker/picker/-/picker-2.11.1.tgz",
|
||||||
@ -7835,6 +7824,17 @@
|
|||||||
"react-native": "*"
|
"react-native": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/expo-clipboard": {
|
||||||
|
"version": "7.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/expo-clipboard/-/expo-clipboard-7.1.5.tgz",
|
||||||
|
"integrity": "sha512-TCANUGOxouoJXxKBW5ASJl2WlmQLGpuZGemDCL2fO5ZMl57DGTypUmagb0CVUFxDl0yAtFIcESd78UsF9o64aw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"expo": "*",
|
||||||
|
"react": "*",
|
||||||
|
"react-native": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/expo-constants": {
|
"node_modules/expo-constants": {
|
||||||
"version": "17.1.7",
|
"version": "17.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-17.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-17.1.7.tgz",
|
||||||
@ -9743,15 +9743,6 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/is-plain-obj": {
|
|
||||||
"version": "2.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
|
|
||||||
"integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/is-regex": {
|
"node_modules/is-regex": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
|
||||||
@ -10819,18 +10810,6 @@
|
|||||||
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==",
|
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/merge-options": {
|
|
||||||
"version": "3.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz",
|
|
||||||
"integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"is-plain-obj": "^2.1.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/merge-stream": {
|
"node_modules/merge-stream": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||||
|
|||||||
@ -29,7 +29,6 @@
|
|||||||
"expo-file-system": "~18.1.10",
|
"expo-file-system": "~18.1.10",
|
||||||
"expo-font": "~13.3.1",
|
"expo-font": "~13.3.1",
|
||||||
"expo-haptics": "~14.1.4",
|
"expo-haptics": "~14.1.4",
|
||||||
"expo-image": "~2.3.2",
|
|
||||||
"expo-image-manipulator": "~13.1.7",
|
"expo-image-manipulator": "~13.1.7",
|
||||||
"expo-image-picker": "~16.1.4",
|
"expo-image-picker": "~16.1.4",
|
||||||
"expo-linking": "~7.1.5",
|
"expo-linking": "~7.1.5",
|
||||||
@ -69,7 +68,8 @@
|
|||||||
"react-native-uuid": "^2.0.3",
|
"react-native-uuid": "^2.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",
|
||||||
|
"expo-clipboard": "~7.1.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.25.2",
|
"@babel/core": "^7.25.2",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user