mirror of
https://github.com/Shik3i/KoalaSync.git
synced 2026-08-28 11:37:16 +00:00
feat(protocol): add host control mode events & constants
Step 1 of host control mode. Adds the protocol surface only — no behavior yet:
- EVENTS.SET_CONTROL_MODE (client->server: host sets mode)
- EVENTS.CONTROL_MODE (server->client: mode changed)
- CONTROL_MODES { EVERYONE, HOST_ONLY }
Purely additive; old clients ignore the new events. Propagated to
extension/shared via build-extension. Also records the audited design
decisions in the edge-case log.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -204,9 +204,25 @@ Host hammering the toggle → many `SET_CONTROL_MODE`. Covered by existing
|
|||||||
| Disney+ / DRM | | | | | |
|
| Disney+ / DRM | | | | | |
|
||||||
| Jellyfin / Emby | | | | | |
|
| Jellyfin / Emby | | | | | |
|
||||||
|
|
||||||
## 8. Open decisions to lock before/while coding
|
## 8. Decisions (audited)
|
||||||
- [ ] Intent-classifier signal set (EC-9) — design first.
|
- [x] **Intent-classifier (EC-9):** A `pause`/`seek` is **involuntary** if ANY of:
|
||||||
- [ ] Host grace period on disconnect, yes/no + duration (EC-10).
|
`readyState < 3`, `video.seeking`, a `waiting` fired < ~1500ms ago (`isBuffering`
|
||||||
- [ ] Desync semantics: full solo vs receive-only (EC-12).
|
flag), inside `visibilityGraceUntil`, OR no own-tracked user gesture
|
||||||
- [ ] Snap-back cooldown duration + retry cap (EC-4).
|
(`Date.now() - lastUserGestureAt < 1000`, via capturing keydown/pointerdown — do
|
||||||
- [ ] Does host-only apply to live streams or degrade (EC-15)?
|
NOT use sticky `navigator.userActivation.hasBeenActive`). Bias: only *clearly*
|
||||||
|
involuntary is ignored; everything else = deliberate. **Note:** in host-only the
|
||||||
|
guest never broadcasts anyway, so this only decides dialog-vs-silent — a UX call,
|
||||||
|
not a room-integrity call. Start simple, tune later.
|
||||||
|
- [x] **Host grace on disconnect (EC-10): NOT in v1.** Immediate fallback to
|
||||||
|
`everyone` (EC-3). A grace window risks a multi-second hard-lock if the host never
|
||||||
|
returns. Revisit as polish once the core flow works.
|
||||||
|
- [x] **Desync semantics (EC-12): full solo.** Ignore host play/pause/seek while
|
||||||
|
desynced; Resync snaps to host position + adopts host play/pause state. Desync
|
||||||
|
auto-clears on new media/episode. Requires a persistent, obvious "You are desynced"
|
||||||
|
UI.
|
||||||
|
- [x] **Snap-back cooldown (EC-4): until-settled, not fixed.** Suppress re-trigger
|
||||||
|
until `readyState>=3 && playing && |Δt|<tol`, hard-cap ~1500ms. Retry target up to
|
||||||
|
3×, then give up (no infinite loop).
|
||||||
|
- [x] **Live streams (EC-15): degrade.** Disable the gate when
|
||||||
|
`video.duration === Infinity`. Caveat: live-DVR may report finite duration and slip
|
||||||
|
through — acceptable for v1.
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ export const EVENTS = {
|
|||||||
ROOM_DATA: "room_data", // Server -> Client: current room state
|
ROOM_DATA: "room_data", // Server -> Client: current room state
|
||||||
ERROR: "error",
|
ERROR: "error",
|
||||||
|
|
||||||
|
// Host Control Mode
|
||||||
|
SET_CONTROL_MODE: "set_control_mode", // Client -> Server: host sets room control mode ('everyone' | 'host-only')
|
||||||
|
CONTROL_MODE: "control_mode", // Server -> Client: room control mode changed { controlMode, hostPeerId }
|
||||||
|
|
||||||
// Media Control
|
// Media Control
|
||||||
PLAY: "play",
|
PLAY: "play",
|
||||||
PAUSE: "pause",
|
PAUSE: "pause",
|
||||||
@@ -57,6 +61,14 @@ export const EVENTS = {
|
|||||||
PONG: "pong" // server responds with same { t } for client RTT calculation
|
PONG: "pong" // server responds with same { t } for client RTT calculation
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Room control modes (Host Control Mode feature).
|
||||||
|
// NOTE: content.js does not import this module — it uses the string literals
|
||||||
|
// 'everyone' / 'host-only' directly. Keep these values in sync there.
|
||||||
|
export const CONTROL_MODES = {
|
||||||
|
EVERYONE: 'everyone', // default: anyone can play/pause/seek for the room
|
||||||
|
HOST_ONLY: 'host-only' // only the host drives the room
|
||||||
|
};
|
||||||
|
|
||||||
export const HEARTBEAT_INTERVAL = 15000; // 15s
|
export const HEARTBEAT_INTERVAL = 15000; // 15s
|
||||||
export const FORCE_SYNC_TIMEOUT = 8500; // 8.5s timeout for force sync ACKs (must be > content.js poll timeout of 8s)
|
export const FORCE_SYNC_TIMEOUT = 8500; // 8.5s timeout for force sync ACKs (must be > content.js poll timeout of 8s)
|
||||||
export const EPISODE_LOBBY_TIMEOUT = 60000; // 60s timeout for episode lobby
|
export const EPISODE_LOBBY_TIMEOUT = 60000; // 60s timeout for episode lobby
|
||||||
|
|||||||
Reference in New Issue
Block a user