feat: 更新隐私同意弹窗和应用名称
- 将应用名称修改为“每日普拉提”,提升品牌识别度 - 新增隐私同意弹窗,确保用户在使用应用前同意隐私政策 - 更新 Redux 状态管理,添加隐私同意状态的处理 - 优化用户信息页面,确保体重和身高的格式化显示 - 更新今日训练页面标题为“快速训练”,提升用户体验 - 添加开发工具函数,便于测试隐私同意功能
This commit is contained in:
@@ -9,8 +9,8 @@ export type UserProfile = {
|
||||
email?: string;
|
||||
gender?: Gender;
|
||||
birthDate?: string;
|
||||
weight?: number;
|
||||
height?: number;
|
||||
weight?: string;
|
||||
height?: string;
|
||||
avatar?: string | null;
|
||||
dailyStepsGoal?: number; // 每日步数目标(用于 Explore 页等)
|
||||
dailyCaloriesGoal?: number; // 每日卡路里消耗目标
|
||||
@@ -22,6 +22,7 @@ export type UserState = {
|
||||
profile: UserProfile;
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
privacyAgreed: boolean;
|
||||
};
|
||||
|
||||
export const DEFAULT_MEMBER_NAME = '普拉提星球学员';
|
||||
@@ -33,6 +34,7 @@ const initialState: UserState = {
|
||||
},
|
||||
loading: false,
|
||||
error: null,
|
||||
privacyAgreed: false,
|
||||
};
|
||||
|
||||
export type LoginPayload = Record<string, any> & {
|
||||
@@ -105,22 +107,30 @@ export const login = createAsyncThunk(
|
||||
);
|
||||
|
||||
export const rehydrateUser = createAsyncThunk('user/rehydrate', async () => {
|
||||
const [token, profileStr] = await Promise.all([
|
||||
const [token, profileStr, privacyAgreedStr] = await Promise.all([
|
||||
loadPersistedToken(),
|
||||
AsyncStorage.getItem(STORAGE_KEYS.userProfile),
|
||||
AsyncStorage.getItem(STORAGE_KEYS.privacyAgreed),
|
||||
]);
|
||||
await setAuthToken(token);
|
||||
let profile: UserProfile = {};
|
||||
if (profileStr) {
|
||||
try { profile = JSON.parse(profileStr) as UserProfile; } catch { profile = {}; }
|
||||
}
|
||||
return { token, profile } as { token: string | null; profile: UserProfile };
|
||||
const privacyAgreed = privacyAgreedStr === 'true';
|
||||
return { token, profile, privacyAgreed } as { token: string | null; profile: UserProfile; privacyAgreed: boolean };
|
||||
});
|
||||
|
||||
export const setPrivacyAgreed = createAsyncThunk('user/setPrivacyAgreed', async () => {
|
||||
await AsyncStorage.setItem(STORAGE_KEYS.privacyAgreed, 'true');
|
||||
return true;
|
||||
});
|
||||
|
||||
export const logout = createAsyncThunk('user/logout', async () => {
|
||||
await Promise.all([
|
||||
AsyncStorage.removeItem(STORAGE_KEYS.authToken),
|
||||
AsyncStorage.removeItem(STORAGE_KEYS.userProfile),
|
||||
AsyncStorage.removeItem(STORAGE_KEYS.privacyAgreed),
|
||||
]);
|
||||
await setAuthToken(null);
|
||||
return true;
|
||||
@@ -176,6 +186,7 @@ const userSlice = createSlice({
|
||||
.addCase(rehydrateUser.fulfilled, (state, action) => {
|
||||
state.token = action.payload.token;
|
||||
state.profile = action.payload.profile;
|
||||
state.privacyAgreed = action.payload.privacyAgreed;
|
||||
if (!state.profile?.name || !state.profile.name.trim()) {
|
||||
state.profile.name = DEFAULT_MEMBER_NAME;
|
||||
}
|
||||
@@ -193,6 +204,10 @@ const userSlice = createSlice({
|
||||
.addCase(logout.fulfilled, (state) => {
|
||||
state.token = null;
|
||||
state.profile = {};
|
||||
state.privacyAgreed = false;
|
||||
})
|
||||
.addCase(setPrivacyAgreed.fulfilled, (state) => {
|
||||
state.privacyAgreed = true;
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user