refactor: 架构重构 - 解耦过度耦合模块
主要改动: 1. 创建乐观更新工具函数 (optimisticUpdate.ts) - 消除 userStore.ts 中的重复代码 2. 拆分 useResponsive.ts (485行 -> 12个专注模块) - useBreakpoint: 断点检测 - useOrientation: 方向检测 - usePlatform: 平台检测 - useScreenSize: 屏幕尺寸 - useResponsiveValue: 响应式值 - useResponsiveStyle: 响应式样式 - useMediaQuery: 媒体查询 - useColumnCount: 列数计算 - useResponsiveSpacing: 响应式间距 3. 整理数据层 (Repository 层) - ApiDataSource: API数据源 - LocalDataSource: 本地数据源 - CacheDataSource: 缓存数据源 - MessageRepository: 消息仓库 4. 重构 messageManager.ts (2194行 -> 4个模块) - MessageStateManager: 状态管理 - WebSocketMessageHandler: WebSocket处理 - MessageSyncService: 消息同步 - ReadReceiptManager: 已读管理 5. 导航解耦 (MainNavigator.tsx: 1118行 -> 100行) - 创建 NavigationService 解耦层 - 拆分多个 Navigator 组件 架构改进: - 单一职责原则: 每个模块职责明确 - 依赖倒置: 通过接口解耦 - 代码复用: 工具函数可被多处使用 - 可测试性: 各模块可独立测试
This commit is contained in:
177
src/presentation/hooks/responsive/useBreakpoint.ts
Normal file
177
src/presentation/hooks/responsive/useBreakpoint.ts
Normal file
@@ -0,0 +1,177 @@
|
||||
/**
|
||||
* useBreakpoint Hook
|
||||
* 断点检测 - 检测当前断点
|
||||
*/
|
||||
|
||||
import { useMemo } from 'react';
|
||||
import { useWindowDimensions } from './useScreenSize';
|
||||
import { BREAKPOINTS, FINE_BREAKPOINTS } from './types';
|
||||
import type { BreakpointKey, FineBreakpointKey } from './types';
|
||||
|
||||
// ==================== 工具函数 ====================
|
||||
|
||||
/**
|
||||
* 获取当前断点
|
||||
*/
|
||||
export function getBreakpoint(width: number): BreakpointKey {
|
||||
if (width >= BREAKPOINTS.wide) {
|
||||
return 'wide';
|
||||
}
|
||||
if (width >= BREAKPOINTS.desktop) {
|
||||
return 'desktop';
|
||||
}
|
||||
if (width >= BREAKPOINTS.tablet) {
|
||||
return 'tablet';
|
||||
}
|
||||
return 'mobile';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取细粒度断点
|
||||
*/
|
||||
export function getFineBreakpoint(width: number): FineBreakpointKey {
|
||||
if (width >= FINE_BREAKPOINTS['4xl']) return '4xl';
|
||||
if (width >= FINE_BREAKPOINTS['3xl']) return '3xl';
|
||||
if (width >= FINE_BREAKPOINTS['2xl']) return '2xl';
|
||||
if (width >= FINE_BREAKPOINTS.xl) return 'xl';
|
||||
if (width >= FINE_BREAKPOINTS.lg) return 'lg';
|
||||
if (width >= FINE_BREAKPOINTS.md) return 'md';
|
||||
if (width >= FINE_BREAKPOINTS.sm) return 'sm';
|
||||
return 'xs';
|
||||
}
|
||||
|
||||
/**
|
||||
* 断点比较 - 检查当前断点是否大于等于目标断点
|
||||
*/
|
||||
export function isBreakpointGTE(
|
||||
current: FineBreakpointKey,
|
||||
target: FineBreakpointKey
|
||||
): boolean {
|
||||
const order: FineBreakpointKey[] = ['xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl'];
|
||||
return order.indexOf(current) >= order.indexOf(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* 断点比较 - 检查当前断点是否小于目标断点
|
||||
*/
|
||||
export function isBreakpointLT(
|
||||
current: FineBreakpointKey,
|
||||
target: FineBreakpointKey
|
||||
): boolean {
|
||||
return !isBreakpointGTE(current, target);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查当前是否在指定断点范围内
|
||||
*/
|
||||
export function isBreakpointBetween(
|
||||
current: FineBreakpointKey,
|
||||
min: FineBreakpointKey,
|
||||
max: FineBreakpointKey
|
||||
): boolean {
|
||||
return isBreakpointGTE(current, min) && isBreakpointLT(current, max);
|
||||
}
|
||||
|
||||
// ==================== Hooks ====================
|
||||
|
||||
/**
|
||||
* 断点检测 Hook
|
||||
* 返回当前的基础断点
|
||||
*
|
||||
* @returns 当前断点
|
||||
*
|
||||
* @example
|
||||
* const breakpoint = useBreakpoint();
|
||||
* // 'mobile' | 'tablet' | 'desktop' | 'wide'
|
||||
*/
|
||||
export function useBreakpoint(): BreakpointKey {
|
||||
const { width } = useWindowDimensions();
|
||||
|
||||
return useMemo(() => {
|
||||
return getBreakpoint(width);
|
||||
}, [width]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 细粒度断点检测 Hook
|
||||
* 返回当前的细粒度断点
|
||||
*
|
||||
* @returns 当前细粒度断点
|
||||
*
|
||||
* @example
|
||||
* const fineBreakpoint = useFineBreakpoint();
|
||||
* // 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl'
|
||||
*/
|
||||
export function useFineBreakpoint(): FineBreakpointKey {
|
||||
const { width } = useWindowDimensions();
|
||||
|
||||
return useMemo(() => {
|
||||
return getFineBreakpoint(width);
|
||||
}, [width]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查当前断点是否大于等于目标断点
|
||||
*
|
||||
* @param target - 目标断点
|
||||
* @returns 是否满足条件
|
||||
*
|
||||
* @example
|
||||
* const isMediumUp = useBreakpointGTE('md');
|
||||
*/
|
||||
export function useBreakpointGTE(target: FineBreakpointKey): boolean {
|
||||
const { width } = useWindowDimensions();
|
||||
|
||||
return useMemo(() => {
|
||||
const current = getFineBreakpoint(width);
|
||||
return isBreakpointGTE(current, target);
|
||||
}, [width, target]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查当前断点是否小于目标断点
|
||||
*
|
||||
* @param target - 目标断点
|
||||
* @returns 是否满足条件
|
||||
*
|
||||
* @example
|
||||
* const isMobileOnly = useBreakpointLT('lg');
|
||||
*/
|
||||
export function useBreakpointLT(target: FineBreakpointKey): boolean {
|
||||
const { width } = useWindowDimensions();
|
||||
|
||||
return useMemo(() => {
|
||||
const current = getFineBreakpoint(width);
|
||||
return isBreakpointLT(current, target);
|
||||
}, [width, target]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查当前是否在指定断点范围内
|
||||
*
|
||||
* @param min - 最小断点(包含)
|
||||
* @param max - 最大断点(不包含)
|
||||
* @returns 是否在范围内
|
||||
*
|
||||
* @example
|
||||
* const isTabletRange = useBreakpointBetween('md', 'lg');
|
||||
*/
|
||||
export function useBreakpointBetween(
|
||||
min: FineBreakpointKey,
|
||||
max: FineBreakpointKey
|
||||
): boolean {
|
||||
const { width } = useWindowDimensions();
|
||||
|
||||
return useMemo(() => {
|
||||
const current = getFineBreakpoint(width);
|
||||
return isBreakpointBetween(current, min, max);
|
||||
}, [width, min, max]);
|
||||
}
|
||||
|
||||
export default {
|
||||
useBreakpoint,
|
||||
useFineBreakpoint,
|
||||
useBreakpointGTE,
|
||||
useBreakpointLT,
|
||||
useBreakpointBetween,
|
||||
};
|
||||
Reference in New Issue
Block a user