@applicaster/zapp-react-native-utils 12.0.0-alpha.5882013252 → 12.0.0-alpha.5895113034
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/actionsExecutor/ActionExecutorContext.tsx +16 -8
- package/analyticsUtils/AnalyticPlayerListener.ts +155 -0
- package/analyticsUtils/AnalyticsEvents/index.ts +6 -0
- package/analyticsUtils/AnalyticsEvents/searchEvents.ts +21 -0
- package/analyticsUtils/PlayerAnalyticsManager.ts +90 -0
- package/analyticsUtils/__tests__/analyticsManager.test.js +75 -73
- package/analyticsUtils/analyticsPlugins.ts +25 -0
- package/analyticsUtils/events.ts +6 -0
- package/analyticsUtils/helpers/hooks.ts +1 -1
- package/analyticsUtils/index.tsx +6 -0
- package/analyticsUtils/{analyticsTracker.ts → playerAnalyticsTracker.ts} +19 -10
- package/appUtils/HooksManager/index.js +3 -1
- package/appUtils/focusManager/treeDataStructure/Utils/index.js +12 -3
- package/appUtils/keyCodes/__tests__/__snapshots__/keyCodes.test.js.snap +1 -1
- package/appUtils/keyCodes/__tests__/keyCodes.test.js +80 -85
- package/appUtils/keyCodes/keys.web.js +1 -0
- package/appUtils/orientationHelper.ts +1 -1
- package/appUtils/playerManager/DelayedSeekPlayerWrapper.tsx +179 -0
- package/appUtils/playerManager/OverlayObserver/OverlaysObserver.ts +53 -0
- package/appUtils/playerManager/conts.ts +5 -0
- package/appUtils/playerManager/index.ts +9 -27
- package/appUtils/playerManager/player.ts +60 -9
- package/appUtils/playerManager/playerFactory.ts +15 -1
- package/appUtils/playerManager/playerNative.ts +39 -3
- package/appUtils/playerManager/usePlayerControllerSetup.tsx +23 -4
- package/appUtils/playerManager/usePlayerState.tsx +13 -1
- package/appUtils/playerManager/usePlayerTitleSummaryOverlay.tsx +50 -0
- package/cellUtils/__tests__/cellUtils.test.ts +48 -0
- package/cellUtils/__tests__/fixtures.ts +13 -0
- package/cellUtils/index.ts +40 -2
- package/dateUtils/index.ts +11 -0
- package/focusManager/index.ts +1 -1
- package/functionUtils/__tests__/__snapshots__/functionUtils.test.js.snap +2 -2
- package/functionUtils/__tests__/functionUtils.test.js +244 -248
- package/headersUtils/index.ts +1 -0
- package/inflatedUrlUtils/index.ts +4 -4
- package/localizationUtils/__tests__/localizationUtils.test.ts +78 -55
- package/localizationUtils/index.ts +13 -19
- package/logger/index.ts +1 -1
- package/manifestUtils/defaultManifestConfigurations/generalContent.js +6 -0
- package/manifestUtils/defaultManifestConfigurations/player.js +10 -1
- package/manifestUtils/index.js +5 -1
- package/manifestUtils/secondaryImage/index.js +18 -15
- package/modalState/index.ts +57 -0
- package/navigationUtils/index.ts +56 -7
- package/numberUtils/index.ts +4 -0
- package/package.json +3 -2
- package/playerUtils/configurationGenerator.ts +11 -1
- package/pluginUtils/index.ts +11 -7
- 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 +11 -2
- package/reactHooks/cell-click/index.ts +4 -4
- package/reactHooks/device/index.ts +0 -1
- package/reactHooks/device/useIsTablet.tsx +28 -3
- package/reactHooks/device/useMemoizedIsTablet.ts +1 -1
- package/reactHooks/device/useOrientation.tsx +3 -1
- package/reactHooks/feed/__tests__/useInflatedUrl.test.ts +18 -3
- package/reactHooks/feed/useInflatedUrl.ts +44 -15
- package/reactHooks/flatList/useLoadNextPageIfNeeded.ts +16 -9
- package/reactHooks/index.ts +2 -0
- package/reactHooks/layout/__tests__/{index.test.js → index.test.tsx} +66 -59
- package/reactHooks/layout/getDeviceInfo/index.ts +4 -2
- package/reactHooks/layout/index.ts +2 -1
- package/reactHooks/layout/types/index.ts +2 -0
- package/reactHooks/layout/useDimensions/helpers/__tests__/getInitialDimensions.native.test.js +11 -16
- package/reactHooks/layout/useDimensions/helpers/__tests__/getInitialDimensions.test.js +12 -14
- package/reactHooks/layout/useDimensions/useDimensions.ts +13 -7
- package/reactHooks/navigation/__mocks__/index.ts +15 -0
- package/reactHooks/navigation/__mocks__/useNavigation.ts +7 -0
- package/reactHooks/navigation/__tests__/index.test.tsx +240 -81
- package/reactHooks/navigation/index.ts +208 -86
- package/reactHooks/player/__tests__/useAutoSeek.test.tsx +8 -1
- package/reactHooks/player/useAutoSeek.tsx +28 -8
- package/reactHooks/player/useSeek.tsx +4 -2
- package/reactHooks/player/useTapSeek.tsx +34 -7
- package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +3 -1
- package/reactHooks/screen/__mocks__/useScreenContext.ts +3 -1
- package/reactHooks/screen/index.ts +2 -0
- package/reactHooks/screen/useScreenContext.ts +5 -4
- package/reactHooks/screen/useScreenData.ts +1 -1
- package/reactHooks/screen/useTargetScreenData.ts +7 -0
- package/reactHooks/state/useRivers.ts +3 -1
- package/reactHooks/useListenEventBusEvent.ts +1 -4
- package/reactHooks/videoModal/hooks/useVideoModalScreenData.tsx +10 -9
- package/riverComponetsMeasurementProvider/index.tsx +2 -2
- package/stringUtils/index.ts +5 -0
- package/testUtils/getByTestId.ts +14 -0
- package/testUtils/index.tsx +38 -23
- package/types.ts +4 -0
- package/reactHooks/device/useIsTablet.android.tsx +0 -14
- package/reactHooks/device/useIsTablet.ios.tsx +0 -7
- package/reactHooks/device/useIsTablet.web.tsx +0 -3
|
@@ -187,11 +187,20 @@ export function getTargetInDirection(
|
|
|
187
187
|
return null;
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
+
const orientationDistance = measureDistance(
|
|
191
|
+
direction,
|
|
192
|
+
comparisonRect,
|
|
193
|
+
componentRect
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
const euclidDistance = measureEuclidianDistanceToCenter(
|
|
197
|
+
comparisonRect,
|
|
198
|
+
componentRect
|
|
199
|
+
);
|
|
200
|
+
|
|
190
201
|
return {
|
|
191
202
|
distance:
|
|
192
|
-
|
|
193
|
-
measureEuclidianDistanceToCenter(comparisonRect, componentRect) /
|
|
194
|
-
10000,
|
|
203
|
+
orientationDistance > 0 ? euclidDistance : orientationDistance,
|
|
195
204
|
target,
|
|
196
205
|
};
|
|
197
206
|
})
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
const { Platform } = require("react-native");
|
|
2
|
+
|
|
3
|
+
Platform.OS = "web";
|
|
4
|
+
|
|
1
5
|
import { directionHelper } from "../../directionHelper";
|
|
2
6
|
|
|
3
7
|
const globalTizen = {
|
|
@@ -6,105 +10,96 @@ const globalTizen = {
|
|
|
6
10
|
},
|
|
7
11
|
};
|
|
8
12
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
describe("keyCode", () => {
|
|
14
|
-
const { keyCode } = require("../index");
|
|
15
|
-
const { KEYS } = require("../keys.web");
|
|
16
|
-
|
|
17
|
-
it("returns an object for a given key event", () => {
|
|
18
|
-
expect(keyCode(KEYS.Enter)).toMatchSnapshot();
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it("has a matcher method for a single key", () => {
|
|
22
|
-
expect(keyCode(KEYS.Enter).matches("Enter")).toBeTruthy();
|
|
23
|
-
expect(keyCode(KEYS.Enter).matches(KEYS.Enter)).toBeTruthy();
|
|
24
|
-
expect(keyCode(KEYS.Back).matches("Enter")).toBeFalsy();
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it("has matcher for multiple keys", () => {
|
|
28
|
-
expect(
|
|
29
|
-
keyCode(KEYS.Enter).matchesAny("Enter", "Back", "ArrowUp")
|
|
30
|
-
).toBeTruthy();
|
|
13
|
+
describe("keyCodes", () => {
|
|
14
|
+
describe("keyCode", () => {
|
|
15
|
+
const { keyCode } = require("..");
|
|
16
|
+
const { KEYS } = require("../keys.web");
|
|
31
17
|
|
|
32
|
-
|
|
33
|
-
keyCode(KEYS.Enter).
|
|
34
|
-
)
|
|
35
|
-
});
|
|
18
|
+
it("returns an object for a given key event", () => {
|
|
19
|
+
expect(keyCode(KEYS.Enter)).toMatchSnapshot();
|
|
20
|
+
});
|
|
36
21
|
|
|
37
|
-
|
|
38
|
-
|
|
22
|
+
it("has a matcher method for a single key", () => {
|
|
23
|
+
expect(keyCode(KEYS.Enter).matches("Enter")).toBeTruthy();
|
|
24
|
+
expect(keyCode(KEYS.Enter).matches(KEYS.Enter)).toBeTruthy();
|
|
25
|
+
expect(keyCode(KEYS.Back).matches("Enter")).toBeFalsy();
|
|
26
|
+
});
|
|
39
27
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
28
|
+
it("has matcher for multiple keys", () => {
|
|
29
|
+
expect(
|
|
30
|
+
keyCode(KEYS.Enter).matchesAny("Enter", "Back", "ArrowUp")
|
|
31
|
+
).toBeTruthy();
|
|
44
32
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
33
|
+
expect(
|
|
34
|
+
keyCode(KEYS.Enter).matchesAny("Back", "ArrowUp", "ArrowDown")
|
|
35
|
+
).toBeFalsy();
|
|
48
36
|
});
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
37
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
return { Platform: { OS: "samsung_tv" } };
|
|
55
|
-
});
|
|
38
|
+
it("returns the direction if it matches an arrow key", () => {
|
|
39
|
+
expect(keyCode(KEYS.Enter).direction()).toBe(null);
|
|
56
40
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
41
|
+
expect(keyCode(KEYS.ArrowDown).direction()).toEqual(
|
|
42
|
+
directionHelper(KEYS.ArrowDown)
|
|
43
|
+
);
|
|
44
|
+
});
|
|
61
45
|
|
|
62
|
-
|
|
63
|
-
|
|
46
|
+
describe("in web env", () => {
|
|
47
|
+
it("uses the proper keyCode for the environment", () => {
|
|
48
|
+
expect(keyCode({ keyCode: 13 }).matches(KEYS.Enter)).toBeTruthy();
|
|
49
|
+
});
|
|
50
|
+
});
|
|
64
51
|
});
|
|
65
52
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
53
|
+
describe("in Tizen Env", () => {
|
|
54
|
+
beforeEach(() => {
|
|
55
|
+
jest.resetModules();
|
|
56
|
+
global.tizen = globalTizen;
|
|
57
|
+
});
|
|
69
58
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
"MediaPlayPause",
|
|
74
|
-
"MediaPause",
|
|
75
|
-
"MediaFastForward",
|
|
76
|
-
"MediaRewind",
|
|
77
|
-
"MediaStop",
|
|
78
|
-
"Exit",
|
|
79
|
-
"0",
|
|
80
|
-
"1",
|
|
81
|
-
"2",
|
|
82
|
-
"3",
|
|
83
|
-
"4",
|
|
84
|
-
"5",
|
|
85
|
-
"6",
|
|
86
|
-
"7",
|
|
87
|
-
"8",
|
|
88
|
-
"9",
|
|
89
|
-
]);
|
|
90
|
-
|
|
91
|
-
expect(keyCode({ keyCode: 10009 }).matches(KEYS.Back)).toBeTruthy();
|
|
92
|
-
});
|
|
93
|
-
});
|
|
59
|
+
afterEach(() => {
|
|
60
|
+
global.tizen = undefined;
|
|
61
|
+
});
|
|
94
62
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
63
|
+
it("uses the proper keyCode for the environment", () => {
|
|
64
|
+
Platform.OS = "samsung_tv";
|
|
65
|
+
const { keyCode } = require("../");
|
|
66
|
+
const { KEYS } = require("../keys.web");
|
|
67
|
+
|
|
68
|
+
expect(globalTizen.tvinputdevice.registerKeyBatch).toHaveBeenCalledWith([
|
|
69
|
+
"MediaPlay",
|
|
70
|
+
"MediaPlayPause",
|
|
71
|
+
"MediaPause",
|
|
72
|
+
"MediaFastForward",
|
|
73
|
+
"MediaRewind",
|
|
74
|
+
"MediaStop",
|
|
75
|
+
"Exit",
|
|
76
|
+
"0",
|
|
77
|
+
"1",
|
|
78
|
+
"2",
|
|
79
|
+
"3",
|
|
80
|
+
"4",
|
|
81
|
+
"5",
|
|
82
|
+
"6",
|
|
83
|
+
"7",
|
|
84
|
+
"8",
|
|
85
|
+
"9",
|
|
86
|
+
]);
|
|
87
|
+
|
|
88
|
+
expect(keyCode({ keyCode: 10009 }).matches(KEYS.Back)).toBeTruthy();
|
|
89
|
+
});
|
|
98
90
|
});
|
|
99
91
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
92
|
+
describe("in WebOS Env", () => {
|
|
93
|
+
beforeEach(() => {
|
|
94
|
+
jest.resetModules();
|
|
95
|
+
});
|
|
103
96
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
97
|
+
it("uses the proper keyCode for the environment", () => {
|
|
98
|
+
Platform.OS = "lg_tv";
|
|
99
|
+
const { keyCode } = require("..");
|
|
100
|
+
const { KEYS } = require("../keys.web");
|
|
101
|
+
// Back is reserved on LG
|
|
102
|
+
expect(keyCode({ keyCode: 417 }).matches(KEYS.Forward)).toBeTruthy();
|
|
103
|
+
});
|
|
109
104
|
});
|
|
110
105
|
});
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import * as ReactNative from "react-native";
|
|
3
3
|
import { isTV, platformSelect } from "../reactUtils";
|
|
4
4
|
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
5
|
+
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
5
6
|
|
|
6
7
|
import {
|
|
7
8
|
QUICK_BRICK_EVENTS,
|
|
@@ -9,7 +10,6 @@ import {
|
|
|
9
10
|
sendQuickBrickEvent,
|
|
10
11
|
} from "@applicaster/zapp-react-native-bridge/QuickBrick";
|
|
11
12
|
import { utilsLogger } from "../logger";
|
|
12
|
-
import { useIsTablet } from "../reactHooks/device/useIsTablet";
|
|
13
13
|
|
|
14
14
|
const { DeviceEventEmitter, NativeModules, NativeEventEmitter } = ReactNative;
|
|
15
15
|
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { Player } from "./player";
|
|
2
|
+
import { BehaviorSubject } from "rxjs";
|
|
3
|
+
|
|
4
|
+
export class DelayedSeekPlayerWrapper extends Player {
|
|
5
|
+
private wrappedPlayer: Player;
|
|
6
|
+
private delayedSeekPosition: number;
|
|
7
|
+
private wasPlaying: boolean;
|
|
8
|
+
|
|
9
|
+
constructor(props, player: Player) {
|
|
10
|
+
super(props);
|
|
11
|
+
this.wrappedPlayer = player;
|
|
12
|
+
|
|
13
|
+
this.wrappedPlayer.addListener({
|
|
14
|
+
id: "Master-Wrapper-Listener",
|
|
15
|
+
listener: this,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
this.onPlayerSeekComplete = this.onPlayerSeekComplete.bind(this);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
getOverlayObservable = () => {
|
|
22
|
+
return this.wrappedPlayer.getOverlayObservable();
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
getEntryObservable = (): BehaviorSubject<ZappEntry | null> => {
|
|
26
|
+
return this.wrappedPlayer.getEntryObservable();
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
getEntry = (): ZappEntry | null => this.wrappedPlayer.getEntry();
|
|
30
|
+
|
|
31
|
+
getListener = (): QuickBrickPlayer.SharedPlayerCallBacks => {
|
|
32
|
+
return this.wrappedPlayer.getListener();
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
togglePlayPause = () => {
|
|
36
|
+
this.wrappedPlayer.togglePlayPause();
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
selectTrack = (_track) => this.wrappedPlayer.selectTrack(_track);
|
|
40
|
+
|
|
41
|
+
// Implement all default methods by delegating them to wrapped player
|
|
42
|
+
public seekTo = (position: number) => {
|
|
43
|
+
this.wrappedPlayer.seekTo(position);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
public isPlaying = () => {
|
|
47
|
+
return this.wrappedPlayer.isPlaying();
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
public isPaused = () => {
|
|
51
|
+
return this.wrappedPlayer.isPaused();
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
public play = () => {
|
|
55
|
+
this.wrappedPlayer.play();
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
public pause = () => {
|
|
59
|
+
this.wrappedPlayer.pause();
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
getState = () => {
|
|
63
|
+
const currentState = this.wrappedPlayer.getState();
|
|
64
|
+
|
|
65
|
+
if (this.delayedSeekPosition === null) {
|
|
66
|
+
return currentState;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
...currentState,
|
|
71
|
+
contentPosition: this.delayedSeekPosition,
|
|
72
|
+
isPaused: false,
|
|
73
|
+
seekPosition: this.delayedSeekPosition,
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
forward = (deltaTime: number) => {
|
|
78
|
+
if (this.delayedSeekPosition !== null) {
|
|
79
|
+
this.delayedSeekPosition += deltaTime;
|
|
80
|
+
this.playerState.seekPosition = this.delayedSeekPosition;
|
|
81
|
+
|
|
82
|
+
this.onVideoProgress({
|
|
83
|
+
currentTime: this.playerState.seekPosition,
|
|
84
|
+
duration: this.getDuration(),
|
|
85
|
+
seekableDuration: this.playerState.seekableDuration,
|
|
86
|
+
isLive: this.playerState.isLive,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// this.scheduleResumePlayback(DELAYED_SEEK_DELAY, this.delayedSeekPosition);
|
|
90
|
+
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (this.playerState.seekPosition == null) {
|
|
95
|
+
this.playerState.seekPosition = this.playerState.contentPosition;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
this.playerState.seekPosition += deltaTime;
|
|
99
|
+
|
|
100
|
+
this.wrappedPlayer.forward(deltaTime);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
rewind = (deltaTime: number) => {
|
|
104
|
+
if (this.delayedSeekPosition !== null) {
|
|
105
|
+
this.delayedSeekPosition -= deltaTime;
|
|
106
|
+
|
|
107
|
+
if (this.delayedSeekPosition < 0) {
|
|
108
|
+
this.delayedSeekPosition = 0;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
this.playerState.seekPosition = this.delayedSeekPosition;
|
|
112
|
+
|
|
113
|
+
this.onVideoProgress({
|
|
114
|
+
currentTime: this.playerState.seekPosition,
|
|
115
|
+
duration: this.getDuration(),
|
|
116
|
+
seekableDuration: this.playerState.seekableDuration,
|
|
117
|
+
isLive: this.playerState.isLive,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// this.scheduleResumePlayback(DELAYED_SEEK_DELAY, this.delayedSeekPosition);
|
|
121
|
+
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (this.playerState.seekPosition == null) {
|
|
126
|
+
this.playerState.seekPosition = this.playerState.contentPosition;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
this.playerState.seekPosition -= deltaTime;
|
|
130
|
+
this.wrappedPlayer.rewind(deltaTime);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
public getConfig = () => this.wrappedPlayer.getConfig();
|
|
134
|
+
|
|
135
|
+
// TODO: replace with enum of supported orientations
|
|
136
|
+
isFullScreenSupported(): boolean {
|
|
137
|
+
return this.wrappedPlayer.isFullScreenSupported();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
public supportsNativeControls = (): boolean =>
|
|
141
|
+
this.wrappedPlayer.supportsNativeControls();
|
|
142
|
+
|
|
143
|
+
public supportNativeCast = (): boolean =>
|
|
144
|
+
this.wrappedPlayer.supportNativeCast();
|
|
145
|
+
|
|
146
|
+
public isInDelayedSeek = () => this.delayedSeekPosition !== null;
|
|
147
|
+
|
|
148
|
+
public enterDelayedSeek() {
|
|
149
|
+
if (this.delayedSeekPosition !== null) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (this.playerState.seekPosition === null) {
|
|
154
|
+
this.playerState.seekPosition = this.playerState.contentPosition;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
this.delayedSeekPosition = this.playerState.seekPosition;
|
|
158
|
+
|
|
159
|
+
if (!this.isPaused()) {
|
|
160
|
+
this.wasPlaying = true;
|
|
161
|
+
this.wrappedPlayer.pause();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
public exitDelayedSeek() {
|
|
166
|
+
if (this.delayedSeekPosition === null) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
this.wrappedPlayer.seekTo(this.delayedSeekPosition);
|
|
171
|
+
|
|
172
|
+
if (this.wasPlaying) {
|
|
173
|
+
this.wasPlaying = false;
|
|
174
|
+
this.wrappedPlayer.play();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
this.delayedSeekPosition = null;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
@@ -41,6 +41,11 @@ export type ChapterMarkerEvent = {
|
|
|
41
41
|
actions: ActionChapter[];
|
|
42
42
|
};
|
|
43
43
|
|
|
44
|
+
export type TitleSummaryEvent = {
|
|
45
|
+
title: string | number;
|
|
46
|
+
summary: string | number;
|
|
47
|
+
};
|
|
48
|
+
|
|
44
49
|
type ChapterMarkersObserverProps = {
|
|
45
50
|
player: Player;
|
|
46
51
|
};
|
|
@@ -60,6 +65,11 @@ export type PlayNextState = PlayNextConfig & {
|
|
|
60
65
|
export class OverlaysObserver {
|
|
61
66
|
readonly chapterSubject: BehaviorSubject<ChapterMarkerEvent>;
|
|
62
67
|
private playNextSubject: BehaviorSubject<PlayNextState>;
|
|
68
|
+
private titleSummarySubject: BehaviorSubject<TitleSummaryEvent>;
|
|
69
|
+
private feedUrl: string;
|
|
70
|
+
private reloadData: () => void;
|
|
71
|
+
private updateTitleAndDescription: (data: any) => void;
|
|
72
|
+
private feedDataInterval: any;
|
|
63
73
|
private releasePlayerObserver?: () => void;
|
|
64
74
|
readonly entry: ZappEntry;
|
|
65
75
|
private chapterMarkerEvents: ChapterMarkerEvent[];
|
|
@@ -70,14 +80,55 @@ export class OverlaysObserver {
|
|
|
70
80
|
constructor({ player }: ChapterMarkersObserverProps) {
|
|
71
81
|
this.chapterSubject = new BehaviorSubject(null);
|
|
72
82
|
this.playNextSubject = new BehaviorSubject(null);
|
|
83
|
+
|
|
84
|
+
this.titleSummarySubject = new BehaviorSubject<TitleSummaryEvent>({
|
|
85
|
+
title: player.getEntry()?.title || "",
|
|
86
|
+
summary: player.getEntry()?.summary || "",
|
|
87
|
+
});
|
|
88
|
+
|
|
73
89
|
this.entry = player.getEntry();
|
|
74
90
|
this.player = player;
|
|
75
91
|
|
|
76
92
|
this.chapterMarkerEvents = this.prepareChapterMarkers();
|
|
77
93
|
this.releasePlayerObserver = this.subscribeToPlayerEvents();
|
|
94
|
+
this.feedUrl = "";
|
|
95
|
+
this.reloadData = () => {};
|
|
96
|
+
this.updateTitleAndDescription = () => {};
|
|
97
|
+
this.feedDataInterval = null;
|
|
78
98
|
void this.preparePlayNext();
|
|
79
99
|
}
|
|
80
100
|
|
|
101
|
+
private setupFeedDataInterval(interval: number) {
|
|
102
|
+
if (this.feedUrl && this.reloadData && this.updateTitleAndDescription) {
|
|
103
|
+
this.feedDataInterval = setInterval(() => {
|
|
104
|
+
this.reloadData();
|
|
105
|
+
}, interval * 1000);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
public clearFeedDataInterval() {
|
|
110
|
+
if (this.feedDataInterval) {
|
|
111
|
+
clearInterval(this.feedDataInterval);
|
|
112
|
+
this.feedDataInterval = null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
public setFeedDataHandlers(
|
|
117
|
+
feedUrl: string,
|
|
118
|
+
reloadData: () => void,
|
|
119
|
+
interval: number,
|
|
120
|
+
updateTitleAndDescription: (data: any) => void
|
|
121
|
+
) {
|
|
122
|
+
this.feedUrl = feedUrl;
|
|
123
|
+
this.reloadData = reloadData;
|
|
124
|
+
this.updateTitleAndDescription = updateTitleAndDescription;
|
|
125
|
+
this.setupFeedDataInterval(interval);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
public getTitleSummaryObservable(): Observable<TitleSummaryEvent> {
|
|
129
|
+
return this.titleSummarySubject.asObservable().pipe(distinctUntilChanged());
|
|
130
|
+
}
|
|
131
|
+
|
|
81
132
|
handleUserCancelPlayNext = () => {
|
|
82
133
|
this.isCanceledByUser = true;
|
|
83
134
|
this.playNextSubject.next(null);
|
|
@@ -281,7 +332,9 @@ export class OverlaysObserver {
|
|
|
281
332
|
onPlayerClose = () => {
|
|
282
333
|
this.chapterSubject.complete();
|
|
283
334
|
this.playNextSubject.complete();
|
|
335
|
+
this.titleSummarySubject.complete();
|
|
284
336
|
this.releasePlayerObserver?.();
|
|
337
|
+
this.clearFeedDataInterval();
|
|
285
338
|
this.releasePlayerObserver = null;
|
|
286
339
|
};
|
|
287
340
|
|
|
@@ -20,6 +20,11 @@ export enum SharedPlayerCallBacksKeys {
|
|
|
20
20
|
OnPlayerMute = "onPlayerMute",
|
|
21
21
|
OnPlayerUnmute = "onPlayerUnmute",
|
|
22
22
|
|
|
23
|
+
onVideoFullscreenPlayerDidDismiss = "onVideoFullscreenPlayerDidDismiss",
|
|
24
|
+
onVideoFullscreenPlayerDidPresent = "onVideoFullscreenPlayerDidPresent",
|
|
25
|
+
onVideoFullscreenPlayerWillDismiss = "onVideoFullscreenPlayerWillDismiss",
|
|
26
|
+
onVideoFullscreenPlayerWillPresent = "onVideoFullscreenPlayerWillPresent",
|
|
27
|
+
|
|
23
28
|
OnAdBegin = "onAdBegin",
|
|
24
29
|
OnAdBreakBegin = "onAdBreakBegin",
|
|
25
30
|
OnAdBreakEnd = "onAdBreakEnd",
|
|
@@ -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,
|
|
@@ -36,7 +35,10 @@ export interface PlayerLifecycleListener {
|
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
type PlayersMap = {
|
|
39
|
-
[id: string]: {
|
|
38
|
+
[id: string]: {
|
|
39
|
+
player: Player;
|
|
40
|
+
isInViewport: boolean;
|
|
41
|
+
};
|
|
40
42
|
};
|
|
41
43
|
|
|
42
44
|
export class PlayerManager {
|
|
@@ -45,7 +47,6 @@ export class PlayerManager {
|
|
|
45
47
|
private playersMap: PlayersMap = {};
|
|
46
48
|
private manager = subscriber();
|
|
47
49
|
private castingReceiver: Player;
|
|
48
|
-
private analyticsTracker: AnalyticsTracker;
|
|
49
50
|
private lifecycleListeners: PlayerLifecycleListener[] = [];
|
|
50
51
|
|
|
51
52
|
public static getInstance() {
|
|
@@ -56,7 +57,7 @@ export class PlayerManager {
|
|
|
56
57
|
return PlayerManager.instance;
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
public getActivePlayerId = ():
|
|
60
|
+
public getActivePlayerId = (): string | null => {
|
|
60
61
|
return this.activePlayerId;
|
|
61
62
|
};
|
|
62
63
|
|
|
@@ -101,7 +102,10 @@ export class PlayerManager {
|
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
private addPlayer = (id: string, player: Player) => {
|
|
104
|
-
this.playersMap[id] = {
|
|
105
|
+
this.playersMap[id] = {
|
|
106
|
+
player: player,
|
|
107
|
+
isInViewport: false,
|
|
108
|
+
};
|
|
105
109
|
};
|
|
106
110
|
|
|
107
111
|
public isPlayerRegistered = (id: string) => !!this.playersMap[id];
|
|
@@ -246,28 +250,6 @@ export class PlayerManager {
|
|
|
246
250
|
this.castingReceiver = null;
|
|
247
251
|
}
|
|
248
252
|
|
|
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
253
|
/**
|
|
272
254
|
* Method retrieves the instantiated player instance controller
|
|
273
255
|
* Instance controller exposes methods like getContentDuration, getContentPosision
|