diff --git a/extension/background.js b/extension/background.js index d1193db..0173498 100644 --- a/extension/background.js +++ b/extension/background.js @@ -391,6 +391,19 @@ function withTitlePrivacy(payload, settings, keys) { return applyTitlePrivacyToPayload(payload, settings?.titlePrivacyMode, keys); } +function emitEpisodeLobbyForCurrentPrivacy() { + if (!episodeLobby || episodeLobby.initiatorPeerId !== peerId) return; + getSettings().then(settings => { + if (!episodeLobby || episodeLobby.initiatorPeerId !== peerId) return; + const expectedTitle = sanitizeSharedTitle(episodeLobby.expectedTitle, settings.titlePrivacyMode); + if (expectedTitle) { + emit(EVENTS.EPISODE_LOBBY, { peerId, expectedTitle }); + } + }).catch(err => { + addLog('Episode lobby privacy error: ' + err.message, 'error'); + }); +} + // Privacy + correctness: only onboardingComplete and dismissedHints belong in // storage.sync. Everything else is per-device local storage. This actively // removes legacy keys that older versions wrote to sync (and that would @@ -1256,7 +1269,7 @@ function handleServerEvent(event, data) { } if (episodeLobby && episodeLobby.initiatorPeerId === peerId) { - emit(EVENTS.EPISODE_LOBBY, { peerId, expectedTitle: episodeLobby.expectedTitle }); + emitEpisodeLobbyForCurrentPrivacy(); } } } else if (data.status === 'left') { @@ -1637,7 +1650,6 @@ chrome.alarms.onAlarm.addListener(async (alarm) => { status: 'heartbeat', username: settings.username, tabTitle: sharedTitles.tabTitle, - mediaTitle: sharedTitles.mediaTitle, desynced: hcmDesynced }); } @@ -2330,6 +2342,12 @@ async function handleAsyncMessage(message, sender, sendResponse) { sendResponse({ status: 'ok' }); } else if (message.type === 'TITLE_PRIVACY_CHANGED') { const settings = await getSettings(); + if (episodeLobby && episodeLobby.initiatorPeerId === peerId) { + const nextLobbyTitle = sanitizeSharedTitle(episodeLobby.expectedTitle, settings.titlePrivacyMode); + if (!nextLobbyTitle || nextLobbyTitle !== episodeLobby.expectedTitle) { + cancelEpisodeLobby('Title privacy changed'); + } + } if (currentRoom && settings.titlePrivacyMode === 'hidden') { const sharedTitles = getSharedTitleFields(settings); emit(EVENTS.PEER_STATUS, { diff --git a/extension/locales/es.json b/extension/locales/es.json index b32e509..98bbe96 100644 --- a/extension/locales/es.json +++ b/extension/locales/es.json @@ -230,9 +230,9 @@ "BTN_RESTART_TOUR": "Reiniciar tutorial", "BTN_RESTART_TOUR_TOOLTIP": "Reiniciar el tutorial de inicio", "HINT_SELECT_VIDEO": "¡Selecciona tu video aquí!", - "LABEL_TITLE_PRIVACY": "Shared Titles", - "LABEL_TITLE_PRIVACY_TOOLTIP": "Choose how tab and media titles are shared with the room. Hidden mode clears titles on the server and disables creating episode lobbies from your client.", - "OPTION_TITLE_PRIVACY_FULL": "Full titles", - "OPTION_TITLE_PRIVACY_EPISODE": "Episode only", - "OPTION_TITLE_PRIVACY_HIDDEN": "Hidden" + "LABEL_TITLE_PRIVACY": "T?tulos compartidos", + "LABEL_TITLE_PRIVACY_TOOLTIP": "Elige c?mo se comparten los t?tulos de pesta?a y multimedia con la sala. El modo oculto borra los t?tulos del servidor y desactiva la creaci?n de salas de episodio desde tu cliente.", + "OPTION_TITLE_PRIVACY_FULL": "T?tulos completos", + "OPTION_TITLE_PRIVACY_EPISODE": "Solo episodio", + "OPTION_TITLE_PRIVACY_HIDDEN": "Ocultos" } diff --git a/extension/locales/fr.json b/extension/locales/fr.json index 0677f61..491c7ec 100644 --- a/extension/locales/fr.json +++ b/extension/locales/fr.json @@ -230,9 +230,9 @@ "BTN_RESTART_TOUR": "Redémarrer le tutoriel", "BTN_RESTART_TOUR_TOOLTIP": "Recommencer le tutoriel d'intégration", "HINT_SELECT_VIDEO": "Sélectionnez votre vidéo ici !", - "LABEL_TITLE_PRIVACY": "Shared Titles", - "LABEL_TITLE_PRIVACY_TOOLTIP": "Choose how tab and media titles are shared with the room. Hidden mode clears titles on the server and disables creating episode lobbies from your client.", - "OPTION_TITLE_PRIVACY_FULL": "Full titles", - "OPTION_TITLE_PRIVACY_EPISODE": "Episode only", - "OPTION_TITLE_PRIVACY_HIDDEN": "Hidden" + "LABEL_TITLE_PRIVACY": "Titres partag?s", + "LABEL_TITLE_PRIVACY_TOOLTIP": "Choisissez comment les titres des onglets et des m?dias sont partag?s avec le salon. Le mode masqu? efface les titres du serveur et d?sactive la cr?ation de salons d??pisode depuis votre client.", + "OPTION_TITLE_PRIVACY_FULL": "Titres complets", + "OPTION_TITLE_PRIVACY_EPISODE": "?pisode seulement", + "OPTION_TITLE_PRIVACY_HIDDEN": "Masqu?s" } diff --git a/extension/locales/it.json b/extension/locales/it.json index f1c2536..9777564 100644 --- a/extension/locales/it.json +++ b/extension/locales/it.json @@ -230,9 +230,9 @@ "BTN_RESTART_TOUR": "Riavvia Tutorial", "BTN_RESTART_TOUR_TOOLTIP": "Riavvia il tutorial introduttivo", "HINT_SELECT_VIDEO": "Scegli il tuo video qui!", - "LABEL_TITLE_PRIVACY": "Shared Titles", - "LABEL_TITLE_PRIVACY_TOOLTIP": "Choose how tab and media titles are shared with the room. Hidden mode clears titles on the server and disables creating episode lobbies from your client.", - "OPTION_TITLE_PRIVACY_FULL": "Full titles", - "OPTION_TITLE_PRIVACY_EPISODE": "Episode only", - "OPTION_TITLE_PRIVACY_HIDDEN": "Hidden" + "LABEL_TITLE_PRIVACY": "Titoli condivisi", + "LABEL_TITLE_PRIVACY_TOOLTIP": "Scegli come condividere con la stanza i titoli delle schede e dei contenuti multimediali. La modalit? nascosta cancella i titoli sul server e disattiva la creazione di lobby episodio dal tuo client.", + "OPTION_TITLE_PRIVACY_FULL": "Titoli completi", + "OPTION_TITLE_PRIVACY_EPISODE": "Solo episodio", + "OPTION_TITLE_PRIVACY_HIDDEN": "Nascosti" } diff --git a/extension/locales/ja.json b/extension/locales/ja.json index 932c67a..f784484 100644 --- a/extension/locales/ja.json +++ b/extension/locales/ja.json @@ -230,9 +230,9 @@ "BTN_RESTART_TOUR": "チュートリアルを再起動", "BTN_RESTART_TOUR_TOOLTIP": "オンボーディングチュートリアルを再起動する", "HINT_SELECT_VIDEO": "ここで動画を選択してください!", - "LABEL_TITLE_PRIVACY": "Shared Titles", - "LABEL_TITLE_PRIVACY_TOOLTIP": "Choose how tab and media titles are shared with the room. Hidden mode clears titles on the server and disables creating episode lobbies from your client.", - "OPTION_TITLE_PRIVACY_FULL": "Full titles", - "OPTION_TITLE_PRIVACY_EPISODE": "Episode only", - "OPTION_TITLE_PRIVACY_HIDDEN": "Hidden" + "LABEL_TITLE_PRIVACY": "??????", + "LABEL_TITLE_PRIVACY_TOOLTIP": "???????????????????????????????????????????????????????????????????????????????????", + "OPTION_TITLE_PRIVACY_FULL": "???????", + "OPTION_TITLE_PRIVACY_EPISODE": "???????", + "OPTION_TITLE_PRIVACY_HIDDEN": "???" } diff --git a/extension/locales/ko.json b/extension/locales/ko.json index d77405f..fb3c79c 100644 --- a/extension/locales/ko.json +++ b/extension/locales/ko.json @@ -230,9 +230,9 @@ "BTN_RESTART_TOUR": "튜토리얼 다시 시작", "BTN_RESTART_TOUR_TOOLTIP": "온보딩 튜토리얼을 다시 시작합니다", "HINT_SELECT_VIDEO": "여기에서 비디오를 선택하세요!", - "LABEL_TITLE_PRIVACY": "Shared Titles", - "LABEL_TITLE_PRIVACY_TOOLTIP": "Choose how tab and media titles are shared with the room. Hidden mode clears titles on the server and disables creating episode lobbies from your client.", - "OPTION_TITLE_PRIVACY_FULL": "Full titles", - "OPTION_TITLE_PRIVACY_EPISODE": "Episode only", - "OPTION_TITLE_PRIVACY_HIDDEN": "Hidden" + "LABEL_TITLE_PRIVACY": "?? ??", + "LABEL_TITLE_PRIVACY_TOOLTIP": "? ??? ??? ??? ?? ??? ???? ?????. ?? ??? ??? ??? ??? ? ??????? ???? ??? ??? ??? ???.", + "OPTION_TITLE_PRIVACY_FULL": "?? ??", + "OPTION_TITLE_PRIVACY_EPISODE": "?????", + "OPTION_TITLE_PRIVACY_HIDDEN": "??" } diff --git a/extension/locales/nl.json b/extension/locales/nl.json index 3718678..7b9faa6 100644 --- a/extension/locales/nl.json +++ b/extension/locales/nl.json @@ -230,9 +230,9 @@ "BTN_RESTART_TOUR": "Tutorial opnieuw starten", "BTN_RESTART_TOUR_TOOLTIP": "Start de introductie-tutorial opnieuw", "HINT_SELECT_VIDEO": "Selecteer hier je video!", - "LABEL_TITLE_PRIVACY": "Shared Titles", - "LABEL_TITLE_PRIVACY_TOOLTIP": "Choose how tab and media titles are shared with the room. Hidden mode clears titles on the server and disables creating episode lobbies from your client.", - "OPTION_TITLE_PRIVACY_FULL": "Full titles", - "OPTION_TITLE_PRIVACY_EPISODE": "Episode only", - "OPTION_TITLE_PRIVACY_HIDDEN": "Hidden" + "LABEL_TITLE_PRIVACY": "Gedeelde titels", + "LABEL_TITLE_PRIVACY_TOOLTIP": "Kies hoe tab- en mediatitels met de kamer worden gedeeld. Verborgen modus wist titels op de server en schakelt het maken van afleveringslobby?s vanaf jouw client uit.", + "OPTION_TITLE_PRIVACY_FULL": "Volledige titels", + "OPTION_TITLE_PRIVACY_EPISODE": "Alleen aflevering", + "OPTION_TITLE_PRIVACY_HIDDEN": "Verborgen" } diff --git a/extension/locales/pl.json b/extension/locales/pl.json index baccdb5..908aef4 100644 --- a/extension/locales/pl.json +++ b/extension/locales/pl.json @@ -230,9 +230,9 @@ "BTN_RESTART_TOUR": "Uruchom samouczek ponownie", "BTN_RESTART_TOUR_TOOLTIP": "Uruchom ponownie samouczek powitalny", "HINT_SELECT_VIDEO": "Wybierz swoje wideo tutaj!", - "LABEL_TITLE_PRIVACY": "Shared Titles", - "LABEL_TITLE_PRIVACY_TOOLTIP": "Choose how tab and media titles are shared with the room. Hidden mode clears titles on the server and disables creating episode lobbies from your client.", - "OPTION_TITLE_PRIVACY_FULL": "Full titles", - "OPTION_TITLE_PRIVACY_EPISODE": "Episode only", - "OPTION_TITLE_PRIVACY_HIDDEN": "Hidden" + "LABEL_TITLE_PRIVACY": "Udost?pniane tytu?y", + "LABEL_TITLE_PRIVACY_TOOLTIP": "Wybierz, jak tytu?y kart i multimedi?w s? udost?pniane w pokoju. Tryb ukryty czy?ci tytu?y na serwerze i wy??cza tworzenie poczekalni odcinka z tego klienta.", + "OPTION_TITLE_PRIVACY_FULL": "Pe?ne tytu?y", + "OPTION_TITLE_PRIVACY_EPISODE": "Tylko odcinek", + "OPTION_TITLE_PRIVACY_HIDDEN": "Ukryte" } diff --git a/extension/locales/pt-BR.json b/extension/locales/pt-BR.json index bcf3cc3..b08d5ec 100644 --- a/extension/locales/pt-BR.json +++ b/extension/locales/pt-BR.json @@ -230,9 +230,9 @@ "BTN_RESTART_TOUR": "Reiniciar tutorial", "BTN_RESTART_TOUR_TOOLTIP": "Reiniciar o tutorial de introdução", "HINT_SELECT_VIDEO": "Selecione seu vídeo aqui!", - "LABEL_TITLE_PRIVACY": "Shared Titles", - "LABEL_TITLE_PRIVACY_TOOLTIP": "Choose how tab and media titles are shared with the room. Hidden mode clears titles on the server and disables creating episode lobbies from your client.", - "OPTION_TITLE_PRIVACY_FULL": "Full titles", - "OPTION_TITLE_PRIVACY_EPISODE": "Episode only", - "OPTION_TITLE_PRIVACY_HIDDEN": "Hidden" + "LABEL_TITLE_PRIVACY": "T?tulos compartilhados", + "LABEL_TITLE_PRIVACY_TOOLTIP": "Escolha como os t?tulos da aba e da m?dia s?o compartilhados com a sala. O modo oculto limpa os t?tulos no servidor e desativa a cria??o de lobby de epis?dio pelo seu cliente.", + "OPTION_TITLE_PRIVACY_FULL": "T?tulos completos", + "OPTION_TITLE_PRIVACY_EPISODE": "S? epis?dio", + "OPTION_TITLE_PRIVACY_HIDDEN": "Ocultos" } diff --git a/extension/locales/pt.json b/extension/locales/pt.json index 77b1a58..3228382 100644 --- a/extension/locales/pt.json +++ b/extension/locales/pt.json @@ -230,9 +230,9 @@ "BTN_RESTART_TOUR": "Reiniciar Tutorial", "BTN_RESTART_TOUR_TOOLTIP": "Reiniciar o tutorial introdutório", "HINT_SELECT_VIDEO": "Selecione o seu vídeo aqui!", - "LABEL_TITLE_PRIVACY": "Shared Titles", - "LABEL_TITLE_PRIVACY_TOOLTIP": "Choose how tab and media titles are shared with the room. Hidden mode clears titles on the server and disables creating episode lobbies from your client.", - "OPTION_TITLE_PRIVACY_FULL": "Full titles", - "OPTION_TITLE_PRIVACY_EPISODE": "Episode only", - "OPTION_TITLE_PRIVACY_HIDDEN": "Hidden" + "LABEL_TITLE_PRIVACY": "T?tulos partilhados", + "LABEL_TITLE_PRIVACY_TOOLTIP": "Escolhe como os t?tulos do separador e do conte?do multim?dia s?o partilhados com a sala. O modo oculto limpa os t?tulos no servidor e desativa a cria??o de salas de epis?dio pelo teu cliente.", + "OPTION_TITLE_PRIVACY_FULL": "T?tulos completos", + "OPTION_TITLE_PRIVACY_EPISODE": "S? epis?dio", + "OPTION_TITLE_PRIVACY_HIDDEN": "Ocultos" } diff --git a/extension/locales/ru.json b/extension/locales/ru.json index be7dfd8..b4d655e 100644 --- a/extension/locales/ru.json +++ b/extension/locales/ru.json @@ -230,9 +230,9 @@ "BTN_RESTART_TOUR": "Перезапустить обучение", "BTN_RESTART_TOUR_TOOLTIP": "Запустить приветственное руководство заново", "HINT_SELECT_VIDEO": "Выберите ваше видео здесь!", - "LABEL_TITLE_PRIVACY": "Shared Titles", - "LABEL_TITLE_PRIVACY_TOOLTIP": "Choose how tab and media titles are shared with the room. Hidden mode clears titles on the server and disables creating episode lobbies from your client.", - "OPTION_TITLE_PRIVACY_FULL": "Full titles", - "OPTION_TITLE_PRIVACY_EPISODE": "Episode only", - "OPTION_TITLE_PRIVACY_HIDDEN": "Hidden" + "LABEL_TITLE_PRIVACY": "????? ????????", + "LABEL_TITLE_PRIVACY_TOOLTIP": "????????, ??? ???????? ??????? ? ????? ?????????? ? ???????. ??????? ????? ??????? ???????? ?? ??????? ? ????????? ???????? ????? ???????? ? ?????? ???????.", + "OPTION_TITLE_PRIVACY_FULL": "?????? ????????", + "OPTION_TITLE_PRIVACY_EPISODE": "?????? ??????", + "OPTION_TITLE_PRIVACY_HIDDEN": "??????" } diff --git a/extension/locales/tr.json b/extension/locales/tr.json index aabeb67..e63baf2 100644 --- a/extension/locales/tr.json +++ b/extension/locales/tr.json @@ -230,9 +230,9 @@ "BTN_RESTART_TOUR": "Eğitimi Yeniden Başlat", "BTN_RESTART_TOUR_TOOLTIP": "Tanıtım eğitimini yeniden başlat", "HINT_SELECT_VIDEO": "Videonuzu buradan seçin!", - "LABEL_TITLE_PRIVACY": "Shared Titles", - "LABEL_TITLE_PRIVACY_TOOLTIP": "Choose how tab and media titles are shared with the room. Hidden mode clears titles on the server and disables creating episode lobbies from your client.", - "OPTION_TITLE_PRIVACY_FULL": "Full titles", - "OPTION_TITLE_PRIVACY_EPISODE": "Episode only", - "OPTION_TITLE_PRIVACY_HIDDEN": "Hidden" + "LABEL_TITLE_PRIVACY": "Payla??lan ba?l?klar", + "LABEL_TITLE_PRIVACY_TOOLTIP": "Sekme ve medya ba?l?klar?n?n odayla nas?l payla??laca??n? se?in. Gizli mod sunucudaki ba?l?klar? temizler ve istemcinizden b?l?m lobisi olu?turmay? devre d??? b?rak?r.", + "OPTION_TITLE_PRIVACY_FULL": "Tam ba?l?klar", + "OPTION_TITLE_PRIVACY_EPISODE": "Sadece b?l?m", + "OPTION_TITLE_PRIVACY_HIDDEN": "Gizli" } diff --git a/extension/locales/uk.json b/extension/locales/uk.json index 29d436b..3321bc7 100644 --- a/extension/locales/uk.json +++ b/extension/locales/uk.json @@ -230,9 +230,9 @@ "BTN_RESTART_TOUR": "Перезапустіть підручник", "BTN_RESTART_TOUR_TOOLTIP": "Перезапустіть навчальний посібник із адаптації", "HINT_SELECT_VIDEO": "Виберіть своє відео тут!", - "LABEL_TITLE_PRIVACY": "Shared Titles", - "LABEL_TITLE_PRIVACY_TOOLTIP": "Choose how tab and media titles are shared with the room. Hidden mode clears titles on the server and disables creating episode lobbies from your client.", - "OPTION_TITLE_PRIVACY_FULL": "Full titles", - "OPTION_TITLE_PRIVACY_EPISODE": "Episode only", - "OPTION_TITLE_PRIVACY_HIDDEN": "Hidden" + "LABEL_TITLE_PRIVACY": "??????? ?????", + "LABEL_TITLE_PRIVACY_TOOLTIP": "????????, ?? ????? ??????? ? ????? ??????????? ?? ???????. ?????????? ????? ?????? ????? ?? ??????? ? ??????? ????????? ???? ???????? ?? ?????? ???????.", + "OPTION_TITLE_PRIVACY_FULL": "????? ?????", + "OPTION_TITLE_PRIVACY_EPISODE": "???? ??????", + "OPTION_TITLE_PRIVACY_HIDDEN": "?????????" } diff --git a/extension/locales/zh.json b/extension/locales/zh.json index e12ecfa..9b2b2e3 100644 --- a/extension/locales/zh.json +++ b/extension/locales/zh.json @@ -230,9 +230,9 @@ "BTN_RESTART_TOUR": "重启教程", "BTN_RESTART_TOUR_TOOLTIP": "重新启动入门教程", "HINT_SELECT_VIDEO": "在这里选择您的视频!", - "LABEL_TITLE_PRIVACY": "Shared Titles", - "LABEL_TITLE_PRIVACY_TOOLTIP": "Choose how tab and media titles are shared with the room. Hidden mode clears titles on the server and disables creating episode lobbies from your client.", - "OPTION_TITLE_PRIVACY_FULL": "Full titles", - "OPTION_TITLE_PRIVACY_EPISODE": "Episode only", - "OPTION_TITLE_PRIVACY_HIDDEN": "Hidden" + "LABEL_TITLE_PRIVACY": "????", + "LABEL_TITLE_PRIVACY_TOOLTIP": "??????????????????????????????????????????????????", + "OPTION_TITLE_PRIVACY_FULL": "????", + "OPTION_TITLE_PRIVACY_EPISODE": "???", + "OPTION_TITLE_PRIVACY_HIDDEN": "??" } diff --git a/extension/popup.js b/extension/popup.js index 1b2fd42..35240eb 100644 --- a/extension/popup.js +++ b/extension/popup.js @@ -89,6 +89,7 @@ let pendingConnectionErrorMsg = null; let roomListRefreshTimer = null; let roomListRefreshInterval = null; const ROOM_LIST_REFRESH_COOLDOWN_MS = 11000; +const TITLE_PRIVACY_MODES = ['full', 'episode', 'hidden']; const FEATURE_HINTS = [ { key: 'audio_processing', @@ -210,7 +211,7 @@ async function init() { elements.username.value = username; if (elements.filterNoise) elements.filterNoise.checked = localData.filterNoise !== false; if (elements.autoSyncNextEpisode) elements.autoSyncNextEpisode.checked = localData.autoSyncNextEpisode !== false; - if (elements.titlePrivacyMode) elements.titlePrivacyMode.value = localData.titlePrivacyMode || 'full'; + if (elements.titlePrivacyMode) elements.titlePrivacyMode.value = TITLE_PRIVACY_MODES.includes(localData.titlePrivacyMode) ? localData.titlePrivacyMode : 'full'; if (elements.forceSyncMode) elements.forceSyncMode.value = localData.forceSyncMode || 'jump-to-others'; if (elements.browserNotifications) elements.browserNotifications.checked = localData.browserNotifications === true; if (elements.autoCopyInvite) elements.autoCopyInvite.checked = localData.autoCopyInvite !== false; diff --git a/scripts/test-title-privacy.mjs b/scripts/test-title-privacy.mjs index 7650fdd..8f1fce1 100644 --- a/scripts/test-title-privacy.mjs +++ b/scripts/test-title-privacy.mjs @@ -34,6 +34,18 @@ assert.deepEqual( } ); +assert.deepEqual( + applyTitlePrivacyToPayload({ + tabTitle: 'Private Jellyfin - S01E04', + status: 'heartbeat' + }, 'episode'), + { + tabTitle: 'S01E04', + status: 'heartbeat' + }, + 'privacy filtering must not add absent title keys' +); + assert.deepEqual( applyTitlePrivacyToPayload({ tabTitle: 'Private Tab',