watchparty/client/src/styles/presence.css
Nicolas b2310216ce
Some checks failed
Publier l'image Docker / publish (push) Has been skipped
Publier l'image Docker / test (push) Failing after 8s
Fix settings menu visibility bug; make the music player a persistent bar
Fix: player settings menu stuck permanently open
----------------------------------------------
.hide { display: none; } and Player.css's .settingsPanel { display: flex;
... } are both single-class selectors - equal specificity - so whichever
one esbuild happened to bundle later into app.css won the `display`
property on an element carrying both classes. Player.css's own
display:flex always landed after base.css's .hide, so #settingsPanel
showed regardless of the hide class ever being toggled - the toggle logic
itself was correct the whole time, it just had no visible effect.

Fixed at the utility class, not the one call site: `.hide` now uses
`display: none !important`, which wins a same-specificity tie regardless
of bundling order - closes off the whole bug class, since several other
components already set their own `display` for a visible state.

Feature: music player is now a persistent bottom bar, not a page
------------------------------------------------------------------
The music player was its own route (/party/:id -> views/musicPlayer/),
which meant navigating anywhere else - the sidebar, an album to queue up
more tracks - tore the whole thing down (router.ts calls a route's
cleanup, which used to call leaveParty, on every hash change). No way to
browse and listen at the same time.

- client/src/musicBar/MusicBar.ts (new): a Shell-level singleton, mounted
  once into a #musicBar element that's a sibling of #mainContent, never
  touched by route changes. Renders as a fixed bottom bar. Exposes
  initMusicBar/joinMusicParty/leaveMusicParty instead of the router's
  render()-returns-cleanup pattern, since it never registers as a route.
- views/player/Player.ts's dispatcher: a music party no longer renders a
  page - it calls joinMusicParty() and bounces back to /home (a no-op for
  every reachable call site except album's). A video party now calls
  leaveMusicParty() first (harmless no-op if nothing's active) - starting
  or joining a video watch party always leaves the listen party, since
  every party-join call site already funnels through this one dispatcher.
- views/album/Album.ts: the last per-track "start a party" UI now that
  the music player's own inline browse panel is gone (browsing just
  means navigating there normally). Each track's button starts a new
  party or adds to whichever one is already active, decided by
  getActiveMusicPartyId() at CLICK time (not render time) so the action
  taken is always correct even if the label is momentarily stale; every
  button is relabeled in place after a successful click. Starting a
  party from here no longer navigates away at all.
- views/musicPlayer/ deleted entirely (MusicPlayer.ts/.html/.css) -
  superseded by musicBar/.
- Comment updates in global.d.ts/presence.css/trackList.css/party.ts/
  types.ts that named the old module by path.

Verified both fixes by rebuilding and driving the real compiled bundle
through a local static server, with fetch/window.io/window.Hls mocked:
starting a party from an album track leaves the sidebar/page in place and
relabels the other tracks; adding a track posts to the already-active
party's id; navigating into a video party hides the bar, disconnects its
socket, and posts a real leave for the music party before the video
player renders; the settings gear opens/closes correctly for the host in
that same run.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-14 10:43:12 +02:00

25 lines
764 B
CSS

/* Shared base for the "who's here" circle, used by both the video player
(Player.css adds the click-to-request-pause states on top) and the
music bar (which just shows presence, no per-avatar interaction - see
MusicBar.css's .musicBarPresence for its size/positioning tweak). */
.presenceOverlay {
display: flex;
gap: 8px;
}
.avatar {
position: relative;
width: 36px;
height: 36px;
flex-shrink: 0;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 13px;
font-weight: 700;
color: white;
opacity: .75; /* "overlay en semi transparence" - background color comes from an inline style, see colorForName() in tiles.ts */
border: 2px solid rgba(255, 255, 255, .3);
user-select: none;
}