@applicaster/zapp-react-native-ui-components 12.0.26 → 12.0.27-alpha.2213255057
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/River/ComponentsMap/ComponentsMap.tsx +39 -65
- package/Components/River/ComponentsMap/hooks/useLoadingState.ts +89 -51
- package/Components/River/RiverFooter.tsx +39 -9
- package/Components/River/RiverItem.tsx +42 -3
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +100 -31
- package/Components/River/__tests__/componentsMap.test.js +3 -4
- package/package.json +5 -5
|
@@ -75,21 +75,6 @@ function ComponentsMapComponent(props: Props) {
|
|
|
75
75
|
|
|
76
76
|
const [flatListHeight, setFlatListHeight] = React.useState(null);
|
|
77
77
|
|
|
78
|
-
const {
|
|
79
|
-
isAnyLoading,
|
|
80
|
-
isAllLoaded,
|
|
81
|
-
waitForAllComponents,
|
|
82
|
-
onLoadFinished,
|
|
83
|
-
onLoadFailed,
|
|
84
|
-
shouldShowLoadingError,
|
|
85
|
-
isAnyLoaded,
|
|
86
|
-
arePreviousComponentsLoaded,
|
|
87
|
-
} = useLoadingState(feed?.entry?.length || components.length);
|
|
88
|
-
|
|
89
|
-
const theme = useTheme();
|
|
90
|
-
|
|
91
|
-
const logTimestamp = useProfilerLogging();
|
|
92
|
-
|
|
93
78
|
const riverComponents = React.useMemo(() => {
|
|
94
79
|
if (feed?.entry?.length < components.length) {
|
|
95
80
|
return R.slice(0, feed?.entry?.length, components);
|
|
@@ -98,55 +83,42 @@ function ComponentsMapComponent(props: Props) {
|
|
|
98
83
|
return components;
|
|
99
84
|
}, [components, feed]);
|
|
100
85
|
|
|
86
|
+
const logTimestamp = useProfilerLogging();
|
|
87
|
+
|
|
88
|
+
const onLoadDone = React.useCallback(() => {
|
|
89
|
+
logTimestamp(riverId?.toString());
|
|
90
|
+
}, [logTimestamp]);
|
|
91
|
+
|
|
92
|
+
const { loadingState, onLoadFinished, onLoadFailed, shouldShowLoadingError } =
|
|
93
|
+
useLoadingState(riverComponents.length, onLoadDone);
|
|
94
|
+
|
|
95
|
+
const theme = useTheme();
|
|
96
|
+
|
|
101
97
|
const renderRiverItem = React.useCallback(
|
|
102
98
|
({ item, index }) => {
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
99
|
+
const riverItemProps = {
|
|
100
|
+
riverId,
|
|
101
|
+
item,
|
|
102
|
+
index,
|
|
103
|
+
isScreenWrappedInContainer,
|
|
104
|
+
feed,
|
|
105
|
+
groupId,
|
|
106
|
+
onLoadFailed,
|
|
107
|
+
onLoadFinished,
|
|
108
|
+
getStaticComponentFeed,
|
|
109
|
+
isLast: isLast(index, riverComponents.length),
|
|
110
|
+
loadingState,
|
|
107
111
|
};
|
|
108
112
|
|
|
109
113
|
return (
|
|
110
|
-
<
|
|
111
|
-
<
|
|
112
|
-
|
|
113
|
-
{...{
|
|
114
|
-
readyToBeDisplayed,
|
|
115
|
-
riverId,
|
|
116
|
-
item,
|
|
117
|
-
index,
|
|
118
|
-
isScreenWrappedInContainer,
|
|
119
|
-
feed,
|
|
120
|
-
groupId,
|
|
121
|
-
onLoadFailed,
|
|
122
|
-
onLoadFinished,
|
|
123
|
-
getStaticComponentFeed,
|
|
124
|
-
isLast: isLast(index, riverComponents.length),
|
|
125
|
-
}}
|
|
126
|
-
/>
|
|
127
|
-
</ScreenLoadingMeasurementsListItemWrapper>
|
|
128
|
-
</View>
|
|
114
|
+
<ScreenLoadingMeasurementsListItemWrapper index={index}>
|
|
115
|
+
<RiverItem {...riverItemProps} />
|
|
116
|
+
</ScreenLoadingMeasurementsListItemWrapper>
|
|
129
117
|
);
|
|
130
118
|
},
|
|
131
|
-
[
|
|
132
|
-
feed,
|
|
133
|
-
getStaticComponentFeed,
|
|
134
|
-
arePreviousComponentsLoaded,
|
|
135
|
-
onLoadFailed,
|
|
136
|
-
onLoadFinished,
|
|
137
|
-
]
|
|
119
|
+
[feed, getStaticComponentFeed, onLoadFailed, onLoadFinished]
|
|
138
120
|
);
|
|
139
121
|
|
|
140
|
-
const renderFooter = React.useCallback(() => {
|
|
141
|
-
return (
|
|
142
|
-
<RiverFooter
|
|
143
|
-
visible={isAnyLoading}
|
|
144
|
-
flatListHeight={flatListHeight}
|
|
145
|
-
isAnyLoaded={isAnyLoaded || waitForAllComponents}
|
|
146
|
-
/>
|
|
147
|
-
);
|
|
148
|
-
}, [flatListHeight, isAnyLoading, isAnyLoaded]);
|
|
149
|
-
|
|
150
122
|
const screenStyle = React.useMemo(
|
|
151
123
|
() => ({
|
|
152
124
|
paddingTop: ifEmptyUseFallback(
|
|
@@ -184,12 +156,6 @@ function ComponentsMapComponent(props: Props) {
|
|
|
184
156
|
|
|
185
157
|
usePipesCacheReset(riverId, riverComponents);
|
|
186
158
|
|
|
187
|
-
React.useEffect(() => {
|
|
188
|
-
if (isAllLoaded) {
|
|
189
|
-
logTimestamp(riverId?.toString());
|
|
190
|
-
}
|
|
191
|
-
}, [isAllLoaded]);
|
|
192
|
-
|
|
193
159
|
const refreshControl = React.useMemo(
|
|
194
160
|
() =>
|
|
195
161
|
pullToRefreshEnabled ? (
|
|
@@ -285,6 +251,11 @@ function ComponentsMapComponent(props: Props) {
|
|
|
285
251
|
}
|
|
286
252
|
}, []);
|
|
287
253
|
|
|
254
|
+
const contentContainerStyle = React.useMemo(
|
|
255
|
+
() => (isScreenWrappedInContainer ? {} : screenStyle),
|
|
256
|
+
[isScreenWrappedInContainer, screenStyle]
|
|
257
|
+
);
|
|
258
|
+
|
|
288
259
|
if (shouldShowLoadingError) {
|
|
289
260
|
return <RiverError />;
|
|
290
261
|
}
|
|
@@ -296,7 +267,7 @@ function ComponentsMapComponent(props: Props) {
|
|
|
296
267
|
<View style={styles.container}>
|
|
297
268
|
<ScreenLoadingMeasurements
|
|
298
269
|
riverId={riverId}
|
|
299
|
-
numberOfComponents={
|
|
270
|
+
numberOfComponents={riverComponents.length}
|
|
300
271
|
>
|
|
301
272
|
<ViewportTracker>
|
|
302
273
|
<FlatList
|
|
@@ -318,10 +289,13 @@ function ComponentsMapComponent(props: Props) {
|
|
|
318
289
|
keyExtractor={keyExtractor}
|
|
319
290
|
renderItem={renderRiverItem}
|
|
320
291
|
data={riverComponents}
|
|
321
|
-
contentContainerStyle={
|
|
322
|
-
|
|
292
|
+
contentContainerStyle={contentContainerStyle}
|
|
293
|
+
ListFooterComponent={
|
|
294
|
+
<RiverFooter
|
|
295
|
+
flatListHeight={flatListHeight}
|
|
296
|
+
loadingState={loadingState}
|
|
297
|
+
/>
|
|
323
298
|
}
|
|
324
|
-
ListFooterComponent={renderFooter}
|
|
325
299
|
refreshControl={refreshControl}
|
|
326
300
|
onScrollBeginDrag={onScrollBeginDrag}
|
|
327
301
|
onScroll={onScroll}
|
|
@@ -1,50 +1,97 @@
|
|
|
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
|
+
}
|
|
53
|
+
|
|
54
|
+
const componentsBefore = slice(0, index, componentStateRef.current);
|
|
43
55
|
|
|
44
|
-
|
|
45
|
-
dispatch({ payload: index });
|
|
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
|
+
// Fix: Only advance index sequentially, don't jump to highest loaded component
|
|
67
|
+
let newIndex = state.index;
|
|
68
|
+
if (payload === state.index + 1) {
|
|
69
|
+
// Only advance if this is the next sequential component
|
|
70
|
+
newIndex = payload;
|
|
71
|
+
} else if (payload < state.index) {
|
|
72
|
+
// If a lower index loads after higher ones, don't change the index
|
|
73
|
+
// This prevents the race condition that causes unmounting
|
|
74
|
+
newIndex = state.index;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const newLoadingState = {
|
|
78
|
+
...state,
|
|
79
|
+
index: newIndex,
|
|
80
|
+
done: isDone,
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
loadingState.current.next(newLoadingState);
|
|
84
|
+
|
|
85
|
+
if (isDone) {
|
|
86
|
+
onLoadDone();
|
|
87
|
+
}
|
|
88
|
+
}, []);
|
|
89
|
+
|
|
90
|
+
const handleComponentLoaded = React.useCallback(
|
|
91
|
+
(index) => dispatch({ payload: index }),
|
|
92
|
+
[]
|
|
93
|
+
);
|
|
94
|
+
|
|
48
95
|
const handleComponentLoadErrorWhenNeedToFail = React.useCallback(
|
|
49
96
|
({ error }) => {
|
|
50
97
|
if (error !== loadingError) {
|
|
@@ -55,35 +102,26 @@ export const useLoadingState = (count: number): Return => {
|
|
|
55
102
|
);
|
|
56
103
|
|
|
57
104
|
const handleComponentLoadErrorWhenNoNeedToFail = React.useCallback(
|
|
58
|
-
({ index }) =>
|
|
59
|
-
handleComponentLoaded(index);
|
|
60
|
-
},
|
|
105
|
+
({ index }) => handleComponentLoaded(index),
|
|
61
106
|
[]
|
|
62
107
|
);
|
|
63
108
|
|
|
64
|
-
|
|
65
|
-
(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
},
|
|
74
|
-
[
|
|
109
|
+
return React.useMemo(
|
|
110
|
+
() => ({
|
|
111
|
+
loadingState: loadingState.current,
|
|
112
|
+
onLoadFinished: handleComponentLoaded,
|
|
113
|
+
onLoadFailed: SHOULD_FAIL_ON_COMPONENT_LOADING
|
|
114
|
+
? handleComponentLoadErrorWhenNeedToFail
|
|
115
|
+
: handleComponentLoadErrorWhenNoNeedToFail,
|
|
116
|
+
shouldShowLoadingError: SHOULD_FAIL_ON_COMPONENT_LOADING && loadingError,
|
|
117
|
+
arePreviousComponentsLoaded,
|
|
118
|
+
}),
|
|
119
|
+
[
|
|
120
|
+
loadingError,
|
|
121
|
+
handleComponentLoaded,
|
|
122
|
+
handleComponentLoadErrorWhenNeedToFail,
|
|
123
|
+
handleComponentLoadErrorWhenNoNeedToFail,
|
|
124
|
+
arePreviousComponentsLoaded,
|
|
125
|
+
]
|
|
75
126
|
);
|
|
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
127
|
};
|
|
@@ -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,37 @@ function getFeedUrl(feed: ZappFeed, index: number) {
|
|
|
36
38
|
}
|
|
37
39
|
}
|
|
38
40
|
|
|
41
|
+
const isNextIndex = (index, readyIndex) => {
|
|
42
|
+
return readyIndex + 1 >= index;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* useLoadingState for RiverItemComponent
|
|
47
|
+
* takes currentIndex and loadingState as arguments
|
|
48
|
+
**/
|
|
49
|
+
const useLoadingState = (
|
|
50
|
+
currentIndex: number,
|
|
51
|
+
loadingState: RiverItemType["loadingState"]
|
|
52
|
+
) => {
|
|
53
|
+
const [readyToBeDisplayed, setReadyToBeDisplayed] = React.useState(
|
|
54
|
+
isNextIndex(currentIndex, loadingState.getValue().index)
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
const subscription = loadingState.subscribe(({ index }) => {
|
|
59
|
+
if (isNextIndex(currentIndex, index)) {
|
|
60
|
+
setReadyToBeDisplayed(true);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
return () => {
|
|
65
|
+
subscription.unsubscribe();
|
|
66
|
+
};
|
|
67
|
+
}, [currentIndex]);
|
|
68
|
+
|
|
69
|
+
return readyToBeDisplayed;
|
|
70
|
+
};
|
|
71
|
+
|
|
39
72
|
function RiverItemComponent(props: RiverItemType) {
|
|
40
73
|
const {
|
|
41
74
|
item,
|
|
@@ -47,10 +80,12 @@ function RiverItemComponent(props: RiverItemType) {
|
|
|
47
80
|
onLoadFinished,
|
|
48
81
|
onLoadFailed,
|
|
49
82
|
getStaticComponentFeed,
|
|
50
|
-
readyToBeDisplayed,
|
|
51
83
|
isLast,
|
|
84
|
+
loadingState,
|
|
52
85
|
} = props;
|
|
53
86
|
|
|
87
|
+
const readyToBeDisplayed = useLoadingState(index, loadingState);
|
|
88
|
+
|
|
54
89
|
const feedUrl = getFeedUrl(feed, index);
|
|
55
90
|
|
|
56
91
|
const Component = useComponentResolver(
|
|
@@ -90,6 +125,10 @@ function RiverItemComponent(props: RiverItemType) {
|
|
|
90
125
|
}
|
|
91
126
|
}, []);
|
|
92
127
|
|
|
128
|
+
if (!readyToBeDisplayed) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
|
|
93
132
|
if (Component === null || typeof Component === "undefined") {
|
|
94
133
|
riverLogger.warning({
|
|
95
134
|
message: `Component ${item.component_type} is null - skipping rendering`,
|
|
@@ -111,7 +150,7 @@ function RiverItemComponent(props: RiverItemType) {
|
|
|
111
150
|
component={item}
|
|
112
151
|
componentIndex={index}
|
|
113
152
|
onLoadFailed={onLoadFailed}
|
|
114
|
-
onLoadFinished={() => onLoadFinished(index)}
|
|
153
|
+
onLoadFinished={() => onLoadFinished(index)}
|
|
115
154
|
groupId={groupId}
|
|
116
155
|
feedUrl={feedUrl}
|
|
117
156
|
isLast={isLast}
|
|
@@ -17,7 +17,90 @@ exports[`componentsMap renders renders components map correctly 1`] = `
|
|
|
17
17
|
}
|
|
18
18
|
>
|
|
19
19
|
<RCTScrollView
|
|
20
|
-
ListFooterComponent={
|
|
20
|
+
ListFooterComponent={
|
|
21
|
+
<Memo(RiverFooterComponent)
|
|
22
|
+
flatListHeight={null}
|
|
23
|
+
loadingState={
|
|
24
|
+
BehaviorSubject {
|
|
25
|
+
"_value": Object {
|
|
26
|
+
"done": false,
|
|
27
|
+
"index": -1,
|
|
28
|
+
"waitForAllComponents": false,
|
|
29
|
+
},
|
|
30
|
+
"closed": false,
|
|
31
|
+
"currentObservers": null,
|
|
32
|
+
"hasError": false,
|
|
33
|
+
"isStopped": false,
|
|
34
|
+
"observers": Array [
|
|
35
|
+
SafeSubscriber {
|
|
36
|
+
"_finalizers": Array [
|
|
37
|
+
Subscription {
|
|
38
|
+
"_finalizers": null,
|
|
39
|
+
"_parentage": [Circular],
|
|
40
|
+
"closed": false,
|
|
41
|
+
"initialTeardown": [Function],
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
"_parentage": null,
|
|
45
|
+
"closed": false,
|
|
46
|
+
"destination": ConsumerObserver {
|
|
47
|
+
"partialObserver": Object {
|
|
48
|
+
"complete": undefined,
|
|
49
|
+
"error": undefined,
|
|
50
|
+
"next": [Function],
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
"initialTeardown": undefined,
|
|
54
|
+
"isStopped": false,
|
|
55
|
+
},
|
|
56
|
+
SafeSubscriber {
|
|
57
|
+
"_finalizers": Array [
|
|
58
|
+
Subscription {
|
|
59
|
+
"_finalizers": null,
|
|
60
|
+
"_parentage": [Circular],
|
|
61
|
+
"closed": false,
|
|
62
|
+
"initialTeardown": [Function],
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
"_parentage": null,
|
|
66
|
+
"closed": false,
|
|
67
|
+
"destination": ConsumerObserver {
|
|
68
|
+
"partialObserver": Object {
|
|
69
|
+
"complete": undefined,
|
|
70
|
+
"error": undefined,
|
|
71
|
+
"next": [Function],
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
"initialTeardown": undefined,
|
|
75
|
+
"isStopped": false,
|
|
76
|
+
},
|
|
77
|
+
SafeSubscriber {
|
|
78
|
+
"_finalizers": Array [
|
|
79
|
+
Subscription {
|
|
80
|
+
"_finalizers": null,
|
|
81
|
+
"_parentage": [Circular],
|
|
82
|
+
"closed": false,
|
|
83
|
+
"initialTeardown": [Function],
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
"_parentage": null,
|
|
87
|
+
"closed": false,
|
|
88
|
+
"destination": ConsumerObserver {
|
|
89
|
+
"partialObserver": Object {
|
|
90
|
+
"complete": undefined,
|
|
91
|
+
"error": undefined,
|
|
92
|
+
"next": [Function],
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
"initialTeardown": undefined,
|
|
96
|
+
"isStopped": false,
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
"thrownError": null,
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/>
|
|
103
|
+
}
|
|
21
104
|
contentContainerStyle={
|
|
22
105
|
Object {
|
|
23
106
|
"paddingBottom": undefined,
|
|
@@ -80,22 +163,14 @@ exports[`componentsMap renders renders components map correctly 1`] = `
|
|
|
80
163
|
style={null}
|
|
81
164
|
>
|
|
82
165
|
<View
|
|
166
|
+
onLayout={[Function]}
|
|
83
167
|
style={
|
|
84
168
|
Object {
|
|
85
|
-
"
|
|
169
|
+
"flex": 1,
|
|
86
170
|
}
|
|
87
171
|
}
|
|
88
172
|
>
|
|
89
|
-
<View
|
|
90
|
-
onLayout={[Function]}
|
|
91
|
-
style={
|
|
92
|
-
Object {
|
|
93
|
-
"flex": 1,
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
>
|
|
97
|
-
<View />
|
|
98
|
-
</View>
|
|
173
|
+
<View />
|
|
99
174
|
</View>
|
|
100
175
|
</View>
|
|
101
176
|
<View
|
|
@@ -103,23 +178,13 @@ exports[`componentsMap renders renders components map correctly 1`] = `
|
|
|
103
178
|
style={null}
|
|
104
179
|
>
|
|
105
180
|
<View
|
|
181
|
+
onLayout={[Function]}
|
|
106
182
|
style={
|
|
107
183
|
Object {
|
|
108
|
-
"
|
|
184
|
+
"flex": 1,
|
|
109
185
|
}
|
|
110
186
|
}
|
|
111
|
-
|
|
112
|
-
<View
|
|
113
|
-
onLayout={[Function]}
|
|
114
|
-
style={
|
|
115
|
-
Object {
|
|
116
|
-
"flex": 1,
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
>
|
|
120
|
-
<View />
|
|
121
|
-
</View>
|
|
122
|
-
</View>
|
|
187
|
+
/>
|
|
123
188
|
</View>
|
|
124
189
|
<View
|
|
125
190
|
onLayout={[Function]}
|
|
@@ -127,12 +192,16 @@ exports[`componentsMap renders renders components map correctly 1`] = `
|
|
|
127
192
|
<View
|
|
128
193
|
renderToHardwareTextureAndroid={true}
|
|
129
194
|
style={
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
195
|
+
Array [
|
|
196
|
+
Object {
|
|
197
|
+
"alignItems": "center",
|
|
198
|
+
"justifyContent": "center",
|
|
199
|
+
"width": "100%",
|
|
200
|
+
},
|
|
201
|
+
Object {
|
|
202
|
+
"height": null,
|
|
203
|
+
},
|
|
204
|
+
]
|
|
136
205
|
}
|
|
137
206
|
>
|
|
138
207
|
<ActivityIndicator
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import
|
|
3
|
-
import { cleanup } from "@testing-library/react-native";
|
|
2
|
+
import { cleanup, render } from "@testing-library/react-native";
|
|
4
3
|
import { Provider } from "react-redux";
|
|
5
4
|
import configureStore from "redux-mock-store";
|
|
6
5
|
|
|
@@ -142,12 +141,12 @@ describe("componentsMap", () => {
|
|
|
142
141
|
.spyOn(themeUtils, "useTheme")
|
|
143
142
|
.mockImplementation(() => () => theme);
|
|
144
143
|
|
|
145
|
-
const
|
|
144
|
+
const { toJSON } = render(
|
|
146
145
|
<Provider store={store}>
|
|
147
146
|
<ComponentsMap {...props} />
|
|
148
147
|
</Provider>
|
|
149
148
|
);
|
|
150
149
|
|
|
151
|
-
expect(
|
|
150
|
+
expect(toJSON()).toMatchSnapshot();
|
|
152
151
|
});
|
|
153
152
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-native-ui-components",
|
|
3
|
-
"version": "12.0.
|
|
3
|
+
"version": "12.0.27-alpha.2213255057",
|
|
4
4
|
"description": "Applicaster Zapp React Native ui components for the Quick Brick App",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
"redux-mock-store": "^1.5.3"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@applicaster/applicaster-types": "12.0.
|
|
38
|
-
"@applicaster/zapp-react-native-bridge": "12.0.
|
|
39
|
-
"@applicaster/zapp-react-native-redux": "12.0.
|
|
40
|
-
"@applicaster/zapp-react-native-utils": "12.0.
|
|
37
|
+
"@applicaster/applicaster-types": "12.0.27-alpha.2213255057",
|
|
38
|
+
"@applicaster/zapp-react-native-bridge": "12.0.27-alpha.2213255057",
|
|
39
|
+
"@applicaster/zapp-react-native-redux": "12.0.27-alpha.2213255057",
|
|
40
|
+
"@applicaster/zapp-react-native-utils": "12.0.27-alpha.2213255057",
|
|
41
41
|
"promise": "^8.3.0",
|
|
42
42
|
"react-router-native": "^5.1.2",
|
|
43
43
|
"url": "^0.11.0",
|