@momo-kits/foundation 0.162.3-fontscale.1 → 0.162.3-test.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Application/NavigationContainer.tsx +44 -8
- package/Application/ScaleSizeProvider.tsx +5 -3
- package/Application/WidgetContainer.tsx +1 -1
- package/Application/types.ts +2 -1
- package/Context/index.ts +6 -3
- package/Input/Input.tsx +1 -12
- package/Input/InputPhoneNumber.tsx +1 -12
- package/Layout/Screen.tsx +1 -8
- package/Text/utils.ts +10 -5
- package/package.json +1 -1
|
@@ -19,7 +19,7 @@ import Navigator from './Navigator';
|
|
|
19
19
|
import ScaleSizeProvider from './ScaleSizeProvider';
|
|
20
20
|
import { getModalOptions, getStackOptions } from './utils';
|
|
21
21
|
import { NavigationContainerProps } from './types';
|
|
22
|
-
import { ApplicationContext, MiniAppContext } from '../Context';
|
|
22
|
+
import { ApplicationContext, FontScaleConfig, MiniAppContext } from '../Context';
|
|
23
23
|
import Localize from './Localize';
|
|
24
24
|
import { Colors, defaultTheme } from '../Consts';
|
|
25
25
|
import { HeaderLeft } from './Components/HeaderLeft';
|
|
@@ -29,6 +29,29 @@ import { HeaderBackground } from './Components/HeaderBackground';
|
|
|
29
29
|
|
|
30
30
|
const Stack = createStackNavigator();
|
|
31
31
|
|
|
32
|
+
const FONT_SCALE_OBSERVER_KEY = 'font_scale_config';
|
|
33
|
+
|
|
34
|
+
// AI-GENERATED START: parse the font_scale_config first-frame seed read straight from async storage (string | {response} | object)
|
|
35
|
+
const parseSeedFontScaleConfig = (raw: any): FontScaleConfig | undefined => {
|
|
36
|
+
let data = raw;
|
|
37
|
+
if (typeof data === 'string') {
|
|
38
|
+
try {
|
|
39
|
+
data = JSON.parse(data);
|
|
40
|
+
} catch {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
data = data?.response ?? data;
|
|
45
|
+
if (!data || (data.useOSFontScale === undefined && data.userScaleRate === undefined)) {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
useOSFontScale: data.useOSFontScale,
|
|
50
|
+
userScaleRate: data.userScaleRate,
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
// AI-GENERATED END: parse the font_scale_config first-frame seed read straight from async storage (string | {response} | object)
|
|
54
|
+
|
|
32
55
|
const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
33
56
|
screen,
|
|
34
57
|
theme = defaultTheme,
|
|
@@ -45,6 +68,11 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
45
68
|
}) => {
|
|
46
69
|
const context = useContext<any>(MiniAppContext);
|
|
47
70
|
const [currentContext, setCurrentContext] = useState<any>({});
|
|
71
|
+
// AI-GENERATED START: self-seed first-frame font scale by reading font_scale_config straight from async storage
|
|
72
|
+
const [observerFontScaleConfig, setObserverFontScaleConfig] = useState<
|
|
73
|
+
FontScaleConfig | undefined
|
|
74
|
+
>(() => parseSeedFontScaleConfig(maxApi?.getItem?.(FONT_SCALE_OBSERVER_KEY)) ?? context?.fontScaleConfig);
|
|
75
|
+
// AI-GENERATED END: self-seed first-frame font scale by reading font_scale_config straight from async storage
|
|
48
76
|
|
|
49
77
|
const mergedContext = {
|
|
50
78
|
...context,
|
|
@@ -55,10 +83,24 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
|
|
|
55
83
|
},
|
|
56
84
|
};
|
|
57
85
|
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
const sub = maxApi?.observer?.(
|
|
88
|
+
FONT_SCALE_OBSERVER_KEY,
|
|
89
|
+
(data: FontScaleConfig) => {
|
|
90
|
+
setObserverFontScaleConfig(data ?? undefined);
|
|
91
|
+
},
|
|
92
|
+
);
|
|
93
|
+
return () => {
|
|
94
|
+
sub?.remove?.();
|
|
95
|
+
};
|
|
96
|
+
}, [maxApi]);
|
|
97
|
+
|
|
58
98
|
return (
|
|
59
99
|
<SafeAreaProvider>
|
|
60
100
|
<MiniAppContext.Provider value={mergedContext}>
|
|
61
|
-
<ScaleSizeProvider
|
|
101
|
+
<ScaleSizeProvider
|
|
102
|
+
fontScaleConfig={observerFontScaleConfig}
|
|
103
|
+
>
|
|
62
104
|
<Navigation
|
|
63
105
|
screen={screen}
|
|
64
106
|
theme={theme}
|
|
@@ -117,12 +159,6 @@ const Navigation: React.FC<any> = ({
|
|
|
117
159
|
},
|
|
118
160
|
);
|
|
119
161
|
|
|
120
|
-
// TEMP: verify FontScale MaxApi end-to-end — remove after test
|
|
121
|
-
// @ts-ignore getFontScale added in newer @momo-platform/api
|
|
122
|
-
maxApi?.getFontScale?.((scale: any) =>
|
|
123
|
-
console.log('[FontScale][momo-kit] getFontScale ->', scale),
|
|
124
|
-
);
|
|
125
|
-
|
|
126
162
|
return () => {
|
|
127
163
|
subscription?.remove?.();
|
|
128
164
|
};
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import React, { FC } from 'react';
|
|
1
|
+
import React, { FC, useContext } from 'react';
|
|
2
2
|
import { ScaleSizeContext } from '../Context';
|
|
3
3
|
import { ScaleSizeProviderProps } from './types';
|
|
4
4
|
|
|
5
5
|
const ScaleSizeProvider: FC<ScaleSizeProviderProps> = ({
|
|
6
|
-
|
|
6
|
+
fontScaleConfig,
|
|
7
7
|
children,
|
|
8
8
|
}) => {
|
|
9
|
+
// Inherit the config from an upper layer (e.g. app root) when the host doesn't set it via MiniAppContext.
|
|
10
|
+
const parent = useContext(ScaleSizeContext);
|
|
9
11
|
return (
|
|
10
|
-
<ScaleSizeContext.Provider value={
|
|
12
|
+
<ScaleSizeContext.Provider value={fontScaleConfig ?? parent}>
|
|
11
13
|
{children}
|
|
12
14
|
</ScaleSizeContext.Provider>
|
|
13
15
|
);
|
|
@@ -78,7 +78,7 @@ const WidgetContainer: React.FC<WidgetContainerProps> = ({
|
|
|
78
78
|
<SafeAreaProvider>
|
|
79
79
|
<MiniAppContext.Provider value={mergedContext}>
|
|
80
80
|
<ScaleSizeProvider
|
|
81
|
-
|
|
81
|
+
fontScaleConfig={mergedContext?.fontScaleConfig}
|
|
82
82
|
>
|
|
83
83
|
<ApplicationContext.Provider
|
|
84
84
|
value={{
|
package/Application/types.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
import type { SharedValue } from 'react-native-reanimated';
|
|
11
11
|
import { PopupNotifyProps } from '../Popup/types';
|
|
12
12
|
import { InputRef, InputSearchProps } from '../Input';
|
|
13
|
+
import { FontScaleConfig } from '../Context';
|
|
13
14
|
import Navigation from './Navigation';
|
|
14
15
|
|
|
15
16
|
export type NavigationProps = {
|
|
@@ -109,7 +110,7 @@ export type Theme = {
|
|
|
109
110
|
};
|
|
110
111
|
|
|
111
112
|
export type ScaleSizeProviderProps = {
|
|
112
|
-
|
|
113
|
+
fontScaleConfig?: FontScaleConfig;
|
|
113
114
|
children: ViewProps['children'];
|
|
114
115
|
};
|
|
115
116
|
|
package/Context/index.ts
CHANGED
|
@@ -9,9 +9,12 @@ const MiniAppContext = (Platform as any).MiniAppContext ?? Context;
|
|
|
9
9
|
const ScreenContext = (Platform as any).ScreenContext ?? Context;
|
|
10
10
|
const ComponentContext = (Platform as any).ComponentContext ?? Context;
|
|
11
11
|
const SkeletonContext = createContext({ loading: false });
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
// Single source of truth: holds both the OS flag and the user-adjusted rate.
|
|
13
|
+
export type FontScaleConfig = {
|
|
14
|
+
useOSFontScale?: boolean;
|
|
15
|
+
userScaleRate?: number;
|
|
16
|
+
};
|
|
17
|
+
const ScaleSizeContext = createContext<FontScaleConfig>({});
|
|
15
18
|
const TrackingScopeContext = createContext<{ scopeName?: string }>({
|
|
16
19
|
scopeName: undefined,
|
|
17
20
|
});
|
package/Input/Input.tsx
CHANGED
|
@@ -77,8 +77,7 @@ const Input = forwardRef(
|
|
|
77
77
|
const scaledFontSize = useScaleSize(14);
|
|
78
78
|
const scaleHeight = useScaleSize(size === 'small' ? 48 : 56);
|
|
79
79
|
const [focused, setFocused] = useState(false);
|
|
80
|
-
const
|
|
81
|
-
const haveValue = value !== undefined ? !!value : !!internalText;
|
|
80
|
+
const haveValue = !!value || !!defaultValue;
|
|
82
81
|
const inputRef = useRef<TextInput | null>(null);
|
|
83
82
|
const componentName = 'Input';
|
|
84
83
|
|
|
@@ -96,9 +95,6 @@ const Input = forwardRef(
|
|
|
96
95
|
};
|
|
97
96
|
|
|
98
97
|
const _onChangeText = (text: string) => {
|
|
99
|
-
if (value === undefined) {
|
|
100
|
-
setInternalText(text);
|
|
101
|
-
}
|
|
102
98
|
onChangeText?.(text);
|
|
103
99
|
};
|
|
104
100
|
|
|
@@ -113,13 +109,6 @@ const Input = forwardRef(
|
|
|
113
109
|
};
|
|
114
110
|
|
|
115
111
|
const _setText = (text: string) => {
|
|
116
|
-
if (__DEV__ && value !== undefined) {
|
|
117
|
-
console.error(
|
|
118
|
-
`${componentName}: calling ref.setText() on a controlled input (\`value\` is provided) is an anti-pattern. ` +
|
|
119
|
-
'It creates two sources of truth: setText will be overridden by React on the next render. ' +
|
|
120
|
-
'Update the state behind `value` instead.',
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
112
|
inputRef?.current?.setNativeProps({ text });
|
|
124
113
|
_onChangeText(text);
|
|
125
114
|
};
|
|
@@ -69,8 +69,7 @@ const InputPhoneNumber = forwardRef(
|
|
|
69
69
|
const context = useContext<any>(MiniAppContext);
|
|
70
70
|
const scaleHeight = useScaleSize(size === 'small' ? 48 : 56);
|
|
71
71
|
const [focused, setFocused] = useState(false);
|
|
72
|
-
const
|
|
73
|
-
const haveValue = value !== undefined ? !!value : !!internalText;
|
|
72
|
+
const haveValue = !!value || !!defaultValue;
|
|
74
73
|
const inputRef = useRef<TextInput | null>(null);
|
|
75
74
|
const componentName = 'InputPhoneNumber';
|
|
76
75
|
|
|
@@ -87,9 +86,6 @@ const InputPhoneNumber = forwardRef(
|
|
|
87
86
|
};
|
|
88
87
|
|
|
89
88
|
const _onChangeText = (text: string) => {
|
|
90
|
-
if (value === undefined) {
|
|
91
|
-
setInternalText(text);
|
|
92
|
-
}
|
|
93
89
|
onChangeText?.(text);
|
|
94
90
|
};
|
|
95
91
|
|
|
@@ -104,13 +100,6 @@ const InputPhoneNumber = forwardRef(
|
|
|
104
100
|
};
|
|
105
101
|
|
|
106
102
|
const _setText = (text: string) => {
|
|
107
|
-
if (__DEV__ && value !== undefined) {
|
|
108
|
-
console.error(
|
|
109
|
-
`${componentName}: calling ref.setText() on a controlled input (\`value\` is provided) is an anti-pattern. ` +
|
|
110
|
-
'It creates two sources of truth: setText will be overridden by React on the next render. ' +
|
|
111
|
-
'Update the state behind `value` instead.',
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
103
|
inputRef?.current?.setNativeProps({ text });
|
|
115
104
|
_onChangeText(text);
|
|
116
105
|
};
|
package/Layout/Screen.tsx
CHANGED
|
@@ -650,14 +650,7 @@ const Screen = forwardRef(
|
|
|
650
650
|
onScroll={handleScroll}
|
|
651
651
|
onScrollEndDrag={handleScrollEnd}
|
|
652
652
|
scrollEventThrottle={16}
|
|
653
|
-
style={
|
|
654
|
-
Styles.flex,
|
|
655
|
-
!scrollable && !Footer && !isTab && { paddingBottom: bottomInset },
|
|
656
|
-
]}
|
|
657
|
-
contentContainerStyle={[
|
|
658
|
-
scrollable && !Footer && !isTab && { paddingBottom: bottomInset },
|
|
659
|
-
scrollViewProps?.contentContainerStyle,
|
|
660
|
-
]}
|
|
653
|
+
style={Styles.flex}
|
|
661
654
|
>
|
|
662
655
|
{renderAnimatedHeader()}
|
|
663
656
|
|
package/Text/utils.ts
CHANGED
|
@@ -7,13 +7,18 @@ const DEFAULT_SCREEN_SIZE = 375;
|
|
|
7
7
|
const MAX_FONT_SCALE = 1.5;
|
|
8
8
|
const MAX_DEVICE_SCALE = 5;
|
|
9
9
|
|
|
10
|
-
const useScaleSize = (size: number,
|
|
11
|
-
const {
|
|
10
|
+
const useScaleSize = (size: number, userScaleRate?: number) => {
|
|
11
|
+
const { useOSFontScale = true, userScaleRate: ctxRate } =
|
|
12
|
+
useContext(ScaleSizeContext);
|
|
12
13
|
const fontScale = PixelRatio.getFontScale();
|
|
13
14
|
const { width } = useWindowDimensions();
|
|
14
15
|
const deviceScale = width / DEFAULT_SCREEN_SIZE;
|
|
15
16
|
|
|
16
|
-
const
|
|
17
|
+
const customRate = userScaleRate ?? ctxRate ?? 1;
|
|
18
|
+
|
|
19
|
+
if (!useOSFontScale) {
|
|
20
|
+
return customRate > 1 ? customRate * size : size;
|
|
21
|
+
}
|
|
17
22
|
|
|
18
23
|
let fontSizeDeviceScale = size;
|
|
19
24
|
let fontSizeOSScale = size;
|
|
@@ -27,8 +32,8 @@ const useScaleSize = (size: number, scaleRate?: number) => {
|
|
|
27
32
|
|
|
28
33
|
if (fontScale > 1) {
|
|
29
34
|
fontSizeOSScale = Math.min(
|
|
30
|
-
|
|
31
|
-
fontSizeOSScale *
|
|
35
|
+
fontScale * fontSizeOSScale,
|
|
36
|
+
fontSizeOSScale * MAX_FONT_SCALE,
|
|
32
37
|
);
|
|
33
38
|
}
|
|
34
39
|
|