@applicaster/zapp-react-native-ui-components 14.0.0-alpha.1661204539 → 14.0.0-alpha.2247415563
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/tv/Artwork.tsx +40 -0
- package/Components/AudioPlayer/{AudioPlayerLayout.tsx → tv/Layout.tsx} +34 -75
- package/Components/AudioPlayer/{Runtime.tsx → tv/Runtime.tsx} +2 -1
- package/Components/AudioPlayer/{Summary.tsx → tv/Summary.tsx} +12 -9
- package/Components/AudioPlayer/{Title.tsx → tv/Title.tsx} +12 -9
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/artWork.test.js.snap +9 -4
- package/Components/AudioPlayer/tv/__tests__/__snapshots__/audioPlayer.test.js.snap +170 -0
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/summary.test.js.snap +1 -1
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/title.test.js.snap +1 -1
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/audioPlayer.test.js +7 -3
- package/Components/AudioPlayer/{helpers.tsx → tv/helpers.tsx} +3 -4
- package/Components/AudioPlayer/{AudioPlayer.tsx → tv/index.tsx} +14 -59
- package/Components/AudioPlayer/types.ts +40 -0
- package/Components/Focusable/FocusableTvOS.tsx +3 -3
- package/Components/FocusableList/index.tsx +4 -0
- package/Components/GeneralContentScreen/GeneralContentScreen.tsx +0 -2
- package/Components/HandlePlayable/HandlePlayable.tsx +14 -8
- package/Components/MasterCell/DefaultComponents/Text/index.tsx +1 -0
- package/Components/MasterCell/elementMapper.tsx +1 -2
- package/Components/MasterCell/utils/behaviorProvider.ts +12 -67
- package/Components/MasterCell/utils/index.ts +3 -13
- package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +13 -18
- package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +9 -0
- package/Components/PlayerContainer/PlayerContainer.tsx +48 -61
- package/Components/PlayerImageBackground/index.tsx +1 -1
- package/Components/River/ComponentsMap/ComponentsMap.tsx +1 -6
- package/Components/River/RiverItem.tsx +8 -8
- package/Components/River/TV/River.tsx +0 -3
- package/Components/River/TV/withTVEventHandler.tsx +1 -1
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +2 -6
- package/Components/Tabs/TV/Tabs.android.tsx +0 -2
- package/Components/TopMarginApplicator/TopMarginApplicator.tsx +16 -15
- package/Components/Touchable/__tests__/__snapshots__/touchable.test.tsx.snap +34 -0
- package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +15 -9
- package/Components/VideoLive/animationUtils.ts +3 -3
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +60 -0
- package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +17 -55
- package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +15 -26
- package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +12 -16
- package/Components/Viewport/ViewportTracker/__tests__/viewportTracker.test.js +84 -24
- package/Decorators/ConfigurationWrapper/withConfigurationProvider.tsx +2 -2
- package/Decorators/RiverFeedLoader/index.tsx +2 -8
- package/Decorators/RiverFeedLoader/utils/index.ts +2 -7
- package/Decorators/ZappPipesDataConnector/index.tsx +2 -16
- package/index.d.ts +0 -1
- package/package.json +5 -6
- package/Components/AudioPlayer/Artwork.tsx +0 -35
- package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayerLayout.test.js.snap +0 -66
- package/Components/AudioPlayer/__tests__/audioPlayerLayout.test.js +0 -26
- package/Components/AudioPlayer/index.ts +0 -1
- package/Components/AudioPlayer/{Channel.tsx → tv/Channel.tsx} +0 -0
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/Runtime.test.js +0 -0
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/Runtime.test.js.snap +2 -2
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/channel.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,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { render } from "@testing-library/react-native";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { AudioPlayerTV } from "..";
|
|
5
|
+
|
|
6
|
+
jest.mock("@applicaster/zapp-react-native-utils/audioPlayerUtils", () => ({
|
|
7
|
+
useArtworkImage: jest.fn(() => "artwork_url"),
|
|
8
|
+
}));
|
|
5
9
|
|
|
6
10
|
const audioPlayerProps = {
|
|
7
11
|
audio_item: {
|
|
@@ -45,9 +49,9 @@ const audioPlayerProps = {
|
|
|
45
49
|
styles: {},
|
|
46
50
|
};
|
|
47
51
|
|
|
48
|
-
describe("<
|
|
52
|
+
describe("<AudioPlayerTV />", () => {
|
|
49
53
|
it("renders correctly", () => {
|
|
50
|
-
const { toJSON } = render(<
|
|
54
|
+
const { toJSON } = render(<AudioPlayerTV {...audioPlayerProps} />);
|
|
51
55
|
expect(toJSON()).toMatchSnapshot();
|
|
52
56
|
});
|
|
53
57
|
});
|
|
@@ -2,9 +2,8 @@ const defaults = {
|
|
|
2
2
|
audio_player_title_color: "white",
|
|
3
3
|
audio_player_summary_color: "white",
|
|
4
4
|
audio_player_background_color: "black",
|
|
5
|
-
|
|
5
|
+
audio_player_background_image: undefined,
|
|
6
6
|
audio_player_rtl: false,
|
|
7
|
-
audio_player_background_image_default_color: "",
|
|
8
7
|
};
|
|
9
8
|
|
|
10
9
|
export function getPropertyFromEntryOrConfig({ entry, plugin_configuration }) {
|
|
@@ -26,14 +25,14 @@ export function getPropertyFromEntryOrConfig({ entry, plugin_configuration }) {
|
|
|
26
25
|
const LTR = {
|
|
27
26
|
flexDirection: "row",
|
|
28
27
|
justifyContent: "flex-start",
|
|
29
|
-
textAlign: "
|
|
28
|
+
textAlign: "left",
|
|
30
29
|
alignItems: "flex-end",
|
|
31
30
|
};
|
|
32
31
|
|
|
33
32
|
const RTL = {
|
|
34
33
|
flexDirection: "row-reverse",
|
|
35
34
|
justifyContent: "flex-end",
|
|
36
|
-
textAlign: "
|
|
35
|
+
textAlign: "right",
|
|
37
36
|
alignItems: "flex-start",
|
|
38
37
|
};
|
|
39
38
|
|
|
@@ -1,60 +1,24 @@
|
|
|
1
1
|
import React, { useCallback, useMemo } from "react";
|
|
2
2
|
|
|
3
3
|
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
4
|
+
import { useArtworkImage } from "@applicaster/zapp-react-native-utils/audioPlayerUtils";
|
|
4
5
|
|
|
5
|
-
import {
|
|
6
|
+
import { AudioPlayerTVLayout } from "./Layout";
|
|
6
7
|
|
|
7
|
-
import { AudioPlayerLayout } from "./AudioPlayerLayout";
|
|
8
8
|
import { Channel } from "./Channel";
|
|
9
9
|
import { Title } from "./Title";
|
|
10
10
|
import { Summary } from "./Summary";
|
|
11
11
|
import { Runtime } from "./Runtime";
|
|
12
12
|
import { getPropertyFromEntryOrConfig } from "./helpers";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
audio_player_artwork_aspect_ratio?: string;
|
|
19
|
-
audio_player_background_image?: string;
|
|
20
|
-
audio_player_background_color?: string;
|
|
21
|
-
audio_player_channel_icon?: string;
|
|
22
|
-
audio_player_title_color?: string;
|
|
23
|
-
audio_player_summary_color?: string;
|
|
24
|
-
audio_player_rtl?: boolean;
|
|
25
|
-
audio_player_background_image_default_color?: string;
|
|
26
|
-
start_time?: string;
|
|
27
|
-
end_time?: string;
|
|
28
|
-
};
|
|
29
|
-
};
|
|
30
|
-
plugin_configuration: {
|
|
31
|
-
audio_player_background_color?: string;
|
|
32
|
-
audio_player_title_color?: string;
|
|
33
|
-
audio_player_summary_color?: string;
|
|
34
|
-
audio_player_rtl?: string;
|
|
35
|
-
audio_player_background_image_default_color?: string;
|
|
36
|
-
audio_player_background_image?: string;
|
|
37
|
-
audio_player_artwork_aspect_ratio?: string;
|
|
38
|
-
lg_tv_audio_player_title_font_family?: string;
|
|
39
|
-
lg_tv_audio_player_title_font_size?: number;
|
|
40
|
-
lg_tv_audio_player_summary_font_family?: string;
|
|
41
|
-
lg_tv_audio_player_summary_font_size?: number;
|
|
42
|
-
samsung_tv_audio_player_title_font_family?: string;
|
|
43
|
-
samsung_tv_audio_player_title_font_size?: number;
|
|
44
|
-
samsung_tv_audio_player_summary_font_family?: string;
|
|
45
|
-
samsung_tv_audio_player_summary_font_size?: number;
|
|
46
|
-
tv_os_audio_player_title_font_family?: string;
|
|
47
|
-
tv_os_audio_player_title_font_size?: number;
|
|
48
|
-
tv_os_audio_player_summary_font_family?: string;
|
|
49
|
-
tv_os_audio_player_summary_font_size?: number;
|
|
50
|
-
};
|
|
51
|
-
style?: ViewStyle;
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
export function AudioPlayer(props: Props) {
|
|
55
|
-
const { audio_item, plugin_configuration, style } = props;
|
|
13
|
+
|
|
14
|
+
import { Props } from "../types";
|
|
15
|
+
|
|
16
|
+
export function AudioPlayerTV(props: Props) {
|
|
17
|
+
const { audio_item, plugin_configuration, style = {} } = props;
|
|
56
18
|
const { extensions, title, summary } = audio_item;
|
|
57
19
|
|
|
20
|
+
const artwork = useArtworkImage(audio_item);
|
|
21
|
+
|
|
58
22
|
const getProp = useCallback(
|
|
59
23
|
getPropertyFromEntryOrConfig({
|
|
60
24
|
entry: audio_item,
|
|
@@ -64,18 +28,14 @@ export function AudioPlayer(props: Props) {
|
|
|
64
28
|
);
|
|
65
29
|
|
|
66
30
|
const config = useMemo(() => {
|
|
67
|
-
// Checking if we are
|
|
31
|
+
// Checking if we are receiving items from the DSP
|
|
68
32
|
const titleColor = getProp("audio_player_title_color");
|
|
69
33
|
const summaryColor = getProp("audio_player_summary_color");
|
|
70
34
|
const backgroundColor = getProp("audio_player_background_color");
|
|
71
35
|
const backgroundImage = getProp("audio_player_background_image");
|
|
72
|
-
const artworkAspectRatio = getProp("audio_player_artwork_aspect_ratio");
|
|
73
36
|
const channelIcon = getProp("audio_player_channel_icon");
|
|
74
37
|
const rtlFlag = getProp("audio_player_rtl");
|
|
75
|
-
|
|
76
|
-
const audioPlayerBackgroundImageDefaultColor = getProp(
|
|
77
|
-
"audio_player_background_image_default_color"
|
|
78
|
-
);
|
|
38
|
+
const artworkBorderRadius = getProp("audio_player_artwork_border_radius");
|
|
79
39
|
|
|
80
40
|
const isRTL = rtlFlag === "1" || rtlFlag === "true" || rtlFlag === true;
|
|
81
41
|
|
|
@@ -151,22 +111,17 @@ export function AudioPlayer(props: Props) {
|
|
|
151
111
|
summaryFontSize,
|
|
152
112
|
runTimeFontFamily,
|
|
153
113
|
runTimeFontSize,
|
|
154
|
-
artworkAspectRatio,
|
|
155
114
|
channelIcon,
|
|
156
|
-
|
|
115
|
+
artworkBorderRadius,
|
|
157
116
|
};
|
|
158
117
|
}, [getProp]);
|
|
159
118
|
|
|
160
|
-
const artwork = imageSrcFromMediaItem(audio_item, [
|
|
161
|
-
config?.artworkAspectRatio,
|
|
162
|
-
]);
|
|
163
|
-
|
|
164
119
|
return (
|
|
165
|
-
<
|
|
120
|
+
<AudioPlayerTVLayout artwork={artwork} config={config} style={style}>
|
|
166
121
|
<Channel srcImage={config?.channelIcon} config={config} />
|
|
167
122
|
<Title title={title} config={config} />
|
|
168
123
|
<Summary summary={summary} config={config} />
|
|
169
124
|
<Runtime {...extensions} config={config} />
|
|
170
|
-
</
|
|
125
|
+
</AudioPlayerTVLayout>
|
|
171
126
|
);
|
|
172
127
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ViewStyle } from "react-native";
|
|
2
|
+
|
|
3
|
+
export type Props = {
|
|
4
|
+
audio_item: ZappEntry & {
|
|
5
|
+
extensions?: {
|
|
6
|
+
audio_player_artwork_aspect_ratio?: string;
|
|
7
|
+
audio_player_background_image?: string;
|
|
8
|
+
audio_player_background_color?: string;
|
|
9
|
+
audio_player_channel_icon?: string;
|
|
10
|
+
audio_player_title_color?: string;
|
|
11
|
+
audio_player_summary_color?: string;
|
|
12
|
+
audio_player_rtl?: boolean;
|
|
13
|
+
audio_player_background_image_default_color?: string;
|
|
14
|
+
start_time?: string;
|
|
15
|
+
end_time?: string;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
plugin_configuration: {
|
|
19
|
+
audio_player_background_color?: string;
|
|
20
|
+
audio_player_title_color?: string;
|
|
21
|
+
audio_player_summary_color?: string;
|
|
22
|
+
audio_player_rtl?: string;
|
|
23
|
+
audio_player_background_image_default_color?: string;
|
|
24
|
+
audio_player_background_image?: string;
|
|
25
|
+
audio_player_artwork_aspect_ratio?: string;
|
|
26
|
+
lg_tv_audio_player_title_font_family?: string;
|
|
27
|
+
lg_tv_audio_player_title_font_size?: number;
|
|
28
|
+
lg_tv_audio_player_summary_font_family?: string;
|
|
29
|
+
lg_tv_audio_player_summary_font_size?: number;
|
|
30
|
+
samsung_tv_audio_player_title_font_family?: string;
|
|
31
|
+
samsung_tv_audio_player_title_font_size?: number;
|
|
32
|
+
samsung_tv_audio_player_summary_font_family?: string;
|
|
33
|
+
samsung_tv_audio_player_summary_font_size?: number;
|
|
34
|
+
tv_os_audio_player_title_font_family?: string;
|
|
35
|
+
tv_os_audio_player_title_font_size?: number;
|
|
36
|
+
tv_os_audio_player_summary_font_family?: string;
|
|
37
|
+
tv_os_audio_player_summary_font_size?: number;
|
|
38
|
+
};
|
|
39
|
+
style?: ViewStyle;
|
|
40
|
+
};
|
|
@@ -16,9 +16,9 @@ function noop() {}
|
|
|
16
16
|
type Props = {
|
|
17
17
|
id: string;
|
|
18
18
|
groupId: string;
|
|
19
|
-
onPress?: (nativeEvent:
|
|
20
|
-
onFocus?: (nativeEvent:
|
|
21
|
-
onBlur?: (nativeEvent:
|
|
19
|
+
onPress?: (nativeEvent: any) => void;
|
|
20
|
+
onFocus?: (nativeEvent: any) => void;
|
|
21
|
+
onBlur?: (nativeEvent: any) => void;
|
|
22
22
|
children: (focused?: boolean) => React.ReactNode;
|
|
23
23
|
isParallaxDisabled: boolean;
|
|
24
24
|
preferredFocus?: boolean;
|
|
@@ -91,6 +91,7 @@ function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
|
|
|
91
91
|
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
92
92
|
omitPropsPropagation = [],
|
|
93
93
|
useScrollView = false,
|
|
94
|
+
onScrollToIndexFailed = noop,
|
|
94
95
|
} = props;
|
|
95
96
|
|
|
96
97
|
useCheckItemIdsForUnique({ componentId: props.id, items: data });
|
|
@@ -277,6 +278,7 @@ function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
|
|
|
277
278
|
"withStateMemory",
|
|
278
279
|
"useSequentialLoading",
|
|
279
280
|
"useScrollView",
|
|
281
|
+
"onScrollToIndexFailed",
|
|
280
282
|
...omitPropsPropagation,
|
|
281
283
|
],
|
|
282
284
|
R.__
|
|
@@ -305,6 +307,7 @@ function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
|
|
|
305
307
|
{...getFlatListProps(props)}
|
|
306
308
|
onEndReached={onEndReached}
|
|
307
309
|
initialNumToRender={initialNumToRender}
|
|
310
|
+
onScrollToIndexFailed={onScrollToIndexFailed}
|
|
308
311
|
renderItem={renderItem}
|
|
309
312
|
focused={focused}
|
|
310
313
|
data={data}
|
|
@@ -319,6 +322,7 @@ function FocusableListComponent<ItemT>(props: Props<ItemT>, ref) {
|
|
|
319
322
|
renderItem={renderItem}
|
|
320
323
|
onEndReached={onEndReached}
|
|
321
324
|
initialNumToRender={initialNumToRender}
|
|
325
|
+
onScrollToIndexFailed={onScrollToIndexFailed}
|
|
322
326
|
/>
|
|
323
327
|
)}
|
|
324
328
|
</ChildrenFocusDeactivatorView>
|
|
@@ -30,7 +30,6 @@ export const GeneralContentScreen = ({
|
|
|
30
30
|
isScreenWrappedInContainer,
|
|
31
31
|
componentsMapExtraProps = {},
|
|
32
32
|
focused,
|
|
33
|
-
extraOffset,
|
|
34
33
|
parentFocus,
|
|
35
34
|
containerHeight,
|
|
36
35
|
preferredFocus = false,
|
|
@@ -122,7 +121,6 @@ export const GeneralContentScreen = ({
|
|
|
122
121
|
isScreenWrappedInContainer={isScreenWrappedInContainer}
|
|
123
122
|
parentFocus={parentFocus}
|
|
124
123
|
focused={focused}
|
|
125
|
-
extraOffset={extraOffset}
|
|
126
124
|
containerHeight={containerHeight}
|
|
127
125
|
preferredFocus={preferredFocus}
|
|
128
126
|
{...componentsMapExtraProps}
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
import { BufferAnimation } from "../PlayerContainer/BufferAnimation";
|
|
14
14
|
import { PlayerContainer } from "../PlayerContainer";
|
|
15
15
|
import { useModalSize } from "../VideoModal/hooks";
|
|
16
|
+
import { ViewStyle } from "react-native";
|
|
16
17
|
|
|
17
18
|
type Props = {
|
|
18
19
|
item: ZappEntry;
|
|
@@ -140,14 +141,19 @@ export function HandlePlayable({
|
|
|
140
141
|
const modalSize = useModalSize();
|
|
141
142
|
|
|
142
143
|
const style = React.useMemo(
|
|
143
|
-
() =>
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
144
|
+
() =>
|
|
145
|
+
({
|
|
146
|
+
width: isModal
|
|
147
|
+
? modalSize.width
|
|
148
|
+
: mode === "PIP"
|
|
149
|
+
? "100%"
|
|
150
|
+
: screenWidth,
|
|
151
|
+
height: isModal
|
|
152
|
+
? modalSize.height
|
|
153
|
+
: mode === "PIP"
|
|
154
|
+
? "100%"
|
|
155
|
+
: screenHeight,
|
|
156
|
+
}) as ViewStyle,
|
|
151
157
|
[screenWidth, screenHeight, modalSize, isModal, mode]
|
|
152
158
|
);
|
|
153
159
|
|
|
@@ -73,7 +73,6 @@ export function elementMapper(
|
|
|
73
73
|
: {};
|
|
74
74
|
|
|
75
75
|
const componentProps = {
|
|
76
|
-
key,
|
|
77
76
|
style,
|
|
78
77
|
skipButtons: otherProps?.skipButtons,
|
|
79
78
|
emitAsyncElementRegistrate: otherProps?.emitAsyncElementRegistrate,
|
|
@@ -91,7 +90,7 @@ export function elementMapper(
|
|
|
91
90
|
const fn = mapElementWithKey(elementMapper(components, otherProps));
|
|
92
91
|
|
|
93
92
|
return (
|
|
94
|
-
<Component {...componentProps}>
|
|
93
|
+
<Component key={key} {...componentProps}>
|
|
95
94
|
{focusableTypes.has(type) && elements.length > 0
|
|
96
95
|
? elements.map(fn)
|
|
97
96
|
: null}
|
|
@@ -1,54 +1,28 @@
|
|
|
1
1
|
import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
|
|
2
|
-
import { StorageSingleValueProvider } from "@applicaster/zapp-react-native-
|
|
2
|
+
import { StorageSingleValueProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageSingleSelectProvider";
|
|
3
3
|
import { PushTopicManager } from "@applicaster/zapp-react-native-bridge/PushNotifications/PushTopicManager";
|
|
4
|
-
import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-
|
|
4
|
+
import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageMultiSelectProvider";
|
|
5
5
|
import React, { useEffect } from "react";
|
|
6
6
|
import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayer";
|
|
7
7
|
import { BehaviorSubject } from "rxjs";
|
|
8
8
|
import { masterCellLogger } from "../logger";
|
|
9
9
|
import get from "lodash/get";
|
|
10
|
-
import { ScreenMultiSelectProvider } from "@applicaster/zapp-react-native-utils/storage/ScreenStateMultiSelectProvider";
|
|
11
|
-
import { ScreenSingleValueProvider } from "@applicaster/zapp-react-native-utils/storage/ScreenSingleValueProvider";
|
|
12
|
-
import { useRoute } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
13
10
|
|
|
14
|
-
const parseContextKey = (
|
|
15
|
-
key
|
|
16
|
-
context: string = "ctx"
|
|
17
|
-
): string | null => {
|
|
18
|
-
if (!key?.startsWith(`@{${context}/`)) return null;
|
|
11
|
+
const parseContextKey = (key: string): string | null => {
|
|
12
|
+
if (!key?.startsWith("@{ctx/")) return null;
|
|
19
13
|
|
|
20
|
-
return key.substring(
|
|
14
|
+
return key.substring("@{ctx/".length, key.length - 1);
|
|
21
15
|
};
|
|
22
16
|
|
|
23
17
|
const getDataSourceProvider = (
|
|
24
|
-
behavior: Behavior
|
|
25
|
-
screenRoute: string
|
|
18
|
+
behavior: Behavior
|
|
26
19
|
): BehaviorSubject<string[] | string> | null => {
|
|
27
20
|
if (!behavior) return null;
|
|
28
21
|
|
|
29
22
|
const selection = String(behavior.current_selection);
|
|
30
|
-
const screenKey = parseContextKey(selection, "screen");
|
|
31
|
-
|
|
32
|
-
if (screenKey) {
|
|
33
|
-
if (behavior.select_mode === "multi") {
|
|
34
|
-
return ScreenMultiSelectProvider.getProvider(
|
|
35
|
-
screenKey,
|
|
36
|
-
screenRoute
|
|
37
|
-
).getObservable();
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (behavior.select_mode === "single") {
|
|
41
|
-
return ScreenSingleValueProvider.getProvider(
|
|
42
|
-
screenKey,
|
|
43
|
-
screenRoute
|
|
44
|
-
).getObservable();
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
23
|
const contextKey = parseContextKey(selection);
|
|
49
24
|
|
|
50
25
|
if (contextKey) {
|
|
51
|
-
// TODO: Add storage scope to behavior
|
|
52
26
|
if (behavior.select_mode === "multi") {
|
|
53
27
|
return StorageMultiSelectProvider.getProvider(contextKey).getObservable();
|
|
54
28
|
}
|
|
@@ -67,7 +41,6 @@ const getDataSourceProvider = (
|
|
|
67
41
|
|
|
68
42
|
export const useBehaviorUpdate = (behavior: Behavior) => {
|
|
69
43
|
const [lastUpdate, setLastUpdate] = React.useState<number | null>(null);
|
|
70
|
-
const screenRoute = useRoute()?.pathname || "";
|
|
71
44
|
const player = usePlayer();
|
|
72
45
|
|
|
73
46
|
const triggerUpdate = () => setLastUpdate(Date.now());
|
|
@@ -75,7 +48,7 @@ export const useBehaviorUpdate = (behavior: Behavior) => {
|
|
|
75
48
|
useEffect(() => {
|
|
76
49
|
if (!behavior) return;
|
|
77
50
|
|
|
78
|
-
const dataSource = getDataSourceProvider(behavior
|
|
51
|
+
const dataSource = getDataSourceProvider(behavior);
|
|
79
52
|
|
|
80
53
|
if (dataSource) {
|
|
81
54
|
const subscription = dataSource.subscribe(triggerUpdate);
|
|
@@ -99,15 +72,10 @@ export const useBehaviorUpdate = (behavior: Behavior) => {
|
|
|
99
72
|
|
|
100
73
|
// We cant use async in this function (its inside render),
|
|
101
74
|
// so we rely on useBehaviorUpdate to update current value and trigger re-render
|
|
102
|
-
export const isCellSelected = (
|
|
103
|
-
item,
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}: {
|
|
107
|
-
item: ZappEntry;
|
|
108
|
-
screenRoute: string;
|
|
109
|
-
behavior?: Behavior;
|
|
110
|
-
}): boolean => {
|
|
75
|
+
export const isCellSelected = (
|
|
76
|
+
item: ZappEntry,
|
|
77
|
+
behavior?: Behavior
|
|
78
|
+
): boolean => {
|
|
111
79
|
if (!behavior) return false;
|
|
112
80
|
|
|
113
81
|
const id = behavior.selector ? get(item, behavior.selector) : item.id;
|
|
@@ -131,30 +99,7 @@ export const isCellSelected = ({
|
|
|
131
99
|
}
|
|
132
100
|
|
|
133
101
|
const selection = String(behavior.current_selection);
|
|
134
|
-
|
|
135
|
-
const screenKey = parseContextKey(selection, "screen");
|
|
136
|
-
|
|
137
|
-
if (screenKey) {
|
|
138
|
-
if (behavior.select_mode === "single") {
|
|
139
|
-
const selectedItem = ScreenSingleValueProvider.getProvider(
|
|
140
|
-
screenKey,
|
|
141
|
-
screenRoute
|
|
142
|
-
).getValue();
|
|
143
|
-
|
|
144
|
-
return selectedItem === String(id);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if (behavior.select_mode === "multi") {
|
|
148
|
-
const selectedItems = ScreenMultiSelectProvider.getProvider(
|
|
149
|
-
screenKey,
|
|
150
|
-
screenRoute
|
|
151
|
-
).getSelectedItems();
|
|
152
|
-
|
|
153
|
-
return selectedItems?.includes(String(id));
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const contextKey = parseContextKey(selection, "ctx");
|
|
102
|
+
const contextKey = parseContextKey(selection);
|
|
158
103
|
|
|
159
104
|
if (contextKey) {
|
|
160
105
|
if (behavior.select_mode === "single") {
|
|
@@ -8,7 +8,6 @@ import { masterCellLogger } from "../logger";
|
|
|
8
8
|
import { getCellState } from "../../Cell/utils";
|
|
9
9
|
import { getColorFromData } from "@applicaster/zapp-react-native-utils/cellUtils";
|
|
10
10
|
import { isCellSelected, useBehaviorUpdate } from "./behaviorProvider";
|
|
11
|
-
import { useRoute } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
12
11
|
|
|
13
12
|
const hasElementSpecificViewType = (viewType) => (element) => {
|
|
14
13
|
if (R.isNil(element)) {
|
|
@@ -191,16 +190,8 @@ export const getFocusedButtonId = (focusable) => {
|
|
|
191
190
|
});
|
|
192
191
|
};
|
|
193
192
|
|
|
194
|
-
export const isSelected = ({
|
|
195
|
-
item,
|
|
196
|
-
screenRoute,
|
|
197
|
-
behavior,
|
|
198
|
-
}: {
|
|
199
|
-
item: ZappEntry;
|
|
200
|
-
screenRoute: string;
|
|
201
|
-
behavior?: Behavior;
|
|
202
|
-
}) => {
|
|
203
|
-
return isCellSelected({ item, screenRoute, behavior });
|
|
193
|
+
export const isSelected = (item: ZappEntry, behavior?: Behavior) => {
|
|
194
|
+
return isCellSelected(item, behavior);
|
|
204
195
|
};
|
|
205
196
|
|
|
206
197
|
export const useCellState = ({
|
|
@@ -213,10 +204,9 @@ export const useCellState = ({
|
|
|
213
204
|
focused: boolean;
|
|
214
205
|
}): CellState => {
|
|
215
206
|
const lastUpdate = useBehaviorUpdate(behavior);
|
|
216
|
-
const router = useRoute();
|
|
217
207
|
|
|
218
208
|
const _isSelected = useMemo(
|
|
219
|
-
() => isSelected(
|
|
209
|
+
() => isSelected(item, behavior),
|
|
220
210
|
[behavior, item, lastUpdate]
|
|
221
211
|
);
|
|
222
212
|
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Text, Animated } from "react-native";
|
|
3
|
+
import { render } from "@testing-library/react-native";
|
|
3
4
|
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
import {
|
|
6
|
+
NotificationView,
|
|
7
|
+
onlinePhrase,
|
|
8
|
+
offlinePhrase,
|
|
9
|
+
} from "../NotificationView";
|
|
7
10
|
|
|
8
11
|
jest.mock("@applicaster/zapp-react-native-redux/hooks", () => ({
|
|
9
12
|
usePickFromState: () => ({
|
|
@@ -32,39 +35,31 @@ jest.mock("react-native-safe-area-context", () => ({
|
|
|
32
35
|
|
|
33
36
|
const dismiss = jest.fn();
|
|
34
37
|
|
|
35
|
-
const {
|
|
36
|
-
NotificationView,
|
|
37
|
-
onlinePhrase,
|
|
38
|
-
offlinePhrase,
|
|
39
|
-
} = require("../NotificationView");
|
|
40
|
-
|
|
41
38
|
describe("NotificationView", () => {
|
|
42
39
|
it("Show online message when Online", () => {
|
|
43
|
-
const component =
|
|
44
|
-
<NotificationView online dismiss={dismiss} />
|
|
45
|
-
);
|
|
40
|
+
const component = render(<NotificationView online dismiss={dismiss} />);
|
|
46
41
|
|
|
47
|
-
expect(component.
|
|
42
|
+
expect(component.UNSAFE_getByType(Text).props.children).toBe(onlinePhrase);
|
|
48
43
|
});
|
|
49
44
|
|
|
50
45
|
it("Show offline message when Online", () => {
|
|
51
|
-
const component =
|
|
46
|
+
const component = render(
|
|
52
47
|
<NotificationView online={false} dismiss={dismiss} />
|
|
53
48
|
);
|
|
54
49
|
|
|
55
|
-
expect(component.
|
|
50
|
+
expect(component.UNSAFE_getByType(Text).props.children).toBe(offlinePhrase);
|
|
56
51
|
});
|
|
57
52
|
|
|
58
53
|
it("When hidden is false to true notification is visible", () => {
|
|
59
|
-
const component =
|
|
54
|
+
const component = render(
|
|
60
55
|
<NotificationView online={false} hidden={false} dismiss={dismiss} />
|
|
61
56
|
);
|
|
62
57
|
|
|
63
|
-
component.
|
|
58
|
+
component.rerender(
|
|
64
59
|
<NotificationView online={false} hidden={true} dismiss={dismiss} />
|
|
65
60
|
);
|
|
66
61
|
|
|
67
|
-
const animatedView = component.
|
|
62
|
+
const animatedView = component.UNSAFE_getByType(Animated.View);
|
|
68
63
|
const animatedViewStyles = animatedView.props.style;
|
|
69
64
|
|
|
70
65
|
expect(animatedViewStyles.opacity).toBe(1);
|
|
@@ -21,6 +21,15 @@ exports[`OfflineHandler renders 1`] = `
|
|
|
21
21
|
}
|
|
22
22
|
>
|
|
23
23
|
<View
|
|
24
|
+
accessibilityState={
|
|
25
|
+
{
|
|
26
|
+
"busy": undefined,
|
|
27
|
+
"checked": undefined,
|
|
28
|
+
"disabled": undefined,
|
|
29
|
+
"expanded": undefined,
|
|
30
|
+
"selected": undefined,
|
|
31
|
+
}
|
|
32
|
+
}
|
|
24
33
|
accessible={true}
|
|
25
34
|
collapsable={false}
|
|
26
35
|
focusable={true}
|