Initial frontend repository commit.

Include app source and update .gitignore to exclude local release artifacts and signing files.

Made-with: Cursor
This commit is contained in:
2026-03-09 21:29:03 +08:00
commit 3968660048
129 changed files with 55599 additions and 0 deletions

167
src/utils/responsive.ts Normal file
View File

@@ -0,0 +1,167 @@
/**
* 响应式样式工具
* 提供基于断点的样式生成功能
*/
import { ViewStyle } from 'react-native';
import { BREAKPOINTS } from '../hooks/useResponsive';
/**
* 断点键名
*/
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;
}