@applicaster/zapp-react-native-utils 13.0.0-alpha.9270615060 → 13.0.0-alpha.9433330286
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/appUtils/HooksManager/{Hook.js → Hook.ts} +35 -23
- package/appUtils/HooksManager/__tests__/__snapshots__/hook.test.js.snap +4 -2
- package/appUtils/HooksManager/__tests__/__snapshots__/hooksManager.test.js.snap +693 -0
- package/appUtils/HooksManager/__tests__/hook.test.js +196 -184
- package/appUtils/HooksManager/__tests__/hooksManager.test.js +96 -99
- package/appUtils/HooksManager/{constants.js → constants.ts} +1 -1
- package/appUtils/HooksManager/{index.js → index.ts} +121 -112
- package/appUtils/HooksManager/types.ts +116 -0
- package/appUtils/RiverFocusManager/index.js +17 -12
- package/appUtils/focusManager/treeDataStructure/Tree/index.js +2 -3
- package/appUtils/focusManager/treeDataStructure/Utils/index.js +1 -3
- package/appUtils/{index.js → index.ts} +1 -1
- package/appUtils/keyCodes/__tests__/keyCodes.test.js +3 -3
- package/appUtils/keyCodes/{index.js → index.ts} +2 -0
- package/appUtils/keyCodes/keys/index.ts +3 -0
- package/appUtils/keyCodes/{keys.android.js → keys/keyEventMapper.ts} +0 -19
- package/appUtils/keyCodes/keys/keys.android.ts +18 -0
- package/appUtils/keyCodes/keys/keys.ios.ts +25 -0
- package/appUtils/keyCodes/keys/keys.ts +15 -0
- package/appUtils/keyCodes/{keysByPlatform.js → keys/keysByPlatform.ts} +0 -3
- package/appUtils/keyCodes/keysByPlatform.ts +8 -0
- package/appUtils/platform/platformUtils.ts +0 -14
- package/appUtils/playerManager/player.ts +5 -18
- package/appUtils/playerManager/playerNative.ts +1 -2
- package/appUtils/playerManager/usePlayerControllerSetup.tsx +3 -17
- package/domUtils/{cookieManager.js → cookieManager.ts} +1 -2
- package/functionUtils/index.ts +15 -11
- package/modalState/index.ts +1 -5
- package/navigationUtils/index.ts +14 -5
- package/package.json +2 -2
- package/reactHooks/navigation/index.ts +7 -4
- package/reactHooks/player/__tests__/useAutoSeek.test.tsx +116 -0
- package/reactHooks/player/__tests__/useTapSeek.test.ts +94 -0
- package/reactHooks/player/const.ts +1 -1
- package/reactHooks/player/index.ts +6 -0
- package/reactHooks/player/useAutoSeek.tsx +87 -0
- package/reactHooks/player/useSeek.tsx +66 -0
- package/reactHooks/player/useTapSeek.tsx +58 -0
- package/reactUtils/index.ts +0 -14
- package/appUtils/keyCodes/keys.ios.js +0 -46
- package/appUtils/keyInputHandler/KeyInputHandler.ts +0 -90
- package/appUtils/playerManager/DelayedSeekPlayerWrapper.tsx +0 -180
- package/reactHooks/player/TVSeekControlller/ISeekController.ts +0 -7
- package/reactHooks/player/TVSeekControlller/LongPressSeekController.ts +0 -123
- package/reactHooks/player/TVSeekControlller/TVSeekController.ts +0 -168
- package/reactHooks/player/TVSeekControlller/TapSeekController.ts +0 -73
- /package/appUtils/HooksManager/{logger.js → logger.ts} +0 -0
- /package/appUtils/{directionHelper.js → directionHelper.ts} +0 -0
- /package/appUtils/keyCodes/{androidTVKeys.js → androidTVKeys.ts} +0 -0
- /package/appUtils/keyCodes/{keys.web.js → keys/keys.web.ts} +0 -0
- /package/appUtils/{localizationsHelper.js → localizationsHelper.ts} +0 -0
- /package/domUtils/{logger.js → logger.ts} +0 -0
|
@@ -1,180 +0,0 @@
|
|
|
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
|
-
this.delayedSeekPosition = null;
|
|
13
|
-
|
|
14
|
-
this.wrappedPlayer.addListener({
|
|
15
|
-
id: "Master-Wrapper-Listener",
|
|
16
|
-
listener: this,
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
this.onPlayerSeekComplete = this.onPlayerSeekComplete.bind(this);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
getOverlayObservable = () => {
|
|
23
|
-
return this.wrappedPlayer.getOverlayObservable();
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
getEntryObservable = (): BehaviorSubject<ZappEntry | null> => {
|
|
27
|
-
return this.wrappedPlayer.getEntryObservable();
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
getEntry = (): ZappEntry | null => this.wrappedPlayer.getEntry();
|
|
31
|
-
|
|
32
|
-
getListener = (): QuickBrickPlayer.SharedPlayerCallBacks => {
|
|
33
|
-
return this.wrappedPlayer.getListener();
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
togglePlayPause = () => {
|
|
37
|
-
this.wrappedPlayer.togglePlayPause();
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
selectTrack = (_track) => this.wrappedPlayer.selectTrack(_track);
|
|
41
|
-
|
|
42
|
-
// Implement all default methods by delegating them to wrapped player
|
|
43
|
-
public seekTo = (position: number) => {
|
|
44
|
-
this.wrappedPlayer.seekTo(position);
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
public isPlaying = () => {
|
|
48
|
-
return this.wrappedPlayer.isPlaying();
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
public isPaused = () => {
|
|
52
|
-
return this.wrappedPlayer.isPaused();
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
public play = () => {
|
|
56
|
-
this.wrappedPlayer.play();
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
public pause = () => {
|
|
60
|
-
this.wrappedPlayer.pause();
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
getState = () => {
|
|
64
|
-
const currentState = this.wrappedPlayer.getState();
|
|
65
|
-
|
|
66
|
-
if (this.delayedSeekPosition === null) {
|
|
67
|
-
return currentState;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return {
|
|
71
|
-
...currentState,
|
|
72
|
-
contentPosition: this.delayedSeekPosition,
|
|
73
|
-
isPaused: false,
|
|
74
|
-
seekPosition: this.delayedSeekPosition,
|
|
75
|
-
};
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
forward = (deltaTime: number) => {
|
|
79
|
-
if (this.delayedSeekPosition !== null) {
|
|
80
|
-
this.delayedSeekPosition += deltaTime;
|
|
81
|
-
this.playerState.seekPosition = this.delayedSeekPosition;
|
|
82
|
-
|
|
83
|
-
this.onVideoProgress({
|
|
84
|
-
currentTime: this.playerState.seekPosition,
|
|
85
|
-
duration: this.getDuration(),
|
|
86
|
-
seekableDuration: this.playerState.seekableDuration,
|
|
87
|
-
isLive: this.playerState.isLive,
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
// this.scheduleResumePlayback(DELAYED_SEEK_DELAY, this.delayedSeekPosition);
|
|
91
|
-
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (this.playerState.seekPosition == null) {
|
|
96
|
-
this.playerState.seekPosition = this.playerState.contentPosition;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
this.playerState.seekPosition += deltaTime;
|
|
100
|
-
|
|
101
|
-
this.wrappedPlayer.forward(deltaTime);
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
rewind = (deltaTime: number) => {
|
|
105
|
-
if (this.delayedSeekPosition !== null) {
|
|
106
|
-
this.delayedSeekPosition -= deltaTime;
|
|
107
|
-
|
|
108
|
-
if (this.delayedSeekPosition < 0) {
|
|
109
|
-
this.delayedSeekPosition = 0;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
this.playerState.seekPosition = this.delayedSeekPosition;
|
|
113
|
-
|
|
114
|
-
this.onVideoProgress({
|
|
115
|
-
currentTime: this.playerState.seekPosition,
|
|
116
|
-
duration: this.getDuration(),
|
|
117
|
-
seekableDuration: this.playerState.seekableDuration,
|
|
118
|
-
isLive: this.playerState.isLive,
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
// this.scheduleResumePlayback(DELAYED_SEEK_DELAY, this.delayedSeekPosition);
|
|
122
|
-
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (this.playerState.seekPosition == null) {
|
|
127
|
-
this.playerState.seekPosition = this.playerState.contentPosition;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
this.playerState.seekPosition -= deltaTime;
|
|
131
|
-
this.wrappedPlayer.rewind(deltaTime);
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
public getConfig = () => this.wrappedPlayer.getConfig();
|
|
135
|
-
|
|
136
|
-
// TODO: replace with enum of supported orientations
|
|
137
|
-
isFullScreenSupported(): boolean {
|
|
138
|
-
return this.wrappedPlayer.isFullScreenSupported();
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
public supportsNativeControls = (): boolean =>
|
|
142
|
-
this.wrappedPlayer.supportsNativeControls();
|
|
143
|
-
|
|
144
|
-
public supportNativeCast = (): boolean =>
|
|
145
|
-
this.wrappedPlayer.supportNativeCast();
|
|
146
|
-
|
|
147
|
-
public isInDelayedSeek = () => this.delayedSeekPosition !== null;
|
|
148
|
-
|
|
149
|
-
public enterDelayedSeek() {
|
|
150
|
-
if (this.delayedSeekPosition !== null) {
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if (this.playerState.seekPosition === null) {
|
|
155
|
-
this.playerState.seekPosition = this.playerState.contentPosition;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
this.delayedSeekPosition = this.playerState.seekPosition;
|
|
159
|
-
|
|
160
|
-
if (!this.isPaused()) {
|
|
161
|
-
this.wasPlaying = true;
|
|
162
|
-
this.wrappedPlayer.pause();
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
public exitDelayedSeek() {
|
|
167
|
-
if (this.delayedSeekPosition === null) {
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
this.wrappedPlayer.seekTo(this.delayedSeekPosition);
|
|
172
|
-
|
|
173
|
-
if (this.wasPlaying) {
|
|
174
|
-
this.wasPlaying = false;
|
|
175
|
-
this.wrappedPlayer.play();
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
this.delayedSeekPosition = null;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import { ISeekController } from "./ISeekController";
|
|
2
|
-
import { SEEK_TYPE } from "../const";
|
|
3
|
-
import {
|
|
4
|
-
log_debug,
|
|
5
|
-
log_error,
|
|
6
|
-
log_verbose,
|
|
7
|
-
TVSeekController,
|
|
8
|
-
} from "./TVSeekController";
|
|
9
|
-
import { timer, interval, Subscription } from "rxjs";
|
|
10
|
-
import { switchMap, tap } from "rxjs/operators";
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Example interface for the configuration needed for long-press seeking.
|
|
14
|
-
*/
|
|
15
|
-
interface LongPressConfig {
|
|
16
|
-
LONG_PRESS_THRESHOLD: number; // ms
|
|
17
|
-
TIMER_INTERVAL_MS: number; // ms
|
|
18
|
-
SKIP_INCREMENT_STEP: number; // seconds
|
|
19
|
-
MAX_SKIP_PER_TICK: number; // seconds
|
|
20
|
-
INITIAL_SKIP_AMOUNT: number; // e.g., 10s to start
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export class LongPressSeekController implements ISeekController {
|
|
24
|
-
private pressStartTime = 0;
|
|
25
|
-
private isLongPressActive = false;
|
|
26
|
-
private currentSkipAmount = 0;
|
|
27
|
-
private subscription: Subscription | null = null;
|
|
28
|
-
|
|
29
|
-
constructor(
|
|
30
|
-
private parent: TVSeekController,
|
|
31
|
-
private config: LongPressConfig
|
|
32
|
-
) {}
|
|
33
|
-
|
|
34
|
-
onPressStart(seekType: SEEK_TYPE) {
|
|
35
|
-
this.cleanUpSubscription();
|
|
36
|
-
|
|
37
|
-
log_debug(
|
|
38
|
-
`LongPressSeekController: start long press seek type:${seekType}.`
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
this.parent.currentSeekType = seekType;
|
|
42
|
-
this.parent.pausePlayer();
|
|
43
|
-
|
|
44
|
-
this.pressStartTime = Date.now();
|
|
45
|
-
this.isLongPressActive = true;
|
|
46
|
-
this.currentSkipAmount = this.config.INITIAL_SKIP_AMOUNT;
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* We wait LONG_PRESS_THRESHOLD ms to confirm it's a long press.
|
|
50
|
-
* If it still active, we switch to an interval that emits every TIMER_INTERVAL_MS.
|
|
51
|
-
*/
|
|
52
|
-
const threshold$ = timer(this.config.LONG_PRESS_THRESHOLD).pipe(
|
|
53
|
-
tap(() =>
|
|
54
|
-
log_verbose("LongPressSeekController: Crossed long-press threshold")
|
|
55
|
-
),
|
|
56
|
-
switchMap(() => {
|
|
57
|
-
return interval(this.config.TIMER_INTERVAL_MS).pipe(
|
|
58
|
-
tap(() => {
|
|
59
|
-
this.parent.handleDelayedSeek(
|
|
60
|
-
this.parent.currentSeekType,
|
|
61
|
-
this.currentSkipAmount
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
log_debug(
|
|
65
|
-
`LongPressSeekController: handle delayed seek type: ${seekType} - currentSkipAmount: ${this.currentSkipAmount}.`
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
this.currentSkipAmount = Math.min(
|
|
69
|
-
this.currentSkipAmount + this.config.SKIP_INCREMENT_STEP,
|
|
70
|
-
this.config.MAX_SKIP_PER_TICK
|
|
71
|
-
);
|
|
72
|
-
})
|
|
73
|
-
);
|
|
74
|
-
})
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
this.subscription = threshold$.subscribe({
|
|
78
|
-
complete: () =>
|
|
79
|
-
log_verbose(
|
|
80
|
-
"LongPressSeekController: Long press subscription complete"
|
|
81
|
-
),
|
|
82
|
-
error: (err) =>
|
|
83
|
-
log_error(
|
|
84
|
-
"LongPressSeekController: Long press subscription error",
|
|
85
|
-
err
|
|
86
|
-
),
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
onPressEnd() {
|
|
91
|
-
const pressDuration = Date.now() - this.pressStartTime;
|
|
92
|
-
|
|
93
|
-
if (
|
|
94
|
-
this.isLongPressActive &&
|
|
95
|
-
pressDuration > this.config.LONG_PRESS_THRESHOLD
|
|
96
|
-
) {
|
|
97
|
-
const offset = this.parent.delayedSeekOffset;
|
|
98
|
-
|
|
99
|
-
if (offset) {
|
|
100
|
-
log_debug(
|
|
101
|
-
`LongPressSeekController: onPressEnd for LongPressSeekController, seek offset: ${offset}`
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
this.parent.seekPlayer(offset);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
this.parent.resetAll();
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
reset() {
|
|
112
|
-
this.isLongPressActive = false;
|
|
113
|
-
this.currentSkipAmount = 0;
|
|
114
|
-
this.cleanUpSubscription();
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
private cleanUpSubscription() {
|
|
118
|
-
if (this.subscription) {
|
|
119
|
-
this.subscription.unsubscribe();
|
|
120
|
-
this.subscription = null;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import { BehaviorSubject } from "rxjs";
|
|
2
|
-
import { TapSeekController } from "./TapSeekController";
|
|
3
|
-
import { LongPressSeekController } from "./LongPressSeekController";
|
|
4
|
-
import { playerManager } from "../../../appUtils";
|
|
5
|
-
import { SEEK_TYPE } from "../const";
|
|
6
|
-
import { createLogger } from "../../../logger";
|
|
7
|
-
import { Player } from "../../../appUtils/playerManager/player";
|
|
8
|
-
import { SeekKeyHandlerListener } from "../../../appUtils/keyInputHandler/KeyInputHandler";
|
|
9
|
-
|
|
10
|
-
export const { log_warning, log_debug, log_info, log_error, log_verbose } =
|
|
11
|
-
createLogger({
|
|
12
|
-
category: "General",
|
|
13
|
-
subsystem: "TVSeekController",
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
export class TVSeekController implements SeekKeyHandlerListener {
|
|
17
|
-
// -- SHARED STATE ACROSS STRATEGIES --
|
|
18
|
-
public currentSeekType: SEEK_TYPE | null = null;
|
|
19
|
-
public delayedSeekOffset: number | null = null;
|
|
20
|
-
private controller: Player;
|
|
21
|
-
private delayedSeekProgressSubject = new BehaviorSubject<number | null>(null);
|
|
22
|
-
|
|
23
|
-
// -- STRATEGY INSTANCES --
|
|
24
|
-
private tapSeekController: TapSeekController;
|
|
25
|
-
private longPressSeekController: LongPressSeekController;
|
|
26
|
-
|
|
27
|
-
// Example config for long press
|
|
28
|
-
private config = {
|
|
29
|
-
LONG_PRESS_THRESHOLD: 500,
|
|
30
|
-
TIMER_INTERVAL_MS: 300,
|
|
31
|
-
SKIP_INCREMENT_STEP: 5,
|
|
32
|
-
MAX_SKIP_PER_TICK: 300,
|
|
33
|
-
INITIAL_SKIP_AMOUNT: 10,
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
constructor(controller: Player) {
|
|
37
|
-
this.controller = controller;
|
|
38
|
-
this.tapSeekController = new TapSeekController(this);
|
|
39
|
-
|
|
40
|
-
this.longPressSeekController = new LongPressSeekController(
|
|
41
|
-
this,
|
|
42
|
-
this.config
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
getDelayedSeekProgressObservable() {
|
|
47
|
-
return this.delayedSeekProgressSubject;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
onForwardPress = (): boolean => {
|
|
51
|
-
this.tapSeekController.onPressStart(SEEK_TYPE.FORWARD);
|
|
52
|
-
|
|
53
|
-
return true;
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
onRewindPress = (): boolean => {
|
|
57
|
-
this.tapSeekController.onPressStart(SEEK_TYPE.REWIND);
|
|
58
|
-
|
|
59
|
-
return true;
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
onForwardLongPress = (): boolean => {
|
|
63
|
-
this.longPressSeekController.onPressStart(SEEK_TYPE.FORWARD);
|
|
64
|
-
this.tapSeekController.reset();
|
|
65
|
-
|
|
66
|
-
return true;
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
onRewindLongPress = (): boolean => {
|
|
70
|
-
this.longPressSeekController.onPressStart(SEEK_TYPE.REWIND);
|
|
71
|
-
this.tapSeekController.reset();
|
|
72
|
-
|
|
73
|
-
return true;
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
onForwardPressOut = () => this.longPressSeekController.onPressEnd();
|
|
77
|
-
onRewindPressOut = () => this.longPressSeekController.onPressEnd();
|
|
78
|
-
|
|
79
|
-
getSeekMethods() {
|
|
80
|
-
return {
|
|
81
|
-
onForwardPress: this.onForwardPress,
|
|
82
|
-
onRewindPress: this.onRewindPress,
|
|
83
|
-
onForwardLongPress: this.onForwardLongPress,
|
|
84
|
-
onRewindLongPress: this.onRewindLongPress,
|
|
85
|
-
onForwardPressOut: this.onForwardPressOut,
|
|
86
|
-
onRewindPressOut: this.onRewindPressOut,
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// ---------------------------
|
|
91
|
-
// SHARED METHODS
|
|
92
|
-
// ---------------------------
|
|
93
|
-
|
|
94
|
-
/** Called by either strategy to accumulate offset while paused. */
|
|
95
|
-
handleDelayedSeek(eventType: SEEK_TYPE, skipTime: number) {
|
|
96
|
-
const player = this.getPlayer();
|
|
97
|
-
if (!player) return;
|
|
98
|
-
|
|
99
|
-
// If not previously delayed, we pause the first time
|
|
100
|
-
if (this.delayedSeekOffset === null) {
|
|
101
|
-
this.pausePlayer();
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const newOffset = (this.delayedSeekOffset || 0) + skipTime;
|
|
105
|
-
const currentPos = player.getPosition();
|
|
106
|
-
let targetPos = currentPos;
|
|
107
|
-
|
|
108
|
-
if (eventType === SEEK_TYPE.FORWARD) {
|
|
109
|
-
targetPos = Math.min(currentPos + newOffset, player.getDuration());
|
|
110
|
-
} else {
|
|
111
|
-
targetPos = Math.max(0, currentPos - newOffset);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
this.delayedSeekOffset = newOffset;
|
|
115
|
-
|
|
116
|
-
log_debug(
|
|
117
|
-
`TVSeekController: handleDelayedSeek - targetPos: ${targetPos}, offset: ${newOffset}, skipTime: ${skipTime}`
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
this.delayedSeekProgressSubject.next(targetPos);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
seekPlayer(offset: number) {
|
|
124
|
-
const player = this.getPlayer();
|
|
125
|
-
if (!player || !this.currentSeekType) return;
|
|
126
|
-
player[this.currentSeekType](offset);
|
|
127
|
-
this.playerPlay();
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
playerPlay() {
|
|
131
|
-
const player = this.getPlayer();
|
|
132
|
-
if (!player) return;
|
|
133
|
-
|
|
134
|
-
if (player.isPaused()) {
|
|
135
|
-
player.play();
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
pausePlayer() {
|
|
140
|
-
const player = this.getPlayer();
|
|
141
|
-
if (!player) return;
|
|
142
|
-
player.pause();
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Reset *all* relevant state and strategy controllers
|
|
147
|
-
*/
|
|
148
|
-
resetAll() {
|
|
149
|
-
log_debug("TVSeekController: Reset all states");
|
|
150
|
-
this.currentSeekType = null;
|
|
151
|
-
this.delayedSeekOffset = null;
|
|
152
|
-
|
|
153
|
-
this.delayedSeekProgressSubject.next(null);
|
|
154
|
-
|
|
155
|
-
this.tapSeekController.reset();
|
|
156
|
-
this.longPressSeekController.reset();
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
private getPlayer() {
|
|
160
|
-
const player = playerManager.getInstanceController();
|
|
161
|
-
|
|
162
|
-
if (!player) {
|
|
163
|
-
log_warning("TVSeekController: No valid player controller found");
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return player;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { ISeekController } from "./ISeekController";
|
|
2
|
-
import { SEEK_TYPE, MAX_SEEK_TIME, SKIP_TIME_BASE } from "../const";
|
|
3
|
-
import { log_debug, TVSeekController } from "./TVSeekController";
|
|
4
|
-
|
|
5
|
-
const getSkipTime = (multiplier: number) =>
|
|
6
|
-
Math.min(MAX_SEEK_TIME, SKIP_TIME_BASE * multiplier);
|
|
7
|
-
|
|
8
|
-
export class TapSeekController implements ISeekController {
|
|
9
|
-
private tapSequenceTimeout: any | null = null;
|
|
10
|
-
private seekMultiplier = 1;
|
|
11
|
-
private readonly ON_PRESS_RESET_DURATION = 500; // ms
|
|
12
|
-
|
|
13
|
-
constructor(private parent: TVSeekController) {}
|
|
14
|
-
|
|
15
|
-
onPressStart(seekType: SEEK_TYPE) {
|
|
16
|
-
log_debug(`TapSeekController: start tap seek type: ${seekType}.`);
|
|
17
|
-
|
|
18
|
-
const prevSeekType = this.parent.currentSeekType;
|
|
19
|
-
|
|
20
|
-
if (prevSeekType !== seekType) {
|
|
21
|
-
this.reset();
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
this.parent.currentSeekType = seekType;
|
|
25
|
-
|
|
26
|
-
if (this.tapSequenceTimeout) {
|
|
27
|
-
clearTimeout(this.tapSequenceTimeout);
|
|
28
|
-
this.tapSequenceTimeout = null;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
this.tapSequenceTimeout = setTimeout(() => {
|
|
32
|
-
if (this.parent.delayedSeekOffset !== null) {
|
|
33
|
-
this.parent.seekPlayer(this.parent.delayedSeekOffset);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
log_debug(
|
|
37
|
-
`TapSeekController: Tap sequence timeout fired, delayedSeekOffset: ${this.parent.delayedSeekOffset}.`
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
this.parent.resetAll();
|
|
41
|
-
}, this.ON_PRESS_RESET_DURATION);
|
|
42
|
-
|
|
43
|
-
const clicksBeforePause = 3;
|
|
44
|
-
const skipTime = getSkipTime(this.seekMultiplier);
|
|
45
|
-
|
|
46
|
-
if (this.seekMultiplier > clicksBeforePause) {
|
|
47
|
-
log_debug(
|
|
48
|
-
`TapSeekController: handle delayed seek type:${seekType} - skipTime: ${skipTime}.`
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
this.parent.handleDelayedSeek(seekType, skipTime);
|
|
52
|
-
} else {
|
|
53
|
-
log_debug(
|
|
54
|
-
`TapSeekController: handle seek type:${seekType} - skipTime: ${skipTime}.`
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
this.parent.seekPlayer(skipTime);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
this.seekMultiplier++;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
reset() {
|
|
64
|
-
log_debug("TapSeekController: Reset states");
|
|
65
|
-
|
|
66
|
-
this.seekMultiplier = 1;
|
|
67
|
-
|
|
68
|
-
if (this.tapSequenceTimeout) {
|
|
69
|
-
clearTimeout(this.tapSequenceTimeout);
|
|
70
|
-
this.tapSequenceTimeout = null;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|