- 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.
232 lines
6.9 KiB
TypeScript
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(),
|
|
});
|
|
},
|
|
})); |