feat(profile): add chat settings and language options to profile settings
- Introduced hrefProfileChatSettings() for navigation to chat settings. - Updated SettingsScreen to include new settings items for chat settings, language selection, data storage, terms, and privacy policy. - Enhanced user experience by providing alerts for language and data storage options. This update improves the profile settings interface by adding more customization options for users.
This commit is contained in:
178
src/stores/user/UserManager.ts
Normal file
178
src/stores/user/UserManager.ts
Normal file
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* UserManager - 用户管ç<C2A1>†æ ¸å¿ƒæ¨¡å<C2A1>—(é‡<C3A9>构版ï¼?
|
||||
*
|
||||
* 使用 Zustand store 进行状æ€<C3A6>管ç<C2A1>?
|
||||
* ä¿<C3A4>æŒ<C3A6>与旧 API çš„å<E2809E>‘å<E28098>Žå…¼å®?
|
||||
*/
|
||||
|
||||
import type { UserDTO } from '../../types/dto';
|
||||
import { authService } from '../../services/authService';
|
||||
import {
|
||||
getCurrentUserCache,
|
||||
getUserCache,
|
||||
saveCurrentUserCache,
|
||||
saveUserCache,
|
||||
} from '../../services/database';
|
||||
import { useUserManagerStore } from './userStore';
|
||||
import { createCacheEntry, isCacheExpired, DEFAULT_TTL } from '../utils/cache';
|
||||
|
||||
// ==================== UserManager ç±?====================
|
||||
|
||||
class UserManager {
|
||||
/**
|
||||
* 获å<C2B7>–当å‰<C3A5>用户
|
||||
* 支æŒ<C3A6>缓å˜è¿‡æœŸæ£€æŸ¥å’Œå<C592>Žå<C5BD>°åˆ·æ–°
|
||||
*/
|
||||
async getCurrentUser(forceRefresh = false): Promise<UserDTO | null> {
|
||||
const store = useUserManagerStore.getState();
|
||||
const entry = store.currentUserEntry;
|
||||
|
||||
// 有效缓å˜
|
||||
if (!forceRefresh && entry && !isCacheExpired(entry)) {
|
||||
return entry.data;
|
||||
}
|
||||
|
||||
// 过期缓å˜ï¼šå<C5A1>Žå<C5BD>°åˆ·æ–°ï¼Œç«‹å<E280B9>³è¿”回旧数æ<C2B0>?
|
||||
if (!forceRefresh && entry && isCacheExpired(entry)) {
|
||||
this.refreshCurrentUserInBackground();
|
||||
return entry.data;
|
||||
}
|
||||
|
||||
// å°<C3A5>试从本地数æ<C2B0>®åº“åŠ è½½
|
||||
if (!forceRefresh) {
|
||||
const cachedFromDb = await getCurrentUserCache();
|
||||
if (cachedFromDb) {
|
||||
const newEntry = createCacheEntry(cachedFromDb, DEFAULT_TTL.USER);
|
||||
store.setCurrentUserEntry(newEntry);
|
||||
this.refreshCurrentUserInBackground();
|
||||
return cachedFromDb;
|
||||
}
|
||||
}
|
||||
|
||||
// å<>‘èµ· API 请求
|
||||
return this.dedupe('users:current', async () => {
|
||||
const user = await authService.fetchCurrentUserFromAPI();
|
||||
const newEntry = createCacheEntry(user, DEFAULT_TTL.USER);
|
||||
store.setCurrentUserEntry(newEntry);
|
||||
|
||||
if (user) {
|
||||
saveCurrentUserCache(user).catch(() => {});
|
||||
saveUserCache(user).catch(() => {});
|
||||
}
|
||||
return user;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* å<>Žå<C5BD>°åˆ·æ–°å½“å‰<C3A5>用户
|
||||
*/
|
||||
private refreshCurrentUserInBackground(): void {
|
||||
this.dedupe('users:current:bg', async () => {
|
||||
const store = useUserManagerStore.getState();
|
||||
const user = await authService.fetchCurrentUserFromAPI();
|
||||
const newEntry = createCacheEntry(user, DEFAULT_TTL.USER);
|
||||
store.setCurrentUserEntry(newEntry);
|
||||
|
||||
if (user) {
|
||||
saveCurrentUserCache(user).catch(() => {});
|
||||
saveUserCache(user).catch(() => {});
|
||||
}
|
||||
return user;
|
||||
}).catch((error) => {
|
||||
console.error('[UserManager] refreshCurrentUserInBackground error:', error);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* æ ¹æ<C2B9>® ID 获å<C2B7>–用户
|
||||
*/
|
||||
async getUserById(userId: string, forceRefresh = false): Promise<UserDTO | null> {
|
||||
const store = useUserManagerStore.getState();
|
||||
const entry = store.usersMap.get(userId);
|
||||
|
||||
// 有效缓å˜
|
||||
if (!forceRefresh && entry && !isCacheExpired(entry)) {
|
||||
return entry.data;
|
||||
}
|
||||
|
||||
// 过期缓å˜ï¼šå<C5A1>Žå<C5BD>°åˆ·æ–°ï¼Œç«‹å<E280B9>³è¿”回旧数æ<C2B0>?
|
||||
if (!forceRefresh && entry && isCacheExpired(entry)) {
|
||||
this.refreshUserByIdInBackground(userId);
|
||||
return entry.data;
|
||||
}
|
||||
|
||||
// å°<C3A5>试从本地数æ<C2B0>®åº“åŠ è½½
|
||||
if (!forceRefresh) {
|
||||
const cachedFromDb = await getUserCache(userId);
|
||||
if (cachedFromDb) {
|
||||
const newEntry = createCacheEntry(cachedFromDb, DEFAULT_TTL.USER);
|
||||
store.setUser(userId, cachedFromDb);
|
||||
this.refreshUserByIdInBackground(userId);
|
||||
return cachedFromDb;
|
||||
}
|
||||
}
|
||||
|
||||
// å<>‘èµ· API 请求
|
||||
return this.dedupe(`users:detail:${userId}`, async () => {
|
||||
const store = useUserManagerStore.getState();
|
||||
const user = await authService.fetchUserByIdFromAPI(userId);
|
||||
const newEntry = createCacheEntry(user, DEFAULT_TTL.USER);
|
||||
store.setUser(userId, user);
|
||||
|
||||
if (user) {
|
||||
saveUserCache(user).catch(() => {});
|
||||
}
|
||||
return user;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* å<>Žå<C5BD>°åˆ·æ–°ç”¨æˆ·
|
||||
*/
|
||||
private refreshUserByIdInBackground(userId: string): void {
|
||||
this.dedupe(`users:detail:bg:${userId}`, async () => {
|
||||
const store = useUserManagerStore.getState();
|
||||
const user = await authService.fetchUserByIdFromAPI(userId);
|
||||
const newEntry = createCacheEntry(user, DEFAULT_TTL.USER);
|
||||
store.setUser(userId, user);
|
||||
|
||||
if (user) {
|
||||
saveUserCache(user).catch(() => {});
|
||||
}
|
||||
return user;
|
||||
}).catch((error) => {
|
||||
console.error('[UserManager] refreshUserByIdInBackground error:', error);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 使缓å˜å¤±æ•?
|
||||
*/
|
||||
invalidateUsers(): void {
|
||||
useUserManagerStore.getState().invalidateAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求去é‡<C3A9>
|
||||
*/
|
||||
private async dedupe<T>(key: string, fetcher: () => Promise<T>): Promise<T> {
|
||||
const store = useUserManagerStore.getState();
|
||||
const pending = store.getPendingRequest<T>(key);
|
||||
if (pending) return pending;
|
||||
|
||||
const request = fetcher().finally(() => {
|
||||
useUserManagerStore.getState().deletePendingRequest(key);
|
||||
});
|
||||
store.setPendingRequest(key, request);
|
||||
return request;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== å<>•例导出 ====================
|
||||
|
||||
export const userManager = new UserManager();
|
||||
|
||||
// 导出类以支æŒ<C3A6>类型检查和测试
|
||||
export { UserManager };
|
||||
|
||||
export default userManager;
|
||||
Reference in New Issue
Block a user