- Introduced new methods for merging posts and comments efficiently, improving performance during data updates. - Updated loading state management in hooks to include initial loading and loading more states for better user feedback. - Refactored HomeScreen and PostDetailScreen to utilize the new loading states and merging logic, enhancing user experience during data fetching. - Improved pagination handling in useCursorPagination and useDifferentialPosts to ensure consistent data management across components.
194 lines
4.6 KiB
TypeScript
194 lines
4.6 KiB
TypeScript
/**
|
|
* useBreakpoint Hook
|
|
* 断点检测 - 检测当前断点
|
|
*/
|
|
|
|
import { useMemo, useState, useEffect } from 'react';
|
|
import { Dimensions, ScaledSize } from 'react-native';
|
|
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 ====================
|
|
|
|
function useWindowDimensionsLocal(): ScaledSize {
|
|
const [dimensions, setDimensions] = useState(() => Dimensions.get('window'));
|
|
|
|
useEffect(() => {
|
|
const subscription = Dimensions.addEventListener('change', ({ window }) => {
|
|
setDimensions(window);
|
|
});
|
|
|
|
return () => {
|
|
subscription.remove();
|
|
};
|
|
}, []);
|
|
|
|
return dimensions;
|
|
}
|
|
|
|
/**
|
|
* 断点检测 Hook
|
|
* 返回当前的基础断点
|
|
*
|
|
* @returns 当前断点
|
|
*
|
|
* @example
|
|
* const breakpoint = useBreakpoint();
|
|
* // 'mobile' | 'tablet' | 'desktop' | 'wide'
|
|
*/
|
|
export function useBreakpoint(): BreakpointKey {
|
|
const { width } = useWindowDimensionsLocal();
|
|
|
|
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 } = useWindowDimensionsLocal();
|
|
|
|
return useMemo(() => {
|
|
return getFineBreakpoint(width);
|
|
}, [width]);
|
|
}
|
|
|
|
/**
|
|
* 检查当前断点是否大于等于目标断点
|
|
*
|
|
* @param target - 目标断点
|
|
* @returns 是否满足条件
|
|
*
|
|
* @example
|
|
* const isMediumUp = useBreakpointGTE('md');
|
|
*/
|
|
export function useBreakpointGTE(target: FineBreakpointKey): boolean {
|
|
const { width } = useWindowDimensionsLocal();
|
|
|
|
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 } = useWindowDimensionsLocal();
|
|
|
|
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 } = useWindowDimensionsLocal();
|
|
|
|
return useMemo(() => {
|
|
const current = getFineBreakpoint(width);
|
|
return isBreakpointBetween(current, min, max);
|
|
}, [width, min, max]);
|
|
}
|
|
|
|
export default {
|
|
useBreakpoint,
|
|
useFineBreakpoint,
|
|
useBreakpointGTE,
|
|
useBreakpointLT,
|
|
useBreakpointBetween,
|
|
};
|