Leave the controls down while swiping through reels
Scrolling woke the HUD, so a swipe to the next reel put the controls up over the video arriving -- the one thing the swipe was for -- and left them there for a second. The scroll now puts them away instead. Removing that alone wasn't enough: the container also woke on pointerdown and touchstart, which is how every drag begins, so the HUD still flashed at the start of one. A press only wakes them now if it lands on a control -- which is a press on something the reader can't see while they're hidden, and never the start of a swipe. A press that turns out to be a tap still wakes them through the gesture layer's onSingleTap, the mouse moving still wakes them, and dragging the scrubber keeps them up, being the one drag that is the HUD. Two details follow from it. The sleep sits after onScroll's suppressScroll guard, so a resize or a picture-in-picture re-snap doesn't count as the reader moving. And opening the feed scrolls to the starting step, whose scroll event would put the controls straight back down, so that wake waits a frame -- scroll events run before animation frames. The checks live in their own file rather than in smoke_reels: one panel and one swipe is all they need, and the split-panel suite is the heaviest thing in the tree to run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MPZFnNdHbPGDTqQUNiE4ZN
This commit is contained in:
@@ -92,6 +92,21 @@ App.feed = App.feed || {};
|
||||
if (state.feedOpen) scheduleHudHide();
|
||||
};
|
||||
|
||||
// Moving through the feed is not using the HUD. A swipe to the next reel
|
||||
// used to put the controls up over the video arriving -- the one thing the
|
||||
// swipe was for -- and leave them there for a second. So the scroll puts
|
||||
// them away instead, and only a real interaction (a tap, the mouse moving,
|
||||
// a control being used) brings them back.
|
||||
const sleepHud = function() {
|
||||
if (hudIdleTimer) {
|
||||
clearTimeout(hudIdleTimer);
|
||||
hudIdleTimer = null;
|
||||
}
|
||||
setHudIdle(true);
|
||||
const root = getRoot();
|
||||
if (root) root.querySelectorAll('.feed-format-menu').forEach((menu) => { menu.hidden = true; });
|
||||
};
|
||||
|
||||
const inRoot = function(id) {
|
||||
const root = getRoot();
|
||||
return root ? root.querySelector(`#${id}`) : null;
|
||||
@@ -287,6 +302,8 @@ App.feed = App.feed || {};
|
||||
|
||||
timeline.addEventListener('pointerdown', (event) => {
|
||||
scrubbing = true;
|
||||
// Dragging the scrubber is the one drag that *is* the HUD.
|
||||
wakeHud();
|
||||
timeline.classList.add('is-scrubbing');
|
||||
timeline.setPointerCapture(event.pointerId);
|
||||
seekFromPointer(slide, video, timeline, event.clientX);
|
||||
@@ -296,6 +313,7 @@ App.feed = App.feed || {};
|
||||
|
||||
timeline.addEventListener('pointermove', (event) => {
|
||||
if (!scrubbing) return;
|
||||
wakeHud();
|
||||
seekFromPointer(slide, video, timeline, event.clientX);
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
@@ -1153,7 +1171,6 @@ App.feed = App.feed || {};
|
||||
};
|
||||
|
||||
const onScroll = function() {
|
||||
wakeHud();
|
||||
if (scrollRaf) return;
|
||||
scrollRaf = requestAnimationFrame(() => {
|
||||
scrollRaf = null;
|
||||
@@ -1162,6 +1179,7 @@ App.feed = App.feed || {};
|
||||
// Ignore scroll events fired by a resize/orientation re-snap; the
|
||||
// active video is realigned by onResize instead (see suppressScroll).
|
||||
if (suppressScroll) return;
|
||||
sleepHud();
|
||||
peekIncoming(scroller);
|
||||
if (peekSettleTimer) clearTimeout(peekSettleTimer);
|
||||
peekSettleTimer = setTimeout(settlePeek, PEEK_SETTLE_MS);
|
||||
@@ -1646,8 +1664,18 @@ App.feed = App.feed || {};
|
||||
|
||||
if (!hudActivityBound) {
|
||||
container.addEventListener('mousemove', wakeHud, { passive: true });
|
||||
container.addEventListener('pointerdown', wakeHud, { passive: true });
|
||||
container.addEventListener('touchstart', wakeHud, { passive: true });
|
||||
// A press on the video is how a swipe begins, and waking on that
|
||||
// flashed the HUD at the start of every drag -- a press that turns
|
||||
// out to be a tap wakes it through the gesture layer's onSingleTap
|
||||
// instead. A press on a control is not a swipe, and the control it
|
||||
// lands on is one the reader can't see while the HUD is hidden.
|
||||
container.addEventListener('pointerdown', (event) => {
|
||||
const target = event.target;
|
||||
if (target && target.closest &&
|
||||
target.closest('button, input, a, .feed-timeline, .feed-format-menu')) {
|
||||
wakeHud();
|
||||
}
|
||||
}, { passive: true });
|
||||
hudActivityBound = true;
|
||||
}
|
||||
|
||||
@@ -1666,7 +1694,10 @@ App.feed = App.feed || {};
|
||||
|
||||
App.feed.updateToggleButton();
|
||||
App.feed.updateMuteButton();
|
||||
wakeHud();
|
||||
// The scroll assignment above fires a scroll event, which puts the HUD
|
||||
// away; the controls should be up when the feed opens, so this waits
|
||||
// for that to land (scroll events run before animation frames).
|
||||
requestAnimationFrame(wakeHud);
|
||||
};
|
||||
|
||||
App.feed.close = function() {
|
||||
|
||||
Reference in New Issue
Block a user