Previews: Add touch gesture support

On devices with touch support, maps left and right swipes to moving to
the next and previous item, and double-taps to toggling fullscreen on
and off.
This commit is contained in:
Martijn Pieters 2022-05-22 15:27:38 +00:00 committed by Martijn Pieters
parent aa94de4945
commit 1b1b6f15f9
1 changed files with 70 additions and 3 deletions

View File

@ -5,6 +5,7 @@ const allsettings = require('../../core/settings');
const store = require('../../core/store');
const win = global.window;
const doc = win.document;
const settings = Object.assign({
enabled: true
}, allsettings.preview);
@ -27,11 +28,15 @@ const overlayTpl =
</div>`;
const storekey = 'ext/preview';
const TOUCH_MAX_DELAY = 250;
const TOUCH_GESTURE_DISTANCE = 40;
let isFullscreen = store.get(storekey) || false;
let userAliveTimeoutId = null;
let spinnerIsVisible = false;
let spinnerTimeoutId = null;
let session = null;
let touchState = {};
const centerContent = () => {
const $container = dom('#pv-container');
@ -54,7 +59,7 @@ const centerContent = () => {
};
const updateGui = () => {
const docEl = win.document.documentElement;
const docEl = doc.documentElement;
const winWidth = docEl.clientWidth;
const winHeight = docEl.clientHeight;
const margin = isFullscreen ? 0 : 20;
@ -149,9 +154,69 @@ const onKeydown = ev => {
}
};
const onTouchstart = ev => {
const now = Date.now();
const deltaT = now - (touchState.last || now);
const touch = ev.changedTouches;
touchState = {
x: touch[0].pageX,
y: touch[0].pageY,
last: now,
deltaX: 0,
deltaY: 0,
isHorizontal: null,
isDoubleTap: touch.length === 1 && deltaT > 0 && deltaT <= TOUCH_MAX_DELAY
};
dom(doc)
.on('touchmove', onTouchmove) // eslint-disable-line no-use-before-define
.on('touchend', onTouchend); // eslint-disable-line no-use-before-define
};
const onTouchmove = ev => {
const touch = ev.changedTouches;
if (touch && touch.length > 1 || ev.scale && ev.scale !== 1) {
return;
}
touchState.deltaX = touch[0].pageX - touchState.x;
touchState.deltaY = touch[0].pageY - touchState.y;
if (touchState.isHorizontal === null) {
touchState.isHorizontal = Math.abs(touchState.deltaX) >= Math.abs(touchState.deltaY);
}
dropEvent(ev);
};
const onTouchend = ev => {
const dX = Math.abs(touchState.deltaX);
const dY = Math.abs(touchState.deltaY);
if (touchState.isDoubleTap && dX <= TOUCH_GESTURE_DISTANCE && dY <= TOUCH_GESTURE_DISTANCE) {
dropEvent(ev);
toggleFullscreen();
} else if (touchState.isHorizontal && dX > TOUCH_GESTURE_DISTANCE && Date.now() - touchState.last < TOUCH_MAX_DELAY) {
switch (touchState.deltaX > 0) {
case true:
dropEvent(ev);
prev();
break;
default:
dropEvent(ev);
next();
}
}
dom(doc)
.off('touchmove', onTouchmove)
.off('touchend', onTouchend);
};
const enter = () => {
setLabels([]);
dom('#pv-container').clr();
dom('#pv-container')
.on('touchstart', onTouchstart)
.clr();
dom('#pv-overlay').show();
dom(win).on('keydown', onKeydown);
updateGui();
@ -159,7 +224,9 @@ const enter = () => {
const exit = () => {
setLabels([]);
dom('#pv-container').clr();
dom('#pv-container')
.off('touchstart', onTouchstart)
.clr();
dom('#pv-overlay').hide();
dom(win).off('keydown', onKeydown);
};