@applicaster/zapp-react-native-ui-components 14.0.0-alpha.1430213104 → 14.0.0-alpha.1661204539

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.
@@ -1,16 +1,5 @@
1
1
  import React from "react";
2
- import { View, Image, StyleSheet } from "react-native";
3
- import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
4
-
5
- const styles = StyleSheet.create({
6
- container: {
7
- marginHorizontal: 24,
8
- },
9
- image: {
10
- width: 400,
11
- height: 400,
12
- },
13
- });
2
+ import { View, Image } from "react-native";
14
3
 
15
4
  type Props = {
16
5
  srcImage: string;
@@ -20,19 +9,25 @@ type Props = {
20
9
  backgroundColor: string;
21
10
  backgroundImage: string;
22
11
  isRTL: boolean;
23
- artworkBorderRadius: Option<number>;
24
12
  };
25
13
  };
26
14
 
27
- export function Artwork({ srcImage, config }: Props) {
28
- const borderRadius = toNumberWithDefaultZero(config.artworkBorderRadius);
15
+ const containerStyles = {
16
+ marginHorizontal: 24,
17
+ };
18
+
19
+ const imageStyles = {
20
+ width: 400,
21
+ height: 400,
22
+ };
29
23
 
24
+ export function Artwork({ srcImage }: Props) {
30
25
  return (
31
- <View style={styles.container}>
26
+ <View style={containerStyles}>
32
27
  <Image
33
28
  fadeDuration={0}
34
29
  source={{ uri: srcImage }}
35
- style={[styles.image, { borderRadius }]}
30
+ style={imageStyles}
36
31
  resizeMode="cover"
37
32
  />
38
33
  </View>
@@ -72,7 +72,6 @@ export function AudioPlayer(props: Props) {
72
72
  const artworkAspectRatio = getProp("audio_player_artwork_aspect_ratio");
73
73
  const channelIcon = getProp("audio_player_channel_icon");
74
74
  const rtlFlag = getProp("audio_player_rtl");
75
- const artworkBorderRadius = getProp("audio_player_artwork_border_radius");
76
75
 
77
76
  const audioPlayerBackgroundImageDefaultColor = getProp(
78
77
  "audio_player_background_image_default_color"
@@ -155,7 +154,6 @@ export function AudioPlayer(props: Props) {
155
154
  artworkAspectRatio,
156
155
  channelIcon,
157
156
  audioPlayerBackgroundImageDefaultColor,
158
- artworkBorderRadius,
159
157
  };
160
158
  }, [getProp]);
161
159
 
@@ -14,7 +14,6 @@ type Props = {
14
14
  backgroundColor: string;
15
15
  backgroundImage: string;
16
16
  isRTL: boolean;
17
- artworkBorderRadius: Option<number>;
18
17
  };
19
18
  children: React.ReactNode;
20
19
  style: ViewStyle;
@@ -98,8 +97,8 @@ export function AudioPlayerLayout({ artwork, config, children, style }: Props) {
98
97
 
99
98
  const backgroundImgStyles = platformSelect({
100
99
  tvos: {
101
- width: "100%",
102
- height: "100%",
100
+ width: 1920,
101
+ height: 1080,
103
102
  alignItems: "center",
104
103
  justifyContent: "center",
105
104
  },
@@ -17,15 +17,10 @@ exports[`<Artwork /> renders correctly 1`] = `
17
17
  }
18
18
  }
19
19
  style={
20
- [
21
- {
22
- "height": 400,
23
- "width": 400,
24
- },
25
- {
26
- "borderRadius": 0,
27
- },
28
- ]
20
+ {
21
+ "height": 400,
22
+ "width": 400,
23
+ }
29
24
  }
30
25
  />
31
26
  </View>
@@ -1,28 +1,54 @@
1
1
  import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
2
- import { StorageSingleValueProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageSingleSelectProvider";
2
+ import { StorageSingleValueProvider } from "@applicaster/zapp-react-native-utils/storage/StorageSingleSelectProvider";
3
3
  import { PushTopicManager } from "@applicaster/zapp-react-native-bridge/PushNotifications/PushTopicManager";
4
- import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageMultiSelectProvider";
4
+ import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-utils/storage/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";
10
13
 
11
- const parseContextKey = (key: string): string | null => {
12
- if (!key?.startsWith("@{ctx/")) return null;
14
+ const parseContextKey = (
15
+ key: string,
16
+ context: string = "ctx"
17
+ ): string | null => {
18
+ if (!key?.startsWith(`@{${context}/`)) return null;
13
19
 
14
- return key.substring("@{ctx/".length, key.length - 1);
20
+ return key.substring(`@{${context}/`.length, key.length - 1);
15
21
  };
16
22
 
17
23
  const getDataSourceProvider = (
18
- behavior: Behavior
24
+ behavior: Behavior,
25
+ screenRoute: string
19
26
  ): BehaviorSubject<string[] | string> | null => {
20
27
  if (!behavior) return null;
21
28
 
22
29
  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
+
23
48
  const contextKey = parseContextKey(selection);
24
49
 
25
50
  if (contextKey) {
51
+ // TODO: Add storage scope to behavior
26
52
  if (behavior.select_mode === "multi") {
27
53
  return StorageMultiSelectProvider.getProvider(contextKey).getObservable();
28
54
  }
@@ -41,6 +67,7 @@ const getDataSourceProvider = (
41
67
 
42
68
  export const useBehaviorUpdate = (behavior: Behavior) => {
43
69
  const [lastUpdate, setLastUpdate] = React.useState<number | null>(null);
70
+ const screenRoute = useRoute()?.pathname || "";
44
71
  const player = usePlayer();
45
72
 
46
73
  const triggerUpdate = () => setLastUpdate(Date.now());
@@ -48,7 +75,7 @@ export const useBehaviorUpdate = (behavior: Behavior) => {
48
75
  useEffect(() => {
49
76
  if (!behavior) return;
50
77
 
51
- const dataSource = getDataSourceProvider(behavior);
78
+ const dataSource = getDataSourceProvider(behavior, screenRoute);
52
79
 
53
80
  if (dataSource) {
54
81
  const subscription = dataSource.subscribe(triggerUpdate);
@@ -72,10 +99,15 @@ export const useBehaviorUpdate = (behavior: Behavior) => {
72
99
 
73
100
  // We cant use async in this function (its inside render),
74
101
  // so we rely on useBehaviorUpdate to update current value and trigger re-render
75
- export const isCellSelected = (
76
- item: ZappEntry,
77
- behavior?: Behavior
78
- ): boolean => {
102
+ export const isCellSelected = ({
103
+ item,
104
+ screenRoute,
105
+ behavior,
106
+ }: {
107
+ item: ZappEntry;
108
+ screenRoute: string;
109
+ behavior?: Behavior;
110
+ }): boolean => {
79
111
  if (!behavior) return false;
80
112
 
81
113
  const id = behavior.selector ? get(item, behavior.selector) : item.id;
@@ -99,7 +131,30 @@ export const isCellSelected = (
99
131
  }
100
132
 
101
133
  const selection = String(behavior.current_selection);
102
- const contextKey = parseContextKey(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");
103
158
 
104
159
  if (contextKey) {
105
160
  if (behavior.select_mode === "single") {
@@ -8,6 +8,7 @@ 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";
11
12
 
12
13
  const hasElementSpecificViewType = (viewType) => (element) => {
13
14
  if (R.isNil(element)) {
@@ -190,8 +191,16 @@ export const getFocusedButtonId = (focusable) => {
190
191
  });
191
192
  };
192
193
 
193
- export const isSelected = (item: ZappEntry, behavior?: Behavior) => {
194
- return isCellSelected(item, behavior);
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 });
195
204
  };
196
205
 
197
206
  export const useCellState = ({
@@ -204,9 +213,10 @@ export const useCellState = ({
204
213
  focused: boolean;
205
214
  }): CellState => {
206
215
  const lastUpdate = useBehaviorUpdate(behavior);
216
+ const router = useRoute();
207
217
 
208
218
  const _isSelected = useMemo(
209
- () => isSelected(item, behavior),
219
+ () => isSelected({ item, screenRoute: router?.pathname, behavior }),
210
220
  [behavior, item, lastUpdate]
211
221
  );
212
222
 
@@ -6,15 +6,12 @@ import * as R from "ramda";
6
6
  import uuid from "uuid/v4";
7
7
  import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils/playerManager";
8
8
  import {
9
+ isApplePlatform,
9
10
  isTV,
10
11
  platformSelect,
11
12
  isAndroidTVPlatform,
12
- isTvOSPlatform,
13
13
  } from "@applicaster/zapp-react-native-utils/reactUtils";
14
- import {
15
- isAudioItem,
16
- isInlineTV as isInlineTVUtil,
17
- } from "@applicaster/zapp-react-native-utils/playerUtils";
14
+ import { isAudioItem } from "@applicaster/zapp-react-native-utils/playerUtils";
18
15
 
19
16
  import { TVEventHandlerComponent } from "@applicaster/zapp-react-native-tvos-ui-components/Components/TVEventHandlerComponent";
20
17
  import { usePrevious } from "@applicaster/zapp-react-native-utils/reactHooks/utils";
@@ -25,7 +22,7 @@ import {
25
22
  } from "@applicaster/zapp-react-native-utils/reactHooks";
26
23
 
27
24
  import { PlayerStateContext } from "../../Contexts/PlayerStateContext";
28
-
25
+ import { isAppleTV } from "../../Helpers/Platform";
29
26
  import {
30
27
  QUICK_BRICK_EVENTS,
31
28
  QuickBrickEvent,
@@ -100,11 +97,6 @@ const focusableBottomContainerId = "player-container-bottom";
100
97
 
101
98
  const isAndroidTV = isAndroidTVPlatform();
102
99
 
103
- const isTvOS = isTvOSPlatform();
104
-
105
- // height for container with additional content below player
106
- const INLINE_CONTAINER_CONTENT_HEIGHT = 400;
107
-
108
100
  const withBorderHack = () => {
109
101
  if (isAndroidTV) {
110
102
  /* @HACK: see GH#7269 */
@@ -134,7 +126,7 @@ const webStyles = {
134
126
  flex: "initial",
135
127
  },
136
128
  inlineRiver: {
137
- height: INLINE_CONTAINER_CONTENT_HEIGHT,
129
+ height: 400,
138
130
  },
139
131
  };
140
132
 
@@ -152,7 +144,7 @@ const nativeStyles = {
152
144
  flex: 1,
153
145
  },
154
146
  inlineRiver: {
155
- height: INLINE_CONTAINER_CONTENT_HEIGHT,
147
+ height: 400,
156
148
  },
157
149
  };
158
150
 
@@ -172,11 +164,12 @@ const renderApplePlayer = ({
172
164
  videoStyle,
173
165
  playNextData,
174
166
  }) => {
175
- if (!isTvOS || !player) {
167
+ const { title, summary } = item || {};
168
+
169
+ if (!isAppleTV() || !player) {
176
170
  return null;
177
171
  }
178
172
 
179
- // render audio_player for tvos
180
173
  if (isAudioContent) {
181
174
  return (
182
175
  <AudioPlayer
@@ -190,8 +183,6 @@ const renderApplePlayer = ({
190
183
  return null;
191
184
  }
192
185
 
193
- const { title, summary } = item || {};
194
-
195
186
  return (
196
187
  <ProgramInfo
197
188
  title={title}
@@ -202,6 +193,21 @@ const renderApplePlayer = ({
202
193
  );
203
194
  };
204
195
 
196
+ const renderRestPlayers = ({ item, showAudioPlayer, pluginConfiguration }) => {
197
+ if (isApplePlatform()) {
198
+ return null;
199
+ }
200
+
201
+ return (
202
+ showAudioPlayer && (
203
+ <AudioPlayer
204
+ audio_item={item}
205
+ plugin_configuration={pluginConfiguration}
206
+ />
207
+ )
208
+ );
209
+ };
210
+
205
211
  const PlayerContainerComponent = (props: Props) => {
206
212
  const {
207
213
  Player,
@@ -331,7 +337,7 @@ const PlayerContainerComponent = (props: Props) => {
331
337
 
332
338
  setState({ error: errorObj });
333
339
 
334
- if (!isTvOS) {
340
+ if (!isAppleTV()) {
335
341
  setTimeout(() => {
336
342
  close();
337
343
  }, 800);
@@ -562,7 +568,10 @@ const PlayerContainerComponent = (props: Props) => {
562
568
 
563
569
  const uri = item?.content ? item.content?.src : null;
564
570
 
565
- const isInlineTV = isInlineTVUtil(screenData);
571
+ const isInlineTV =
572
+ screenData?.ui_components &&
573
+ screenData?.ui_components?.length > 0 &&
574
+ isTV();
566
575
 
567
576
  const inline =
568
577
  [VideoModalMode.MAXIMIZED, VideoModalMode.MINIMIZED].includes(mode) ||
@@ -617,6 +626,12 @@ const PlayerContainerComponent = (props: Props) => {
617
626
  playNextData,
618
627
  };
619
628
 
629
+ const restPlayerProps = {
630
+ item,
631
+ showAudioPlayer: isAudioContent,
632
+ pluginConfiguration,
633
+ };
634
+
620
635
  return (
621
636
  <PlayerStateContext.Provider value={value}>
622
637
  <PlayerContainerContextProvider
@@ -692,6 +707,8 @@ const PlayerContainerComponent = (props: Props) => {
692
707
  </Player>
693
708
  </PlayerFocusableWrapperView>
694
709
 
710
+ {renderRestPlayers(restPlayerProps)}
711
+
695
712
  {state.error ? <ErrorDisplay error={state.error} /> : null}
696
713
  </View>
697
714
  {/* Components container */}
@@ -715,7 +732,7 @@ const PlayerContainerComponent = (props: Props) => {
715
732
  screenId={screenData.id}
716
733
  key={item.id}
717
734
  groupId={FocusableGroupMainContainerId}
718
- cellTapAction={onCellTap}
735
+ cellTapAction={(event) => onCellTap(event)}
719
736
  extraAnchorPointYOffset={-600}
720
737
  isScreenWrappedInContainer={true}
721
738
  containerHeight={styles.inlineRiver.height}
@@ -13,6 +13,7 @@ import {
13
13
  loadDatasources,
14
14
  usePipesContexts,
15
15
  } from "./utils";
16
+ import { useScreenResolvers } from "@applicaster/zapp-react-native-utils/actionsExecutor/screenResolver";
16
17
 
17
18
  type RiverProps = {
18
19
  dispatch: DispatchProp;
@@ -25,7 +26,7 @@ export function WithRiverFeedLoader(Component: ZappComponent) {
25
26
  return function WrappedWithRiverFeedLoader(props: RiverProps) {
26
27
  const { river } = props;
27
28
  const { screenData, pathname } = useRoute();
28
-
29
+ const resolvers = useScreenResolvers(pathname);
29
30
  const pipesContexts = usePipesContexts(river.id, pathname);
30
31
 
31
32
  const componentsToLoad = ignoreComponentsWithClearCacheFlag(
@@ -49,7 +50,12 @@ export function WithRiverFeedLoader(Component: ZappComponent) {
49
50
  item?.filter((item2) => item2 !== undefined)
50
51
  );
51
52
 
52
- loadDatasources(nonEmptyDataSources, river?.id, props.dispatch);
53
+ loadDatasources(
54
+ nonEmptyDataSources,
55
+ river?.id,
56
+ props.dispatch,
57
+ resolvers
58
+ );
53
59
  }, []);
54
60
 
55
61
  return <Component {...props} />;
@@ -12,11 +12,16 @@ export { getDatasourceUrl } from "./getDatasourceUrl";
12
12
 
13
13
  export const DATASOURCE_CHUNKS = 10;
14
14
 
15
- export async function loadDatasources(urls: string[][], riverId, dispatch) {
15
+ export async function loadDatasources(
16
+ urls: string[][],
17
+ riverId,
18
+ dispatch,
19
+ resolvers
20
+ ) {
16
21
  return reducePromises<string, void>(
17
22
  mapPromises<string, void>((url) => {
18
23
  if (url) {
19
- return dispatch(loadPipesData(url, { riverId }));
24
+ return dispatch(loadPipesData(url, { riverId, resolvers }));
20
25
  }
21
26
  }),
22
27
  undefined,
@@ -19,7 +19,10 @@ import { ZappPipesSearchContext } from "@applicaster/zapp-react-native-ui-compon
19
19
  import { useScreenContext } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useScreenContext";
20
20
 
21
21
  import { isVerticalListOrGrid } from "./utils";
22
- import { subscribeForUrlContextKeyChanges } from "@applicaster/zapp-pipes-v2-client";
22
+ import {
23
+ subscribeForUrlContextKeyChanges,
24
+ subscribeForUrlScreenKeyChanges,
25
+ } from "@applicaster/zapp-pipes-v2-client";
23
26
 
24
27
  type Props = {
25
28
  component: ZappUIComponent;
@@ -204,7 +207,7 @@ export function zappPipesDataConnector(
204
207
  Component: React.FC<any> | React.ComponentClass<any>
205
208
  ) {
206
209
  return function WrappedWithZappPipesData(props: Props) {
207
- const { screenData } = useRoute();
210
+ const { screenData, pathname } = useRoute();
208
211
  const { plugins } = usePickFromState(["plugins"]);
209
212
 
210
213
  const screenContextData = useScreenContext();
@@ -286,6 +289,17 @@ export function zappPipesDataConnector(
286
289
  componentIndex
287
290
  );
288
291
 
292
+ useEffect(() => {
293
+ if (!(dataSourceUrl?.includes("pipesv2://") && reloadData)) {
294
+ return subscribeForUrlScreenKeyChanges(
295
+ dataSourceUrl,
296
+ pathname,
297
+ {},
298
+ reloadData
299
+ );
300
+ }
301
+ }, [dataSourceUrl, reloadData]);
302
+
289
303
  useEffect(() => {
290
304
  if (dataSourceUrl?.includes("pipesv2://") && reloadData) {
291
305
  const addListener = getListenerFromPlugin(dataSourceUrl, plugins);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-native-ui-components",
3
- "version": "14.0.0-alpha.1430213104",
3
+ "version": "14.0.0-alpha.1661204539",
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",
@@ -31,10 +31,10 @@
31
31
  "redux-mock-store": "^1.5.3"
32
32
  },
33
33
  "dependencies": {
34
- "@applicaster/applicaster-types": "14.0.0-alpha.1430213104",
35
- "@applicaster/zapp-react-native-bridge": "14.0.0-alpha.1430213104",
36
- "@applicaster/zapp-react-native-redux": "14.0.0-alpha.1430213104",
37
- "@applicaster/zapp-react-native-utils": "14.0.0-alpha.1430213104",
34
+ "@applicaster/applicaster-types": "14.0.0-alpha.1661204539",
35
+ "@applicaster/zapp-react-native-bridge": "14.0.0-alpha.1661204539",
36
+ "@applicaster/zapp-react-native-redux": "14.0.0-alpha.1661204539",
37
+ "@applicaster/zapp-react-native-utils": "14.0.0-alpha.1661204539",
38
38
  "promise": "^8.3.0",
39
39
  "url": "^0.11.0",
40
40
  "uuid": "^3.3.2"