diff options
| author | Adam Soltys <[email protected]> | 2026-10-25 07:52:27 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-10-25 07:52:27 -0700 |
| commit | 67e184a659c6a4b3251a57e0a862e3435bfda751 (patch) | |
| tree | 3aed0bd0bdb05e5568183bfe6e917f4f2d493dcb /src/features | |
| parent | 4c3ec3ea6b8d909466044071bee3b852c6bf0845 (diff) | |
| download | coinosv3-67e184a659c6a4b3251a57e0a862e3435bfda751.tar.gz coinosv3-67e184a659c6a4b3251a57e0a862e3435bfda751.zip | |
A feed clip with timed reactions seeks on the moments bar alone: the player's own controls (its seek bar) stay off, the middle play/pause shows whenever it's paused (touch too), and the sound button stays to turn it down again
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QjVvE4YAcK3AGwV7kZXeN4
Diffstat (limited to 'src/features')
| -rw-r--r-- | src/features/messages.js | 39 |
1 files changed, 32 insertions, 7 deletions
diff --git a/src/features/messages.js b/src/features/messages.js index 74b7d4a..da79671 100644 --- a/src/features/messages.js +++ b/src/features/messages.js @@ -4562,7 +4562,8 @@ export function messagesFeature(ctx) { }; const box = player.parentElement; box._skipMorph = true; - box.append(mediaTimeline(player, url, { h, event, label: t, moments: momentsOn, glyph: momentGlyph })); + box.append(mediaTimeline(player, url, { h, event, label: t, moments: momentsOn, glyph: momentGlyph, + onMarks: player.tagName === 'VIDEO' ? (on) => ownBar(player, on) : null })); player.dispatchEvent(new Event('timeupdate')); } function noteEvent(ev) { @@ -7967,7 +7968,7 @@ export function messagesFeature(ctx) { if (v) { if (v.getAttribute('src') !== playSrc(url)) v.setAttribute('src', playSrc(url)); v.preload = 'auto'; - v.play().catch(() => { wokeClips.add(url); box.classList.remove('idle'); v.controls = true; }); + v.play().catch(() => { wokeClips.add(url); box.classList.remove('idle'); nativeControls(v); }); } } }, h('span', { class: 'vid-heavy-play', 'aria-hidden': 'true' }, '\u25b6'), h('span', {}, heavyLabel(url))); box.append(cover); @@ -8108,6 +8109,25 @@ export function messagesFeature(ctx) { document.addEventListener('pointermove', (e) => { if (e.pointerType === 'mouse') mouseIs(true); }, { passive: true }); document.addEventListener('pointerdown', (e) => { if (e.pointerType !== 'mouse') mouseIs(false); }, { passive: true }); } + // A clip whose post has timed reactions seeks on the moments bar under it + // (the reactions sit on it at their moments), so the player's own controls + // — a second seek bar — stay off; the middle button and the sound button + // are its controls then (Adam: "hide the main seek bar … and only show a + // moments seek bar"). Otherwise the player's controls, once it has woken. + const nativeControls = (v) => { v.controls = !v._ownBar; }; + function ownBar(player, on) { + const box = player.closest('.note-video-box'); + if (!box || player._ownBar === on) return; + player._ownBar = on; + box.classList.toggle('own-bar', on); + if (!box.classList.contains('idle')) nativeControls(player); + // with no player controls, the sound button stays to turn it back down + if (on && !box.querySelector('.vid-sound')) { + const b = soundBtn((button) => { player.muted = !player.muted; button.setSound(!player.muted); }); + b.setSound(!player.muted); + box.append(b); + } + } const fsElement = () => (typeof document !== 'undefined' && (document.fullscreenElement || document.webkitFullscreenElement)) || null; let videoTapAt = 0; // a touch's tap on a clip, taken at pointerup: the click after it lands on whatever opened function videoTap(e, url) { @@ -8138,7 +8158,7 @@ export function messagesFeature(ctx) { wokeClips.add(url); const box = v.closest('.note-video-box'); if (box) { box.classList.remove('idle'); box._skipMorph = true; } - v.controls = true; + nativeControls(v); return true; } if (openClip(v, url)) return true; @@ -8146,7 +8166,7 @@ export function messagesFeature(ctx) { wokeClips.add(url); const box = v.closest('.note-video-box'); if (box) { box.classList.remove('idle'); box._skipMorph = true; } - v.controls = true; + nativeControls(v); const go = v.requestFullscreen || v.webkitRequestFullscreen || v.webkitEnterFullscreen; if (!go) return true; // (the screen isn't turned for it: a wide clip plays with bars, and the @@ -8239,7 +8259,7 @@ export function messagesFeature(ctx) { const wake = () => { wokeClips.add(url); box.classList.remove('idle'); - v.controls = true; + nativeControls(v); }; v.addEventListener('playing', wake); const btn = loud ? null : soundBtn((button) => { @@ -8248,14 +8268,19 @@ export function messagesFeature(ctx) { const liveBox = button.closest('.note-video-box'); const player = liveBox?.querySelector('video'); if (!player) return; + if (player._ownBar && !player.muted) { player.muted = true; button.setSound(false); return; } player.muted = false; unmutedClips.add(url); liveBox._skipMorph = true; // the box is the viewer's now: no repaint rebuilds it muted if (player.paused) player.play().catch(() => {}); - button.remove(); // the player's own controls carry mute from here + // the player's own controls carry mute from here — unless they're off + // for the moments bar: then this button turns it down again + if (player._ownBar) button.setSound(true); else button.remove(); }); v.onvolumechange = () => { - if (!v.muted) { unmutedClips.add(url); if (btn && btn.isConnected) btn.remove(); } // unmuted from the native control: same + const b = v.closest('.note-video-box')?.querySelector('.vid-sound'); + if (v._ownBar && b && b.setSound) b.setSound(!v.muted); + if (!v.muted) { unmutedClips.add(url); if (btn && btn.isConnected && !v._ownBar) btn.remove(); } // unmuted from the native control: same else unmutedClips.delete(url); // muted again from the control: the next box starts quiet }; if (btn) box.append(btn); |
