refactor(database): migrate to new modular database layer and unify data access
All checks were successful
Frontend CI / build-and-push-web (push) Successful in 2m44s
Frontend CI / ota-android (push) Successful in 12m51s
Frontend CI / build-android-apk (push) Successful in 1h1m26s

- Remove legacy database.ts, LocalDataSource.ts, and MessageRepository.ts
- Create new src/database/ module with messageRepository, userCacheRepository, conversationRepository, and groupCacheRepository
- Update all consumers to import from @/database instead of services/database
- Add web platform blur handling for modal components to fix focus issues
- Flatten SystemMessageItem and NotificationsScreen styles for consistent design
- Add draggable slider in ChatSettingsScreen and dynamic font size support
- Introduce 9 new chat color themes
- Add profile screens for about, terms, and privacy policy with navigation routes
- Add policy links to login and registration screens
- Fix post share URL format from /posts/ to /post/
This commit is contained in:
lafay
2026-04-04 08:01:45 +08:00
parent 189b977fac
commit 82c2970a85
76 changed files with 3382 additions and 2000 deletions

View File

@@ -1,46 +1,34 @@
/**
* UserManager - 用户管ç<EFBFBD>†æ ¸å¿ƒæ¨¡å<EFBFBD>—(é‡<EFBFBD>构版ï¼?
* UserManager - 用户管理核心模块(重构版)
*
* 使用 Zustand store è¿è¡Œçжæ€<EFBFBD>管ç<EFBFBD>?
* ä¿<EFBFBD>æŒ<EFBFBD>与旧 API çš„å<E2809E>å<E28098>Žå…¼å®?
* 使用 Zustand store 进行状态管理
* 保持与旧 API 的向后兼容
*/
import type { UserDTO } from '../../types/dto';
import { authService } from '../../services/authService';
import {
getCurrentUserCache,
getUserCache,
saveCurrentUserCache,
saveUserCache,
} from '../../services/database';
import { userCacheRepository } from '@/database';
import { useUserManagerStore } from './userStore';
import { createCacheEntry, isCacheExpired, DEFAULT_TTL } from '../utils/cache';
// ==================== UserManager ç±?====================
// ==================== 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();
const cachedFromDb = await userCacheRepository.getCurrent();
if (cachedFromDb) {
const newEntry = createCacheEntry(cachedFromDb, DEFAULT_TTL.USER);
store.setCurrentUserEntry(newEntry);
@@ -49,23 +37,19 @@ class UserManager {
}
}
// å<>èµ· 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(() => {});
userCacheRepository.saveCurrent(user).catch(() => {});
userCacheRepository.save(user).catch(() => {});
}
return user;
});
}
/**
* å<>Žå<C5BD>°åˆ·æ°å½“å‰<C3A5>用户
*/
private refreshCurrentUserInBackground(): void {
this.dedupe('users:current:bg', async () => {
const store = useUserManagerStore.getState();
@@ -74,8 +58,8 @@ class UserManager {
store.setCurrentUserEntry(newEntry);
if (user) {
saveCurrentUserCache(user).catch(() => {});
saveUserCache(user).catch(() => {});
userCacheRepository.saveCurrent(user).catch(() => {});
userCacheRepository.save(user).catch(() => {});
}
return user;
}).catch((error) => {
@@ -83,27 +67,21 @@ class UserManager {
});
}
/**
* æ ¹æ<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);
const cachedFromDb = await userCacheRepository.get(userId);
if (cachedFromDb) {
const newEntry = createCacheEntry(cachedFromDb, DEFAULT_TTL.USER);
store.setUser(userId, cachedFromDb);
@@ -112,7 +90,6 @@ class UserManager {
}
}
// å<>èµ· API 请求
return this.dedupe(`users:detail:${userId}`, async () => {
const store = useUserManagerStore.getState();
const user = await authService.fetchUserByIdFromAPI(userId);
@@ -120,15 +97,12 @@ class UserManager {
store.setUser(userId, user);
if (user) {
saveUserCache(user).catch(() => {});
userCacheRepository.save(user).catch(() => {});
}
return user;
});
}
/**
* å<>Žå<C5BD>°åˆ·æ°ç”¨æˆ·
*/
private refreshUserByIdInBackground(userId: string): void {
this.dedupe(`users:detail:bg:${userId}`, async () => {
const store = useUserManagerStore.getState();
@@ -137,7 +111,7 @@ class UserManager {
store.setUser(userId, user);
if (user) {
saveUserCache(user).catch(() => {});
userCacheRepository.save(user).catch(() => {});
}
return user;
}).catch((error) => {
@@ -145,16 +119,10 @@ class UserManager {
});
}
/**
* 使缓存失�
*/
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);
@@ -168,11 +136,8 @@ class UserManager {
}
}
// ==================== å<>•ä¾å¯¼å‡º ====================
export const userManager = new UserManager();
// 导出类以支æŒ<C3A6>ç±»åžæ£€æŸ¥åŒæµè¯•
export { UserManager };
export default userManager;
export default userManager;