Files
frontend/src/stores/post/postStore.ts
lafay 5614b4078a
All checks were successful
Frontend CI / ota-android (push) Successful in 13m7s
Frontend CI / build-and-push-web (push) Successful in 16m58s
Frontend CI / build-android-apk (push) Successful in 1h4m18s
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.
2026-04-01 02:17:36 +08:00

232 lines
6.9 KiB
TypeScript

/**
* 帖子状态 Zustand Store
*/
import { create } from 'zustand';
import type { Post } from '../../types';
import { CacheEntry, createCacheEntry, isCacheExpired, DEFAULT_TTL } from '../utils/cache';
// ==================== 状态接口 ====================
export interface PostManagerState {
// 帖子列表缓存 (key: list:type:page:pageSize)
listsMap: Map<string, CacheEntry<Post[]>>;
// 帖子详情缓存
detailsMap: Map<string, CacheEntry<Post | null>>;
// 加载状态
loadingListKeys: Set<string>;
loadingDetailIds: Set<string>;
// 待处理请求(去重)
pendingRequests: Map<string, Promise<any>>;
}
export interface PostManagerActions {
// 获取状态
getPostsList: (type: string, page: number, pageSize: number) => Post[] | null;
getPostDetail: (postId: string) => Post | null;
isListExpired: (type: string, page: number, pageSize: number) => boolean;
isDetailExpired: (postId: string) => boolean;
isLoadingList: (type: string, page: number, pageSize: number) => boolean;
isLoadingDetail: (postId: string) => boolean;
// 设置状态
setPostsList: (type: string, page: number, pageSize: number, posts: Post[]) => void;
setPostDetail: (postId: string, post: Post | null) => void;
setLoadingList: (type: string, page: number, pageSize: number, loading: boolean) => void;
setLoadingDetail: (postId: string, loading: boolean) => void;
// 缓存管理
invalidateList: (type?: string, page?: number, pageSize?: number) => void;
invalidateDetail: (postId: string) => void;
invalidateAll: () => void;
// 请求去重
getPendingRequest: <T>(key: string) => Promise<T> | undefined;
setPendingRequest: <T>(key: string, request: Promise<T>) => void;
deletePendingRequest: (key: string) => void;
clearPendingRequests: () => void;
// 重置
reset: () => void;
}
// ==================== 辅助函数 ====================
function buildListKey(type: string, page: number, pageSize: number): string {
return `list:${type}:${page}:${pageSize}`;
}
// ==================== 初始状态 ====================
const initialState: PostManagerState = {
listsMap: new Map(),
detailsMap: new Map(),
loadingListKeys: new Set(),
loadingDetailIds: new Set(),
pendingRequests: new Map(),
};
// ==================== Store 创建 ====================
export type PostManagerStore = PostManagerState & PostManagerActions;
export const usePostManagerStore = create<PostManagerStore>((set, get) => ({
// ==================== 初始状态 ====================
...initialState,
// ==================== 获取状态 ====================
getPostsList: (type: string, page: number, pageSize: number) => {
const key = buildListKey(type, page, pageSize);
const entry = get().listsMap.get(key);
if (!entry) return null;
if (isCacheExpired(entry)) return null;
return entry.data;
},
getPostDetail: (postId: string) => {
const entry = get().detailsMap.get(postId);
if (!entry) return null;
if (isCacheExpired(entry)) return null;
return entry.data;
},
isListExpired: (type: string, page: number, pageSize: number) => {
const key = buildListKey(type, page, pageSize);
const entry = get().listsMap.get(key);
if (!entry) return true;
return isCacheExpired(entry);
},
isDetailExpired: (postId: string) => {
const entry = get().detailsMap.get(postId);
if (!entry) return true;
return isCacheExpired(entry);
},
isLoadingList: (type: string, page: number, pageSize: number) => {
const key = buildListKey(type, page, pageSize);
return get().loadingListKeys.has(key);
},
isLoadingDetail: (postId: string) => {
return get().loadingDetailIds.has(postId);
},
// ==================== 设置状态 ====================
setPostsList: (type: string, page: number, pageSize: number, posts: Post[]) => {
const key = buildListKey(type, page, pageSize);
set(state => {
const newListsMap = new Map(state.listsMap);
newListsMap.set(key, createCacheEntry(posts, DEFAULT_TTL.POST_LIST));
return { listsMap: newListsMap };
});
},
setPostDetail: (postId: string, post: Post | null) => {
set(state => {
const newDetailsMap = new Map(state.detailsMap);
newDetailsMap.set(postId, createCacheEntry(post, DEFAULT_TTL.POST_DETAIL));
return { detailsMap: newDetailsMap };
});
},
setLoadingList: (type: string, page: number, pageSize: number, loading: boolean) => {
const key = buildListKey(type, page, pageSize);
set(state => {
const newLoadingListKeys = new Set(state.loadingListKeys);
if (loading) {
newLoadingListKeys.add(key);
} else {
newLoadingListKeys.delete(key);
}
return { loadingListKeys: newLoadingListKeys };
});
},
setLoadingDetail: (postId: string, loading: boolean) => {
set(state => {
const newLoadingDetailIds = new Set(state.loadingDetailIds);
if (loading) {
newLoadingDetailIds.add(postId);
} else {
newLoadingDetailIds.delete(postId);
}
return { loadingDetailIds: newLoadingDetailIds };
});
},
// ==================== 缓存管理 ====================
invalidateList: (type?: string, page?: number, pageSize?: number) => {
if (type !== undefined && page !== undefined && pageSize !== undefined) {
const key = buildListKey(type, page, pageSize);
set(state => {
const newListsMap = new Map(state.listsMap);
newListsMap.delete(key);
return { listsMap: newListsMap };
});
} else {
set({ listsMap: new Map() });
}
},
invalidateDetail: (postId: string) => {
set(state => {
const newDetailsMap = new Map(state.detailsMap);
newDetailsMap.delete(postId);
return { detailsMap: newDetailsMap };
});
},
invalidateAll: () => {
set({
listsMap: new Map(),
detailsMap: new Map(),
pendingRequests: new Map(),
});
},
// ==================== 请求去重 ====================
getPendingRequest: <T>(key: string) => {
return get().pendingRequests.get(key) as Promise<T> | undefined;
},
setPendingRequest: <T>(key: string, request: Promise<T>) => {
set(state => {
const newPendingRequests = new Map(state.pendingRequests);
newPendingRequests.set(key, request);
return { pendingRequests: newPendingRequests };
});
},
deletePendingRequest: (key: string) => {
set(state => {
const newPendingRequests = new Map(state.pendingRequests);
newPendingRequests.delete(key);
return { pendingRequests: newPendingRequests };
});
},
clearPendingRequests: () => {
set({ pendingRequests: new Map() });
},
// ==================== 重置 ====================
reset: () => {
set({
...initialState,
listsMap: new Map(),
detailsMap: new Map(),
loadingListKeys: new Set(),
loadingDetailIds: new Set(),
pendingRequests: new Map(),
});
},
}));