@momo-kits/foundation 0.167.1-duotest.3 → 0.167.1-duotest.4
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/StackScreen.tsx +16 -6
- package/Layout/Screen.tsx +63 -16
- package/package.json +1 -1
|
@@ -75,13 +75,15 @@ const StackScreen: React.FC<any> = props => {
|
|
|
75
75
|
*/
|
|
76
76
|
const canAutoLayout = Platform.OS === 'ios' && !bottomTab;
|
|
77
77
|
const Observer: React.ComponentType<any> = ScrollObserverView ?? View;
|
|
78
|
-
|
|
78
|
+
// screens that drive the header themselves: a root <Screen>, a BottomTab
|
|
79
|
+
const [headerClaims] = useState(() => new Set<object>());
|
|
80
|
+
const contentRef = useRef<View>(null);
|
|
79
81
|
const [autoHeader, setAutoHeader] = useState(false);
|
|
80
82
|
const syncHeader = useCallback(() => {
|
|
81
83
|
setAutoHeader(
|
|
82
|
-
canAutoLayout && layout.isIPhoneDuo &&
|
|
84
|
+
canAutoLayout && layout.isIPhoneDuo && headerClaims.size === 0,
|
|
83
85
|
);
|
|
84
|
-
}, [canAutoLayout, layout.isIPhoneDuo]);
|
|
86
|
+
}, [canAutoLayout, layout.isIPhoneDuo, headerClaims]);
|
|
85
87
|
// parent effects run after the screen's, so a claim made on mount is already in
|
|
86
88
|
useEffect(syncHeader, [syncHeader]);
|
|
87
89
|
const headerScroll = useHeaderScrollState({ navigation }, autoHeader);
|
|
@@ -441,10 +443,16 @@ const StackScreen: React.FC<any> = props => {
|
|
|
441
443
|
onSetParams: (item: ScreenTrackingParams) => {
|
|
442
444
|
tracking.current.params = item;
|
|
443
445
|
},
|
|
444
|
-
claimHeader: () => {
|
|
445
|
-
|
|
446
|
+
claimHeader: (owner: object = headerClaims) => {
|
|
447
|
+
headerClaims.add(owner);
|
|
448
|
+
},
|
|
449
|
+
releaseHeader: (owner: object) => {
|
|
450
|
+
if (headerClaims.delete(owner)) {
|
|
451
|
+
syncHeader();
|
|
452
|
+
}
|
|
446
453
|
},
|
|
447
454
|
syncHeader,
|
|
455
|
+
contentRef,
|
|
448
456
|
}}
|
|
449
457
|
>
|
|
450
458
|
<TooltipPortalProvider>
|
|
@@ -458,7 +466,9 @@ const StackScreen: React.FC<any> = props => {
|
|
|
458
466
|
>
|
|
459
467
|
{headerScroll.background}
|
|
460
468
|
<Animated.View style={[styles.flex, headerScroll.contentStyle]}>
|
|
461
|
-
<
|
|
469
|
+
<View ref={contentRef} collapsable={false} style={styles.flex}>
|
|
470
|
+
<Component heightHeader={heightHeader} {...data} />
|
|
471
|
+
</View>
|
|
462
472
|
</Animated.View>
|
|
463
473
|
</Observer>
|
|
464
474
|
) : (
|
package/Layout/Screen.tsx
CHANGED
|
@@ -10,6 +10,7 @@ import React, {
|
|
|
10
10
|
useEffect,
|
|
11
11
|
useImperativeHandle,
|
|
12
12
|
useRef,
|
|
13
|
+
useState,
|
|
13
14
|
} from 'react';
|
|
14
15
|
import {
|
|
15
16
|
Animated,
|
|
@@ -213,9 +214,28 @@ const Screen = forwardRef(
|
|
|
213
214
|
ref: any,
|
|
214
215
|
) => {
|
|
215
216
|
const screenRef = useRef<View | ScrollView>(null);
|
|
216
|
-
const
|
|
217
|
+
const rootRef = useRef<View>(null);
|
|
217
218
|
const { theme } = useContext(ApplicationContext);
|
|
218
219
|
const screen: any = useContext(ScreenContext);
|
|
220
|
+
const screenLayout = useScreenLayout();
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* iPhone Duo: a Screen nested in the route's content (e.g. a TabView page) is not
|
|
224
|
+
* the route's screen. The route keeps clear of the side bar and drives the header,
|
|
225
|
+
* the nested Screen lays out as plain content.
|
|
226
|
+
*/
|
|
227
|
+
const [headerOwner] = useState(() => ({}));
|
|
228
|
+
const nested = useRef(false);
|
|
229
|
+
const [isNested, setIsNested] = useState(false);
|
|
230
|
+
const layout = isNested
|
|
231
|
+
? {
|
|
232
|
+
...screenLayout,
|
|
233
|
+
insetLeft: 0,
|
|
234
|
+
insetRight: 0,
|
|
235
|
+
sideBar: undefined,
|
|
236
|
+
statusBarClearance: undefined,
|
|
237
|
+
}
|
|
238
|
+
: screenLayout;
|
|
219
239
|
const insets = useSafeAreaInsets();
|
|
220
240
|
const frame = useSafeAreaFrame();
|
|
221
241
|
const heightHeader = useHeaderHeight();
|
|
@@ -293,9 +313,30 @@ const Screen = forwardRef(
|
|
|
293
313
|
*/
|
|
294
314
|
screen?.onSetParams?.(trackingParams);
|
|
295
315
|
// the screen drives its header, the stack screen's scroll observer stays off
|
|
296
|
-
|
|
316
|
+
if (!nested.current) {
|
|
317
|
+
screen?.claimHeader?.(headerOwner);
|
|
318
|
+
}
|
|
297
319
|
useEffect(() => {
|
|
320
|
+
// passive: the stack screen's content ref attaches after this screen's layout
|
|
321
|
+
const content = screen?.contentRef?.current;
|
|
322
|
+
if (!screenLayout.sideBar || !content || !rootRef.current) {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
rootRef.current.measureLayout(content, (x, y) => {
|
|
326
|
+
if (Math.abs(x) > 1 || Math.abs(y) > 1) {
|
|
327
|
+
nested.current = true;
|
|
328
|
+
setIsNested(true);
|
|
329
|
+
screen?.releaseHeader?.(headerOwner);
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
333
|
+
}, [!!screenLayout.sideBar]);
|
|
334
|
+
useEffect(() => {
|
|
335
|
+
if (!nested.current) {
|
|
336
|
+
screen?.claimHeader?.(headerOwner);
|
|
337
|
+
}
|
|
298
338
|
screen?.syncHeader?.();
|
|
339
|
+
return () => screen?.releaseHeader?.(headerOwner);
|
|
299
340
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
300
341
|
}, []);
|
|
301
342
|
|
|
@@ -536,7 +577,9 @@ const Screen = forwardRef(
|
|
|
536
577
|
StatusBar.setBarStyle(barStyle, true);
|
|
537
578
|
});
|
|
538
579
|
|
|
539
|
-
if (
|
|
580
|
+
if (nested.current) {
|
|
581
|
+
// the route drives the header
|
|
582
|
+
} else if (animatedHeader) {
|
|
540
583
|
setAnimatedHeader(animatedHeader);
|
|
541
584
|
} else if (inputSearchProps) {
|
|
542
585
|
setAnimatedSearch();
|
|
@@ -556,6 +599,7 @@ const Screen = forwardRef(
|
|
|
556
599
|
setAnimatedHeader,
|
|
557
600
|
setAnimatedSearch,
|
|
558
601
|
setHeaderType,
|
|
602
|
+
isNested,
|
|
559
603
|
]);
|
|
560
604
|
|
|
561
605
|
/**
|
|
@@ -596,7 +640,7 @@ const Screen = forwardRef(
|
|
|
596
640
|
if (offsetY > 50) {
|
|
597
641
|
color = Colors.black_17;
|
|
598
642
|
}
|
|
599
|
-
if (color !== currentTint.current) {
|
|
643
|
+
if (!nested.current && color !== currentTint.current) {
|
|
600
644
|
currentTint.current = color;
|
|
601
645
|
navigation?.setOptions({
|
|
602
646
|
headerTintColor: color,
|
|
@@ -734,6 +778,7 @@ const Screen = forwardRef(
|
|
|
734
778
|
|
|
735
779
|
return (
|
|
736
780
|
<View
|
|
781
|
+
ref={rootRef}
|
|
737
782
|
style={[
|
|
738
783
|
Styles.flex,
|
|
739
784
|
{
|
|
@@ -754,18 +799,20 @@ const Screen = forwardRef(
|
|
|
754
799
|
followScroll={useQuickReturn}
|
|
755
800
|
/>
|
|
756
801
|
) : (
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
802
|
+
!isNested && (
|
|
803
|
+
<HeaderExtendHeader
|
|
804
|
+
headerType={headerType}
|
|
805
|
+
heightHeader={heightHeader}
|
|
806
|
+
headerRightWidth={headerRightWidth}
|
|
807
|
+
animatedValue={sharedValue}
|
|
808
|
+
inputSearchProps={inputSearchProps}
|
|
809
|
+
navigation={navigation}
|
|
810
|
+
inputSearchRef={inputSearchRef}
|
|
811
|
+
useShadowHeader={useShadowHeader}
|
|
812
|
+
gradientColor={gradientColor}
|
|
813
|
+
headerBackground={headerBackground}
|
|
814
|
+
/>
|
|
815
|
+
)
|
|
769
816
|
)}
|
|
770
817
|
|
|
771
818
|
<KeyboardAvoidingView
|