Files
frontend/src/utils/responsive.ts
lafay a6cdb97e24 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 组件

架构改进:
- 单一职责原则: 每个模块职责明确
- 依赖倒置: 通过接口解耦
- 代码复用: 工具函数可被多处使用
- 可测试性: 各模块可独立测试
2026-03-18 12:11:49 +08:00

168 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 响应式样式工具
* 提供基于断点的样式生成功能
*/
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;
}