@applicaster/zapp-react-native-ui-components 14.0.0-rc.9 → 15.0.0-rc.1
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 +5 -3
- package/Components/AudioPlayer/index.tsx +15 -0
- package/Components/AudioPlayer/mobile/Layout.tsx +66 -0
- package/Components/AudioPlayer/{__tests__/__snapshots__/audioPlayer.test.js.snap → mobile/__tests__/__snapshots__/audioPlayerMobileLayout.test.js.snap} +2 -2
- package/Components/AudioPlayer/mobile/__tests__/audioPlayerMobileLayout.test.js +18 -0
- package/Components/AudioPlayer/mobile/index.tsx +18 -0
- package/Components/AudioPlayer/{Artwork.tsx → tv/Artwork.tsx} +3 -2
- package/Components/AudioPlayer/{Channel.tsx → tv/Channel.tsx} +7 -7
- package/Components/AudioPlayer/tv/Layout.tsx +168 -0
- package/Components/AudioPlayer/{Runtime.tsx → tv/Runtime.tsx} +7 -1
- package/Components/AudioPlayer/{Summary.tsx → tv/Summary.tsx} +6 -2
- package/Components/AudioPlayer/{Title.tsx → tv/Title.tsx} +6 -2
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/Runtime.test.js.snap +2 -2
- package/Components/AudioPlayer/tv/__tests__/__snapshots__/audioPlayer.test.js.snap +164 -0
- package/Components/AudioPlayer/tv/__tests__/__snapshots__/channel.test.js.snap +19 -0
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/summary.test.js.snap +1 -2
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/title.test.js.snap +1 -2
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/audioPlayer.test.js +7 -3
- package/Components/AudioPlayer/{helpers.tsx → tv/helpers.tsx} +11 -5
- package/Components/AudioPlayer/{AudioPlayer.tsx → tv/index.tsx} +17 -58
- package/Components/AudioPlayer/types.ts +40 -0
- package/Components/BaseFocusable/index.tsx +23 -12
- package/Components/Cell/Cell.tsx +91 -64
- package/Components/Cell/CellWithFocusable.tsx +3 -0
- package/Components/Cell/__tests__/CellWIthFocusable.test.js +3 -2
- package/Components/Cell/index.js +7 -3
- package/Components/ComponentResolver/index.ts +1 -1
- 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 +12 -3
- package/Components/Focusable/FocusableTvOS.tsx +5 -5
- package/Components/Focusable/FocusableiOS.tsx +2 -2
- package/Components/Focusable/Touchable.tsx +5 -3
- package/Components/Focusable/__tests__/index.android.test.tsx +3 -0
- package/Components/Focusable/index.android.tsx +19 -11
- package/Components/Focusable/index.tsx +1 -1
- 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 +20 -9
- package/Components/FreezeWithCallback/__tests__/index.test.tsx +67 -43
- package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +42 -59
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +13 -10
- package/Components/HandlePlayable/HandlePlayable.tsx +25 -9
- package/Components/HookRenderer/HookRenderer.tsx +5 -1
- package/Components/Layout/TV/LayoutBackground.tsx +1 -1
- package/Components/Layout/TV/__tests__/index.test.tsx +0 -1
- package/Components/MasterCell/DefaultComponents/ActionButton.tsx +6 -2
- package/Components/MasterCell/DefaultComponents/Button.tsx +1 -1
- package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -39
- package/Components/MasterCell/DefaultComponents/Image/hoc/withDimensions.tsx +1 -1
- package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +1 -1
- 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/elementMapper.tsx +1 -2
- package/Components/MasterCell/index.tsx +1 -1
- package/Components/MasterCell/utils/behaviorProvider.ts +82 -14
- package/Components/MasterCell/utils/index.ts +11 -5
- package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +13 -18
- package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +9 -0
- package/Components/OfflineHandler/__tests__/index.test.tsx +26 -35
- package/Components/PlayerContainer/ErrorDisplay/index.ts +1 -1
- package/Components/PlayerContainer/PlayerContainer.tsx +46 -33
- package/Components/PlayerContainer/ProgramInfo/index.tsx +1 -1
- package/Components/PlayerContainer/index.ts +1 -1
- package/Components/PlayerImageBackground/index.tsx +1 -1
- package/Components/River/ComponentsMap/ComponentsMap.tsx +0 -1
- package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +378 -0
- package/Components/River/ComponentsMap/hooks/useLoadingState.ts +2 -2
- package/Components/River/RefreshControl.tsx +11 -17
- package/Components/River/RiverItem.tsx +3 -0
- package/Components/River/TV/River.tsx +2 -17
- package/Components/River/TV/index.tsx +3 -1
- package/Components/River/TV/withPipesV1DataLoader.tsx +43 -0
- package/Components/River/TV/withRiverDataLoader.tsx +17 -0
- package/Components/River/TV/withTVEventHandler.tsx +1 -1
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +2 -0
- package/Components/River/__tests__/river.test.js +12 -26
- package/Components/River/index.tsx +1 -1
- package/Components/Screen/__tests__/Screen.test.tsx +28 -29
- package/Components/Screen/__tests__/navigationHandler.test.ts +133 -22
- package/Components/Screen/navigationHandler.ts +20 -2
- package/Components/ScreenResolver/index.tsx +15 -0
- package/Components/ScreenRevealManager/ScreenRevealManager.ts +76 -0
- package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +107 -0
- package/Components/ScreenRevealManager/__tests__/withScreenRevealManager.test.tsx +96 -0
- package/Components/ScreenRevealManager/index.ts +1 -0
- package/Components/ScreenRevealManager/withScreenRevealManager.tsx +79 -0
- package/Components/Tabs/TV/Tabs.android.tsx +1 -3
- 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__/__snapshots__/touchable.test.tsx.snap +34 -0
- package/Components/Touchable/__tests__/touchable.test.tsx +12 -17
- package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +15 -9
- package/Components/VideoLive/animationUtils.ts +3 -3
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +3 -9
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.web.tsx +294 -0
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.web.tsx +93 -0
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +73 -29
- package/Components/VideoModal/PlayerDetails.tsx +24 -2
- package/Components/VideoModal/PlayerWrapper.tsx +26 -142
- package/Components/VideoModal/VideoModal.tsx +3 -17
- package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +5 -5
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +1 -7
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +44 -240
- package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +9 -1
- package/Components/VideoModal/hooks/index.ts +0 -2
- package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +40 -15
- package/Components/VideoModal/hooks/useModalSize.ts +18 -2
- package/Components/VideoModal/hooks/utils/__tests__/showDetails.test.ts +2 -2
- package/Components/VideoModal/hooks/utils/index.ts +4 -0
- package/Components/VideoModal/utils.ts +6 -0
- package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +12 -16
- package/Components/Viewport/ViewportTracker/__tests__/viewportTracker.test.js +84 -24
- package/Components/Viewport/VisibilitySensor/VisibilitySensor.tsx +3 -3
- package/Components/default-cell-renderer/viewTrees/tv/DefaultCell/index.ts +3 -3
- package/Contexts/CellFocusedStateContext/index.tsx +27 -0
- package/Contexts/ConfigutaionContext/__tests__/ConfigurationProvider.test.tsx +3 -3
- package/Contexts/ScreenContext/index.tsx +46 -6
- package/Decorators/ConfigurationWrapper/__tests__/withConfigurationProvider.test.tsx +3 -3
- package/Decorators/ConfigurationWrapper/withConfigurationProvider.tsx +2 -2
- 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 +22 -4
- package/Decorators/RiverFeedLoader/utils/index.ts +0 -18
- package/Decorators/RiverResolver/__tests__/riverResolver.test.tsx +3 -6
- package/Decorators/ZappPipesDataConnector/ResolverSelector.tsx +25 -0
- package/Decorators/ZappPipesDataConnector/__tests__/NullFeedResolver.test.tsx +78 -0
- package/Decorators/ZappPipesDataConnector/__tests__/ResolverSelector.test.tsx +205 -0
- package/Decorators/ZappPipesDataConnector/__tests__/StaticFeedResolver.test.tsx +251 -0
- package/Decorators/ZappPipesDataConnector/__tests__/UrlFeedResolver.test.tsx +368 -0
- package/Decorators/ZappPipesDataConnector/__tests__/utils.test.ts +39 -0
- package/Decorators/ZappPipesDataConnector/index.tsx +26 -293
- package/Decorators/ZappPipesDataConnector/resolvers/NullFeedResolver.tsx +25 -0
- package/Decorators/ZappPipesDataConnector/resolvers/StaticFeedResolver.tsx +87 -0
- package/Decorators/ZappPipesDataConnector/resolvers/UrlFeedResolver.tsx +266 -0
- package/Decorators/ZappPipesDataConnector/types.ts +29 -0
- package/Decorators/ZappPipesDataConnector/utils/mongoFilter.ts +738 -0
- package/Decorators/ZappPipesDataConnector/utils/useFilter.tsx +157 -0
- package/events/index.ts +3 -0
- package/package.json +5 -10
- package/Components/AudioPlayer/AudioPlayerLayout.tsx +0 -202
- package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayerLayout.test.js.snap +0 -66
- package/Components/AudioPlayer/__tests__/__snapshots__/channel.test.js.snap +0 -28
- package/Components/AudioPlayer/__tests__/audioPlayerLayout.test.js +0 -26
- package/Components/AudioPlayer/index.ts +0 -1
- package/Components/River/__tests__/__snapshots__/river.test.js.snap +0 -27
- package/Components/VideoModal/hooks/useBackgroundColor.ts +0 -10
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/Runtime.test.js +0 -0
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/artWork.test.js.snap +0 -0
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/artWork.test.js +0 -0
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/channel.test.js +0 -0
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/summary.test.js +0 -0
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/title.test.js +0 -0
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { useEffect, useReducer } from "react";
|
|
3
|
-
|
|
4
|
-
import { TVMenuControl, View, ViewStyle } from "react-native";
|
|
3
|
+
import { View, ViewStyle } from "react-native";
|
|
5
4
|
import * as R from "ramda";
|
|
6
5
|
import uuid from "uuid/v4";
|
|
7
6
|
import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils/playerManager";
|
|
@@ -62,6 +61,11 @@ import {
|
|
|
62
61
|
useModalAnimationContext,
|
|
63
62
|
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
64
63
|
|
|
64
|
+
import {
|
|
65
|
+
PlayerNativeCommandTypes,
|
|
66
|
+
PlayerNativeSendCommand,
|
|
67
|
+
} from "@applicaster/zapp-react-native-utils/appUtils/playerManager/playerNativeCommand";
|
|
68
|
+
|
|
65
69
|
type Props = {
|
|
66
70
|
Player: React.ComponentType<any>;
|
|
67
71
|
PlayerLoadingView?: React.ComponentType<any>; // 👀 we are not receiving this prop
|
|
@@ -88,7 +92,7 @@ export const VideoModalMode = {
|
|
|
88
92
|
MAXIMIZED: "MAXIMIZED",
|
|
89
93
|
MINIMIZED: "MINIMIZED",
|
|
90
94
|
FULLSCREEN: "FULLSCREEN",
|
|
91
|
-
};
|
|
95
|
+
} as const;
|
|
92
96
|
|
|
93
97
|
export type PlayNextData = {
|
|
94
98
|
state: PlayNextState;
|
|
@@ -127,7 +131,7 @@ const webStyles = {
|
|
|
127
131
|
playerScreen: {
|
|
128
132
|
flex: 1,
|
|
129
133
|
height: "100vh",
|
|
130
|
-
|
|
134
|
+
backgroundColor: "black",
|
|
131
135
|
},
|
|
132
136
|
playerWrapper: {
|
|
133
137
|
height: "100%",
|
|
@@ -135,9 +139,6 @@ const webStyles = {
|
|
|
135
139
|
},
|
|
136
140
|
inlineRiver: {
|
|
137
141
|
height: INLINE_CONTAINER_CONTENT_HEIGHT,
|
|
138
|
-
|
|
139
|
-
borderWidth: 4,
|
|
140
|
-
borderColor: "yellow",
|
|
141
142
|
},
|
|
142
143
|
};
|
|
143
144
|
|
|
@@ -148,7 +149,6 @@ const nativeStyles = {
|
|
|
148
149
|
},
|
|
149
150
|
playerScreen: {
|
|
150
151
|
flex: 1,
|
|
151
|
-
backgroundColor: "black",
|
|
152
152
|
overflow: "hidden",
|
|
153
153
|
},
|
|
154
154
|
playerWrapper: {
|
|
@@ -263,9 +263,15 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
263
263
|
return;
|
|
264
264
|
}
|
|
265
265
|
|
|
266
|
+
// send command to clear and stop player
|
|
267
|
+
PlayerNativeSendCommand(
|
|
268
|
+
PlayerNativeCommandTypes.clearPlayerData,
|
|
269
|
+
state.playerId
|
|
270
|
+
);
|
|
271
|
+
|
|
266
272
|
showNavBar(true);
|
|
267
273
|
navigator.goBack();
|
|
268
|
-
}, [isModal, navigator.goBack, showNavBar]);
|
|
274
|
+
}, [isModal, navigator.goBack, state.playerId, showNavBar]);
|
|
269
275
|
|
|
270
276
|
const playEntry = (entry) => navigator.replaceTop(entry, { mode });
|
|
271
277
|
|
|
@@ -393,13 +399,17 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
393
399
|
}
|
|
394
400
|
};
|
|
395
401
|
|
|
396
|
-
const playerRemoteHandler = (
|
|
397
|
-
|
|
402
|
+
const playerRemoteHandler = React.useCallback(
|
|
403
|
+
(isLanguageOverlayVisible = false) =>
|
|
404
|
+
(event) => {
|
|
405
|
+
const { eventType } = event;
|
|
398
406
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
407
|
+
if (!isLanguageOverlayVisible && eventType === "menu") {
|
|
408
|
+
close();
|
|
409
|
+
}
|
|
410
|
+
},
|
|
411
|
+
[close]
|
|
412
|
+
);
|
|
403
413
|
|
|
404
414
|
// Effects
|
|
405
415
|
useEffect(() => {
|
|
@@ -413,7 +423,10 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
413
423
|
id: playerContainerId,
|
|
414
424
|
listener: {
|
|
415
425
|
onVideoEnd,
|
|
416
|
-
onError
|
|
426
|
+
onError: (err: Error) => {
|
|
427
|
+
// Adapt Error to the expected shape for onError
|
|
428
|
+
onError({ error: err });
|
|
429
|
+
},
|
|
417
430
|
onLoad,
|
|
418
431
|
onPlayerClose: close,
|
|
419
432
|
onPlayerDetached: close,
|
|
@@ -512,16 +525,6 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
512
525
|
}
|
|
513
526
|
}, [isAudioContent]);
|
|
514
527
|
|
|
515
|
-
// Needs to handle back button on Apple TV
|
|
516
|
-
// https://github.com/facebook/react-native/issues/18930
|
|
517
|
-
useEffect(() => {
|
|
518
|
-
TVMenuControl?.enableTVMenuKey();
|
|
519
|
-
|
|
520
|
-
return () => {
|
|
521
|
-
TVMenuControl?.disableTVMenuKey();
|
|
522
|
-
};
|
|
523
|
-
}, []);
|
|
524
|
-
|
|
525
528
|
useEffect(() => {
|
|
526
529
|
playerEvent("source_changed", { item });
|
|
527
530
|
|
|
@@ -568,8 +571,9 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
568
571
|
const isInlineTV = isInlineTVUtil(screenData);
|
|
569
572
|
|
|
570
573
|
const inline =
|
|
571
|
-
[VideoModalMode.MAXIMIZED, VideoModalMode.MINIMIZED].includes(
|
|
572
|
-
|
|
574
|
+
[VideoModalMode.MAXIMIZED, VideoModalMode.MINIMIZED].includes(
|
|
575
|
+
mode as any
|
|
576
|
+
) || isInlineTV;
|
|
573
577
|
|
|
574
578
|
const value = React.useMemo(
|
|
575
579
|
() => ({ playerId: state.playerId }),
|
|
@@ -590,7 +594,11 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
590
594
|
);
|
|
591
595
|
}
|
|
592
596
|
|
|
593
|
-
if (
|
|
597
|
+
if (
|
|
598
|
+
screen_background_color &&
|
|
599
|
+
mode !== VideoModalMode.FULLSCREEN &&
|
|
600
|
+
isTV()
|
|
601
|
+
) {
|
|
594
602
|
updatedStyles.playerScreen.backgroundColor = screen_background_color;
|
|
595
603
|
}
|
|
596
604
|
|
|
@@ -620,6 +628,8 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
620
628
|
playNextData,
|
|
621
629
|
};
|
|
622
630
|
|
|
631
|
+
const pointerEventsProp = mode === "MINIMIZED" ? "box-none" : "auto";
|
|
632
|
+
|
|
623
633
|
return (
|
|
624
634
|
<PlayerStateContext.Provider value={value}>
|
|
625
635
|
<PlayerContainerContextProvider
|
|
@@ -630,9 +640,9 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
630
640
|
<PlayerContainerContext.Consumer>
|
|
631
641
|
{(context) => (
|
|
632
642
|
<TVEventHandlerComponent
|
|
633
|
-
tvEventHandler={(
|
|
634
|
-
|
|
635
|
-
}
|
|
643
|
+
tvEventHandler={playerRemoteHandler(
|
|
644
|
+
context.isLanguageOverlayVisible
|
|
645
|
+
)}
|
|
636
646
|
>
|
|
637
647
|
<FocusableGroup
|
|
638
648
|
id={FocusableGroupMainContainerId}
|
|
@@ -640,14 +650,17 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
640
650
|
preferredFocus
|
|
641
651
|
shouldUsePreferredFocus
|
|
642
652
|
groupId={groupId}
|
|
653
|
+
pointerEvents={pointerEventsProp}
|
|
643
654
|
>
|
|
644
655
|
{/* Video player and components */}
|
|
645
656
|
<View
|
|
646
657
|
style={styles.playerScreen}
|
|
647
658
|
testID={"player-screen-container"}
|
|
659
|
+
pointerEvents={pointerEventsProp}
|
|
648
660
|
>
|
|
649
661
|
{/* Player container */}
|
|
650
662
|
<View
|
|
663
|
+
pointerEvents={pointerEventsProp}
|
|
651
664
|
style={[
|
|
652
665
|
styles.playerWrapper,
|
|
653
666
|
// eslint-disable-next-line react-native/no-inline-styles, react-native/no-color-literals
|
|
@@ -719,7 +732,7 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
719
732
|
key={item.id}
|
|
720
733
|
groupId={FocusableGroupMainContainerId}
|
|
721
734
|
cellTapAction={onCellTap}
|
|
722
|
-
extraAnchorPointYOffset={
|
|
735
|
+
extraAnchorPointYOffset={0}
|
|
723
736
|
isScreenWrappedInContainer={true}
|
|
724
737
|
containerHeight={styles.inlineRiver.height}
|
|
725
738
|
componentsMapExtraProps={{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { connectToStore } from "@applicaster/zapp-react-native-redux";
|
|
1
|
+
import { connectToStore } from "@applicaster/zapp-react-native-redux/utils/connectToStore";
|
|
2
2
|
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
3
3
|
import { styleKeys } from "@applicaster/zapp-react-native-utils/styleKeysUtils";
|
|
4
4
|
import { transformColorCode as fixColorHexCode } from "@applicaster/zapp-react-native-utils/transform";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as R from "ramda";
|
|
2
2
|
|
|
3
|
-
import { connectToStore } from "@applicaster/zapp-react-native-redux";
|
|
3
|
+
import { connectToStore } from "@applicaster/zapp-react-native-redux/utils/connectToStore";
|
|
4
4
|
import { loadPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";
|
|
5
5
|
|
|
6
6
|
import { PlayerContainer as PlayerContainerComponent } from "./PlayerContainer";
|
|
@@ -28,7 +28,7 @@ const PlayerImageBackgroundComponent = ({
|
|
|
28
28
|
defaultImageDimensions,
|
|
29
29
|
}: Props) => {
|
|
30
30
|
const source = React.useMemo(
|
|
31
|
-
() => ({ uri: imageSrcFromMediaItem(entry, imageKey) }),
|
|
31
|
+
() => ({ uri: imageSrcFromMediaItem(entry, [imageKey]) }),
|
|
32
32
|
[imageKey, entry]
|
|
33
33
|
);
|
|
34
34
|
|
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import { renderHook, act } from "@testing-library/react-hooks";
|
|
2
|
+
import { BehaviorSubject } from "rxjs";
|
|
3
|
+
import { useLoadingState } from "../useLoadingState";
|
|
4
|
+
|
|
5
|
+
jest.mock(
|
|
6
|
+
"@applicaster/zapp-react-native-utils/reactHooks/state/useRefWithInitialValue",
|
|
7
|
+
() => ({
|
|
8
|
+
useRefWithInitialValue: jest.fn((initializer) => ({
|
|
9
|
+
current: initializer(),
|
|
10
|
+
})),
|
|
11
|
+
})
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
describe("useLoadingState", () => {
|
|
15
|
+
let onLoadDone: jest.Mock;
|
|
16
|
+
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
onLoadDone = jest.fn();
|
|
19
|
+
jest.clearAllMocks();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
describe("initialization", () => {
|
|
23
|
+
it("should initialize with correct default state for zero components", () => {
|
|
24
|
+
const { result } = renderHook(() => useLoadingState(0, onLoadDone));
|
|
25
|
+
|
|
26
|
+
const initialState = result.current.loadingState.getValue();
|
|
27
|
+
|
|
28
|
+
expect(initialState).toEqual({
|
|
29
|
+
index: -1,
|
|
30
|
+
done: true,
|
|
31
|
+
waitForAllComponents: false,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
expect(result.current.shouldShowLoadingError).toBe(false);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("should initialize with correct default state for multiple components", () => {
|
|
38
|
+
const { result } = renderHook(() => useLoadingState(3, onLoadDone));
|
|
39
|
+
|
|
40
|
+
const initialState = result.current.loadingState.getValue();
|
|
41
|
+
|
|
42
|
+
expect(initialState).toEqual({
|
|
43
|
+
index: -1,
|
|
44
|
+
done: false,
|
|
45
|
+
waitForAllComponents: false,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
expect(result.current.shouldShowLoadingError).toBe(false);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("should return a BehaviorSubject for loadingState", () => {
|
|
52
|
+
const { result } = renderHook(() => useLoadingState(3, onLoadDone));
|
|
53
|
+
|
|
54
|
+
expect(result.current.loadingState).toBeInstanceOf(BehaviorSubject);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe("arePreviousComponentsLoaded", () => {
|
|
59
|
+
it("should return true for index 0 (first component)", () => {
|
|
60
|
+
const { result } = renderHook(() => useLoadingState(3, onLoadDone));
|
|
61
|
+
|
|
62
|
+
expect(result.current.arePreviousComponentsLoaded(0)).toBe(true);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("should return false when previous components are not loaded", () => {
|
|
66
|
+
const { result } = renderHook(() => useLoadingState(3, onLoadDone));
|
|
67
|
+
|
|
68
|
+
expect(result.current.arePreviousComponentsLoaded(1)).toBe(false);
|
|
69
|
+
expect(result.current.arePreviousComponentsLoaded(2)).toBe(false);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("should return true when all previous components are loaded", () => {
|
|
73
|
+
const { result } = renderHook(() => useLoadingState(3, onLoadDone));
|
|
74
|
+
|
|
75
|
+
act(() => {
|
|
76
|
+
result.current.onLoadFinished(0);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
expect(result.current.arePreviousComponentsLoaded(1)).toBe(true);
|
|
80
|
+
expect(result.current.arePreviousComponentsLoaded(2)).toBe(false);
|
|
81
|
+
|
|
82
|
+
act(() => {
|
|
83
|
+
result.current.onLoadFinished(1);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
expect(result.current.arePreviousComponentsLoaded(2)).toBe(true);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
describe("onLoadFinished", () => {
|
|
91
|
+
it("should update component state and loading state when component finishes loading", () => {
|
|
92
|
+
const { result } = renderHook(() => useLoadingState(3, onLoadDone));
|
|
93
|
+
|
|
94
|
+
act(() => {
|
|
95
|
+
result.current.onLoadFinished(0);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const state = result.current.loadingState.getValue();
|
|
99
|
+
expect(state.index).toBe(0);
|
|
100
|
+
expect(state.done).toBe(false);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("should update index to highest loaded component", () => {
|
|
104
|
+
const { result } = renderHook(() => useLoadingState(3, onLoadDone));
|
|
105
|
+
|
|
106
|
+
act(() => {
|
|
107
|
+
result.current.onLoadFinished(2);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
let state = result.current.loadingState.getValue();
|
|
111
|
+
expect(state.index).toBe(2);
|
|
112
|
+
|
|
113
|
+
act(() => {
|
|
114
|
+
result.current.onLoadFinished(1);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
state = result.current.loadingState.getValue();
|
|
118
|
+
expect(state.index).toBe(2); // Should remain 2, not decrease to 1
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("should mark as done when all components are loaded", () => {
|
|
122
|
+
const { result } = renderHook(() => useLoadingState(2, onLoadDone));
|
|
123
|
+
|
|
124
|
+
act(() => {
|
|
125
|
+
result.current.onLoadFinished(0);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
let state = result.current.loadingState.getValue();
|
|
129
|
+
expect(state.done).toBe(true); // True because arePreviousComponentsLoaded(1) returns true when component 0 is loaded
|
|
130
|
+
expect(onLoadDone).toHaveBeenCalledTimes(1);
|
|
131
|
+
|
|
132
|
+
act(() => {
|
|
133
|
+
result.current.onLoadFinished(1);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
state = result.current.loadingState.getValue();
|
|
137
|
+
expect(state.done).toBe(true);
|
|
138
|
+
expect(onLoadDone).toHaveBeenCalledTimes(2); // Called again
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it("should call onLoadDone when count is 0", () => {
|
|
142
|
+
const { result } = renderHook(() => useLoadingState(0, onLoadDone));
|
|
143
|
+
|
|
144
|
+
const state = result.current.loadingState.getValue();
|
|
145
|
+
expect(state.done).toBe(true);
|
|
146
|
+
// onLoadDone is not called on initialization for count 0, only when all components are loaded via dispatch
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it("should handle loading components out of order", () => {
|
|
150
|
+
const { result } = renderHook(() => useLoadingState(3, onLoadDone));
|
|
151
|
+
|
|
152
|
+
// Load component 2 first
|
|
153
|
+
act(() => {
|
|
154
|
+
result.current.onLoadFinished(2);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
let state = result.current.loadingState.getValue();
|
|
158
|
+
expect(state.done).toBe(false);
|
|
159
|
+
|
|
160
|
+
// Load component 0
|
|
161
|
+
act(() => {
|
|
162
|
+
result.current.onLoadFinished(0);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
state = result.current.loadingState.getValue();
|
|
166
|
+
expect(state.done).toBe(false);
|
|
167
|
+
|
|
168
|
+
// Load component 1 - should complete loading
|
|
169
|
+
act(() => {
|
|
170
|
+
result.current.onLoadFinished(1);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
state = result.current.loadingState.getValue();
|
|
174
|
+
expect(state.done).toBe(true);
|
|
175
|
+
expect(onLoadDone).toHaveBeenCalledTimes(1);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it("should call onLoadDone again on subsequent dispatches", () => {
|
|
179
|
+
const { result } = renderHook(() => useLoadingState(2, onLoadDone));
|
|
180
|
+
|
|
181
|
+
act(() => {
|
|
182
|
+
result.current.onLoadFinished(0);
|
|
183
|
+
result.current.onLoadFinished(1);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
expect(onLoadDone).toHaveBeenCalledTimes(2); // Called for each dispatch when done is true
|
|
187
|
+
|
|
188
|
+
// Try loading again - onLoadDone will be called again because dispatch runs again
|
|
189
|
+
act(() => {
|
|
190
|
+
result.current.onLoadFinished(0);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
expect(onLoadDone).toHaveBeenCalledTimes(3); // Will be called again
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
describe("onLoadFailed", () => {
|
|
198
|
+
it("should treat failed components as loaded when SHOULD_FAIL_ON_COMPONENT_LOADING is false", () => {
|
|
199
|
+
const { result } = renderHook(() => useLoadingState(2, onLoadDone));
|
|
200
|
+
|
|
201
|
+
const error = new Error("Load failed");
|
|
202
|
+
|
|
203
|
+
act(() => {
|
|
204
|
+
result.current.onLoadFailed({ error, index: 0 });
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
const state = result.current.loadingState.getValue();
|
|
208
|
+
expect(state.index).toBe(0);
|
|
209
|
+
expect(result.current.shouldShowLoadingError).toBe(false);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it("should complete loading when all components fail", () => {
|
|
213
|
+
const { result } = renderHook(() => useLoadingState(2, onLoadDone));
|
|
214
|
+
|
|
215
|
+
const error = new Error("Load failed");
|
|
216
|
+
|
|
217
|
+
act(() => {
|
|
218
|
+
result.current.onLoadFailed({ error, index: 0 });
|
|
219
|
+
result.current.onLoadFailed({ error, index: 1 });
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
const state = result.current.loadingState.getValue();
|
|
223
|
+
expect(state.done).toBe(true);
|
|
224
|
+
expect(onLoadDone).toHaveBeenCalledTimes(2); // Called for each failed component
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it("should handle mixed success and failure", () => {
|
|
228
|
+
const { result } = renderHook(() => useLoadingState(3, onLoadDone));
|
|
229
|
+
|
|
230
|
+
const error = new Error("Load failed");
|
|
231
|
+
|
|
232
|
+
act(() => {
|
|
233
|
+
result.current.onLoadFinished(0);
|
|
234
|
+
result.current.onLoadFailed({ error, index: 1 });
|
|
235
|
+
result.current.onLoadFinished(2);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
const state = result.current.loadingState.getValue();
|
|
239
|
+
expect(state.done).toBe(true);
|
|
240
|
+
expect(onLoadDone).toHaveBeenCalledTimes(2); // Called when all components 0,1,2 are handled
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
describe("loading state observable", () => {
|
|
245
|
+
it("should emit state changes through BehaviorSubject", () => {
|
|
246
|
+
const { result } = renderHook(() => useLoadingState(3, onLoadDone)); // Use 3 components so loading component 0 doesn't complete everything
|
|
247
|
+
const mockSubscriber = jest.fn();
|
|
248
|
+
|
|
249
|
+
result.current.loadingState.subscribe(mockSubscriber);
|
|
250
|
+
|
|
251
|
+
act(() => {
|
|
252
|
+
result.current.onLoadFinished(0);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
// Should have been called twice: initial state + update
|
|
256
|
+
expect(mockSubscriber).toHaveBeenCalledTimes(2);
|
|
257
|
+
|
|
258
|
+
expect(mockSubscriber).toHaveBeenLastCalledWith({
|
|
259
|
+
index: 0,
|
|
260
|
+
done: false, // Will be false because we need components 1 and 2 as well
|
|
261
|
+
waitForAllComponents: false,
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it("should preserve waitForAllComponents flag in state updates", () => {
|
|
266
|
+
const { result } = renderHook(() => useLoadingState(2, onLoadDone));
|
|
267
|
+
|
|
268
|
+
act(() => {
|
|
269
|
+
result.current.onLoadFinished(0);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
const state = result.current.loadingState.getValue();
|
|
273
|
+
expect(state.waitForAllComponents).toBe(false);
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
describe("memoization", () => {
|
|
278
|
+
it("should return stable references for functions", () => {
|
|
279
|
+
const { result, rerender } = renderHook(() =>
|
|
280
|
+
useLoadingState(2, onLoadDone)
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
const firstRender = {
|
|
284
|
+
onLoadFinished: result.current.onLoadFinished,
|
|
285
|
+
onLoadFailed: result.current.onLoadFailed,
|
|
286
|
+
arePreviousComponentsLoaded: result.current.arePreviousComponentsLoaded,
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
rerender();
|
|
290
|
+
|
|
291
|
+
expect(result.current.onLoadFinished).toBe(firstRender.onLoadFinished);
|
|
292
|
+
expect(result.current.onLoadFailed).toBe(firstRender.onLoadFailed);
|
|
293
|
+
|
|
294
|
+
expect(result.current.arePreviousComponentsLoaded).toBe(
|
|
295
|
+
firstRender.arePreviousComponentsLoaded
|
|
296
|
+
);
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
it("should return stable function references (current behavior)", () => {
|
|
300
|
+
const { result, rerender } = renderHook(
|
|
301
|
+
({ onLoadDone }) => useLoadingState(2, onLoadDone),
|
|
302
|
+
{ initialProps: { onLoadDone } }
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
const firstResult = result.current;
|
|
306
|
+
|
|
307
|
+
const newOnLoadDone = jest.fn();
|
|
308
|
+
rerender({ onLoadDone: newOnLoadDone });
|
|
309
|
+
|
|
310
|
+
// Functions should remain the same due to empty dependency arrays (this is the current behavior)
|
|
311
|
+
expect(result.current.onLoadFinished).toBe(firstResult.onLoadFinished);
|
|
312
|
+
expect(result.current.onLoadFailed).toBe(firstResult.onLoadFailed);
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
describe("edge cases", () => {
|
|
317
|
+
it("should handle duplicate load finished calls gracefully", () => {
|
|
318
|
+
const { result } = renderHook(() => useLoadingState(2, onLoadDone));
|
|
319
|
+
|
|
320
|
+
act(() => {
|
|
321
|
+
result.current.onLoadFinished(0);
|
|
322
|
+
result.current.onLoadFinished(0); // Duplicate call
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
const state = result.current.loadingState.getValue();
|
|
326
|
+
expect(state.index).toBe(0);
|
|
327
|
+
expect(state.done).toBe(true); // True because loading component 0 makes it done in a 2-component setup
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
it("should handle loading index greater than component count", () => {
|
|
331
|
+
const { result } = renderHook(() => useLoadingState(2, onLoadDone));
|
|
332
|
+
|
|
333
|
+
act(() => {
|
|
334
|
+
result.current.onLoadFinished(5); // Index out of bounds
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
const state = result.current.loadingState.getValue();
|
|
338
|
+
expect(state.index).toBe(5);
|
|
339
|
+
expect(state.done).toBe(false); // Should not be done as not all components loaded
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
it("should handle negative indices", () => {
|
|
343
|
+
const { result } = renderHook(() => useLoadingState(2, onLoadDone));
|
|
344
|
+
|
|
345
|
+
act(() => {
|
|
346
|
+
result.current.onLoadFinished(-1);
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
const state = result.current.loadingState.getValue();
|
|
350
|
+
expect(state.index).toBe(-1); // Should remain -1
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
describe("component count changes", () => {
|
|
355
|
+
it("should handle changing component count", () => {
|
|
356
|
+
const { result, rerender } = renderHook(
|
|
357
|
+
({ count }) => useLoadingState(count, onLoadDone),
|
|
358
|
+
{ initialProps: { count: 2 } }
|
|
359
|
+
);
|
|
360
|
+
|
|
361
|
+
act(() => {
|
|
362
|
+
result.current.onLoadFinished(0);
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
// Change count
|
|
366
|
+
rerender({ count: 3 });
|
|
367
|
+
|
|
368
|
+
// The hook should work with the new count
|
|
369
|
+
act(() => {
|
|
370
|
+
result.current.onLoadFinished(1);
|
|
371
|
+
result.current.onLoadFinished(2);
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
const state = result.current.loadingState.getValue();
|
|
375
|
+
expect(state.done).toBe(true);
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { isNil, set, lensIndex,
|
|
2
|
+
import { isNil, set, lensIndex, slice } from "ramda";
|
|
3
3
|
import { BehaviorSubject } from "rxjs";
|
|
4
4
|
import { useRefWithInitialValue } from "@applicaster/zapp-react-native-utils/reactHooks/state/useRefWithInitialValue";
|
|
5
5
|
|
|
@@ -53,7 +53,7 @@ export const useLoadingState = (
|
|
|
53
53
|
|
|
54
54
|
const componentsBefore = slice(0, index, componentStateRef.current);
|
|
55
55
|
|
|
56
|
-
return componentsBefore.every(
|
|
56
|
+
return componentsBefore.every(Boolean);
|
|
57
57
|
}, []);
|
|
58
58
|
|
|
59
59
|
const dispatch = React.useCallback(({ payload }) => {
|
|
@@ -10,11 +10,10 @@ import { useLocalizedStrings } from "@applicaster/zapp-react-native-utils/locali
|
|
|
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
12
|
import { useCurrentScreenData } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useCurrentScreenData";
|
|
13
|
-
import { loadPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";
|
|
14
|
-
import { useDispatch } from "react-redux";
|
|
15
13
|
import { useShallow } from "zustand/react/shallow";
|
|
16
14
|
import { useScreenContextV2 } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useScreenContext";
|
|
17
15
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
16
|
+
import { useLoadPipesDataDispatch } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
18
17
|
|
|
19
18
|
const BRIGHTNESS_THRESHOLD = 160;
|
|
20
19
|
const ABOVE_DEFAULT_COLOR = "gray";
|
|
@@ -61,38 +60,33 @@ export const usePullToRefresh = (
|
|
|
61
60
|
) => {
|
|
62
61
|
const isPipesV1 = !!pullToRefreshPipesV1RefreshingStateUpdater;
|
|
63
62
|
|
|
64
|
-
const dispatch = useDispatch();
|
|
65
|
-
|
|
66
63
|
const [refreshing, setRefreshing] = React.useState(false);
|
|
67
64
|
|
|
68
65
|
const feeds: string[] =
|
|
69
66
|
riverComponents?.map(R.path(["data", "source"])).filter((feed) => !!feed) ??
|
|
70
67
|
[];
|
|
71
68
|
|
|
72
|
-
const screenData = useCurrentScreenData();
|
|
73
|
-
|
|
74
69
|
const feedsLength = feeds.length;
|
|
75
70
|
|
|
76
71
|
const [requestsCompletedCounter, setRequestsCompletedCounter] =
|
|
77
72
|
React.useState(0);
|
|
78
73
|
|
|
74
|
+
const loadPipesDataDispatcher = useLoadPipesDataDispatch();
|
|
75
|
+
|
|
79
76
|
React.useEffect(() => {
|
|
80
77
|
// will not work for pipes v1 on 1st level screens
|
|
81
78
|
if (refreshing && !isPipesV1) {
|
|
82
79
|
feeds.forEach((feed) => {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
riverId: screenData.id,
|
|
91
|
-
})
|
|
92
|
-
);
|
|
80
|
+
loadPipesDataDispatcher(feed, {
|
|
81
|
+
silentRefresh: true,
|
|
82
|
+
clearCache: true,
|
|
83
|
+
callback: () => {
|
|
84
|
+
setRequestsCompletedCounter(R.inc);
|
|
85
|
+
},
|
|
86
|
+
});
|
|
93
87
|
});
|
|
94
88
|
}
|
|
95
|
-
}, [refreshing, isPipesV1]);
|
|
89
|
+
}, [refreshing, isPipesV1, feeds, loadPipesDataDispatcher]);
|
|
96
90
|
|
|
97
91
|
React.useEffect(() => {
|
|
98
92
|
if (requestsCompletedCounter === feedsLength) {
|