refactor: restructure core architecture and responsive system
All checks were successful
Frontend CI / ota-android (push) Successful in 1m40s
Frontend CI / ota-ios (push) Successful in 1m39s
Frontend CI / build-and-push-web (push) Successful in 3m30s
Frontend CI / build-android-apk (push) Successful in 1h1m8s

This commit implements a major architectural refactor to improve modularity, type safety, and maintainability across the codebase.

Key changes include:
- **Responsive System Refactor**: Migrated from a monolithic `useResponsive` hook to a set of specialized, granular hooks (`useBreakpoint`, `useOrientation`, `usePlatform`, etc.) located in `src/presentation/hooks/responsive`. This reduces unnecessary re-renders and improves developer experience.
- **Core Service Restructuring**: Introduced a new directory structure for services, including dedicated folders for `datasources`, `mappers`, and domain-specific types (`message`, `post`).
- **Data Layer Improvements**:
    - Centralized JSON parsing logic in `src/database/core/jsonUtils.ts`.
    - Cleaned up repository implementations by removing redundant local utility functions.
    - Refactored `MessageMapper` to use the new centralized JSON utility.
- **Type System Cleanup**:
    - Decomposed the large `src/types/dto.ts` into a modular `src/types/dto/` directory.
    - Simplified `src/types/index.ts` and introduced backward-compatible aliases for core entities.
- **Utility Consolidation**:
    - Created a centralized `src/utils/formatTime.ts` to replace fragmented date formatting logic across various screens and components.
    - Removed deprecated responsive utility files in favor of the new hook-based system.
- **Service Logic Refinement**: Refactored `ApiClient` and `WebSocketService` to use a centralized `showVerificationModal` service, removing duplicated state management for verification prompts.
This commit is contained in:
2026-05-05 19:07:33 +08:00
parent f5f9c3a619
commit 3196972596
96 changed files with 4609 additions and 3149 deletions

View File

