@applicaster/zapp-react-native-ui-components 13.0.0-alpha.6714678893 → 13.0.0-alpha.7100577251
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/AppContainer/__tests__/__snapshots__/AppContainer.test.js.snap +1 -1
- package/Components/AudioPlayer/__tests__/__snapshots__/Runtime.test.js.snap +4 -4
- package/Components/AudioPlayer/__tests__/__snapshots__/artWork.test.js.snap +3 -3
- package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayer.test.js.snap +6 -6
- package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayerLayout.test.js.snap +7 -7
- package/Components/AudioPlayer/__tests__/__snapshots__/channel.test.js.snap +3 -3
- package/Components/AudioPlayer/__tests__/__snapshots__/summary.test.js.snap +2 -2
- package/Components/AudioPlayer/__tests__/__snapshots__/title.test.js.snap +2 -2
- package/Components/BaseFocusable/index.ios.ts +1 -1
- package/Components/BaseFocusable/index.tsx +66 -29
- package/Components/Cell/Cell.tsx +7 -3
- package/Components/Cell/TvOSCellComponent.tsx +4 -8
- package/Components/CellRendererResolver/__tests__/__snapshots__/cellRendererResolver.test.js.snap +20 -20
- package/Components/CellRendererResolver/__tests__/cellRendererResolver.test.js +5 -3
- package/Components/ComponentResolver/__tests__/__snapshots__/componentResolver.test.js.snap +5 -5
- package/Components/ComponentResolver/__tests__/componentResolver.test.js +11 -9
- package/Components/DisplayState/__tests__/__snapshots__/displayState.test.js.snap +2 -2
- package/Components/Focusable/Focusable.tsx +0 -54
- package/Components/Focusable/FocusableTvOS.tsx +1 -5
- package/Components/Focusable/Touchable.tsx +19 -20
- package/Components/FocusableList/index.tsx +0 -1
- package/Components/FocusableScrollView/index.tsx +12 -39
- package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +9 -0
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +1 -1
- package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +1 -0
- package/Components/Layout/TV/__tests__/__snapshots__/LayoutContainer.test.tsx.snap +1 -1
- package/Components/Layout/TV/__tests__/__snapshots__/NavBarContainer.test.tsx.snap +3 -3
- package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +9 -9
- package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +1 -1
- package/Components/Layout/TV/__tests__/index.test.tsx +7 -3
- package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +66 -0
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +4 -1
- package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +6 -12
- package/Components/MasterCell/DefaultComponents/ImageBorderContainer/__tests__/index.test.ts +93 -0
- package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/__snapshots__/Image.test.tsx.snap +3 -3
- package/Components/MasterCell/DefaultComponents/SecondaryImage/utils.ts +1 -1
- package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
- package/Components/MasterCell/SharedUI/CollapsibleTextContainer/__tests__/__snapshots__/index.test.tsx.snap +1 -1
- package/Components/MasterCell/__tests__/__snapshots__/dataAdapter.test.js.snap +180 -180
- package/Components/MasterCell/__tests__/__snapshots__/elementMapper.test.js.snap +7 -7
- package/Components/MasterCell/__tests__/__snapshots__/masterCell.test.js.snap +34 -34
- package/Components/MasterCell/hooks/useAsyncRendering/MasterCellAsyncRenderManager.ts +2 -2
- package/Components/MasterCell/hooks/useAsyncRendering/index.ts +2 -2
- package/Components/MasterCell/utils/index.ts +1 -1
- package/Components/ModalComponent/Header/index.tsx +3 -3
- package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +7 -7
- package/Components/OfflineHandler/__tests__/index.test.tsx +28 -25
- package/Components/PlayerContainer/PlayerContainer.tsx +5 -11
- package/Components/PlayerContainer/PlayerContainerContext.tsx +9 -0
- package/Components/PlayerImageBackground/index.tsx +23 -3
- package/Components/River/ComponentsMap/ComponentsMap.tsx +39 -65
- package/Components/River/ComponentsMap/hooks/useLoadingState.ts +78 -51
- package/Components/River/RefreshControl.tsx +1 -1
- package/Components/River/RiverFooter.tsx +39 -9
- package/Components/River/RiverItem.tsx +37 -2
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +114 -45
- package/Components/River/__tests__/__snapshots__/river.test.js.snap +12 -12
- package/Components/River/__tests__/componentsMap.test.js +64 -17
- package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +1 -1
- package/Components/RouteManager/__tests__/__snapshots__/testId.test.js.snap +1 -1
- package/Components/Screen/__tests__/Screen.test.tsx +41 -27
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +4 -4
- package/Components/Screen/hooks.ts +56 -0
- package/Components/Screen/index.tsx +13 -39
- package/Components/ScreenResolver/__tests__/__snapshots__/screenResolver.test.js.snap +2 -2
- package/Components/ScreenResolver/__tests__/screenResolver.test.js +31 -27
- package/Components/Tabs/Tab.tsx +7 -6
- package/Components/TextInputTv/__tests__/TextInputTv.test.js +42 -42
- package/Components/TextInputTv/__tests__/__snapshots__/TextInputTv.test.js.snap +7 -0
- package/Components/TextInputTv/index.tsx +4 -4
- package/Components/Touchable/__tests__/__snapshots__/touchable.test.tsx.snap +2 -2
- package/Components/Transitioner/AnimationManager.js +8 -8
- package/Components/Transitioner/Scene.tsx +52 -23
- package/Components/Transitioner/__tests__/__snapshots__/AnimationManager.test.js.snap +26 -26
- package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +62 -46
- package/Components/Transitioner/__tests__/__snapshots__/config.test.js.snap +20 -20
- package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +4 -4
- package/Components/Transitioner/index.js +8 -4
- package/Components/VideoLive/LiveImageManager.ts +27 -1
- package/Components/VideoLive/PlayerLiveImageComponent.tsx +29 -21
- package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +63 -8
- package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +5 -10
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +5 -1
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +5 -1
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +8 -7
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +4 -10
- package/Components/VideoModal/ModalAnimation/index.ts +2 -1
- package/Components/VideoModal/ModalAnimation/useModalAnimationContext.ts +6 -0
- package/Components/VideoModal/ModalAnimation/utils.ts +2 -2
- package/Components/VideoModal/OpaqueLayer.tsx +33 -0
- package/Components/VideoModal/PlayerDetails.tsx +4 -1
- package/Components/VideoModal/PlayerWrapper.tsx +16 -35
- package/Components/VideoModal/VideoModal.tsx +14 -23
- package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +5 -2
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +13 -10
- package/Components/VideoModal/__tests__/__snapshots__/PlayerDetails.test.tsx.snap +4 -4
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +66 -156
- package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +89 -0
- package/Components/VideoModal/hooks/index.ts +7 -0
- package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +49 -0
- package/Components/VideoModal/hooks/utils/__tests__/showDetails.test.ts +91 -0
- package/Components/VideoModal/hooks/utils/index.ts +33 -0
- package/Components/VideoModal/utils.ts +3 -5
- package/Components/Viewport/ViewportAware/__tests__/__snapshots__/viewportAware.test.js.snap +2 -2
- package/Components/Viewport/ViewportTracker/__tests__/__snapshots__/viewportTracker.test.js.snap +1 -1
- package/Components/ZappUIComponent/__tests__/__snapshots__/ZappUIComponent.test.js.snap +11 -11
- package/Components/default-cell-renderer/__tests__/__snapshots__/defaultCellRenderer.test.tsx.snap +30 -30
- package/Contexts/ConfigutaionContext/__tests__/__snapshots__/ConfigurationProvider.test.tsx.snap +1 -1
- package/Contexts/ScreenContext/index.tsx +3 -2
- package/Decorators/Navigator/__tests__/__snapshots__/navigator.test.js.snap +2 -2
- package/Decorators/RiverFeedLoader/__tests__/__snapshots__/riverFeedLoader.test.tsx.snap +77 -77
- package/Decorators/RiverFeedLoader/__tests__/riverFeedLoader.test.tsx +34 -39
- package/Decorators/RiverFeedLoader/__tests__/utils.test.ts +0 -9
- package/Decorators/RiverFeedLoader/index.tsx +1 -1
- package/Decorators/RiverFeedLoader/utils/getDatasourceUrl.ts +39 -0
- package/Decorators/RiverFeedLoader/utils/index.ts +29 -0
- package/Decorators/RiverFeedLoader/utils/usePipesContexts.ts +40 -0
- package/Decorators/RiverResolver/__tests__/__snapshots__/riverResolver.test.tsx.snap +5 -5
- package/Decorators/RiverResolver/__tests__/riverResolver.test.tsx +16 -10
- package/Decorators/ZappPipesDataConnector/__tests__/Hero.js +1 -1
- package/Decorators/ZappPipesDataConnector/index.tsx +32 -2
- package/package.json +12 -6
- package/Decorators/RiverFeedLoader/utils.ts +0 -100
|
@@ -70,21 +70,6 @@ function ComponentsMapComponent(props: Props) {
|
|
|
70
70
|
|
|
71
71
|
const [flatListHeight, setFlatListHeight] = React.useState(null);
|
|
72
72
|
|
|
73
|
-
const {
|
|
74
|
-
isAnyLoading,
|
|
75
|
-
isAllLoaded,
|
|
76
|
-
waitForAllComponents,
|
|
77
|
-
onLoadFinished,
|
|
78
|
-
onLoadFailed,
|
|
79
|
-
shouldShowLoadingError,
|
|
80
|
-
isAnyLoaded,
|
|
81
|
-
arePreviousComponentsLoaded,
|
|
82
|
-
} = useLoadingState(feed?.entry?.length || components.length);
|
|
83
|
-
|
|
84
|
-
const theme = useTheme();
|
|
85
|
-
|
|
86
|
-
const logTimestamp = useProfilerLogging();
|
|
87
|
-
|
|
88
73
|
const riverComponents = React.useMemo(() => {
|
|
89
74
|
if (feed?.entry?.length < components.length) {
|
|
90
75
|
return R.slice(0, feed?.entry?.length, components);
|
|
@@ -93,55 +78,42 @@ function ComponentsMapComponent(props: Props) {
|
|
|
93
78
|
return components;
|
|
94
79
|
}, [components, feed]);
|
|
95
80
|
|
|
81
|
+
const logTimestamp = useProfilerLogging();
|
|
82
|
+
|
|
83
|
+
const onLoadDone = React.useCallback(() => {
|
|
84
|
+
logTimestamp(riverId?.toString());
|
|
85
|
+
}, [logTimestamp]);
|
|
86
|
+
|
|
87
|
+
const { loadingState, onLoadFinished, onLoadFailed, shouldShowLoadingError } =
|
|
88
|
+
useLoadingState(riverComponents.length, onLoadDone);
|
|
89
|
+
|
|
90
|
+
const theme = useTheme();
|
|
91
|
+
|
|
96
92
|
const renderRiverItem = React.useCallback(
|
|
97
93
|
({ item, index }) => {
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
94
|
+
const riverItemProps = {
|
|
95
|
+
riverId,
|
|
96
|
+
item,
|
|
97
|
+
index,
|
|
98
|
+
isScreenWrappedInContainer,
|
|
99
|
+
feed,
|
|
100
|
+
groupId,
|
|
101
|
+
onLoadFailed,
|
|
102
|
+
onLoadFinished,
|
|
103
|
+
getStaticComponentFeed,
|
|
104
|
+
isLast: isLast(index, riverComponents.length),
|
|
105
|
+
loadingState,
|
|
102
106
|
};
|
|
103
107
|
|
|
104
108
|
return (
|
|
105
|
-
<
|
|
106
|
-
<
|
|
107
|
-
|
|
108
|
-
{...{
|
|
109
|
-
readyToBeDisplayed,
|
|
110
|
-
riverId,
|
|
111
|
-
item,
|
|
112
|
-
index,
|
|
113
|
-
isScreenWrappedInContainer,
|
|
114
|
-
feed,
|
|
115
|
-
groupId,
|
|
116
|
-
onLoadFailed,
|
|
117
|
-
onLoadFinished,
|
|
118
|
-
getStaticComponentFeed,
|
|
119
|
-
isLast: isLast(index, riverComponents.length),
|
|
120
|
-
}}
|
|
121
|
-
/>
|
|
122
|
-
</ScreenLoadingMeasurementsListItemWrapper>
|
|
123
|
-
</View>
|
|
109
|
+
<ScreenLoadingMeasurementsListItemWrapper index={index}>
|
|
110
|
+
<RiverItem {...riverItemProps} />
|
|
111
|
+
</ScreenLoadingMeasurementsListItemWrapper>
|
|
124
112
|
);
|
|
125
113
|
},
|
|
126
|
-
[
|
|
127
|
-
feed,
|
|
128
|
-
getStaticComponentFeed,
|
|
129
|
-
arePreviousComponentsLoaded,
|
|
130
|
-
onLoadFailed,
|
|
131
|
-
onLoadFinished,
|
|
132
|
-
]
|
|
114
|
+
[feed, getStaticComponentFeed, onLoadFailed, onLoadFinished]
|
|
133
115
|
);
|
|
134
116
|
|
|
135
|
-
const renderFooter = React.useCallback(() => {
|
|
136
|
-
return (
|
|
137
|
-
<RiverFooter
|
|
138
|
-
visible={isAnyLoading}
|
|
139
|
-
flatListHeight={flatListHeight}
|
|
140
|
-
isAnyLoaded={isAnyLoaded || waitForAllComponents}
|
|
141
|
-
/>
|
|
142
|
-
);
|
|
143
|
-
}, [flatListHeight, isAnyLoading, isAnyLoaded]);
|
|
144
|
-
|
|
145
117
|
const screenStyle = React.useMemo(
|
|
146
118
|
() => ({
|
|
147
119
|
paddingTop: ifEmptyUseFallback(
|
|
@@ -179,12 +151,6 @@ function ComponentsMapComponent(props: Props) {
|
|
|
179
151
|
|
|
180
152
|
usePipesCacheReset(riverId, riverComponents);
|
|
181
153
|
|
|
182
|
-
React.useEffect(() => {
|
|
183
|
-
if (isAllLoaded) {
|
|
184
|
-
logTimestamp(riverId?.toString());
|
|
185
|
-
}
|
|
186
|
-
}, [isAllLoaded]);
|
|
187
|
-
|
|
188
154
|
const refreshControl = React.useMemo(
|
|
189
155
|
() =>
|
|
190
156
|
pullToRefreshEnabled ? (
|
|
@@ -280,6 +246,11 @@ function ComponentsMapComponent(props: Props) {
|
|
|
280
246
|
}
|
|
281
247
|
}, []);
|
|
282
248
|
|
|
249
|
+
const contentContainerStyle = React.useMemo(
|
|
250
|
+
() => (isScreenWrappedInContainer ? {} : screenStyle),
|
|
251
|
+
[isScreenWrappedInContainer, screenStyle]
|
|
252
|
+
);
|
|
253
|
+
|
|
283
254
|
if (shouldShowLoadingError) {
|
|
284
255
|
return <RiverError />;
|
|
285
256
|
}
|
|
@@ -291,7 +262,7 @@ function ComponentsMapComponent(props: Props) {
|
|
|
291
262
|
<View style={styles.container}>
|
|
292
263
|
<ScreenLoadingMeasurements
|
|
293
264
|
riverId={riverId}
|
|
294
|
-
numberOfComponents={
|
|
265
|
+
numberOfComponents={riverComponents.length}
|
|
295
266
|
>
|
|
296
267
|
<ViewportTracker>
|
|
297
268
|
<FlatList
|
|
@@ -312,10 +283,13 @@ function ComponentsMapComponent(props: Props) {
|
|
|
312
283
|
keyExtractor={keyExtractor}
|
|
313
284
|
renderItem={renderRiverItem}
|
|
314
285
|
data={riverComponents}
|
|
315
|
-
contentContainerStyle={
|
|
316
|
-
|
|
286
|
+
contentContainerStyle={contentContainerStyle}
|
|
287
|
+
ListFooterComponent={
|
|
288
|
+
<RiverFooter
|
|
289
|
+
flatListHeight={flatListHeight}
|
|
290
|
+
loadingState={loadingState}
|
|
291
|
+
/>
|
|
317
292
|
}
|
|
318
|
-
ListFooterComponent={renderFooter}
|
|
319
293
|
refreshControl={refreshControl}
|
|
320
294
|
onScrollBeginDrag={onScrollBeginDrag}
|
|
321
295
|
onScroll={onScroll}
|
|
@@ -1,50 +1,86 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const anyFalse = R.any(R.equals(false));
|
|
6
|
-
const anyTrue = R.any(R.equals(true));
|
|
2
|
+
import { isNil, set, lensIndex, T, slice } from "ramda";
|
|
3
|
+
import { BehaviorSubject } from "rxjs";
|
|
4
|
+
import { useRefWithInitialValue } from "@applicaster/zapp-react-native-utils/reactHooks/state/useRefWithInitialValue";
|
|
7
5
|
|
|
8
6
|
const reducer = (state, { payload }) => {
|
|
9
|
-
if (!
|
|
10
|
-
return
|
|
7
|
+
if (!isNil(payload) && !state[payload]) {
|
|
8
|
+
return set(lensIndex(payload), true)(state);
|
|
11
9
|
}
|
|
12
10
|
|
|
13
11
|
return state;
|
|
14
12
|
};
|
|
15
13
|
|
|
16
|
-
type
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
type LoadingState = {
|
|
15
|
+
index: number;
|
|
16
|
+
done: boolean;
|
|
19
17
|
waitForAllComponents: boolean;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
type Return = {
|
|
21
|
+
loadingState: BehaviorSubject<LoadingState>;
|
|
20
22
|
onLoadFinished: (index: number) => void;
|
|
21
23
|
onLoadFailed: ({ error, index }: { error: Error; index: number }) => void;
|
|
22
24
|
shouldShowLoadingError: boolean;
|
|
23
|
-
isAnyLoaded: boolean;
|
|
24
25
|
arePreviousComponentsLoaded: (index: number) => boolean;
|
|
25
26
|
};
|
|
26
27
|
|
|
27
|
-
type Action = { payload: { index: number } };
|
|
28
|
-
|
|
29
|
-
type Loaded = true;
|
|
30
|
-
type Loading = false;
|
|
31
|
-
|
|
32
|
-
type LoadingState = Array<Loaded | Loading>;
|
|
33
|
-
|
|
34
28
|
// TODO: Take this value from Zapp configuration, when feature is added to GeneralScreen
|
|
35
29
|
const SHOULD_FAIL_ON_COMPONENT_LOADING = false;
|
|
36
30
|
|
|
37
|
-
|
|
31
|
+
const createLoadingStateObservable = () =>
|
|
32
|
+
new BehaviorSubject<LoadingState>({
|
|
33
|
+
index: -1,
|
|
34
|
+
done: false,
|
|
35
|
+
waitForAllComponents: SHOULD_FAIL_ON_COMPONENT_LOADING,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export const useLoadingState = (
|
|
39
|
+
count: number,
|
|
40
|
+
onLoadDone: () => void
|
|
41
|
+
): Return => {
|
|
42
|
+
const componentStateRef = React.useRef(new Array(count).fill(false));
|
|
38
43
|
const [loadingError, setLoadingError] = React.useState(null);
|
|
39
44
|
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
const loadingState = useRefWithInitialValue<BehaviorSubject<LoadingState>>(
|
|
46
|
+
createLoadingStateObservable
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const arePreviousComponentsLoaded = React.useCallback((index) => {
|
|
50
|
+
if (index === 0) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
43
53
|
|
|
44
|
-
|
|
45
|
-
|
|
54
|
+
const componentsBefore = slice(0, index, componentStateRef.current);
|
|
55
|
+
|
|
56
|
+
return componentsBefore.every(T);
|
|
46
57
|
}, []);
|
|
47
58
|
|
|
59
|
+
const dispatch = React.useCallback(({ payload }) => {
|
|
60
|
+
const newState = reducer(componentStateRef.current, { payload });
|
|
61
|
+
componentStateRef.current = newState;
|
|
62
|
+
const isDone = arePreviousComponentsLoaded(count - 1);
|
|
63
|
+
|
|
64
|
+
const state = loadingState.current.getValue();
|
|
65
|
+
|
|
66
|
+
const newLoadingState = {
|
|
67
|
+
...state,
|
|
68
|
+
index: state.index < payload ? payload : state.index,
|
|
69
|
+
done: isDone,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
loadingState.current.next(newLoadingState);
|
|
73
|
+
|
|
74
|
+
if (isDone) {
|
|
75
|
+
onLoadDone();
|
|
76
|
+
}
|
|
77
|
+
}, []);
|
|
78
|
+
|
|
79
|
+
const handleComponentLoaded = React.useCallback(
|
|
80
|
+
(index) => dispatch({ payload: index }),
|
|
81
|
+
[]
|
|
82
|
+
);
|
|
83
|
+
|
|
48
84
|
const handleComponentLoadErrorWhenNeedToFail = React.useCallback(
|
|
49
85
|
({ error }) => {
|
|
50
86
|
if (error !== loadingError) {
|
|
@@ -55,35 +91,26 @@ export const useLoadingState = (count: number): Return => {
|
|
|
55
91
|
);
|
|
56
92
|
|
|
57
93
|
const handleComponentLoadErrorWhenNoNeedToFail = React.useCallback(
|
|
58
|
-
({ index }) =>
|
|
59
|
-
handleComponentLoaded(index);
|
|
60
|
-
},
|
|
94
|
+
({ index }) => handleComponentLoaded(index),
|
|
61
95
|
[]
|
|
62
96
|
);
|
|
63
97
|
|
|
64
|
-
|
|
65
|
-
(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
},
|
|
74
|
-
[
|
|
98
|
+
return React.useMemo(
|
|
99
|
+
() => ({
|
|
100
|
+
loadingState: loadingState.current,
|
|
101
|
+
onLoadFinished: handleComponentLoaded,
|
|
102
|
+
onLoadFailed: SHOULD_FAIL_ON_COMPONENT_LOADING
|
|
103
|
+
? handleComponentLoadErrorWhenNeedToFail
|
|
104
|
+
: handleComponentLoadErrorWhenNoNeedToFail,
|
|
105
|
+
shouldShowLoadingError: SHOULD_FAIL_ON_COMPONENT_LOADING && loadingError,
|
|
106
|
+
arePreviousComponentsLoaded,
|
|
107
|
+
}),
|
|
108
|
+
[
|
|
109
|
+
loadingError,
|
|
110
|
+
handleComponentLoaded,
|
|
111
|
+
handleComponentLoadErrorWhenNeedToFail,
|
|
112
|
+
handleComponentLoadErrorWhenNoNeedToFail,
|
|
113
|
+
arePreviousComponentsLoaded,
|
|
114
|
+
]
|
|
75
115
|
);
|
|
76
|
-
|
|
77
|
-
return {
|
|
78
|
-
isAnyLoading: anyFalse(componentsState),
|
|
79
|
-
isAllLoaded: allTrue(componentsState),
|
|
80
|
-
onLoadFinished: handleComponentLoaded,
|
|
81
|
-
onLoadFailed: SHOULD_FAIL_ON_COMPONENT_LOADING
|
|
82
|
-
? handleComponentLoadErrorWhenNeedToFail
|
|
83
|
-
: handleComponentLoadErrorWhenNoNeedToFail,
|
|
84
|
-
shouldShowLoadingError: SHOULD_FAIL_ON_COMPONENT_LOADING && loadingError,
|
|
85
|
-
isAnyLoaded: anyTrue(componentsState),
|
|
86
|
-
waitForAllComponents: SHOULD_FAIL_ON_COMPONENT_LOADING,
|
|
87
|
-
arePreviousComponentsLoaded,
|
|
88
|
-
};
|
|
89
116
|
};
|
|
@@ -9,7 +9,7 @@ import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
|
9
9
|
import { useLocalizedStrings } from "@applicaster/zapp-react-native-utils/localizationUtils";
|
|
10
10
|
import { useAnalytics } from "@applicaster/zapp-react-native-utils/analyticsUtils";
|
|
11
11
|
import { useSendAnalyticsEventWithFunction } from "@applicaster/zapp-react-native-utils/analyticsUtils/helpers/hooks";
|
|
12
|
-
import { useCurrentScreenData } from "@applicaster/zapp-react-native-utils/reactHooks/screen";
|
|
12
|
+
import { useCurrentScreenData } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useCurrentScreenData";
|
|
13
13
|
import { loadPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";
|
|
14
14
|
import { useDispatch } from "react-redux";
|
|
15
15
|
import { useShallow } from "zustand/react/shallow";
|
|
@@ -1,11 +1,23 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { useCallback } from "react";
|
|
2
2
|
import { StyleSheet, View } from "react-native";
|
|
3
3
|
import { Spinner } from "@applicaster/zapp-react-native-ui-components/Components/Spinner";
|
|
4
|
+
import type { Subject } from "rxjs";
|
|
5
|
+
import { useStateFromSubscribe } from "@applicaster/zapp-react-native-utils/reactHooks/state/useStateFromSubscribe";
|
|
6
|
+
|
|
7
|
+
type LoadingState = {
|
|
8
|
+
waitForAllComponents: boolean;
|
|
9
|
+
index: number;
|
|
10
|
+
done: boolean;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
type State = {
|
|
14
|
+
visible: boolean;
|
|
15
|
+
isAnyLoaded: boolean;
|
|
16
|
+
};
|
|
4
17
|
|
|
5
18
|
type Props = {
|
|
6
|
-
visible?: boolean;
|
|
7
19
|
flatListHeight?: number;
|
|
8
|
-
|
|
20
|
+
loadingState: Subject<LoadingState>;
|
|
9
21
|
};
|
|
10
22
|
|
|
11
23
|
const FOOTER_COMPONENT_HEIGHT = 200;
|
|
@@ -19,17 +31,35 @@ const footerStyles = StyleSheet.create({
|
|
|
19
31
|
});
|
|
20
32
|
|
|
21
33
|
function RiverFooterComponent(props: Props) {
|
|
22
|
-
const {
|
|
34
|
+
const { flatListHeight, loadingState } = props;
|
|
35
|
+
|
|
36
|
+
const { visible, isAnyLoaded } = useStateFromSubscribe<LoadingState, State>(
|
|
37
|
+
loadingState,
|
|
38
|
+
useCallback(
|
|
39
|
+
({ index, done, waitForAllComponents }, setState) =>
|
|
40
|
+
setState(() => ({
|
|
41
|
+
visible: !done,
|
|
42
|
+
isAnyLoaded: index >= 0 || waitForAllComponents,
|
|
43
|
+
})),
|
|
44
|
+
[]
|
|
45
|
+
),
|
|
46
|
+
{
|
|
47
|
+
visible: true,
|
|
48
|
+
isAnyLoaded: false,
|
|
49
|
+
}
|
|
50
|
+
);
|
|
23
51
|
|
|
24
52
|
if (!visible) return null;
|
|
25
53
|
|
|
26
54
|
return (
|
|
27
55
|
<View
|
|
28
|
-
renderToHardwareTextureAndroid
|
|
29
|
-
style={
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
56
|
+
renderToHardwareTextureAndroid
|
|
57
|
+
style={[
|
|
58
|
+
footerStyles.container,
|
|
59
|
+
{
|
|
60
|
+
height: isAnyLoaded ? FOOTER_COMPONENT_HEIGHT : flatListHeight,
|
|
61
|
+
},
|
|
62
|
+
]}
|
|
33
63
|
>
|
|
34
64
|
<Spinner size={isAnyLoaded ? "small" : "large"} />
|
|
35
65
|
</View>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { useEffect } from "react";
|
|
2
2
|
import * as R from "ramda";
|
|
3
3
|
|
|
4
4
|
import { applyDecorators } from "../../Decorators";
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import { riverLogger } from "./logger";
|
|
12
12
|
import { tvPluginsWithCellRenderer } from "../../const";
|
|
13
13
|
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
14
|
+
import type { BehaviorSubject } from "rxjs";
|
|
14
15
|
|
|
15
16
|
export type RiverItemType = {
|
|
16
17
|
item: ZappUIComponent;
|
|
@@ -24,6 +25,7 @@ export type RiverItemType = {
|
|
|
24
25
|
getStaticComponentFeed: GeneralContentScreenProps["getStaticComponentFeed"];
|
|
25
26
|
readyToBeDisplayed?: boolean;
|
|
26
27
|
isLast: boolean;
|
|
28
|
+
loadingState: BehaviorSubject<{ index: number }>;
|
|
27
29
|
};
|
|
28
30
|
|
|
29
31
|
function getFeedUrl(feed: ZappFeed, index: number) {
|
|
@@ -36,6 +38,33 @@ function getFeedUrl(feed: ZappFeed, index: number) {
|
|
|
36
38
|
}
|
|
37
39
|
}
|
|
38
40
|
|
|
41
|
+
/**
|
|
42
|
+
* useLoadingState for RiverItemComponent
|
|
43
|
+
* takes currentIndex and loadingState as arguments
|
|
44
|
+
**/
|
|
45
|
+
const useLoadingState = (
|
|
46
|
+
currentIndex: number,
|
|
47
|
+
loadingState: RiverItemType["loadingState"]
|
|
48
|
+
) => {
|
|
49
|
+
const [readyToBeDisplayed, setReadyToBeDisplayed] = React.useState(
|
|
50
|
+
loadingState.getValue().index + 1 === currentIndex
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
const subscription = loadingState.subscribe(({ index }) => {
|
|
55
|
+
if (index + 1 === currentIndex) {
|
|
56
|
+
setReadyToBeDisplayed(true);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
return () => {
|
|
61
|
+
subscription.unsubscribe();
|
|
62
|
+
};
|
|
63
|
+
}, [loadingState, currentIndex]);
|
|
64
|
+
|
|
65
|
+
return readyToBeDisplayed;
|
|
66
|
+
};
|
|
67
|
+
|
|
39
68
|
function RiverItemComponent(props: RiverItemType) {
|
|
40
69
|
const {
|
|
41
70
|
item,
|
|
@@ -47,10 +76,12 @@ function RiverItemComponent(props: RiverItemType) {
|
|
|
47
76
|
onLoadFinished,
|
|
48
77
|
onLoadFailed,
|
|
49
78
|
getStaticComponentFeed,
|
|
50
|
-
readyToBeDisplayed,
|
|
51
79
|
isLast,
|
|
80
|
+
loadingState,
|
|
52
81
|
} = props;
|
|
53
82
|
|
|
83
|
+
const readyToBeDisplayed = useLoadingState(index, loadingState);
|
|
84
|
+
|
|
54
85
|
const feedUrl = getFeedUrl(feed, index);
|
|
55
86
|
|
|
56
87
|
const Component = useComponentResolver(
|
|
@@ -90,6 +121,10 @@ function RiverItemComponent(props: RiverItemType) {
|
|
|
90
121
|
}
|
|
91
122
|
}, []);
|
|
92
123
|
|
|
124
|
+
if (!readyToBeDisplayed) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
|
|
93
128
|
if (Component === null || typeof Component === "undefined") {
|
|
94
129
|
riverLogger.warning({
|
|
95
130
|
message: `Component ${item.component_type} is null - skipping rendering`,
|