feat: watch together recent rooms, plex usernames, action toasts, shorter codes

close #855
This commit is contained in:
edde746
2026-04-13 14:02:21 +02:00
parent 17eb37cb37
commit b81f6eaa96
38 changed files with 748 additions and 139 deletions
+9 -3
View File
@@ -702,10 +702,10 @@
"leave": "Forlad",
"syncing": "Synkroniserer...",
"joinWatchSession": "Deltag i se-session",
"enterCodeHint": "Indtast 8-tegns kode",
"enterCodeHint": "Indtast 5-tegns kode",
"pasteFromClipboard": "Indsæt fra udklipsholder",
"pleaseEnterCode": "Indtast en sessionskode",
"codeMustBe8Chars": "Sessionskode skal være 8 tegn",
"codeMustBe5Chars": "Sessionskode skal være 5 tegn",
"joinInstructions": "Indtast sessionskoden delt af værten for at deltage i se-sessionen.",
"failedToCreate": "Kunne ikke oprette session",
"failedToJoin": "Kunne ikke deltage i session",
@@ -717,7 +717,13 @@
"joinCurrentPlaybackDescription": "Hop tilbage til det værten ser nu",
"failedToOpenCurrentPlayback": "Kunne ikke åbne nuværende afspilning",
"participantJoined": "${name} deltog",
"participantLeft": "${name} forlod"
"participantLeft": "${name} forlod",
"participantPaused": "${name} satte på pause",
"participantResumed": "${name} genoptog",
"participantSeeked": "${name} spoled",
"recentRooms": "Seneste rum",
"renameRoom": "Omdøb rum",
"removeRoom": "Fjern"
},
"downloads": {
"title": "Downloads",
+9 -3
View File
@@ -729,10 +729,10 @@
"leave": "Verlassen",
"syncing": "Synchronisieren...",
"joinWatchSession": "Schausitzung Beitreten",
"enterCodeHint": "8-stelligen Code eingeben",
"enterCodeHint": "5-stelligen Code eingeben",
"pasteFromClipboard": "Aus Zwischenablage einfügen",
"pleaseEnterCode": "Bitte gib einen Sitzungscode ein",
"codeMustBe8Chars": "Sitzungscode muss 8 Zeichen haben",
"codeMustBe5Chars": "Sitzungscode muss 5 Zeichen haben",
"joinInstructions": "Gib den vom Host geteilten Sitzungscode ein, um seiner Schausitzung beizutreten.",
"failedToCreate": "Sitzung konnte nicht erstellt werden",
"failedToJoin": "Sitzung konnte nicht beigetreten werden",
@@ -744,7 +744,13 @@
"joinCurrentPlaybackDescription": "Springe zurück zu dem, was der Host gerade ansieht",
"failedToOpenCurrentPlayback": "Aktuelle Wiedergabe konnte nicht geöffnet werden",
"participantJoined": "${name} ist beigetreten",
"participantLeft": "${name} hat die Sitzung verlassen"
"participantLeft": "${name} hat die Sitzung verlassen",
"participantPaused": "${name} hat pausiert",
"participantResumed": "${name} hat fortgesetzt",
"participantSeeked": "${name} hat gespult",
"recentRooms": "Letzte Räume",
"renameRoom": "Raum umbenennen",
"removeRoom": "Entfernen"
},
"shaders": {
"title": "Shader",
+9 -3
View File
@@ -702,10 +702,10 @@
"leave": "Leave",
"syncing": "Syncing...",
"joinWatchSession": "Join Watch Session",
"enterCodeHint": "Enter 8-character code",
"enterCodeHint": "Enter 5-character code",
"pasteFromClipboard": "Paste from clipboard",
"pleaseEnterCode": "Please enter a session code",
"codeMustBe8Chars": "Session code must be 8 characters",
"codeMustBe5Chars": "Session code must be 5 characters",
"joinInstructions": "Enter the session code shared by the host to join their watch session.",
"failedToCreate": "Failed to create session",
"failedToJoin": "Failed to join session",
@@ -717,7 +717,13 @@
"joinCurrentPlaybackDescription": "Jump back into what the host is currently watching",
"failedToOpenCurrentPlayback": "Failed to open current playback",
"participantJoined": "${name} joined",
"participantLeft": "${name} left"
"participantLeft": "${name} left",
"participantPaused": "${name} paused",
"participantResumed": "${name} resumed",
"participantSeeked": "${name} seeked",
"recentRooms": "Recent Rooms",
"renameRoom": "Rename Room",
"removeRoom": "Remove"
},
"downloads": {
"title": "Downloads",
+9 -3
View File
@@ -702,10 +702,10 @@
"leave": "Salir",
"syncing": "Sincronizando...",
"joinWatchSession": "Unirse a Sesión de Visualización",
"enterCodeHint": "Introduce el código de 8 caracteres",
"enterCodeHint": "Introduce el código de 5 caracteres",
"pasteFromClipboard": "Pegar desde el portapapeles",
"pleaseEnterCode": "Por favor, introduce un código de sesión",
"codeMustBe8Chars": "El código de sesión debe tener 8 caracteres",
"codeMustBe5Chars": "El código de sesión debe tener 5 caracteres",
"joinInstructions": "Introduce el código de sesión compartido por el anfitrión para unirte a su sesión.",
"failedToCreate": "Error al crear la sesión",
"failedToJoin": "Error al unirse a la sesión",
@@ -717,7 +717,13 @@
"joinCurrentPlaybackDescription": "Vuelve a lo que el anfitrión está viendo ahora mismo",
"failedToOpenCurrentPlayback": "No se pudo abrir la reproducción actual",
"participantJoined": "${name} se unió",
"participantLeft": "${name} se fue"
"participantLeft": "${name} se fue",
"participantPaused": "${name} pausó",
"participantResumed": "${name} reanudó",
"participantSeeked": "${name} avanzó",
"recentRooms": "Salas recientes",
"renameRoom": "Renombrar sala",
"removeRoom": "Eliminar"
},
"downloads": {
"title": "Descargas",
+9 -3
View File
@@ -702,10 +702,10 @@
"leave": "Fin",
"syncing": "Synchronisation...",
"joinWatchSession": "Rejoindre la session de visionnage",
"enterCodeHint": "Entrez le code à 8 caractères",
"enterCodeHint": "Entrez le code à 5 caractères",
"pasteFromClipboard": "Coller depuis le presse-papiers",
"pleaseEnterCode": "Veuillez saisir un code de session",
"codeMustBe8Chars": "Le code de session doit comporter 8 caractères",
"codeMustBe5Chars": "Le code de session doit comporter 5 caractères",
"joinInstructions": "Entrez le code de session partagé par l'hôte pour rejoindre sa session de visionnage.",
"failedToCreate": "Échec de la création de la session",
"failedToJoin": "Échec de la connexion à la session",
@@ -717,7 +717,13 @@
"joinCurrentPlaybackDescription": "Revenez à ce que l'hôte regarde actuellement",
"failedToOpenCurrentPlayback": "Impossible d'ouvrir la lecture en cours",
"participantJoined": "${name} a rejoint",
"participantLeft": "${name} est parti"
"participantLeft": "${name} est parti",
"participantPaused": "${name} a mis en pause",
"participantResumed": "${name} a repris",
"participantSeeked": "${name} a avancé",
"recentRooms": "Salons récents",
"renameRoom": "Renommer le salon",
"removeRoom": "Supprimer"
},
"downloads": {
"title": "Téléchargements",
+9 -3
View File
@@ -729,10 +729,10 @@
"leave": "Lascia",
"syncing": "Sincronizzazione...",
"joinWatchSession": "Unisciti alla Sessione di Visione",
"enterCodeHint": "Inserisci codice di 8 caratteri",
"enterCodeHint": "Inserisci codice di 5 caratteri",
"pasteFromClipboard": "Incolla dagli appunti",
"pleaseEnterCode": "Inserisci un codice sessione",
"codeMustBe8Chars": "Il codice sessione deve essere di 8 caratteri",
"codeMustBe5Chars": "Il codice sessione deve essere di 5 caratteri",
"joinInstructions": "Inserisci il codice sessione condiviso dall'host per unirti alla loro sessione di visione.",
"failedToCreate": "Impossibile creare la sessione",
"failedToJoin": "Impossibile unirsi alla sessione",
@@ -744,7 +744,13 @@
"joinCurrentPlaybackDescription": "Torna a ciò che l'host sta guardando in questo momento",
"failedToOpenCurrentPlayback": "Impossibile aprire la riproduzione corrente",
"participantJoined": "${name} si è unito",
"participantLeft": "${name} se ne è andato"
"participantLeft": "${name} se ne è andato",
"participantPaused": "${name} ha messo in pausa",
"participantResumed": "${name} ha ripreso",
"participantSeeked": "${name} ha cercato",
"recentRooms": "Stanze recenti",
"renameRoom": "Rinomina stanza",
"removeRoom": "Rimuovi"
},
"shaders": {
"title": "Shader",
+9 -3
View File
@@ -702,10 +702,10 @@
"leave": "退出",
"syncing": "同期中...",
"joinWatchSession": "視聴セッションに参加",
"enterCodeHint": "8文字のコードを入力",
"enterCodeHint": "5文字のコードを入力",
"pasteFromClipboard": "クリップボードから貼り付け",
"pleaseEnterCode": "セッションコードを入力してください",
"codeMustBe8Chars": "セッションコードは8文字である必要があります",
"codeMustBe5Chars": "セッションコードは5文字である必要があります",
"joinInstructions": "ホストが共有したセッションコードを入力して視聴セッションに参加してください。",
"failedToCreate": "セッションの作成に失敗しました",
"failedToJoin": "セッションへの参加に失敗しました",
@@ -717,7 +717,13 @@
"joinCurrentPlaybackDescription": "ホストが現在視聴中のコンテンツに戻る",
"failedToOpenCurrentPlayback": "現在の再生を開けませんでした",
"participantJoined": "${name}が参加しました",
"participantLeft": "${name}が退出しました"
"participantLeft": "${name}が退出しました",
"participantPaused": "${name}が一時停止しました",
"participantResumed": "${name}が再開しました",
"participantSeeked": "${name}がシークしました",
"recentRooms": "最近のルーム",
"renameRoom": "ルーム名を変更",
"removeRoom": "削除"
},
"downloads": {
"title": "ダウンロード",
+9 -3
View File
@@ -702,10 +702,10 @@
"leave": "이탈",
"syncing": "동기화 중...",
"joinWatchSession": "시청 세션에 참여",
"enterCodeHint": "8자리 코드 입력",
"enterCodeHint": "5자리 코드 입력",
"pasteFromClipboard": "클립보드에서 붙여넣기",
"pleaseEnterCode": "세션 코드를 입력하세요",
"codeMustBe8Chars": "세션 코드는 반드시 8자리여야 합니다",
"codeMustBe5Chars": "세션 코드는 반드시 5자리여야 합니다",
"joinInstructions": "호스트가 공유한 세션 코드를 입력하여 시청 세션에 참여하세요.",
"failedToCreate": "세션 생성 실패",
"failedToJoin": "세션 참여 실패",
@@ -717,7 +717,13 @@
"joinCurrentPlaybackDescription": "호스트가 현재 보고 있는 항목으로 돌아갑니다",
"failedToOpenCurrentPlayback": "현재 재생을 열 수 없습니다",
"participantJoined": "${name}님이 참여했습니다",
"participantLeft": "${name}님이 나갔습니다"
"participantLeft": "${name}님이 나갔습니다",
"participantPaused": "${name}님이 일시정지했습니다",
"participantResumed": "${name}님이 재생했습니다",
"participantSeeked": "${name}님이 탐색했습니다",
"recentRooms": "최근 방",
"renameRoom": "방 이름 변경",
"removeRoom": "제거"
},
"downloads": {
"title": "다운로드",
+9 -3
View File
@@ -702,10 +702,10 @@
"leave": "Forlat",
"syncing": "Synkroniserer...",
"joinWatchSession": "Bli med i se sammen-økt",
"enterCodeHint": "Skriv inn 8-tegns kode",
"enterCodeHint": "Skriv inn 5-tegns kode",
"pasteFromClipboard": "Lim inn fra utklippstavle",
"pleaseEnterCode": "Vennligst skriv inn en øktkode",
"codeMustBe8Chars": "Øktkoden må være 8 tegn",
"codeMustBe5Chars": "Øktkoden må være 5 tegn",
"joinInstructions": "Skriv inn øktkoden delt av verten for å bli med i se sammen-økten.",
"failedToCreate": "Kunne ikke opprette økt",
"failedToJoin": "Kunne ikke bli med i økt",
@@ -717,7 +717,13 @@
"joinCurrentPlaybackDescription": "Hopp tilbake til det verten ser på nå",
"failedToOpenCurrentPlayback": "Kunne ikke åpne gjeldende avspilling",
"participantJoined": "${name} ble med",
"participantLeft": "${name} forlot"
"participantLeft": "${name} forlot",
"participantPaused": "${name} pauset",
"participantResumed": "${name} gjenopptok",
"participantSeeked": "${name} spolet",
"recentRooms": "Nylige rom",
"renameRoom": "Gi nytt navn til rom",
"removeRoom": "Fjern"
},
"downloads": {
"title": "Nedlastinger",
+9 -3
View File
@@ -729,10 +729,10 @@
"leave": "Verlaten",
"syncing": "Synchroniseren...",
"joinWatchSession": "Kijksessie Deelnemen",
"enterCodeHint": "Voer 8-teken code in",
"enterCodeHint": "Voer 5-teken code in",
"pasteFromClipboard": "Plakken van klembord",
"pleaseEnterCode": "Voer een sessiecode in",
"codeMustBe8Chars": "Sessiecode moet 8 tekens zijn",
"codeMustBe5Chars": "Sessiecode moet 5 tekens zijn",
"joinInstructions": "Voer de sessiecode in die door de host is gedeeld om deel te nemen aan hun kijksessie.",
"failedToCreate": "Sessie maken mislukt",
"failedToJoin": "Sessie deelnemen mislukt",
@@ -744,7 +744,13 @@
"joinCurrentPlaybackDescription": "Ga terug naar wat de host nu kijkt",
"failedToOpenCurrentPlayback": "Huidige weergave kon niet worden geopend",
"participantJoined": "${name} is toegetreden",
"participantLeft": "${name} heeft de sessie verlaten"
"participantLeft": "${name} heeft de sessie verlaten",
"participantPaused": "${name} heeft gepauzeerd",
"participantResumed": "${name} heeft hervat",
"participantSeeked": "${name} heeft gespoeld",
"recentRooms": "Recente kamers",
"renameRoom": "Kamer hernoemen",
"removeRoom": "Verwijderen"
},
"shaders": {
"title": "Shaders",
+9 -3
View File
@@ -702,10 +702,10 @@
"leave": "Opuść",
"syncing": "Synchronizacja...",
"joinWatchSession": "Dołącz do sesji oglądania",
"enterCodeHint": "Wprowadź 8-znakowy kod",
"enterCodeHint": "Wprowadź 5-znakowy kod",
"pasteFromClipboard": "Wklej ze schowka",
"pleaseEnterCode": "Wprowadź kod sesji",
"codeMustBe8Chars": "Kod sesji musi mieć 8 znaków",
"codeMustBe5Chars": "Kod sesji musi mieć 5 znaków",
"joinInstructions": "Wprowadź kod sesji udostępniony przez hosta, aby dołączyć do sesji oglądania.",
"failedToCreate": "Nie udało się utworzyć sesji",
"failedToJoin": "Nie udało się dołączyć do sesji",
@@ -717,7 +717,13 @@
"joinCurrentPlaybackDescription": "Wróć do tego, co host aktualnie ogląda",
"failedToOpenCurrentPlayback": "Nie udało się otworzyć bieżącego odtwarzania",
"participantJoined": "${name} dołączył",
"participantLeft": "${name} opuścił"
"participantLeft": "${name} opuścił",
"participantPaused": "${name} wstrzymał",
"participantResumed": "${name} wznowił",
"participantSeeked": "${name} przewinął",
"recentRooms": "Ostatnie pokoje",
"renameRoom": "Zmień nazwę pokoju",
"removeRoom": "Usuń"
},
"downloads": {
"title": "Pobrania",
+9 -3
View File
@@ -702,10 +702,10 @@
"leave": "Sair",
"syncing": "Sincronizando...",
"joinWatchSession": "Entrar na Sessão",
"enterCodeHint": "Insira o código de 8 caracteres",
"enterCodeHint": "Insira o código de 5 caracteres",
"pasteFromClipboard": "Colar da área de transferência",
"pleaseEnterCode": "Insira um código de sessão",
"codeMustBe8Chars": "O código da sessão deve ter 8 caracteres",
"codeMustBe5Chars": "O código da sessão deve ter 5 caracteres",
"joinInstructions": "Insira o código da sessão compartilhado pelo anfitrião para entrar na sessão.",
"failedToCreate": "Falha ao criar sessão",
"failedToJoin": "Falha ao entrar na sessão",
@@ -717,7 +717,13 @@
"joinCurrentPlaybackDescription": "Voltar ao que o anfitrião está assistindo agora",
"failedToOpenCurrentPlayback": "Falha ao abrir reprodução atual",
"participantJoined": "${name} entrou",
"participantLeft": "${name} saiu"
"participantLeft": "${name} saiu",
"participantPaused": "${name} pausou",
"participantResumed": "${name} retomou",
"participantSeeked": "${name} avançou",
"recentRooms": "Salas recentes",
"renameRoom": "Renomear sala",
"removeRoom": "Remover"
},
"downloads": {
"title": "Downloads",
+9 -3
View File
@@ -702,10 +702,10 @@
"leave": "Покинуть",
"syncing": "Синхронизация...",
"joinWatchSession": "Присоединиться к просмотру",
"enterCodeHint": "Введите 8-символьный код",
"enterCodeHint": "Введите 5-символьный код",
"pasteFromClipboard": "Вставить из буфера обмена",
"pleaseEnterCode": "Введите код сессии",
"codeMustBe8Chars": "Код сессии должен содержать 8 символов",
"codeMustBe5Chars": "Код сессии должен содержать 5 символов",
"joinInstructions": "Введите код сессии, предоставленный хостом, чтобы присоединиться к просмотру.",
"failedToCreate": "Не удалось создать сессию",
"failedToJoin": "Не удалось присоединиться к сессии",
@@ -717,7 +717,13 @@
"joinCurrentPlaybackDescription": "Вернуться к тому, что сейчас смотрит хост",
"failedToOpenCurrentPlayback": "Не удалось открыть текущее воспроизведение",
"participantJoined": "${name} присоединился",
"participantLeft": "${name} вышел"
"participantLeft": "${name} вышел",
"participantPaused": "${name} поставил на паузу",
"participantResumed": "${name} возобновил",
"participantSeeked": "${name} перемотал",
"recentRooms": "Недавние комнаты",
"renameRoom": "Переименовать комнату",
"removeRoom": "Удалить"
},
"downloads": {
"title": "Загрузки",
+2 -2
View File
@@ -4,9 +4,9 @@
/// To regenerate, run: `dart run slang`
///
/// Locales: 15
/// Strings: 12975 (865 per locale)
/// Strings: 13065 (871 per locale)
///
/// Built on 2026-04-11 at 05:59 UTC
/// Built on 2026-04-13 at 10:11 UTC
// coverage:ignore-file
// ignore_for_file: type=lint, unused_import
+16 -4
View File
@@ -955,10 +955,10 @@ class _TranslationsWatchTogetherDa implements TranslationsWatchTogetherEn {
@override String get leave => 'Forlad';
@override String get syncing => 'Synkroniserer...';
@override String get joinWatchSession => 'Deltag i se-session';
@override String get enterCodeHint => 'Indtast 8-tegns kode';
@override String get enterCodeHint => 'Indtast 5-tegns kode';
@override String get pasteFromClipboard => 'Indsæt fra udklipsholder';
@override String get pleaseEnterCode => 'Indtast en sessionskode';
@override String get codeMustBe8Chars => 'Sessionskode skal være 8 tegn';
@override String get codeMustBe5Chars => 'Sessionskode skal være 5 tegn';
@override String get joinInstructions => 'Indtast sessionskoden delt af værten for at deltage i se-sessionen.';
@override String get failedToCreate => 'Kunne ikke oprette session';
@override String get failedToJoin => 'Kunne ikke deltage i session';
@@ -971,6 +971,12 @@ class _TranslationsWatchTogetherDa implements TranslationsWatchTogetherEn {
@override String get failedToOpenCurrentPlayback => 'Kunne ikke åbne nuværende afspilning';
@override String participantJoined({required Object name}) => '${name} deltog';
@override String participantLeft({required Object name}) => '${name} forlod';
@override String participantPaused({required Object name}) => '${name} satte på pause';
@override String participantResumed({required Object name}) => '${name} genoptog';
@override String participantSeeked({required Object name}) => '${name} spoled';
@override String get recentRooms => 'Seneste rum';
@override String get renameRoom => 'Omdøb rum';
@override String get removeRoom => 'Fjern';
}
// Path: downloads
@@ -1998,10 +2004,10 @@ extension on TranslationsDa {
'watchTogether.leave' => 'Forlad',
'watchTogether.syncing' => 'Synkroniserer...',
'watchTogether.joinWatchSession' => 'Deltag i se-session',
'watchTogether.enterCodeHint' => 'Indtast 8-tegns kode',
'watchTogether.enterCodeHint' => 'Indtast 5-tegns kode',
'watchTogether.pasteFromClipboard' => 'Indsæt fra udklipsholder',
'watchTogether.pleaseEnterCode' => 'Indtast en sessionskode',
'watchTogether.codeMustBe8Chars' => 'Sessionskode skal være 8 tegn',
'watchTogether.codeMustBe5Chars' => 'Sessionskode skal være 5 tegn',
'watchTogether.joinInstructions' => 'Indtast sessionskoden delt af værten for at deltage i se-sessionen.',
'watchTogether.failedToCreate' => 'Kunne ikke oprette session',
'watchTogether.failedToJoin' => 'Kunne ikke deltage i session',
@@ -2014,6 +2020,12 @@ extension on TranslationsDa {
'watchTogether.failedToOpenCurrentPlayback' => 'Kunne ikke åbne nuværende afspilning',
'watchTogether.participantJoined' => ({required Object name}) => '${name} deltog',
'watchTogether.participantLeft' => ({required Object name}) => '${name} forlod',
'watchTogether.participantPaused' => ({required Object name}) => '${name} satte på pause',
'watchTogether.participantResumed' => ({required Object name}) => '${name} genoptog',
'watchTogether.participantSeeked' => ({required Object name}) => '${name} spoled',
'watchTogether.recentRooms' => 'Seneste rum',
'watchTogether.renameRoom' => 'Omdøb rum',
'watchTogether.removeRoom' => 'Fjern',
'downloads.title' => 'Downloads',
'downloads.manage' => 'Administrer',
'downloads.tvShows' => 'TV-serier',
+16 -4
View File
@@ -989,10 +989,10 @@ class _TranslationsWatchTogetherDe implements TranslationsWatchTogetherEn {
@override String get leave => 'Verlassen';
@override String get syncing => 'Synchronisieren...';
@override String get joinWatchSession => 'Schausitzung Beitreten';
@override String get enterCodeHint => '8-stelligen Code eingeben';
@override String get enterCodeHint => '5-stelligen Code eingeben';
@override String get pasteFromClipboard => 'Aus Zwischenablage einfügen';
@override String get pleaseEnterCode => 'Bitte gib einen Sitzungscode ein';
@override String get codeMustBe8Chars => 'Sitzungscode muss 8 Zeichen haben';
@override String get codeMustBe5Chars => 'Sitzungscode muss 5 Zeichen haben';
@override String get joinInstructions => 'Gib den vom Host geteilten Sitzungscode ein, um seiner Schausitzung beizutreten.';
@override String get failedToCreate => 'Sitzung konnte nicht erstellt werden';
@override String get failedToJoin => 'Sitzung konnte nicht beigetreten werden';
@@ -1005,6 +1005,12 @@ class _TranslationsWatchTogetherDe implements TranslationsWatchTogetherEn {
@override String get failedToOpenCurrentPlayback => 'Aktuelle Wiedergabe konnte nicht geöffnet werden';
@override String participantJoined({required Object name}) => '${name} ist beigetreten';
@override String participantLeft({required Object name}) => '${name} hat die Sitzung verlassen';
@override String participantPaused({required Object name}) => '${name} hat pausiert';
@override String participantResumed({required Object name}) => '${name} hat fortgesetzt';
@override String participantSeeked({required Object name}) => '${name} hat gespult';
@override String get recentRooms => 'Letzte Räume';
@override String get renameRoom => 'Raum umbenennen';
@override String get removeRoom => 'Entfernen';
}
// Path: shaders
@@ -2023,10 +2029,10 @@ extension on TranslationsDe {
'watchTogether.leave' => 'Verlassen',
'watchTogether.syncing' => 'Synchronisieren...',
'watchTogether.joinWatchSession' => 'Schausitzung Beitreten',
'watchTogether.enterCodeHint' => '8-stelligen Code eingeben',
'watchTogether.enterCodeHint' => '5-stelligen Code eingeben',
'watchTogether.pasteFromClipboard' => 'Aus Zwischenablage einfügen',
'watchTogether.pleaseEnterCode' => 'Bitte gib einen Sitzungscode ein',
'watchTogether.codeMustBe8Chars' => 'Sitzungscode muss 8 Zeichen haben',
'watchTogether.codeMustBe5Chars' => 'Sitzungscode muss 5 Zeichen haben',
'watchTogether.joinInstructions' => 'Gib den vom Host geteilten Sitzungscode ein, um seiner Schausitzung beizutreten.',
'watchTogether.failedToCreate' => 'Sitzung konnte nicht erstellt werden',
'watchTogether.failedToJoin' => 'Sitzung konnte nicht beigetreten werden',
@@ -2039,6 +2045,12 @@ extension on TranslationsDe {
'watchTogether.failedToOpenCurrentPlayback' => 'Aktuelle Wiedergabe konnte nicht geöffnet werden',
'watchTogether.participantJoined' => ({required Object name}) => '${name} ist beigetreten',
'watchTogether.participantLeft' => ({required Object name}) => '${name} hat die Sitzung verlassen',
'watchTogether.participantPaused' => ({required Object name}) => '${name} hat pausiert',
'watchTogether.participantResumed' => ({required Object name}) => '${name} hat fortgesetzt',
'watchTogether.participantSeeked' => ({required Object name}) => '${name} hat gespult',
'watchTogether.recentRooms' => 'Letzte Räume',
'watchTogether.renameRoom' => 'Raum umbenennen',
'watchTogether.removeRoom' => 'Entfernen',
'shaders.title' => 'Shader',
'shaders.noShaderDescription' => 'Keine Videoverbesserung',
'shaders.nvscalerDescription' => 'NVIDIA-Bildskalierung für schärferes Video',
+30 -6
View File
@@ -2156,8 +2156,8 @@ class TranslationsWatchTogetherEn {
/// en: 'Join Watch Session'
String get joinWatchSession => 'Join Watch Session';
/// en: 'Enter 8-character code'
String get enterCodeHint => 'Enter 8-character code';
/// en: 'Enter 5-character code'
String get enterCodeHint => 'Enter 5-character code';
/// en: 'Paste from clipboard'
String get pasteFromClipboard => 'Paste from clipboard';
@@ -2165,8 +2165,8 @@ class TranslationsWatchTogetherEn {
/// en: 'Please enter a session code'
String get pleaseEnterCode => 'Please enter a session code';
/// en: 'Session code must be 8 characters'
String get codeMustBe8Chars => 'Session code must be 8 characters';
/// en: 'Session code must be 5 characters'
String get codeMustBe5Chars => 'Session code must be 5 characters';
/// en: 'Enter the session code shared by the host to join their watch session.'
String get joinInstructions => 'Enter the session code shared by the host to join their watch session.';
@@ -2203,6 +2203,24 @@ class TranslationsWatchTogetherEn {
/// en: '${name} left'
String participantLeft({required Object name}) => '${name} left';
/// en: '${name} paused'
String participantPaused({required Object name}) => '${name} paused';
/// en: '${name} resumed'
String participantResumed({required Object name}) => '${name} resumed';
/// en: '${name} seeked'
String participantSeeked({required Object name}) => '${name} seeked';
/// en: 'Recent Rooms'
String get recentRooms => 'Recent Rooms';
/// en: 'Rename Room'
String get renameRoom => 'Rename Room';
/// en: 'Remove'
String get removeRoom => 'Remove';
}
// Path: downloads
@@ -3735,10 +3753,10 @@ extension on Translations {
'watchTogether.leave' => 'Leave',
'watchTogether.syncing' => 'Syncing...',
'watchTogether.joinWatchSession' => 'Join Watch Session',
'watchTogether.enterCodeHint' => 'Enter 8-character code',
'watchTogether.enterCodeHint' => 'Enter 5-character code',
'watchTogether.pasteFromClipboard' => 'Paste from clipboard',
'watchTogether.pleaseEnterCode' => 'Please enter a session code',
'watchTogether.codeMustBe8Chars' => 'Session code must be 8 characters',
'watchTogether.codeMustBe5Chars' => 'Session code must be 5 characters',
'watchTogether.joinInstructions' => 'Enter the session code shared by the host to join their watch session.',
'watchTogether.failedToCreate' => 'Failed to create session',
'watchTogether.failedToJoin' => 'Failed to join session',
@@ -3751,6 +3769,12 @@ extension on Translations {
'watchTogether.failedToOpenCurrentPlayback' => 'Failed to open current playback',
'watchTogether.participantJoined' => ({required Object name}) => '${name} joined',
'watchTogether.participantLeft' => ({required Object name}) => '${name} left',
'watchTogether.participantPaused' => ({required Object name}) => '${name} paused',
'watchTogether.participantResumed' => ({required Object name}) => '${name} resumed',
'watchTogether.participantSeeked' => ({required Object name}) => '${name} seeked',
'watchTogether.recentRooms' => 'Recent Rooms',
'watchTogether.renameRoom' => 'Rename Room',
'watchTogether.removeRoom' => 'Remove',
'downloads.title' => 'Downloads',
'downloads.manage' => 'Manage',
'downloads.tvShows' => 'TV Shows',
+16 -4
View File
@@ -955,10 +955,10 @@ class _TranslationsWatchTogetherEs implements TranslationsWatchTogetherEn {
@override String get leave => 'Salir';
@override String get syncing => 'Sincronizando...';
@override String get joinWatchSession => 'Unirse a Sesión de Visualización';
@override String get enterCodeHint => 'Introduce el código de 8 caracteres';
@override String get enterCodeHint => 'Introduce el código de 5 caracteres';
@override String get pasteFromClipboard => 'Pegar desde el portapapeles';
@override String get pleaseEnterCode => 'Por favor, introduce un código de sesión';
@override String get codeMustBe8Chars => 'El código de sesión debe tener 8 caracteres';
@override String get codeMustBe5Chars => 'El código de sesión debe tener 5 caracteres';
@override String get joinInstructions => 'Introduce el código de sesión compartido por el anfitrión para unirte a su sesión.';
@override String get failedToCreate => 'Error al crear la sesión';
@override String get failedToJoin => 'Error al unirse a la sesión';
@@ -971,6 +971,12 @@ class _TranslationsWatchTogetherEs implements TranslationsWatchTogetherEn {
@override String get failedToOpenCurrentPlayback => 'No se pudo abrir la reproducción actual';
@override String participantJoined({required Object name}) => '${name} se unió';
@override String participantLeft({required Object name}) => '${name} se fue';
@override String participantPaused({required Object name}) => '${name} pausó';
@override String participantResumed({required Object name}) => '${name} reanudó';
@override String participantSeeked({required Object name}) => '${name} avanzó';
@override String get recentRooms => 'Salas recientes';
@override String get renameRoom => 'Renombrar sala';
@override String get removeRoom => 'Eliminar';
}
// Path: downloads
@@ -1998,10 +2004,10 @@ extension on TranslationsEs {
'watchTogether.leave' => 'Salir',
'watchTogether.syncing' => 'Sincronizando...',
'watchTogether.joinWatchSession' => 'Unirse a Sesión de Visualización',
'watchTogether.enterCodeHint' => 'Introduce el código de 8 caracteres',
'watchTogether.enterCodeHint' => 'Introduce el código de 5 caracteres',
'watchTogether.pasteFromClipboard' => 'Pegar desde el portapapeles',
'watchTogether.pleaseEnterCode' => 'Por favor, introduce un código de sesión',
'watchTogether.codeMustBe8Chars' => 'El código de sesión debe tener 8 caracteres',
'watchTogether.codeMustBe5Chars' => 'El código de sesión debe tener 5 caracteres',
'watchTogether.joinInstructions' => 'Introduce el código de sesión compartido por el anfitrión para unirte a su sesión.',
'watchTogether.failedToCreate' => 'Error al crear la sesión',
'watchTogether.failedToJoin' => 'Error al unirse a la sesión',
@@ -2014,6 +2020,12 @@ extension on TranslationsEs {
'watchTogether.failedToOpenCurrentPlayback' => 'No se pudo abrir la reproducción actual',
'watchTogether.participantJoined' => ({required Object name}) => '${name} se unió',
'watchTogether.participantLeft' => ({required Object name}) => '${name} se fue',
'watchTogether.participantPaused' => ({required Object name}) => '${name} pausó',
'watchTogether.participantResumed' => ({required Object name}) => '${name} reanudó',
'watchTogether.participantSeeked' => ({required Object name}) => '${name} avanzó',
'watchTogether.recentRooms' => 'Salas recientes',
'watchTogether.renameRoom' => 'Renombrar sala',
'watchTogether.removeRoom' => 'Eliminar',
'downloads.title' => 'Descargas',
'downloads.manage' => 'Gestionar',
'downloads.tvShows' => 'Series de TV',
+16 -4
View File
@@ -955,10 +955,10 @@ class _TranslationsWatchTogetherFr implements TranslationsWatchTogetherEn {
@override String get leave => 'Fin';
@override String get syncing => 'Synchronisation...';
@override String get joinWatchSession => 'Rejoindre la session de visionnage';
@override String get enterCodeHint => 'Entrez le code à 8 caractères';
@override String get enterCodeHint => 'Entrez le code à 5 caractères';
@override String get pasteFromClipboard => 'Coller depuis le presse-papiers';
@override String get pleaseEnterCode => 'Veuillez saisir un code de session';
@override String get codeMustBe8Chars => 'Le code de session doit comporter 8 caractères';
@override String get codeMustBe5Chars => 'Le code de session doit comporter 5 caractères';
@override String get joinInstructions => 'Entrez le code de session partagé par l\'hôte pour rejoindre sa session de visionnage.';
@override String get failedToCreate => 'Échec de la création de la session';
@override String get failedToJoin => 'Échec de la connexion à la session';
@@ -971,6 +971,12 @@ class _TranslationsWatchTogetherFr implements TranslationsWatchTogetherEn {
@override String get failedToOpenCurrentPlayback => 'Impossible d\'ouvrir la lecture en cours';
@override String participantJoined({required Object name}) => '${name} a rejoint';
@override String participantLeft({required Object name}) => '${name} est parti';
@override String participantPaused({required Object name}) => '${name} a mis en pause';
@override String participantResumed({required Object name}) => '${name} a repris';
@override String participantSeeked({required Object name}) => '${name} a avancé';
@override String get recentRooms => 'Salons récents';
@override String get renameRoom => 'Renommer le salon';
@override String get removeRoom => 'Supprimer';
}
// Path: downloads
@@ -1998,10 +2004,10 @@ extension on TranslationsFr {
'watchTogether.leave' => 'Fin',
'watchTogether.syncing' => 'Synchronisation...',
'watchTogether.joinWatchSession' => 'Rejoindre la session de visionnage',
'watchTogether.enterCodeHint' => 'Entrez le code à 8 caractères',
'watchTogether.enterCodeHint' => 'Entrez le code à 5 caractères',
'watchTogether.pasteFromClipboard' => 'Coller depuis le presse-papiers',
'watchTogether.pleaseEnterCode' => 'Veuillez saisir un code de session',
'watchTogether.codeMustBe8Chars' => 'Le code de session doit comporter 8 caractères',
'watchTogether.codeMustBe5Chars' => 'Le code de session doit comporter 5 caractères',
'watchTogether.joinInstructions' => 'Entrez le code de session partagé par l\'hôte pour rejoindre sa session de visionnage.',
'watchTogether.failedToCreate' => 'Échec de la création de la session',
'watchTogether.failedToJoin' => 'Échec de la connexion à la session',
@@ -2014,6 +2020,12 @@ extension on TranslationsFr {
'watchTogether.failedToOpenCurrentPlayback' => 'Impossible d\'ouvrir la lecture en cours',
'watchTogether.participantJoined' => ({required Object name}) => '${name} a rejoint',
'watchTogether.participantLeft' => ({required Object name}) => '${name} est parti',
'watchTogether.participantPaused' => ({required Object name}) => '${name} a mis en pause',
'watchTogether.participantResumed' => ({required Object name}) => '${name} a repris',
'watchTogether.participantSeeked' => ({required Object name}) => '${name} a avancé',
'watchTogether.recentRooms' => 'Salons récents',
'watchTogether.renameRoom' => 'Renommer le salon',
'watchTogether.removeRoom' => 'Supprimer',
'downloads.title' => 'Téléchargements',
'downloads.manage' => 'Gérer',
'downloads.tvShows' => 'Show TV',
+16 -4
View File
@@ -989,10 +989,10 @@ class _TranslationsWatchTogetherIt implements TranslationsWatchTogetherEn {
@override String get leave => 'Lascia';
@override String get syncing => 'Sincronizzazione...';
@override String get joinWatchSession => 'Unisciti alla Sessione di Visione';
@override String get enterCodeHint => 'Inserisci codice di 8 caratteri';
@override String get enterCodeHint => 'Inserisci codice di 5 caratteri';
@override String get pasteFromClipboard => 'Incolla dagli appunti';
@override String get pleaseEnterCode => 'Inserisci un codice sessione';
@override String get codeMustBe8Chars => 'Il codice sessione deve essere di 8 caratteri';
@override String get codeMustBe5Chars => 'Il codice sessione deve essere di 5 caratteri';
@override String get joinInstructions => 'Inserisci il codice sessione condiviso dall\'host per unirti alla loro sessione di visione.';
@override String get failedToCreate => 'Impossibile creare la sessione';
@override String get failedToJoin => 'Impossibile unirsi alla sessione';
@@ -1005,6 +1005,12 @@ class _TranslationsWatchTogetherIt implements TranslationsWatchTogetherEn {
@override String get failedToOpenCurrentPlayback => 'Impossibile aprire la riproduzione corrente';
@override String participantJoined({required Object name}) => '${name} si è unito';
@override String participantLeft({required Object name}) => '${name} se ne è andato';
@override String participantPaused({required Object name}) => '${name} ha messo in pausa';
@override String participantResumed({required Object name}) => '${name} ha ripreso';
@override String participantSeeked({required Object name}) => '${name} ha cercato';
@override String get recentRooms => 'Stanze recenti';
@override String get renameRoom => 'Rinomina stanza';
@override String get removeRoom => 'Rimuovi';
}
// Path: shaders
@@ -2023,10 +2029,10 @@ extension on TranslationsIt {
'watchTogether.leave' => 'Lascia',
'watchTogether.syncing' => 'Sincronizzazione...',
'watchTogether.joinWatchSession' => 'Unisciti alla Sessione di Visione',
'watchTogether.enterCodeHint' => 'Inserisci codice di 8 caratteri',
'watchTogether.enterCodeHint' => 'Inserisci codice di 5 caratteri',
'watchTogether.pasteFromClipboard' => 'Incolla dagli appunti',
'watchTogether.pleaseEnterCode' => 'Inserisci un codice sessione',
'watchTogether.codeMustBe8Chars' => 'Il codice sessione deve essere di 8 caratteri',
'watchTogether.codeMustBe5Chars' => 'Il codice sessione deve essere di 5 caratteri',
'watchTogether.joinInstructions' => 'Inserisci il codice sessione condiviso dall\'host per unirti alla loro sessione di visione.',
'watchTogether.failedToCreate' => 'Impossibile creare la sessione',
'watchTogether.failedToJoin' => 'Impossibile unirsi alla sessione',
@@ -2039,6 +2045,12 @@ extension on TranslationsIt {
'watchTogether.failedToOpenCurrentPlayback' => 'Impossibile aprire la riproduzione corrente',
'watchTogether.participantJoined' => ({required Object name}) => '${name} si è unito',
'watchTogether.participantLeft' => ({required Object name}) => '${name} se ne è andato',
'watchTogether.participantPaused' => ({required Object name}) => '${name} ha messo in pausa',
'watchTogether.participantResumed' => ({required Object name}) => '${name} ha ripreso',
'watchTogether.participantSeeked' => ({required Object name}) => '${name} ha cercato',
'watchTogether.recentRooms' => 'Stanze recenti',
'watchTogether.renameRoom' => 'Rinomina stanza',
'watchTogether.removeRoom' => 'Rimuovi',
'shaders.title' => 'Shader',
'shaders.noShaderDescription' => 'Nessun miglioramento video',
'shaders.nvscalerDescription' => 'Ridimensionamento NVIDIA per video più nitido',
+16 -4
View File
@@ -955,10 +955,10 @@ class _TranslationsWatchTogetherJa implements TranslationsWatchTogetherEn {
@override String get leave => '退出';
@override String get syncing => '同期中...';
@override String get joinWatchSession => '視聴セッションに参加';
@override String get enterCodeHint => '8文字のコードを入力';
@override String get enterCodeHint => '5文字のコードを入力';
@override String get pasteFromClipboard => 'クリップボードから貼り付け';
@override String get pleaseEnterCode => 'セッションコードを入力してください';
@override String get codeMustBe8Chars => 'セッションコードは8文字である必要があります';
@override String get codeMustBe5Chars => 'セッションコードは5文字である必要があります';
@override String get joinInstructions => 'ホストが共有したセッションコードを入力して視聴セッションに参加してください。';
@override String get failedToCreate => 'セッションの作成に失敗しました';
@override String get failedToJoin => 'セッションへの参加に失敗しました';
@@ -971,6 +971,12 @@ class _TranslationsWatchTogetherJa implements TranslationsWatchTogetherEn {
@override String get failedToOpenCurrentPlayback => '現在の再生を開けませんでした';
@override String participantJoined({required Object name}) => '${name}が参加しました';
@override String participantLeft({required Object name}) => '${name}が退出しました';
@override String participantPaused({required Object name}) => '${name}が一時停止しました';
@override String participantResumed({required Object name}) => '${name}が再開しました';
@override String participantSeeked({required Object name}) => '${name}がシークしました';
@override String get recentRooms => '最近のルーム';
@override String get renameRoom => 'ルーム名を変更';
@override String get removeRoom => '削除';
}
// Path: downloads
@@ -1998,10 +2004,10 @@ extension on TranslationsJa {
'watchTogether.leave' => '退出',
'watchTogether.syncing' => '同期中...',
'watchTogether.joinWatchSession' => '視聴セッションに参加',
'watchTogether.enterCodeHint' => '8文字のコードを入力',
'watchTogether.enterCodeHint' => '5文字のコードを入力',
'watchTogether.pasteFromClipboard' => 'クリップボードから貼り付け',
'watchTogether.pleaseEnterCode' => 'セッションコードを入力してください',
'watchTogether.codeMustBe8Chars' => 'セッションコードは8文字である必要があります',
'watchTogether.codeMustBe5Chars' => 'セッションコードは5文字である必要があります',
'watchTogether.joinInstructions' => 'ホストが共有したセッションコードを入力して視聴セッションに参加してください。',
'watchTogether.failedToCreate' => 'セッションの作成に失敗しました',
'watchTogether.failedToJoin' => 'セッションへの参加に失敗しました',
@@ -2014,6 +2020,12 @@ extension on TranslationsJa {
'watchTogether.failedToOpenCurrentPlayback' => '現在の再生を開けませんでした',
'watchTogether.participantJoined' => ({required Object name}) => '${name}が参加しました',
'watchTogether.participantLeft' => ({required Object name}) => '${name}が退出しました',
'watchTogether.participantPaused' => ({required Object name}) => '${name}が一時停止しました',
'watchTogether.participantResumed' => ({required Object name}) => '${name}が再開しました',
'watchTogether.participantSeeked' => ({required Object name}) => '${name}がシークしました',
'watchTogether.recentRooms' => '最近のルーム',
'watchTogether.renameRoom' => 'ルーム名を変更',
'watchTogether.removeRoom' => '削除',
'downloads.title' => 'ダウンロード',
'downloads.manage' => '管理',
'downloads.tvShows' => 'テレビ番組',
+16 -4
View File
@@ -955,10 +955,10 @@ class _TranslationsWatchTogetherKo implements TranslationsWatchTogetherEn {
@override String get leave => '이탈';
@override String get syncing => '동기화 중...';
@override String get joinWatchSession => '시청 세션에 참여';
@override String get enterCodeHint => '8자리 코드 입력';
@override String get enterCodeHint => '5자리 코드 입력';
@override String get pasteFromClipboard => '클립보드에서 붙여넣기';
@override String get pleaseEnterCode => '세션 코드를 입력하세요';
@override String get codeMustBe8Chars => '세션 코드는 반드시 8자리여야 합니다';
@override String get codeMustBe5Chars => '세션 코드는 반드시 5자리여야 합니다';
@override String get joinInstructions => '호스트가 공유한 세션 코드를 입력하여 시청 세션에 참여하세요.';
@override String get failedToCreate => '세션 생성 실패';
@override String get failedToJoin => '세션 참여 실패';
@@ -971,6 +971,12 @@ class _TranslationsWatchTogetherKo implements TranslationsWatchTogetherEn {
@override String get failedToOpenCurrentPlayback => '현재 재생을 열 수 없습니다';
@override String participantJoined({required Object name}) => '${name}님이 참여했습니다';
@override String participantLeft({required Object name}) => '${name}님이 나갔습니다';
@override String participantPaused({required Object name}) => '${name}님이 일시정지했습니다';
@override String participantResumed({required Object name}) => '${name}님이 재생했습니다';
@override String participantSeeked({required Object name}) => '${name}님이 탐색했습니다';
@override String get recentRooms => '최근 방';
@override String get renameRoom => '방 이름 변경';
@override String get removeRoom => '제거';
}
// Path: downloads
@@ -1998,10 +2004,10 @@ extension on TranslationsKo {
'watchTogether.leave' => '이탈',
'watchTogether.syncing' => '동기화 중...',
'watchTogether.joinWatchSession' => '시청 세션에 참여',
'watchTogether.enterCodeHint' => '8자리 코드 입력',
'watchTogether.enterCodeHint' => '5자리 코드 입력',
'watchTogether.pasteFromClipboard' => '클립보드에서 붙여넣기',
'watchTogether.pleaseEnterCode' => '세션 코드를 입력하세요',
'watchTogether.codeMustBe8Chars' => '세션 코드는 반드시 8자리여야 합니다',
'watchTogether.codeMustBe5Chars' => '세션 코드는 반드시 5자리여야 합니다',
'watchTogether.joinInstructions' => '호스트가 공유한 세션 코드를 입력하여 시청 세션에 참여하세요.',
'watchTogether.failedToCreate' => '세션 생성 실패',
'watchTogether.failedToJoin' => '세션 참여 실패',
@@ -2014,6 +2020,12 @@ extension on TranslationsKo {
'watchTogether.failedToOpenCurrentPlayback' => '현재 재생을 열 수 없습니다',
'watchTogether.participantJoined' => ({required Object name}) => '${name}님이 참여했습니다',
'watchTogether.participantLeft' => ({required Object name}) => '${name}님이 나갔습니다',
'watchTogether.participantPaused' => ({required Object name}) => '${name}님이 일시정지했습니다',
'watchTogether.participantResumed' => ({required Object name}) => '${name}님이 재생했습니다',
'watchTogether.participantSeeked' => ({required Object name}) => '${name}님이 탐색했습니다',
'watchTogether.recentRooms' => '최근 방',
'watchTogether.renameRoom' => '방 이름 변경',
'watchTogether.removeRoom' => '제거',
'downloads.title' => '다운로드',
'downloads.manage' => '관리',
'downloads.tvShows' => 'TV 프로그램',
+16 -4
View File
@@ -955,10 +955,10 @@ class _TranslationsWatchTogetherNb implements TranslationsWatchTogetherEn {
@override String get leave => 'Forlat';
@override String get syncing => 'Synkroniserer...';
@override String get joinWatchSession => 'Bli med i se sammen-økt';
@override String get enterCodeHint => 'Skriv inn 8-tegns kode';
@override String get enterCodeHint => 'Skriv inn 5-tegns kode';
@override String get pasteFromClipboard => 'Lim inn fra utklippstavle';
@override String get pleaseEnterCode => 'Vennligst skriv inn en øktkode';
@override String get codeMustBe8Chars => 'Øktkoden må være 8 tegn';
@override String get codeMustBe5Chars => 'Øktkoden må være 5 tegn';
@override String get joinInstructions => 'Skriv inn øktkoden delt av verten for å bli med i se sammen-økten.';
@override String get failedToCreate => 'Kunne ikke opprette økt';
@override String get failedToJoin => 'Kunne ikke bli med i økt';
@@ -971,6 +971,12 @@ class _TranslationsWatchTogetherNb implements TranslationsWatchTogetherEn {
@override String get failedToOpenCurrentPlayback => 'Kunne ikke åpne gjeldende avspilling';
@override String participantJoined({required Object name}) => '${name} ble med';
@override String participantLeft({required Object name}) => '${name} forlot';
@override String participantPaused({required Object name}) => '${name} pauset';
@override String participantResumed({required Object name}) => '${name} gjenopptok';
@override String participantSeeked({required Object name}) => '${name} spolet';
@override String get recentRooms => 'Nylige rom';
@override String get renameRoom => 'Gi nytt navn til rom';
@override String get removeRoom => 'Fjern';
}
// Path: downloads
@@ -1998,10 +2004,10 @@ extension on TranslationsNb {
'watchTogether.leave' => 'Forlat',
'watchTogether.syncing' => 'Synkroniserer...',
'watchTogether.joinWatchSession' => 'Bli med i se sammen-økt',
'watchTogether.enterCodeHint' => 'Skriv inn 8-tegns kode',
'watchTogether.enterCodeHint' => 'Skriv inn 5-tegns kode',
'watchTogether.pasteFromClipboard' => 'Lim inn fra utklippstavle',
'watchTogether.pleaseEnterCode' => 'Vennligst skriv inn en øktkode',
'watchTogether.codeMustBe8Chars' => 'Øktkoden må være 8 tegn',
'watchTogether.codeMustBe5Chars' => 'Øktkoden må være 5 tegn',
'watchTogether.joinInstructions' => 'Skriv inn øktkoden delt av verten for å bli med i se sammen-økten.',
'watchTogether.failedToCreate' => 'Kunne ikke opprette økt',
'watchTogether.failedToJoin' => 'Kunne ikke bli med i økt',
@@ -2014,6 +2020,12 @@ extension on TranslationsNb {
'watchTogether.failedToOpenCurrentPlayback' => 'Kunne ikke åpne gjeldende avspilling',
'watchTogether.participantJoined' => ({required Object name}) => '${name} ble med',
'watchTogether.participantLeft' => ({required Object name}) => '${name} forlot',
'watchTogether.participantPaused' => ({required Object name}) => '${name} pauset',
'watchTogether.participantResumed' => ({required Object name}) => '${name} gjenopptok',
'watchTogether.participantSeeked' => ({required Object name}) => '${name} spolet',
'watchTogether.recentRooms' => 'Nylige rom',
'watchTogether.renameRoom' => 'Gi nytt navn til rom',
'watchTogether.removeRoom' => 'Fjern',
'downloads.title' => 'Nedlastinger',
'downloads.manage' => 'Administrer',
'downloads.tvShows' => 'TV-serier',
+16 -4
View File
@@ -989,10 +989,10 @@ class _TranslationsWatchTogetherNl implements TranslationsWatchTogetherEn {
@override String get leave => 'Verlaten';
@override String get syncing => 'Synchroniseren...';
@override String get joinWatchSession => 'Kijksessie Deelnemen';
@override String get enterCodeHint => 'Voer 8-teken code in';
@override String get enterCodeHint => 'Voer 5-teken code in';
@override String get pasteFromClipboard => 'Plakken van klembord';
@override String get pleaseEnterCode => 'Voer een sessiecode in';
@override String get codeMustBe8Chars => 'Sessiecode moet 8 tekens zijn';
@override String get codeMustBe5Chars => 'Sessiecode moet 5 tekens zijn';
@override String get joinInstructions => 'Voer de sessiecode in die door de host is gedeeld om deel te nemen aan hun kijksessie.';
@override String get failedToCreate => 'Sessie maken mislukt';
@override String get failedToJoin => 'Sessie deelnemen mislukt';
@@ -1005,6 +1005,12 @@ class _TranslationsWatchTogetherNl implements TranslationsWatchTogetherEn {
@override String get failedToOpenCurrentPlayback => 'Huidige weergave kon niet worden geopend';
@override String participantJoined({required Object name}) => '${name} is toegetreden';
@override String participantLeft({required Object name}) => '${name} heeft de sessie verlaten';
@override String participantPaused({required Object name}) => '${name} heeft gepauzeerd';
@override String participantResumed({required Object name}) => '${name} heeft hervat';
@override String participantSeeked({required Object name}) => '${name} heeft gespoeld';
@override String get recentRooms => 'Recente kamers';
@override String get renameRoom => 'Kamer hernoemen';
@override String get removeRoom => 'Verwijderen';
}
// Path: shaders
@@ -2023,10 +2029,10 @@ extension on TranslationsNl {
'watchTogether.leave' => 'Verlaten',
'watchTogether.syncing' => 'Synchroniseren...',
'watchTogether.joinWatchSession' => 'Kijksessie Deelnemen',
'watchTogether.enterCodeHint' => 'Voer 8-teken code in',
'watchTogether.enterCodeHint' => 'Voer 5-teken code in',
'watchTogether.pasteFromClipboard' => 'Plakken van klembord',
'watchTogether.pleaseEnterCode' => 'Voer een sessiecode in',
'watchTogether.codeMustBe8Chars' => 'Sessiecode moet 8 tekens zijn',
'watchTogether.codeMustBe5Chars' => 'Sessiecode moet 5 tekens zijn',
'watchTogether.joinInstructions' => 'Voer de sessiecode in die door de host is gedeeld om deel te nemen aan hun kijksessie.',
'watchTogether.failedToCreate' => 'Sessie maken mislukt',
'watchTogether.failedToJoin' => 'Sessie deelnemen mislukt',
@@ -2039,6 +2045,12 @@ extension on TranslationsNl {
'watchTogether.failedToOpenCurrentPlayback' => 'Huidige weergave kon niet worden geopend',
'watchTogether.participantJoined' => ({required Object name}) => '${name} is toegetreden',
'watchTogether.participantLeft' => ({required Object name}) => '${name} heeft de sessie verlaten',
'watchTogether.participantPaused' => ({required Object name}) => '${name} heeft gepauzeerd',
'watchTogether.participantResumed' => ({required Object name}) => '${name} heeft hervat',
'watchTogether.participantSeeked' => ({required Object name}) => '${name} heeft gespoeld',
'watchTogether.recentRooms' => 'Recente kamers',
'watchTogether.renameRoom' => 'Kamer hernoemen',
'watchTogether.removeRoom' => 'Verwijderen',
'shaders.title' => 'Shaders',
'shaders.noShaderDescription' => 'Geen videoverbetering',
'shaders.nvscalerDescription' => 'NVIDIA-beeldschaling voor scherpere video',
+16 -4
View File
@@ -955,10 +955,10 @@ class _TranslationsWatchTogetherPl implements TranslationsWatchTogetherEn {
@override String get leave => 'Opuść';
@override String get syncing => 'Synchronizacja...';
@override String get joinWatchSession => 'Dołącz do sesji oglądania';
@override String get enterCodeHint => 'Wprowadź 8-znakowy kod';
@override String get enterCodeHint => 'Wprowadź 5-znakowy kod';
@override String get pasteFromClipboard => 'Wklej ze schowka';
@override String get pleaseEnterCode => 'Wprowadź kod sesji';
@override String get codeMustBe8Chars => 'Kod sesji musi mieć 8 znaków';
@override String get codeMustBe5Chars => 'Kod sesji musi mieć 5 znaków';
@override String get joinInstructions => 'Wprowadź kod sesji udostępniony przez hosta, aby dołączyć do sesji oglądania.';
@override String get failedToCreate => 'Nie udało się utworzyć sesji';
@override String get failedToJoin => 'Nie udało się dołączyć do sesji';
@@ -971,6 +971,12 @@ class _TranslationsWatchTogetherPl implements TranslationsWatchTogetherEn {
@override String get failedToOpenCurrentPlayback => 'Nie udało się otworzyć bieżącego odtwarzania';
@override String participantJoined({required Object name}) => '${name} dołączył';
@override String participantLeft({required Object name}) => '${name} opuścił';
@override String participantPaused({required Object name}) => '${name} wstrzymał';
@override String participantResumed({required Object name}) => '${name} wznowił';
@override String participantSeeked({required Object name}) => '${name} przewinął';
@override String get recentRooms => 'Ostatnie pokoje';
@override String get renameRoom => 'Zmień nazwę pokoju';
@override String get removeRoom => 'Usuń';
}
// Path: downloads
@@ -1998,10 +2004,10 @@ extension on TranslationsPl {
'watchTogether.leave' => 'Opuść',
'watchTogether.syncing' => 'Synchronizacja...',
'watchTogether.joinWatchSession' => 'Dołącz do sesji oglądania',
'watchTogether.enterCodeHint' => 'Wprowadź 8-znakowy kod',
'watchTogether.enterCodeHint' => 'Wprowadź 5-znakowy kod',
'watchTogether.pasteFromClipboard' => 'Wklej ze schowka',
'watchTogether.pleaseEnterCode' => 'Wprowadź kod sesji',
'watchTogether.codeMustBe8Chars' => 'Kod sesji musi mieć 8 znaków',
'watchTogether.codeMustBe5Chars' => 'Kod sesji musi mieć 5 znaków',
'watchTogether.joinInstructions' => 'Wprowadź kod sesji udostępniony przez hosta, aby dołączyć do sesji oglądania.',
'watchTogether.failedToCreate' => 'Nie udało się utworzyć sesji',
'watchTogether.failedToJoin' => 'Nie udało się dołączyć do sesji',
@@ -2014,6 +2020,12 @@ extension on TranslationsPl {
'watchTogether.failedToOpenCurrentPlayback' => 'Nie udało się otworzyć bieżącego odtwarzania',
'watchTogether.participantJoined' => ({required Object name}) => '${name} dołączył',
'watchTogether.participantLeft' => ({required Object name}) => '${name} opuścił',
'watchTogether.participantPaused' => ({required Object name}) => '${name} wstrzymał',
'watchTogether.participantResumed' => ({required Object name}) => '${name} wznowił',
'watchTogether.participantSeeked' => ({required Object name}) => '${name} przewinął',
'watchTogether.recentRooms' => 'Ostatnie pokoje',
'watchTogether.renameRoom' => 'Zmień nazwę pokoju',
'watchTogether.removeRoom' => 'Usuń',
'downloads.title' => 'Pobrania',
'downloads.manage' => 'Zarządzaj',
'downloads.tvShows' => 'Seriale TV',
+16 -4
View File
@@ -955,10 +955,10 @@ class _TranslationsWatchTogetherPt implements TranslationsWatchTogetherEn {
@override String get leave => 'Sair';
@override String get syncing => 'Sincronizando...';
@override String get joinWatchSession => 'Entrar na Sessão';
@override String get enterCodeHint => 'Insira o código de 8 caracteres';
@override String get enterCodeHint => 'Insira o código de 5 caracteres';
@override String get pasteFromClipboard => 'Colar da área de transferência';
@override String get pleaseEnterCode => 'Insira um código de sessão';
@override String get codeMustBe8Chars => 'O código da sessão deve ter 8 caracteres';
@override String get codeMustBe5Chars => 'O código da sessão deve ter 5 caracteres';
@override String get joinInstructions => 'Insira o código da sessão compartilhado pelo anfitrião para entrar na sessão.';
@override String get failedToCreate => 'Falha ao criar sessão';
@override String get failedToJoin => 'Falha ao entrar na sessão';
@@ -971,6 +971,12 @@ class _TranslationsWatchTogetherPt implements TranslationsWatchTogetherEn {
@override String get failedToOpenCurrentPlayback => 'Falha ao abrir reprodução atual';
@override String participantJoined({required Object name}) => '${name} entrou';
@override String participantLeft({required Object name}) => '${name} saiu';
@override String participantPaused({required Object name}) => '${name} pausou';
@override String participantResumed({required Object name}) => '${name} retomou';
@override String participantSeeked({required Object name}) => '${name} avançou';
@override String get recentRooms => 'Salas recentes';
@override String get renameRoom => 'Renomear sala';
@override String get removeRoom => 'Remover';
}
// Path: downloads
@@ -1998,10 +2004,10 @@ extension on TranslationsPt {
'watchTogether.leave' => 'Sair',
'watchTogether.syncing' => 'Sincronizando...',
'watchTogether.joinWatchSession' => 'Entrar na Sessão',
'watchTogether.enterCodeHint' => 'Insira o código de 8 caracteres',
'watchTogether.enterCodeHint' => 'Insira o código de 5 caracteres',
'watchTogether.pasteFromClipboard' => 'Colar da área de transferência',
'watchTogether.pleaseEnterCode' => 'Insira um código de sessão',
'watchTogether.codeMustBe8Chars' => 'O código da sessão deve ter 8 caracteres',
'watchTogether.codeMustBe5Chars' => 'O código da sessão deve ter 5 caracteres',
'watchTogether.joinInstructions' => 'Insira o código da sessão compartilhado pelo anfitrião para entrar na sessão.',
'watchTogether.failedToCreate' => 'Falha ao criar sessão',
'watchTogether.failedToJoin' => 'Falha ao entrar na sessão',
@@ -2014,6 +2020,12 @@ extension on TranslationsPt {
'watchTogether.failedToOpenCurrentPlayback' => 'Falha ao abrir reprodução atual',
'watchTogether.participantJoined' => ({required Object name}) => '${name} entrou',
'watchTogether.participantLeft' => ({required Object name}) => '${name} saiu',
'watchTogether.participantPaused' => ({required Object name}) => '${name} pausou',
'watchTogether.participantResumed' => ({required Object name}) => '${name} retomou',
'watchTogether.participantSeeked' => ({required Object name}) => '${name} avançou',
'watchTogether.recentRooms' => 'Salas recentes',
'watchTogether.renameRoom' => 'Renomear sala',
'watchTogether.removeRoom' => 'Remover',
'downloads.title' => 'Downloads',
'downloads.manage' => 'Gerenciar',
'downloads.tvShows' => 'Séries de TV',
+16 -4
View File
@@ -955,10 +955,10 @@ class _TranslationsWatchTogetherRu implements TranslationsWatchTogetherEn {
@override String get leave => 'Покинуть';
@override String get syncing => 'Синхронизация...';
@override String get joinWatchSession => 'Присоединиться к просмотру';
@override String get enterCodeHint => 'Введите 8-символьный код';
@override String get enterCodeHint => 'Введите 5-символьный код';
@override String get pasteFromClipboard => 'Вставить из буфера обмена';
@override String get pleaseEnterCode => 'Введите код сессии';
@override String get codeMustBe8Chars => 'Код сессии должен содержать 8 символов';
@override String get codeMustBe5Chars => 'Код сессии должен содержать 5 символов';
@override String get joinInstructions => 'Введите код сессии, предоставленный хостом, чтобы присоединиться к просмотру.';
@override String get failedToCreate => 'Не удалось создать сессию';
@override String get failedToJoin => 'Не удалось присоединиться к сессии';
@@ -971,6 +971,12 @@ class _TranslationsWatchTogetherRu implements TranslationsWatchTogetherEn {
@override String get failedToOpenCurrentPlayback => 'Не удалось открыть текущее воспроизведение';
@override String participantJoined({required Object name}) => '${name} присоединился';
@override String participantLeft({required Object name}) => '${name} вышел';
@override String participantPaused({required Object name}) => '${name} поставил на паузу';
@override String participantResumed({required Object name}) => '${name} возобновил';
@override String participantSeeked({required Object name}) => '${name} перемотал';
@override String get recentRooms => 'Недавние комнаты';
@override String get renameRoom => 'Переименовать комнату';
@override String get removeRoom => 'Удалить';
}
// Path: downloads
@@ -1998,10 +2004,10 @@ extension on TranslationsRu {
'watchTogether.leave' => 'Покинуть',
'watchTogether.syncing' => 'Синхронизация...',
'watchTogether.joinWatchSession' => 'Присоединиться к просмотру',
'watchTogether.enterCodeHint' => 'Введите 8-символьный код',
'watchTogether.enterCodeHint' => 'Введите 5-символьный код',
'watchTogether.pasteFromClipboard' => 'Вставить из буфера обмена',
'watchTogether.pleaseEnterCode' => 'Введите код сессии',
'watchTogether.codeMustBe8Chars' => 'Код сессии должен содержать 8 символов',
'watchTogether.codeMustBe5Chars' => 'Код сессии должен содержать 5 символов',
'watchTogether.joinInstructions' => 'Введите код сессии, предоставленный хостом, чтобы присоединиться к просмотру.',
'watchTogether.failedToCreate' => 'Не удалось создать сессию',
'watchTogether.failedToJoin' => 'Не удалось присоединиться к сессии',
@@ -2014,6 +2020,12 @@ extension on TranslationsRu {
'watchTogether.failedToOpenCurrentPlayback' => 'Не удалось открыть текущее воспроизведение',
'watchTogether.participantJoined' => ({required Object name}) => '${name} присоединился',
'watchTogether.participantLeft' => ({required Object name}) => '${name} вышел',
'watchTogether.participantPaused' => ({required Object name}) => '${name} поставил на паузу',
'watchTogether.participantResumed' => ({required Object name}) => '${name} возобновил',
'watchTogether.participantSeeked' => ({required Object name}) => '${name} перемотал',
'watchTogether.recentRooms' => 'Недавние комнаты',
'watchTogether.renameRoom' => 'Переименовать комнату',
'watchTogether.removeRoom' => 'Удалить',
'downloads.title' => 'Загрузки',
'downloads.manage' => 'Управление',
'downloads.tvShows' => 'Сериалы',
+16 -4
View File
@@ -989,10 +989,10 @@ class _TranslationsWatchTogetherSv implements TranslationsWatchTogetherEn {
@override String get leave => 'Lämna';
@override String get syncing => 'Synkroniserar...';
@override String get joinWatchSession => 'Gå med i Tittarsession';
@override String get enterCodeHint => 'Ange 8-teckens kod';
@override String get enterCodeHint => 'Ange 5-teckens kod';
@override String get pasteFromClipboard => 'Klistra in från urklipp';
@override String get pleaseEnterCode => 'Vänligen ange en sessionskod';
@override String get codeMustBe8Chars => 'Sessionskod måste vara 8 tecken';
@override String get codeMustBe5Chars => 'Sessionskod måste vara 5 tecken';
@override String get joinInstructions => 'Ange sessionskoden som delats av värden för att gå med i deras tittarsession.';
@override String get failedToCreate => 'Det gick inte att skapa session';
@override String get failedToJoin => 'Det gick inte att gå med i session';
@@ -1005,6 +1005,12 @@ class _TranslationsWatchTogetherSv implements TranslationsWatchTogetherEn {
@override String get failedToOpenCurrentPlayback => 'Kunde inte öppna aktuell uppspelning';
@override String participantJoined({required Object name}) => '${name} gick med';
@override String participantLeft({required Object name}) => '${name} lämnade';
@override String participantPaused({required Object name}) => '${name} pausade';
@override String participantResumed({required Object name}) => '${name} återupptog';
@override String participantSeeked({required Object name}) => '${name} spolade';
@override String get recentRooms => 'Senaste rum';
@override String get renameRoom => 'Byt namn på rum';
@override String get removeRoom => 'Ta bort';
}
// Path: shaders
@@ -2023,10 +2029,10 @@ extension on TranslationsSv {
'watchTogether.leave' => 'Lämna',
'watchTogether.syncing' => 'Synkroniserar...',
'watchTogether.joinWatchSession' => 'Gå med i Tittarsession',
'watchTogether.enterCodeHint' => 'Ange 8-teckens kod',
'watchTogether.enterCodeHint' => 'Ange 5-teckens kod',
'watchTogether.pasteFromClipboard' => 'Klistra in från urklipp',
'watchTogether.pleaseEnterCode' => 'Vänligen ange en sessionskod',
'watchTogether.codeMustBe8Chars' => 'Sessionskod måste vara 8 tecken',
'watchTogether.codeMustBe5Chars' => 'Sessionskod måste vara 5 tecken',
'watchTogether.joinInstructions' => 'Ange sessionskoden som delats av värden för att gå med i deras tittarsession.',
'watchTogether.failedToCreate' => 'Det gick inte att skapa session',
'watchTogether.failedToJoin' => 'Det gick inte att gå med i session',
@@ -2039,6 +2045,12 @@ extension on TranslationsSv {
'watchTogether.failedToOpenCurrentPlayback' => 'Kunde inte öppna aktuell uppspelning',
'watchTogether.participantJoined' => ({required Object name}) => '${name} gick med',
'watchTogether.participantLeft' => ({required Object name}) => '${name} lämnade',
'watchTogether.participantPaused' => ({required Object name}) => '${name} pausade',
'watchTogether.participantResumed' => ({required Object name}) => '${name} återupptog',
'watchTogether.participantSeeked' => ({required Object name}) => '${name} spolade',
'watchTogether.recentRooms' => 'Senaste rum',
'watchTogether.renameRoom' => 'Byt namn på rum',
'watchTogether.removeRoom' => 'Ta bort',
'shaders.title' => 'Shaders',
'shaders.noShaderDescription' => 'Ingen videoförbättring',
'shaders.nvscalerDescription' => 'NVIDIA-bildskalning för skarpare video',
+16 -4
View File
@@ -989,10 +989,10 @@ class _TranslationsWatchTogetherZh implements TranslationsWatchTogetherEn {
@override String get leave => '离开';
@override String get syncing => '同步中...';
@override String get joinWatchSession => '加入观看会话';
@override String get enterCodeHint => '输入8位代码';
@override String get enterCodeHint => '输入5位代码';
@override String get pasteFromClipboard => '从剪贴板粘贴';
@override String get pleaseEnterCode => '请输入会话代码';
@override String get codeMustBe8Chars => '会话代码必须是8个字符';
@override String get codeMustBe5Chars => '会话代码必须是5个字符';
@override String get joinInstructions => '输入主持人分享的会话代码以加入他们的观看会话。';
@override String get failedToCreate => '创建会话失败';
@override String get failedToJoin => '加入会话失败';
@@ -1005,6 +1005,12 @@ class _TranslationsWatchTogetherZh implements TranslationsWatchTogetherEn {
@override String get failedToOpenCurrentPlayback => '无法打开当前播放';
@override String participantJoined({required Object name}) => '${name} 加入了';
@override String participantLeft({required Object name}) => '${name} 离开了';
@override String participantPaused({required Object name}) => '${name} 暂停了';
@override String participantResumed({required Object name}) => '${name} 继续播放了';
@override String participantSeeked({required Object name}) => '${name} 跳转了';
@override String get recentRooms => '最近的房间';
@override String get renameRoom => '重命名房间';
@override String get removeRoom => '移除';
}
// Path: shaders
@@ -2023,10 +2029,10 @@ extension on TranslationsZh {
'watchTogether.leave' => '离开',
'watchTogether.syncing' => '同步中...',
'watchTogether.joinWatchSession' => '加入观看会话',
'watchTogether.enterCodeHint' => '输入8位代码',
'watchTogether.enterCodeHint' => '输入5位代码',
'watchTogether.pasteFromClipboard' => '从剪贴板粘贴',
'watchTogether.pleaseEnterCode' => '请输入会话代码',
'watchTogether.codeMustBe8Chars' => '会话代码必须是8个字符',
'watchTogether.codeMustBe5Chars' => '会话代码必须是5个字符',
'watchTogether.joinInstructions' => '输入主持人分享的会话代码以加入他们的观看会话。',
'watchTogether.failedToCreate' => '创建会话失败',
'watchTogether.failedToJoin' => '加入会话失败',
@@ -2039,6 +2045,12 @@ extension on TranslationsZh {
'watchTogether.failedToOpenCurrentPlayback' => '无法打开当前播放',
'watchTogether.participantJoined' => ({required Object name}) => '${name} 加入了',
'watchTogether.participantLeft' => ({required Object name}) => '${name} 离开了',
'watchTogether.participantPaused' => ({required Object name}) => '${name} 暂停了',
'watchTogether.participantResumed' => ({required Object name}) => '${name} 继续播放了',
'watchTogether.participantSeeked' => ({required Object name}) => '${name} 跳转了',
'watchTogether.recentRooms' => '最近的房间',
'watchTogether.renameRoom' => '重命名房间',
'watchTogether.removeRoom' => '移除',
'shaders.title' => '着色器',
'shaders.noShaderDescription' => '无视频增强',
'shaders.nvscalerDescription' => 'NVIDIA 图像缩放,使视频更清晰',
+9 -3
View File
@@ -729,10 +729,10 @@
"leave": "Lämna",
"syncing": "Synkroniserar...",
"joinWatchSession": "Gå med i Tittarsession",
"enterCodeHint": "Ange 8-teckens kod",
"enterCodeHint": "Ange 5-teckens kod",
"pasteFromClipboard": "Klistra in från urklipp",
"pleaseEnterCode": "Vänligen ange en sessionskod",
"codeMustBe8Chars": "Sessionskod måste vara 8 tecken",
"codeMustBe5Chars": "Sessionskod måste vara 5 tecken",
"joinInstructions": "Ange sessionskoden som delats av värden för att gå med i deras tittarsession.",
"failedToCreate": "Det gick inte att skapa session",
"failedToJoin": "Det gick inte att gå med i session",
@@ -744,7 +744,13 @@
"joinCurrentPlaybackDescription": "Hoppa tillbaka till det värden tittar på just nu",
"failedToOpenCurrentPlayback": "Kunde inte öppna aktuell uppspelning",
"participantJoined": "${name} gick med",
"participantLeft": "${name} lämnade"
"participantLeft": "${name} lämnade",
"participantPaused": "${name} pausade",
"participantResumed": "${name} återupptog",
"participantSeeked": "${name} spolade",
"recentRooms": "Senaste rum",
"renameRoom": "Byt namn på rum",
"removeRoom": "Ta bort"
},
"shaders": {
"title": "Shaders",
+9 -3
View File
@@ -729,10 +729,10 @@
"leave": "离开",
"syncing": "同步中...",
"joinWatchSession": "加入观看会话",
"enterCodeHint": "输入8位代码",
"enterCodeHint": "输入5位代码",
"pasteFromClipboard": "从剪贴板粘贴",
"pleaseEnterCode": "请输入会话代码",
"codeMustBe8Chars": "会话代码必须是8个字符",
"codeMustBe5Chars": "会话代码必须是5个字符",
"joinInstructions": "输入主持人分享的会话代码以加入他们的观看会话。",
"failedToCreate": "创建会话失败",
"failedToJoin": "加入会话失败",
@@ -744,7 +744,13 @@
"joinCurrentPlaybackDescription": "回到房主当前正在观看的内容",
"failedToOpenCurrentPlayback": "无法打开当前播放",
"participantJoined": "${name} 加入了",
"participantLeft": "${name} 离开了"
"participantLeft": "${name} 离开了",
"participantPaused": "${name} 暂停了",
"participantResumed": "${name} 继续播放了",
"participantSeeked": "${name} 跳转了",
"recentRooms": "最近的房间",
"renameRoom": "重命名房间",
"removeRoom": "移除"
},
"shaders": {
"title": "着色器",
+10
View File
@@ -113,6 +113,7 @@ class SettingsService extends BaseSharedPreferencesService {
static const String _keyCustomShaderPresets = 'custom_shader_presets';
static const String _keyLiveTvDefaultFavorites = 'live_tv_default_favorites';
static const String _keyCustomRelayUrl = 'custom_relay_url';
static const String _keyRecentRooms = 'watch_together_recent_rooms';
static const String _keyMatchRefreshRate = 'match_refresh_rate';
static const String _keyMatchDynamicRange = 'match_dynamic_range';
static const String _keyDisplaySwitchDelay = 'display_switch_delay';
@@ -938,6 +939,15 @@ class SettingsService extends BaseSharedPreferencesService {
return prefs.getString(_keyCustomRelayUrl);
}
// Recent Watch Together rooms
Future<void> setRecentRooms(String json) async {
await prefs.setString(_keyRecentRooms, json);
}
String? getRecentRooms() {
return prefs.getString(_keyRecentRooms);
}
// Download on WiFi Only
Future<void> setDownloadOnWifiOnly(bool value) async {
await prefs.setBool(_keyDownloadOnWifiOnly, value);
@@ -50,6 +50,9 @@ class WatchTogetherProvider with ChangeNotifier {
Timer? _hostReconnectTimer;
bool _isWaitingForHostReconnect = false;
// Debounce map for action events (peerId+type → last emission timestamp)
final Map<String, int> _lastActionEventMs = {};
/// Generate a random display name for this session
static String _generateDisplayName() {
const adjectives = ['Happy', 'Sleepy', 'Sunny', 'Cozy', 'Chill', 'Swift', 'Brave', 'Calm', 'Jolly', 'Lucky'];
@@ -180,6 +183,8 @@ class WatchTogetherProvider with ChangeNotifier {
/// Create a new watch together session as host
Future<String> createSession({
required ControlMode controlMode,
String? displayName,
String? sessionId,
String? mediaRatingKey,
String? mediaServerId,
String? mediaTitle,
@@ -195,10 +200,10 @@ class WatchTogetherProvider with ChangeNotifier {
_setupPeerServiceListeners();
try {
final sessionId = await _peerService!.createSession();
final createdSessionId = await _peerService!.createSession(sessionId: sessionId);
_session = WatchSession.createAsHost(
sessionId: sessionId,
sessionId: createdSessionId,
hostPeerId: _peerService!.myPeerId!,
controlMode: controlMode,
mediaRatingKey: mediaRatingKey,
@@ -206,8 +211,7 @@ class WatchTogetherProvider with ChangeNotifier {
mediaTitle: mediaTitle,
).copyWith(state: SessionState.connected);
// Generate a random display name and add self to participants
_displayName = _generateDisplayName();
_displayName = displayName ?? _generateDisplayName();
_participants.add(Participant(peerId: _peerService!.myPeerId!, displayName: _displayName, isHost: true));
_syncManager = WatchTogetherSyncManager(
@@ -219,9 +223,9 @@ class WatchTogetherProvider with ChangeNotifier {
_wireSyncStateChanges();
notifyListeners();
appLogger.d('WatchTogether: Session created: $sessionId');
appLogger.d('WatchTogether: Session created: $createdSessionId');
return sessionId;
return createdSessionId;
} catch (e) {
appLogger.e('WatchTogether: Failed to create session', error: e);
_session = _session?.copyWith(state: SessionState.error, errorMessage: e.toString());
@@ -231,7 +235,7 @@ class WatchTogetherProvider with ChangeNotifier {
}
/// Join an existing session as guest
Future<void> joinSession(String sessionId) async {
Future<void> joinSession(String sessionId, {String? displayName}) async {
// Clean up any existing session
await leaveSession();
_lastHandledCurrentPlaybackKey = null;
@@ -251,8 +255,7 @@ class WatchTogetherProvider with ChangeNotifier {
// Session will be fully configured when we receive sessionConfig from host
_session = _session!.copyWith(state: SessionState.connected, hostPeerId: 'wt-${sessionId.toUpperCase()}');
// Generate a random display name for this session
_displayName = _generateDisplayName();
_displayName = displayName ?? _generateDisplayName();
_syncManager = WatchTogetherSyncManager(
peerService: _peerService!,
@@ -285,6 +288,32 @@ class WatchTogetherProvider with ChangeNotifier {
}
}
/// Enter a room by code — joins if it exists, creates if empty.
///
/// Returns `true` if the user became the host.
Future<bool> enterRoom(String sessionId, {ControlMode controlMode = ControlMode.anyone, String? displayName}) async {
// Probe the relay to determine if the room exists, then delegate to
// the existing createSession / joinSession which handle all setup.
final customRelayUrl = SettingsService.instanceOrNull?.getCustomRelayUrl();
final probe = WatchTogetherPeerService(customBaseUrl: customRelayUrl);
try {
final becameHost = await probe.joinOrCreateSession(sessionId);
await probe.disconnect();
probe.dispose();
if (becameHost) {
await createSession(controlMode: controlMode, displayName: displayName, sessionId: sessionId);
} else {
await joinSession(sessionId, displayName: displayName);
}
return becameHost;
} catch (e) {
await probe.disconnect();
probe.dispose();
rethrow;
}
}
/// Leave the current session
Future<void> leaveSession() async {
if (_session == null) return;
@@ -320,6 +349,7 @@ class WatchTogetherProvider with ChangeNotifier {
_participants.clear();
_isSyncing = false;
_lastHandledCurrentPlaybackKey = null;
_lastActionEventMs.clear();
notifyListeners();
appLogger.d('WatchTogether: Session left');
@@ -493,11 +523,39 @@ class WatchTogetherProvider with ChangeNotifier {
// Handled at sync manager level (host responds with config)
break;
case SyncMessageType.play:
_emitActionEvent(message.peerId, ParticipantEventType.resumed);
break;
case SyncMessageType.pause:
_emitActionEvent(message.peerId, ParticipantEventType.paused);
break;
case SyncMessageType.seek:
_emitActionEvent(message.peerId, ParticipantEventType.seeked);
break;
default:
break;
}
}
/// Emit an action event for a remote peer (with 1s debounce per peer+type)
void _emitActionEvent(String? peerId, ParticipantEventType type) {
if (peerId == null || peerId == _peerService?.myPeerId) return;
final key = '$peerId:${type.name}';
final now = DateTime.now().millisecondsSinceEpoch;
final last = _lastActionEventMs[key] ?? 0;
if (now - last < 1000) return;
_lastActionEventMs[key] = now;
final name = _participants.where((p) => p.peerId == peerId).map((p) => p.displayName).firstOrNull;
if (name != null) {
_participantEventController.add(ParticipantEvent(displayName: name, type: type));
}
}
/// Handle session config from host (guest only)
/// This is handled at provider level so it's processed even before player is attached
void _handleSessionConfig(SyncMessage message) {
@@ -679,7 +737,7 @@ class WatchTogetherProvider with ChangeNotifier {
}
/// Type of participant event
enum ParticipantEventType { joined, left }
enum ParticipantEventType { joined, left, paused, resumed, seeked }
/// Event emitted when a participant joins or leaves
class ParticipantEvent {
@@ -11,12 +11,14 @@ import '../../focus/focusable_button.dart';
import '../../focus/focusable_wrapper.dart';
import '../../services/settings_service.dart';
import '../../utils/app_logger.dart';
import '../../utils/provider_extensions.dart';
import '../../utils/dialogs.dart';
import '../../utils/snackbar_helper.dart';
import '../../utils/video_player_navigation.dart';
import '../../widgets/focused_scroll_scaffold.dart';
import '../models/watch_session.dart';
import '../providers/watch_together_provider.dart';
import '../services/recent_rooms_service.dart';
import '../services/watch_together_peer_service.dart';
import '../widgets/join_session_dialog.dart';
@@ -80,16 +82,23 @@ class _NotInSessionView extends StatefulWidget {
class _NotInSessionViewState extends State<_NotInSessionView> {
bool _isCreating = false;
bool _isJoining = false;
String? _enteringRoomCode;
bool? _healthOk;
String? _customRelayUrl;
List<RecentRoom> _recentRooms = [];
@override
void initState() {
super.initState();
_customRelayUrl = SettingsService.instanceOrNull?.getCustomRelayUrl();
_recentRooms = RecentRoomsService.getRecentRooms();
_checkHealth();
}
bool get _isBusy => _isCreating || _isJoining || _enteringRoomCode != null;
String? get _plexDisplayName => context.userProfile.currentUser?.displayName;
Future<void> _checkHealth() async {
try {
final client = HttpClient();
@@ -117,7 +126,7 @@ class _NotInSessionViewState extends State<_NotInSessionView> {
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Icon(Symbols.group_rounded, size: 80, color: theme.colorScheme.primary),
const SizedBox(height: 24),
@@ -153,10 +162,10 @@ class _NotInSessionViewState extends State<_NotInSessionView> {
SizedBox(
width: double.infinity,
child: FocusableButton(
autofocus: true,
onPressed: _isCreating || _isJoining ? null : _createSession,
autofocus: _recentRooms.isEmpty,
onPressed: _isBusy ? null : _createSession,
child: FilledButton.icon(
onPressed: _isCreating || _isJoining ? null : _createSession,
onPressed: _isBusy ? null : _createSession,
icon: _isCreating
? const SizedBox(width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2))
: const Icon(Symbols.add_rounded),
@@ -168,9 +177,9 @@ class _NotInSessionViewState extends State<_NotInSessionView> {
SizedBox(
width: double.infinity,
child: FocusableButton(
onPressed: _isCreating || _isJoining ? null : _joinSession,
onPressed: _isBusy ? null : _joinSession,
child: OutlinedButton.icon(
onPressed: _isCreating || _isJoining ? null : _joinSession,
onPressed: _isBusy ? null : _joinSession,
icon: _isJoining
? const SizedBox(width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2))
: const Icon(Symbols.group_add_rounded),
@@ -178,6 +187,22 @@ class _NotInSessionViewState extends State<_NotInSessionView> {
),
),
),
if (_recentRooms.isNotEmpty) ...[
const SizedBox(height: 32),
Align(
alignment: Alignment.centerLeft,
child: Text(t.watchTogether.recentRooms, style: theme.textTheme.titleSmall),
),
const SizedBox(height: 8),
..._recentRooms.map((room) => _RecentRoomTile(
room: room,
isBusy: _isBusy,
isEntering: _enteringRoomCode == room.code,
onTap: () => _enterRoom(room),
onRename: () => _renameRoom(room),
onRemove: () => _removeRoom(room),
)),
],
],
),
),
@@ -192,7 +217,12 @@ class _NotInSessionViewState extends State<_NotInSessionView> {
setState(() => _isCreating = true);
try {
await widget.watchTogether.createSession(controlMode: controlMode);
final sessionId = await widget.watchTogether.createSession(
controlMode: controlMode,
displayName: _plexDisplayName,
);
await RecentRoomsService.addOrUpdateRoom(sessionId);
if (mounted) setState(() => _recentRooms = RecentRoomsService.getRecentRooms());
} catch (e) {
appLogger.e('Failed to create session', error: e);
if (mounted) {
@@ -250,7 +280,9 @@ class _NotInSessionViewState extends State<_NotInSessionView> {
setState(() => _isJoining = true);
try {
await widget.watchTogether.joinSession(sessionId);
await widget.watchTogether.joinSession(sessionId, displayName: _plexDisplayName);
await RecentRoomsService.addOrUpdateRoom(sessionId);
if (mounted) setState(() => _recentRooms = RecentRoomsService.getRecentRooms());
} catch (e) {
appLogger.e('Failed to join session', error: e);
if (mounted) {
@@ -262,6 +294,133 @@ class _NotInSessionViewState extends State<_NotInSessionView> {
}
}
}
Future<void> _enterRoom(RecentRoom room) async {
setState(() => _enteringRoomCode = room.code);
try {
await widget.watchTogether.enterRoom(room.code, displayName: _plexDisplayName);
await RecentRoomsService.addOrUpdateRoom(room.code);
if (mounted) setState(() => _recentRooms = RecentRoomsService.getRecentRooms());
} catch (e) {
appLogger.e('Failed to enter room', error: e);
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('${t.watchTogether.failedToJoin}: $e')));
}
} finally {
if (mounted) {
setState(() => _enteringRoomCode = null);
}
}
}
Future<void> _renameRoom(RecentRoom room) async {
final controller = TextEditingController(text: room.name ?? '');
final name = await showDialog<String>(
context: context,
builder: (context) => AlertDialog(
title: Text(t.watchTogether.renameRoom),
content: TextField(
controller: controller,
autofocus: true,
decoration: InputDecoration(hintText: room.code),
onSubmitted: (value) => Navigator.pop(context, value),
),
actions: [
TextButton(onPressed: () => Navigator.pop(context), child: Text(t.common.cancel)),
FilledButton(onPressed: () => Navigator.pop(context, controller.text), child: Text(t.common.save)),
],
),
);
controller.dispose();
if (name == null || !mounted) return;
await RecentRoomsService.renameRoom(room.code, name.isEmpty ? null : name);
setState(() => _recentRooms = RecentRoomsService.getRecentRooms());
}
Future<void> _removeRoom(RecentRoom room) async {
await RecentRoomsService.removeRoom(room.code);
setState(() => _recentRooms = RecentRoomsService.getRecentRooms());
}
}
class _RecentRoomTile extends StatelessWidget {
final RecentRoom room;
final bool isBusy;
final bool isEntering;
final VoidCallback onTap;
final VoidCallback onRename;
final VoidCallback onRemove;
const _RecentRoomTile({
required this.room,
required this.isBusy,
required this.isEntering,
required this.onTap,
required this.onRename,
required this.onRemove,
});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final title = room.name ?? room.code;
return Padding(
padding: const EdgeInsets.only(bottom: 4),
child: FocusableWrapper(
useBackgroundFocus: true,
borderRadius: 12,
onSelect: isBusy ? null : onTap,
onLongPress: () => _showActions(context),
child: ListTile(
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(12))),
leading: isEntering
? const SizedBox(width: 24, height: 24, child: CircularProgressIndicator(strokeWidth: 2))
: const Icon(Symbols.meeting_room_rounded),
title: Text(title, maxLines: 1, overflow: TextOverflow.ellipsis),
subtitle: room.name != null
? Text(room.code, style: TextStyle(fontFamily: 'monospace', color: theme.colorScheme.onSurfaceVariant))
: null,
trailing: IconButton(
icon: const Icon(Symbols.more_vert_rounded),
onPressed: () => _showActions(context),
),
onTap: isBusy ? null : onTap,
),
),
);
}
void _showActions(BuildContext context) {
showModalBottomSheet(
context: context,
builder: (context) => SafeArea(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: const Icon(Symbols.edit_rounded),
title: Text(t.watchTogether.renameRoom),
onTap: () {
Navigator.pop(context);
onRename();
},
),
ListTile(
leading: Icon(Symbols.delete_rounded, color: Theme.of(context).colorScheme.error),
title: Text(t.watchTogether.removeRoom, style: TextStyle(color: Theme.of(context).colorScheme.error)),
onTap: () {
Navigator.pop(context);
onRemove();
},
),
],
),
),
);
}
}
/// Content shown when in an active session (without scroll wrapper)
@@ -0,0 +1,78 @@
import 'dart:convert';
import '../../services/settings_service.dart';
class RecentRoom {
final String code;
final String? name;
final DateTime lastUsed;
const RecentRoom({required this.code, this.name, required this.lastUsed});
Map<String, dynamic> toJson() => {
'code': code,
if (name != null) 'name': name,
'lastUsed': lastUsed.millisecondsSinceEpoch,
};
factory RecentRoom.fromJson(Map<String, dynamic> json) => RecentRoom(
code: json['code'] as String,
name: json['name'] as String?,
lastUsed: DateTime.fromMillisecondsSinceEpoch(json['lastUsed'] as int),
);
RecentRoom copyWith({String? code, String? name, DateTime? lastUsed, bool clearName = false}) => RecentRoom(
code: code ?? this.code,
name: clearName ? null : (name ?? this.name),
lastUsed: lastUsed ?? this.lastUsed,
);
}
class RecentRoomsService {
static const int _maxRooms = 20;
static List<RecentRoom> getRecentRooms() {
final json = SettingsService.instanceOrNull?.getRecentRooms();
if (json == null) return [];
try {
final list = jsonDecode(json) as List<dynamic>;
final rooms = list.map((e) => RecentRoom.fromJson(e as Map<String, dynamic>)).toList();
rooms.sort((a, b) => b.lastUsed.compareTo(a.lastUsed));
return rooms;
} catch (_) {
return [];
}
}
static Future<void> _save(List<RecentRoom> rooms) async {
rooms.sort((a, b) => b.lastUsed.compareTo(a.lastUsed));
if (rooms.length > _maxRooms) rooms.removeRange(_maxRooms, rooms.length);
await SettingsService.instanceOrNull?.setRecentRooms(jsonEncode(rooms.map((r) => r.toJson()).toList()));
}
static Future<void> addOrUpdateRoom(String code, {String? name}) async {
final rooms = getRecentRooms();
final index = rooms.indexWhere((r) => r.code == code);
if (index >= 0) {
rooms[index] = rooms[index].copyWith(lastUsed: DateTime.now(), name: name ?? rooms[index].name);
} else {
rooms.add(RecentRoom(code: code, name: name, lastUsed: DateTime.now()));
}
await _save(rooms);
}
static Future<void> removeRoom(String code) async {
final rooms = getRecentRooms();
rooms.removeWhere((r) => r.code == code);
await _save(rooms);
}
static Future<void> renameRoom(String code, String? name) async {
final rooms = getRecentRooms();
final index = rooms.indexWhere((r) => r.code == code);
if (index >= 0) {
rooms[index] = rooms[index].copyWith(name: name, clearName: name == null);
await _save(rooms);
}
}
}
@@ -1,5 +1,6 @@
import 'dart:async';
import 'dart:convert';
import 'dart:math';
import 'package:uuid/uuid.dart';
import '../../utils/future_extensions.dart';
@@ -98,9 +99,11 @@ class WatchTogetherPeerService with KeepaliveMixin {
/// List of connected peer IDs
List<String> get connectedPeers => _connectedPeers.toList();
/// Generate a short, readable session ID
String _generateSessionId() {
return const Uuid().v4().substring(0, 8).toUpperCase();
/// Generate a short, readable session ID (5 alphanumeric chars)
static String _generateSessionId() {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
final random = Random.secure();
return String.fromCharCodes(List.generate(5, (_) => chars.codeUnitAt(random.nextInt(chars.length))));
}
/// Connect to the relay WebSocket and set up the message listener.
@@ -308,13 +311,14 @@ class WatchTogetherPeerService with KeepaliveMixin {
/// Create a new session as host
///
/// Returns the session ID that others can use to join.
Future<String> createSession() async {
/// If [sessionId] is provided, uses that instead of generating a new one.
Future<String> createSession({String? sessionId}) async {
if (_channel != null) {
await disconnect();
}
_isHost = true;
_sessionId = _generateSessionId();
_sessionId = sessionId?.toUpperCase() ?? _generateSessionId();
_myPeerId = 'wt-$_sessionId';
_reconnectAttempts = 0;
@@ -380,6 +384,20 @@ class WatchTogetherPeerService with KeepaliveMixin {
}
}
/// Try to join a session; if it doesn't exist, create it as host.
///
/// Returns `true` if the user became the host (room was empty).
Future<bool> joinOrCreateSession(String sessionId) async {
try {
await joinSession(sessionId);
return false; // joined as guest
} on PeerError catch (e) {
if (e.type != PeerErrorType.serverError) rethrow;
await createSession(sessionId: sessionId);
return true; // created as host
}
}
/// Broadcast a message to all connected peers
void broadcast(SyncMessage message) {
final payload = message.toJson();
@@ -72,7 +72,7 @@ class _JoinSessionDialogState extends State<JoinSessionDialog> {
border: const OutlineInputBorder(),
),
textCapitalization: TextCapitalization.characters,
maxLength: 8,
maxLength: 5,
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'[A-Za-z0-9]')),
UpperCaseTextFormatter(),
@@ -81,8 +81,8 @@ class _JoinSessionDialogState extends State<JoinSessionDialog> {
if (value == null || value.isEmpty) {
return t.watchTogether.pleaseEnterCode;
}
if (value.length != 8) {
return t.watchTogether.codeMustBe8Chars;
if (value.length != 5) {
return t.watchTogether.codeMustBe5Chars;
}
return null;
},
@@ -123,7 +123,7 @@ class _JoinSessionDialogState extends State<JoinSessionDialog> {
// Clean the pasted text - extract alphanumeric characters and take first 8
final cleaned = data!.text!.replaceAll(RegExp(r'[^A-Za-z0-9]'), '').toUpperCase();
if (cleaned.isNotEmpty) {
_sessionIdController.text = cleaned.substring(0, cleaned.length.clamp(0, 8));
_sessionIdController.text = cleaned.substring(0, cleaned.length.clamp(0, 5));
_sessionIdController.selection = TextSelection.collapsed(offset: _sessionIdController.text.length);
}
}
@@ -346,9 +346,13 @@ class _ParticipantNotificationOverlayState extends State<ParticipantNotification
child: Column(
mainAxisSize: MainAxisSize.min,
children: _notifications.map((n) {
final text = n.event.type == ParticipantEventType.joined
? t.watchTogether.participantJoined(name: n.event.displayName)
: t.watchTogether.participantLeft(name: n.event.displayName);
final text = switch (n.event.type) {
ParticipantEventType.joined => t.watchTogether.participantJoined(name: n.event.displayName),
ParticipantEventType.left => t.watchTogether.participantLeft(name: n.event.displayName),
ParticipantEventType.paused => t.watchTogether.participantPaused(name: n.event.displayName),
ParticipantEventType.resumed => t.watchTogether.participantResumed(name: n.event.displayName),
ParticipantEventType.seeked => t.watchTogether.participantSeeked(name: n.event.displayName),
};
return Container(
margin: const EdgeInsets.only(bottom: 4),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),