@@ -0,0 +1,266 @@
/**
* 分页状态管理类型定义
*
* 提供分页相关的接口和类型定义
* 用于统一管理分页状态、缓存和配置
*/
/**
* 分页状态
* 跟踪特定分页键的分页信息
*/
export interface PaginationState {
/** 当前页码1-based */
currentPage: number;
/** 每页大小 */
pageSize: number;
/** 已加载的总条目数 */
totalLoaded: number;
/** 是否存在更多数据 */
hasMore: boolean;
/** 是否正在加载 */
isLoading: boolean;
/** 最后加载时间戳 */
lastLoadTime: number;
/** 分页游标(用于基于游标的分页) */
cursor?: string | number | null;
/** 是否发生过错误 */
hasError: boolean;
/** 错误信息 */
error?: string;
}
/**
* 页面缓存
* 存储已加载页面的数据
*/
export interface PageCache<T = any> {
/** 页码 */
page: number;
/** 该页的数据 */
data: T[];
/** 缓存时间戳 */
cachedAt: number;
/** 分页游标 */
cursor?: string | number | null;
}
/**
* 分页配置
* 配置分页行为
*/
export interface PaginationConfig {
/** 每页默认大小 */
pageSize: number;
/** 预加载阈值(距离底部多少条时触发预加载) */
prefetchThreshold: number;
/** 最大缓存页数 */
maxCachedPages: number;
/** 缓存过期时间(毫秒) */
cacheTtl: number;
/** 是否启用预加载 */
enablePrefetch: boolean;
/** 是否启用缓存 */
enableCache: boolean;
/** 最大重试次数 */
maxRetries: number;
/** 重试延迟(毫秒) */
retryDelay: number;
}
/**
* 加载更多结果
* loadMore 方法的返回类型
*/
export interface LoadMoreResult<T = any> {
/** 是否成功 */
success: boolean;
/** 加载的数据 */
data: T[];
/** 是否有更多数据 */
hasMore: boolean;
/** 是否来自缓存 */
fromCache: boolean;
/** 错误信息(如果失败) */
error?: string;
}
/**
* 刷新结果
* refresh 方法的返回类型
*/
export interface RefreshResult<T = any> {
/** 是否成功 */
success: boolean;
/** 刷新后的数据 */
data: T[];
/** 是否有更多数据 */
hasMore: boolean;
/** 错误信息(如果失败) */
error?: string;
}
/**
* 预加载结果
* prefetch 方法的返回类型
*/
export interface PrefetchResult<T = any> {
/** 是否成功 */
success: boolean;
/** 预加载的数据 */
data?: T[];
/** 错误信息(如果失败) */
error?: string;
}
/**
* 分页数据加载函数
* 用于从数据源加载分页数据
*/
export type FetchPageFunction<T = any> = (
page: number,
pageSize: number,
cursor?: string | number | null
) => Promise<{
data: T[];
hasMore: boolean;
cursor?: string | number | null;
}>;
/**
* 默认分页配置
*/
export const DEFAULT_PAGINATION_CONFIG: PaginationConfig = {
pageSize: 20,
prefetchThreshold: 5,
maxCachedPages: 10,
cacheTtl: 5 * 60 * 1000, // 5分钟
enablePrefetch: true,
enableCache: true,
maxRetries: 3,
retryDelay: 1000,
};
/**
* 初始分页状态
*/
export function createInitialPaginationState(pageSize: number = 20): PaginationState {
return {
currentPage: 0,
pageSize,
totalLoaded: 0,
hasMore: true,
isLoading: false,
lastLoadTime: 0,
cursor: null,
hasError: false,
error: undefined,
};
}
/**
* 创建页面缓存
*/
export function createPageCache<T>(
page: number,
data: T[],
cursor?: string | number | null
): PageCache<T> {
return {
page,
data,
cachedAt: Date.now(),
cursor,
};
}
/**
* 检查缓存是否过期
*/
export function isCacheExpired<T>(cache: PageCache<T>, ttl: number): boolean {
return Date.now() - cache.cachedAt > ttl;
}
// ==================== 游标分页相关类型 ====================
/**
* 游标分页方向
*/
export type CursorDirection = 'forward' | 'backward';
/**
* 游标分页配置
*/
export interface CursorPaginationConfig {
/** 每页数量 */
pageSize: number;
/** 是否启用双向分页 */
bidirectional?: boolean;
/** 是否自动加载第一页,默认为 true */
autoLoad?: boolean;
}
/**
* 游标分页状态
*/
export interface CursorPaginationState<T> {
/** 数据项列表 */
list: T[];
/** 下一页游标 */
nextCursor: string | null;
/** 上一页游标 */
prevCursor: string | null;
/** 是否有更多数据 */
hasMore: boolean;
/** 是否正在加载 */
isLoading: boolean;
/** 是否首屏加载(空列表初始化) */
isInitialLoading: boolean;
/** 是否正在加载更多 */
isLoadingMore: boolean;
/** 是否正在刷新 */
isRefreshing: boolean;
/** 错误信息 */
error: string | null;
/** 是否为首次加载 */
isFirstLoad: boolean;
}
/**
* 游标分页操作
*/
export interface CursorPaginationActions<T> {
/** 加载更多(下一页) */
loadMore: () => Promise<void>;
/** 加载上一页(双向分页) */
loadPrevious: () => Promise<void>;
/** 刷新数据(重新从第一页加载) */
refresh: () => Promise<void>;
/** 重置状态 */
reset: () => void;
/** 设置数据(用于外部数据注入) */
setList: (list: T[], nextCursor: string | null, prevCursor: string | null, hasMore: boolean) => void;
/** 就地更新单条数据 */
updateItem: (id: string, updates: Partial<T>) => void;
}
/**
* 游标分页 Hook 返回值
*/
export interface UseCursorPaginationReturn<T> extends CursorPaginationState<T>, CursorPaginationActions<T> {}
/**
* 游标分页数据获取函数
*/
export type CursorFetchFunction<T, P = void> = (params: {
cursor?: string;
direction: CursorDirection;
pageSize: number;
/** 额外参数 */
extraParams?: P;
}) => Promise<{
list: T[];
next_cursor: string | null;
prev_cursor: string | null;
has_more: boolean;
}>;