@applicaster/zapp-react-native-utils 12.0.0-alpha.9262886003 → 12.0.0-alpha.9417984401
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/analyticsUtils/AnalyticPlayerListener.ts +141 -0
- package/analyticsUtils/AnalyticsEvents/index.ts +13 -0
- package/analyticsUtils/AnalyticsEvents/searchEvents.ts +21 -0
- package/analyticsUtils/AnalyticsEvents/sendShareEvent.ts +21 -0
- package/analyticsUtils/PlayerAnalyticsManager.ts +90 -0
- package/analyticsUtils/analyticsPlugins.ts +25 -0
- package/analyticsUtils/events.ts +12 -0
- package/analyticsUtils/index.tsx +12 -0
- package/analyticsUtils/{analyticsTracker.ts → playerAnalyticsTracker.ts} +19 -10
- package/appUtils/HooksManager/index.js +3 -1
- package/appUtils/accessibilityManager/const.ts +50 -0
- package/appUtils/accessibilityManager/hooks.ts +40 -0
- package/appUtils/accessibilityManager/index.ts +166 -0
- package/appUtils/accessibilityManager/logger.ts +5 -0
- package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +2 -3
- package/appUtils/focusManager/__tests__/focusManager.test.js +4 -24
- package/appUtils/focusManager/__tests__/index.test.ts +2 -3
- package/appUtils/focusManager/index.ts +76 -57
- package/appUtils/focusManager/treeDataStructure/Utils/index.js +75 -44
- package/appUtils/focusManager/utils/index.ts +100 -0
- package/appUtils/focusManagerAux/index.ts +76 -0
- package/appUtils/focusManagerAux/utils/index.ts +100 -0
- package/appUtils/index.js +2 -0
- package/appUtils/keyCodes/keys.web.js +8 -0
- package/appUtils/keyCodes/keysByPlatform.js +11 -1
- package/appUtils/platform/const.ts +25 -0
- package/appUtils/platform/index.ts +3 -0
- package/appUtils/platform/platformUtils.ts +217 -0
- package/appUtils/playerManager/conts.ts +6 -0
- package/appUtils/playerManager/index.ts +20 -32
- package/appUtils/playerManager/nativePlayerManager.ts +12 -0
- package/appUtils/playerManager/player.ts +44 -3
- package/appUtils/playerManager/playerFactory.ts +13 -11
- package/appUtils/playerManager/playerHooks/usePlayerCurrentTime.tsx +57 -0
- package/appUtils/playerManager/playerNative.ts +15 -15
- package/appUtils/playerManager/usePlayerControllerSetup.tsx +8 -2
- package/appUtils/playerManager/usePlayerState.tsx +19 -34
- package/arrayUtils/__tests__/isFilledArray.test.ts +63 -0
- package/arrayUtils/index.ts +5 -0
- package/booleanUtils/index.ts +4 -4
- package/cellUtils/__tests__/cellUtils.test.ts +9 -20
- package/cellUtils/index.ts +48 -19
- package/dateUtils/index.ts +11 -0
- package/functionUtils/index.ts +38 -0
- package/headersUtils/index.ts +1 -0
- package/index.d.ts +15 -0
- package/inflatedUrlUtils/index.ts +4 -4
- package/keyboardState/index.ts +0 -0
- package/localizationUtils/__tests__/localizationUtils.test.ts +72 -53
- package/localizationUtils/index.ts +13 -22
- package/manifestUtils/defaultManifestConfigurations/generalContent.js +6 -0
- package/manifestUtils/defaultManifestConfigurations/player.js +123 -1
- package/manifestUtils/index.js +5 -1
- package/manifestUtils/keys.js +2 -1
- package/manifestUtils/secondaryImage/index.js +18 -15
- package/navigationUtils/index.ts +48 -0
- package/numberUtils/__tests__/isLikeNumber.test.ts +18 -0
- package/numberUtils/__tests__/toNumber.test.ts +2 -2
- package/numberUtils/index.ts +9 -18
- package/package.json +2 -2
- package/playerUtils/configurationGenerator.ts +123 -1
- package/playerUtils/imaScriptDom.ts +59 -0
- package/pluginUtils/index.ts +9 -0
- package/reactHooks/autoscrolling/__tests__/useTrackCurrentAutoScrollingElement.test.ts +2 -0
- package/reactHooks/autoscrolling/__tests__/{useTrackedView.test.ts → useTrackedView.test.tsx} +18 -1
- package/reactHooks/cell-click/__tests__/index.test.js +10 -1
- package/reactHooks/cell-click/index.ts +12 -12
- package/reactHooks/debugging/__tests__/index.test.js +81 -11
- package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +30 -70
- package/reactHooks/feed/__tests__/useFeedRefresh.test.tsx +6 -2
- package/reactHooks/feed/__tests__/useInflatedUrl.test.ts +18 -3
- package/reactHooks/feed/useBuildPipesUrl.ts +7 -10
- package/reactHooks/feed/useFeedRefresh.tsx +9 -7
- package/reactHooks/feed/useInflatedUrl.ts +44 -15
- package/reactHooks/layout/__tests__/{index.test.js → index.test.tsx} +44 -29
- package/reactHooks/layout/getDeviceInfo/index.ts +4 -2
- package/reactHooks/layout/types/index.ts +2 -0
- package/reactHooks/layout/useDimensions/useDimensions.ts +15 -7
- package/reactHooks/navigation/__mocks__/index.ts +15 -0
- package/reactHooks/navigation/__mocks__/useNavigation.ts +3 -0
- package/reactHooks/navigation/__tests__/index.test.tsx +11 -8
- package/reactHooks/navigation/index.ts +64 -21
- package/reactHooks/player/useAutoSeek.tsx +9 -7
- package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +3 -1
- package/reactHooks/resolvers/useCellResolver.ts +5 -1
- package/reactHooks/screen/__tests__/useCurrentScreenData.test.tsx +21 -23
- package/reactHooks/screen/index.ts +2 -0
- package/reactHooks/screen/useScreenBackgroundColor.ts +23 -0
- package/reactHooks/screen/useScreenContext.ts +3 -3
- package/reactHooks/screen/useTargetScreenData.ts +7 -0
- package/reactHooks/useConfiguration.ts +2 -2
- package/reactUtils/index.ts +104 -0
- package/screenState/index.ts +0 -8
- package/stringUtils/index.ts +5 -0
- package/testUtils/getByTestId.ts +14 -0
- package/testUtils/index.tsx +24 -22
- package/types.ts +4 -0
- package/appUtils/focusManager/FocusableEvents.ts +0 -8
- package/appUtils/focusManager/treeDataStructure/Utils/__tests__/Utils_android.test.js +0 -1094
- package/appUtils/focusManager/treeDataStructure/Utils/index.android.js +0 -261
|
@@ -3,7 +3,6 @@ import * as R from "ramda";
|
|
|
3
3
|
import { subscriber } from "../../functionUtils";
|
|
4
4
|
import { utilsLogger, createLogger } from "../../logger";
|
|
5
5
|
import { Player } from "./player";
|
|
6
|
-
import { AnalyticsTracker } from "../../analyticsUtils/analyticsTracker";
|
|
7
6
|
import {
|
|
8
7
|
hasTizenAPIs,
|
|
9
8
|
subscribeToDeviceNetworkChanges,
|
|
@@ -11,6 +10,7 @@ import {
|
|
|
11
10
|
} from "@applicaster/quick-brick-core/App/NetworkStatusProvider/utils";
|
|
12
11
|
import { setUserLanguagePreference } from "./userLanguagePreference";
|
|
13
12
|
import { PlayerRole } from "./conts";
|
|
13
|
+
import { RNPlayerManager } from "./nativePlayerManager";
|
|
14
14
|
|
|
15
15
|
const { log_error, log_debug, log_warning } = createLogger({
|
|
16
16
|
category: "General",
|
|
@@ -36,7 +36,10 @@ export interface PlayerLifecycleListener {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
type PlayersMap = {
|
|
39
|
-
[id: string]: {
|
|
39
|
+
[id: string]: {
|
|
40
|
+
player: Player;
|
|
41
|
+
isInViewport: boolean;
|
|
42
|
+
};
|
|
40
43
|
};
|
|
41
44
|
|
|
42
45
|
export class PlayerManager {
|
|
@@ -45,7 +48,6 @@ export class PlayerManager {
|
|
|
45
48
|
private playersMap: PlayersMap = {};
|
|
46
49
|
private manager = subscriber();
|
|
47
50
|
private castingReceiver: Player;
|
|
48
|
-
private analyticsTracker: AnalyticsTracker;
|
|
49
51
|
private lifecycleListeners: PlayerLifecycleListener[] = [];
|
|
50
52
|
|
|
51
53
|
public static getInstance() {
|
|
@@ -56,7 +58,7 @@ export class PlayerManager {
|
|
|
56
58
|
return PlayerManager.instance;
|
|
57
59
|
}
|
|
58
60
|
|
|
59
|
-
public getActivePlayerId = ():
|
|
61
|
+
public getActivePlayerId = (): string | null => {
|
|
60
62
|
return this.activePlayerId;
|
|
61
63
|
};
|
|
62
64
|
|
|
@@ -101,7 +103,10 @@ export class PlayerManager {
|
|
|
101
103
|
}
|
|
102
104
|
|
|
103
105
|
private addPlayer = (id: string, player: Player) => {
|
|
104
|
-
this.playersMap[id] = {
|
|
106
|
+
this.playersMap[id] = {
|
|
107
|
+
player: player,
|
|
108
|
+
isInViewport: false,
|
|
109
|
+
};
|
|
105
110
|
};
|
|
106
111
|
|
|
107
112
|
public isPlayerRegistered = (id: string) => !!this.playersMap[id];
|
|
@@ -164,6 +169,10 @@ export class PlayerManager {
|
|
|
164
169
|
this.addPlayer(id, playerController);
|
|
165
170
|
|
|
166
171
|
if (playerController.playerRole === PlayerRole.Primary) {
|
|
172
|
+
if (playerController.playerPluginId !== "QuickBrickPlayerPlugin") {
|
|
173
|
+
RNPlayerManager?.["QuickBrickPlayerPlugin"]?.stopBackgroundPlayback?.();
|
|
174
|
+
}
|
|
175
|
+
|
|
167
176
|
playerController.addListener({
|
|
168
177
|
id: this.getPlayerListenerId(id),
|
|
169
178
|
listener: {
|
|
@@ -246,28 +255,6 @@ export class PlayerManager {
|
|
|
246
255
|
this.castingReceiver = null;
|
|
247
256
|
}
|
|
248
257
|
|
|
249
|
-
/**
|
|
250
|
-
* Handles analytic events, generates a new analytics tracker and transmits events
|
|
251
|
-
* Passes entry data, and playerState to the tracker for additional context
|
|
252
|
-
* The end result is an event formatted and passed to AnalyticsBridge.postEvent
|
|
253
|
-
* When we get the synthetic event we need to pull the data in the e object
|
|
254
|
-
* e contains the return value from native
|
|
255
|
-
*/
|
|
256
|
-
public handleAnalyticEvent(event, data = {}, entry: ZappEntry) {
|
|
257
|
-
const playerState = this.getActivePlayer()?.getState();
|
|
258
|
-
|
|
259
|
-
if (!this.analyticsTracker?.handleAnalyticEvent) {
|
|
260
|
-
this.analyticsTracker = new AnalyticsTracker(entry);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
this.analyticsTracker?.handleAnalyticEvent?.(
|
|
264
|
-
event,
|
|
265
|
-
data,
|
|
266
|
-
entry,
|
|
267
|
-
playerState
|
|
268
|
-
);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
258
|
/**
|
|
272
259
|
* Method retrieves the instantiated player instance controller
|
|
273
260
|
* Instance controller exposes methods like getContentDuration, getContentPosision
|
|
@@ -361,9 +348,9 @@ export class PlayerManager {
|
|
|
361
348
|
// TODO: Remove
|
|
362
349
|
if (this.castingReceiver) {
|
|
363
350
|
this.castingReceiver.rewind(deltaTime);
|
|
351
|
+
} else {
|
|
352
|
+
this.getActivePlayer()?.rewind(deltaTime);
|
|
364
353
|
}
|
|
365
|
-
|
|
366
|
-
this.getActivePlayer()?.rewind(deltaTime);
|
|
367
354
|
}
|
|
368
355
|
|
|
369
356
|
public forward(deltaTime = null) {
|
|
@@ -371,9 +358,9 @@ export class PlayerManager {
|
|
|
371
358
|
|
|
372
359
|
if (this.castingReceiver) {
|
|
373
360
|
this.castingReceiver.forward(deltaTime);
|
|
361
|
+
} else {
|
|
362
|
+
this.getActivePlayer()?.forward(deltaTime);
|
|
374
363
|
}
|
|
375
|
-
|
|
376
|
-
this.getActivePlayer()?.forward(deltaTime);
|
|
377
364
|
}
|
|
378
365
|
|
|
379
366
|
public seeking(time) {
|
|
@@ -436,7 +423,7 @@ export class PlayerManager {
|
|
|
436
423
|
}
|
|
437
424
|
|
|
438
425
|
// Call method on player just in case
|
|
439
|
-
return this.getActivePlayer()?.
|
|
426
|
+
return this.getActivePlayer()?.selectTrack(track);
|
|
440
427
|
}
|
|
441
428
|
|
|
442
429
|
public isRegistered() {
|
|
@@ -461,6 +448,7 @@ export class PlayerManager {
|
|
|
461
448
|
if (this.castingReceiver) {
|
|
462
449
|
this.castingReceiver.closeNativePlayer();
|
|
463
450
|
} else {
|
|
451
|
+
this.getActivePlayer().closeNativePlayer();
|
|
464
452
|
this.invokeHandler("close");
|
|
465
453
|
}
|
|
466
454
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { NativeModules } from "react-native";
|
|
2
|
+
import { isApplePlatform } from "../../reactUtils";
|
|
3
|
+
|
|
4
|
+
export const RNPlayerManager = {
|
|
5
|
+
QuickBrickPlayerPlugin: isApplePlatform()
|
|
6
|
+
? NativeModules.PlayerModule
|
|
7
|
+
: NativeModules.QuickBrickDefaultPlayerModule,
|
|
8
|
+
KalturaPlayerPlugin: isApplePlatform()
|
|
9
|
+
? NativeModules.KalturaPlayerModule
|
|
10
|
+
: NativeModules.QBKalturaPlayerModule,
|
|
11
|
+
"quick-brick-player-brightcove": NativeModules.BrightcovePlayerModule,
|
|
12
|
+
};
|
|
@@ -359,6 +359,13 @@ export class Player {
|
|
|
359
359
|
});
|
|
360
360
|
};
|
|
361
361
|
|
|
362
|
+
onVideoError = (error: Error) => {
|
|
363
|
+
this.invokeListenersUpdate({
|
|
364
|
+
callbackName: SharedPlayerCallBacksKeys.OnVideoError,
|
|
365
|
+
event: error,
|
|
366
|
+
});
|
|
367
|
+
};
|
|
368
|
+
|
|
362
369
|
onError = (error: Error) => {
|
|
363
370
|
this.invokeListenersUpdate({
|
|
364
371
|
callbackName: SharedPlayerCallBacksKeys.OnError,
|
|
@@ -414,6 +421,32 @@ export class Player {
|
|
|
414
421
|
});
|
|
415
422
|
};
|
|
416
423
|
|
|
424
|
+
onVideoFullscreenPlayerWillDismiss = () => {
|
|
425
|
+
this.invokeListenersUpdate({
|
|
426
|
+
callbackName:
|
|
427
|
+
SharedPlayerCallBacksKeys.onVideoFullscreenPlayerWillDismiss,
|
|
428
|
+
});
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
onVideoFullscreenPlayerDidDismiss = () => {
|
|
432
|
+
this.invokeListenersUpdate({
|
|
433
|
+
callbackName: SharedPlayerCallBacksKeys.onVideoFullscreenPlayerDidDismiss,
|
|
434
|
+
});
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
onVideoFullscreenPlayerWillPresent = () => {
|
|
438
|
+
this.invokeListenersUpdate({
|
|
439
|
+
callbackName:
|
|
440
|
+
SharedPlayerCallBacksKeys.onVideoFullscreenPlayerWillPresent,
|
|
441
|
+
});
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
onVideoFullscreenPlayerDidPresent = () => {
|
|
445
|
+
this.invokeListenersUpdate({
|
|
446
|
+
callbackName: SharedPlayerCallBacksKeys.onVideoFullscreenPlayerDidPresent,
|
|
447
|
+
});
|
|
448
|
+
};
|
|
449
|
+
|
|
417
450
|
public invokeListenersUpdate = ({
|
|
418
451
|
callbackName,
|
|
419
452
|
event = {},
|
|
@@ -624,6 +657,7 @@ export class Player {
|
|
|
624
657
|
onPlayerSeekComplete: this.onSeekComplete,
|
|
625
658
|
onVideoEnd: this.onVideoEnd,
|
|
626
659
|
onError: this.onError,
|
|
660
|
+
onVideoError: this.onVideoError,
|
|
627
661
|
onLoad: this.onLoad,
|
|
628
662
|
onPlayerPause: this.onPlayerPause,
|
|
629
663
|
onPlayerResume: this.onPlayerResume,
|
|
@@ -634,6 +668,12 @@ export class Player {
|
|
|
634
668
|
onBufferStart: this.onBufferStart,
|
|
635
669
|
onBufferComplete: this.onBufferComplete,
|
|
636
670
|
|
|
671
|
+
onPlayerClose: this.onPlayerClose,
|
|
672
|
+
onVideoFullscreenPlayerWillPresent: this.onVideoFullscreenPlayerWillPresent,
|
|
673
|
+
onVideoFullscreenPlayerDidPresent: this.onVideoFullscreenPlayerDidPresent,
|
|
674
|
+
onVideoFullscreenPlayerWillDismiss: this.onVideoFullscreenPlayerWillDismiss,
|
|
675
|
+
onVideoFullscreenPlayerDidDismiss: this.onVideoFullscreenPlayerDidDismiss,
|
|
676
|
+
|
|
637
677
|
// Ads Callbacks:
|
|
638
678
|
onAdBegin: this.onAdBegin,
|
|
639
679
|
onAdBreakBegin: this.onAdBreakBegin,
|
|
@@ -652,9 +692,6 @@ export class Player {
|
|
|
652
692
|
play = () => {};
|
|
653
693
|
pause = () => {};
|
|
654
694
|
disableBufferAnimation = (): boolean => true;
|
|
655
|
-
setLanguage = (
|
|
656
|
-
_selected?: QuickBrickPlayer.TextTrack | QuickBrickPlayer.AudioTrack
|
|
657
|
-
) => {};
|
|
658
695
|
|
|
659
696
|
setPlaybackRate = (_rate) => {};
|
|
660
697
|
startSleepTimer = (_timestamp) => {};
|
|
@@ -693,4 +730,8 @@ export class Player {
|
|
|
693
730
|
isFullScreenSupported(): boolean {
|
|
694
731
|
return true;
|
|
695
732
|
}
|
|
733
|
+
|
|
734
|
+
public supportsNativeControls = (): boolean => false;
|
|
735
|
+
public supportNativeCast = (): boolean => false;
|
|
736
|
+
public destroy = () => {};
|
|
696
737
|
}
|
|
@@ -9,21 +9,23 @@ type PlayerFactoryItem = {
|
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
type PlayerFactoryProps = {
|
|
12
|
-
player: any
|
|
13
|
-
playerId: string
|
|
14
|
-
autoplay: boolean
|
|
15
|
-
entry: ZappEntry
|
|
16
|
-
muted: boolean
|
|
17
|
-
playerPluginId: string
|
|
18
|
-
screenConfig: Record<string, any
|
|
19
|
-
playerRole: PlayerRole
|
|
20
|
-
}
|
|
12
|
+
player: any;
|
|
13
|
+
playerId: string;
|
|
14
|
+
autoplay: boolean;
|
|
15
|
+
entry: ZappEntry;
|
|
16
|
+
muted: boolean;
|
|
17
|
+
playerPluginId: string;
|
|
18
|
+
screenConfig: Record<string, any>;
|
|
19
|
+
playerRole: PlayerRole;
|
|
20
|
+
};
|
|
21
21
|
|
|
22
22
|
interface PlayerConstructor {
|
|
23
23
|
new (params: any): Player;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
export const playerFactory = (
|
|
26
|
+
export const playerFactory = (
|
|
27
|
+
config: PlayerFactoryProps
|
|
28
|
+
): PlayerFactoryItem | null => {
|
|
27
29
|
const IDENTIFIER = config?.playerPluginId;
|
|
28
30
|
|
|
29
31
|
if (!IDENTIFIER) {
|
|
@@ -44,7 +46,7 @@ export const playerFactory = (config: PlayerFactoryProps): PlayerFactoryItem | n
|
|
|
44
46
|
|
|
45
47
|
// TODO: Fix type:
|
|
46
48
|
const playerProtocol: PlayerConstructor =
|
|
47
|
-
playerPlugin?.module?.playerProtocol(config?.screenConfig);
|
|
49
|
+
playerPlugin?.module?.playerProtocol(config?.screenConfig, config?.entry);
|
|
48
50
|
|
|
49
51
|
const playerView = (playerProtocol as any)?.Component || null;
|
|
50
52
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { useState, useEffect, useCallback } from "react";
|
|
2
|
+
import { Player } from "../player";
|
|
3
|
+
import { usePlayer } from "../usePlayer";
|
|
4
|
+
import { useThrottle } from "../../../functionUtils";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @param listenerId - A unique identifier for the listener.
|
|
9
|
+
* @param playerId - (Optional) The ID of the player to observe.
|
|
10
|
+
* @returns The current playback time in seconds.
|
|
11
|
+
*/
|
|
12
|
+
export const usePlayerCurrentTime = (
|
|
13
|
+
listenerId: string,
|
|
14
|
+
playerId?: string
|
|
15
|
+
): number | null => {
|
|
16
|
+
const [currentTime, setCurrentTime] = useState<number | null>(null);
|
|
17
|
+
const player: Player = usePlayer(playerId);
|
|
18
|
+
|
|
19
|
+
const updateCurrentTime = useCallback(() => {
|
|
20
|
+
if (player) {
|
|
21
|
+
const newCurrentTime = player.getContentPosition();
|
|
22
|
+
|
|
23
|
+
setCurrentTime((prevTime) =>
|
|
24
|
+
prevTime !== newCurrentTime ? newCurrentTime : prevTime
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
}, [player]);
|
|
28
|
+
|
|
29
|
+
const { throttledFunction: throttledUpdate, cancel } = useThrottle(
|
|
30
|
+
updateCurrentTime,
|
|
31
|
+
1000
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
if (player) {
|
|
36
|
+
throttledUpdate();
|
|
37
|
+
|
|
38
|
+
const listeners = {
|
|
39
|
+
onVideoProgress: throttledUpdate,
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const id = `${listenerId}_player_current_time`;
|
|
43
|
+
|
|
44
|
+
player.addListener({
|
|
45
|
+
id: id,
|
|
46
|
+
listener: listeners,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return () => {
|
|
50
|
+
player.removeListener(id);
|
|
51
|
+
cancel();
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}, [player, listenerId, throttledUpdate, cancel]);
|
|
55
|
+
|
|
56
|
+
return currentTime;
|
|
57
|
+
};
|
|
@@ -2,18 +2,10 @@ import * as R from "ramda";
|
|
|
2
2
|
import { isEmptyOrNil } from "@applicaster/zapp-react-native-utils/cellUtils";
|
|
3
3
|
import { createLogger, utilsLogger } from "../../logger";
|
|
4
4
|
import { Player } from "./player";
|
|
5
|
-
import { findNodeHandle
|
|
6
|
-
import { isApplePlatform } from "../../reactUtils";
|
|
5
|
+
import { findNodeHandle } from "react-native";
|
|
7
6
|
import { PlayerRole } from "./conts";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
QuickBrickPlayerPlugin: isApplePlatform()
|
|
11
|
-
? NativeModules.PlayerModule
|
|
12
|
-
: NativeModules.QuickBrickDefaultPlayerModule,
|
|
13
|
-
KalturaPlayerPlugin: isApplePlatform()
|
|
14
|
-
? NativeModules.KalturaPlayerModule
|
|
15
|
-
: NativeModules.QBKalturaPlayerModule,
|
|
16
|
-
};
|
|
7
|
+
import { toBooleanWithDefaultFalse } from "../../booleanUtils";
|
|
8
|
+
import { RNPlayerManager } from "./nativePlayerManager";
|
|
17
9
|
|
|
18
10
|
const logger = createLogger({
|
|
19
11
|
category: "PlayerNativeController",
|
|
@@ -69,7 +61,7 @@ export class PlayerNative extends Player {
|
|
|
69
61
|
currentPlayerComponent = (): ReactComponent<PlayerProps> =>
|
|
70
62
|
this.playerComponent?.current;
|
|
71
63
|
|
|
72
|
-
getState = () => this.
|
|
64
|
+
getState = () => this.playerState;
|
|
73
65
|
|
|
74
66
|
// TODO: Try to add module interface
|
|
75
67
|
invokeNativeFunction = (funcName: string, ...params: any[]): boolean => {
|
|
@@ -110,7 +102,7 @@ export class PlayerNative extends Player {
|
|
|
110
102
|
return;
|
|
111
103
|
}
|
|
112
104
|
|
|
113
|
-
const newPosition = R.clamp(0,
|
|
105
|
+
const newPosition = R.clamp(0, this.playerState.seekableDuration, position);
|
|
114
106
|
|
|
115
107
|
if (
|
|
116
108
|
!this.invokeNativeFunction(
|
|
@@ -196,10 +188,10 @@ export class PlayerNative extends Player {
|
|
|
196
188
|
|
|
197
189
|
disableBufferAnimation = (): boolean => false;
|
|
198
190
|
|
|
199
|
-
|
|
191
|
+
selectTrack = (
|
|
200
192
|
selected: QuickBrickPlayer.TextTrack | QuickBrickPlayer.AudioTrack
|
|
201
193
|
) => {
|
|
202
|
-
this.currentPlayerComponent()?.["
|
|
194
|
+
this.currentPlayerComponent()?.["selectTrack"]?.(selected);
|
|
203
195
|
};
|
|
204
196
|
|
|
205
197
|
setPlaybackRate = (rate: number) => {
|
|
@@ -291,4 +283,12 @@ export class PlayerNative extends Player {
|
|
|
291
283
|
|
|
292
284
|
return !(isFullScreenAudioPlayer && this.isAudioItem());
|
|
293
285
|
};
|
|
286
|
+
|
|
287
|
+
supportsNativeControls = (): boolean =>
|
|
288
|
+
toBooleanWithDefaultFalse(this.getConfig()?.["supports_native_controls"]);
|
|
289
|
+
|
|
290
|
+
supportNativeCast = (): boolean =>
|
|
291
|
+
toBooleanWithDefaultFalse(
|
|
292
|
+
this.playerPluginId === "quick-brick-player-brightcove"
|
|
293
|
+
);
|
|
294
294
|
}
|
|
@@ -4,6 +4,7 @@ import { useEffect } from "react";
|
|
|
4
4
|
import { playerManager } from "./index";
|
|
5
5
|
import { useValidatePlayerConfig } from "../../playerUtils/useValidatePlayerConfig";
|
|
6
6
|
import { PlayerRole } from "./conts";
|
|
7
|
+
import { isAppleTV } from "@applicaster/zapp-react-native-ui-components/Helpers/Platform";
|
|
7
8
|
|
|
8
9
|
// TODO: Rename to ControllerType
|
|
9
10
|
export const usePlayerControllerSetup = ({
|
|
@@ -34,10 +35,14 @@ export const usePlayerControllerSetup = ({
|
|
|
34
35
|
useValidatePlayerConfig(config);
|
|
35
36
|
|
|
36
37
|
useEffect(() => {
|
|
38
|
+
const newConfig = isAppleTV()
|
|
39
|
+
? { supports_native_controls: true, ...config }
|
|
40
|
+
: config;
|
|
41
|
+
|
|
37
42
|
const newPlayerController = new ControllerType({
|
|
38
43
|
player: ref,
|
|
39
44
|
listener: props as any,
|
|
40
|
-
config,
|
|
45
|
+
config: newConfig,
|
|
41
46
|
playerId,
|
|
42
47
|
entry,
|
|
43
48
|
playerPluginId: pluginId,
|
|
@@ -45,7 +50,7 @@ export const usePlayerControllerSetup = ({
|
|
|
45
50
|
});
|
|
46
51
|
|
|
47
52
|
setPlayerController(newPlayerController);
|
|
48
|
-
}, [playerId, entry?.id]);
|
|
53
|
+
}, [playerId, entry?.id, ref.current]);
|
|
49
54
|
|
|
50
55
|
React.useEffect(() => {
|
|
51
56
|
if (!playerController) {
|
|
@@ -67,6 +72,7 @@ export const usePlayerControllerSetup = ({
|
|
|
67
72
|
|
|
68
73
|
return () => {
|
|
69
74
|
playerManager.unregisterPlayer(playerId);
|
|
75
|
+
playerController.destroy?.();
|
|
70
76
|
};
|
|
71
77
|
}, [playerId, playerController]);
|
|
72
78
|
|
|
@@ -16,24 +16,28 @@ export const usePlayerState = (
|
|
|
16
16
|
listenerId: string,
|
|
17
17
|
playerId?: string
|
|
18
18
|
): PlayerState => {
|
|
19
|
-
const [
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
const [state, setState] = React.useState<PlayerState>({
|
|
20
|
+
currentTime: null,
|
|
21
|
+
duration: null,
|
|
22
|
+
seekableDuration: null,
|
|
23
|
+
isLive: null,
|
|
24
|
+
isPaused: null,
|
|
25
|
+
isBuffering: false,
|
|
26
|
+
isReadyToPlay: false,
|
|
27
|
+
});
|
|
26
28
|
|
|
27
29
|
const player: Player = usePlayer(playerId);
|
|
28
30
|
|
|
29
31
|
const onPlayerChangeState = React.useCallback(() => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
setState({
|
|
33
|
+
currentTime: player.getContentPosition(),
|
|
34
|
+
duration: player.getDuration(),
|
|
35
|
+
seekableDuration: player.getSeekableDuration(),
|
|
36
|
+
isLive: player.isLive(),
|
|
37
|
+
isPaused: player.isPaused(),
|
|
38
|
+
isBuffering: player.isBuffering(),
|
|
39
|
+
isReadyToPlay: player.isReadyToPlay(),
|
|
40
|
+
});
|
|
37
41
|
}, [player]);
|
|
38
42
|
|
|
39
43
|
React.useEffect(() => {
|
|
@@ -55,24 +59,5 @@ export const usePlayerState = (
|
|
|
55
59
|
}
|
|
56
60
|
}, [player]);
|
|
57
61
|
|
|
58
|
-
return
|
|
59
|
-
() => ({
|
|
60
|
-
currentTime,
|
|
61
|
-
duration,
|
|
62
|
-
seekableDuration,
|
|
63
|
-
isLive,
|
|
64
|
-
isPaused,
|
|
65
|
-
isBuffering,
|
|
66
|
-
isReadyToPlay,
|
|
67
|
-
}),
|
|
68
|
-
[
|
|
69
|
-
currentTime,
|
|
70
|
-
duration,
|
|
71
|
-
seekableDuration,
|
|
72
|
-
isLive,
|
|
73
|
-
isPaused,
|
|
74
|
-
isBuffering,
|
|
75
|
-
isReadyToPlay,
|
|
76
|
-
]
|
|
77
|
-
);
|
|
62
|
+
return state;
|
|
78
63
|
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { isFilledArray } from "..";
|
|
2
|
+
|
|
3
|
+
describe("isFilledArray", () => {
|
|
4
|
+
it("non-empty array is not empty", () => {
|
|
5
|
+
const value = [1, 2, 3];
|
|
6
|
+
|
|
7
|
+
expect(isFilledArray(value)).toBe(true);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it("empty array is empty", () => {
|
|
11
|
+
const value = [];
|
|
12
|
+
|
|
13
|
+
expect(isFilledArray(value)).toBe(false);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("number is not array", () => {
|
|
17
|
+
const value = 123;
|
|
18
|
+
|
|
19
|
+
expect(isFilledArray(value)).toBe(false);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("string is not array", () => {
|
|
23
|
+
const value = "vfnjdk";
|
|
24
|
+
|
|
25
|
+
expect(isFilledArray(value)).toBe(false);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("empty string is not array", () => {
|
|
29
|
+
const value = "";
|
|
30
|
+
|
|
31
|
+
expect(isFilledArray(value)).toBe(false);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("NaN is not array", () => {
|
|
35
|
+
const value = "";
|
|
36
|
+
|
|
37
|
+
expect(isFilledArray(value)).toBe(false);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("object is not array", () => {
|
|
41
|
+
const value = { test: 1 };
|
|
42
|
+
|
|
43
|
+
expect(isFilledArray(value)).toBe(false);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("empty object is not array", () => {
|
|
47
|
+
const value = {};
|
|
48
|
+
|
|
49
|
+
expect(isFilledArray(value)).toBe(false);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("undefined is not array", () => {
|
|
53
|
+
const value = undefined;
|
|
54
|
+
|
|
55
|
+
expect(isFilledArray(value)).toBe(false);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("null is not array", () => {
|
|
59
|
+
const value = null;
|
|
60
|
+
|
|
61
|
+
expect(isFilledArray(value)).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
});
|
package/arrayUtils/index.ts
CHANGED
|
@@ -95,3 +95,8 @@ export const makeListOfIndexes = (size: number): number[] =>
|
|
|
95
95
|
export const makeListOf = (value: unknown, size: number): number[] => {
|
|
96
96
|
return Array(size).fill(value);
|
|
97
97
|
};
|
|
98
|
+
|
|
99
|
+
/** Checks if a value is a non-empty array */
|
|
100
|
+
export function isFilledArray(value: unknown): boolean {
|
|
101
|
+
return R.is(Array, value) && R.length(value) > 0;
|
|
102
|
+
}
|
package/booleanUtils/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { is, toLower } from "ramda";
|
|
2
2
|
|
|
3
3
|
export const toBoolean = (value: any): boolean | undefined => {
|
|
4
|
-
if (
|
|
4
|
+
if (is(Boolean, value)) {
|
|
5
5
|
return value;
|
|
6
6
|
}
|
|
7
7
|
|
|
@@ -17,12 +17,12 @@ export const toBooleanWithDefaultTrue = toBooleanWithDefault(true);
|
|
|
17
17
|
|
|
18
18
|
export const toBooleanWithDefaultFalse = toBooleanWithDefault(false);
|
|
19
19
|
|
|
20
|
-
export const isTrue = (value:
|
|
20
|
+
export const isTrue = (value: unknown): boolean => {
|
|
21
21
|
if (value === true) {
|
|
22
22
|
return true;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
if (
|
|
25
|
+
if (is(String, value) && toLower(value) === "true") {
|
|
26
26
|
return true;
|
|
27
27
|
}
|
|
28
28
|
|
|
@@ -24,7 +24,6 @@ import {
|
|
|
24
24
|
EMPTY,
|
|
25
25
|
FALLBACK,
|
|
26
26
|
TRANSFORM,
|
|
27
|
-
defaultColor,
|
|
28
27
|
} from "./fixtures";
|
|
29
28
|
|
|
30
29
|
describe("getKeyForLabel", () => {
|
|
@@ -395,9 +394,7 @@ describe("getColorFromData", () => {
|
|
|
395
394
|
it("should return value directly if valid color", () => {
|
|
396
395
|
const result = getColorFromData({
|
|
397
396
|
data: entry,
|
|
398
|
-
|
|
399
|
-
getValue: getValue(componentStyle),
|
|
400
|
-
defaultColor,
|
|
397
|
+
valueFromLayout: "#123456",
|
|
401
398
|
});
|
|
402
399
|
|
|
403
400
|
expect(result).toBe("#123456");
|
|
@@ -406,9 +403,7 @@ describe("getColorFromData", () => {
|
|
|
406
403
|
it("should return valid rgba color name", () => {
|
|
407
404
|
const result = getColorFromData({
|
|
408
405
|
data: entry,
|
|
409
|
-
|
|
410
|
-
getValue: getValue(componentStyle),
|
|
411
|
-
defaultColor,
|
|
406
|
+
valueFromLayout: "rgba(255, 255, 255, 0)",
|
|
412
407
|
});
|
|
413
408
|
|
|
414
409
|
expect(result).toBe("rgba(255, 255, 255, 0)");
|
|
@@ -417,33 +412,27 @@ describe("getColorFromData", () => {
|
|
|
417
412
|
it("should return path value if path value is set and is valid color", () => {
|
|
418
413
|
const result = getColorFromData({
|
|
419
414
|
data: entry,
|
|
420
|
-
|
|
421
|
-
getValue: getValue(componentStyle),
|
|
422
|
-
defaultColor,
|
|
415
|
+
valueFromLayout: "background_color",
|
|
423
416
|
});
|
|
424
417
|
|
|
425
418
|
expect(result).toBe("#123456");
|
|
426
419
|
});
|
|
427
420
|
|
|
428
|
-
it("should return
|
|
421
|
+
it("should return path value if path value is set, nested and is valid color", () => {
|
|
429
422
|
const result = getColorFromData({
|
|
430
423
|
data: entry,
|
|
431
|
-
|
|
432
|
-
getValue: getValue(componentStyle),
|
|
433
|
-
defaultColor,
|
|
424
|
+
valueFromLayout: "extensions.background_color",
|
|
434
425
|
});
|
|
435
426
|
|
|
436
|
-
expect(result).toBe(
|
|
427
|
+
expect(result).toBe("#123456");
|
|
437
428
|
});
|
|
438
429
|
|
|
439
|
-
it("should return
|
|
430
|
+
it("should return valueFromLayout if path does not exist", () => {
|
|
440
431
|
const result = getColorFromData({
|
|
441
432
|
data: entry,
|
|
442
|
-
|
|
443
|
-
getValue: getValue(componentStyle),
|
|
444
|
-
defaultColor,
|
|
433
|
+
valueFromLayout: "invalid_color",
|
|
445
434
|
});
|
|
446
435
|
|
|
447
|
-
expect(result).toBe(
|
|
436
|
+
expect(result).toBe("invalid_color");
|
|
448
437
|
});
|
|
449
438
|
});
|