refactor(database): migrate to new modular database layer and unify data access
- 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:
@@ -1,10 +1,3 @@
|
||||
/**
|
||||
* GroupManager - 蝢斤<E89DA2>蝞∠<E89D9E><E288A0>詨<EFBFBD>璅∪<E79285>嚗<EFBFBD><E59A97><EFBFBD><EFBFBD><EFBFBD>嚗?
|
||||
*
|
||||
* 雿輻鍂 Zustand store 餈𥡝<E9A488><F0A5A19D>嗆<EFBFBD><E59786>恣<EFBFBD>?
|
||||
* 靽脲<E99DBD>銝擧唂 API <20><><EFBFBD><EFBFBD>𤾸<EFBFBD>摰?
|
||||
*/
|
||||
|
||||
import type {
|
||||
GroupListResponse,
|
||||
GroupMemberListResponse,
|
||||
@@ -12,15 +5,7 @@ import type {
|
||||
GroupResponse,
|
||||
} from '../../types/dto';
|
||||
import { groupService } from '../../services/groupService';
|
||||
import {
|
||||
getAllGroupsCache,
|
||||
getGroupCache,
|
||||
getGroupMembersCache,
|
||||
saveGroupCache,
|
||||
saveGroupMembersCache,
|
||||
saveGroupsCache,
|
||||
saveUsersCache,
|
||||
} from '../../services/database';
|
||||
import { groupCacheRepository, userCacheRepository } from '@/database';
|
||||
import { useGroupManagerStore } from './groupStore';
|
||||
import { createCacheEntry, isCacheExpired, DEFAULT_TTL } from '../utils/cache';
|
||||
import {
|
||||
@@ -33,8 +18,6 @@ import {
|
||||
GROUP_MEMBER_LIST_PAGE_SIZE,
|
||||
} from '../groupListSources';
|
||||
|
||||
// ==================== 颲<>𨭌<EFBFBD>賣㺭 ====================
|
||||
|
||||
function buildMembersKey(groupId: string, page: number, pageSize: number): string {
|
||||
return `members:${groupId}:${page}:${pageSize}`;
|
||||
}
|
||||
@@ -63,14 +46,7 @@ function buildMemberListResponse(
|
||||
};
|
||||
}
|
||||
|
||||
// ==================== GroupManager 蝐?====================
|
||||
|
||||
class GroupManager {
|
||||
// ==================== 蝢斤<E89DA2><E696A4>𡑒”<F0A19192>詨<EFBFBD> ====================
|
||||
|
||||
/**
|
||||
* <20>瑕<EFBFBD>蝢斤<E89DA2><E696A4>𡑒”
|
||||
*/
|
||||
async getGroups(
|
||||
page = 1,
|
||||
pageSize = GROUP_LIST_PAGE_SIZE,
|
||||
@@ -79,20 +55,17 @@ class GroupManager {
|
||||
const store = useGroupManagerStore.getState();
|
||||
const entry = store.groupsListEntry;
|
||||
|
||||
// 蝚砌<E89D9A>憿萎<E686BF><E8908E>㗇<EFBFBD><E39787><EFBFBD><EFBFBD>摮?
|
||||
if (page === 1 && !forceRefresh && entry && !isCacheExpired(entry)) {
|
||||
return buildGroupListResponse(entry.data, pageSize);
|
||||
}
|
||||
|
||||
// 蝚砌<E89D9A>憿萎<E686BF>蝻枏<E89DBB>餈<EFBFBD><E9A488>嚗𡁜<E59A97><F0A1819C>啣<EFBFBD><E595A3>?
|
||||
if (page === 1 && !forceRefresh && entry && isCacheExpired(entry)) {
|
||||
this.refreshGroupsInBackground(page, pageSize);
|
||||
return buildGroupListResponse(entry.data, pageSize);
|
||||
}
|
||||
|
||||
// 蝚砌<E89D9A>憿蛛<E686BF>撠肽<E692A0><E882BD>砍𧑐蝻枏<E89DBB>
|
||||
if (page === 1 && !forceRefresh) {
|
||||
const localGroups = await getAllGroupsCache();
|
||||
const localGroups = await groupCacheRepository.getAll();
|
||||
if (localGroups.length > 0) {
|
||||
const newEntry = createCacheEntry(localGroups, DEFAULT_TTL.GROUP);
|
||||
store.setGroupsListEntry(newEntry);
|
||||
@@ -101,7 +74,6 @@ class GroupManager {
|
||||
}
|
||||
}
|
||||
|
||||
// <20>𤏸絲霂瑟<E99C82>
|
||||
return this.dedupe(`groups:list:${page}:${pageSize}`, async () => {
|
||||
const store = useGroupManagerStore.getState();
|
||||
const response = await groupService.getGroups(page, pageSize);
|
||||
@@ -109,7 +81,7 @@ class GroupManager {
|
||||
if (page === 1) {
|
||||
store.setGroupsList(groups);
|
||||
}
|
||||
await saveGroupsCache(groups).catch(() => {});
|
||||
await groupCacheRepository.saveBatch(groups).catch(() => {});
|
||||
return response;
|
||||
});
|
||||
}
|
||||
@@ -122,16 +94,13 @@ class GroupManager {
|
||||
if (page === 1) {
|
||||
store.setGroupsList(groups);
|
||||
}
|
||||
saveGroupsCache(groups).catch(() => {});
|
||||
groupCacheRepository.saveBatch(groups).catch(() => {});
|
||||
return response;
|
||||
}).catch((error) => {
|
||||
console.error('[GroupManager] refreshGroupsInBackground error:', error);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* <20>𥕦遣蝢斤<E89DA2><E696A4>𡑒”<F0A19192>唳旿皞琜<E79A9E><E7909C>其<EFBFBD> Sources 璅∪<E79285>嚗?
|
||||
*/
|
||||
createGroupListSource(
|
||||
kind: RemoteGroupListSourceKind = 'cursor',
|
||||
pageSize: number = GROUP_LIST_PAGE_SIZE
|
||||
@@ -139,29 +108,21 @@ class GroupManager {
|
||||
return createRemoteGroupListSource(kind, pageSize);
|
||||
}
|
||||
|
||||
// ==================== 蝢斤<E89DA2>霂行<E99C82><E8A18C>詨<EFBFBD> ====================
|
||||
|
||||
/**
|
||||
* <20>瑕<EFBFBD>蝢斤<E89DA2>霂行<E99C82>
|
||||
*/
|
||||
async getGroup(groupId: string, forceRefresh = false): Promise<GroupResponse> {
|
||||
const store = useGroupManagerStore.getState();
|
||||
const entry = store.groupsMap.get(groupId);
|
||||
|
||||
// <20>㗇<EFBFBD>蝻枏<E89DBB>
|
||||
if (!forceRefresh && entry && !isCacheExpired(entry)) {
|
||||
return entry.data;
|
||||
}
|
||||
|
||||
// 餈<><E9A488>蝻枏<E89DBB>嚗𡁜<E59A97><F0A1819C>啣<EFBFBD><E595A3>?
|
||||
if (!forceRefresh && entry && isCacheExpired(entry)) {
|
||||
this.refreshGroupInBackground(groupId);
|
||||
return entry.data;
|
||||
}
|
||||
|
||||
// 撠肽<E692A0><E882BD>砍𧑐蝻枏<E89DBB>
|
||||
if (!forceRefresh) {
|
||||
const localGroup = await getGroupCache(groupId);
|
||||
const localGroup = await groupCacheRepository.get(groupId);
|
||||
if (localGroup) {
|
||||
store.setGroup(groupId, localGroup);
|
||||
this.refreshGroupInBackground(groupId);
|
||||
@@ -169,12 +130,11 @@ class GroupManager {
|
||||
}
|
||||
}
|
||||
|
||||
// <20>𤏸絲霂瑟<E99C82>
|
||||
return this.dedupe(`groups:detail:${groupId}`, async () => {
|
||||
const store = useGroupManagerStore.getState();
|
||||
const group = await groupService.getGroup(groupId);
|
||||
store.setGroup(groupId, group);
|
||||
await saveGroupCache(group).catch(() => {});
|
||||
await groupCacheRepository.save(group).catch(() => {});
|
||||
return group;
|
||||
});
|
||||
}
|
||||
@@ -184,18 +144,13 @@ class GroupManager {
|
||||
const store = useGroupManagerStore.getState();
|
||||
const group = await groupService.getGroup(groupId);
|
||||
store.setGroup(groupId, group);
|
||||
saveGroupCache(group).catch(() => {});
|
||||
groupCacheRepository.save(group).catch(() => {});
|
||||
return group;
|
||||
}).catch((error) => {
|
||||
console.error('[GroupManager] refreshGroupInBackground error:', error);
|
||||
});
|
||||
}
|
||||
|
||||
// ==================== 蝢斤<E89DA2><E696A4>𣂼<EFBFBD><F0A382BC>詨<EFBFBD> ====================
|
||||
|
||||
/**
|
||||
* <20>瑕<EFBFBD>蝢斤<E89DA2><E696A4>𣂼<EFBFBD><F0A382BC>𡑒”
|
||||
*/
|
||||
async getMembers(
|
||||
groupId: string,
|
||||
page = 1,
|
||||
@@ -206,20 +161,17 @@ class GroupManager {
|
||||
const store = useGroupManagerStore.getState();
|
||||
const entry = store.membersMap.get(key);
|
||||
|
||||
// <20>㗇<EFBFBD>蝻枏<E89DBB>
|
||||
if (!forceRefresh && entry && !isCacheExpired(entry)) {
|
||||
return buildMemberListResponse(entry.data, page, pageSize);
|
||||
}
|
||||
|
||||
// 餈<><E9A488>蝻枏<E89DBB>嚗𡁜<E59A97><F0A1819C>啣<EFBFBD><E595A3>?
|
||||
if (!forceRefresh && entry && isCacheExpired(entry)) {
|
||||
this.refreshMembersInBackground(groupId, page, pageSize);
|
||||
return buildMemberListResponse(entry.data, page, pageSize);
|
||||
}
|
||||
|
||||
// 蝚砌<E89D9A>憿蛛<E686BF>撠肽<E692A0><E882BD>砍𧑐蝻枏<E89DBB>
|
||||
if (page === 1 && !forceRefresh) {
|
||||
const localMembers = await getGroupMembersCache(groupId);
|
||||
const localMembers = await groupCacheRepository.getMembers(groupId);
|
||||
if (localMembers.length > 0) {
|
||||
store.setMembers(groupId, localMembers, page, pageSize);
|
||||
this.refreshMembersInBackground(groupId, page, pageSize);
|
||||
@@ -227,16 +179,15 @@ class GroupManager {
|
||||
}
|
||||
}
|
||||
|
||||
// <20>𤏸絲霂瑟<E99C82>
|
||||
return this.dedupe(`groups:members:${key}`, async () => {
|
||||
const store = useGroupManagerStore.getState();
|
||||
const response = await groupService.getMembers(groupId, page, pageSize);
|
||||
const members = response.list || [];
|
||||
store.setMembers(groupId, members, page, pageSize);
|
||||
if (page === 1) {
|
||||
await saveGroupMembersCache(groupId, members).catch(() => {});
|
||||
await groupCacheRepository.saveMembers(groupId, members).catch(() => {});
|
||||
}
|
||||
await saveUsersCache(
|
||||
await userCacheRepository.saveBatch(
|
||||
members
|
||||
.map((member) => member.user)
|
||||
.filter((user): user is NonNullable<typeof user> => Boolean(user))
|
||||
@@ -257,9 +208,9 @@ class GroupManager {
|
||||
const members = response.list || [];
|
||||
store.setMembers(groupId, members, page, pageSize);
|
||||
if (page === 1) {
|
||||
saveGroupMembersCache(groupId, members).catch(() => {});
|
||||
groupCacheRepository.saveMembers(groupId, members).catch(() => {});
|
||||
}
|
||||
saveUsersCache(
|
||||
userCacheRepository.saveBatch(
|
||||
members
|
||||
.map((member) => member.user)
|
||||
.filter((user): user is NonNullable<typeof user> => Boolean(user))
|
||||
@@ -270,9 +221,6 @@ class GroupManager {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* <20>𥕦遣蝢斤<E89DA2><E696A4>𣂼<EFBFBD><F0A382BC>𡑒”<F0A19192>唳旿皞琜<E79A9E><E7909C>其<EFBFBD> Sources 璅∪<E79285>嚗?
|
||||
*/
|
||||
createGroupMemberListSource(
|
||||
groupId: string,
|
||||
kind: RemoteGroupListSourceKind = 'cursor',
|
||||
@@ -281,11 +229,6 @@ class GroupManager {
|
||||
return createRemoteGroupMemberListSource(groupId, kind, pageSize);
|
||||
}
|
||||
|
||||
// ==================== 蝻枏<E89DBB>蝞∠<E89D9E> ====================
|
||||
|
||||
/**
|
||||
* 雿輻<E99BBF>摮睃仃<E79D83>?
|
||||
*/
|
||||
invalidate(groupId?: string): void {
|
||||
if (!groupId) {
|
||||
useGroupManagerStore.getState().invalidateAll();
|
||||
@@ -294,15 +237,10 @@ class GroupManager {
|
||||
useGroupManagerStore.getState().invalidateGroup(groupId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 皜<>膄<EFBFBD><E88684><EFBFBD>㗇㺭<E39787>?
|
||||
*/
|
||||
clear(): void {
|
||||
useGroupManagerStore.getState().reset();
|
||||
}
|
||||
|
||||
// ==================== 霂瑟<E99C82><E7919F>駁<EFBFBD> ====================
|
||||
|
||||
private async dedupe<T>(key: string, fetcher: () => Promise<T>): Promise<T> {
|
||||
const store = useGroupManagerStore.getState();
|
||||
const pending = store.getPendingRequest<T>(key);
|
||||
@@ -316,11 +254,8 @@ class GroupManager {
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== <20>蓥<EFBFBD>撖澆枂 ====================
|
||||
|
||||
export const groupManager = new GroupManager();
|
||||
|
||||
// 撖澆枂蝐颱誑<E9A2B1>舀<EFBFBD>蝐餃<E89D90>璉<EFBFBD><E79289>亙<EFBFBD>瘚贝<E7989A>
|
||||
export { GroupManager };
|
||||
|
||||
export default groupManager;
|
||||
export default groupManager;
|
||||
Reference in New Issue
Block a user