- 品牌與顯示:app.json、Info.plist、package scheme、iOS 產物 DearMama.app - 協議與條款:隱私協議/使用條款全文、設計文檔、server legal_docs + legal API、push 預設 title - 多語言:all.json / zh-TW / zh-CN / en / es / pt 的 consent、widget 標題與引導文案 - 小工具:EmotionWidget.swift 品牌文案、Dear Mama.xcscheme - CocoaPods:project.pbxproj objectVersion 70→56 以通過 pod install - Metro:react-native-text-size 用 require + extraNodeModules 解析 - textWrap:measureWidthImpl 改為 require 載入 react-native-text-size Co-authored-by: Cursor <cursoragent@cursor.com>
67 lines
2.4 KiB
TypeScript
67 lines
2.4 KiB
TypeScript
import type { FontSpec, MeasureWidthImpl } from './types';
|
||
|
||
/**
|
||
* 默认测量实现(成熟方案):react-native-text-size
|
||
*
|
||
* 注意:
|
||
* - 该库的 `measure` 是 Promise 异步接口,本模块以 async 方式对齐。
|
||
* - 为避免在测试/Node 环境直接 require `react-native` 造成崩溃,这里使用“延迟加载 + 捕获异常”。
|
||
*/
|
||
|
||
type TextSizeMeasureParams = {
|
||
text: string;
|
||
width?: number;
|
||
fontFamily?: string;
|
||
fontSize?: number;
|
||
fontWeight?: string;
|
||
allowFontScaling?: boolean;
|
||
usePreciseWidth?: boolean;
|
||
};
|
||
|
||
type TextSizeMeasureResult = { width: number };
|
||
|
||
function loadReactNativeTextSize(): {
|
||
measure: (params: TextSizeMeasureParams) => Promise<TextSizeMeasureResult>;
|
||
} {
|
||
// 使用 require 确保 Metro 能解析并打包该原生模块(动态 import 在某些环境下无法被正确解析)
|
||
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-explicit-any
|
||
const mod: any = require('react-native-text-size');
|
||
return mod?.default ?? mod;
|
||
}
|
||
|
||
function toTextSizeFontSpecs(fontSpec: FontSpec): Pick<TextSizeMeasureParams, 'fontFamily' | 'fontSize' | 'fontWeight'> {
|
||
return {
|
||
fontFamily: fontSpec.fontFamily,
|
||
fontSize: fontSpec.fontSize,
|
||
fontWeight: fontSpec.fontWeight,
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 默认测量函数(可替换/可注入)。
|
||
* - width 约束设为极大值,避免自动换行影响“单行宽度”测量
|
||
* - usePreciseWidth=true,取更精确的宽度(开销更大,但对本算法更稳定)
|
||
*/
|
||
export const defaultMeasureWidthImpl: MeasureWidthImpl = async ({ text, fontSpec }) => {
|
||
const TextSize = loadReactNativeTextSize();
|
||
if (!TextSize || typeof TextSize.measure !== 'function') {
|
||
// 典型原因:在 Expo Go 中运行,或没有使用包含该原生模块的 Development Build。
|
||
// 这里抛出更明确的错误,方便上层捕获并在 meta.reason=MEASURE_FAILED 时看到根因。
|
||
throw new Error(
|
||
[
|
||
'react-native-text-size 原生模块不可用:TextSize.measure 不是函数。',
|
||
'请确认你不是在 Expo Go 里运行;需要使用包含该原生模块的 Development Build(expo-dev-client / expo run:ios / EAS dev build)。',
|
||
].join(' '),
|
||
);
|
||
}
|
||
const res = await TextSize.measure({
|
||
text,
|
||
width: 1_000_000_000,
|
||
usePreciseWidth: true,
|
||
allowFontScaling: true,
|
||
...toTextSizeFontSpecs(fontSpec),
|
||
});
|
||
return res.width;
|
||
};
|
||
|