@applicaster/zapp-react-native-ui-components 15.0.0-alpha.5918085834 → 15.0.0-alpha.5949018320

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.
@@ -22,6 +22,7 @@ type Props = {
22
22
  onFocus?: FocusManager.FocusEventCB;
23
23
  onBlur?: FocusManager.FocusEventCB;
24
24
  selected?: boolean;
25
+ skipFocusManagerRegistration?: boolean;
25
26
  };
26
27
 
27
28
  export class BaseFocusable<
@@ -61,10 +62,14 @@ export class BaseFocusable<
61
62
  }
62
63
 
63
64
  componentDidMount() {
64
- const { id } = this.props;
65
+ const { id, skipFocusManagerRegistration } = this.props;
65
66
  const component = this;
66
67
  this.node = this.ref.current;
67
68
 
69
+ if (skipFocusManagerRegistration) {
70
+ return;
71
+ }
72
+
68
73
  focusManager.register({
69
74
  id,
70
75
  component: component,
@@ -118,7 +123,12 @@ export class BaseFocusable<
118
123
 
119
124
  componentWillUnmount() {
120
125
  this._isMounted = false;
121
- const { id } = this.props;
126
+ const { id, skipFocusManagerRegistration } = this.props;
127
+
128
+ if (skipFocusManagerRegistration) {
129
+ return;
130
+ }
131
+
122
132
  focusManager.unregister(id, { group: this.isGroup || false });
123
133
  }
124
134
 
@@ -10,6 +10,7 @@ type Props = {
10
10
  children: (focused: boolean) => React.ReactNode;
11
11
  onFocus: (arg1: any, index?: number) => void;
12
12
  onBlur: Callback;
13
+ skipFocusManagerRegistration?: boolean;
13
14
  };
14
15
 
15
16
  export const FocusableWrapper = ({
@@ -20,6 +21,7 @@ export const FocusableWrapper = ({
20
21
  applyWrapper,
21
22
  onFocus,
22
23
  onBlur,
24
+ skipFocusManagerRegistration,
23
25
  }: Props) => {
24
26
  if (applyWrapper) {
25
27
  return (
@@ -34,6 +36,7 @@ export const FocusableWrapper = ({
34
36
  // @ts-ignore
35
37
  offsetUpdater={noop}
36
38
  isFocusable
39
+ skipFocusManagerRegistration={skipFocusManagerRegistration}
37
40
  >
38
41
  {(focused) => children(focused)}
39
42
  </Focusable>
@@ -80,6 +80,7 @@ type Props = {
80
80
  componentsMapOffset: number;
81
81
  applyFocusableWrapper: boolean;
82
82
  hasFocusableInside: boolean;
83
+ skipFocusManagerRegistration?: boolean;
83
84
  };
84
85
 
85
86
  type State = {
@@ -266,6 +267,7 @@ class TvOSCell extends React.Component<Props, State> {
266
267
  behavior,
267
268
  applyFocusableWrapper,
268
269
  hasFocusableInside,
270
+ skipFocusManagerRegistration,
269
271
  } = this.props;
270
272
 
271
273
  const { id } = item;
@@ -291,6 +293,7 @@ class TvOSCell extends React.Component<Props, State> {
291
293
  onFocus={handleFocus}
292
294
  onBlur={onBlur || this.onBlur}
293
295
  applyWrapper={applyFocusableWrapper}
296
+ skipFocusManagerRegistration={skipFocusManagerRegistration}
294
297
  >
295
298
  {(focused) => (
296
299
  <CellWithFocusable
@@ -305,6 +308,7 @@ class TvOSCell extends React.Component<Props, State> {
305
308
  focused={focused || this.props.focused}
306
309
  behavior={behavior}
307
310
  isFocusable={isFocusable}
311
+ skipFocusManagerRegistration={skipFocusManagerRegistration}
308
312
  />
309
313
  )}
310
314
  </FocusableWrapper>
@@ -327,6 +331,7 @@ class TvOSCell extends React.Component<Props, State> {
327
331
  offsetUpdater={offsetUpdater}
328
332
  style={baseCellStyles}
329
333
  isFocusable={isFocusable}
334
+ skipFocusManagerRegistration={skipFocusManagerRegistration}
330
335
  >
331
336
  {(focused) => (
332
337
  <FocusableCell
@@ -10,8 +10,8 @@ import {
10
10
  forceFocusableFocus,
11
11
  } from "@applicaster/zapp-react-native-utils/appUtils/focusManager/index.ios";
12
12
  import { findNodeHandle, ViewStyle } from "react-native";
13
-
14
- function noop() {}
13
+ import { emitNativeRegistered } from "@applicaster/zapp-react-native-utils/appUtils/focusManagerAux/utils/utils.ios";
14
+ import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
15
15
 
16
16
  type Props = {
17
17
  id: string;
@@ -39,6 +39,7 @@ type Props = {
39
39
  hasReceivedFocus: () => void;
40
40
  offsetUpdater: (arg1: string, arg2: number) => number;
41
41
  style: ViewStyle;
42
+ skipFocusManagerRegistration?: boolean;
42
43
  };
43
44
 
44
45
  export class Focusable extends BaseFocusable<Props> {
@@ -53,6 +54,7 @@ export class Focusable extends BaseFocusable<Props> {
53
54
  this.nextFocusableReactTags = {};
54
55
  this.preferredFocus = this.preferredFocus.bind(this);
55
56
  this.measureView = this.measureView.bind(this);
57
+ this.onRegistered = this.onRegistered.bind(this);
56
58
  }
57
59
 
58
60
  /**
@@ -169,6 +171,13 @@ export class Focusable extends BaseFocusable<Props> {
169
171
  });
170
172
  }
171
173
 
174
+ onRegistered({ nativeEvent }) {
175
+ const groupId = nativeEvent?.groupId;
176
+ const id = nativeEvent?.itemId;
177
+
178
+ emitNativeRegistered({ id, groupId, isGroup: false });
179
+ }
180
+
172
181
  render() {
173
182
  const {
174
183
  children,
@@ -203,6 +212,7 @@ export class Focusable extends BaseFocusable<Props> {
203
212
  focusable={isFocusable}
204
213
  {...this.nextFocusableReactTags}
205
214
  {...otherProps}
215
+ onRegistered={this.onRegistered}
206
216
  >
207
217
  {typeof children === "function" ? children(focused) : children}
208
218
  </FocusableItemNative>
@@ -5,6 +5,7 @@ exports[`FocusableTvOS should render correctly 1`] = `
5
5
  groupId={null}
6
6
  itemId={null}
7
7
  onLayout={[Function]}
8
+ onRegistered={[Function]}
8
9
  onViewBlur={[Function]}
9
10
  onViewFocus={[Function]}
10
11
  onViewPress={[Function]}
@@ -2,6 +2,7 @@ import * as React from "react";
2
2
  import { FocusableGroupNative } from "@applicaster/zapp-react-native-ui-components/Components/NativeFocusables";
3
3
  import { BaseFocusable } from "@applicaster/zapp-react-native-ui-components/Components/BaseFocusable";
4
4
  import { createLogger } from "@applicaster/zapp-react-native-utils/logger";
5
+ import { emitNativeRegistered } from "@applicaster/zapp-react-native-utils/appUtils/focusManagerAux/utils/utils.ios";
5
6
 
6
7
  const { log_verbose } = createLogger({
7
8
  subsystem: "General",
@@ -34,6 +35,15 @@ type Props = {
34
35
  };
35
36
 
36
37
  export class FocusableGroup extends BaseFocusable<Props> {
38
+ public readonly isGroup: boolean = true;
39
+
40
+ onRegistered = ({ nativeEvent }) => {
41
+ const groupId = nativeEvent?.groupId;
42
+ const id = nativeEvent?.itemId;
43
+
44
+ emitNativeRegistered({ id, groupId, isGroup: true });
45
+ };
46
+
37
47
  render() {
38
48
  const {
39
49
  children,
@@ -66,6 +76,7 @@ export class FocusableGroup extends BaseFocusable<Props> {
66
76
  onGroupBlur={onGroupBlur}
67
77
  style={style}
68
78
  {...otherProps}
79
+ onRegistered={this.onRegistered}
69
80
  >
70
81
  {children}
71
82
  </FocusableGroupNative>
@@ -1,4 +1,4 @@
1
- import { all, equals, path, prop, isEmpty, pluck, values } from "ramda";
1
+ import { all, equals, isEmpty, path, pluck, prop, values } from "ramda";
2
2
 
3
3
  import { useEffect, useMemo } from "react";
4
4
 
@@ -24,6 +24,7 @@ import {
24
24
 
25
25
  import { produce } from "immer";
26
26
  import { useLoadPipesDataDispatch } from "@applicaster/zapp-react-native-utils/reactHooks";
27
+
27
28
  // types reference
28
29
 
29
30
  declare interface CurationEntry {
@@ -35,6 +36,7 @@ type Feeds = Record<string, ZappPipesData>;
35
36
 
36
37
  type LayoutPresets = PresetsMapping["presets_mappings"];
37
38
 
39
+ const TABS_SCREEN_TYPE = "tabs_screen";
38
40
  const SMART_COMPONENT_TYPE = "quick-brick-smart-component";
39
41
  const SOURCE_PATH = ["data", "source"];
40
42
  const MAPPING_PATH = ["data", "mapping"];
@@ -53,7 +55,10 @@ export const getTransformedPreset = (
53
55
  const presetComponent = layoutPresets?.[preset?.preset_name];
54
56
 
55
57
  if (!presetComponent) {
56
- logger.log_error("Preset missing or wrong data format", { entry: preset });
58
+ logger.log_error(
59
+ `Preset "${preset?.preset_name}" missing or wrong data format`,
60
+ { entry: preset }
61
+ );
57
62
 
58
63
  return;
59
64
  }
@@ -131,10 +136,16 @@ export const useCurationAPI = (
131
136
  );
132
137
 
133
138
  const { pathname } = useRoute();
134
- const [entryContext] = ZappPipesEntryContext.useZappPipesContext(pathname);
135
139
  const [searchContext] = ZappPipesSearchContext.useZappPipesContext();
136
140
  const [screenContext] = ZappPipesScreenContext.useZappPipesContext();
137
141
 
142
+ const isNestedScreen = screenContext?.type === TABS_SCREEN_TYPE;
143
+
144
+ const [entryContext] = ZappPipesEntryContext.useZappPipesContext(
145
+ pathname,
146
+ isNestedScreen
147
+ );
148
+
138
149
  const urlsMap = useMemo<{ [key: string]: string }>(() => {
139
150
  const map = {};
140
151
 
@@ -61,6 +61,7 @@ import {
61
61
  PlayerNativeSendCommand,
62
62
  } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/playerNativeCommand";
63
63
  import { useAppData } from "@applicaster/zapp-react-native-redux";
64
+ import { useRestrictMobilePlayback } from "./useRestrictMobilePlayback";
64
65
 
65
66
  type Props = {
66
67
  Player: React.ComponentType<any>;
@@ -264,7 +265,21 @@ const PlayerContainerComponent = (props: Props) => {
264
265
 
265
266
  showNavBar(true);
266
267
  navigator.goBack();
267
- }, [isModal, navigator.goBack, state.playerId, showNavBar]);
268
+ }, [isModal, state.playerId, showNavBar, navigator]);
269
+
270
+ const pluginConfiguration = React.useMemo(() => {
271
+ return (
272
+ playerManager.getPluginConfiguration() ||
273
+ R.prop("__plugin_configuration", Player)
274
+ );
275
+ }, [playerManager.isRegistered()]);
276
+
277
+ useRestrictMobilePlayback({
278
+ player,
279
+ entry: item,
280
+ pluginConfiguration,
281
+ close,
282
+ });
268
283
 
269
284
  const playEntry = (entry) => navigator.replaceTop(entry, { mode });
270
285
 
@@ -456,13 +471,6 @@ const PlayerContainerComponent = (props: Props) => {
456
471
  }
457
472
  }, []);
458
473
 
459
- const pluginConfiguration = React.useMemo(() => {
460
- return (
461
- playerManager.getPluginConfiguration() ||
462
- R.prop("__plugin_configuration", Player)
463
- );
464
- }, [playerManager.isRegistered()]);
465
-
466
474
  const disableMiniPlayer = React.useMemo(() => {
467
475
  return pluginConfiguration?.disable_mini_player_when_inline;
468
476
  }, [pluginConfiguration]);
@@ -0,0 +1,112 @@
1
+ import { Player } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/player";
2
+ import NetInfo from "@react-native-community/netinfo";
3
+
4
+ import { useEffect, useMemo, useRef } from "react";
5
+ import { showAlertDialog } from "@applicaster/zapp-react-native-utils/alertUtils";
6
+ import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
7
+ import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
8
+ import { log_info } from "./logger";
9
+
10
+ export const useRestrictMobilePlayback = ({
11
+ player,
12
+ entry,
13
+ pluginConfiguration,
14
+ close,
15
+ }: {
16
+ player?: Player;
17
+ entry?: ZappEntry;
18
+ pluginConfiguration?: Record<string, string>;
19
+ close: () => void;
20
+ }) => {
21
+ const dialogVisibleRef = useRef(false);
22
+
23
+ const theme = useTheme();
24
+
25
+ useEffect(() => {
26
+ return () => {
27
+ if (isTV()) {
28
+ return;
29
+ }
30
+
31
+ dialogVisibleRef.current = false;
32
+ };
33
+ }, []);
34
+
35
+ const isConnectionRestricted = useMemo(() => {
36
+ if (isTV()) {
37
+ return false;
38
+ }
39
+
40
+ return player && entry?.extensions?.connection_restricted;
41
+ }, [player, entry]);
42
+
43
+ useEffect(() => {
44
+ if (!isConnectionRestricted) {
45
+ return;
46
+ }
47
+
48
+ return player.addListener({
49
+ id: "restrictMobilePlaybackListener",
50
+ listener: {
51
+ onVideoProgress: () => {
52
+ if (dialogVisibleRef.current) {
53
+ player.pause();
54
+ }
55
+ },
56
+ onPlayerResume: () => {
57
+ if (dialogVisibleRef.current) {
58
+ player.pause();
59
+ }
60
+ },
61
+ },
62
+ });
63
+ }, [isConnectionRestricted, player]);
64
+
65
+ useEffect(() => {
66
+ if (!isConnectionRestricted) {
67
+ return;
68
+ }
69
+
70
+ const stopPlayer = () => {
71
+ log_info(
72
+ "Stopping player due to mobile restriction, connection_restricted: true"
73
+ );
74
+
75
+ player.pause();
76
+
77
+ dialogVisibleRef.current = true;
78
+
79
+ showAlertDialog({
80
+ title:
81
+ pluginConfiguration?.mobile_connection_restricted_alert_title ||
82
+ "N/A",
83
+ message:
84
+ pluginConfiguration?.mobile_connection_restricted_alert_message ||
85
+ "N/A",
86
+ okButtonText: theme.ok_button || "OK",
87
+ completion: () => {
88
+ dialogVisibleRef.current = false;
89
+
90
+ close();
91
+ },
92
+ });
93
+ };
94
+
95
+ return NetInfo.addEventListener((state) => {
96
+ if (state.type === "cellular") {
97
+ if (dialogVisibleRef.current) {
98
+ return;
99
+ }
100
+
101
+ stopPlayer();
102
+ }
103
+ });
104
+ }, [
105
+ close,
106
+ entry.extensions.connection_restricted,
107
+ pluginConfiguration,
108
+ player,
109
+ theme.ok_button,
110
+ isConnectionRestricted,
111
+ ]);
112
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applicaster/zapp-react-native-ui-components",
3
- "version": "15.0.0-alpha.5918085834",
3
+ "version": "15.0.0-alpha.5949018320",
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",
@@ -28,10 +28,10 @@
28
28
  },
29
29
  "homepage": "https://github.com/applicaster/quickbrick#readme",
30
30
  "dependencies": {
31
- "@applicaster/applicaster-types": "15.0.0-alpha.5918085834",
32
- "@applicaster/zapp-react-native-bridge": "15.0.0-alpha.5918085834",
33
- "@applicaster/zapp-react-native-redux": "15.0.0-alpha.5918085834",
34
- "@applicaster/zapp-react-native-utils": "15.0.0-alpha.5918085834",
31
+ "@applicaster/applicaster-types": "15.0.0-alpha.5949018320",
32
+ "@applicaster/zapp-react-native-bridge": "15.0.0-alpha.5949018320",
33
+ "@applicaster/zapp-react-native-redux": "15.0.0-alpha.5949018320",
34
+ "@applicaster/zapp-react-native-utils": "15.0.0-alpha.5949018320",
35
35
  "fast-json-stable-stringify": "^2.1.0",
36
36
  "promise": "^8.3.0",
37
37
  "url": "^0.11.0",