fix(host-control-mode): harden gates, close UX races, debounce toggles, surface desync state

Bis auf peerId-Auth (akzeptiert) alle Audit-Findings behoben:
- Snap-back spielt nicht mehr blind ab, wenn Host-Status unbekannt
- Teardown-Pfade broadcasten jetzt CONTROL_MODE → kein verwaistes Badge/Dialog
- Dialog-Timer bei Ersetzung sauber gecleart
- Server re-synchronisiert Sender bei nicht-Host-Reject
- Popup-Toggle revertiert bei Server-Ablehnung
- Desync-Zweig sendet keine Phantom-ACKs mehr an Host
- Toggle-Debouncing serverseitig (500ms pro Raum)
- Button-Text auf Unlock zurückgesetzt
- Live-Erkennung defensiver, Resync-Retry bei fehlendem Target, Badge-Retry

Neu: Host sieht 'Solo'-Badge für desyncte Gäste via PEER_STATUS-Heartbeat
(16 Sprachen, neuer i18n-Key BADGE_DESYNCED/TOOLTIP_PEER_DESYNCED)

Tests: H-5-Reject-Unicast, M-4-Debounce, Desync-Heartbeat-Relay
This commit is contained in:
KoalaDev
2026-06-26 13:07:17 +02:00
parent 69f8f4cfd7
commit 58af258fd3
20 changed files with 245 additions and 20 deletions
+2
View File
@@ -50,6 +50,8 @@
"NOTICE_HOST_CONTROLS": "Der Host steuert die Wiedergabe für alle.",
"BADGE_HOST": "Host",
"BADGE_GUEST": "Gast",
"BADGE_DESYNCED": "Solo",
"TOOLTIP_PEER_DESYNCED": "Schaut alleine — ignoriert die Befehle des Hosts",
"NO_PEERS_CONNECTED": "Keine Teilnehmer verbunden",
"BTN_LEAVE_ROOM": "Raum verlassen",
"LABEL_SELECT_VIDEO": "Video auswählen",
+2
View File
@@ -50,6 +50,8 @@
"NOTICE_HOST_CONTROLS": "The host controls playback for everyone.",
"BADGE_HOST": "Host",
"BADGE_GUEST": "Guest",
"BADGE_DESYNCED": "Solo",
"TOOLTIP_PEER_DESYNCED": "Watching on their own — host's commands are ignored",
"NO_PEERS_CONNECTED": "No peers connected",
"BTN_LEAVE_ROOM": "Leave Room",
"LABEL_SELECT_VIDEO": "Select Video",
+2
View File
@@ -50,6 +50,8 @@
"NOTICE_HOST_CONTROLS": "El anfitrión controla la reproducción para todos.",
"BADGE_HOST": "Anfitrión",
"BADGE_GUEST": "Invitado",
"BADGE_DESYNCED": "Solo",
"TOOLTIP_PEER_DESYNCED": "Viendo por su cuenta — ignora los comandos del anfitrión",
"NO_PEERS_CONNECTED": "Sin participantes conectados",
"BTN_LEAVE_ROOM": "Salir de la sala",
"LABEL_SELECT_VIDEO": "Seleccionar video",
+2
View File
@@ -50,6 +50,8 @@
"NOTICE_HOST_CONTROLS": "L'hôte contrôle la lecture pour tout le monde.",
"BADGE_HOST": "Hôte",
"BADGE_GUEST": "Invité",
"BADGE_DESYNCED": "Solo",
"TOOLTIP_PEER_DESYNCED": "Regarde de son côté — ignore les commandes de l'hôte",
"NO_PEERS_CONNECTED": "Aucun membre connecté",
"BTN_LEAVE_ROOM": "Quitter le salon",
"LABEL_SELECT_VIDEO": "Choisir une vidéo",
+2
View File
@@ -50,6 +50,8 @@
"NOTICE_HOST_CONTROLS": "L'host controlla la riproduzione per tutti.",
"BADGE_HOST": "Host",
"BADGE_GUEST": "Ospite",
"BADGE_DESYNCED": "Solo",
"TOOLTIP_PEER_DESYNCED": "Guarda per conto proprio — ignora i comandi dell'host",
"NO_PEERS_CONNECTED": "Nessun partecipante connesso",
"BTN_LEAVE_ROOM": "Lascia Stanza",
"LABEL_SELECT_VIDEO": "Seleziona Video",
+2
View File
@@ -50,6 +50,8 @@
"NOTICE_HOST_CONTROLS": "ホストが全員の再生を操作します。",
"BADGE_HOST": "ホスト",
"BADGE_GUEST": "ゲスト",
"BADGE_DESYNCED": "ソロ",
"TOOLTIP_PEER_DESYNCED": "単独で視聴中 — ホストのコマンドを無視しています",
"NO_PEERS_CONNECTED": "接続しているメンバーはいません",
"BTN_LEAVE_ROOM": "ルームを退室",
"LABEL_SELECT_VIDEO": "ビデオを選択",
+2
View File
@@ -50,6 +50,8 @@
"NOTICE_HOST_CONTROLS": "호스트가 모두의 재생을 제어합니다.",
"BADGE_HOST": "호스트",
"BADGE_GUEST": "게스트",
"BADGE_DESYNCED": "단독",
"TOOLTIP_PEER_DESYNCED": "혼자 시청 중 — 호스트 명령을 무시합니다",
"NO_PEERS_CONNECTED": "연결된 참여자가 없습니다",
"BTN_LEAVE_ROOM": "방 나가기",
"LABEL_SELECT_VIDEO": "비디오 선택",
+2
View File
@@ -50,6 +50,8 @@
"NOTICE_HOST_CONTROLS": "De host bedient de weergave voor iedereen.",
"BADGE_HOST": "Host",
"BADGE_GUEST": "Gast",
"BADGE_DESYNCED": "Solo",
"TOOLTIP_PEER_DESYNCED": "Zelfstandig aan het kijken — negeert de commando's van de host",
"NO_PEERS_CONNECTED": "Geen deelnemers verbonden",
"BTN_LEAVE_ROOM": "Kamer verlaten",
"LABEL_SELECT_VIDEO": "Selecteer video",
+2
View File
@@ -50,6 +50,8 @@
"NOTICE_HOST_CONTROLS": "Host steruje odtwarzaniem dla wszystkich.",
"BADGE_HOST": "Host",
"BADGE_GUEST": "Gość",
"BADGE_DESYNCED": "Solo",
"TOOLTIP_PEER_DESYNCED": "Ogląda samodzielnie — ignoruje polecenia hosta",
"NO_PEERS_CONNECTED": "Brak połączonych uczestników",
"BTN_LEAVE_ROOM": "Opuść pokój",
"LABEL_SELECT_VIDEO": "Wybierz wideo",
+2
View File
@@ -50,6 +50,8 @@
"NOTICE_HOST_CONTROLS": "O anfitrião controla a reprodução para todos.",
"BADGE_HOST": "Anfitrião",
"BADGE_GUEST": "Convidado",
"BADGE_DESYNCED": "Solo",
"TOOLTIP_PEER_DESYNCED": "Assistindo por conta própria — ignora os comandos do anfitrião",
"NO_PEERS_CONNECTED": "Sem participantes conectados",
"BTN_LEAVE_ROOM": "Sair da sala",
"LABEL_SELECT_VIDEO": "Selecionar vídeo",
+2
View File
@@ -50,6 +50,8 @@
"NOTICE_HOST_CONTROLS": "O anfitrião controla a reprodução para todos.",
"BADGE_HOST": "Anfitrião",
"BADGE_GUEST": "Convidado",
"BADGE_DESYNCED": "Solo",
"TOOLTIP_PEER_DESYNCED": "A ver por conta própria — ignora os comandos do anfitrião",
"NO_PEERS_CONNECTED": "Nenhum participante ligado",
"BTN_LEAVE_ROOM": "Sair da Sala",
"LABEL_SELECT_VIDEO": "Selecionar Vídeo",
+2
View File
@@ -50,6 +50,8 @@
"NOTICE_HOST_CONTROLS": "Ведущий управляет воспроизведением для всех.",
"BADGE_HOST": "Ведущий",
"BADGE_GUEST": "Гость",
"BADGE_DESYNCED": "Соло",
"TOOLTIP_PEER_DESYNCED": "Смотрит отдельно — игнорирует команды ведущего",
"NO_PEERS_CONNECTED": "Нет подключенных участников",
"BTN_LEAVE_ROOM": "Выйти из комнаты",
"LABEL_SELECT_VIDEO": "Выбрать видео",
+2
View File
@@ -50,6 +50,8 @@
"NOTICE_HOST_CONTROLS": "Oynatmayı herkes için sunucu kontrol eder.",
"BADGE_HOST": "Sunucu",
"BADGE_GUEST": "Misafir",
"BADGE_DESYNCED": "Solo",
"TOOLTIP_PEER_DESYNCED": "Tek başına izliyor — sunucu komutlarını yok sayar",
"NO_PEERS_CONNECTED": "Bağlı kimse yok",
"BTN_LEAVE_ROOM": "Odadan Ayrıl",
"LABEL_SELECT_VIDEO": "Video Seç",
+2
View File
@@ -50,6 +50,8 @@
"NOTICE_HOST_CONTROLS": "Ведучий керує відтворенням для всіх.",
"BADGE_HOST": "Ведучий",
"BADGE_GUEST": "Гість",
"BADGE_DESYNCED": "Соло",
"TOOLTIP_PEER_DESYNCED": "Дивиться окремо — ігнорує команди ведучого",
"NO_PEERS_CONNECTED": "Немає підключених однорангових пристроїв",
"BTN_LEAVE_ROOM": "Вийти з кімнати",
"LABEL_SELECT_VIDEO": "Виберіть Відео",
+2
View File
@@ -50,6 +50,8 @@
"NOTICE_HOST_CONTROLS": "由主持人为所有人控制播放。",
"BADGE_HOST": "主持人",
"BADGE_GUEST": "访客",
"BADGE_DESYNCED": "单独",
"TOOLTIP_PEER_DESYNCED": "单独观看中 — 忽略主持人的命令",
"NO_PEERS_CONNECTED": "没有对等点连接",
"BTN_LEAVE_ROOM": "离开房间",
"LABEL_SELECT_VIDEO": "选择视频",