Move the request-pause/resume buttons off the subtitle zone
All checks were successful
Publier l'image Docker / test (push) Successful in 22s
Publier l'image Docker / publish (push) Successful in 8s

Asked for directly: .requestToolbar (the non-host's "Demander une
pause"/"Demander une reprise" buttons) shared .bottomOverlay's
centered-bottom column with the request banner and the follower
notice - which is also exactly where a native <track> subtitle
renders. Real, clickable buttons sitting there for the whole session
is a worse problem than the banner (transient, 4s) or the notice
(static text) occasionally doing the same.

Pulled #requestToolbar out of .bottomOverlay into its own sibling
block in Player.html, positioned independently in the bottom-right
corner instead (position: absolute; right: 16px; bottom: 20px), and
stacked as a column (align-items: flex-end) rather than a row so the
two pill buttons never fight a narrow phone screen for width side by
side. .bottomOverlay itself is untouched - still centered-bottom,
still just the banner and the notice.

Verified against the real bundle (mocked-fetch + real dist, this
session's standing harness) as a follower at both desktop and phone
width: the two buttons render bottom-right, clear of the (still
centered) follower notice, at both widths. Client typecheck/build
clean. docs/architecture.md updated.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Nicolas 2026-09-14 23:08:28 +02:00
parent 8718175bae
commit 8c9852d854
4 changed files with 63 additions and 15 deletions

View file

@ -139,7 +139,12 @@
comment, and docs/architecture.md for the exact bug this avoided: a
<p>'s default margin silently throwing off a hand-picked bottom offset
on the element above it - not repeatable once nothing is positioned
independently any more). */
independently any more). Centered on purpose - this is exactly where
a native <track> subtitle renders too, but both children here are
passive text (a transient banner, a static notice), not something a
viewer needs to click through subtitle text to reach - unlike
.requestToolbar below, which used to live in this same column and
was moved out for exactly that reason. */
.bottomOverlay {
position: absolute;
bottom: 20px;
@ -174,10 +179,25 @@
Player.ts's requestPauseBtn/requestResumeBtn. Pill buttons matching
the banner/notice's own dark-overlay look above, not the plain-text
.linklike used in the (opaque) top action bar - this sits directly on
top of the video image, same as the rest of .bottomOverlay. */
top of the video image, same as .bottomOverlay.
Its own bottom-RIGHT corner, independently of .bottomOverlay -
deliberately not centered-bottom any more (see .bottomOverlay's own
comment): that's also where a native <track> subtitle renders, and
these are real buttons someone needs to read and click, not passive
text a subtitle could just as easily sit behind. Stacked as a column
(not a row, unlike the old centered layout) so two pill buttons next
to each other never has to fight a narrow phone screen for width -
each just takes however much it needs, right-aligned under the other. */
.requestToolbar {
position: absolute;
right: 16px;
bottom: 20px;
z-index: 6;
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 8px;
max-width: calc(50% - 16px);
}
.requestBtn {
@ -186,6 +206,7 @@
padding: 8px 14px;
border-radius: 20px;
font-size: 12.5px;
white-space: nowrap; /* keeps the pill shape even in .requestToolbar's own narrow corner on a phone-width screen */
}
.requestBtn:hover { background: rgba(0, 0, 0, .8); }

View file

@ -31,16 +31,21 @@
<!-- Stacked as one column (same reasoning as .topOverlay's own
actionBar+presenceOverlay grouping - see Player.css) so the
transient banner, the passive notice and the request toolbar
always sit in the right order relative to each other regardless
of which are visible at a given moment, instead of each guessing
a fixed pixel offset from the bottom edge. -->
transient banner and the passive notice always sit in the right
order relative to each other regardless of which is visible at a
given moment, instead of each guessing a fixed pixel offset from
the bottom edge. The request toolbar (the actual buttons) used to
live here too, third in this same column - moved out to its own
bottom-right corner instead (see .requestToolbar in Player.css):
centered-bottom is also where a native <track> subtitle renders,
and the buttons sat right on top of it. -->
<div class="bottomOverlay">
<div id="requestBanner" class="requestBanner hide"></div>
<p id="followerNotice" class="followerNotice hide">L'hôte contrôle la lecture.</p>
</div>
<div id="requestToolbar" class="requestToolbar hide">
<button id="requestPauseBtn" class="requestBtn">Demander une pause</button>
<button id="requestResumeBtn" class="requestBtn">Demander une reprise</button>
</div>
</div>
</div>

View file

@ -636,11 +636,14 @@ function renderVideoPlayer(root: HTMLElement, partyId: string, party: PartyPubli
showRequestBanner(msg.userId, msg.userName, 'une reprise');
}
// The toolbar itself - see .bottomOverlay/.requestToolbar in Player.css
// for why this replaced the old "click your own avatar" affordance.
// Each button has its own client-side cooldown (mirroring the server's
// own independent per-request throttle in SocketGateway) purely so a
// rapid double-click doesn't even bother emitting the second request.
// The toolbar itself - see .requestToolbar in Player.css for why this
// replaced the old "click your own avatar" affordance, and for why it
// sits in its own bottom-right corner rather than centered-bottom like
// .bottomOverlay next to it (that's also where a native <track>
// subtitle renders). Each button has its own client-side cooldown
// (mirroring the server's own independent per-request throttle in
// SocketGateway) purely so a rapid double-click doesn't even bother
// emitting the second request.
requestPauseBtn.addEventListener('click', () => {
const now = Date.now();
if (now < pauseRequestCooldownUntil || !conn) return;

View file

@ -409,6 +409,25 @@ button's own client-side cooldown collapses a rapid double-click to one
`requestResume` emission; a pushed `resumeRequested` shows the banner
with the right text and highlights the right avatar.
**Much later still: moved the toolbar off the subtitle zone.** Asked
for directly - `.requestToolbar` shared `.bottomOverlay`'s centered
column with the banner/follower-notice above, which is also exactly
where a native `<track>` subtitle renders (see "Player track
selection" below): real, clickable buttons sitting on top of subtitle
text, for the whole session, is a worse problem than a transient
banner or static notice occasionally doing the same. Pulled `#request
Toolbar` out into its own sibling block in `Player.html`, positioned
independently in the bottom-right corner (`position: absolute; right:
16px; bottom: 20px`) and stacked as a column instead of a row (`align-
items: flex-end`) so two pill buttons never have to fight a narrow
phone screen for width side by side. `.bottomOverlay` itself is
untouched - still centered-bottom, still just the banner and the
notice, neither of which is something a viewer needs to click through
subtitle text to reach. Verified against the real bundle at both
desktop and phone width: the two buttons render bottom-right,
non-overlapping with the (still centered) follower notice, in both
widths.
## Player track selection: forcing our pick onto Emby's own negotiation
First real-world bug report once someone actually watched something end to