refactor(core): introduce EventBus and refactor store infrastructure
All checks were successful
Frontend CI / build-and-push-web (push) Successful in 2m46s
Frontend CI / ota-android (push) Successful in 10m34s
Frontend CI / build-android-apk (push) Successful in 1h15m8s

- Add EventBus for decoupled event-driven communication between services
- Add EventSubscriber component for centralized event handling
- Add requestDedupe utility for shared request deduplication
- Refactor api/wsService to use eventBus instead of direct router navigation
- Extract MessageMapper.toCachedMessages for consistent message mapping
- Remove deprecated BaseManager and CacheBus classes
- Improve @mention rendering with memberMap support in segment rendering
- Update hooks to use useRef instead of useState for fetch tracking
This commit is contained in:
lafay
2026-04-12 18:14:29 +08:00
parent 4b5ce1ba21
commit 6610d2f173
28 changed files with 378 additions and 512 deletions

View File

@@ -10,6 +10,9 @@ import { authService } from '../../services/authService';
import { userCacheRepository } from '@/database';
import { useUserManagerStore } from './userStore';
import { createCacheEntry, isCacheExpired, DEFAULT_TTL } from '../utils/cache';
import { createDedupe } from '../utils/requestDedupe';
const dedupe = createDedupe(() => useUserManagerStore);
// ==================== UserManager 类 ====================
@@ -37,7 +40,7 @@ class UserManager {
}
}
return this.dedupe('users:current', async () => {
return dedupe('users:current', async () => {
const user = await authService.fetchCurrentUserFromAPI();
const newEntry = createCacheEntry(user, DEFAULT_TTL.USER);
store.setCurrentUserEntry(newEntry);
@@ -51,7 +54,7 @@ class UserManager {
}
private refreshCurrentUserInBackground(): void {
this.dedupe('users:current:bg', async () => {
dedupe('users:current:bg', async () => {
const store = useUserManagerStore.getState();
const user = await authService.fetchCurrentUserFromAPI();
const newEntry = createCacheEntry(user, DEFAULT_TTL.USER);
@@ -90,7 +93,7 @@ class UserManager {
}
}
return this.dedupe(`users:detail:${userId}`, async () => {
return dedupe(`users:detail:${userId}`, async () => {
const store = useUserManagerStore.getState();
const user = await authService.fetchUserByIdFromAPI(userId);
const newEntry = createCacheEntry(user, DEFAULT_TTL.USER);
@@ -104,7 +107,7 @@ class UserManager {
}
private refreshUserByIdInBackground(userId: string): void {
this.dedupe(`users:detail:bg:${userId}`, async () => {
dedupe(`users:detail:bg:${userId}`, async () => {
const store = useUserManagerStore.getState();
const user = await authService.fetchUserByIdFromAPI(userId);
const newEntry = createCacheEntry(user, DEFAULT_TTL.USER);
@@ -122,18 +125,6 @@ class UserManager {
invalidateUsers(): void {
useUserManagerStore.getState().invalidateAll();
}
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();