@applicaster/zapp-react-native-ui-components 14.0.0-alpha.5974411329 → 14.0.0-alpha.6000342231
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/Components/AnimatedInOut/index.tsx +69 -26
- package/Components/BaseFocusable/index.tsx +23 -12
- package/Components/Cell/Cell.tsx +91 -64
- package/Components/Cell/CellWithFocusable.tsx +3 -0
- package/Components/Cell/FocusableWrapper.tsx +44 -0
- package/Components/Cell/TvOSCellComponent.tsx +80 -14
- package/Components/Cell/__tests__/CellWIthFocusable.test.js +3 -2
- package/Components/FeedLoader/FeedLoader.tsx +7 -16
- package/Components/FeedLoader/FeedLoaderHOC.tsx +21 -0
- package/Components/FeedLoader/index.js +2 -8
- package/Components/Focusable/Focusable.tsx +10 -3
- package/Components/Focusable/FocusableTvOS.tsx +2 -2
- package/Components/Focusable/Touchable.tsx +5 -3
- package/Components/Focusable/index.android.tsx +8 -4
- package/Components/FocusableGroup/FocusableTvOS.tsx +1 -1
- package/Components/FocusableList/FocusableItem.tsx +4 -3
- package/Components/FocusableList/FocusableListItemWrapper.tsx +2 -1
- package/Components/FocusableList/hooks/useCellState.android.ts +13 -3
- package/Components/FocusableList/index.tsx +16 -9
- package/Components/FreezeWithCallback/__tests__/index.test.tsx +67 -43
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +14 -17
- package/Components/HandlePlayable/HandlePlayable.tsx +14 -65
- package/Components/HandlePlayable/const.ts +3 -0
- package/Components/HandlePlayable/utils.ts +74 -0
- package/Components/Layout/TV/__tests__/index.test.tsx +0 -1
- package/Components/MasterCell/DefaultComponents/ActionButton.tsx +6 -2
- package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +0 -12
- package/Components/MasterCell/DefaultComponents/SecondaryImage/Image.tsx +65 -17
- package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/Image.test.tsx +21 -3
- package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/__snapshots__/Image.test.tsx.snap +6 -3
- package/Components/MasterCell/DefaultComponents/Text/index.tsx +26 -6
- package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +10 -10
- package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +18 -18
- package/Components/MasterCell/SharedUI/CollapsibleTextContainer/__tests__/index.test.tsx +10 -10
- package/Components/MasterCell/utils/behaviorProvider.ts +2 -2
- package/Components/MasterCell/utils/index.ts +1 -19
- package/Components/OfflineHandler/__tests__/index.test.tsx +6 -13
- package/Components/PlayerContainer/PlayerContainer.tsx +5 -17
- package/Components/PlayerImageBackground/index.tsx +3 -22
- package/Components/River/ComponentsMap/ComponentsMap.tsx +49 -42
- package/Components/River/ComponentsMap/ContextProviders/ComponentsMapHeightContext.ts +8 -0
- package/Components/River/ComponentsMap/ContextProviders/ComponentsMapRefContext.ts +8 -0
- package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +0 -1
- package/Components/River/RefreshControl.tsx +11 -19
- package/Components/River/__tests__/river.test.js +12 -26
- package/Components/Screen/TV/hooks/useInitialFocus.ts +14 -4
- package/Components/Screen/__tests__/Screen.test.tsx +5 -17
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +2 -0
- package/Components/Screen/__tests__/navigationHandler.test.ts +133 -22
- package/Components/Screen/index.tsx +22 -5
- package/Components/Screen/navigationHandler.ts +20 -2
- package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +2 -2
- package/Components/ScreenRevealManager/utils/index.ts +23 -0
- package/Components/ScreenRevealManager/withScreenRevealManager.tsx +54 -24
- package/Components/Tabs/TV/Tabs.android.tsx +1 -1
- package/Components/Tabs/Tabs.tsx +2 -3
- package/Components/TextInputTv/__tests__/__snapshots__/TextInputTv.test.js.snap +13 -0
- package/Components/TextInputTv/index.tsx +11 -0
- package/Components/Touchable/__tests__/touchable.test.tsx +12 -17
- package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +1 -0
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +117 -157
- package/Components/VideoModal/ModalAnimation/index.ts +2 -13
- package/Components/VideoModal/ModalAnimation/utils.ts +1 -327
- package/Components/VideoModal/PlayerDetails.tsx +5 -5
- package/Components/VideoModal/PlayerWrapper.tsx +14 -88
- package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +5 -5
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +1 -0
- package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +9 -1
- package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +40 -15
- package/Components/VideoModal/hooks/useModalSize.ts +10 -5
- package/Components/VideoModal/hooks/utils/__tests__/showDetails.test.ts +2 -2
- package/Components/VideoModal/hooks/utils/index.ts +4 -0
- package/Components/VideoModal/playerWrapperStyle.ts +70 -0
- package/Components/VideoModal/playerWrapperUtils.ts +91 -0
- package/Contexts/CellFocusedStateContext/index.tsx +27 -0
- package/Contexts/ConfigutaionContext/__tests__/ConfigurationProvider.test.tsx +3 -3
- package/Contexts/ScreenContext/index.tsx +28 -32
- package/Decorators/ConfigurationWrapper/__tests__/withConfigurationProvider.test.tsx +3 -3
- package/Decorators/RiverFeedLoader/__tests__/__snapshots__/riverFeedLoader.test.tsx.snap +221 -209
- package/Decorators/RiverFeedLoader/__tests__/riverFeedLoader.test.tsx +14 -16
- package/Decorators/RiverFeedLoader/__tests__/utils.test.ts +0 -20
- package/Decorators/RiverFeedLoader/index.tsx +21 -13
- package/Decorators/RiverFeedLoader/utils/getDatasourceUrl.ts +6 -10
- package/Decorators/RiverFeedLoader/utils/index.ts +0 -35
- package/Decorators/ZappPipesDataConnector/__tests__/UrlFeedResolver.test.tsx +27 -27
- package/Decorators/ZappPipesDataConnector/resolvers/UrlFeedResolver.tsx +3 -5
- package/Decorators/ZappPipesDataConnector/utils/useFilter.tsx +68 -76
- package/events/index.ts +3 -0
- package/package.json +5 -5
- package/Components/River/__tests__/__snapshots__/river.test.js.snap +0 -27
- package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +0 -60
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +0 -421
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +0 -176
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +0 -500
- package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +0 -108
|
@@ -1,25 +1,16 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import * as R from "ramda";
|
|
3
|
+
import { selectZappPipes } from "@applicaster/zapp-react-native-redux";
|
|
3
4
|
|
|
4
5
|
type Props = {
|
|
5
|
-
zappPipes:
|
|
6
|
-
loadPipesData:
|
|
7
|
-
feed
|
|
8
|
-
|
|
9
|
-
clearCache: boolean;
|
|
10
|
-
meta: any;
|
|
11
|
-
loadLocalFavorites: boolean;
|
|
12
|
-
silentRefresh: boolean;
|
|
13
|
-
parentFeed: ZappFeed;
|
|
14
|
-
callback: () => void;
|
|
15
|
-
bodyParams: any;
|
|
16
|
-
riverId: string;
|
|
17
|
-
}>
|
|
18
|
-
) => void;
|
|
6
|
+
zappPipes: ReturnType<typeof selectZappPipes>;
|
|
7
|
+
loadPipesData: ReturnType<
|
|
8
|
+
typeof import("@applicaster/zapp-react-native-utils/reactHooks/feed").useLoadPipesDataDispatch
|
|
9
|
+
>;
|
|
19
10
|
feedUrl: string;
|
|
20
|
-
children: (feed: ZappFeed) => React.
|
|
11
|
+
children: (feed: ZappFeed) => React.ReactNode;
|
|
21
12
|
onFeedLoaded: (feed: ZappFeed) => {};
|
|
22
|
-
onError: (
|
|
13
|
+
onError: (error: ZappPipesData["error"]) => {};
|
|
23
14
|
refreshing: boolean;
|
|
24
15
|
refreshCallback: () => void;
|
|
25
16
|
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
selectZappPipes,
|
|
4
|
+
useAppSelector,
|
|
5
|
+
} from "@applicaster/zapp-react-native-redux";
|
|
6
|
+
import { useLoadPipesDataDispatch } from "@applicaster/zapp-react-native-utils/reactHooks/feed";
|
|
7
|
+
|
|
8
|
+
export const FeedLoaderHOC = (_Component: any) => {
|
|
9
|
+
return function FeedLoaderHOC(props: any) {
|
|
10
|
+
const zappPipes = useAppSelector(selectZappPipes);
|
|
11
|
+
const loadPipesData = useLoadPipesDataDispatch();
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<_Component
|
|
15
|
+
{...props}
|
|
16
|
+
zappPipes={zappPipes}
|
|
17
|
+
loadPipesData={loadPipesData}
|
|
18
|
+
/>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
};
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import * as R from "ramda";
|
|
2
|
-
|
|
3
|
-
import { connectToStore } from "@applicaster/zapp-react-native-redux/utils/connectToStore";
|
|
4
|
-
import { loadPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";
|
|
5
|
-
|
|
6
1
|
import { FeedLoaderComponent } from "./FeedLoader";
|
|
2
|
+
import { FeedLoaderHOC } from "./FeedLoaderHOC";
|
|
7
3
|
|
|
8
|
-
export const FeedLoader =
|
|
9
|
-
loadPipesData,
|
|
10
|
-
})(FeedLoaderComponent);
|
|
4
|
+
export const FeedLoader = FeedLoaderHOC(FeedLoaderComponent);
|
|
@@ -6,6 +6,7 @@ import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focu
|
|
|
6
6
|
import { LONG_KEY_PRESS_TIMEOUT } from "@applicaster/quick-brick-core/const";
|
|
7
7
|
import { withFocusableContext } from "../../Contexts/FocusableGroupContext/withFocusableContext";
|
|
8
8
|
import { StyleSheet, ViewStyle } from "react-native";
|
|
9
|
+
import { AccessibilityManager } from "@applicaster/zapp-react-native-utils/appUtils/accessibilityManager";
|
|
9
10
|
|
|
10
11
|
type Props = {
|
|
11
12
|
initialFocus?: boolean;
|
|
@@ -20,7 +21,7 @@ type Props = {
|
|
|
20
21
|
onPressOut?: () => void;
|
|
21
22
|
onLongPress?: () => void;
|
|
22
23
|
handleFocus?: ({ mouse }: { mouse: boolean }) => void;
|
|
23
|
-
children: (boolean, string) => React.
|
|
24
|
+
children: (boolean, string) => React.ReactNode;
|
|
24
25
|
selected?: boolean;
|
|
25
26
|
style?: ViewStyle[] | ViewStyle;
|
|
26
27
|
};
|
|
@@ -29,6 +30,7 @@ class Focusable extends BaseFocusable<Props> {
|
|
|
29
30
|
isGroup: boolean;
|
|
30
31
|
mouse: boolean;
|
|
31
32
|
longPressTimeout = null;
|
|
33
|
+
accessibilityManager: AccessibilityManager;
|
|
32
34
|
|
|
33
35
|
constructor(props) {
|
|
34
36
|
super(props);
|
|
@@ -43,6 +45,8 @@ class Focusable extends BaseFocusable<Props> {
|
|
|
43
45
|
this.resetLongPressTimeout = this.resetLongPressTimeout.bind(this);
|
|
44
46
|
this.longPress = this.longPress.bind(this);
|
|
45
47
|
this.press = this.press.bind(this);
|
|
48
|
+
|
|
49
|
+
this.accessibilityManager = AccessibilityManager.getInstance();
|
|
46
50
|
}
|
|
47
51
|
|
|
48
52
|
/**
|
|
@@ -123,12 +127,15 @@ class Focusable extends BaseFocusable<Props> {
|
|
|
123
127
|
}
|
|
124
128
|
|
|
125
129
|
render() {
|
|
126
|
-
const { children, style
|
|
130
|
+
const { children, style } = this.props;
|
|
127
131
|
const { focused } = this.state;
|
|
128
132
|
|
|
129
133
|
const id = this.getId();
|
|
130
134
|
const focusableId = `focusable-${id}`;
|
|
131
135
|
|
|
136
|
+
const accessibilityProps =
|
|
137
|
+
this.accessibilityManager.getWebAccessibilityProps(this.props);
|
|
138
|
+
|
|
132
139
|
return (
|
|
133
140
|
<div
|
|
134
141
|
id={focusableId}
|
|
@@ -141,7 +148,7 @@ class Focusable extends BaseFocusable<Props> {
|
|
|
141
148
|
data-testid={focusableId}
|
|
142
149
|
focused-teststate={focused ? "focused" : "default"}
|
|
143
150
|
style={StyleSheet.flatten(style) as any as React.CSSProperties}
|
|
144
|
-
{...
|
|
151
|
+
{...accessibilityProps}
|
|
145
152
|
>
|
|
146
153
|
{children(focused, { mouse: this.mouse })}
|
|
147
154
|
</div>
|
|
@@ -19,7 +19,7 @@ type Props = {
|
|
|
19
19
|
onPress?: (nativeEvent: any) => void;
|
|
20
20
|
onFocus?: (nativeEvent: any) => void;
|
|
21
21
|
onBlur?: (nativeEvent: any) => void;
|
|
22
|
-
children: (focused?: boolean) => React.ReactNode;
|
|
22
|
+
children: ((focused?: boolean) => React.ReactNode) | React.ReactNode;
|
|
23
23
|
isParallaxDisabled: boolean;
|
|
24
24
|
preferredFocus?: boolean;
|
|
25
25
|
selected?: boolean;
|
|
@@ -204,7 +204,7 @@ export class Focusable extends BaseFocusable<Props> {
|
|
|
204
204
|
{...this.nextFocusableReactTags}
|
|
205
205
|
{...otherProps}
|
|
206
206
|
>
|
|
207
|
-
{
|
|
207
|
+
{typeof children === "function" ? children(focused) : children}
|
|
208
208
|
</FocusableItemNative>
|
|
209
209
|
);
|
|
210
210
|
}
|
|
@@ -9,7 +9,8 @@ type Props = {
|
|
|
9
9
|
onLongPress?: (ref: FocusManager.TouchableRef) => void;
|
|
10
10
|
onFocus?: (
|
|
11
11
|
ref: FocusManager.TouchableRef,
|
|
12
|
-
options: FocusManager.Android.CallbackOptions
|
|
12
|
+
options: FocusManager.Android.CallbackOptions,
|
|
13
|
+
context: Option<FocusManager.FocusContext>
|
|
13
14
|
) => void;
|
|
14
15
|
onBlur?: (
|
|
15
16
|
ref: FocusManager.TouchableRef,
|
|
@@ -39,9 +40,10 @@ export class Touchable extends React.Component<Props> {
|
|
|
39
40
|
|
|
40
41
|
onFocus(
|
|
41
42
|
focusableRef: FocusManager.TouchableRef,
|
|
42
|
-
options: FocusManager.Android.CallbackOptions
|
|
43
|
+
options: FocusManager.Android.CallbackOptions,
|
|
44
|
+
context: Option<FocusManager.FocusContext>
|
|
43
45
|
): void {
|
|
44
|
-
this.props?.onFocus?.(focusableRef, options);
|
|
46
|
+
this.props?.onFocus?.(focusableRef, options, context);
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
onBlur(
|
|
@@ -22,7 +22,8 @@ type Props = {
|
|
|
22
22
|
onPress?: (ref: FocusManager.FocusableRef) => void;
|
|
23
23
|
onFocus?: (
|
|
24
24
|
ref: FocusManager.FocusableRef,
|
|
25
|
-
options: FocusManager.Android.CallbackOptions
|
|
25
|
+
options: FocusManager.Android.CallbackOptions,
|
|
26
|
+
context?: FocusManager.FocusContext
|
|
26
27
|
) => void;
|
|
27
28
|
onBlur?: (
|
|
28
29
|
ref: FocusManager.FocusableRef,
|
|
@@ -32,6 +33,7 @@ type Props = {
|
|
|
32
33
|
onPressOut?: (ref: FocusManager.FocusableRef) => void;
|
|
33
34
|
onLongPress?: (ref: FocusManager.FocusableRef) => void;
|
|
34
35
|
onRegister?: () => void;
|
|
36
|
+
onUnregister?: () => void;
|
|
35
37
|
isFocusableCell?: boolean;
|
|
36
38
|
/** only for FocusableScrollView */
|
|
37
39
|
onSetIsFocusable?: (isFocusable: boolean) => void;
|
|
@@ -70,6 +72,7 @@ function FocusableComponent(props: Props, forwardedRef) {
|
|
|
70
72
|
onPressOut,
|
|
71
73
|
onLongPress,
|
|
72
74
|
onRegister = noop,
|
|
75
|
+
onUnregister = noop,
|
|
73
76
|
isFocusableCell = true,
|
|
74
77
|
onSetIsFocusable,
|
|
75
78
|
} = props;
|
|
@@ -113,9 +116,10 @@ function FocusableComponent(props: Props, forwardedRef) {
|
|
|
113
116
|
|
|
114
117
|
return () => {
|
|
115
118
|
unregister();
|
|
119
|
+
onUnregister();
|
|
116
120
|
};
|
|
117
121
|
}
|
|
118
|
-
}, [id, onRegister, isFocusableCell, parentFocusableId]);
|
|
122
|
+
}, [id, onRegister, onUnregister, isFocusableCell, parentFocusableId]);
|
|
119
123
|
|
|
120
124
|
if (R.isNil(id)) {
|
|
121
125
|
// eslint-disable-next-line no-console
|
|
@@ -125,9 +129,9 @@ function FocusableComponent(props: Props, forwardedRef) {
|
|
|
125
129
|
}
|
|
126
130
|
|
|
127
131
|
const _onFocus = React.useCallback(
|
|
128
|
-
(ref, options) => {
|
|
132
|
+
(ref, options, context) => {
|
|
129
133
|
setFocused(true);
|
|
130
|
-
onFocus?.(ref, options);
|
|
134
|
+
onFocus?.(ref, options, context);
|
|
131
135
|
},
|
|
132
136
|
[onFocus]
|
|
133
137
|
);
|
|
@@ -10,7 +10,8 @@ type FocusableItemComponentProps = {
|
|
|
10
10
|
onFocus: (
|
|
11
11
|
element: FocusManager.FocusableRef,
|
|
12
12
|
renderArgs: { item: FocusableItemComponentProps["item"]; index: number },
|
|
13
|
-
|
|
13
|
+
options: FocusManager.Android.CallbackOptions,
|
|
14
|
+
context: Option<FocusManager.FocusContext>
|
|
14
15
|
) => void;
|
|
15
16
|
onListElementFocus?: (any, RenderItemProps, Direction) => void;
|
|
16
17
|
onListElementBlur?: (any, RenderItemProps, Direction) => void;
|
|
@@ -45,8 +46,8 @@ const FocusableItemComponent = ({
|
|
|
45
46
|
const renderArgs = { item, index };
|
|
46
47
|
|
|
47
48
|
const onFocusHandler = React.useCallback(
|
|
48
|
-
(element,
|
|
49
|
-
onFocus?.(element, renderArgs,
|
|
49
|
+
(element, options, context) => {
|
|
50
|
+
onFocus?.(element, renderArgs, options, context);
|
|
50
51
|
},
|
|
51
52
|
[item, onFocus]
|
|
52
53
|
);
|
|
@@ -17,7 +17,8 @@ type Props = {
|
|
|
17
17
|
onFocus: (
|
|
18
18
|
element: FocusManager.FocusableRef,
|
|
19
19
|
renderArgs: { item: Item; index: number },
|
|
20
|
-
|
|
20
|
+
options: FocusManager.Android.CallbackOptions,
|
|
21
|
+
context: FocusManager.FocusContext
|
|
21
22
|
) => void;
|
|
22
23
|
onListElementBlur?: (any, RenderItemProps, Direction) => void;
|
|
23
24
|
onListElementPress?: (any, RenderItemProps) => void;
|
|
@@ -10,15 +10,25 @@ export const useCellState = (id: string) => {
|
|
|
10
10
|
);
|
|
11
11
|
|
|
12
12
|
React.useEffect(() => {
|
|
13
|
-
const
|
|
13
|
+
const focusHandler = (focusable) => {
|
|
14
14
|
const isChildren = focusManager.isFocusableChildOf(focusable, id);
|
|
15
|
+
|
|
15
16
|
setCurrentCellFocused(isChildren);
|
|
16
17
|
};
|
|
17
18
|
|
|
18
|
-
focusManager.on(FOCUS_EVENTS.FOCUS,
|
|
19
|
+
focusManager.on(FOCUS_EVENTS.FOCUS, focusHandler);
|
|
20
|
+
|
|
21
|
+
const resetHandler = ({ focusedId }) => {
|
|
22
|
+
if (id === focusedId) {
|
|
23
|
+
setCurrentCellFocused(false);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
focusManager.on(FOCUS_EVENTS.RESET, resetHandler);
|
|
19
28
|
|
|
20
29
|
return () => {
|
|
21
|
-
focusManager.removeHandler(FOCUS_EVENTS.FOCUS,
|
|
30
|
+
focusManager.removeHandler(FOCUS_EVENTS.FOCUS, focusHandler);
|
|
31
|
+
focusManager.removeHandler(FOCUS_EVENTS.RESET, resetHandler);
|
|
22
32
|
};
|
|
23
33
|
}, [id]);
|
|
24
34
|
|
|
@@ -20,27 +20,34 @@ import { FocusableScrollView } from "../FocusableScrollView";
|
|
|
20
20
|
const mapIndexed = R.addIndex(R.map);
|
|
21
21
|
|
|
22
22
|
export type IListRenderItem<ItemT> = (
|
|
23
|
-
info:
|
|
23
|
+
info: {
|
|
24
24
|
focused: boolean;
|
|
25
25
|
onLoadFinished: () => void;
|
|
26
26
|
onLoadFailed: () => void;
|
|
27
|
-
}
|
|
27
|
+
} & IListRenderItemInfo<ItemT>
|
|
28
28
|
) => React.ReactElement | null;
|
|
29
29
|
|
|
30
30
|
export const getFocusableId = (parentId, index) =>
|
|
31
31
|
`${parentId}___index:${index}`;
|
|
32
32
|
|
|
33
|
+
type Item = ZappEntry | ZappUIComponent | any;
|
|
34
|
+
|
|
33
35
|
export type Props<ItemT> = FlatListProps<ItemT> & {
|
|
34
36
|
id?: number | string;
|
|
35
37
|
horizontal?: boolean;
|
|
36
38
|
loop?: boolean;
|
|
37
39
|
numColumns?: number;
|
|
38
40
|
data: ZappEntry[] | ZappUIComponent[] | any[];
|
|
39
|
-
onListElementFocus?: (
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
onListElementFocus?: (
|
|
42
|
+
element: FocusManager.FocusableRef,
|
|
43
|
+
renderItemProps: { item: Item; index: number },
|
|
44
|
+
options: FocusManager.Android.CallbackOptions,
|
|
45
|
+
context: FocusManager.FocusContext
|
|
46
|
+
) => void;
|
|
47
|
+
onListElementBlur?: (element, renderItemProps, direction) => void;
|
|
48
|
+
onListElementPress?: (element, renderItemProps) => void;
|
|
49
|
+
onListElementPressOut?: (element, renderItemProps) => void;
|
|
50
|
+
onListElementLongPress?: (element, renderItemProps) => void;
|
|
44
51
|
focusableItemProps?: any;
|
|
45
52
|
focused?: boolean;
|
|
46
53
|
initialScrollIndex?: number;
|
|
@@ -138,11 +145,11 @@ function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
|
|
|
138
145
|
);
|
|
139
146
|
|
|
140
147
|
const onFocus = React.useCallback(
|
|
141
|
-
(element, renderArgs,
|
|
148
|
+
(element, renderArgs, options, context) => {
|
|
142
149
|
const { index } = renderArgs;
|
|
143
150
|
|
|
144
151
|
updateFocusedIndex?.(index);
|
|
145
|
-
onListElementFocus?.(element, renderArgs,
|
|
152
|
+
onListElementFocus?.(element, renderArgs, options, context);
|
|
146
153
|
},
|
|
147
154
|
[onListElementFocus, updateFocusedIndex]
|
|
148
155
|
);
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import React, { Dispatch, useEffect, useState } from "react";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
create,
|
|
5
|
-
ReactTestRenderer,
|
|
6
|
-
ReactTestRendererJSON,
|
|
7
|
-
} from "react-test-renderer";
|
|
2
|
+
import { act, render } from "@testing-library/react-native";
|
|
3
|
+
import { View } from "react-native";
|
|
8
4
|
import { FreezeWithCallback } from "../index";
|
|
9
5
|
|
|
10
|
-
const SimpleContent = () => <
|
|
6
|
+
const SimpleContent = () => <View testID="simple-content" />;
|
|
11
7
|
|
|
12
8
|
interface InnerProps {
|
|
13
9
|
value: number;
|
|
14
10
|
}
|
|
11
|
+
|
|
15
12
|
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
16
|
-
const Inner = ({ value }: InnerProps) =>
|
|
13
|
+
const Inner = ({ value }: InnerProps) => (
|
|
14
|
+
<View testID="inner-component" data-value={value} />
|
|
15
|
+
);
|
|
17
16
|
|
|
18
17
|
interface TestSubscriber {
|
|
19
18
|
renderCount: number;
|
|
@@ -51,24 +50,20 @@ const Container = ({ freeze, children }: ContainerProps) => (
|
|
|
51
50
|
);
|
|
52
51
|
|
|
53
52
|
function setupTest(initialFreeze: boolean = false) {
|
|
54
|
-
let testRenderer: ReactTestRenderer | undefined;
|
|
55
53
|
const [Subscriber, subscriberState] = createSubscriberComponent();
|
|
56
54
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
<
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
);
|
|
63
|
-
});
|
|
55
|
+
const renderResult = render(
|
|
56
|
+
<Container freeze={initialFreeze}>
|
|
57
|
+
<Subscriber />
|
|
58
|
+
</Container>
|
|
59
|
+
);
|
|
64
60
|
|
|
65
61
|
return {
|
|
66
|
-
|
|
67
|
-
testInstance: testRenderer?.root,
|
|
62
|
+
renderResult,
|
|
68
63
|
subscriberState,
|
|
69
64
|
updateFreeze: (freeze: boolean) => {
|
|
70
65
|
act(() =>
|
|
71
|
-
|
|
66
|
+
renderResult.rerender(
|
|
72
67
|
<Container freeze={freeze}>
|
|
73
68
|
<Subscriber />
|
|
74
69
|
</Container>
|
|
@@ -80,91 +75,120 @@ function setupTest(initialFreeze: boolean = false) {
|
|
|
80
75
|
|
|
81
76
|
describe("FreezeWithCallback", () => {
|
|
82
77
|
test("Renders stuff not frozen", () => {
|
|
83
|
-
const
|
|
78
|
+
const { getByTestId } = render(
|
|
84
79
|
<Container freeze={false}>
|
|
85
80
|
<SimpleContent />
|
|
86
81
|
</Container>
|
|
87
82
|
);
|
|
88
83
|
|
|
89
|
-
expect(
|
|
84
|
+
expect(getByTestId("simple-content")).toBeTruthy();
|
|
90
85
|
});
|
|
91
86
|
|
|
92
87
|
test("Does not render stuff when frozen", () => {
|
|
93
|
-
const
|
|
88
|
+
const { queryByTestId } = render(
|
|
94
89
|
<Container freeze>
|
|
95
90
|
<SimpleContent />
|
|
96
91
|
</Container>
|
|
97
92
|
);
|
|
98
93
|
|
|
99
|
-
expect(
|
|
94
|
+
expect(queryByTestId("simple-content")).toBe(null);
|
|
100
95
|
});
|
|
101
96
|
|
|
102
97
|
test("Stuff is gone after freeze", () => {
|
|
103
|
-
const
|
|
98
|
+
const { toJSON, getByTestId, rerender } = render(
|
|
104
99
|
<Container freeze={false}>
|
|
105
100
|
<SimpleContent />
|
|
106
101
|
</Container>
|
|
107
102
|
);
|
|
108
103
|
|
|
109
|
-
expect(
|
|
104
|
+
expect(getByTestId("simple-content")).toBeTruthy();
|
|
110
105
|
|
|
111
106
|
act(() =>
|
|
112
|
-
|
|
107
|
+
rerender(
|
|
113
108
|
<Container freeze>
|
|
114
109
|
<SimpleContent />
|
|
115
110
|
</Container>
|
|
116
111
|
)
|
|
117
112
|
);
|
|
118
113
|
|
|
119
|
-
expect(
|
|
114
|
+
expect(toJSON()).toBe(null);
|
|
120
115
|
});
|
|
121
116
|
|
|
122
117
|
test("Updates work when not frozen", () => {
|
|
123
|
-
const {
|
|
118
|
+
const { renderResult, subscriberState } = setupTest();
|
|
119
|
+
|
|
120
|
+
expect(
|
|
121
|
+
renderResult.getByTestId("inner-component").props["data-value"]
|
|
122
|
+
).toEqual(0);
|
|
124
123
|
|
|
125
|
-
expect(testInstance?.findByType(Inner).props.value).toEqual(0);
|
|
126
124
|
act(() => subscriberState.subscription(1));
|
|
127
|
-
|
|
125
|
+
|
|
126
|
+
expect(
|
|
127
|
+
renderResult.getByTestId("inner-component").props["data-value"]
|
|
128
|
+
).toEqual(1);
|
|
129
|
+
|
|
128
130
|
expect(subscriberState.renderCount).toBe(2);
|
|
129
131
|
});
|
|
130
132
|
|
|
131
133
|
test("Updates does not propagate when frozen", () => {
|
|
132
|
-
const {
|
|
134
|
+
const { renderResult, subscriberState, updateFreeze } = setupTest();
|
|
135
|
+
|
|
136
|
+
expect(
|
|
137
|
+
renderResult.getByTestId("inner-component").props["data-value"]
|
|
138
|
+
).toEqual(0);
|
|
133
139
|
|
|
134
|
-
expect(testInstance?.findByType(Inner).props.value).toEqual(0);
|
|
135
140
|
updateFreeze(true);
|
|
136
141
|
act(() => subscriberState.subscription(1));
|
|
137
|
-
|
|
142
|
+
|
|
143
|
+
expect(
|
|
144
|
+
renderResult.getByTestId("inner-component").props["data-value"]
|
|
145
|
+
).toEqual(0);
|
|
146
|
+
|
|
138
147
|
expect(subscriberState.renderCount).toBe(1);
|
|
139
148
|
});
|
|
140
149
|
|
|
141
150
|
test("State persists after defrost", () => {
|
|
142
|
-
const {
|
|
143
|
-
|
|
151
|
+
const { renderResult, subscriberState, updateFreeze } = setupTest();
|
|
152
|
+
|
|
153
|
+
expect(
|
|
154
|
+
renderResult.getByTestId("inner-component").props["data-value"]
|
|
155
|
+
).toEqual(0);
|
|
144
156
|
|
|
145
|
-
expect(testInstance?.findByType(Inner).props.value).toEqual(0);
|
|
146
157
|
act(() => subscriberState.subscription(1));
|
|
147
|
-
|
|
158
|
+
|
|
159
|
+
expect(
|
|
160
|
+
renderResult.getByTestId("inner-component").props["data-value"]
|
|
161
|
+
).toEqual(1);
|
|
148
162
|
|
|
149
163
|
updateFreeze(true);
|
|
150
|
-
expect(
|
|
164
|
+
expect(renderResult.toJSON()).toBe(null);
|
|
151
165
|
|
|
152
166
|
updateFreeze(false);
|
|
153
|
-
expect((
|
|
154
|
-
|
|
167
|
+
expect(renderResult.getByTestId("inner-component")).toBeTruthy();
|
|
168
|
+
|
|
169
|
+
expect(
|
|
170
|
+
renderResult.getByTestId("inner-component").props["data-value"]
|
|
171
|
+
).toEqual(1);
|
|
155
172
|
});
|
|
156
173
|
|
|
157
174
|
test("Update propagate after defrost", () => {
|
|
158
|
-
const {
|
|
175
|
+
const { renderResult, subscriberState, updateFreeze } = setupTest();
|
|
159
176
|
|
|
160
177
|
updateFreeze(true);
|
|
161
178
|
act(() => subscriberState.subscription(1));
|
|
162
179
|
act(() => subscriberState.subscription(2));
|
|
163
180
|
act(() => subscriberState.subscription(3));
|
|
164
|
-
|
|
181
|
+
|
|
182
|
+
expect(
|
|
183
|
+
renderResult.getByTestId("inner-component").props["data-value"]
|
|
184
|
+
).toEqual(0);
|
|
165
185
|
|
|
166
186
|
updateFreeze(false);
|
|
167
|
-
|
|
187
|
+
|
|
188
|
+
expect(
|
|
189
|
+
renderResult.getByTestId("inner-component").props["data-value"]
|
|
190
|
+
).toEqual(3);
|
|
191
|
+
|
|
168
192
|
expect(subscriberState.renderCount).toBe(2);
|
|
169
193
|
});
|
|
170
194
|
});
|
|
@@ -3,8 +3,6 @@ import { all, equals, path, prop, isEmpty, pluck, values } from "ramda";
|
|
|
3
3
|
import { useEffect, useMemo } from "react";
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
|
-
ZappPipes,
|
|
7
|
-
useAppDispatch,
|
|
8
6
|
useLayoutPresets,
|
|
9
7
|
useZappPipesFeed,
|
|
10
8
|
} from "@applicaster/zapp-react-native-redux";
|
|
@@ -25,6 +23,7 @@ import {
|
|
|
25
23
|
} from "@applicaster/zapp-react-native-utils/reactHooks/feed/useInflatedUrl";
|
|
26
24
|
|
|
27
25
|
import { produce } from "immer";
|
|
26
|
+
import { useLoadPipesDataDispatch } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
28
27
|
// types reference
|
|
29
28
|
|
|
30
29
|
declare interface CurationEntry {
|
|
@@ -126,8 +125,6 @@ export const getFinalComponents = (
|
|
|
126
125
|
export const useCurationAPI = (
|
|
127
126
|
components: Array<ZappUIComponent>
|
|
128
127
|
): ZappUIComponent[] => {
|
|
129
|
-
const dispatch = useAppDispatch();
|
|
130
|
-
|
|
131
128
|
const smartComponents = useMemo(
|
|
132
129
|
() => components?.filter?.(isSmartComponent) ?? [],
|
|
133
130
|
[components]
|
|
@@ -145,17 +142,15 @@ export const useCurationAPI = (
|
|
|
145
142
|
const url = path(SOURCE_PATH, component);
|
|
146
143
|
const mapping = path(MAPPING_PATH, component);
|
|
147
144
|
|
|
148
|
-
map[component.id] =
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
})
|
|
158
|
-
: url;
|
|
145
|
+
map[component.id] = getInflatedDataSourceUrl({
|
|
146
|
+
source: url,
|
|
147
|
+
contexts: {
|
|
148
|
+
entry: entryContext,
|
|
149
|
+
screen: screenContext,
|
|
150
|
+
search: getSearchContext(searchContext, mapping),
|
|
151
|
+
},
|
|
152
|
+
mapping,
|
|
153
|
+
});
|
|
159
154
|
});
|
|
160
155
|
|
|
161
156
|
return map;
|
|
@@ -163,17 +158,19 @@ export const useCurationAPI = (
|
|
|
163
158
|
|
|
164
159
|
const urls = useMemo<string[]>(() => Object.values(urlsMap), [urlsMap]);
|
|
165
160
|
|
|
161
|
+
const loadPipesDataDispatcher = useLoadPipesDataDispatch();
|
|
162
|
+
|
|
166
163
|
useEffect(() => {
|
|
167
164
|
urls.forEach((url, index) => {
|
|
168
165
|
if (url) {
|
|
169
|
-
|
|
166
|
+
loadPipesDataDispatcher(url, { clearCache: false });
|
|
170
167
|
} else {
|
|
171
168
|
logger.log_error("Curation url is empty", {
|
|
172
169
|
componentId: smartComponents?.[index]?.id,
|
|
173
170
|
});
|
|
174
171
|
}
|
|
175
172
|
});
|
|
176
|
-
}, [urls]);
|
|
173
|
+
}, [urls, loadPipesDataDispatcher]);
|
|
177
174
|
|
|
178
175
|
const feeds = useZappPipesFeed(urls);
|
|
179
176
|
const layoutPresets = useLayoutPresets();
|