@applicaster/zapp-react-dom-app 12.0.0-alpha.5812543239 → 12.0.0-alpha.5840700068
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 +568 -478
- package/App/Loader/appLoader.js +2 -6
- package/App/Loader/setUpRTL.js +3 -3
- package/App/Loader/utils/__tests__/getLanguageCode.test.js +0 -1
- package/App/Loader/utils/const.js +3 -0
- package/App/Loader/utils/index.js +19 -18
- package/App/Loader/utils/platform.js +48 -0
- package/Polyfills/AnalyticsBridge/index.ts +5 -1
- package/Polyfills/AppLoaderBridge/utils/enums.ts +1 -0
- package/Polyfills/QuickBrickCommunicationModule/__tests__/index.test.js +225 -0
- package/Polyfills/QuickBrickCommunicationModule/index.js +115 -52
- package/index.js +5 -6
- package/main.css +2 -2
- package/package.json +6 -6
- package/App/Loader/utils/__tests__/getAvailableAppLanguages.test.js +0 -35
|
@@ -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,620 +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
|
-
) {
|
|
599
|
-
this.resetHudTimeout();
|
|
600
|
-
}
|
|
640
|
+
if (activeInputRef) {
|
|
641
|
+
// Update the input's value
|
|
642
|
+
activeInputRef.value = value;
|
|
601
643
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
644
|
+
// Dispatch keyboard update event
|
|
645
|
+
const keyboardEvent = new CustomEvent("keyboardUpdate", {
|
|
646
|
+
detail: { value },
|
|
647
|
+
});
|
|
605
648
|
|
|
606
|
-
|
|
607
|
-
|
|
649
|
+
document.dispatchEvent(keyboardEvent);
|
|
650
|
+
}
|
|
608
651
|
|
|
609
|
-
|
|
652
|
+
this.setState({ keyboardInput: value });
|
|
653
|
+
};
|
|
610
654
|
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
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
|
+
}
|
|
617
678
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
Platform.OS === ("lg_tv" as QuickBrickPlatforms) ? "down" : "up";
|
|
621
|
-
} else if (deltaY < 0) {
|
|
622
|
-
DIRECTION.value =
|
|
623
|
-
Platform.OS === ("lg_tv" as QuickBrickPlatforms) ? "up" : "down";
|
|
624
|
-
}
|
|
679
|
+
private resetSequenceTimeout() {
|
|
680
|
+
const SEQUENCE_ENTRY_TIME = 1900;
|
|
625
681
|
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
displayState === DISPLAY_STATES.HUD
|
|
629
|
-
) {
|
|
630
|
-
this.resetHudTimeout();
|
|
631
|
-
} else {
|
|
632
|
-
focusManager.moveFocus(DIRECTION);
|
|
633
|
-
}
|
|
682
|
+
if (this.sequenceTimeout) {
|
|
683
|
+
clearTimeout(this.sequenceTimeout);
|
|
634
684
|
}
|
|
635
685
|
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
686
|
+
this.sequenceTimeout = setTimeout(() => {
|
|
687
|
+
this.sequenceTimeout = null;
|
|
688
|
+
this.userSequence = [];
|
|
689
|
+
}, SEQUENCE_ENTRY_TIME);
|
|
690
|
+
}
|
|
639
691
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
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;
|
|
647
713
|
}
|
|
714
|
+
};
|
|
648
715
|
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
716
|
+
private handleLongPressRelease = (event: CustomEvent) => {
|
|
717
|
+
const { keyCode } = event.detail;
|
|
718
|
+
this.longPressActive = false;
|
|
719
|
+
this.resetHudTimeout();
|
|
652
720
|
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
721
|
+
switch (keyCode) {
|
|
722
|
+
case KEYS.Forward.code:
|
|
723
|
+
this.props.seekMethods.onForwardPressOut();
|
|
724
|
+
break;
|
|
656
725
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
726
|
+
case KEYS.Rewind.code:
|
|
727
|
+
this.props.seekMethods.onRewindPressOut();
|
|
728
|
+
break;
|
|
660
729
|
|
|
661
|
-
|
|
662
|
-
|
|
730
|
+
case KEYS.Enter.code:
|
|
731
|
+
focusManager.pressOut();
|
|
732
|
+
break;
|
|
663
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
|
+
);
|
|
664
740
|
}
|
|
665
741
|
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
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
|
+
}
|
|
673
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);
|