Skip to content

feat(desktop): Watch Together on the desktop (phase 3) - #534

Open
playbridgeapp wants to merge 3 commits into
feat/watch-together-androidfrom
feat/watch-together-desktop
Open

playbridgeapp wants to merge 3 commits into
feat/watch-together-androidfrom
feat/watch-together-desktop

Conversation

@playbridgeapp

@playbridgeapp playbridgeapp commented Nov 10, 2026 •

Copy link
Copy Markdown
Owner

Phase 3 of Watch Together (docs/design-watch-together.md): the desktop as a screen, a remote and a host. Stacked on #533; retarget to main once #533 merges.

Desktop

  • Watch Together screen in the sidebar: start a party (shared relay or your own), join with a link, or show a code and QR so a phone can add this computer.
  • Screen: "Watch on this computer" (on unless a TV is the chosen screen) plays the party video in the desktop player, loaded paused, outside history and resume points. Play, pause and seek from keys, the player, media keys, the extension or a phone remote go to the party; speed nudges bypass the speed ladder. Hiding the window and "Still watching?" don't pause a party. Playing something else or stopping the player turns this computer into a remote.
  • Remote and host: play, pause, seek, copy the invite, add the connected PlayBridge TV (it becomes this computer's own and, for the host, its delegate) or a TV by code, lock, who can change the video, requests, sign-in sharing.
  • Paired phone handoff: the desktop advertises watch_together_v1; the Rust receiver passes an authenticated sender's watch_together_join to the app, which joins and answers watch_together_joined with its member ID and keys.
  • Extension: a video sent during a party plays in the party (direct links; synthetic playlists are refused).
  • Dart binding for pb_together_* in packages/playbridge_cast_core_dart; desktop builds (script and PR CI) include the together feature.

Engine (all platforms)

  • The room pauses once no device shows the video, and a video waits for a screen before it starts. Found while testing: with every player stopped, the party clock kept running.
  • Live streams (every screen loaded them with no length) share only playing or paused: no seeks or speed nudges, since live positions differ per device.
    • The room announces a live party; the phone and desktop party screens hide seeking, and seeks are refused.
    • A buffering device doesn't pause a live party (that would put everyone behind live).
    • Play after a pause jumps every device to its live point (go_live: ExoPlayer default position, mpv seek 100 absolute-percent; new seekToLive on the TV renderer interface).
    • TV fix: when it isn't told in time whether a video is live, it uses the length it already knows instead of assuming live.
  • Phone, TV and desktop native libraries rebuilt.

Tests

  • Desktop: 449 Flutter tests, including 10 new Watch Together tests.
  • Dart binding: 5 new tests. Kotlin: shared, phone and TV unit tests and builds.
  • Rust: 27 + 17 together tests (3 new simulations, live covered for buffering, seeks and go-live), 51 FFI tests, receiver handoff test; fmt and clippy clean.
  • On this Mac: a desktop-hosted party with the Samsung joining worked, and with the new engine the party paused once both players were stopped. Live streams are covered by simulations only. Windows and Linux share the code but are untested.

- Dart binding for pb_together_* in playbridge_cast_core
- Watch Together screen: start or join, show a code for a phone, party controls
- the party drives the desktop player; play, pause and seek go to the party
- a paired phone can add the Mac (watch_together_join), and the Mac can add
  its connected PlayBridge TV
- extension casts during a party play in the party
- desktop builds include the together feature
…pause

- the leader pauses the party once no device shows the video, and a video
  waits for a screen before it starts
- live streams (loaded with no length) share only playing or paused: no seeks
  or speed nudges
- rebuild the phone and TV native libraries
- a TV that isn't told in time whether a video is live uses its known length
- live parties don't pause for a buffering device; play after a pause jumps
  every device to its live point (go_live), on ExoPlayer and mpv
- the room announces live parties; phone and desktop party screens hide
  seeking, and seeks are refused
- rebuild the phone, TV and desktop native libraries
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant