@applicaster/zapp-react-native-utils 15.0.0-rc.98 → 15.1.0-alpha.1852552014

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.
Files changed (172) hide show
  1. package/actionsExecutor/ActionExecutorContext.tsx +51 -5
  2. package/actionsExecutor/feedDecorator.ts +6 -6
  3. package/adsUtils/index.ts +2 -2
  4. package/analyticsUtils/AnalyticsEvents/sendMenuClickEvent.ts +2 -2
  5. package/analyticsUtils/PlayerAnalyticsManager.ts +11 -1
  6. package/analyticsUtils/README.md +1 -1
  7. package/analyticsUtils/__tests__/analyticsMapper.test.ts +35 -0
  8. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testACP_events.json +1 -1
  9. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testBlockUnlistedParams_rules.json +1 -1
  10. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testEmptyRenameKeepsName_events.json +4 -0
  11. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testEmptyRenameKeepsName_rules.json +6 -0
  12. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testEventRegex_events.json +3 -9
  13. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testIgnoreOrdering_events.json +18 -0
  14. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testIgnoreOrdering_rules.json +16 -0
  15. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexEventNoFallback_events.json +4 -0
  16. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexEventNoFallback_rules.json +6 -0
  17. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexMultiGroupRename_events.json +4 -0
  18. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexMultiGroupRename_rules.json +6 -0
  19. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexNonNamedFullMatch_events.json +4 -0
  20. package/analyticsUtils/__tests__/fixtures/analytics_mapper_testRegexNonNamedFullMatch_rules.json +6 -0
  21. package/analyticsUtils/__tests__/fixtures/index.js +20 -0
  22. package/analyticsUtils/analyticsMapper.ts +4 -1
  23. package/analyticsUtils/playerAnalyticsTracker.ts +26 -3
  24. package/appUtils/HooksManager/__tests__/__snapshots__/hooksManager.test.js.snap +188 -0
  25. package/appUtils/HooksManager/__tests__/hooksManager.test.js +2 -16
  26. package/appUtils/HooksManager/index.ts +47 -17
  27. package/appUtils/RiverFocusManager/{index.ts → index.js} +18 -25
  28. package/appUtils/accessibilityManager/const.ts +0 -4
  29. package/appUtils/accessibilityManager/utils.ts +1 -0
  30. package/appUtils/contextKeysManager/__tests__/getKeys/failure.test.ts +2 -7
  31. package/appUtils/contextKeysManager/__tests__/getKeys/success.test.ts +0 -48
  32. package/appUtils/contextKeysManager/contextResolver.ts +22 -51
  33. package/appUtils/contextKeysManager/index.ts +10 -65
  34. package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +0 -3
  35. package/appUtils/focusManager/index.ios.ts +4 -43
  36. package/appUtils/focusManagerAux/utils/index.ts +3 -5
  37. package/appUtils/focusManagerAux/utils/utils.ios.ts +3 -199
  38. package/appUtils/keyCodes/keys/keys.web.ts +4 -1
  39. package/appUtils/localizationsHelper.ts +4 -0
  40. package/appUtils/orientationHelper.ts +4 -2
  41. package/appUtils/platform/platformUtils.ts +1 -1
  42. package/appUtils/playerManager/__tests__/playerFactory.test.ts +150 -0
  43. package/appUtils/playerManager/index.ts +9 -0
  44. package/appUtils/playerManager/player.ts +1 -5
  45. package/appUtils/playerManager/playerFactory.ts +17 -34
  46. package/appUtils/playerManager/playerNative.ts +22 -30
  47. package/appUtils/playerManager/usePlayer.tsx +5 -3
  48. package/appUtils/playerManager/usePlayerState.tsx +2 -14
  49. package/cellUtils/__tests__/cellUtils.test.ts +39 -0
  50. package/cellUtils/index.ts +14 -6
  51. package/cloudEventsUtils/index.ts +1 -65
  52. package/colorUtils/__tests__/isTransparentColor.test.ts +76 -0
  53. package/colorUtils/__tests__/isValidColor.test.ts +70 -0
  54. package/colorUtils/index.ts +50 -0
  55. package/configurationUtils/__tests__/manifestKeyParser.test.ts +26 -26
  56. package/dateUtils/__tests__/dayjs.test.ts +0 -3
  57. package/dateUtils/index.ts +2 -0
  58. package/focusManager/aux/index.ts +1 -1
  59. package/headersUtils/__tests__/headersUtils.test.js +1 -11
  60. package/headersUtils/index.ts +1 -2
  61. package/manifestUtils/defaultManifestConfigurations/player.js +7 -75
  62. package/manifestUtils/keys.js +1 -0
  63. package/manifestUtils/platformIsTV.js +14 -0
  64. package/manifestUtils/tvAction/container/index.js +1 -1
  65. package/numberUtils/__tests__/toNumber.test.ts +0 -12
  66. package/numberUtils/index.ts +1 -19
  67. package/package.json +4 -4
  68. package/pipesUtils/__tests__/buildUrlWithQuery.test.ts +33 -0
  69. package/pipesUtils/__tests__/withPipesEndpoint.test.tsx +56 -0
  70. package/pipesUtils/index.ts +1 -0
  71. package/pipesUtils/withPipesEndpoint.tsx +54 -0
  72. package/playerUtils/index.ts +24 -2
  73. package/pluginUtils/index.ts +4 -9
  74. package/reactHooks/advertising/index.ts +2 -2
  75. package/reactHooks/app/__tests__/useAppState.test.ts +1 -1
  76. package/reactHooks/autoscrolling/__tests__/useTrackCurrentAutoScrollingElement.test.ts +1 -1
  77. package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +2 -1
  78. package/reactHooks/casting/index.ts +1 -0
  79. package/reactHooks/casting/useIsCasting.tsx +57 -0
  80. package/reactHooks/cell-click/__tests__/index.test.js +3 -1
  81. package/reactHooks/componentsMap/index.ts +55 -0
  82. package/reactHooks/configuration/__tests__/index.test.tsx +1 -1
  83. package/reactHooks/connection/__tests__/index.test.js +1 -1
  84. package/reactHooks/debugging/__tests__/index.test.js +4 -4
  85. package/reactHooks/device/useIsTablet.tsx +19 -14
  86. package/reactHooks/device/useMemoizedIsTablet.ts +3 -3
  87. package/reactHooks/events/index.ts +20 -0
  88. package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +23 -32
  89. package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +19 -19
  90. package/reactHooks/feed/__tests__/useEntryScreenId.test.tsx +1 -4
  91. package/reactHooks/feed/__tests__/useFeedLoader.test.tsx +30 -42
  92. package/reactHooks/feed/__tests__/useFeedRefresh.test.tsx +1 -1
  93. package/reactHooks/feed/__tests__/useInflatedUrl.test.tsx +1 -1
  94. package/reactHooks/feed/useBatchLoading.ts +1 -7
  95. package/reactHooks/feed/useEntryScreenId.ts +2 -2
  96. package/reactHooks/feed/useInflatedUrl.ts +1 -1
  97. package/reactHooks/feed/usePipesCacheReset.ts +1 -3
  98. package/reactHooks/flatList/useLoadNextPageIfNeeded.ts +16 -13
  99. package/reactHooks/index.ts +2 -0
  100. package/reactHooks/layout/__tests__/index.test.tsx +1 -1
  101. package/reactHooks/layout/__tests__/useLayoutVersion.test.tsx +1 -1
  102. package/reactHooks/layout/useDimensions/__tests__/{useDimensions.test.tsx → useDimensions.test.ts} +25 -105
  103. package/reactHooks/layout/useDimensions/useDimensions.ts +2 -2
  104. package/reactHooks/navigation/__tests__/index.test.tsx +4 -2
  105. package/reactHooks/navigation/index.ts +6 -7
  106. package/reactHooks/navigation/useRoute.ts +6 -8
  107. package/reactHooks/player/TVSeekControlller/TVSeekController.ts +10 -27
  108. package/reactHooks/player/__tests__/useAutoSeek._test.tsx +1 -1
  109. package/reactHooks/player/__tests__/useTapSeek._test.ts +1 -1
  110. package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +1 -1
  111. package/reactHooks/resolvers/__tests__/useComponentResolver.test.tsx +1 -1
  112. package/reactHooks/resolvers/useCellResolver.ts +2 -6
  113. package/reactHooks/resolvers/useComponentResolver.ts +13 -9
  114. package/reactHooks/screen/__tests__/useCurrentScreenData.test.tsx +2 -2
  115. package/reactHooks/screen/__tests__/useCurrentScreenIsHook.test.ts +103 -0
  116. package/reactHooks/screen/__tests__/useCurrentScreenIsStartupHook.test.ts +94 -0
  117. package/reactHooks/screen/__tests__/useScreenBackgroundColor.test.tsx +1 -1
  118. package/reactHooks/screen/__tests__/useScreenData.test.tsx +1 -1
  119. package/reactHooks/screen/__tests__/useTargetScreenData.test.tsx +4 -12
  120. package/reactHooks/screen/index.ts +6 -0
  121. package/reactHooks/screen/useCurrentScreenIsHook.ts +9 -0
  122. package/reactHooks/screen/useCurrentScreenIsStartupHook.ts +8 -0
  123. package/reactHooks/screen/useIsStandaloneFullscreen.ts +12 -0
  124. package/reactHooks/screen/useTargetScreenData.ts +2 -4
  125. package/reactHooks/state/__tests__/useComponentScreenState.test.ts +246 -0
  126. package/reactHooks/state/index.ts +2 -0
  127. package/reactHooks/state/useComponentScreenState.ts +45 -0
  128. package/reactHooks/state/useRivers.ts +1 -1
  129. package/reactHooks/usePluginConfiguration.ts +2 -2
  130. package/reactHooks/utils/__tests__/index.test.js +1 -1
  131. package/reactHooks/videoModal/hooks/useVideoModalScreenData.tsx +22 -4
  132. package/rectUtils/index.ts +2 -2
  133. package/riverComponetsMeasurementProvider/index.tsx +12 -8
  134. package/screenPickerUtils/index.ts +5 -0
  135. package/screenState/__tests__/index.test.ts +1 -1
  136. package/stringUtils/index.ts +1 -1
  137. package/testUtils/index.tsx +21 -30
  138. package/typeGuards/index.ts +0 -4
  139. package/utils/__tests__/clone.test.ts +158 -0
  140. package/utils/clone.ts +7 -0
  141. package/utils/index.ts +1 -13
  142. package/utils/path.ts +3 -6
  143. package/utils/pathOr.ts +1 -5
  144. package/zappFrameworkUtils/HookCallback/callbackNavigationAction.ts +2 -2
  145. package/zappFrameworkUtils/HookCallback/hookCallbackManifestExtensions.config.js +1 -1
  146. package/zappFrameworkUtils/loginPluginUtils.ts +1 -1
  147. package/adsUtils/__tests__/createVMAP.test.ts +0 -419
  148. package/appDataUtils/__tests__/urlScheme.test.ts +0 -678
  149. package/appUtils/focusManagerAux/utils/index.ios.ts +0 -122
  150. package/cloudEventsUtils/__tests__/index.test.ts +0 -529
  151. package/enumUtils/__tests__/getEnumKeyByEnumValue.test.ts +0 -207
  152. package/errorUtils/__tests__/GeneralError.test.ts +0 -97
  153. package/errorUtils/__tests__/HttpStatusCode.test.ts +0 -344
  154. package/errorUtils/__tests__/MissingPluginError.test.ts +0 -113
  155. package/errorUtils/__tests__/NetworkError.test.ts +0 -202
  156. package/errorUtils/__tests__/getParsedResponse.test.ts +0 -188
  157. package/errorUtils/__tests__/invariant.test.ts +0 -112
  158. package/numberUtils/__tests__/toPositiveNumber.test.ts +0 -165
  159. package/reactHooks/analytics/__tests__/useSendAnalyticsOnPress.test.ts +0 -537
  160. package/reactHooks/dev/__tests__/useReRenderLog.test.ts +0 -188
  161. package/reactHooks/ui/__tests__/useFadeOutWhenBlurred.test.ts +0 -580
  162. package/rectUtils/__tests__/index.test.ts +0 -549
  163. package/screenPickerUtils/__tests__/index.test.ts +0 -333
  164. package/searchUtils/const.ts +0 -7
  165. package/searchUtils/index.ts +0 -3
  166. package/time/__tests__/BackgroundTimer.test.ts +0 -156
  167. package/time/__tests__/Timer.test.ts +0 -236
  168. package/typeGuards/__tests__/isString.test.ts +0 -21
  169. package/utils/__tests__/mergeRight.test.ts +0 -48
  170. package/utils/__tests__/selectors.test.ts +0 -124
  171. package/utils/mergeRight.ts +0 -5
  172. package/utils/selectors.ts +0 -46
