主要改动: 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 组件 架构改进: - 单一职责原则: 每个模块职责明确 - 依赖倒置: 通过接口解耦 - 代码复用: 工具函数可被多处使用 - 可测试性: 各模块可独立测试
168 lines
3.6 KiB
TypeScript
168 lines
3.6 KiB
TypeScript
/**
|
||
* 响应式样式工具
|
||
* 提供基于断点的样式生成功能
|
||
*/
|
||
|
||
import { ViewStyle } from 'react-native';
|
||
import { BREAKPOINTS } from '../presentation/hooks/responsive';
|
||
|
||
/**
|
||
* 断点键名
|
||
*/
|
||
export type ResponsiveBreakpoint = 'mobile' | 'tablet' | 'desktop' | 'wide';
|
||
|
||
/**
|
||
* 断点值映射
|
||
*/
|
||
export type ResponsiveValues<T> = {
|
||
mobile?: T;
|
||
tablet?: T;
|
||
desktop?: T;
|
||
wide?: T;
|
||
};
|
||
|
||
/**
|
||
* 断点样式映射
|
||
*/
|
||
export type ResponsiveStyles = {
|
||
mobile?: ViewStyle;
|
||
tablet?: ViewStyle;
|
||
desktop?: ViewStyle;
|
||
wide?: ViewStyle;
|
||
};
|
||
|
||
/**
|
||
* 根据当前断点返回对应的值
|
||
*
|
||
* @param breakpoint - 当前断点
|
||
* @param values - 各断点对应的值
|
||
* @returns 对应断点的值,如果未找到则返回 undefined
|
||
*
|
||
* @example
|
||
* const fontSize = responsiveValue('tablet', {
|
||
* mobile: 14,
|
||
* tablet: 16,
|
||
* desktop: 18,
|
||
* wide: 20
|
||
* });
|
||
*/
|
||
export function responsiveValue<T>(
|
||
breakpoint: string,
|
||
values: ResponsiveValues<T>
|
||
): T | undefined {
|
||
// 按断点优先级顺序查找
|
||
const breakpoints: ResponsiveBreakpoint[] = ['wide', 'desktop', 'tablet', 'mobile'];
|
||
|
||
for (const bp of breakpoints) {
|
||
if (breakpoint === bp && values[bp] !== undefined) {
|
||
return values[bp];
|
||
}
|
||
}
|
||
|
||
return undefined;
|
||
}
|
||
|
||
/**
|
||
* 创建响应式样式
|
||
* 根据当前断点返回对应的样式对象
|
||
*
|
||
* @param breakpoint - 当前断点
|
||
* @param styles - 各断点对应的样式
|
||
* @returns 合并后的样式对象
|
||
*
|
||
* @example
|
||
* const containerStyle = createResponsiveStyles(breakpoint, {
|
||
* mobile: { padding: 12 },
|
||
* tablet: { padding: 24 },
|
||
* desktop: { padding: 32 },
|
||
* wide: { padding: 48 }
|
||
* });
|
||
*/
|
||
export function createResponsiveStyles(
|
||
breakpoint: string,
|
||
styles: ResponsiveStyles
|
||
): ViewStyle {
|
||
const result: ViewStyle = {};
|
||
|
||
// 按断点优先级从低到高合并样式
|
||
const breakpoints: ResponsiveBreakpoint[] = ['mobile', 'tablet', 'desktop', 'wide'];
|
||
|
||
for (const bp of breakpoints) {
|
||
const style = styles[bp];
|
||
if (style) {
|
||
Object.assign(result, style);
|
||
}
|
||
// 到达当前断点后停止合并
|
||
if (breakpoint === bp) {
|
||
break;
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* 获取响应式数值
|
||
* 根据屏幕宽度返回对应的数值
|
||
*
|
||
* @param width - 当前屏幕宽度
|
||
* @param config - 各断点对应的数值
|
||
* @returns 对应的数值
|
||
*
|
||
* @example
|
||
* const padding = getResponsiveValue(screenWidth, {
|
||
* mobile: 12,
|
||
* tablet: 16,
|
||
* desktop: 24,
|
||
* wide: 32
|
||
* });
|
||
*/
|
||
export function getResponsiveValue(
|
||
width: number,
|
||
config: ResponsiveValues<number>
|
||
): number | undefined {
|
||
if (width >= BREAKPOINTS.wide && config.wide !== undefined) {
|
||
return config.wide;
|
||
}
|
||
if (width >= BREAKPOINTS.desktop && config.desktop !== undefined) {
|
||
return config.desktop;
|
||
}
|
||
if (width >= BREAKPOINTS.tablet && config.tablet !== undefined) {
|
||
return config.tablet;
|
||
}
|
||
if (config.mobile !== undefined) {
|
||
return config.mobile;
|
||
}
|
||
return undefined;
|
||
}
|
||
|
||
/**
|
||
* 判断当前是否为宽屏
|
||
*
|
||
* @param width - 当前屏幕宽度
|
||
* @returns 是否为宽屏(tablet 及以上)
|
||
*/
|
||
export function isWideScreen(width: number): boolean {
|
||
return width >= BREAKPOINTS.tablet;
|
||
}
|
||
|
||
/**
|
||
* 判断当前是否为桌面端
|
||
*
|
||
* @param width - 当前屏幕宽度
|
||
* @returns 是否为桌面端(desktop 及以上)
|
||
*/
|
||
export function isDesktop(width: number): boolean {
|
||
return width >= BREAKPOINTS.desktop;
|
||
}
|
||
|
||
/**
|
||
* 判断当前是否为超大屏
|
||
*
|
||
* @param width - 当前屏幕宽度
|
||
* @returns 是否为超大屏(wide)
|
||
*/
|
||
export function isWide(width: number): boolean {
|
||
return width >= BREAKPOINTS.wide;
|
||
}
|