@applicaster/zapp-react-dom-app 12.0.0-alpha.4337072244 → 12.0.0-alpha.4342457208
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/App/InteractionManager/index.tsx +567 -483
- package/App/Loader/utils/const.js +3 -0
- package/App/Loader/utils/platform.js +48 -0
- package/Polyfills/AnalyticsBridge/index.ts +5 -1
- package/index.js +5 -6
- package/main.css +2 -2
- package/package.json +6 -6
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import * as R from "ramda";
|
|
3
3
|
|
|
4
|
+
import { connectToStore } from "@applicaster/zapp-react-native-redux";
|
|
5
|
+
|
|
4
6
|
import {
|
|
5
7
|
QUICK_BRICK_EVENTS,
|
|
6
8
|
sendQuickBrickEvent,
|
|
@@ -31,14 +33,28 @@ import {
|
|
|
31
33
|
import { PlayerContentContext } from "@applicaster/zapp-react-dom-ui-components/Contexts";
|
|
32
34
|
|
|
33
35
|
import { withNavigator } from "@applicaster/zapp-react-native-ui-components/Decorators/Navigator";
|
|
34
|
-
import { Platform } from "react-native";
|
|
35
|
-
import { LONG_KEY_PRESS_TIMEOUT } from "@applicaster/quick-brick-core/const";
|
|
36
36
|
import { getXray } from "@applicaster/zapp-react-native-utils/logger";
|
|
37
|
-
|
|
37
|
+
|
|
38
|
+
import {
|
|
39
|
+
confirmationDialogStore,
|
|
40
|
+
ConfirmationDialogState,
|
|
41
|
+
} from "@applicaster/zapp-react-native-ui-components/Contexts/ConfirmDialogState";
|
|
42
|
+
|
|
43
|
+
import {
|
|
44
|
+
isLgPlatform,
|
|
45
|
+
isSamsungPlatform,
|
|
46
|
+
isVizioPlatform,
|
|
47
|
+
} from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
48
|
+
|
|
49
|
+
import { OnScreenKeyboard } from "@applicaster/zapp-react-dom-ui-components/Components/OnScreenKeyboard";
|
|
50
|
+
import { KeyboardLongPressManager } from "@applicaster/zapp-react-dom-ui-components/Utils/KeyboardLongPressManager";
|
|
38
51
|
|
|
39
52
|
const { withXray } = getXray();
|
|
40
53
|
const globalAny: any = global;
|
|
41
54
|
|
|
55
|
+
const shouldUseOnScreenKeyboard = () =>
|
|
56
|
+
isVizioPlatform() || window.applicaster.useOnScreenKeyboard;
|
|
57
|
+
|
|
42
58
|
type Props = {
|
|
43
59
|
displayState: string;
|
|
44
60
|
setDisplayState: (state: string) => void;
|
|
@@ -54,626 +70,694 @@ type Props = {
|
|
|
54
70
|
onRewindPressOut: () => void;
|
|
55
71
|
onForwardPressOut: () => void;
|
|
56
72
|
};
|
|
73
|
+
confirmDialog: typeof confirmationDialogStore;
|
|
57
74
|
};
|
|
58
75
|
|
|
59
|
-
|
|
76
|
+
interface State {
|
|
77
|
+
isKeyboardVisible: boolean;
|
|
78
|
+
keyboardInput: string;
|
|
79
|
+
activeInputRef: HTMLInputElement | null;
|
|
80
|
+
}
|
|
60
81
|
|
|
61
82
|
type KeyCode = { code: string; keyCode: number | string };
|
|
62
83
|
|
|
63
84
|
export const alertConfirmationMesage =
|
|
64
85
|
"Are you sure you want to exit application?";
|
|
65
86
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
87
|
+
class InteractionManagerClass extends React.Component<Props, State> {
|
|
88
|
+
onKeyDownListener: (keyCode: KeyCode) => void;
|
|
89
|
+
onMouseDownListener: (event: MouseEvent) => void;
|
|
90
|
+
onMouseMoveListener: (event: MouseEvent) => void;
|
|
91
|
+
onScrollListener: (event: MouseEvent) => void;
|
|
92
|
+
|
|
93
|
+
private longPressDetector: KeyboardLongPressManager;
|
|
94
|
+
private longPressActive: boolean = false;
|
|
95
|
+
private timeout: any | null = null;
|
|
96
|
+
private sequenceTimeout: NodeJS.Timeout | null;
|
|
97
|
+
private userSequence: number[] = [];
|
|
98
|
+
private isDismissing = false;
|
|
99
|
+
private confirmDialog: ConfirmationDialogState =
|
|
100
|
+
confirmationDialogStore.getState();
|
|
101
|
+
// private logger: LoggerService = createLogger({
|
|
102
|
+
// category: "zapp-react-dom-app",
|
|
103
|
+
// subsystem: "InteractionManager",
|
|
104
|
+
// });
|
|
105
|
+
|
|
106
|
+
state: State = {
|
|
107
|
+
isKeyboardVisible: false,
|
|
108
|
+
keyboardInput: "",
|
|
109
|
+
activeInputRef: null,
|
|
110
|
+
};
|
|
79
111
|
|
|
80
|
-
|
|
81
|
-
|
|
112
|
+
constructor(props) {
|
|
113
|
+
super(props);
|
|
114
|
+
|
|
115
|
+
this.onMouseMoveListener = debounce({
|
|
116
|
+
fn: this.onMouseMove,
|
|
117
|
+
context: this,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
this.onScrollListener = debounce({
|
|
121
|
+
fn: this.onScroll,
|
|
122
|
+
wait: 100,
|
|
123
|
+
context: this,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
this.onMouseDownListener = debounce({
|
|
127
|
+
fn: this.onMouseDown,
|
|
128
|
+
context: this,
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
this.onKeyDownListener = this.onKeyDown.bind(this);
|
|
132
|
+
this.resetHudTimeout = this.resetHudTimeout.bind(this);
|
|
133
|
+
this.cursorVisibilityChange = this.cursorVisibilityChange.bind(this);
|
|
134
|
+
this.onKeyDown = this.onKeyDown.bind(this);
|
|
135
|
+
this.onKeyUp = this.onKeyUp.bind(this);
|
|
136
|
+
this.onMouseMove = this.onMouseMove.bind(this);
|
|
137
|
+
this.onScroll = this.onScroll.bind(this);
|
|
138
|
+
this.onMouseDown = this.onMouseDown.bind(this);
|
|
139
|
+
this.onKeyboardStateChange = this.onKeyboardStateChange.bind(this);
|
|
140
|
+
this.onConfirmDialogOpen = this.onConfirmDialogOpen.bind(this);
|
|
141
|
+
this.onConfirmDialogClose = this.onConfirmDialogClose.bind(this);
|
|
142
|
+
this.performExit = this.performExit.bind(this);
|
|
143
|
+
this.handleInputFocus = this.handleInputFocus.bind(this);
|
|
144
|
+
this.handleInputBlur = this.handleInputBlur.bind(this);
|
|
145
|
+
this.handleKeyboardInput = this.handleKeyboardInput.bind(this);
|
|
146
|
+
this.handleKeyboardDismiss = this.handleKeyboardDismiss.bind(this);
|
|
147
|
+
this.onKeyDownListener = this.onKeyDown.bind(this);
|
|
148
|
+
this.onKeyUp = this.onKeyUp.bind(this);
|
|
149
|
+
this.onMouseMoveListener = this.onMouseMove.bind(this);
|
|
150
|
+
this.onScrollListener = this.onScroll.bind(this);
|
|
151
|
+
this.onMouseDownListener = this.onMouseDown.bind(this);
|
|
152
|
+
this.onKeyboardStateChange = this.onKeyboardStateChange.bind(this);
|
|
153
|
+
this.onConfirmDialogOpen = this.onConfirmDialogOpen.bind(this);
|
|
154
|
+
this.onConfirmDialogClose = this.onConfirmDialogClose.bind(this);
|
|
155
|
+
|
|
156
|
+
this.confirmDialog.setConfirmAction(this.performExit);
|
|
157
|
+
this.confirmDialog.setCancelAction(this.onConfirmDialogClose);
|
|
158
|
+
this.longPressDetector = new KeyboardLongPressManager();
|
|
159
|
+
}
|
|
82
160
|
|
|
83
|
-
|
|
161
|
+
componentDidMount() {
|
|
162
|
+
window.addEventListener("keydown", this.onKeyDownListener);
|
|
163
|
+
window.addEventListener("keyup", this.onKeyUp);
|
|
164
|
+
window.addEventListener("mousemove", this.onMouseMoveListener);
|
|
84
165
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
166
|
+
document.addEventListener("wheel", this.onScrollListener, {
|
|
167
|
+
passive: true,
|
|
168
|
+
});
|
|
88
169
|
|
|
89
|
-
|
|
90
|
-
fn: this.onMouseMove,
|
|
91
|
-
context: this,
|
|
92
|
-
});
|
|
170
|
+
document.addEventListener("mousedown", this.onMouseDownListener);
|
|
93
171
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
172
|
+
document.addEventListener(
|
|
173
|
+
"keyboardStateChange",
|
|
174
|
+
this.onKeyboardStateChange,
|
|
175
|
+
false
|
|
176
|
+
);
|
|
99
177
|
|
|
100
|
-
|
|
101
|
-
fn: this.onMouseDown,
|
|
102
|
-
context: this,
|
|
103
|
-
});
|
|
178
|
+
document.addEventListener("focusin", this.handleInputFocus);
|
|
104
179
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
this.
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
this.onKeyDown = this.onKeyDown.bind(this);
|
|
111
|
-
this.onKeyUp = this.onKeyUp.bind(this);
|
|
112
|
-
this.onMouseMove = this.onMouseMove.bind(this);
|
|
113
|
-
this.onScroll = this.onScroll.bind(this);
|
|
114
|
-
this.onMouseDown = this.onMouseDown.bind(this);
|
|
115
|
-
this.onKeyboardStateChange = this.onKeyboardStateChange.bind(this);
|
|
116
|
-
this.onConfirmDialogOpen = this.onConfirmDialogOpen.bind(this);
|
|
117
|
-
this.onConfirmDialogClose = this.onConfirmDialogClose.bind(this);
|
|
118
|
-
this.performExit = this.performExit.bind(this);
|
|
119
|
-
|
|
120
|
-
this.confirmDialog.setConfirmAction(this.performExit);
|
|
121
|
-
this.confirmDialog.setCancelAction(this.onConfirmDialogClose);
|
|
122
|
-
}
|
|
180
|
+
document.addEventListener(
|
|
181
|
+
"cursorStateChange",
|
|
182
|
+
this.cursorVisibilityChange,
|
|
183
|
+
false
|
|
184
|
+
);
|
|
123
185
|
|
|
124
|
-
|
|
125
|
-
window.addEventListener("keydown", this.onKeyDownListener);
|
|
126
|
-
window.addEventListener("keyup", this.onKeyUp);
|
|
127
|
-
window.addEventListener("mousemove", this.onMouseMoveListener);
|
|
186
|
+
window.addEventListener("onLongPress", this.handleLongPress.bind(this));
|
|
128
187
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
188
|
+
window.addEventListener(
|
|
189
|
+
"onLongPressRelease",
|
|
190
|
+
this.handleLongPressRelease.bind(this)
|
|
191
|
+
);
|
|
192
|
+
}
|
|
132
193
|
|
|
133
|
-
|
|
194
|
+
componentWillUnmount() {
|
|
195
|
+
window.removeEventListener("keydown", this.onKeyDownListener);
|
|
196
|
+
window.removeEventListener("keyup", this.onKeyUp);
|
|
197
|
+
document.removeEventListener("wheel", this.onScrollListener);
|
|
134
198
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
);
|
|
199
|
+
document.removeEventListener(
|
|
200
|
+
"cursorStateChange",
|
|
201
|
+
this.cursorVisibilityChange
|
|
202
|
+
);
|
|
140
203
|
|
|
141
|
-
|
|
142
|
-
"cursorStateChange",
|
|
143
|
-
this.cursorVisibilityChange,
|
|
144
|
-
false
|
|
145
|
-
);
|
|
146
|
-
}
|
|
204
|
+
document.removeEventListener("focusin", this.handleInputFocus);
|
|
147
205
|
|
|
148
|
-
|
|
149
|
-
window.removeEventListener("keydown", this.onKeyDownListener);
|
|
150
|
-
window.removeEventListener("keyup", this.onKeyUp);
|
|
151
|
-
document.removeEventListener("wheel", this.onScrollListener);
|
|
206
|
+
document.removeEventListener("mousedown", this.onMouseDownListener);
|
|
152
207
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
);
|
|
208
|
+
if (this.timeout) {
|
|
209
|
+
this.clearTimeout();
|
|
210
|
+
}
|
|
157
211
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
);
|
|
212
|
+
this.isDismissing = false;
|
|
213
|
+
this.longPressDetector.cleanup();
|
|
214
|
+
window.removeEventListener("onLongPress", this.handleLongPress);
|
|
162
215
|
|
|
163
|
-
|
|
216
|
+
window.removeEventListener(
|
|
217
|
+
"onLongPressRelease",
|
|
218
|
+
this.handleLongPressRelease
|
|
219
|
+
);
|
|
220
|
+
}
|
|
164
221
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
222
|
+
performExit() {
|
|
223
|
+
if (isSamsungPlatform()) {
|
|
224
|
+
this.onConfirmDialogClose();
|
|
225
|
+
sendQuickBrickEvent(QUICK_BRICK_EVENTS.MOVE_APP_TO_BACKGROUND);
|
|
168
226
|
}
|
|
169
227
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
228
|
+
if (isLgPlatform()) {
|
|
229
|
+
// webOS recommend to use this method when implemention a custom exit
|
|
230
|
+
globalAny.close();
|
|
231
|
+
}
|
|
175
232
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
globalAny.close();
|
|
179
|
-
}
|
|
233
|
+
if (isVizioPlatform()) {
|
|
234
|
+
window?.VIZIO?.exitApplication();
|
|
180
235
|
}
|
|
236
|
+
}
|
|
181
237
|
|
|
182
|
-
|
|
183
|
-
|
|
238
|
+
handleWebOsBack() {
|
|
239
|
+
const systemBack = globalAny?.webOS?.platformBack;
|
|
184
240
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
241
|
+
if (systemBack) {
|
|
242
|
+
systemBack();
|
|
243
|
+
} else {
|
|
244
|
+
/**
|
|
245
|
+
* In case webOS failed to show the exit pop-up, we show a regular promtp as fallback
|
|
246
|
+
*/
|
|
247
|
+
showConfirmationDialog({
|
|
248
|
+
title: "",
|
|
249
|
+
message: alertConfirmationMesage,
|
|
250
|
+
confirmCompletion: this.performExit,
|
|
251
|
+
});
|
|
197
252
|
}
|
|
253
|
+
}
|
|
198
254
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
}
|
|
221
|
-
} else if (Platform.OS === ("lg_tv" as QuickBrickPlatforms)) {
|
|
222
|
-
this.handleWebOsBack();
|
|
255
|
+
/**
|
|
256
|
+
* This methods sends the app to background in whatever way is appropriate for each platform
|
|
257
|
+
* In the case of Tizen it shows a custom dialog on confirm it exits the app
|
|
258
|
+
* WebOS behavior depends on the SDK version, WebOS 4 would pull up the launcher menu
|
|
259
|
+
* following versions would show a native exit prompt
|
|
260
|
+
*/
|
|
261
|
+
platformBack() {
|
|
262
|
+
try {
|
|
263
|
+
// TODO: temporary hack until this code is refactored
|
|
264
|
+
if (isSamsungPlatform() || isVizioPlatform()) {
|
|
265
|
+
const { isDialogVisible } = confirmationDialogStore.getState();
|
|
266
|
+
|
|
267
|
+
if (isDialogVisible) {
|
|
268
|
+
this.onConfirmDialogClose();
|
|
269
|
+
} else {
|
|
270
|
+
showConfirmationDialog({
|
|
271
|
+
title: "",
|
|
272
|
+
message: alertConfirmationMesage,
|
|
273
|
+
confirmCompletion: this.performExit,
|
|
274
|
+
cancelCompletion: this.onConfirmDialogClose,
|
|
275
|
+
});
|
|
223
276
|
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
console.warn("Failed to execute platformBack", e);
|
|
277
|
+
} else if (isLgPlatform()) {
|
|
278
|
+
this.handleWebOsBack();
|
|
227
279
|
}
|
|
280
|
+
} catch (e) {
|
|
281
|
+
// eslint-disable-next-line no-console
|
|
282
|
+
console.warn("Failed to execute platformBack", e);
|
|
228
283
|
}
|
|
284
|
+
}
|
|
229
285
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
286
|
+
cursorVisibilityChange(event) {
|
|
287
|
+
const visible = event.detail.visibility;
|
|
288
|
+
const { setDisplayState, displayState } = this.props;
|
|
233
289
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
}
|
|
290
|
+
if (visible && displayState === DISPLAY_STATES.PLAYER) {
|
|
291
|
+
setDisplayState(DISPLAY_STATES.HUD);
|
|
292
|
+
this.resetHudTimeout();
|
|
238
293
|
}
|
|
294
|
+
}
|
|
239
295
|
|
|
240
|
-
|
|
241
|
-
|
|
296
|
+
onMouseMove() {
|
|
297
|
+
const { setDisplayState, displayState } = this.props;
|
|
242
298
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
299
|
+
if (displayState === DISPLAY_STATES.PLAYER) {
|
|
300
|
+
setDisplayState(DISPLAY_STATES.HUD);
|
|
301
|
+
this.resetHudTimeout();
|
|
247
302
|
}
|
|
303
|
+
}
|
|
248
304
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
305
|
+
isHomeScreen() {
|
|
306
|
+
const { navigator } = this.props;
|
|
307
|
+
const { rivers } = this.props;
|
|
252
308
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
309
|
+
const homeId = R.compose(
|
|
310
|
+
R.prop("id"),
|
|
311
|
+
R.find(R.prop("home")),
|
|
312
|
+
R.values
|
|
313
|
+
)(rivers);
|
|
258
314
|
|
|
259
|
-
|
|
315
|
+
const homePath = `/river/${homeId}`;
|
|
260
316
|
|
|
261
|
-
|
|
262
|
-
|
|
317
|
+
return homePath === navigator.currentRoute;
|
|
318
|
+
}
|
|
263
319
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
320
|
+
goToHome() {
|
|
321
|
+
const { navigator } = this.props;
|
|
322
|
+
const { rivers } = this.props;
|
|
323
|
+
const homeRiver = R.find(R.propEq("home", true), R.values(rivers));
|
|
268
324
|
|
|
269
|
-
|
|
325
|
+
navigator.replace(homeRiver);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
resetHudTimeout() {
|
|
329
|
+
const { resetHudTimer = noop } = this.props;
|
|
330
|
+
|
|
331
|
+
resetHudTimer?.();
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
clearTimeout() {
|
|
335
|
+
if (this.timeout) {
|
|
336
|
+
clearTimeout(this.timeout);
|
|
337
|
+
this.timeout = null;
|
|
270
338
|
}
|
|
339
|
+
}
|
|
271
340
|
|
|
272
|
-
|
|
273
|
-
|
|
341
|
+
cancelHudTimeout() {
|
|
342
|
+
this.resetHudTimeout();
|
|
343
|
+
}
|
|
274
344
|
|
|
275
|
-
|
|
345
|
+
onKeyUp(event: KeyboardEvent) {
|
|
346
|
+
if (this.keySupportsLongPress(event)) {
|
|
347
|
+
this.longPressDetector.endKeyPressMonitoring(event.code);
|
|
276
348
|
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
onKeyDown(event) {
|
|
352
|
+
const { displayState, setDisplayState, navigator } = this.props;
|
|
353
|
+
const { isKeyboardVisible } = this.state;
|
|
354
|
+
|
|
355
|
+
const { isDialogVisible } = confirmationDialogStore.getState();
|
|
277
356
|
|
|
278
|
-
|
|
279
|
-
if (
|
|
280
|
-
|
|
281
|
-
this.timeout = null;
|
|
357
|
+
if (isKeyboardVisible && shouldUseOnScreenKeyboard()) {
|
|
358
|
+
if (keyCode(event).matchesAny("Escape", "Back")) {
|
|
359
|
+
this.handleKeyboardDismiss();
|
|
282
360
|
}
|
|
361
|
+
|
|
362
|
+
event.preventDefault();
|
|
363
|
+
event.stopPropagation();
|
|
364
|
+
|
|
365
|
+
return;
|
|
283
366
|
}
|
|
284
367
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
clearTimeout(this.longKeyPressTimeout);
|
|
288
|
-
this.longKeyPressTimeout = null;
|
|
289
|
-
}
|
|
368
|
+
if (this.keySupportsLongPress(event)) {
|
|
369
|
+
this.longPressDetector.monitorKeyPress(event.code, event);
|
|
290
370
|
}
|
|
291
371
|
|
|
372
|
+
// None of the logic below should be executed for repeated keys
|
|
373
|
+
if (event.repeat) return;
|
|
374
|
+
|
|
292
375
|
/**
|
|
293
|
-
|
|
294
|
-
|
|
376
|
+
When the player is displayed, we listen to Native Play / Pause / Stop
|
|
377
|
+
buttons. Any other key press will display the transport controls
|
|
295
378
|
*/
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
switch (event.code) {
|
|
306
|
-
case KEYS.Back.code:
|
|
307
|
-
// If you longpress the back button we probably want to exit
|
|
308
|
-
this.platformBack();
|
|
379
|
+
if (
|
|
380
|
+
displayState === DISPLAY_STATES.PLAYER ||
|
|
381
|
+
displayState === DISPLAY_STATES.HUD
|
|
382
|
+
) {
|
|
383
|
+
/**
|
|
384
|
+
registering native keys for playback
|
|
385
|
+
*/
|
|
386
|
+
if (keyCode(event).matches(KEYS.TogglePlayPause)) {
|
|
387
|
+
const { playing } = playerManager.getState() || {};
|
|
309
388
|
|
|
310
|
-
|
|
389
|
+
if (!playing) {
|
|
390
|
+
return playerManager.togglePlayPause();
|
|
391
|
+
}
|
|
392
|
+
}
|
|
311
393
|
|
|
312
|
-
|
|
313
|
-
|
|
394
|
+
if (keyCode(event).matches(KEYS.Play)) {
|
|
395
|
+
return playerManager.play();
|
|
396
|
+
}
|
|
314
397
|
|
|
315
|
-
|
|
398
|
+
if (keyCode(event).matches(KEYS.Pause)) {
|
|
399
|
+
setDisplayState(DISPLAY_STATES.HUD);
|
|
316
400
|
|
|
317
|
-
|
|
318
|
-
|
|
401
|
+
return playerManager.pause();
|
|
402
|
+
}
|
|
319
403
|
|
|
320
|
-
|
|
404
|
+
if (keyCode(event).matches(KEYS.Stop)) {
|
|
405
|
+
setDisplayState(DISPLAY_STATES.DEFAULT);
|
|
406
|
+
navigator.goBack();
|
|
321
407
|
|
|
322
|
-
|
|
323
|
-
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
324
410
|
|
|
325
|
-
|
|
411
|
+
if (keyCode(event).matches(KEYS.Forward)) {
|
|
412
|
+
setDisplayState(DISPLAY_STATES.HUD);
|
|
413
|
+
this.props.seekMethods.onForwardPress();
|
|
326
414
|
|
|
327
|
-
|
|
328
|
-
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
if (keyCode(event).matches(KEYS.Rewind)) {
|
|
419
|
+
setDisplayState(DISPLAY_STATES.HUD);
|
|
420
|
+
this.props.seekMethods.onRewindPress();
|
|
421
|
+
|
|
422
|
+
return;
|
|
329
423
|
}
|
|
330
424
|
}
|
|
331
425
|
|
|
332
426
|
/**
|
|
333
|
-
|
|
334
|
-
|
|
427
|
+
When pressing backspace or the Native "Back" button:
|
|
428
|
+
if on the transport controls: we show the player
|
|
429
|
+
if on the player : we show the UI
|
|
430
|
+
if on the UI : we exit the app
|
|
335
431
|
*/
|
|
336
|
-
onLongPressRelease(event) {
|
|
337
|
-
this.longPressActive = false;
|
|
338
|
-
this.resetHudTimeout();
|
|
339
|
-
|
|
340
|
-
focusManager.pressOut();
|
|
341
432
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
433
|
+
if (
|
|
434
|
+
keyCode(event).matchesAny(
|
|
435
|
+
KEYS.Back,
|
|
436
|
+
KEYS.Escape,
|
|
437
|
+
KEYS.EscapeDevice,
|
|
438
|
+
KEYS.Backspace
|
|
439
|
+
)
|
|
440
|
+
) {
|
|
441
|
+
switch (displayState) {
|
|
442
|
+
case DISPLAY_STATES.DEFAULT:
|
|
443
|
+
case DISPLAY_STATES.PLAYER:
|
|
444
|
+
if (isDialogVisible) {
|
|
445
|
+
this.onConfirmDialogClose();
|
|
446
|
+
} else if (navigator.canGoBack()) {
|
|
447
|
+
navigator.goBack();
|
|
448
|
+
} else if (this.isHomeScreen()) {
|
|
449
|
+
this.platformBack();
|
|
450
|
+
} else if (navigator.currentRoute.includes("hook")) {
|
|
451
|
+
// If code reaches this block navigator cant go back, it is not home,
|
|
452
|
+
// and this is a login plugin that was pushed on top of the home
|
|
453
|
+
// Treat it like a home screen and run platformBack()
|
|
454
|
+
const entryData = navigator?.data?.entry;
|
|
455
|
+
const isHookInHomescreen = entryData?.payload?.home;
|
|
456
|
+
|
|
457
|
+
const isHookFlowBlocker =
|
|
458
|
+
entryData?.hookPlugin?.module?.isFlowBlocker();
|
|
459
|
+
|
|
460
|
+
if (isHookInHomescreen && isHookFlowBlocker) {
|
|
461
|
+
this.platformBack();
|
|
462
|
+
} else {
|
|
463
|
+
navigator.goBack(false, true);
|
|
464
|
+
}
|
|
465
|
+
} else {
|
|
466
|
+
this.goToHome();
|
|
467
|
+
}
|
|
345
468
|
|
|
346
469
|
break;
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
470
|
+
case DISPLAY_STATES.HUD:
|
|
471
|
+
// IF transport controls are open, close them instead of closing player
|
|
472
|
+
setDisplayState(DISPLAY_STATES.PLAYER);
|
|
351
473
|
break;
|
|
352
|
-
|
|
353
474
|
default:
|
|
475
|
+
setDisplayState(DISPLAY_STATES.PLAYER);
|
|
354
476
|
break;
|
|
355
477
|
}
|
|
356
478
|
}
|
|
357
479
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
resetSequenceTimeout() {
|
|
364
|
-
const SEQUENCE_ENTRY_TIME = 1900;
|
|
365
|
-
|
|
366
|
-
if (this.sequenceTimeout) {
|
|
367
|
-
// Start timer over
|
|
368
|
-
clearTimeout(this.sequenceTimeout);
|
|
480
|
+
if (keyCode(event).matches(KEYS.Enter)) {
|
|
481
|
+
if (displayState === DISPLAY_STATES.PLAYER) {
|
|
482
|
+
setDisplayState(DISPLAY_STATES.HUD);
|
|
483
|
+
} else {
|
|
484
|
+
focusManager.press();
|
|
369
485
|
}
|
|
370
486
|
|
|
371
|
-
|
|
372
|
-
// User needs to complete sequence before SEQUENCE_ENTRY_TIME
|
|
373
|
-
// or we set userSequence, and prev sequenceTimeout to empty values
|
|
374
|
-
this.sequenceTimeout = null;
|
|
375
|
-
this.userSequence = [];
|
|
376
|
-
}, SEQUENCE_ENTRY_TIME);
|
|
487
|
+
return true;
|
|
377
488
|
}
|
|
378
489
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
*/
|
|
383
|
-
checkSequence(key) {
|
|
384
|
-
const SINK_SEQUENCE = [
|
|
385
|
-
KEYS.ArrowUp.keyCode,
|
|
386
|
-
KEYS.ArrowUp.keyCode,
|
|
387
|
-
KEYS.ArrowDown.keyCode,
|
|
388
|
-
KEYS.ArrowDown.keyCode,
|
|
389
|
-
KEYS.ArrowLeft.keyCode,
|
|
390
|
-
KEYS.ArrowRight.keyCode,
|
|
391
|
-
KEYS.ArrowLeft.keyCode,
|
|
392
|
-
KEYS.ArrowRight.keyCode,
|
|
393
|
-
];
|
|
394
|
-
|
|
395
|
-
this.resetSequenceTimeout();
|
|
396
|
-
this.userSequence.push(key);
|
|
397
|
-
|
|
398
|
-
// Remember [1,2,3] !== [1,2,3] in js, so string comparison is better
|
|
399
|
-
const shouldAddSink =
|
|
400
|
-
this.userSequence.toString() === SINK_SEQUENCE.toString();
|
|
401
|
-
|
|
402
|
-
if (shouldAddSink) {
|
|
403
|
-
this.props.xray.addRemoteSink({});
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
/**
|
|
408
|
-
* Determines whether the key supports or handles longpress
|
|
409
|
-
* At the moment the only keys that support are the ones defined in
|
|
410
|
-
* supportedEvents array. This logic just prevents us from registering timeouts for every key
|
|
411
|
-
*/
|
|
412
|
-
keySupportsLongPress(event): boolean {
|
|
413
|
-
const supportedEvents = [
|
|
414
|
-
KEYS.Back,
|
|
415
|
-
KEYS.Enter,
|
|
416
|
-
KEYS.Rewind,
|
|
417
|
-
KEYS.Forward,
|
|
418
|
-
];
|
|
419
|
-
|
|
420
|
-
const eventMatcher = R.compose(R.prop("matches"), keyCode)(event);
|
|
490
|
+
if (keyCode(event).matches(KEYS.Exit)) {
|
|
491
|
+
if (isSamsungPlatform() || shouldUseOnScreenKeyboard()) {
|
|
492
|
+
this.performExit();
|
|
421
493
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
R.map(eventMatcher)
|
|
425
|
-
)(supportedEvents);
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
426
496
|
|
|
427
|
-
|
|
497
|
+
this.platformBack();
|
|
428
498
|
}
|
|
429
499
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
} else {
|
|
437
|
-
this.clearLongPressTimeout();
|
|
438
|
-
}
|
|
500
|
+
if (
|
|
501
|
+
keyCode(event).matchesAny(...ARROW_KEYS) &&
|
|
502
|
+
!this.state.isKeyboardVisible
|
|
503
|
+
) {
|
|
504
|
+
if (displayState === DISPLAY_STATES.PLAYER) {
|
|
505
|
+
setDisplayState(DISPLAY_STATES.HUD);
|
|
439
506
|
}
|
|
440
|
-
}
|
|
441
507
|
|
|
442
|
-
|
|
443
|
-
const { displayState, setDisplayState, navigator } = this.props;
|
|
508
|
+
this.checkSequence(event.keyCode);
|
|
444
509
|
|
|
445
|
-
const
|
|
510
|
+
const direction = keyCode(event).direction();
|
|
446
511
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
512
|
+
if (!isDialogVisible || !["up", "down"].includes(direction.value)) {
|
|
513
|
+
focusManager.moveFocus(direction);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
if (!isDialogVisible) {
|
|
517
|
+
// run focus recovery on user interaction attempt
|
|
518
|
+
// probably we failed to set initial focus for some reason
|
|
519
|
+
focusManager.recoverFocus();
|
|
452
520
|
}
|
|
453
521
|
|
|
454
|
-
/**
|
|
455
|
-
When the player is displayed, we listen to Native Play / Pause / Stop
|
|
456
|
-
buttons. Any other key press will display the transport controls
|
|
457
|
-
*/
|
|
458
522
|
if (
|
|
459
523
|
displayState === DISPLAY_STATES.PLAYER ||
|
|
460
524
|
displayState === DISPLAY_STATES.HUD
|
|
461
525
|
) {
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
*/
|
|
465
|
-
if (keyCode(event).matches(KEYS.TogglePlayPause)) {
|
|
466
|
-
const { playing } = playerManager.getState() || {};
|
|
467
|
-
|
|
468
|
-
if (!playing) {
|
|
469
|
-
return playerManager.togglePlayPause();
|
|
470
|
-
}
|
|
471
|
-
}
|
|
526
|
+
this.resetHudTimeout();
|
|
527
|
+
}
|
|
472
528
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
529
|
+
return true;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
476
532
|
|
|
477
|
-
|
|
478
|
-
|
|
533
|
+
onScroll(event) {
|
|
534
|
+
const { displayState } = this.props;
|
|
479
535
|
|
|
480
|
-
|
|
481
|
-
}
|
|
536
|
+
const deltaY = event?.deltaY;
|
|
482
537
|
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
538
|
+
const DIRECTION = {
|
|
539
|
+
axis: "y",
|
|
540
|
+
isHorizontal: false,
|
|
541
|
+
isVertical: true,
|
|
542
|
+
value: "",
|
|
543
|
+
};
|
|
486
544
|
|
|
487
|
-
|
|
488
|
-
|
|
545
|
+
if (deltaY > 0) {
|
|
546
|
+
DIRECTION.value = isLgPlatform() ? "down" : "up";
|
|
547
|
+
} else if (deltaY < 0) {
|
|
548
|
+
DIRECTION.value = isLgPlatform() ? "up" : "down";
|
|
549
|
+
}
|
|
489
550
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
551
|
+
if (
|
|
552
|
+
displayState === DISPLAY_STATES.PLAYER ||
|
|
553
|
+
displayState === DISPLAY_STATES.HUD
|
|
554
|
+
) {
|
|
555
|
+
this.resetHudTimeout();
|
|
556
|
+
} else {
|
|
557
|
+
focusManager.moveFocus(DIRECTION);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
493
560
|
|
|
494
|
-
|
|
495
|
-
|
|
561
|
+
onMouseDown(event) {
|
|
562
|
+
const { button } = event;
|
|
563
|
+
const { displayState } = this.props;
|
|
496
564
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
565
|
+
if (
|
|
566
|
+
button === 1 && // number 1 represents press on the scroll wheel
|
|
567
|
+
(displayState === DISPLAY_STATES.PLAYER ||
|
|
568
|
+
displayState === DISPLAY_STATES.HUD)
|
|
569
|
+
) {
|
|
570
|
+
this.resetHudTimeout();
|
|
571
|
+
}
|
|
572
|
+
}
|
|
500
573
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
574
|
+
onKeyboardStateChange(event) {
|
|
575
|
+
this.setState({ isKeyboardVisible: event.visibility });
|
|
576
|
+
}
|
|
504
577
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
if on the player : we show the UI
|
|
509
|
-
if on the UI : we exit the app
|
|
510
|
-
*/
|
|
578
|
+
onConfirmDialogOpen() {
|
|
579
|
+
this.confirmDialog.showDialog();
|
|
580
|
+
}
|
|
511
581
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
KEYS.Back,
|
|
515
|
-
KEYS.Escape,
|
|
516
|
-
KEYS.EscapeDevice,
|
|
517
|
-
KEYS.Backspace
|
|
518
|
-
)
|
|
519
|
-
) {
|
|
520
|
-
switch (displayState) {
|
|
521
|
-
case DISPLAY_STATES.DEFAULT:
|
|
522
|
-
case DISPLAY_STATES.PLAYER:
|
|
523
|
-
if (isDialogVisible) {
|
|
524
|
-
this.onConfirmDialogClose();
|
|
525
|
-
} else if (navigator.canGoBack()) {
|
|
526
|
-
navigator.goBack();
|
|
527
|
-
} else if (this.isHomeScreen()) {
|
|
528
|
-
this.platformBack();
|
|
529
|
-
} else if (navigator.currentRoute.includes("hook")) {
|
|
530
|
-
// If code reaches this block navigator cant go back, it is not home,
|
|
531
|
-
// and this is a login plugin that was pushed on top of the home
|
|
532
|
-
// Treat it like a home screen and run platformBack()
|
|
533
|
-
const entryData = navigator?.data?.entry;
|
|
534
|
-
const isHookInHomescreen = entryData?.payload?.home;
|
|
535
|
-
|
|
536
|
-
const isHookFlowBlocker =
|
|
537
|
-
entryData?.hookPlugin?.module?.isFlowBlocker();
|
|
538
|
-
|
|
539
|
-
if (isHookInHomescreen && isHookFlowBlocker) {
|
|
540
|
-
this.platformBack();
|
|
541
|
-
} else {
|
|
542
|
-
navigator.goBack(false, true);
|
|
543
|
-
}
|
|
544
|
-
} else {
|
|
545
|
-
this.goToHome();
|
|
546
|
-
}
|
|
582
|
+
onConfirmDialogClose() {
|
|
583
|
+
this.confirmDialog.hideDialog();
|
|
547
584
|
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
setDisplayState(DISPLAY_STATES.PLAYER);
|
|
552
|
-
break;
|
|
553
|
-
default:
|
|
554
|
-
setDisplayState(DISPLAY_STATES.PLAYER);
|
|
555
|
-
break;
|
|
556
|
-
}
|
|
557
|
-
}
|
|
585
|
+
// restore initial focus after closing dialog
|
|
586
|
+
focusManager.setInitialFocus();
|
|
587
|
+
}
|
|
558
588
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
} else {
|
|
563
|
-
focusManager.press();
|
|
564
|
-
}
|
|
589
|
+
handleInputFocus = (event: FocusEvent) => {
|
|
590
|
+
if (!shouldUseOnScreenKeyboard()) return;
|
|
591
|
+
const target = event.target as HTMLInputElement;
|
|
565
592
|
|
|
566
|
-
|
|
567
|
-
}
|
|
593
|
+
if (this.isDismissing) return;
|
|
568
594
|
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
595
|
+
if (target.tagName === "INPUT" || target.tagName === "TEXTAREA") {
|
|
596
|
+
this.setState({
|
|
597
|
+
isKeyboardVisible: true,
|
|
598
|
+
keyboardInput: target.value || "",
|
|
599
|
+
activeInputRef: target,
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
};
|
|
572
603
|
|
|
573
|
-
|
|
574
|
-
|
|
604
|
+
handleInputBlur(event: FocusEvent) {
|
|
605
|
+
if (!shouldUseOnScreenKeyboard()) return;
|
|
575
606
|
|
|
576
|
-
|
|
577
|
-
|
|
607
|
+
const target = event.target as HTMLElement;
|
|
608
|
+
|
|
609
|
+
if (target.tagName === "INPUT" || target.tagName === "TEXTAREA") {
|
|
610
|
+
const relatedTarget = event.relatedTarget as HTMLElement;
|
|
578
611
|
|
|
579
612
|
if (
|
|
580
|
-
|
|
581
|
-
|
|
613
|
+
!relatedTarget ||
|
|
614
|
+
(relatedTarget.tagName !== "INPUT" &&
|
|
615
|
+
relatedTarget.tagName !== "TEXTAREA")
|
|
582
616
|
) {
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
617
|
+
this.setState({ isKeyboardVisible: false });
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}
|
|
586
621
|
|
|
587
|
-
|
|
622
|
+
handleKeyboardDismiss = () => {
|
|
623
|
+
this.isDismissing = true;
|
|
588
624
|
|
|
589
|
-
|
|
625
|
+
this.setState(
|
|
626
|
+
{
|
|
627
|
+
isKeyboardVisible: false,
|
|
628
|
+
keyboardInput: "",
|
|
629
|
+
activeInputRef: null,
|
|
630
|
+
},
|
|
631
|
+
() => {
|
|
632
|
+
this.isDismissing = false;
|
|
633
|
+
}
|
|
634
|
+
);
|
|
635
|
+
};
|
|
590
636
|
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
}
|
|
637
|
+
handleKeyboardInput = (value: string) => {
|
|
638
|
+
const { activeInputRef } = this.state;
|
|
594
639
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
focusManager.recoverFocus();
|
|
599
|
-
}
|
|
640
|
+
if (activeInputRef) {
|
|
641
|
+
// Update the input's value
|
|
642
|
+
activeInputRef.value = value;
|
|
600
643
|
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
this.resetHudTimeout();
|
|
606
|
-
}
|
|
644
|
+
// Dispatch keyboard update event
|
|
645
|
+
const keyboardEvent = new CustomEvent("keyboardUpdate", {
|
|
646
|
+
detail: { value },
|
|
647
|
+
});
|
|
607
648
|
|
|
608
|
-
|
|
609
|
-
}
|
|
649
|
+
document.dispatchEvent(keyboardEvent);
|
|
610
650
|
}
|
|
611
651
|
|
|
612
|
-
|
|
613
|
-
|
|
652
|
+
this.setState({ keyboardInput: value });
|
|
653
|
+
};
|
|
614
654
|
|
|
615
|
-
|
|
655
|
+
// TODO: use RemoteSequenceHandler class
|
|
656
|
+
private checkSequence(key: number) {
|
|
657
|
+
const SINK_SEQUENCE = [
|
|
658
|
+
KEYS.ArrowUp.keyCode,
|
|
659
|
+
KEYS.ArrowUp.keyCode,
|
|
660
|
+
KEYS.ArrowDown.keyCode,
|
|
661
|
+
KEYS.ArrowDown.keyCode,
|
|
662
|
+
KEYS.ArrowLeft.keyCode,
|
|
663
|
+
KEYS.ArrowRight.keyCode,
|
|
664
|
+
KEYS.ArrowLeft.keyCode,
|
|
665
|
+
KEYS.ArrowRight.keyCode,
|
|
666
|
+
];
|
|
667
|
+
|
|
668
|
+
this.resetSequenceTimeout();
|
|
669
|
+
this.userSequence.push(key);
|
|
670
|
+
|
|
671
|
+
const shouldAddSink =
|
|
672
|
+
this.userSequence.toString() === SINK_SEQUENCE.toString();
|
|
673
|
+
|
|
674
|
+
if (shouldAddSink) {
|
|
675
|
+
this.props.xray.addRemoteSink({});
|
|
676
|
+
}
|
|
677
|
+
}
|
|
616
678
|
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
isHorizontal: false,
|
|
620
|
-
isVertical: true,
|
|
621
|
-
value: "",
|
|
622
|
-
};
|
|
679
|
+
private resetSequenceTimeout() {
|
|
680
|
+
const SEQUENCE_ENTRY_TIME = 1900;
|
|
623
681
|
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
Platform.OS === ("lg_tv" as QuickBrickPlatforms) ? "down" : "up";
|
|
627
|
-
} else if (deltaY < 0) {
|
|
628
|
-
DIRECTION.value =
|
|
629
|
-
Platform.OS === ("lg_tv" as QuickBrickPlatforms) ? "up" : "down";
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
if (
|
|
633
|
-
displayState === DISPLAY_STATES.PLAYER ||
|
|
634
|
-
displayState === DISPLAY_STATES.HUD
|
|
635
|
-
) {
|
|
636
|
-
this.resetHudTimeout();
|
|
637
|
-
} else {
|
|
638
|
-
focusManager.moveFocus(DIRECTION);
|
|
639
|
-
}
|
|
682
|
+
if (this.sequenceTimeout) {
|
|
683
|
+
clearTimeout(this.sequenceTimeout);
|
|
640
684
|
}
|
|
641
685
|
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
686
|
+
this.sequenceTimeout = setTimeout(() => {
|
|
687
|
+
this.sequenceTimeout = null;
|
|
688
|
+
this.userSequence = [];
|
|
689
|
+
}, SEQUENCE_ENTRY_TIME);
|
|
690
|
+
}
|
|
645
691
|
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
692
|
+
private handleLongPress = (event: CustomEvent) => {
|
|
693
|
+
const { keyCode } = event.detail;
|
|
694
|
+
const { displayState } = this.props;
|
|
695
|
+
const playerState = displayState === DISPLAY_STATES.PLAYER;
|
|
696
|
+
const hudState = displayState === DISPLAY_STATES.HUD;
|
|
697
|
+
const playbackState = playerState || hudState;
|
|
698
|
+
this.longPressActive = true;
|
|
699
|
+
this.cancelHudTimeout();
|
|
700
|
+
|
|
701
|
+
switch (keyCode) {
|
|
702
|
+
case KEYS.Forward.code:
|
|
703
|
+
playbackState && this.props.seekMethods.onForwardLongPress();
|
|
704
|
+
break;
|
|
705
|
+
|
|
706
|
+
case KEYS.Rewind.code:
|
|
707
|
+
playbackState && this.props.seekMethods.onRewindLongPress();
|
|
708
|
+
break;
|
|
709
|
+
|
|
710
|
+
case KEYS.Enter.code:
|
|
711
|
+
focusManager.longPress();
|
|
712
|
+
break;
|
|
653
713
|
}
|
|
714
|
+
};
|
|
654
715
|
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
716
|
+
private handleLongPressRelease = (event: CustomEvent) => {
|
|
717
|
+
const { keyCode } = event.detail;
|
|
718
|
+
this.longPressActive = false;
|
|
719
|
+
this.resetHudTimeout();
|
|
658
720
|
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
721
|
+
switch (keyCode) {
|
|
722
|
+
case KEYS.Forward.code:
|
|
723
|
+
this.props.seekMethods.onForwardPressOut();
|
|
724
|
+
break;
|
|
662
725
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
726
|
+
case KEYS.Rewind.code:
|
|
727
|
+
this.props.seekMethods.onRewindPressOut();
|
|
728
|
+
break;
|
|
666
729
|
|
|
667
|
-
|
|
668
|
-
|
|
730
|
+
case KEYS.Enter.code:
|
|
731
|
+
focusManager.pressOut();
|
|
732
|
+
break;
|
|
669
733
|
}
|
|
734
|
+
};
|
|
735
|
+
|
|
736
|
+
private keySupportsLongPress(event: KeyboardEvent): boolean {
|
|
737
|
+
return [KEYS.Forward.code, KEYS.Rewind.code, KEYS.Enter.code].includes(
|
|
738
|
+
event.code
|
|
739
|
+
);
|
|
670
740
|
}
|
|
671
741
|
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
742
|
+
render() {
|
|
743
|
+
return (
|
|
744
|
+
(shouldUseOnScreenKeyboard() && this.state.isKeyboardVisible && (
|
|
745
|
+
<OnScreenKeyboard
|
|
746
|
+
value={this.state.keyboardInput}
|
|
747
|
+
onInput={this.handleKeyboardInput}
|
|
748
|
+
onDismiss={this.handleKeyboardDismiss}
|
|
749
|
+
/>
|
|
750
|
+
)) ||
|
|
751
|
+
null
|
|
752
|
+
);
|
|
753
|
+
}
|
|
679
754
|
}
|
|
755
|
+
|
|
756
|
+
export const InteractionManager = R.compose(
|
|
757
|
+
withNavigator,
|
|
758
|
+
withUseSeek,
|
|
759
|
+
withXray,
|
|
760
|
+
connectToStore(R.pick(["rivers"])),
|
|
761
|
+
PlayerContentContext.withConsumer,
|
|
762
|
+
DisplayStateContext.withConsumer
|
|
763
|
+
)(InteractionManagerClass);
|