feat: setting

This commit is contained in:
jinyaqiu 2025-07-17 17:35:12 +08:00
parent 521a4d0a51
commit e68e8b7141
9 changed files with 82 additions and 73 deletions

View File

@ -1,4 +1,5 @@
import ConversationsSvg from '@/assets/icons/svg/conversations.svg';
import MoreArrowSvg from '@/assets/icons/svg/moreArrow.svg';
import PointsSvg from '@/assets/icons/svg/points.svg';
import StoriesSvg from '@/assets/icons/svg/stories.svg';
import UsedStorageSvg from '@/assets/icons/svg/usedStorage.svg';
@ -74,8 +75,11 @@ export default function OwnerPage() {
{/* 资源数据 */}
<View style={styles.resourceContainer}>
<ResourceComponent title={t("generalSetting.usedStorage", { ns: "personal" })} subtitle={`${countData?.counter?.total_count?.video_count || 0}videos/${countData?.counter?.total_count?.photo_count || 0}photos`} data={{ all: userInfoDetails.total_bytes, used: countData.used_bytes }} icon={<UsedStorageSvg />} style={{ flex: 1 }} isFormatBytes={true} />
<ResourceComponent title={t("generalSetting.remainingPoints", { ns: "personal" })} data={{ all: userInfoDetails.total_points, used: userInfoDetails.remain_points }} icon={<PointsSvg />} style={{ flex: 1 }} />
<View style={{ gap: 16 }}>
<ResourceComponent title={t("generalSetting.usedStorage", { ns: "personal" })} data={{ all: userInfoDetails.total_bytes, used: countData.used_bytes }} icon={<UsedStorageSvg />} isFormatBytes={true} />
<ResourceComponent title={t("generalSetting.remainingPoints", { ns: "personal" })} data={{ all: userInfoDetails.total_points, used: userInfoDetails.remain_points }} icon={<PointsSvg />} />
</View>
<MoreArrowSvg />
</View>
{/* 数据统计 */}
<CountComponent
@ -130,7 +134,12 @@ const styles = StyleSheet.create({
},
resourceContainer: {
flexDirection: 'row',
gap: 16
alignItems: 'center',
justifyContent: 'space-between',
gap: 16,
backgroundColor: "#FAF9F6",
padding: 16,
borderRadius: 18,
},
userInfo: {
flexDirection: 'row',

View File

@ -0,0 +1,3 @@
<svg width="11" height="20" viewBox="0 0 11 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.0002 1L9.77832 9.77812L1.0002 18.5562" stroke="#4C320C" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 237 B

View File

@ -27,9 +27,7 @@ const Ranking = ({ data }: { data: TitleRankings[] }) => {
renderItem={({ item }) => (
<View style={styles.item}>
<ThemedText style={styles.rank}>No.{item.ranking}</ThemedText>
<ThemedText style={styles.title}>{item.region}</ThemedText>
<ThemedText style={styles.title}>{item.display_name}</ThemedText>
<ThemedText style={styles.number}>{item.value}</ThemedText>
<ThemedText style={styles.title}>{item.region}{item.display_name}</ThemedText>
</View>
)}
/>
@ -73,8 +71,8 @@ const styles = StyleSheet.create({
flexDirection: 'row',
alignItems: 'center',
width: "100%",
justifyContent: 'space-between',
paddingVertical: 8, // 建议加行高
justifyContent: 'space-between',
},
rank: {
fontSize: 20,
@ -86,7 +84,6 @@ const styles = StyleSheet.create({
fontSize: 16,
fontWeight: '700',
color: '#4C320C',
flex: 1,
marginHorizontal: 8, // 新增
},
number: {

View File

@ -1,4 +1,4 @@
import { StyleProp, StyleSheet, View, ViewStyle } from "react-native";
import { Dimensions, StyleProp, StyleSheet, View, ViewStyle } from "react-native";
import * as Progress from 'react-native-progress';
import { ThemedText } from "../ThemedText";
import { formatBytes } from "../utils/bytes";
@ -17,29 +17,20 @@ interface ResourceProps {
isFormatBytes?: boolean;
}
const ResourceComponent = (props: ResourceProps) => {
// 获取设备的宽度
const width = Dimensions.get("window").width;
return (
<View style={[styles.container, props.style]}>
<View style={styles.header}>
<View>
<View style={styles.content}>
<View style={styles.titleContent}>
<ThemedText style={styles.title} className="!text-textSecondary">{props.title}</ThemedText>
<ThemedText style={styles.subtitle} className="!text-textPrimary">{props.subtitle || " "}</ThemedText>
<Progress.Bar progress={props.data.used / props.data.all} width={width * 0.5} color="#AC7E35" unfilledColor="#fff" borderWidth={0} borderRadius={8} height={2} />
</View>
<View>
<View style={styles.dataContainer}>
<ThemedText style={styles.dataText}>{props.isFormatBytes ? formatBytes(props.data.used) : props.data.used}/{props.isFormatBytes ? formatBytes(props.data.all) : props.data.all}</ThemedText>
{props.icon}
</View>
</View>
<View style={styles.dataContainer}>
<ThemedText style={styles.dataText}>{props.isFormatBytes ? formatBytes(props.data.used) : props.data.used}/{props.isFormatBytes ? formatBytes(props.data.all) : props.data.all}</ThemedText>
<Progress.Bar
progress={props.data.used / props.data.all}
width={"100%"}
color="#AC7E35"
unfilledColor="#ddd"
borderWidth={0}
borderRadius={8}
height={2}
/>
</View>
</View>
);
};
@ -47,25 +38,35 @@ const ResourceComponent = (props: ResourceProps) => {
const styles = StyleSheet.create({
container: {
width: "100%",
backgroundColor: "#FAF9F6",
padding: 16,
borderRadius: 18,
position: "relative",
},
header: {
content: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
},
titleContent: {
width: "90%",
flexDirection: "row",
alignItems: "center",
gap: 16,
},
title: {
fontSize: 12,
fontWeight: "700",
width: 100
},
subtitle: {
fontSize: 10,
fontWeight: "400",
},
dataContainer: {
flexDirection: "column",
position: "absolute",
right: 0,
top: -16,
flexDirection: "row",
alignItems: "center",
gap: 8,
},
dataText: {
fontSize: 12,

View File

@ -7,7 +7,7 @@ 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, Platform, Pressable, ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
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';
@ -205,7 +205,7 @@ const SettingModal = (props: { modalVisible: boolean, setModalVisible: (visible:
currentLocation={currentLocation}
/>
{/* 升级版本 */}
<View style={{ marginTop: 16 }}>
{/* <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>
@ -223,9 +223,9 @@ const SettingModal = (props: { modalVisible: boolean, setModalVisible: (visible:
</Text>
</TouchableOpacity>
</View>
</View>
</View> */}
{/* 消息通知 */}
<View style={{ marginTop: 16 }}>
{/* <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>
@ -236,7 +236,7 @@ const SettingModal = (props: { modalVisible: boolean, setModalVisible: (visible:
toggleSwitch={toggleNotifications}
/>
</View>
</View>
</View> */}
{/* 权限信息 */}
<View style={{ marginTop: 16 }}>
<ThemedText style={{ marginLeft: 16, marginVertical: 8, color: '#AC7E35', fontSize: 14, fontWeight: '600' }}>{t('permission.permissionManagement', { ns: 'personal' })}</ThemedText>
@ -261,7 +261,16 @@ const SettingModal = (props: { modalVisible: boolean, setModalVisible: (visible:
toggleSwitch={toggleLocation}
/>
</View>
{/* <Divider /> */}
<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>
@ -298,26 +307,11 @@ const SettingModal = (props: { modalVisible: boolean, setModalVisible: (visible:
<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={() => { 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>
<Divider />
<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('ai'); setPrivacyModalVisible(true) }} >
<ThemedText style={styles.itemText}>{t('lcenses.aiPolicy', { 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 />
@ -327,6 +321,21 @@ const SettingModal = (props: { modalVisible: boolean, setModalVisible: (visible:
<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>
{/* 其他信息 */}
@ -338,15 +347,6 @@ const SettingModal = (props: { modalVisible: boolean, setModalVisible: (visible:
{/* <RightArrowSvg /> */}
</TouchableOpacity>
<Divider />
{Platform.OS !== 'ios' && (
<View>
<TouchableOpacity style={styles.item} onPress={() => Linking.openURL("https://work.weixin.qq.com/kfid/kfca0ac87f4e05e8bfd")} >
<ThemedText style={styles.itemText}>{t('generalSetting.cleanCache', { ns: 'personal' })}</ThemedText>
{/* <RightArrowSvg /> */}
</TouchableOpacity>
<Divider />
</View>
)}
<View style={styles.item}>
<ThemedText style={styles.itemText}>{t('generalSetting.version', { ns: 'personal' })}</ThemedText>
<ThemedText style={styles.itemText}>{"0.5.0"}</ThemedText>

View File

@ -64,12 +64,8 @@ export default function UserInfo({ userInfo }: { userInfo: UserInfoDetails }) {
source={{ uri: userInfo.user_info.avatar_file_url }}
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} />

View File

@ -82,6 +82,7 @@
"live": "Live Photos",
"videoLength": "Video Duration",
"storiesCreated": "Stories Created",
"conversationsWithMemo": "Conversations with Memo"
"conversationsWithMemo": "Conversations with Memo",
"setting": "Settings"
}
}

View File

@ -40,30 +40,30 @@
"otherLcenses": "其他协议",
"userAgreement": "用户协议",
"privacyPolicy": "隐私政策",
"aiPolicy": "AI功能使用规范",
"applyPermission": "申请使用权限",
"aiPolicy": "AI功能使用规范",
"applyPermission": "服务协议",
"qualification": "资质证照"
},
"permission": {
"permissionManagement": "权限管理设置",
"permissionManagement": "权限管理",
"pushNotification": "推送权限",
"galleryAccess": "相册权限",
"locationPermission": "位置权限",
"personalizedRecommendation": "个性化推荐设置"
"personalizedRecommendation": "个性化推荐"
},
"generalSetting": {
"title": "通用设置",
"permissionManagement": "权限管理设置",
"permissionManagement": "权限管理",
"pushNotification": "推送权限",
"galleryAccess": "相册权限",
"personalizedRecommendation": "个性化推荐设置",
"personalizedRecommendation": "个性化推荐",
"deleteAccount": "注销账号",
"logout": "退出登录",
"upgrade": "升级",
"subscription": "订阅",
"subscriptionTitle": "MemoWake Premium",
"subscriptionText": "Unlock more of what you love",
"otherInformation": "其他信息",
"otherInformation": "通用设置",
"contactUs": "联系客服",
"version": "版本号",
"cleanCache": "清理缓存",
@ -82,6 +82,7 @@
"live": "动图",
"videoLength": "视频时长",
"storiesCreated": "创作视频",
"conversationsWithMemo": "Memo对话"
"conversationsWithMemo": "Memo对话",
"setting": "设置"
}
}

View File

@ -54,6 +54,7 @@ export interface UserInfoDetails {
remain_points: number,
total_points: number,
title_rankings: TitleRankings[],
total_bytes: number,
medal_infos: {
"id": number,
"url": string