@@ -33,6 +33,7 @@ function deprecationWarning(method) {
33
33
  export interface PlayerLifecycleListener {
34
34
  onRegistered?: (player: Player) => void;
35
35
  onUnRegistered?: (player: Player) => void;
36
+ onCastingChanged?: (isCasting: boolean) => void;
36
37
  }
37
38
 
38
39
  type PlayersMap = {
@@ -253,10 +254,18 @@ export class PlayerManager {
253
254
 
254
255
  public registerCastingReceiver(receiver: Player) {
255
256
  this.castingReceiver = receiver;
257
+
258
+ this.lifecycleListeners.forEach((listener) => {
259
+ listener.onCastingChanged?.(true);
260
+ });
256
261
  }
257
262
 
258
263
  public unregisterCastingReceiver() {
259
264
  this.castingReceiver = null;
265
+
266
+ this.lifecycleListeners.forEach((listener) => {
267
+ listener.onCastingChanged?.(false);
268
+ });
260
269
  }
261
270
 
262
271
  /**
@@ -250,15 +250,11 @@ export class Player {
250
250
  return false;
251
251
  }
252
252
 
253
- if (!Number.isFinite(duration)) {
254
- return this.getSeekableDuration() > 0;
255
- }
256
-
257
253
  return duration > 0;
258
254
  };
259
255
 
260
256
  isAd = () => {
261
- return !!this.playerState.adState || this.playerState.isInAdBreak;
257
+ return !!this.playerState.adState || !!this.playerState.isInAdBreak;
262
258
  };
263
259
 
264
260
  isSeeking = () => {
@@ -19,52 +19,35 @@ type PlayerFactoryProps = {
19
19
  playerRole: PlayerRole;
20
20
  };
21
21
 
22
- interface PlayerConstructor {
22
+ interface PlayerControllerConstructor {
23
23
  new (params: any): Player;
24
24
  }
25
25
 
26
- export const playerFactory = (
27
- config: PlayerFactoryProps
28
- ): PlayerFactoryItem | null => {
29
- const IDENTIFIER = config?.playerPluginId;
26
+ type PlayerProtocol = {
27
+ Component: any;
28
+ controllerClass: PlayerControllerConstructor;
29
+ };
30
30
 
31
- if (!IDENTIFIER) {
32
- return null;
33
- }
31
+ export const playerFactory = async (
32
+ config: PlayerFactoryProps
33
+ ): Promise<PlayerFactoryItem | null> => {
34
+ if (!config?.playerPluginId) return null;
34
35
 
35
36
  const plugins = appStore.get("plugins");
37
+ if (!plugins) return null;
36
38
 
37
- if (!plugins) {
38
- return null;
39
- }
40
-
41
- const playerPlugin = findPluginByIdentifier(IDENTIFIER, plugins);
39
+ const playerPlugin = findPluginByIdentifier(config.playerPluginId, plugins);
40
+ if (!playerPlugin?.module?.playerProtocol) return null;
42
41
 
43
- if (!playerPlugin?.module?.playerProtocol) {
44
- return null;
45
- }
46
-
47
- const playerProtocol: PlayerConstructor = playerPlugin.module.playerProtocol(
48
- config?.screenConfig,
49
- config?.entry
50
- );
42
+ const playerProtocol: PlayerProtocol | null =
43
+ await playerPlugin.module.playerProtocol(config.screenConfig, config.entry);
51
44
 
52
- const playerView = (playerProtocol as any)?.Component || null;
53
-
54
- if (!playerView) {
45
+ if (!playerProtocol?.Component || !playerProtocol.controllerClass) {
55
46
  return null;
56
47
  }
57
48
 
58
- const Controller = (playerProtocol as any)?.controllerClass || null;
59
-
60
- if (Controller === null) {
61
- return null;
62
- }
63
-
64
- const controller = new Controller(config);
65
-
66
49
  return {
67
- controller,
68
- Component: playerView,
50
+ controller: new playerProtocol.controllerClass(config),
51
+ Component: playerProtocol.Component,
69
52
  };
70
53
  };
@@ -15,22 +15,6 @@ const logger = createLogger({
15
15
 
16
16
  const { log_warning } = logger;
17
17
 
18
- interface PlayerMethods {
19
- seeking?: (position: number) => void;
20
- forward?: (deltaTime: number) => void;
21
- rewind?: (deltaTime: number) => void;
22
- startSleepTimer?: (sleepTimestamp: number) => void;
23
- selectTrack?: (
24
- selected: QuickBrickPlayer.TextTrack | QuickBrickPlayer.AudioTrack
25
- ) => void;
26
- setPlaybackRate?: (rate: number) => void;
27
- appStateChange?: (appState: string, previousAppState: string) => void;
28
- closeNativePlayer?: () => void;
29
- togglePlayPause?: () => void;
30
- }
31
-
32
- type PlayerComponent = ReactComponent<PlayerRefProps> & PlayerMethods;
33
-
34
18
  type PlayerPlugnId = "QuickBrickPlayerPlugin" | "KalturaPlayerPlugin";
35
19
 
36
20
  type Props = {
@@ -78,7 +62,7 @@ export class PlayerNative extends Player {
78
62
  return this.playerState.contentPosition;
79
63
  };
80
64
 
81
- currentPlayerComponent = (): PlayerComponent | null =>
65
+ currentPlayerComponent = (): ReactComponent<PlayerRefProps> =>
82
66
  this.playerComponent?.current;
83
67
 
84
68
  getState = () => this.playerState;
@@ -137,7 +121,7 @@ export class PlayerNative extends Player {
137
121
 
138
122
  this.playerState.seekPosition = newPosition;
139
123
 
140
- this.currentPlayerComponent()?.seeking?.(this.playerState.seekPosition);
124
+ this.currentPlayerComponent()?.["seeking"](this.playerState.seekPosition);
141
125
  }
142
126
 
143
127
  this.logState(PlayerModuleFuncNames.seekTo, { position });
@@ -151,7 +135,7 @@ export class PlayerNative extends Player {
151
135
  if (!this.invokeNativeFunction(PlayerModuleFuncNames.forward, deltaTime)) {
152
136
  // Kaltura does not have yet this implementation, use legacy code
153
137
 
154
- this.currentPlayerComponent()?.forward?.(deltaTime);
138
+ this.currentPlayerComponent()?.["forward"](deltaTime);
155
139
  }
156
140
 
157
141
  this.notifyPlayHeadPositionUpdate();
@@ -167,7 +151,7 @@ export class PlayerNative extends Player {
167
151
  if (!this.invokeNativeFunction(PlayerModuleFuncNames.rewind, deltaTime)) {
168
152
  // Kaltura does not have yet this implementation, use legacy code
169
153
 
170
- this.currentPlayerComponent()?.rewind?.(deltaTime);
154
+ this.currentPlayerComponent()?.["rewind"](deltaTime);
171
155
  }
172
156
 
173
157
  this.notifyPlayHeadPositionUpdate();
@@ -194,7 +178,7 @@ export class PlayerNative extends Player {
194
178
  sleepTimestamp
195
179
  )
196
180
  ) {
197
- this.currentPlayerComponent()?.startSleepTimer?.(sleepTimestamp);
181
+ this.currentPlayerComponent()?.["startSleepTimer"](sleepTimestamp);
198
182
  }
199
183
  };
200
184
 
@@ -211,11 +195,11 @@ export class PlayerNative extends Player {
211
195
  selectTrack = (
212
196
  selected: QuickBrickPlayer.TextTrack | QuickBrickPlayer.AudioTrack
213
197
  ) => {
214
- this.currentPlayerComponent()?.selectTrack?.(selected);
198
+ this.currentPlayerComponent()?.["selectTrack"]?.(selected);
215
199
  };
216
200
 
217
201
  setPlaybackRate = (rate: number) => {
218
- this.currentPlayerComponent()?.setPlaybackRate?.(rate);
202
+ this.currentPlayerComponent()?.["setPlaybackRate"]?.(rate);
219
203
  };
220
204
 
221
205
  getPluginConfiguration = () => {
@@ -225,16 +209,24 @@ export class PlayerNative extends Player {
225
209
  getProps = () => (this.currentPlayerComponent() as any)?.props;
226
210
 
227
211
  appStateChange = (appState, previousAppState) => {
228
- this.currentPlayerComponent()?.appStateChange?.(appState, previousAppState);
212
+ this.currentPlayerComponent()?.["appStateChange"]?.(
213
+ appState,
214
+ previousAppState
215
+ );
229
216
  };
230
217
 
231
218
  closeNativePlayer = () => {
232
- // TODO: Delete does not work
233
- this.currentPlayerComponent()?.closeNativePlayer?.();
219
+ // The player component ref may be null (for example, when the native player view is not mounted),
220
+ // so calling closeNativePlayer on the component is best‑effort only. We cannot use invokeNativeFunction
221
+ // here because it prepends the view id, while the native closeNativePlayer implementation does not
222
+ // expect a view id argument. As a reliable fallback we always call stopBackgroundPlayback on the
223
+ // native module to ensure background playback is stopped.
224
+ this.currentPlayerComponent()?.["closeNativePlayer"]?.();
225
+ this.getPlayerModule()?.stopBackgroundPlayback?.();
234
226
  };
235
227
 
236
228
  togglePlayPause = () => {
237
- this.currentPlayerComponent()?.togglePlayPause?.();
229
+ this.currentPlayerComponent()?.["togglePlayPause"]?.();
238
230
  };
239
231
 
240
232
  onVideoLoad = (event) => {
@@ -302,19 +294,19 @@ export class PlayerNative extends Player {
302
294
  isFullScreenSupported = (): boolean => {
303
295
  const config = this.getConfig();
304
296
 
305
- const disableFullScreen = config?.disable_fullscreen;
297
+ const disableFullScreen = config?.["disable_fullscreen"];
306
298
 
307
299
  if (disableFullScreen) {
308
300
  return false;
309
301
  }
310
302
 
311
- const isFullScreenAudioPlayer = config?.full_screen_audio_player;
303
+ const isFullScreenAudioPlayer = config?.["full_screen_audio_player"];
312
304
 
313
305
  return !(isFullScreenAudioPlayer && this.isAudioItem());
314
306
  };
315
307
 
316
308
  supportsNativeControls = (): boolean =>
317
- toBooleanWithDefaultFalse(this.getConfig()?.supports_native_controls);
309
+ toBooleanWithDefaultFalse(this.getConfig()?.["supports_native_controls"]);
318
310
 
319
311
  supportNativeCast = (): boolean =>
320
312
  toBooleanWithDefaultFalse(
@@ -22,7 +22,6 @@ export const usePlayer = (playerId?: string): Player => {
22
22
 
23
23
  const isCasting = playerManager.isCasting();
24
24
 
25
- // TODO: We need to prerender when we start/stop casting, fix this
26
25
  const getPlayer = (playerId, isCasting) =>
27
26
  getControlledPlayer(playerId, isCasting);
28
27
 
@@ -46,7 +45,7 @@ export const usePlayer = (playerId?: string): Player => {
46
45
  return playerManager.addLifecycleListener({
47
46
  onRegistered: (player) => {
48
47
  if (playerIdToUse === player.playerId) {
49
- setPlayer(getPlayer(playerIdToUse, isCasting));
48
+ setPlayer(getPlayer(playerIdToUse, playerManager.isCasting()));
50
49
  }
51
50
  },
52
51
  onUnRegistered: (player) => {
@@ -54,8 +53,11 @@ export const usePlayer = (playerId?: string): Player => {
54
53
  setPlayer(null);
55
54
  }
56
55
  },
56
+ onCastingChanged: () => {
57
+ setPlayer(getPlayer(playerIdToUse, playerManager.isCasting()));
58
+ },
57
59
  } as PlayerLifecycleListener);
58
- }, [playerIdToUse, isCasting]);
60
+ }, [playerIdToUse]);
59
61
 
60
62
  return player;
61
63
  };
@@ -2,7 +2,7 @@ import * as React from "react";
2
2
  import { Player } from "./player";
3
3
  import { usePlayer } from "./usePlayer";
4
4
 
5
- export type PlayerState = {
5
+ type PlayerState = {
6
6
  currentTime: number;
7
7
  duration: number;
8
8
  seekableDuration: number;
@@ -10,8 +10,6 @@ export type PlayerState = {
10
10
  isPaused: boolean;
11
11
  isBuffering: boolean;
12
12
  isReadyToPlay: boolean;
13
- trackState?: QuickBrickPlayer.TracksState;
14
- isAd: boolean;
15
13
  };
16
14
 
17
15
  export const usePlayerState = (
@@ -26,8 +24,6 @@ export const usePlayerState = (
26
24
  isPaused: null,
27
25
  isBuffering: false,
28
26
  isReadyToPlay: false,
29
- trackState: null,
30
- isAd: false,
31
27
  });
32
28
 
33
29
  const player: Player = usePlayer(playerId);
@@ -41,8 +37,6 @@ export const usePlayerState = (
41
37
  isPaused: player.isPaused(),
42
38
  isBuffering: player.isBuffering(),
43
39
  isReadyToPlay: player.isReadyToPlay(),
44
- trackState: player.getTracksState(),
45
- isAd: player.isAd(),
46
40
  });
47
41
  }, [player]);
48
42
 
@@ -60,16 +54,10 @@ export const usePlayerState = (
60
54
  onPlayerPause: onPlayerChangeState,
61
55
  onPlayerResume: onPlayerChangeState,
62
56
  onPlayerSeekComplete: onPlayerChangeState,
63
- onTracksChanged: onPlayerChangeState,
64
- onAdBreakBegin: onPlayerChangeState,
65
- onAdBreakEnd: onPlayerChangeState,
66
- onAdBegin: onPlayerChangeState,
67
- onAdEnd: onPlayerChangeState,
68
- onAdError: onPlayerChangeState,
69
57
  },
70
58
  });
71
59
  }
72
- }, [listenerId, onPlayerChangeState, player]);
60
+ }, [player]);
73
61
 
74
62
  return state;
75
63
  };
@@ -3,6 +3,7 @@ import {
3
3
  ifEmptyUseFallback,
4
4
  textTransform,
5
5
  getKeyForLabel,
6
+ getDataTransformForLabel,
6
7
  getLabel,
7
8
  getAspectRatio,
8
9
  getCellWidth,
@@ -56,6 +57,44 @@ describe("getKeyForLabel", () => {
56
57
  });
57
58
  });
58
59
 
60
+ describe("getDataTransformForLabel", () => {
61
+ it("returns dataKey when dataKey is not other", () => {
62
+ expect(getDataTransformForLabel(VAL.dataKey, VAL.customKey)).toEqual(
63
+ VAL.dataKey
64
+ );
65
+ });
66
+
67
+ it("returns customKey when dataKey is other", () => {
68
+ expect(getDataTransformForLabel(VAL.other, VAL.customKey)).toEqual(
69
+ VAL.customKey
70
+ );
71
+ });
72
+
73
+ it("preserves full date formats containing dots", () => {
74
+ expect(getDataTransformForLabel(VAL.other, "DD.MM.YYYY")).toEqual(
75
+ "DD.MM.YYYY"
76
+ );
77
+ });
78
+
79
+ it("returns default date format when selected key is null or undefined", () => {
80
+ expect(getDataTransformForLabel(EMPTY.nulls, VAL.customKey)).toEqual(
81
+ "DD/MM/YYYY"
82
+ );
83
+
84
+ expect(getDataTransformForLabel(EMPTY.undef, VAL.customKey)).toEqual(
85
+ "DD/MM/YYYY"
86
+ );
87
+
88
+ expect(getDataTransformForLabel(VAL.other, EMPTY.nulls)).toEqual(
89
+ "DD/MM/YYYY"
90
+ );
91
+
92
+ expect(getDataTransformForLabel(VAL.other, EMPTY.undef)).toEqual(
93
+ "DD/MM/YYYY"
94
+ );
95
+ });
96
+ });
97
+
59
98
  describe("getLabel", () => {
60
99
  it("returns a string from dataKey's path", () => {
61
100
  expect(getLabel(VAL.dataKey, VAL.customKey)(entry)).toEqual(entry.id);
@@ -1,7 +1,7 @@
1
1
  import * as R from "ramda";
2
- import dayjs from "dayjs";
3
- import validateColor from "validate-color";
2
+ import { dayjs } from "../dateUtils";
4
3
 
4
+ import { isValidColor } from "@applicaster/zapp-react-native-utils/colorUtils";
5
5
  import { transformColorCode as fixColorHexCode } from "@applicaster/zapp-react-native-utils/transform";
6
6
  import {
7
7
  capitalize,
@@ -31,6 +31,16 @@ export const getKeyForLabel = (dataKey, customKey) => {
31
31
  return keyToUse.split(".");
32
32
  };
33
33
 
34
+ /**
35
+ * Provides `format` for date formatting. Returns customKey if dataKey is "other", otherwise it returns dataKey.
36
+ * Should consist of valid dayjs tokens - https://day.js.org/docs/en/parse/string-format#list-of-all-available-parsing-tokens
37
+ */
38
+ export const getDataTransformForLabel = (dataKey, customKey) => {
39
+ const keyToUse = dataKey === CUSTOM_KEY ? customKey : dataKey;
40
+
41
+ return keyToUse ?? "DD/MM/YYYY";
42
+ };
43
+
34
44
  /**
35
45
  * This method will return true if the argument passed to it is either empty or nil
36
46
  * The method prevents zero from being evaluated as falsey in an || condition
@@ -458,15 +468,13 @@ export const getColorFromData = ({
458
468
  data,
459
469
  valueFromLayout,
460
470
  }: GetColorFromData): string => {
461
- // Temporary hack to fix color validation when alpha is floating point number
462
- // https://github.com/dreamyguy/validate-color/issues/44
463
- if (validateColor(valueFromLayout.replace(".00", ""))) {
471
+ if (isValidColor(valueFromLayout)) {
464
472
  return valueFromLayout;
465
473
  }
466
474
 
467
475
  const pathValue = R.path(valueFromLayout.split("."), data);
468
476
 
469
- if (pathValue && validateColor(pathValue)) {
477
+ if (pathValue && isValidColor(pathValue)) {
470
478
  return pathValue;
471
479
  }
472
480
 
@@ -3,41 +3,6 @@ import { RequestBuilder } from "@applicaster/zapp-pipes-v2-client";
3
3
  import { sessionStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/SessionStorage";
4
4
  import { getAppUrlScheme } from "@applicaster/zapp-react-native-utils/appDataUtils";
5
5
 
6
- /**
7
- * CloudEvents v1.0 compliant event object
8
- * @see https://github.com/cloudevents/spec/blob/v1.0/spec.md
9
- */
10
- export interface CloudEvent<T = any> {
11
- /** CloudEvents specification version (always "1.0") */
12
- specversion: "1.0";
13
- /** Type of event (e.g., "user.action", "commerce.purchase") */
14
- type: string;
15
- /** Identifier for the entity that produced the event */
16
- source: string;
17
- /** Unique identifier for the event */
18
- id: string;
19
- /** Subject of the event in the context of the event producer */
20
- subject: string;
21
- /** Timestamp of when the event occurred (ISO 8601 format) */
22
- time: string;
23
- /** Content type of the data attribute (always "application/json") */
24
- datacontenttype: "application/json";
25
- /** Event payload */
26
- data: T;
27
- }
28
-
29
- /**
30
- * Parameters required to create a cloud event
31
- */
32
- export interface CreateCloudEventParams<T = any> {
33
- /** Type of event (e.g., "user.action", "commerce.purchase") */
34
- type: string;
35
- /** Subject of the event in the context of the event producer */
36
- subject: string;
37
- /** Event payload */
38
- data: T;
39
- }
40
-
41
6
  let source: string | null = null;
42
7
 
43
8
  const addSource = async () => {
@@ -61,36 +26,7 @@ const addSource = async () => {
61
26
  return source;
62
27
  };
63
28
 
64
- /**
65
- * Resets the cached CloudEvents source.
66
- *
67
- * @internal
68
- * @testonly This function is intended for test use only and will only work in test environments.
69
- *
70
- * @remarks
71
- * This function clears the cached source value, forcing the next call to `createCloudEvent`
72
- * to regenerate the source from app metadata. It only operates when NODE_ENV is set to "test"
73
- * to prevent accidental misuse in production code.
74
- *
75
- * @example
76
- * ```typescript
77
- * // In Jest tests
78
- * beforeEach(() => {
79
- * resetCloudEventsSource();
80
- * });
81
- * ```
82
- */
83
- export const resetCloudEventsSource = (): void => {
84
- if (process.env.NODE_ENV === "test") {
85
- source = null;
86
- }
87
- };
88
-
89
- export const createCloudEvent = async <T = any>({
90
- type,
91
- subject,
92
- data,
93
- }: CreateCloudEventParams<T>): Promise<CloudEvent<T>> => {
29
+ export const createCloudEvent = async ({ type, subject, data }) => {
94
30
  return {
95
31
  specversion: "1.0",
96
32
  type,
@@ -0,0 +1,76 @@
1
+ import { isTransparentColor } from "..";
2
+
3
+ describe("isTransparentColor", () => {
4
+ it("returns true for transparent keyword and rgba colors with zero alpha", () => {
5
+ const transparentColors = [
6
+ "transparent",
7
+ "rgba(0,0,0,0)",
8
+ "rgba(255, 255, 255, 0)",
9
+ "rgba(0,0,0,0.0)",
10
+ "rgba(0,0,0,0.00)",
11
+ "rgba(0,0,0, 0)",
12
+ "hsla(0,0%,0%,0)",
13
+ ];
14
+
15
+ expect.assertions(transparentColors.length);
16
+
17
+ transparentColors.forEach((color) => {
18
+ expect(isTransparentColor(color)).toBe(true);
19
+ });
20
+ });
21
+
22
+ it("returns false for valid colors that are not fully transparent", () => {
23
+ const nonTransparentColors = [
24
+ "red",
25
+ "#fff",
26
+ "#ffffff",
27
+ "rgb(0,0,0)",
28
+ "rgba(0,0,0)",
29
+ "rgba(0,0,0,0.5)",
30
+ "rgba(255, 255, 255, 0.3)",
31
+ "rgba(255, 255, 255, 1.0)",
32
+ "rgba(239,239,239,1.0)",
33
+ "currentColor",
34
+ "inherit",
35
+ "#00000000",
36
+ "#fff0",
37
+ ];
38
+
39
+ expect.assertions(nonTransparentColors.length);
40
+
41
+ nonTransparentColors.forEach((color) => {
42
+ expect(isTransparentColor(color)).toBe(false);
43
+ });
44
+ });
45
+
46
+ it("returns false for case variants of the transparent keyword", () => {
47
+ expect(isTransparentColor("Transparent")).toBe(false);
48
+ expect(isTransparentColor("TRANSPARENT")).toBe(false);
49
+ });
50
+
51
+ it("returns false for invalid color strings", () => {
52
+ const invalidColors = [
53
+ "invalid",
54
+ "",
55
+ "#gggggg",
56
+ "#fff.00",
57
+ "unset",
58
+ " rgba(0,0,0,0) ",
59
+ "transparent ",
60
+ ];
61
+
62
+ expect.assertions(invalidColors.length);
63
+
64
+ invalidColors.forEach((color) => {
65
+ expect(isTransparentColor(color)).toBe(false);
66
+ });
67
+ });
68
+
69
+ it("returns false for nullish and non-string values", () => {
70
+ expect(isTransparentColor(undefined)).toBe(false);
71
+ expect(isTransparentColor(null)).toBe(false);
72
+ expect(isTransparentColor(123)).toBe(false);
73
+ expect(isTransparentColor({})).toBe(false);
74
+ expect(isTransparentColor([])).toBe(false);
75
+ });
76
+ });
@@ -0,0 +1,70 @@
1
+ import { isValidColor } from "..";
2
+
3
+ describe("isValidColor", () => {
4
+ it("returns true for valid hex colors", () => {
5
+ const validHexColors = ["#fff", "#ffffff", "#FF0000", "#000", "#abc123"];
6
+
7
+ expect.assertions(validHexColors.length);
8
+
9
+ validHexColors.forEach((color) => {
10
+ expect(isValidColor(color)).toBe(true);
11
+ });
12
+ });
13
+
14
+ it("returns true for valid rgb and rgba colors", () => {
15
+ const validRgbColors = [
16
+ "rgb(255,0,0)",
17
+ "rgb(255, 0, 0)",
18
+ "rgba(255,0,0,0.5)",
19
+ "rgba(255, 0, 0, 0.5)",
20
+ ];
21
+
22
+ expect.assertions(validRgbColors.length);
23
+
24
+ validRgbColors.forEach((color) => {
25
+ expect(isValidColor(color)).toBe(true);
26
+ });
27
+ });
28
+
29
+ it("returns true for valid named and special CSS colors", () => {
30
+ const validNamedColors = ["red", "transparent", "currentColor", "inherit"];
31
+
32
+ expect.assertions(validNamedColors.length);
33
+
34
+ validNamedColors.forEach((color) => {
35
+ expect(isValidColor(color)).toBe(true);
36
+ });
37
+ });
38
+
39
+ it("returns true for valid hsl colors", () => {
40
+ expect(isValidColor("hsl(0, 100%, 50%)")).toBe(true);
41
+ });
42
+
43
+ it("returns false for invalid color strings", () => {
44
+ const invalidColors = [
45
+ "invalid",
46
+ "",
47
+ "#gggggg",
48
+ "#fff.00",
49
+ "unset",
50
+ undefined,
51
+ null,
52
+ ];
53
+
54
+ expect.assertions(invalidColors.length);
55
+
56
+ invalidColors.forEach((color) => {
57
+ expect(isValidColor(color)).toBe(false);
58
+ });
59
+ });
60
+
61
+ it("returns true for valid rgb and rgba colors", () => {
62
+ const validRgbColors = ["rgba(239,239,239,1.0)"];
63
+
64
+ expect.assertions(validRgbColors.length);
65
+
66
+ validRgbColors.forEach((color) => {
67
+ expect(isValidColor(color)).toBe(true);
68
+ });
69
+ });
70
+ });