@applicaster/zapp-react-native-utils 13.0.0-alpha.7210171818 → 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 -106
- package/reactHooks/player/TVSeekControlller/TVSeekController.ts +0 -199
- package/reactHooks/player/TVSeekControlller/TapSeekController.ts +0 -75
- /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,106 +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 { interval, Subscription } from "rxjs";
|
|
10
|
-
import { 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
|
-
onStartSeek(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
|
-
// Start the interval immediately without waiting for a threshold.
|
|
49
|
-
this.subscription = interval(this.config.TIMER_INTERVAL_MS).pipe(
|
|
50
|
-
tap(() => {
|
|
51
|
-
this.parent.handleDelayedSeek(
|
|
52
|
-
this.parent.currentSeekType,
|
|
53
|
-
this.currentSkipAmount
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
log_debug(
|
|
57
|
-
`LongPressSeekController: handle delayed seek type: ${seekType} - currentSkipAmount: ${this.currentSkipAmount}.`
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
this.currentSkipAmount = Math.min(
|
|
61
|
-
this.currentSkipAmount + this.config.SKIP_INCREMENT_STEP,
|
|
62
|
-
this.config.MAX_SKIP_PER_TICK
|
|
63
|
-
);
|
|
64
|
-
})
|
|
65
|
-
).subscribe({
|
|
66
|
-
complete: () =>
|
|
67
|
-
log_verbose("LongPressSeekController: Long press subscription complete"),
|
|
68
|
-
error: (err) =>
|
|
69
|
-
log_error("LongPressSeekController: Long press subscription error", err),
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
onSeekEnd() {
|
|
74
|
-
const pressDuration = Date.now() - this.pressStartTime;
|
|
75
|
-
|
|
76
|
-
if (
|
|
77
|
-
this.isLongPressActive &&
|
|
78
|
-
pressDuration > this.config.LONG_PRESS_THRESHOLD
|
|
79
|
-
) {
|
|
80
|
-
const offset = this.parent.delayedSeekOffset;
|
|
81
|
-
|
|
82
|
-
if (offset) {
|
|
83
|
-
log_debug(
|
|
84
|
-
`LongPressSeekController: onPressEnd for LongPressSeekController, seek offset: ${offset}`
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
this.parent.seekPlayer(offset);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
this.parent.resetAll();
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
reset() {
|
|
95
|
-
this.isLongPressActive = false;
|
|
96
|
-
this.currentSkipAmount = 0;
|
|
97
|
-
this.cleanUpSubscription();
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
private cleanUpSubscription() {
|
|
101
|
-
if (this.subscription) {
|
|
102
|
-
this.subscription.unsubscribe();
|
|
103
|
-
this.subscription = null;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
@@ -1,199 +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
|
-
import { ISeekController } from "./ISeekController";
|
|
10
|
-
|
|
11
|
-
export const { log_warning, log_debug, log_info, log_error, log_verbose } =
|
|
12
|
-
createLogger({
|
|
13
|
-
category: "General",
|
|
14
|
-
subsystem: "TVSeekController",
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
export enum SEEK_STRATEGY {
|
|
18
|
-
TAP_SEEK = "TAP_SEEK",
|
|
19
|
-
AUTO_SEEK = "AUTO_SEEK",
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export class TVSeekController implements SeekKeyHandlerListener {
|
|
23
|
-
// -- SHARED STATE ACROSS STRATEGIES --
|
|
24
|
-
public currentSeekType: SEEK_TYPE | null = null;
|
|
25
|
-
public delayedSeekOffset: number | null = null;
|
|
26
|
-
private controller: Player;
|
|
27
|
-
private delayedSeekProgressSubject = new BehaviorSubject<number | null>(null);
|
|
28
|
-
|
|
29
|
-
private currentSeekController: ISeekController;
|
|
30
|
-
|
|
31
|
-
// -- STRATEGY INSTANCES --
|
|
32
|
-
private tapSeekController: TapSeekController;
|
|
33
|
-
private longPressSeekController: LongPressSeekController;
|
|
34
|
-
private longPressThresholdTimeout: any | null = null;
|
|
35
|
-
|
|
36
|
-
// Example config for long press
|
|
37
|
-
private config = {
|
|
38
|
-
LONG_PRESS_THRESHOLD: 500,
|
|
39
|
-
TIMER_INTERVAL_MS: 300,
|
|
40
|
-
SKIP_INCREMENT_STEP: 5,
|
|
41
|
-
MAX_SKIP_PER_TICK: 300,
|
|
42
|
-
INITIAL_SKIP_AMOUNT: 10,
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
constructor(controller: Player) {
|
|
46
|
-
this.controller = controller;
|
|
47
|
-
this.tapSeekController = new TapSeekController(this);
|
|
48
|
-
|
|
49
|
-
this.longPressSeekController = new LongPressSeekController(
|
|
50
|
-
this,
|
|
51
|
-
this.config
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
getDelayedSeekProgressObservable = () => {
|
|
56
|
-
return this.delayedSeekProgressSubject;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
setStrategy = (seekStrategy: SEEK_STRATEGY) => {
|
|
60
|
-
switch (seekStrategy) {
|
|
61
|
-
case SEEK_STRATEGY.TAP_SEEK:
|
|
62
|
-
clearTimeout(this.longPressThresholdTimeout);
|
|
63
|
-
this.longPressThresholdTimeout = null;
|
|
64
|
-
this.currentSeekController = this.tapSeekController;
|
|
65
|
-
|
|
66
|
-
break;
|
|
67
|
-
case SEEK_STRATEGY.AUTO_SEEK:
|
|
68
|
-
this.currentSeekController.reset();
|
|
69
|
-
this.currentSeekController = this.longPressSeekController;
|
|
70
|
-
break;
|
|
71
|
-
default:
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
handleStartSeek = (seekType: SEEK_TYPE) => {
|
|
76
|
-
this.setStrategy(SEEK_STRATEGY.TAP_SEEK);
|
|
77
|
-
this.currentSeekController.onStartSeek(seekType);
|
|
78
|
-
log_verbose(`handleStartSeek: TAP seekType: ${seekType}`);
|
|
79
|
-
|
|
80
|
-
this.longPressThresholdTimeout = setTimeout(() => {
|
|
81
|
-
log_verbose(`handleStartSeek: longPressThresholdTimeout: TIMEOUT, START AUTO_SEEK seekType: ${seekType}`);
|
|
82
|
-
this.setStrategy(SEEK_STRATEGY.AUTO_SEEK);
|
|
83
|
-
this.currentSeekController.onStartSeek(seekType);
|
|
84
|
-
}, this.config.LONG_PRESS_THRESHOLD);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
onForwardPress = (): boolean => {
|
|
88
|
-
this.handleStartSeek(SEEK_TYPE.FORWARD);
|
|
89
|
-
|
|
90
|
-
return true;
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
onRewindPress = (): boolean => {
|
|
94
|
-
this.handleStartSeek(SEEK_TYPE.REWIND);
|
|
95
|
-
|
|
96
|
-
return true;
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
onSeekEnd = () => {
|
|
100
|
-
this.currentSeekController.onSeekEnd();
|
|
101
|
-
this.setStrategy(SEEK_STRATEGY.TAP_SEEK);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
onRewindPressOut = () => {
|
|
105
|
-
const isAutoSeek = this.currentSeekController === this.longPressSeekController;
|
|
106
|
-
|
|
107
|
-
log_verbose(`handleStartSeek: onRewindPressOut, isAutoSeek: ${isAutoSeek}`);
|
|
108
|
-
|
|
109
|
-
this.onSeekEnd();
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
onForwardPressOut = () => {
|
|
113
|
-
const isAutoSeek = this.currentSeekController === this.longPressSeekController;
|
|
114
|
-
|
|
115
|
-
log_verbose(`handleStartSeek: onForwardPressOut, isAutoSeek: ${isAutoSeek}`);
|
|
116
|
-
this.onSeekEnd();
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// ---------------------------
|
|
120
|
-
// SHARED METHODS
|
|
121
|
-
// ---------------------------
|
|
122
|
-
|
|
123
|
-
/** Called by either strategy to accumulate offset while paused. */
|
|
124
|
-
handleDelayedSeek(eventType: SEEK_TYPE, skipTime: number) {
|
|
125
|
-
const player = this.getPlayer();
|
|
126
|
-
if (!player) return;
|
|
127
|
-
|
|
128
|
-
// If not previously delayed, we pause the first time
|
|
129
|
-
if (this.delayedSeekOffset === null) {
|
|
130
|
-
this.pausePlayer();
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const newOffset = (this.delayedSeekOffset || 0) + skipTime;
|
|
134
|
-
const currentPos = player.getPosition();
|
|
135
|
-
let targetPos = currentPos;
|
|
136
|
-
|
|
137
|
-
if (eventType === SEEK_TYPE.FORWARD) {
|
|
138
|
-
targetPos = Math.min(currentPos + newOffset, player.getDuration());
|
|
139
|
-
} else {
|
|
140
|
-
targetPos = Math.max(0, currentPos - newOffset);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
this.delayedSeekOffset = newOffset;
|
|
144
|
-
|
|
145
|
-
log_debug(
|
|
146
|
-
`TVSeekController: handleDelayedSeek - targetPos: ${targetPos}, offset: ${newOffset}, skipTime: ${skipTime}`
|
|
147
|
-
);
|
|
148
|
-
|
|
149
|
-
this.delayedSeekProgressSubject.next(targetPos);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
seekPlayer(offset: number) {
|
|
153
|
-
const player = this.getPlayer();
|
|
154
|
-
if (!player || !this.currentSeekType) return;
|
|
155
|
-
player[this.currentSeekType](offset);
|
|
156
|
-
this.playerPlay();
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
playerPlay() {
|
|
160
|
-
const player = this.getPlayer();
|
|
161
|
-
if (!player) return;
|
|
162
|
-
|
|
163
|
-
if (player.isPaused()) {
|
|
164
|
-
player.play();
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
pausePlayer() {
|
|
169
|
-
const player = this.getPlayer();
|
|
170
|
-
if (!player) return;
|
|
171
|
-
player.pause();
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Reset *all* relevant state and strategy controllers
|
|
176
|
-
*/
|
|
177
|
-
resetAll() {
|
|
178
|
-
log_debug("TVSeekController: Reset all states");
|
|
179
|
-
this.currentSeekType = null;
|
|
180
|
-
this.delayedSeekOffset = null;
|
|
181
|
-
|
|
182
|
-
this.delayedSeekProgressSubject.next(null);
|
|
183
|
-
|
|
184
|
-
this.tapSeekController.reset();
|
|
185
|
-
this.longPressSeekController.reset();
|
|
186
|
-
|
|
187
|
-
this.setStrategy(SEEK_STRATEGY.TAP_SEEK);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
private getPlayer() {
|
|
191
|
-
const player = playerManager.getInstanceController();
|
|
192
|
-
|
|
193
|
-
if (!player) {
|
|
194
|
-
log_warning("TVSeekController: No valid player controller found");
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
return player;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
@@ -1,75 +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
|
-
onStartSeek = (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
|
-
const clicksBeforePause = 0;
|
|
32
|
-
const skipTime = getSkipTime(this.seekMultiplier);
|
|
33
|
-
|
|
34
|
-
if (this.seekMultiplier > clicksBeforePause) {
|
|
35
|
-
log_debug(
|
|
36
|
-
`TapSeekController: handle delayed seek type:${seekType} - skipTime: ${skipTime}.`
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
this.parent.handleDelayedSeek(seekType, skipTime);
|
|
40
|
-
} else {
|
|
41
|
-
log_debug(
|
|
42
|
-
`TapSeekController: handle seek type:${seekType} - skipTime: ${skipTime}.`
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
this.parent.seekPlayer(skipTime);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
this.seekMultiplier++;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
onSeekEnd = () => {
|
|
52
|
-
this.tapSequenceTimeout = setTimeout(() => {
|
|
53
|
-
if (this.parent.delayedSeekOffset !== null) {
|
|
54
|
-
this.parent.seekPlayer(this.parent.delayedSeekOffset);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
log_debug(
|
|
58
|
-
`TapSeekController: Tap sequence timeout fired, delayedSeekOffset: ${this.parent.delayedSeekOffset}.`
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
this.parent.resetAll();
|
|
62
|
-
}, this.ON_PRESS_RESET_DURATION);
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
reset = () => {
|
|
66
|
-
log_debug("TapSeekController: Reset states");
|
|
67
|
-
|
|
68
|
-
this.seekMultiplier = 1;
|
|
69
|
-
|
|
70
|
-
if (this.tapSequenceTimeout) {
|
|
71
|
-
clearTimeout(this.tapSequenceTimeout);
|
|
72
|
-
this.tapSequenceTimeout = null;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|