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