clone

a desktop tv and program guide for over-the-air broadcasts: what's on air, what your tuner gets, live tv, recordings

Know a Galaxy phone as a touch screen, and take a finger's gestures in any layout

FelineStateMachine committed 6129c5c
A browser counted as a touch screen only if it had no fine pointer at all. A
Galaxy phone with an S Pen reports one, so it got the desktop layout, where
nothing answered a tap or a swipe on the picture. Now its main pointer
decides. Taps and swipes are also taken from a finger in any layout, as on a
laptop's touch screen.

On TV a swipe over the banner, or over the timeline, counts as one over the
picture. The browser no longer takes a drag on the banner as a scroll, which
ended the swipe.
commit
6129c5cc215d1cf96465e8d95f51f0b14a43c950
parent
f6cf4475353c7a4ce39af19307372557698e221a
author
FelineStateMachine <226808055+FelineStateMachine@users.noreply.github.com>
kind
feat risk score 2.1 of 3, Jev's estimate
4 files changed, +18 -12
MREADME.md5+++--
Mfrontend/dist/js/touch.js17++++++++++-------
Mfrontend/dist/style.css2+-
Mfrontend/dist/web.js6++++--
M README.md +3 -2
M frontend/dist/js/touch.js +10 -7
@@ -17,7 +17,9 @@ const TOUCH_SWIPE = 48; // CSS pixels a finger travels for a swipe
1717 const TOUCH_HOLD_MS = 550; // a press this long is a hold1818 const TOUCH_MOUSE_MS = 1000; // a finger's stand-in mouse events follow it within this1919 20-const touching = (e) => platform === 'touch' && e.pointerType !== 'mouse';20+// A finger's or a pen's pointer: its gestures are a finger's in any21+// layout, as on a laptop's touch screen.22+const touching = (e) => e.pointerType !== 'mouse';2123 2224 // A finger also sends a mouse's events after it, for pages made for one.2325 // Here they'd act twice: its move is a pointer brought to the screen, which
@@ -25,9 +27,10 @@ const touching = (e) => platform === 'touch' && e.pointerType !== 'mouse';
2527 // double click, which plays what the second tap already played. What a2628 // finger does is handled here, from its pointer events.2729 const fromFinger = () => performance.now() - touch.at < TOUCH_MOUSE_MS;30+const fingerTap = () => platform === 'touch' || fromFinger();2831 2932 function wireTouch() {30- const lastFinger = (e) => { if (e.pointerType !== 'mouse') touch.at = performance.now(); };33+ const lastFinger = (e) => { if (touching(e)) touch.at = performance.now(); };3134 document.addEventListener('pointerdown', (e) => {3235 lastFinger(e);3336 if (!touching(e)) return;
@@ -68,17 +71,17 @@ function wireTouch() {
6871 // click only to what listens for one, and first (capture), so a tap on6972 // the picture elsewhere, which goes back to TV (wireDock), isn't one.7073 const tapTV = (e) => {71- if (platform !== 'touch' || state.view !== 'tv' || document.body.classList.contains('booting')) return;74+ if (!fingerTap() || state.view !== 'tv' || document.body.classList.contains('booting')) return;7275 if (e.target.closest('button, input, a, .tl, [data-act]')) return;7376 if (osd.open) hideBanner(); else openOSD(null);7477 };7578 for (const el of [stage, $('#banner')]) el.addEventListener('click', tapTV, true);7679 }7780 78-// swipe acts on a swipe over el: on TV, the arrows; in the guide, the79-// hours shown.81+// swipe acts on a swipe over el: on TV, over the picture or the banner,82+// the arrows; in the guide, the hours shown.8083 function swipe(el, dir) {81- if (state.view === 'tv' && (stage.contains(el) || el === document.body)) {84+ if (state.view === 'tv' && !el.closest('#dock')) {8285 if (dir === 'left' || dir === 'right') {8386 skip(dir === 'right' ? 30 : -10);8487 return openOSD('timeline');
@@ -105,4 +108,4 @@ function holdCell(cell) {
105108 106109 // tappedAgain reports whether a tap lands on what was already picked: the107110 // guide's, Recordings' and Podcasts' second tap does it.108-const tappedAgain = (was, now) => platform === 'touch' && was === now;111+const tappedAgain = (was, now) => fingerTap() && was === now;
M frontend/dist/style.css +1 -1
M frontend/dist/web.js +4 -2