diff --git a/lib/i18n/da.i18n.json b/lib/i18n/da.i18n.json index 3706336b..cd6cb7b8 100644 --- a/lib/i18n/da.i18n.json +++ b/lib/i18n/da.i18n.json @@ -1046,6 +1046,20 @@ "body": "Scan denne QR-kode med din telefon, eller åbn URL'en nedenfor på en enhed med browser.", "openToSignIn": "Åbn ${service} for at logge ind", "urlCopied": "URL kopieret" + }, + "libraryFilter": { + "title": "Bibliotekfilter", + "subtitleAllSyncing": "Synkroniserer alle biblioteker", + "subtitleNoneSyncing": "Intet synkroniseres", + "subtitleBlocked": "${count} blokeret", + "subtitleAllowed": "${count} tilladt", + "mode": "Filtertilstand", + "modeBlacklist": "Sortliste", + "modeWhitelist": "Hvidliste", + "modeHintBlacklist": "Synkroniser alle biblioteker undtagen dem du markerer nedenfor.", + "modeHintWhitelist": "Synkroniser kun de biblioteker du markerer nedenfor.", + "libraries": "Biblioteker", + "noLibraries": "Ingen biblioteker tilgængelige" } } } diff --git a/lib/i18n/de.i18n.json b/lib/i18n/de.i18n.json index 26278ec1..c0375318 100644 --- a/lib/i18n/de.i18n.json +++ b/lib/i18n/de.i18n.json @@ -1046,6 +1046,20 @@ "body": "Scanne diesen QR-Code mit deinem Handy oder öffne die URL unten auf einem Gerät mit Browser.", "openToSignIn": "${service} zum Anmelden öffnen", "urlCopied": "URL kopiert" + }, + "libraryFilter": { + "title": "Bibliothekfilter", + "subtitleAllSyncing": "Alle Bibliotheken werden synchronisiert", + "subtitleNoneSyncing": "Nichts wird synchronisiert", + "subtitleBlocked": "${count} blockiert", + "subtitleAllowed": "${count} erlaubt", + "mode": "Filtermodus", + "modeBlacklist": "Blacklist", + "modeWhitelist": "Whitelist", + "modeHintBlacklist": "Alle Bibliotheken außer den unten markierten synchronisieren.", + "modeHintWhitelist": "Nur die unten markierten Bibliotheken synchronisieren.", + "libraries": "Bibliotheken", + "noLibraries": "Keine Bibliotheken verfügbar" } } } diff --git a/lib/i18n/en.i18n.json b/lib/i18n/en.i18n.json index 48593450..dba37a47 100644 --- a/lib/i18n/en.i18n.json +++ b/lib/i18n/en.i18n.json @@ -1046,6 +1046,20 @@ "body": "Scan this QR code with your phone, or open the URL below on any device with a browser.", "openToSignIn": "Open ${service} to sign in", "urlCopied": "URL copied" + }, + "libraryFilter": { + "title": "Library filter", + "subtitleAllSyncing": "Syncing all libraries", + "subtitleNoneSyncing": "Nothing syncing", + "subtitleBlocked": "${count} blocked", + "subtitleAllowed": "${count} allowed", + "mode": "Filter mode", + "modeBlacklist": "Blacklist", + "modeWhitelist": "Whitelist", + "modeHintBlacklist": "Sync every library except the ones checked below.", + "modeHintWhitelist": "Sync only the libraries checked below.", + "libraries": "Libraries", + "noLibraries": "No libraries available" } } } diff --git a/lib/i18n/es.i18n.json b/lib/i18n/es.i18n.json index 42f392c5..dcf9f5b7 100644 --- a/lib/i18n/es.i18n.json +++ b/lib/i18n/es.i18n.json @@ -1046,6 +1046,20 @@ "body": "Escanea este código QR con tu teléfono, o abre la URL de abajo en cualquier dispositivo con navegador.", "openToSignIn": "Abrir ${service} para iniciar sesión", "urlCopied": "URL copiada" + }, + "libraryFilter": { + "title": "Filtro de bibliotecas", + "subtitleAllSyncing": "Sincronizando todas las bibliotecas", + "subtitleNoneSyncing": "Nada se sincroniza", + "subtitleBlocked": "${count} bloqueadas", + "subtitleAllowed": "${count} permitidas", + "mode": "Modo de filtro", + "modeBlacklist": "Lista negra", + "modeWhitelist": "Lista blanca", + "modeHintBlacklist": "Sincronizar todas las bibliotecas excepto las marcadas abajo.", + "modeHintWhitelist": "Sincronizar solo las bibliotecas marcadas abajo.", + "libraries": "Bibliotecas", + "noLibraries": "No hay bibliotecas disponibles" } } } diff --git a/lib/i18n/fr.i18n.json b/lib/i18n/fr.i18n.json index e6bc6df9..c344abaa 100644 --- a/lib/i18n/fr.i18n.json +++ b/lib/i18n/fr.i18n.json @@ -1046,6 +1046,20 @@ "body": "Scannez ce code QR avec votre téléphone, ou ouvrez l'URL ci-dessous sur un appareil équipé d'un navigateur.", "openToSignIn": "Ouvrir ${service} pour se connecter", "urlCopied": "URL copiée" + }, + "libraryFilter": { + "title": "Filtre de bibliothèques", + "subtitleAllSyncing": "Synchronisation de toutes les bibliothèques", + "subtitleNoneSyncing": "Aucune synchronisation", + "subtitleBlocked": "${count} bloquées", + "subtitleAllowed": "${count} autorisées", + "mode": "Mode de filtrage", + "modeBlacklist": "Liste noire", + "modeWhitelist": "Liste blanche", + "modeHintBlacklist": "Synchroniser toutes les bibliothèques sauf celles cochées ci-dessous.", + "modeHintWhitelist": "Synchroniser uniquement les bibliothèques cochées ci-dessous.", + "libraries": "Bibliothèques", + "noLibraries": "Aucune bibliothèque disponible" } } } diff --git a/lib/i18n/it.i18n.json b/lib/i18n/it.i18n.json index b77137c3..086d1a36 100644 --- a/lib/i18n/it.i18n.json +++ b/lib/i18n/it.i18n.json @@ -1046,6 +1046,20 @@ "body": "Scansiona questo codice QR con il telefono oppure apri l'URL sottostante su un dispositivo con browser.", "openToSignIn": "Apri ${service} per accedere", "urlCopied": "URL copiato" + }, + "libraryFilter": { + "title": "Filtro librerie", + "subtitleAllSyncing": "Sincronizzazione di tutte le librerie", + "subtitleNoneSyncing": "Nulla da sincronizzare", + "subtitleBlocked": "${count} bloccate", + "subtitleAllowed": "${count} consentite", + "mode": "Modalità filtro", + "modeBlacklist": "Lista nera", + "modeWhitelist": "Lista bianca", + "modeHintBlacklist": "Sincronizza tutte le librerie tranne quelle selezionate sotto.", + "modeHintWhitelist": "Sincronizza solo le librerie selezionate sotto.", + "libraries": "Librerie", + "noLibraries": "Nessuna libreria disponibile" } } } diff --git a/lib/i18n/ja.i18n.json b/lib/i18n/ja.i18n.json index a8c2ee54..eea05d73 100644 --- a/lib/i18n/ja.i18n.json +++ b/lib/i18n/ja.i18n.json @@ -1046,6 +1046,20 @@ "body": "このQRコードをスマートフォンで読み取るか、下のURLをブラウザで開いてください。", "openToSignIn": "${service} を開いてサインイン", "urlCopied": "URLをコピーしました" + }, + "libraryFilter": { + "title": "ライブラリフィルター", + "subtitleAllSyncing": "すべてのライブラリを同期中", + "subtitleNoneSyncing": "同期なし", + "subtitleBlocked": "${count} 件をブロック", + "subtitleAllowed": "${count} 件を許可", + "mode": "フィルターモード", + "modeBlacklist": "ブロックリスト", + "modeWhitelist": "許可リスト", + "modeHintBlacklist": "下でチェックしたライブラリ以外をすべて同期します。", + "modeHintWhitelist": "下でチェックしたライブラリのみ同期します。", + "libraries": "ライブラリ", + "noLibraries": "利用できるライブラリがありません" } } } diff --git a/lib/i18n/ko.i18n.json b/lib/i18n/ko.i18n.json index e79d4105..8f3596ca 100644 --- a/lib/i18n/ko.i18n.json +++ b/lib/i18n/ko.i18n.json @@ -1046,6 +1046,20 @@ "body": "휴대전화로 이 QR 코드를 스캔하거나 아래 URL을 브라우저가 있는 기기에서 여세요.", "openToSignIn": "로그인하려면 ${service} 열기", "urlCopied": "URL이 복사되었습니다" + }, + "libraryFilter": { + "title": "라이브러리 필터", + "subtitleAllSyncing": "모든 라이브러리 동기화 중", + "subtitleNoneSyncing": "동기화 안 함", + "subtitleBlocked": "${count}개 차단됨", + "subtitleAllowed": "${count}개 허용됨", + "mode": "필터 모드", + "modeBlacklist": "차단 목록", + "modeWhitelist": "허용 목록", + "modeHintBlacklist": "아래에 선택한 라이브러리를 제외한 모든 라이브러리를 동기화합니다.", + "modeHintWhitelist": "아래에 선택한 라이브러리만 동기화합니다.", + "libraries": "라이브러리", + "noLibraries": "사용 가능한 라이브러리가 없습니다" } } } diff --git a/lib/i18n/nb.i18n.json b/lib/i18n/nb.i18n.json index eacc98b8..bd1bdccd 100644 --- a/lib/i18n/nb.i18n.json +++ b/lib/i18n/nb.i18n.json @@ -1046,6 +1046,20 @@ "body": "Skann denne QR-koden med telefonen din, eller åpne URL-en under på en enhet med nettleser.", "openToSignIn": "Åpne ${service} for å logge inn", "urlCopied": "URL kopiert" + }, + "libraryFilter": { + "title": "Biblioteksfilter", + "subtitleAllSyncing": "Synkroniserer alle biblioteker", + "subtitleNoneSyncing": "Ingenting synkroniseres", + "subtitleBlocked": "${count} blokkert", + "subtitleAllowed": "${count} tillatt", + "mode": "Filtermodus", + "modeBlacklist": "Svarteliste", + "modeWhitelist": "Hviteliste", + "modeHintBlacklist": "Synkroniser alle biblioteker bortsett fra dem du markerer nedenfor.", + "modeHintWhitelist": "Synkroniser kun bibliotekene du markerer nedenfor.", + "libraries": "Biblioteker", + "noLibraries": "Ingen biblioteker tilgjengelige" } } } diff --git a/lib/i18n/nl.i18n.json b/lib/i18n/nl.i18n.json index d171ca0d..a88a5056 100644 --- a/lib/i18n/nl.i18n.json +++ b/lib/i18n/nl.i18n.json @@ -1046,6 +1046,20 @@ "body": "Scan deze QR-code met je telefoon, of open onderstaande URL op een apparaat met browser.", "openToSignIn": "${service} openen om aan te melden", "urlCopied": "URL gekopieerd" + }, + "libraryFilter": { + "title": "Bibliotheekfilter", + "subtitleAllSyncing": "Alle bibliotheken synchroniseren", + "subtitleNoneSyncing": "Niets wordt gesynchroniseerd", + "subtitleBlocked": "${count} geblokkeerd", + "subtitleAllowed": "${count} toegestaan", + "mode": "Filtermodus", + "modeBlacklist": "Zwarte lijst", + "modeWhitelist": "Witte lijst", + "modeHintBlacklist": "Synchroniseer alle bibliotheken behalve die hieronder aangevinkt zijn.", + "modeHintWhitelist": "Synchroniseer alleen de hieronder aangevinkte bibliotheken.", + "libraries": "Bibliotheken", + "noLibraries": "Geen bibliotheken beschikbaar" } } } diff --git a/lib/i18n/pl.i18n.json b/lib/i18n/pl.i18n.json index 436f3073..f0b20f1b 100644 --- a/lib/i18n/pl.i18n.json +++ b/lib/i18n/pl.i18n.json @@ -1046,6 +1046,20 @@ "body": "Zeskanuj ten kod QR telefonem lub otwórz poniższy adres URL na dowolnym urządzeniu z przeglądarką.", "openToSignIn": "Otwórz ${service}, aby się zalogować", "urlCopied": "URL skopiowany" + }, + "libraryFilter": { + "title": "Filtr bibliotek", + "subtitleAllSyncing": "Synchronizowanie wszystkich bibliotek", + "subtitleNoneSyncing": "Nic nie synchronizuje", + "subtitleBlocked": "${count} zablokowanych", + "subtitleAllowed": "${count} dozwolonych", + "mode": "Tryb filtra", + "modeBlacklist": "Czarna lista", + "modeWhitelist": "Biała lista", + "modeHintBlacklist": "Synchronizuj wszystkie biblioteki oprócz zaznaczonych poniżej.", + "modeHintWhitelist": "Synchronizuj tylko biblioteki zaznaczone poniżej.", + "libraries": "Biblioteki", + "noLibraries": "Brak dostępnych bibliotek" } } } diff --git a/lib/i18n/pt.i18n.json b/lib/i18n/pt.i18n.json index 6f717ae0..b082b863 100644 --- a/lib/i18n/pt.i18n.json +++ b/lib/i18n/pt.i18n.json @@ -1046,6 +1046,20 @@ "body": "Escaneie este código QR com o celular, ou abra o URL abaixo em qualquer dispositivo com navegador.", "openToSignIn": "Abrir ${service} para entrar", "urlCopied": "URL copiado" + }, + "libraryFilter": { + "title": "Filtro de bibliotecas", + "subtitleAllSyncing": "Sincronizando todas as bibliotecas", + "subtitleNoneSyncing": "Nada a sincronizar", + "subtitleBlocked": "${count} bloqueadas", + "subtitleAllowed": "${count} permitidas", + "mode": "Modo de filtro", + "modeBlacklist": "Lista negra", + "modeWhitelist": "Lista branca", + "modeHintBlacklist": "Sincronizar todas as bibliotecas exceto as marcadas abaixo.", + "modeHintWhitelist": "Sincronizar apenas as bibliotecas marcadas abaixo.", + "libraries": "Bibliotecas", + "noLibraries": "Nenhuma biblioteca disponível" } } } diff --git a/lib/i18n/ru.i18n.json b/lib/i18n/ru.i18n.json index 5b0df64b..ed87b332 100644 --- a/lib/i18n/ru.i18n.json +++ b/lib/i18n/ru.i18n.json @@ -1046,6 +1046,20 @@ "body": "Отсканируйте этот QR-код телефоном или откройте ссылку ниже на любом устройстве с браузером.", "openToSignIn": "Открыть ${service} для входа", "urlCopied": "URL скопирован" + }, + "libraryFilter": { + "title": "Фильтр библиотек", + "subtitleAllSyncing": "Синхронизация всех библиотек", + "subtitleNoneSyncing": "Ничего не синхронизируется", + "subtitleBlocked": "${count} заблокировано", + "subtitleAllowed": "${count} разрешено", + "mode": "Режим фильтра", + "modeBlacklist": "Чёрный список", + "modeWhitelist": "Белый список", + "modeHintBlacklist": "Синхронизировать все библиотеки, кроме отмеченных ниже.", + "modeHintWhitelist": "Синхронизировать только библиотеки, отмеченные ниже.", + "libraries": "Библиотеки", + "noLibraries": "Библиотеки недоступны" } } } diff --git a/lib/i18n/strings.g.dart b/lib/i18n/strings.g.dart index 13742d8e..d9041a62 100644 --- a/lib/i18n/strings.g.dart +++ b/lib/i18n/strings.g.dart @@ -4,9 +4,9 @@ /// To regenerate, run: `dart run slang` /// /// Locales: 15 -/// Strings: 14205 (947 per locale) +/// Strings: 14385 (959 per locale) /// -/// Built on 2026-04-24 at 07:00 UTC +/// Built on 2026-04-24 at 08:07 UTC // coverage:ignore-file // ignore_for_file: type=lint, unused_import diff --git a/lib/i18n/strings_da.g.dart b/lib/i18n/strings_da.g.dart index 4c659a4c..adf93619 100644 --- a/lib/i18n/strings_da.g.dart +++ b/lib/i18n/strings_da.g.dart @@ -1299,6 +1299,7 @@ class _TranslationsTrackersDa implements TranslationsTrackersEn { @override late final _TranslationsTrackersServicesDa services = _TranslationsTrackersServicesDa._(_root); @override late final _TranslationsTrackersDeviceCodeDa deviceCode = _TranslationsTrackersDeviceCodeDa._(_root); @override late final _TranslationsTrackersOauthProxyDa oauthProxy = _TranslationsTrackersOauthProxyDa._(_root); + @override late final _TranslationsTrackersLibraryFilterDa libraryFilter = _TranslationsTrackersLibraryFilterDa._(_root); } // Path: hotkeys.actions @@ -1496,6 +1497,27 @@ class _TranslationsTrackersOauthProxyDa implements TranslationsTrackersOauthProx @override String get urlCopied => 'URL kopieret'; } +// Path: trackers.libraryFilter +class _TranslationsTrackersLibraryFilterDa implements TranslationsTrackersLibraryFilterEn { + _TranslationsTrackersLibraryFilterDa._(this._root); + + final TranslationsDa _root; // ignore: unused_field + + // Translations + @override String get title => 'Bibliotekfilter'; + @override String get subtitleAllSyncing => 'Synkroniserer alle biblioteker'; + @override String get subtitleNoneSyncing => 'Intet synkroniseres'; + @override String subtitleBlocked({required Object count}) => '${count} blokeret'; + @override String subtitleAllowed({required Object count}) => '${count} tilladt'; + @override String get mode => 'Filtertilstand'; + @override String get modeBlacklist => 'Sortliste'; + @override String get modeWhitelist => 'Hvidliste'; + @override String get modeHintBlacklist => 'Synkroniser alle biblioteker undtagen dem du markerer nedenfor.'; + @override String get modeHintWhitelist => 'Synkroniser kun de biblioteker du markerer nedenfor.'; + @override String get libraries => 'Biblioteker'; + @override String get noLibraries => 'Ingen biblioteker tilgængelige'; +} + /// The flat map containing all translations for locale . /// Only for edge cases! For simple maps, use the map function of this library. /// @@ -2453,6 +2475,18 @@ extension on TranslationsDa { 'trackers.oauthProxy.body' => 'Scan denne QR-kode med din telefon, eller åbn URL\'en nedenfor på en enhed med browser.', 'trackers.oauthProxy.openToSignIn' => ({required Object service}) => 'Åbn ${service} for at logge ind', 'trackers.oauthProxy.urlCopied' => 'URL kopieret', + 'trackers.libraryFilter.title' => 'Bibliotekfilter', + 'trackers.libraryFilter.subtitleAllSyncing' => 'Synkroniserer alle biblioteker', + 'trackers.libraryFilter.subtitleNoneSyncing' => 'Intet synkroniseres', + 'trackers.libraryFilter.subtitleBlocked' => ({required Object count}) => '${count} blokeret', + 'trackers.libraryFilter.subtitleAllowed' => ({required Object count}) => '${count} tilladt', + 'trackers.libraryFilter.mode' => 'Filtertilstand', + 'trackers.libraryFilter.modeBlacklist' => 'Sortliste', + 'trackers.libraryFilter.modeWhitelist' => 'Hvidliste', + 'trackers.libraryFilter.modeHintBlacklist' => 'Synkroniser alle biblioteker undtagen dem du markerer nedenfor.', + 'trackers.libraryFilter.modeHintWhitelist' => 'Synkroniser kun de biblioteker du markerer nedenfor.', + 'trackers.libraryFilter.libraries' => 'Biblioteker', + 'trackers.libraryFilter.noLibraries' => 'Ingen biblioteker tilgængelige', _ => null, }; } diff --git a/lib/i18n/strings_de.g.dart b/lib/i18n/strings_de.g.dart index 083c1167..071e76bd 100644 --- a/lib/i18n/strings_de.g.dart +++ b/lib/i18n/strings_de.g.dart @@ -1299,6 +1299,7 @@ class _TranslationsTrackersDe implements TranslationsTrackersEn { @override late final _TranslationsTrackersServicesDe services = _TranslationsTrackersServicesDe._(_root); @override late final _TranslationsTrackersDeviceCodeDe deviceCode = _TranslationsTrackersDeviceCodeDe._(_root); @override late final _TranslationsTrackersOauthProxyDe oauthProxy = _TranslationsTrackersOauthProxyDe._(_root); + @override late final _TranslationsTrackersLibraryFilterDe libraryFilter = _TranslationsTrackersLibraryFilterDe._(_root); } // Path: hotkeys.actions @@ -1496,6 +1497,27 @@ class _TranslationsTrackersOauthProxyDe implements TranslationsTrackersOauthProx @override String get urlCopied => 'URL kopiert'; } +// Path: trackers.libraryFilter +class _TranslationsTrackersLibraryFilterDe implements TranslationsTrackersLibraryFilterEn { + _TranslationsTrackersLibraryFilterDe._(this._root); + + final TranslationsDe _root; // ignore: unused_field + + // Translations + @override String get title => 'Bibliothekfilter'; + @override String get subtitleAllSyncing => 'Alle Bibliotheken werden synchronisiert'; + @override String get subtitleNoneSyncing => 'Nichts wird synchronisiert'; + @override String subtitleBlocked({required Object count}) => '${count} blockiert'; + @override String subtitleAllowed({required Object count}) => '${count} erlaubt'; + @override String get mode => 'Filtermodus'; + @override String get modeBlacklist => 'Blacklist'; + @override String get modeWhitelist => 'Whitelist'; + @override String get modeHintBlacklist => 'Alle Bibliotheken außer den unten markierten synchronisieren.'; + @override String get modeHintWhitelist => 'Nur die unten markierten Bibliotheken synchronisieren.'; + @override String get libraries => 'Bibliotheken'; + @override String get noLibraries => 'Keine Bibliotheken verfügbar'; +} + /// The flat map containing all translations for locale . /// Only for edge cases! For simple maps, use the map function of this library. /// @@ -2453,6 +2475,18 @@ extension on TranslationsDe { 'trackers.oauthProxy.body' => 'Scanne diesen QR-Code mit deinem Handy oder öffne die URL unten auf einem Gerät mit Browser.', 'trackers.oauthProxy.openToSignIn' => ({required Object service}) => '${service} zum Anmelden öffnen', 'trackers.oauthProxy.urlCopied' => 'URL kopiert', + 'trackers.libraryFilter.title' => 'Bibliothekfilter', + 'trackers.libraryFilter.subtitleAllSyncing' => 'Alle Bibliotheken werden synchronisiert', + 'trackers.libraryFilter.subtitleNoneSyncing' => 'Nichts wird synchronisiert', + 'trackers.libraryFilter.subtitleBlocked' => ({required Object count}) => '${count} blockiert', + 'trackers.libraryFilter.subtitleAllowed' => ({required Object count}) => '${count} erlaubt', + 'trackers.libraryFilter.mode' => 'Filtermodus', + 'trackers.libraryFilter.modeBlacklist' => 'Blacklist', + 'trackers.libraryFilter.modeWhitelist' => 'Whitelist', + 'trackers.libraryFilter.modeHintBlacklist' => 'Alle Bibliotheken außer den unten markierten synchronisieren.', + 'trackers.libraryFilter.modeHintWhitelist' => 'Nur die unten markierten Bibliotheken synchronisieren.', + 'trackers.libraryFilter.libraries' => 'Bibliotheken', + 'trackers.libraryFilter.noLibraries' => 'Keine Bibliotheken verfügbar', _ => null, }; } diff --git a/lib/i18n/strings_en.g.dart b/lib/i18n/strings_en.g.dart index c810bd99..a498e3f0 100644 --- a/lib/i18n/strings_en.g.dart +++ b/lib/i18n/strings_en.g.dart @@ -2991,6 +2991,7 @@ class TranslationsTrackersEn { late final TranslationsTrackersServicesEn services = TranslationsTrackersServicesEn._(_root); late final TranslationsTrackersDeviceCodeEn deviceCode = TranslationsTrackersDeviceCodeEn._(_root); late final TranslationsTrackersOauthProxyEn oauthProxy = TranslationsTrackersOauthProxyEn._(_root); + late final TranslationsTrackersLibraryFilterEn libraryFilter = TranslationsTrackersLibraryFilterEn._(_root); } // Path: hotkeys.actions @@ -3398,6 +3399,51 @@ class TranslationsTrackersOauthProxyEn { String get urlCopied => 'URL copied'; } +// Path: trackers.libraryFilter +class TranslationsTrackersLibraryFilterEn { + TranslationsTrackersLibraryFilterEn._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + + /// en: 'Library filter' + String get title => 'Library filter'; + + /// en: 'Syncing all libraries' + String get subtitleAllSyncing => 'Syncing all libraries'; + + /// en: 'Nothing syncing' + String get subtitleNoneSyncing => 'Nothing syncing'; + + /// en: '${count} blocked' + String subtitleBlocked({required Object count}) => '${count} blocked'; + + /// en: '${count} allowed' + String subtitleAllowed({required Object count}) => '${count} allowed'; + + /// en: 'Filter mode' + String get mode => 'Filter mode'; + + /// en: 'Blacklist' + String get modeBlacklist => 'Blacklist'; + + /// en: 'Whitelist' + String get modeWhitelist => 'Whitelist'; + + /// en: 'Sync every library except the ones checked below.' + String get modeHintBlacklist => 'Sync every library except the ones checked below.'; + + /// en: 'Sync only the libraries checked below.' + String get modeHintWhitelist => 'Sync only the libraries checked below.'; + + /// en: 'Libraries' + String get libraries => 'Libraries'; + + /// en: 'No libraries available' + String get noLibraries => 'No libraries available'; +} + /// The flat map containing all translations for locale . /// Only for edge cases! For simple maps, use the map function of this library. /// @@ -4355,6 +4401,18 @@ extension on Translations { 'trackers.oauthProxy.body' => 'Scan this QR code with your phone, or open the URL below on any device with a browser.', 'trackers.oauthProxy.openToSignIn' => ({required Object service}) => 'Open ${service} to sign in', 'trackers.oauthProxy.urlCopied' => 'URL copied', + 'trackers.libraryFilter.title' => 'Library filter', + 'trackers.libraryFilter.subtitleAllSyncing' => 'Syncing all libraries', + 'trackers.libraryFilter.subtitleNoneSyncing' => 'Nothing syncing', + 'trackers.libraryFilter.subtitleBlocked' => ({required Object count}) => '${count} blocked', + 'trackers.libraryFilter.subtitleAllowed' => ({required Object count}) => '${count} allowed', + 'trackers.libraryFilter.mode' => 'Filter mode', + 'trackers.libraryFilter.modeBlacklist' => 'Blacklist', + 'trackers.libraryFilter.modeWhitelist' => 'Whitelist', + 'trackers.libraryFilter.modeHintBlacklist' => 'Sync every library except the ones checked below.', + 'trackers.libraryFilter.modeHintWhitelist' => 'Sync only the libraries checked below.', + 'trackers.libraryFilter.libraries' => 'Libraries', + 'trackers.libraryFilter.noLibraries' => 'No libraries available', _ => null, }; } diff --git a/lib/i18n/strings_es.g.dart b/lib/i18n/strings_es.g.dart index 88863f77..40f02070 100644 --- a/lib/i18n/strings_es.g.dart +++ b/lib/i18n/strings_es.g.dart @@ -1299,6 +1299,7 @@ class _TranslationsTrackersEs implements TranslationsTrackersEn { @override late final _TranslationsTrackersServicesEs services = _TranslationsTrackersServicesEs._(_root); @override late final _TranslationsTrackersDeviceCodeEs deviceCode = _TranslationsTrackersDeviceCodeEs._(_root); @override late final _TranslationsTrackersOauthProxyEs oauthProxy = _TranslationsTrackersOauthProxyEs._(_root); + @override late final _TranslationsTrackersLibraryFilterEs libraryFilter = _TranslationsTrackersLibraryFilterEs._(_root); } // Path: hotkeys.actions @@ -1496,6 +1497,27 @@ class _TranslationsTrackersOauthProxyEs implements TranslationsTrackersOauthProx @override String get urlCopied => 'URL copiada'; } +// Path: trackers.libraryFilter +class _TranslationsTrackersLibraryFilterEs implements TranslationsTrackersLibraryFilterEn { + _TranslationsTrackersLibraryFilterEs._(this._root); + + final TranslationsEs _root; // ignore: unused_field + + // Translations + @override String get title => 'Filtro de bibliotecas'; + @override String get subtitleAllSyncing => 'Sincronizando todas las bibliotecas'; + @override String get subtitleNoneSyncing => 'Nada se sincroniza'; + @override String subtitleBlocked({required Object count}) => '${count} bloqueadas'; + @override String subtitleAllowed({required Object count}) => '${count} permitidas'; + @override String get mode => 'Modo de filtro'; + @override String get modeBlacklist => 'Lista negra'; + @override String get modeWhitelist => 'Lista blanca'; + @override String get modeHintBlacklist => 'Sincronizar todas las bibliotecas excepto las marcadas abajo.'; + @override String get modeHintWhitelist => 'Sincronizar solo las bibliotecas marcadas abajo.'; + @override String get libraries => 'Bibliotecas'; + @override String get noLibraries => 'No hay bibliotecas disponibles'; +} + /// The flat map containing all translations for locale . /// Only for edge cases! For simple maps, use the map function of this library. /// @@ -2453,6 +2475,18 @@ extension on TranslationsEs { 'trackers.oauthProxy.body' => 'Escanea este código QR con tu teléfono, o abre la URL de abajo en cualquier dispositivo con navegador.', 'trackers.oauthProxy.openToSignIn' => ({required Object service}) => 'Abrir ${service} para iniciar sesión', 'trackers.oauthProxy.urlCopied' => 'URL copiada', + 'trackers.libraryFilter.title' => 'Filtro de bibliotecas', + 'trackers.libraryFilter.subtitleAllSyncing' => 'Sincronizando todas las bibliotecas', + 'trackers.libraryFilter.subtitleNoneSyncing' => 'Nada se sincroniza', + 'trackers.libraryFilter.subtitleBlocked' => ({required Object count}) => '${count} bloqueadas', + 'trackers.libraryFilter.subtitleAllowed' => ({required Object count}) => '${count} permitidas', + 'trackers.libraryFilter.mode' => 'Modo de filtro', + 'trackers.libraryFilter.modeBlacklist' => 'Lista negra', + 'trackers.libraryFilter.modeWhitelist' => 'Lista blanca', + 'trackers.libraryFilter.modeHintBlacklist' => 'Sincronizar todas las bibliotecas excepto las marcadas abajo.', + 'trackers.libraryFilter.modeHintWhitelist' => 'Sincronizar solo las bibliotecas marcadas abajo.', + 'trackers.libraryFilter.libraries' => 'Bibliotecas', + 'trackers.libraryFilter.noLibraries' => 'No hay bibliotecas disponibles', _ => null, }; } diff --git a/lib/i18n/strings_fr.g.dart b/lib/i18n/strings_fr.g.dart index 85c067d3..c83f7921 100644 --- a/lib/i18n/strings_fr.g.dart +++ b/lib/i18n/strings_fr.g.dart @@ -1299,6 +1299,7 @@ class _TranslationsTrackersFr implements TranslationsTrackersEn { @override late final _TranslationsTrackersServicesFr services = _TranslationsTrackersServicesFr._(_root); @override late final _TranslationsTrackersDeviceCodeFr deviceCode = _TranslationsTrackersDeviceCodeFr._(_root); @override late final _TranslationsTrackersOauthProxyFr oauthProxy = _TranslationsTrackersOauthProxyFr._(_root); + @override late final _TranslationsTrackersLibraryFilterFr libraryFilter = _TranslationsTrackersLibraryFilterFr._(_root); } // Path: hotkeys.actions @@ -1496,6 +1497,27 @@ class _TranslationsTrackersOauthProxyFr implements TranslationsTrackersOauthProx @override String get urlCopied => 'URL copiée'; } +// Path: trackers.libraryFilter +class _TranslationsTrackersLibraryFilterFr implements TranslationsTrackersLibraryFilterEn { + _TranslationsTrackersLibraryFilterFr._(this._root); + + final TranslationsFr _root; // ignore: unused_field + + // Translations + @override String get title => 'Filtre de bibliothèques'; + @override String get subtitleAllSyncing => 'Synchronisation de toutes les bibliothèques'; + @override String get subtitleNoneSyncing => 'Aucune synchronisation'; + @override String subtitleBlocked({required Object count}) => '${count} bloquées'; + @override String subtitleAllowed({required Object count}) => '${count} autorisées'; + @override String get mode => 'Mode de filtrage'; + @override String get modeBlacklist => 'Liste noire'; + @override String get modeWhitelist => 'Liste blanche'; + @override String get modeHintBlacklist => 'Synchroniser toutes les bibliothèques sauf celles cochées ci-dessous.'; + @override String get modeHintWhitelist => 'Synchroniser uniquement les bibliothèques cochées ci-dessous.'; + @override String get libraries => 'Bibliothèques'; + @override String get noLibraries => 'Aucune bibliothèque disponible'; +} + /// The flat map containing all translations for locale . /// Only for edge cases! For simple maps, use the map function of this library. /// @@ -2453,6 +2475,18 @@ extension on TranslationsFr { 'trackers.oauthProxy.body' => 'Scannez ce code QR avec votre téléphone, ou ouvrez l\'URL ci-dessous sur un appareil équipé d\'un navigateur.', 'trackers.oauthProxy.openToSignIn' => ({required Object service}) => 'Ouvrir ${service} pour se connecter', 'trackers.oauthProxy.urlCopied' => 'URL copiée', + 'trackers.libraryFilter.title' => 'Filtre de bibliothèques', + 'trackers.libraryFilter.subtitleAllSyncing' => 'Synchronisation de toutes les bibliothèques', + 'trackers.libraryFilter.subtitleNoneSyncing' => 'Aucune synchronisation', + 'trackers.libraryFilter.subtitleBlocked' => ({required Object count}) => '${count} bloquées', + 'trackers.libraryFilter.subtitleAllowed' => ({required Object count}) => '${count} autorisées', + 'trackers.libraryFilter.mode' => 'Mode de filtrage', + 'trackers.libraryFilter.modeBlacklist' => 'Liste noire', + 'trackers.libraryFilter.modeWhitelist' => 'Liste blanche', + 'trackers.libraryFilter.modeHintBlacklist' => 'Synchroniser toutes les bibliothèques sauf celles cochées ci-dessous.', + 'trackers.libraryFilter.modeHintWhitelist' => 'Synchroniser uniquement les bibliothèques cochées ci-dessous.', + 'trackers.libraryFilter.libraries' => 'Bibliothèques', + 'trackers.libraryFilter.noLibraries' => 'Aucune bibliothèque disponible', _ => null, }; } diff --git a/lib/i18n/strings_it.g.dart b/lib/i18n/strings_it.g.dart index 81bc7bcd..93f755eb 100644 --- a/lib/i18n/strings_it.g.dart +++ b/lib/i18n/strings_it.g.dart @@ -1299,6 +1299,7 @@ class _TranslationsTrackersIt implements TranslationsTrackersEn { @override late final _TranslationsTrackersServicesIt services = _TranslationsTrackersServicesIt._(_root); @override late final _TranslationsTrackersDeviceCodeIt deviceCode = _TranslationsTrackersDeviceCodeIt._(_root); @override late final _TranslationsTrackersOauthProxyIt oauthProxy = _TranslationsTrackersOauthProxyIt._(_root); + @override late final _TranslationsTrackersLibraryFilterIt libraryFilter = _TranslationsTrackersLibraryFilterIt._(_root); } // Path: hotkeys.actions @@ -1496,6 +1497,27 @@ class _TranslationsTrackersOauthProxyIt implements TranslationsTrackersOauthProx @override String get urlCopied => 'URL copiato'; } +// Path: trackers.libraryFilter +class _TranslationsTrackersLibraryFilterIt implements TranslationsTrackersLibraryFilterEn { + _TranslationsTrackersLibraryFilterIt._(this._root); + + final TranslationsIt _root; // ignore: unused_field + + // Translations + @override String get title => 'Filtro librerie'; + @override String get subtitleAllSyncing => 'Sincronizzazione di tutte le librerie'; + @override String get subtitleNoneSyncing => 'Nulla da sincronizzare'; + @override String subtitleBlocked({required Object count}) => '${count} bloccate'; + @override String subtitleAllowed({required Object count}) => '${count} consentite'; + @override String get mode => 'Modalità filtro'; + @override String get modeBlacklist => 'Lista nera'; + @override String get modeWhitelist => 'Lista bianca'; + @override String get modeHintBlacklist => 'Sincronizza tutte le librerie tranne quelle selezionate sotto.'; + @override String get modeHintWhitelist => 'Sincronizza solo le librerie selezionate sotto.'; + @override String get libraries => 'Librerie'; + @override String get noLibraries => 'Nessuna libreria disponibile'; +} + /// The flat map containing all translations for locale . /// Only for edge cases! For simple maps, use the map function of this library. /// @@ -2453,6 +2475,18 @@ extension on TranslationsIt { 'trackers.oauthProxy.body' => 'Scansiona questo codice QR con il telefono oppure apri l\'URL sottostante su un dispositivo con browser.', 'trackers.oauthProxy.openToSignIn' => ({required Object service}) => 'Apri ${service} per accedere', 'trackers.oauthProxy.urlCopied' => 'URL copiato', + 'trackers.libraryFilter.title' => 'Filtro librerie', + 'trackers.libraryFilter.subtitleAllSyncing' => 'Sincronizzazione di tutte le librerie', + 'trackers.libraryFilter.subtitleNoneSyncing' => 'Nulla da sincronizzare', + 'trackers.libraryFilter.subtitleBlocked' => ({required Object count}) => '${count} bloccate', + 'trackers.libraryFilter.subtitleAllowed' => ({required Object count}) => '${count} consentite', + 'trackers.libraryFilter.mode' => 'Modalità filtro', + 'trackers.libraryFilter.modeBlacklist' => 'Lista nera', + 'trackers.libraryFilter.modeWhitelist' => 'Lista bianca', + 'trackers.libraryFilter.modeHintBlacklist' => 'Sincronizza tutte le librerie tranne quelle selezionate sotto.', + 'trackers.libraryFilter.modeHintWhitelist' => 'Sincronizza solo le librerie selezionate sotto.', + 'trackers.libraryFilter.libraries' => 'Librerie', + 'trackers.libraryFilter.noLibraries' => 'Nessuna libreria disponibile', _ => null, }; } diff --git a/lib/i18n/strings_ja.g.dart b/lib/i18n/strings_ja.g.dart index 00eec88d..a47ce87b 100644 --- a/lib/i18n/strings_ja.g.dart +++ b/lib/i18n/strings_ja.g.dart @@ -1299,6 +1299,7 @@ class _TranslationsTrackersJa implements TranslationsTrackersEn { @override late final _TranslationsTrackersServicesJa services = _TranslationsTrackersServicesJa._(_root); @override late final _TranslationsTrackersDeviceCodeJa deviceCode = _TranslationsTrackersDeviceCodeJa._(_root); @override late final _TranslationsTrackersOauthProxyJa oauthProxy = _TranslationsTrackersOauthProxyJa._(_root); + @override late final _TranslationsTrackersLibraryFilterJa libraryFilter = _TranslationsTrackersLibraryFilterJa._(_root); } // Path: hotkeys.actions @@ -1496,6 +1497,27 @@ class _TranslationsTrackersOauthProxyJa implements TranslationsTrackersOauthProx @override String get urlCopied => 'URLをコピーしました'; } +// Path: trackers.libraryFilter +class _TranslationsTrackersLibraryFilterJa implements TranslationsTrackersLibraryFilterEn { + _TranslationsTrackersLibraryFilterJa._(this._root); + + final TranslationsJa _root; // ignore: unused_field + + // Translations + @override String get title => 'ライブラリフィルター'; + @override String get subtitleAllSyncing => 'すべてのライブラリを同期中'; + @override String get subtitleNoneSyncing => '同期なし'; + @override String subtitleBlocked({required Object count}) => '${count} 件をブロック'; + @override String subtitleAllowed({required Object count}) => '${count} 件を許可'; + @override String get mode => 'フィルターモード'; + @override String get modeBlacklist => 'ブロックリスト'; + @override String get modeWhitelist => '許可リスト'; + @override String get modeHintBlacklist => '下でチェックしたライブラリ以外をすべて同期します。'; + @override String get modeHintWhitelist => '下でチェックしたライブラリのみ同期します。'; + @override String get libraries => 'ライブラリ'; + @override String get noLibraries => '利用できるライブラリがありません'; +} + /// The flat map containing all translations for locale . /// Only for edge cases! For simple maps, use the map function of this library. /// @@ -2453,6 +2475,18 @@ extension on TranslationsJa { 'trackers.oauthProxy.body' => 'このQRコードをスマートフォンで読み取るか、下のURLをブラウザで開いてください。', 'trackers.oauthProxy.openToSignIn' => ({required Object service}) => '${service} を開いてサインイン', 'trackers.oauthProxy.urlCopied' => 'URLをコピーしました', + 'trackers.libraryFilter.title' => 'ライブラリフィルター', + 'trackers.libraryFilter.subtitleAllSyncing' => 'すべてのライブラリを同期中', + 'trackers.libraryFilter.subtitleNoneSyncing' => '同期なし', + 'trackers.libraryFilter.subtitleBlocked' => ({required Object count}) => '${count} 件をブロック', + 'trackers.libraryFilter.subtitleAllowed' => ({required Object count}) => '${count} 件を許可', + 'trackers.libraryFilter.mode' => 'フィルターモード', + 'trackers.libraryFilter.modeBlacklist' => 'ブロックリスト', + 'trackers.libraryFilter.modeWhitelist' => '許可リスト', + 'trackers.libraryFilter.modeHintBlacklist' => '下でチェックしたライブラリ以外をすべて同期します。', + 'trackers.libraryFilter.modeHintWhitelist' => '下でチェックしたライブラリのみ同期します。', + 'trackers.libraryFilter.libraries' => 'ライブラリ', + 'trackers.libraryFilter.noLibraries' => '利用できるライブラリがありません', _ => null, }; } diff --git a/lib/i18n/strings_ko.g.dart b/lib/i18n/strings_ko.g.dart index 185ca27e..8432bb63 100644 --- a/lib/i18n/strings_ko.g.dart +++ b/lib/i18n/strings_ko.g.dart @@ -1299,6 +1299,7 @@ class _TranslationsTrackersKo implements TranslationsTrackersEn { @override late final _TranslationsTrackersServicesKo services = _TranslationsTrackersServicesKo._(_root); @override late final _TranslationsTrackersDeviceCodeKo deviceCode = _TranslationsTrackersDeviceCodeKo._(_root); @override late final _TranslationsTrackersOauthProxyKo oauthProxy = _TranslationsTrackersOauthProxyKo._(_root); + @override late final _TranslationsTrackersLibraryFilterKo libraryFilter = _TranslationsTrackersLibraryFilterKo._(_root); } // Path: hotkeys.actions @@ -1496,6 +1497,27 @@ class _TranslationsTrackersOauthProxyKo implements TranslationsTrackersOauthProx @override String get urlCopied => 'URL이 복사되었습니다'; } +// Path: trackers.libraryFilter +class _TranslationsTrackersLibraryFilterKo implements TranslationsTrackersLibraryFilterEn { + _TranslationsTrackersLibraryFilterKo._(this._root); + + final TranslationsKo _root; // ignore: unused_field + + // Translations + @override String get title => '라이브러리 필터'; + @override String get subtitleAllSyncing => '모든 라이브러리 동기화 중'; + @override String get subtitleNoneSyncing => '동기화 안 함'; + @override String subtitleBlocked({required Object count}) => '${count}개 차단됨'; + @override String subtitleAllowed({required Object count}) => '${count}개 허용됨'; + @override String get mode => '필터 모드'; + @override String get modeBlacklist => '차단 목록'; + @override String get modeWhitelist => '허용 목록'; + @override String get modeHintBlacklist => '아래에 선택한 라이브러리를 제외한 모든 라이브러리를 동기화합니다.'; + @override String get modeHintWhitelist => '아래에 선택한 라이브러리만 동기화합니다.'; + @override String get libraries => '라이브러리'; + @override String get noLibraries => '사용 가능한 라이브러리가 없습니다'; +} + /// The flat map containing all translations for locale . /// Only for edge cases! For simple maps, use the map function of this library. /// @@ -2453,6 +2475,18 @@ extension on TranslationsKo { 'trackers.oauthProxy.body' => '휴대전화로 이 QR 코드를 스캔하거나 아래 URL을 브라우저가 있는 기기에서 여세요.', 'trackers.oauthProxy.openToSignIn' => ({required Object service}) => '로그인하려면 ${service} 열기', 'trackers.oauthProxy.urlCopied' => 'URL이 복사되었습니다', + 'trackers.libraryFilter.title' => '라이브러리 필터', + 'trackers.libraryFilter.subtitleAllSyncing' => '모든 라이브러리 동기화 중', + 'trackers.libraryFilter.subtitleNoneSyncing' => '동기화 안 함', + 'trackers.libraryFilter.subtitleBlocked' => ({required Object count}) => '${count}개 차단됨', + 'trackers.libraryFilter.subtitleAllowed' => ({required Object count}) => '${count}개 허용됨', + 'trackers.libraryFilter.mode' => '필터 모드', + 'trackers.libraryFilter.modeBlacklist' => '차단 목록', + 'trackers.libraryFilter.modeWhitelist' => '허용 목록', + 'trackers.libraryFilter.modeHintBlacklist' => '아래에 선택한 라이브러리를 제외한 모든 라이브러리를 동기화합니다.', + 'trackers.libraryFilter.modeHintWhitelist' => '아래에 선택한 라이브러리만 동기화합니다.', + 'trackers.libraryFilter.libraries' => '라이브러리', + 'trackers.libraryFilter.noLibraries' => '사용 가능한 라이브러리가 없습니다', _ => null, }; } diff --git a/lib/i18n/strings_nb.g.dart b/lib/i18n/strings_nb.g.dart index 8d27ebdd..fe5d7d92 100644 --- a/lib/i18n/strings_nb.g.dart +++ b/lib/i18n/strings_nb.g.dart @@ -1299,6 +1299,7 @@ class _TranslationsTrackersNb implements TranslationsTrackersEn { @override late final _TranslationsTrackersServicesNb services = _TranslationsTrackersServicesNb._(_root); @override late final _TranslationsTrackersDeviceCodeNb deviceCode = _TranslationsTrackersDeviceCodeNb._(_root); @override late final _TranslationsTrackersOauthProxyNb oauthProxy = _TranslationsTrackersOauthProxyNb._(_root); + @override late final _TranslationsTrackersLibraryFilterNb libraryFilter = _TranslationsTrackersLibraryFilterNb._(_root); } // Path: hotkeys.actions @@ -1496,6 +1497,27 @@ class _TranslationsTrackersOauthProxyNb implements TranslationsTrackersOauthProx @override String get urlCopied => 'URL kopiert'; } +// Path: trackers.libraryFilter +class _TranslationsTrackersLibraryFilterNb implements TranslationsTrackersLibraryFilterEn { + _TranslationsTrackersLibraryFilterNb._(this._root); + + final TranslationsNb _root; // ignore: unused_field + + // Translations + @override String get title => 'Biblioteksfilter'; + @override String get subtitleAllSyncing => 'Synkroniserer alle biblioteker'; + @override String get subtitleNoneSyncing => 'Ingenting synkroniseres'; + @override String subtitleBlocked({required Object count}) => '${count} blokkert'; + @override String subtitleAllowed({required Object count}) => '${count} tillatt'; + @override String get mode => 'Filtermodus'; + @override String get modeBlacklist => 'Svarteliste'; + @override String get modeWhitelist => 'Hviteliste'; + @override String get modeHintBlacklist => 'Synkroniser alle biblioteker bortsett fra dem du markerer nedenfor.'; + @override String get modeHintWhitelist => 'Synkroniser kun bibliotekene du markerer nedenfor.'; + @override String get libraries => 'Biblioteker'; + @override String get noLibraries => 'Ingen biblioteker tilgjengelige'; +} + /// The flat map containing all translations for locale . /// Only for edge cases! For simple maps, use the map function of this library. /// @@ -2453,6 +2475,18 @@ extension on TranslationsNb { 'trackers.oauthProxy.body' => 'Skann denne QR-koden med telefonen din, eller åpne URL-en under på en enhet med nettleser.', 'trackers.oauthProxy.openToSignIn' => ({required Object service}) => 'Åpne ${service} for å logge inn', 'trackers.oauthProxy.urlCopied' => 'URL kopiert', + 'trackers.libraryFilter.title' => 'Biblioteksfilter', + 'trackers.libraryFilter.subtitleAllSyncing' => 'Synkroniserer alle biblioteker', + 'trackers.libraryFilter.subtitleNoneSyncing' => 'Ingenting synkroniseres', + 'trackers.libraryFilter.subtitleBlocked' => ({required Object count}) => '${count} blokkert', + 'trackers.libraryFilter.subtitleAllowed' => ({required Object count}) => '${count} tillatt', + 'trackers.libraryFilter.mode' => 'Filtermodus', + 'trackers.libraryFilter.modeBlacklist' => 'Svarteliste', + 'trackers.libraryFilter.modeWhitelist' => 'Hviteliste', + 'trackers.libraryFilter.modeHintBlacklist' => 'Synkroniser alle biblioteker bortsett fra dem du markerer nedenfor.', + 'trackers.libraryFilter.modeHintWhitelist' => 'Synkroniser kun bibliotekene du markerer nedenfor.', + 'trackers.libraryFilter.libraries' => 'Biblioteker', + 'trackers.libraryFilter.noLibraries' => 'Ingen biblioteker tilgjengelige', _ => null, }; } diff --git a/lib/i18n/strings_nl.g.dart b/lib/i18n/strings_nl.g.dart index f2ea401f..dda25320 100644 --- a/lib/i18n/strings_nl.g.dart +++ b/lib/i18n/strings_nl.g.dart @@ -1299,6 +1299,7 @@ class _TranslationsTrackersNl implements TranslationsTrackersEn { @override late final _TranslationsTrackersServicesNl services = _TranslationsTrackersServicesNl._(_root); @override late final _TranslationsTrackersDeviceCodeNl deviceCode = _TranslationsTrackersDeviceCodeNl._(_root); @override late final _TranslationsTrackersOauthProxyNl oauthProxy = _TranslationsTrackersOauthProxyNl._(_root); + @override late final _TranslationsTrackersLibraryFilterNl libraryFilter = _TranslationsTrackersLibraryFilterNl._(_root); } // Path: hotkeys.actions @@ -1496,6 +1497,27 @@ class _TranslationsTrackersOauthProxyNl implements TranslationsTrackersOauthProx @override String get urlCopied => 'URL gekopieerd'; } +// Path: trackers.libraryFilter +class _TranslationsTrackersLibraryFilterNl implements TranslationsTrackersLibraryFilterEn { + _TranslationsTrackersLibraryFilterNl._(this._root); + + final TranslationsNl _root; // ignore: unused_field + + // Translations + @override String get title => 'Bibliotheekfilter'; + @override String get subtitleAllSyncing => 'Alle bibliotheken synchroniseren'; + @override String get subtitleNoneSyncing => 'Niets wordt gesynchroniseerd'; + @override String subtitleBlocked({required Object count}) => '${count} geblokkeerd'; + @override String subtitleAllowed({required Object count}) => '${count} toegestaan'; + @override String get mode => 'Filtermodus'; + @override String get modeBlacklist => 'Zwarte lijst'; + @override String get modeWhitelist => 'Witte lijst'; + @override String get modeHintBlacklist => 'Synchroniseer alle bibliotheken behalve die hieronder aangevinkt zijn.'; + @override String get modeHintWhitelist => 'Synchroniseer alleen de hieronder aangevinkte bibliotheken.'; + @override String get libraries => 'Bibliotheken'; + @override String get noLibraries => 'Geen bibliotheken beschikbaar'; +} + /// The flat map containing all translations for locale . /// Only for edge cases! For simple maps, use the map function of this library. /// @@ -2453,6 +2475,18 @@ extension on TranslationsNl { 'trackers.oauthProxy.body' => 'Scan deze QR-code met je telefoon, of open onderstaande URL op een apparaat met browser.', 'trackers.oauthProxy.openToSignIn' => ({required Object service}) => '${service} openen om aan te melden', 'trackers.oauthProxy.urlCopied' => 'URL gekopieerd', + 'trackers.libraryFilter.title' => 'Bibliotheekfilter', + 'trackers.libraryFilter.subtitleAllSyncing' => 'Alle bibliotheken synchroniseren', + 'trackers.libraryFilter.subtitleNoneSyncing' => 'Niets wordt gesynchroniseerd', + 'trackers.libraryFilter.subtitleBlocked' => ({required Object count}) => '${count} geblokkeerd', + 'trackers.libraryFilter.subtitleAllowed' => ({required Object count}) => '${count} toegestaan', + 'trackers.libraryFilter.mode' => 'Filtermodus', + 'trackers.libraryFilter.modeBlacklist' => 'Zwarte lijst', + 'trackers.libraryFilter.modeWhitelist' => 'Witte lijst', + 'trackers.libraryFilter.modeHintBlacklist' => 'Synchroniseer alle bibliotheken behalve die hieronder aangevinkt zijn.', + 'trackers.libraryFilter.modeHintWhitelist' => 'Synchroniseer alleen de hieronder aangevinkte bibliotheken.', + 'trackers.libraryFilter.libraries' => 'Bibliotheken', + 'trackers.libraryFilter.noLibraries' => 'Geen bibliotheken beschikbaar', _ => null, }; } diff --git a/lib/i18n/strings_pl.g.dart b/lib/i18n/strings_pl.g.dart index bf1d8753..b98b0189 100644 --- a/lib/i18n/strings_pl.g.dart +++ b/lib/i18n/strings_pl.g.dart @@ -1299,6 +1299,7 @@ class _TranslationsTrackersPl implements TranslationsTrackersEn { @override late final _TranslationsTrackersServicesPl services = _TranslationsTrackersServicesPl._(_root); @override late final _TranslationsTrackersDeviceCodePl deviceCode = _TranslationsTrackersDeviceCodePl._(_root); @override late final _TranslationsTrackersOauthProxyPl oauthProxy = _TranslationsTrackersOauthProxyPl._(_root); + @override late final _TranslationsTrackersLibraryFilterPl libraryFilter = _TranslationsTrackersLibraryFilterPl._(_root); } // Path: hotkeys.actions @@ -1496,6 +1497,27 @@ class _TranslationsTrackersOauthProxyPl implements TranslationsTrackersOauthProx @override String get urlCopied => 'URL skopiowany'; } +// Path: trackers.libraryFilter +class _TranslationsTrackersLibraryFilterPl implements TranslationsTrackersLibraryFilterEn { + _TranslationsTrackersLibraryFilterPl._(this._root); + + final TranslationsPl _root; // ignore: unused_field + + // Translations + @override String get title => 'Filtr bibliotek'; + @override String get subtitleAllSyncing => 'Synchronizowanie wszystkich bibliotek'; + @override String get subtitleNoneSyncing => 'Nic nie synchronizuje'; + @override String subtitleBlocked({required Object count}) => '${count} zablokowanych'; + @override String subtitleAllowed({required Object count}) => '${count} dozwolonych'; + @override String get mode => 'Tryb filtra'; + @override String get modeBlacklist => 'Czarna lista'; + @override String get modeWhitelist => 'Biała lista'; + @override String get modeHintBlacklist => 'Synchronizuj wszystkie biblioteki oprócz zaznaczonych poniżej.'; + @override String get modeHintWhitelist => 'Synchronizuj tylko biblioteki zaznaczone poniżej.'; + @override String get libraries => 'Biblioteki'; + @override String get noLibraries => 'Brak dostępnych bibliotek'; +} + /// The flat map containing all translations for locale . /// Only for edge cases! For simple maps, use the map function of this library. /// @@ -2453,6 +2475,18 @@ extension on TranslationsPl { 'trackers.oauthProxy.body' => 'Zeskanuj ten kod QR telefonem lub otwórz poniższy adres URL na dowolnym urządzeniu z przeglądarką.', 'trackers.oauthProxy.openToSignIn' => ({required Object service}) => 'Otwórz ${service}, aby się zalogować', 'trackers.oauthProxy.urlCopied' => 'URL skopiowany', + 'trackers.libraryFilter.title' => 'Filtr bibliotek', + 'trackers.libraryFilter.subtitleAllSyncing' => 'Synchronizowanie wszystkich bibliotek', + 'trackers.libraryFilter.subtitleNoneSyncing' => 'Nic nie synchronizuje', + 'trackers.libraryFilter.subtitleBlocked' => ({required Object count}) => '${count} zablokowanych', + 'trackers.libraryFilter.subtitleAllowed' => ({required Object count}) => '${count} dozwolonych', + 'trackers.libraryFilter.mode' => 'Tryb filtra', + 'trackers.libraryFilter.modeBlacklist' => 'Czarna lista', + 'trackers.libraryFilter.modeWhitelist' => 'Biała lista', + 'trackers.libraryFilter.modeHintBlacklist' => 'Synchronizuj wszystkie biblioteki oprócz zaznaczonych poniżej.', + 'trackers.libraryFilter.modeHintWhitelist' => 'Synchronizuj tylko biblioteki zaznaczone poniżej.', + 'trackers.libraryFilter.libraries' => 'Biblioteki', + 'trackers.libraryFilter.noLibraries' => 'Brak dostępnych bibliotek', _ => null, }; } diff --git a/lib/i18n/strings_pt.g.dart b/lib/i18n/strings_pt.g.dart index 6b8d46a2..b21d0eab 100644 --- a/lib/i18n/strings_pt.g.dart +++ b/lib/i18n/strings_pt.g.dart @@ -1299,6 +1299,7 @@ class _TranslationsTrackersPt implements TranslationsTrackersEn { @override late final _TranslationsTrackersServicesPt services = _TranslationsTrackersServicesPt._(_root); @override late final _TranslationsTrackersDeviceCodePt deviceCode = _TranslationsTrackersDeviceCodePt._(_root); @override late final _TranslationsTrackersOauthProxyPt oauthProxy = _TranslationsTrackersOauthProxyPt._(_root); + @override late final _TranslationsTrackersLibraryFilterPt libraryFilter = _TranslationsTrackersLibraryFilterPt._(_root); } // Path: hotkeys.actions @@ -1496,6 +1497,27 @@ class _TranslationsTrackersOauthProxyPt implements TranslationsTrackersOauthProx @override String get urlCopied => 'URL copiado'; } +// Path: trackers.libraryFilter +class _TranslationsTrackersLibraryFilterPt implements TranslationsTrackersLibraryFilterEn { + _TranslationsTrackersLibraryFilterPt._(this._root); + + final TranslationsPt _root; // ignore: unused_field + + // Translations + @override String get title => 'Filtro de bibliotecas'; + @override String get subtitleAllSyncing => 'Sincronizando todas as bibliotecas'; + @override String get subtitleNoneSyncing => 'Nada a sincronizar'; + @override String subtitleBlocked({required Object count}) => '${count} bloqueadas'; + @override String subtitleAllowed({required Object count}) => '${count} permitidas'; + @override String get mode => 'Modo de filtro'; + @override String get modeBlacklist => 'Lista negra'; + @override String get modeWhitelist => 'Lista branca'; + @override String get modeHintBlacklist => 'Sincronizar todas as bibliotecas exceto as marcadas abaixo.'; + @override String get modeHintWhitelist => 'Sincronizar apenas as bibliotecas marcadas abaixo.'; + @override String get libraries => 'Bibliotecas'; + @override String get noLibraries => 'Nenhuma biblioteca disponível'; +} + /// The flat map containing all translations for locale . /// Only for edge cases! For simple maps, use the map function of this library. /// @@ -2453,6 +2475,18 @@ extension on TranslationsPt { 'trackers.oauthProxy.body' => 'Escaneie este código QR com o celular, ou abra o URL abaixo em qualquer dispositivo com navegador.', 'trackers.oauthProxy.openToSignIn' => ({required Object service}) => 'Abrir ${service} para entrar', 'trackers.oauthProxy.urlCopied' => 'URL copiado', + 'trackers.libraryFilter.title' => 'Filtro de bibliotecas', + 'trackers.libraryFilter.subtitleAllSyncing' => 'Sincronizando todas as bibliotecas', + 'trackers.libraryFilter.subtitleNoneSyncing' => 'Nada a sincronizar', + 'trackers.libraryFilter.subtitleBlocked' => ({required Object count}) => '${count} bloqueadas', + 'trackers.libraryFilter.subtitleAllowed' => ({required Object count}) => '${count} permitidas', + 'trackers.libraryFilter.mode' => 'Modo de filtro', + 'trackers.libraryFilter.modeBlacklist' => 'Lista negra', + 'trackers.libraryFilter.modeWhitelist' => 'Lista branca', + 'trackers.libraryFilter.modeHintBlacklist' => 'Sincronizar todas as bibliotecas exceto as marcadas abaixo.', + 'trackers.libraryFilter.modeHintWhitelist' => 'Sincronizar apenas as bibliotecas marcadas abaixo.', + 'trackers.libraryFilter.libraries' => 'Bibliotecas', + 'trackers.libraryFilter.noLibraries' => 'Nenhuma biblioteca disponível', _ => null, }; } diff --git a/lib/i18n/strings_ru.g.dart b/lib/i18n/strings_ru.g.dart index ed8241df..1a459175 100644 --- a/lib/i18n/strings_ru.g.dart +++ b/lib/i18n/strings_ru.g.dart @@ -1299,6 +1299,7 @@ class _TranslationsTrackersRu implements TranslationsTrackersEn { @override late final _TranslationsTrackersServicesRu services = _TranslationsTrackersServicesRu._(_root); @override late final _TranslationsTrackersDeviceCodeRu deviceCode = _TranslationsTrackersDeviceCodeRu._(_root); @override late final _TranslationsTrackersOauthProxyRu oauthProxy = _TranslationsTrackersOauthProxyRu._(_root); + @override late final _TranslationsTrackersLibraryFilterRu libraryFilter = _TranslationsTrackersLibraryFilterRu._(_root); } // Path: hotkeys.actions @@ -1496,6 +1497,27 @@ class _TranslationsTrackersOauthProxyRu implements TranslationsTrackersOauthProx @override String get urlCopied => 'URL скопирован'; } +// Path: trackers.libraryFilter +class _TranslationsTrackersLibraryFilterRu implements TranslationsTrackersLibraryFilterEn { + _TranslationsTrackersLibraryFilterRu._(this._root); + + final TranslationsRu _root; // ignore: unused_field + + // Translations + @override String get title => 'Фильтр библиотек'; + @override String get subtitleAllSyncing => 'Синхронизация всех библиотек'; + @override String get subtitleNoneSyncing => 'Ничего не синхронизируется'; + @override String subtitleBlocked({required Object count}) => '${count} заблокировано'; + @override String subtitleAllowed({required Object count}) => '${count} разрешено'; + @override String get mode => 'Режим фильтра'; + @override String get modeBlacklist => 'Чёрный список'; + @override String get modeWhitelist => 'Белый список'; + @override String get modeHintBlacklist => 'Синхронизировать все библиотеки, кроме отмеченных ниже.'; + @override String get modeHintWhitelist => 'Синхронизировать только библиотеки, отмеченные ниже.'; + @override String get libraries => 'Библиотеки'; + @override String get noLibraries => 'Библиотеки недоступны'; +} + /// The flat map containing all translations for locale . /// Only for edge cases! For simple maps, use the map function of this library. /// @@ -2453,6 +2475,18 @@ extension on TranslationsRu { 'trackers.oauthProxy.body' => 'Отсканируйте этот QR-код телефоном или откройте ссылку ниже на любом устройстве с браузером.', 'trackers.oauthProxy.openToSignIn' => ({required Object service}) => 'Открыть ${service} для входа', 'trackers.oauthProxy.urlCopied' => 'URL скопирован', + 'trackers.libraryFilter.title' => 'Фильтр библиотек', + 'trackers.libraryFilter.subtitleAllSyncing' => 'Синхронизация всех библиотек', + 'trackers.libraryFilter.subtitleNoneSyncing' => 'Ничего не синхронизируется', + 'trackers.libraryFilter.subtitleBlocked' => ({required Object count}) => '${count} заблокировано', + 'trackers.libraryFilter.subtitleAllowed' => ({required Object count}) => '${count} разрешено', + 'trackers.libraryFilter.mode' => 'Режим фильтра', + 'trackers.libraryFilter.modeBlacklist' => 'Чёрный список', + 'trackers.libraryFilter.modeWhitelist' => 'Белый список', + 'trackers.libraryFilter.modeHintBlacklist' => 'Синхронизировать все библиотеки, кроме отмеченных ниже.', + 'trackers.libraryFilter.modeHintWhitelist' => 'Синхронизировать только библиотеки, отмеченные ниже.', + 'trackers.libraryFilter.libraries' => 'Библиотеки', + 'trackers.libraryFilter.noLibraries' => 'Библиотеки недоступны', _ => null, }; } diff --git a/lib/i18n/strings_sv.g.dart b/lib/i18n/strings_sv.g.dart index 772f2567..d1d437f6 100644 --- a/lib/i18n/strings_sv.g.dart +++ b/lib/i18n/strings_sv.g.dart @@ -1299,6 +1299,7 @@ class _TranslationsTrackersSv implements TranslationsTrackersEn { @override late final _TranslationsTrackersServicesSv services = _TranslationsTrackersServicesSv._(_root); @override late final _TranslationsTrackersDeviceCodeSv deviceCode = _TranslationsTrackersDeviceCodeSv._(_root); @override late final _TranslationsTrackersOauthProxySv oauthProxy = _TranslationsTrackersOauthProxySv._(_root); + @override late final _TranslationsTrackersLibraryFilterSv libraryFilter = _TranslationsTrackersLibraryFilterSv._(_root); } // Path: hotkeys.actions @@ -1496,6 +1497,27 @@ class _TranslationsTrackersOauthProxySv implements TranslationsTrackersOauthProx @override String get urlCopied => 'URL kopierad'; } +// Path: trackers.libraryFilter +class _TranslationsTrackersLibraryFilterSv implements TranslationsTrackersLibraryFilterEn { + _TranslationsTrackersLibraryFilterSv._(this._root); + + final TranslationsSv _root; // ignore: unused_field + + // Translations + @override String get title => 'Biblioteksfilter'; + @override String get subtitleAllSyncing => 'Synkroniserar alla bibliotek'; + @override String get subtitleNoneSyncing => 'Ingenting synkroniseras'; + @override String subtitleBlocked({required Object count}) => '${count} blockerade'; + @override String subtitleAllowed({required Object count}) => '${count} tillåtna'; + @override String get mode => 'Filterläge'; + @override String get modeBlacklist => 'Svartlista'; + @override String get modeWhitelist => 'Vitlista'; + @override String get modeHintBlacklist => 'Synkronisera alla bibliotek utom de som markerats nedan.'; + @override String get modeHintWhitelist => 'Synkronisera endast de bibliotek som markerats nedan.'; + @override String get libraries => 'Bibliotek'; + @override String get noLibraries => 'Inga bibliotek tillgängliga'; +} + /// The flat map containing all translations for locale . /// Only for edge cases! For simple maps, use the map function of this library. /// @@ -2453,6 +2475,18 @@ extension on TranslationsSv { 'trackers.oauthProxy.body' => 'Skanna den här QR-koden med din telefon, eller öppna URL:en nedan på en enhet med webbläsare.', 'trackers.oauthProxy.openToSignIn' => ({required Object service}) => 'Öppna ${service} för att logga in', 'trackers.oauthProxy.urlCopied' => 'URL kopierad', + 'trackers.libraryFilter.title' => 'Biblioteksfilter', + 'trackers.libraryFilter.subtitleAllSyncing' => 'Synkroniserar alla bibliotek', + 'trackers.libraryFilter.subtitleNoneSyncing' => 'Ingenting synkroniseras', + 'trackers.libraryFilter.subtitleBlocked' => ({required Object count}) => '${count} blockerade', + 'trackers.libraryFilter.subtitleAllowed' => ({required Object count}) => '${count} tillåtna', + 'trackers.libraryFilter.mode' => 'Filterläge', + 'trackers.libraryFilter.modeBlacklist' => 'Svartlista', + 'trackers.libraryFilter.modeWhitelist' => 'Vitlista', + 'trackers.libraryFilter.modeHintBlacklist' => 'Synkronisera alla bibliotek utom de som markerats nedan.', + 'trackers.libraryFilter.modeHintWhitelist' => 'Synkronisera endast de bibliotek som markerats nedan.', + 'trackers.libraryFilter.libraries' => 'Bibliotek', + 'trackers.libraryFilter.noLibraries' => 'Inga bibliotek tillgängliga', _ => null, }; } diff --git a/lib/i18n/strings_zh.g.dart b/lib/i18n/strings_zh.g.dart index 8255ed4d..d51b4cc8 100644 --- a/lib/i18n/strings_zh.g.dart +++ b/lib/i18n/strings_zh.g.dart @@ -1299,6 +1299,7 @@ class _TranslationsTrackersZh implements TranslationsTrackersEn { @override late final _TranslationsTrackersServicesZh services = _TranslationsTrackersServicesZh._(_root); @override late final _TranslationsTrackersDeviceCodeZh deviceCode = _TranslationsTrackersDeviceCodeZh._(_root); @override late final _TranslationsTrackersOauthProxyZh oauthProxy = _TranslationsTrackersOauthProxyZh._(_root); + @override late final _TranslationsTrackersLibraryFilterZh libraryFilter = _TranslationsTrackersLibraryFilterZh._(_root); } // Path: hotkeys.actions @@ -1496,6 +1497,27 @@ class _TranslationsTrackersOauthProxyZh implements TranslationsTrackersOauthProx @override String get urlCopied => 'URL 已复制'; } +// Path: trackers.libraryFilter +class _TranslationsTrackersLibraryFilterZh implements TranslationsTrackersLibraryFilterEn { + _TranslationsTrackersLibraryFilterZh._(this._root); + + final TranslationsZh _root; // ignore: unused_field + + // Translations + @override String get title => '媒体库筛选'; + @override String get subtitleAllSyncing => '同步所有媒体库'; + @override String get subtitleNoneSyncing => '不同步任何内容'; + @override String subtitleBlocked({required Object count}) => '已屏蔽 ${count} 个'; + @override String subtitleAllowed({required Object count}) => '已允许 ${count} 个'; + @override String get mode => '筛选模式'; + @override String get modeBlacklist => '黑名单'; + @override String get modeWhitelist => '白名单'; + @override String get modeHintBlacklist => '同步下方未勾选的所有媒体库。'; + @override String get modeHintWhitelist => '仅同步下方勾选的媒体库。'; + @override String get libraries => '媒体库'; + @override String get noLibraries => '没有可用的媒体库'; +} + /// The flat map containing all translations for locale . /// Only for edge cases! For simple maps, use the map function of this library. /// @@ -2453,6 +2475,18 @@ extension on TranslationsZh { 'trackers.oauthProxy.body' => '用手机扫描此二维码,或在任何带浏览器的设备上打开下方 URL。', 'trackers.oauthProxy.openToSignIn' => ({required Object service}) => '打开 ${service} 以登录', 'trackers.oauthProxy.urlCopied' => 'URL 已复制', + 'trackers.libraryFilter.title' => '媒体库筛选', + 'trackers.libraryFilter.subtitleAllSyncing' => '同步所有媒体库', + 'trackers.libraryFilter.subtitleNoneSyncing' => '不同步任何内容', + 'trackers.libraryFilter.subtitleBlocked' => ({required Object count}) => '已屏蔽 ${count} 个', + 'trackers.libraryFilter.subtitleAllowed' => ({required Object count}) => '已允许 ${count} 个', + 'trackers.libraryFilter.mode' => '筛选模式', + 'trackers.libraryFilter.modeBlacklist' => '黑名单', + 'trackers.libraryFilter.modeWhitelist' => '白名单', + 'trackers.libraryFilter.modeHintBlacklist' => '同步下方未勾选的所有媒体库。', + 'trackers.libraryFilter.modeHintWhitelist' => '仅同步下方勾选的媒体库。', + 'trackers.libraryFilter.libraries' => '媒体库', + 'trackers.libraryFilter.noLibraries' => '没有可用的媒体库', _ => null, }; } diff --git a/lib/i18n/sv.i18n.json b/lib/i18n/sv.i18n.json index 410e8519..770b5e6c 100644 --- a/lib/i18n/sv.i18n.json +++ b/lib/i18n/sv.i18n.json @@ -1046,6 +1046,20 @@ "body": "Skanna den här QR-koden med din telefon, eller öppna URL:en nedan på en enhet med webbläsare.", "openToSignIn": "Öppna ${service} för att logga in", "urlCopied": "URL kopierad" + }, + "libraryFilter": { + "title": "Biblioteksfilter", + "subtitleAllSyncing": "Synkroniserar alla bibliotek", + "subtitleNoneSyncing": "Ingenting synkroniseras", + "subtitleBlocked": "${count} blockerade", + "subtitleAllowed": "${count} tillåtna", + "mode": "Filterläge", + "modeBlacklist": "Svartlista", + "modeWhitelist": "Vitlista", + "modeHintBlacklist": "Synkronisera alla bibliotek utom de som markerats nedan.", + "modeHintWhitelist": "Synkronisera endast de bibliotek som markerats nedan.", + "libraries": "Bibliotek", + "noLibraries": "Inga bibliotek tillgängliga" } } } diff --git a/lib/i18n/zh.i18n.json b/lib/i18n/zh.i18n.json index ea236f93..54e46d12 100644 --- a/lib/i18n/zh.i18n.json +++ b/lib/i18n/zh.i18n.json @@ -1046,6 +1046,20 @@ "body": "用手机扫描此二维码,或在任何带浏览器的设备上打开下方 URL。", "openToSignIn": "打开 ${service} 以登录", "urlCopied": "URL 已复制" + }, + "libraryFilter": { + "title": "媒体库筛选", + "subtitleAllSyncing": "同步所有媒体库", + "subtitleNoneSyncing": "不同步任何内容", + "subtitleBlocked": "已屏蔽 ${count} 个", + "subtitleAllowed": "已允许 ${count} 个", + "mode": "筛选模式", + "modeBlacklist": "黑名单", + "modeWhitelist": "白名单", + "modeHintBlacklist": "同步下方未勾选的所有媒体库。", + "modeHintWhitelist": "仅同步下方勾选的媒体库。", + "libraries": "媒体库", + "noLibraries": "没有可用的媒体库" } } } diff --git a/lib/models/plex_metadata.dart b/lib/models/plex_metadata.dart index 97ab3a4e..db1b33d5 100644 --- a/lib/models/plex_metadata.dart +++ b/lib/models/plex_metadata.dart @@ -154,6 +154,12 @@ class PlexMetadata with MultiServerFields { /// Global unique identifier across all servers (serverId:ratingKey) String get globalKey => serverId != null ? buildGlobalKey(serverId!, ratingKey) : ratingKey; + /// Global unique identifier of this item's library section, matching + /// [PlexLibrary.globalKey]. Null when either [serverId] or [librarySectionID] + /// is missing. + String? get librarySectionGlobalKey => + serverId != null && librarySectionID != null ? buildGlobalKey(serverId!, librarySectionID!.toString()) : null; + /// Parent rating keys for hierarchical invalidation. /// For an episode: [seasonRatingKey, showRatingKey] /// For a season: [showRatingKey] diff --git a/lib/models/trackers/tracker_context.dart b/lib/models/trackers/tracker_context.dart index 74cc348a..ded5522e 100644 --- a/lib/models/trackers/tracker_context.dart +++ b/lib/models/trackers/tracker_context.dart @@ -20,11 +20,16 @@ class TrackerContext { /// sent to any tracker. final String ratingKey; + /// Library globalKey the item belongs to, or null when the metadata didn't + /// carry library info. + final String? libraryGlobalKey; + const TrackerContext._({ required this.external, required this.anime, required this.isMovie, required this.ratingKey, + required this.libraryGlobalKey, this.season, this.episodeNumber, }); @@ -33,14 +38,22 @@ class TrackerContext { required PlexExternalIds external, required AnimeIds? anime, required String ratingKey, + required String? libraryGlobalKey, }) { - return TrackerContext._(external: external, anime: anime, isMovie: true, ratingKey: ratingKey); + return TrackerContext._( + external: external, + anime: anime, + isMovie: true, + ratingKey: ratingKey, + libraryGlobalKey: libraryGlobalKey, + ); } factory TrackerContext.episode({ required PlexExternalIds external, required AnimeIds? anime, required String ratingKey, + required String? libraryGlobalKey, required int season, required int episodeNumber, }) { @@ -49,6 +62,7 @@ class TrackerContext { anime: anime, isMovie: false, ratingKey: ratingKey, + libraryGlobalKey: libraryGlobalKey, season: season, episodeNumber: episodeNumber, ); diff --git a/lib/providers/trackers_provider.dart b/lib/providers/trackers_provider.dart index 8ebc6f4b..a064a204 100644 --- a/lib/providers/trackers_provider.dart +++ b/lib/providers/trackers_provider.dart @@ -20,13 +20,10 @@ import '../services/trackers/simkl/simkl_client.dart'; import '../services/trackers/simkl/simkl_session.dart'; import '../services/trackers/simkl/simkl_tracker.dart'; import '../services/trackers/tracker_account_store.dart'; +import '../services/trackers/tracker_constants.dart'; import '../services/trackers/tracker_coordinator.dart'; import '../utils/app_logger.dart'; -/// Identifier used in the settings UI to disambiguate disconnect/connect -/// actions without importing the per-service session classes into widgets. -enum TrackerService { mal, anilist, simkl } - /// Owns the active MAL / AniList / Simkl sessions for the currently-selected /// Plex profile. Single rebind seam: [onActiveProfileChanged] loads all three /// sessions from their stores and pushes them to their trackers. diff --git a/lib/screens/settings/tracker_library_filter_screen.dart b/lib/screens/settings/tracker_library_filter_screen.dart new file mode 100644 index 00000000..e43e041b --- /dev/null +++ b/lib/screens/settings/tracker_library_filter_screen.dart @@ -0,0 +1,174 @@ +import 'package:flutter/material.dart'; +import 'package:material_symbols_icons/symbols.dart'; +import 'package:provider/provider.dart'; + +import '../../i18n/strings.g.dart'; +import '../../models/plex_library.dart'; +import '../../providers/libraries_provider.dart'; +import '../../services/settings_service.dart'; +import '../../services/trackers/tracker_constants.dart'; +import '../../widgets/app_icon.dart'; +import '../../widgets/focusable_list_tile.dart'; +import '../../widgets/focused_scroll_scaffold.dart'; +import '../../widgets/settings_section.dart'; + +/// Per-provider library whitelist/blacklist screen. Toggling a switch +/// adds/removes the library from the filter set; "selected" means "in the +/// filter list" in both modes. +class TrackerLibraryFilterScreen extends StatefulWidget { + final TrackerService service; + + const TrackerLibraryFilterScreen({super.key, required this.service}); + + /// Human-readable summary of the current filter state for [service], used as + /// the subtitle on the parent settings screen's "Library filter" tile. + static String subtitleFor(SettingsService settings, TrackerService service) { + final mode = settings.getTrackerLibraryFilterMode(service); + final ids = settings.getTrackerLibraryFilterIds(service); + if (ids.isEmpty) { + return mode == TrackerLibraryFilterMode.blacklist + ? t.trackers.libraryFilter.subtitleAllSyncing + : t.trackers.libraryFilter.subtitleNoneSyncing; + } + final count = ids.length.toString(); + return mode == TrackerLibraryFilterMode.blacklist + ? t.trackers.libraryFilter.subtitleBlocked(count: count) + : t.trackers.libraryFilter.subtitleAllowed(count: count); + } + + @override + State createState() => _TrackerLibraryFilterScreenState(); +} + +class _TrackerLibraryFilterScreenState extends State { + late SettingsService _settings; + TrackerLibraryFilterMode _mode = TrackerLibraryFilterMode.blacklist; + final Set _selectedIds = {}; + bool _loaded = false; + + @override + void initState() { + super.initState(); + _load(); + } + + Future _load() async { + final s = await SettingsService.getInstance(); + if (!mounted) return; + setState(() { + _settings = s; + _mode = s.getTrackerLibraryFilterMode(widget.service); + _selectedIds + ..clear() + ..addAll(s.getTrackerLibraryFilterIds(widget.service)); + _loaded = true; + }); + } + + Future _setMode(TrackerLibraryFilterMode mode) async { + if (mode == _mode) return; + setState(() => _mode = mode); + await _settings.setTrackerLibraryFilterMode(widget.service, mode); + } + + Future _toggleLibrary(String globalKey, bool value) async { + setState(() { + if (value) { + _selectedIds.add(globalKey); + } else { + _selectedIds.remove(globalKey); + } + }); + await _settings.setTrackerLibraryFilterIds(widget.service, _selectedIds); + } + + @override + Widget build(BuildContext context) { + final title = Text(t.trackers.libraryFilter.title); + if (!_loaded) { + return FocusedScrollScaffold( + title: title, + slivers: const [SliverFillRemaining(child: Center(child: CircularProgressIndicator()))], + ); + } + + final theme = Theme.of(context); + + return Consumer( + builder: (context, provider, _) { + final libraries = provider.libraries; + final grouped = _groupByServer(libraries); + final showServerHeaders = grouped.length > 1; + + final children = [ + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), + child: Text( + _mode == TrackerLibraryFilterMode.blacklist + ? t.trackers.libraryFilter.modeHintBlacklist + : t.trackers.libraryFilter.modeHintWhitelist, + style: theme.textTheme.bodyMedium?.copyWith(color: theme.colorScheme.onSurfaceVariant), + ), + ), + SegmentedSetting( + icon: Symbols.filter_list_rounded, + title: t.trackers.libraryFilter.mode, + segments: [ + ButtonSegment( + value: TrackerLibraryFilterMode.blacklist, + label: Text(t.trackers.libraryFilter.modeBlacklist), + ), + ButtonSegment( + value: TrackerLibraryFilterMode.whitelist, + label: Text(t.trackers.libraryFilter.modeWhitelist), + ), + ], + selected: _mode, + onChanged: _setMode, + ), + SettingsSectionHeader(t.trackers.libraryFilter.libraries), + ]; + + if (libraries.isEmpty) { + children.add(ListTile(title: Text(t.trackers.libraryFilter.noLibraries))); + } else { + for (final entry in grouped.entries) { + if (showServerHeaders) { + children.add(SettingsSectionHeader(entry.value.first.serverName ?? entry.key)); + } + for (final lib in entry.value) { + children.add( + FocusableSwitchListTile( + key: ValueKey('tracker-library-filter-${lib.globalKey}'), + secondary: const AppIcon(Symbols.folder_rounded, fill: 1), + title: Text(lib.title), + value: _selectedIds.contains(lib.globalKey), + onChanged: (v) => _toggleLibrary(lib.globalKey, v), + ), + ); + } + } + } + + children.add(const SizedBox(height: 24)); + + return FocusedScrollScaffold( + title: title, + slivers: [ + SliverList(delegate: SliverChildListDelegate(children)), + ], + ); + }, + ); + } + + static Map> _groupByServer(List libs) { + final out = >{}; + for (final lib in libs) { + final serverId = lib.serverId; + if (serverId == null) continue; + out.putIfAbsent(serverId, () => []).add(lib); + } + return out; + } +} diff --git a/lib/screens/settings/tracker_settings_screen.dart b/lib/screens/settings/tracker_settings_screen.dart index d090b0d1..46e35b63 100644 --- a/lib/screens/settings/tracker_settings_screen.dart +++ b/lib/screens/settings/tracker_settings_screen.dart @@ -13,6 +13,7 @@ import '../../services/trackers/anilist/anilist_tracker.dart'; import '../../services/trackers/mal/mal_tracker.dart'; import '../../services/trackers/oauth_proxy_client.dart'; import '../../services/trackers/simkl/simkl_tracker.dart'; +import '../../services/trackers/tracker_constants.dart'; import '../../services/settings_service.dart'; import '../../utils/app_logger.dart'; import '../../utils/dialogs.dart'; @@ -22,6 +23,7 @@ import '../../widgets/device_code_dialog.dart'; import '../../widgets/focused_scroll_scaffold.dart'; import '../../widgets/oauth_proxy_dialog.dart'; import '../../widgets/settings_section.dart'; +import 'tracker_library_filter_screen.dart'; /// Shared dialog-driven connect flow used by all three trackers. Handles the /// guard, auto-launch-on-pointer, dialog lifecycle, and failure snackbar — @@ -114,6 +116,7 @@ Future startSimklConnection(BuildContext context) { /// Per-service wiring for [TrackerSettingsScreen]. Keeps tracker-specific /// method names out of the shared screen body. class TrackerConfig { + final TrackerService service; final String displayName; final bool Function(TrackersProvider) isConnected; final String? Function(TrackersProvider) username; @@ -122,6 +125,7 @@ class TrackerConfig { final Future Function(TrackersProvider) disconnect; const TrackerConfig({ + required this.service, required this.displayName, required this.isConnected, required this.username, @@ -131,6 +135,7 @@ class TrackerConfig { }); static TrackerConfig mal() => TrackerConfig( + service: TrackerService.mal, displayName: t.trackers.services.mal, isConnected: (a) => a.isMalConnected, username: (a) => a.malUsername, @@ -143,6 +148,7 @@ class TrackerConfig { ); static TrackerConfig anilist() => TrackerConfig( + service: TrackerService.anilist, displayName: t.trackers.services.anilist, isConnected: (a) => a.isAnilistConnected, username: (a) => a.anilistUsername, @@ -155,6 +161,7 @@ class TrackerConfig { ); static TrackerConfig simkl() => TrackerConfig( + service: TrackerService.simkl, displayName: t.trackers.services.simkl, isConnected: (a) => a.isSimklConnected, username: (a) => a.simklUsername, @@ -258,6 +265,20 @@ class _TrackerSettingsScreenState extends State { await widget.config.setScrobbleEnabled(_settings!, value); }, ), + ListTile( + leading: const AppIcon(Symbols.filter_list_rounded, fill: 1), + title: Text(t.trackers.libraryFilter.title), + subtitle: Text(TrackerLibraryFilterScreen.subtitleFor(_settings!, widget.config.service)), + trailing: const AppIcon(Symbols.chevron_right_rounded, fill: 1), + onTap: () async { + await Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => TrackerLibraryFilterScreen(service: widget.config.service), + ), + ); + if (mounted) setState(() {}); + }, + ), const Divider(height: 32), ListTile( leading: AppIcon(Symbols.link_off_rounded, fill: 1, color: Theme.of(context).colorScheme.error), diff --git a/lib/screens/settings/trakt_settings_screen.dart b/lib/screens/settings/trakt_settings_screen.dart index 6341b87c..4d231b95 100644 --- a/lib/screens/settings/trakt_settings_screen.dart +++ b/lib/screens/settings/trakt_settings_screen.dart @@ -9,6 +9,7 @@ import '../../focus/input_mode_tracker.dart'; import '../../i18n/strings.g.dart'; import '../../providers/trakt_account_provider.dart'; import '../../services/settings_service.dart'; +import '../../services/trackers/tracker_constants.dart'; import '../../services/trakt/trakt_scrobble_service.dart'; import '../../services/trakt/trakt_sync_service.dart'; import '../../utils/app_logger.dart'; @@ -18,6 +19,7 @@ import '../../widgets/app_icon.dart'; import '../../widgets/device_code_dialog.dart'; import '../../widgets/focused_scroll_scaffold.dart'; import '../../widgets/settings_section.dart'; +import 'tracker_library_filter_screen.dart'; /// Start the Trakt device-code OAuth flow from anywhere in the app. /// @@ -174,6 +176,20 @@ class _TraktSettingsScreenState extends State { await TraktSyncService.instance.setEnabled(value); }, ), + ListTile( + leading: const AppIcon(Symbols.filter_list_rounded, fill: 1), + title: Text(t.trackers.libraryFilter.title), + subtitle: Text(TrackerLibraryFilterScreen.subtitleFor(_settings!, TrackerService.trakt)), + trailing: const AppIcon(Symbols.chevron_right_rounded, fill: 1), + onTap: () async { + await Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => const TrackerLibraryFilterScreen(service: TrackerService.trakt), + ), + ); + if (mounted) setState(() {}); + }, + ), const Divider(height: 32), ListTile( leading: AppIcon(Symbols.link_off_rounded, fill: 1, color: Theme.of(context).colorScheme.error), diff --git a/lib/services/settings_service.dart b/lib/services/settings_service.dart index 0292ffd1..2906ccd0 100644 --- a/lib/services/settings_service.dart +++ b/lib/services/settings_service.dart @@ -10,6 +10,7 @@ import '../models/mpv_config_models.dart'; import '../models/external_player_models.dart'; import 'base_shared_preferences_service.dart'; import '../utils/platform_detector.dart'; +import 'trackers/tracker_constants.dart'; enum ThemeMode { system, light, dark, oled } @@ -98,6 +99,8 @@ class SettingsService extends BaseSharedPreferencesService { static const String _keyEnableMalScrobble = 'enable_mal_scrobble'; static const String _keyEnableAnilistScrobble = 'enable_anilist_scrobble'; static const String _keyEnableSimklScrobble = 'enable_simkl_scrobble'; + static const String _prefixTrackerLibraryFilterMode = 'tracker_library_filter_mode_'; + static const String _prefixTrackerLibraryFilterIds = 'tracker_library_filter_ids_'; static const String _keyEnableCompanionRemoteServer = 'enable_companion_remote_server'; static const String _keyAutoPip = 'auto_pip'; static const String _keyMatchContentFrameRate = 'match_content_frame_rate'; @@ -1194,6 +1197,34 @@ class SettingsService extends BaseSharedPreferencesService { return prefs.getBool(_keyEnableSimklScrobble) ?? true; } + // Per-tracker library filter. Default blacklist+empty = sync every library. + TrackerLibraryFilterMode getTrackerLibraryFilterMode(TrackerService service) => _getEnumValue( + '$_prefixTrackerLibraryFilterMode${service.name}', + TrackerLibraryFilterMode.values, + TrackerLibraryFilterMode.blacklist, + ); + + Future setTrackerLibraryFilterMode(TrackerService service, TrackerLibraryFilterMode mode) async { + await prefs.setString('$_prefixTrackerLibraryFilterMode${service.name}', mode.name); + } + + Set getTrackerLibraryFilterIds(TrackerService service) { + final ids = prefs.getStringList('$_prefixTrackerLibraryFilterIds${service.name}'); + return ids?.toSet() ?? {}; + } + + Future setTrackerLibraryFilterIds(TrackerService service, Set ids) async { + await prefs.setStringList('$_prefixTrackerLibraryFilterIds${service.name}', ids.toList()); + } + + /// Whether a scrobble/sync for [libraryGlobalKey] should be sent to [service]. + /// Null keys bypass the filter so we err on the side of syncing. + bool isLibraryAllowedForTracker(TrackerService service, String? libraryGlobalKey) { + if (libraryGlobalKey == null) return true; + final inList = getTrackerLibraryFilterIds(service).contains(libraryGlobalKey); + return getTrackerLibraryFilterMode(service) == TrackerLibraryFilterMode.blacklist ? !inList : inList; + } + // Companion Remote Server Future setEnableCompanionRemoteServer(bool enabled) async { await prefs.setBool(_keyEnableCompanionRemoteServer, enabled); @@ -1536,6 +1567,10 @@ class SettingsService extends BaseSharedPreferencesService { prefs.remove(_keyEnableMalScrobble), prefs.remove(_keyEnableAnilistScrobble), prefs.remove(_keyEnableSimklScrobble), + ...TrackerService.values.expand((s) => [ + prefs.remove('$_prefixTrackerLibraryFilterMode${s.name}'), + prefs.remove('$_prefixTrackerLibraryFilterIds${s.name}'), + ]), prefs.remove(_keyAutoPip), prefs.remove(_keyMatchContentFrameRate), prefs.remove(_keyTunneledPlayback), diff --git a/lib/services/trackers/anilist/anilist_tracker.dart b/lib/services/trackers/anilist/anilist_tracker.dart index 61313470..a3d515d9 100644 --- a/lib/services/trackers/anilist/anilist_tracker.dart +++ b/lib/services/trackers/anilist/anilist_tracker.dart @@ -2,6 +2,7 @@ import '../../../models/trackers/tracker_context.dart'; import '../../../utils/app_logger.dart'; import '../../settings_service.dart'; import '../tracker.dart'; +import '../tracker_constants.dart'; import 'anilist_client.dart'; import 'anilist_session.dart'; @@ -17,6 +18,9 @@ class AnilistTracker extends TrackerBase { @override String get name => 'anilist'; + @override + TrackerService get service => TrackerService.anilist; + @override bool get needsFribb => true; diff --git a/lib/services/trackers/mal/mal_tracker.dart b/lib/services/trackers/mal/mal_tracker.dart index b8cf39c5..6acbee1c 100644 --- a/lib/services/trackers/mal/mal_tracker.dart +++ b/lib/services/trackers/mal/mal_tracker.dart @@ -2,6 +2,7 @@ import '../../../models/trackers/tracker_context.dart'; import '../../../utils/app_logger.dart'; import '../../settings_service.dart'; import '../tracker.dart'; +import '../tracker_constants.dart'; import 'mal_client.dart'; import 'mal_session.dart'; @@ -22,6 +23,9 @@ class MalTracker extends TrackerBase { @override String get name => 'mal'; + @override + TrackerService get service => TrackerService.mal; + @override bool get needsFribb => true; diff --git a/lib/services/trackers/simkl/simkl_tracker.dart b/lib/services/trackers/simkl/simkl_tracker.dart index 275cd714..7aa77645 100644 --- a/lib/services/trackers/simkl/simkl_tracker.dart +++ b/lib/services/trackers/simkl/simkl_tracker.dart @@ -2,6 +2,7 @@ import '../../../models/trackers/tracker_context.dart'; import '../../../utils/app_logger.dart'; import '../../settings_service.dart'; import '../tracker.dart'; +import '../tracker_constants.dart'; import 'simkl_client.dart'; import 'simkl_session.dart'; @@ -20,6 +21,9 @@ class SimklTracker extends TrackerBase { @override String get name => 'simkl'; + @override + TrackerService get service => TrackerService.simkl; + @override bool get needsFribb => false; diff --git a/lib/services/trackers/tracker.dart b/lib/services/trackers/tracker.dart index 9f8b510d..ad544983 100644 --- a/lib/services/trackers/tracker.dart +++ b/lib/services/trackers/tracker.dart @@ -1,5 +1,6 @@ import '../../models/trackers/tracker_context.dart'; import '../settings_service.dart'; +import 'tracker_constants.dart'; /// Abstract tracker contract: the coordinator calls [markWatched] once per /// playback when progress crosses the watched threshold. Enabled/auth gating @@ -7,6 +8,10 @@ import '../settings_service.dart'; abstract class Tracker { String get name; + /// Stable identifier used to persist per-service settings (library filter, + /// scrobble enabled, etc.). + TrackerService get service; + bool get canScrobble; /// True if this tracker's IDs only come from the Fribb anime mapping @@ -18,6 +23,12 @@ abstract class Tracker { Future initialize(); Future setEnabled(bool enabled); + /// Whether an item in the given library should be scrobbled. Applies the + /// per-tracker whitelist/blacklist — callers pass the Plex library + /// `serverId:sectionId` globalKey (null when unknown, in which case the + /// filter is bypassed so we err on the side of syncing). + bool shouldScrobbleForLibrary(String? libraryGlobalKey); + Future markWatched(TrackerContext ctx); } @@ -45,4 +56,8 @@ abstract class TrackerBase implements Tracker { Future setEnabled(bool enabled) async { _isEnabled = enabled; } + + @override + bool shouldScrobbleForLibrary(String? libraryGlobalKey) => + SettingsService.instanceOrNull?.isLibraryAllowedForTracker(service, libraryGlobalKey) ?? true; } diff --git a/lib/services/trackers/tracker_constants.dart b/lib/services/trackers/tracker_constants.dart index 4c39bcc9..d6b6e821 100644 --- a/lib/services/trackers/tracker_constants.dart +++ b/lib/services/trackers/tracker_constants.dart @@ -6,3 +6,11 @@ class TrackerConstants { /// pushed to each tracker. static const double watchedThresholdPercent = 80.0; } + +/// Identifier used across the app to disambiguate per-service operations. +/// The enum's `.name` forms part of the persistence key — do not rename +/// without a migration. +enum TrackerService { mal, anilist, simkl, trakt } + +/// Blacklist+[] syncs every library (the default); whitelist+[] syncs nothing. +enum TrackerLibraryFilterMode { blacklist, whitelist } diff --git a/lib/services/trackers/tracker_coordinator.dart b/lib/services/trackers/tracker_coordinator.dart index 487239b0..861eb121 100644 --- a/lib/services/trackers/tracker_coordinator.dart +++ b/lib/services/trackers/tracker_coordinator.dart @@ -113,7 +113,9 @@ class TrackerCoordinator { } Future _dispatchMarkWatched(TrackerContext ctx) async { - final active = _trackers.where((t) => t.canScrobble); + final active = _trackers.where( + (t) => t.canScrobble && t.shouldScrobbleForLibrary(ctx.libraryGlobalKey), + ); await Future.wait(active.map((t) async { try { await t.markWatched(ctx); @@ -127,6 +129,8 @@ class TrackerCoordinator { final resolver = _resolver; if (resolver == null) return null; + final libraryKey = metadata.librarySectionGlobalKey; + if (metadata.mediaType == PlexMediaType.movie) { final ids = await resolver.resolveForMovie(metadata.ratingKey); if (ids == null) return null; @@ -134,6 +138,7 @@ class TrackerCoordinator { external: ids.external, anime: ids.anime, ratingKey: metadata.ratingKey, + libraryGlobalKey: libraryKey, ); } @@ -147,6 +152,7 @@ class TrackerCoordinator { external: ids.external, anime: ids.anime, ratingKey: metadata.ratingKey, + libraryGlobalKey: libraryKey, season: season, episodeNumber: number, ); diff --git a/lib/services/trakt/trakt_scrobble_service.dart b/lib/services/trakt/trakt_scrobble_service.dart index 199821e4..13092218 100644 --- a/lib/services/trakt/trakt_scrobble_service.dart +++ b/lib/services/trakt/trakt_scrobble_service.dart @@ -6,6 +6,7 @@ import '../../models/trakt/trakt_scrobble_request.dart'; import '../../utils/app_logger.dart'; import '../plex_client.dart'; import '../settings_service.dart'; +import '../trackers/tracker_constants.dart'; import '../trackers/tracker_id_resolver.dart'; import 'trakt_client.dart'; import 'trakt_constants.dart'; @@ -91,6 +92,13 @@ class TraktScrobbleService { final type = metadata.mediaType; if (type != PlexMediaType.movie && type != PlexMediaType.episode) return; + final settings = SettingsService.instanceOrNull; + if (settings != null && + !settings.isLibraryAllowedForTracker(TrackerService.trakt, metadata.librarySectionGlobalKey)) { + appLogger.d('Trakt: library filtered out for ${metadata.ratingKey}'); + return; + } + // Seed with the resume offset so the first real position update doesn't // look like a seek when resuming mid-item. _currentPosition = metadata.viewOffset != null ? Duration(milliseconds: metadata.viewOffset!) : Duration.zero; diff --git a/lib/services/trakt/trakt_sync_service.dart b/lib/services/trakt/trakt_sync_service.dart index 6a8fcb62..29e12ad9 100644 --- a/lib/services/trakt/trakt_sync_service.dart +++ b/lib/services/trakt/trakt_sync_service.dart @@ -7,6 +7,7 @@ import '../../utils/app_logger.dart'; import '../../utils/watch_state_notifier.dart'; import '../multi_server_manager.dart'; import '../settings_service.dart'; +import '../trackers/tracker_constants.dart'; import '../trackers/tracker_id_resolver.dart'; import 'trakt_client.dart'; import 'trakt_constants.dart'; @@ -109,6 +110,13 @@ class TraktSyncService { final kind = TraktMediaKind.tryFromPlexType(event.mediaType); if (kind == null) return; + final settings = SettingsService.instanceOrNull; + if (settings != null && + !settings.isLibraryAllowedForTracker(TrackerService.trakt, event.librarySectionGlobalKey)) { + appLogger.d('Trakt sync: library filtered out for ${event.ratingKey}'); + return; + } + final op = event.changeType == WatchStateChangeType.watched ? TraktSyncOp.add : TraktSyncOp.remove; await _push( op: op, diff --git a/lib/utils/watch_state_notifier.dart b/lib/utils/watch_state_notifier.dart index 9f6b5ee7..a10d94ef 100644 --- a/lib/utils/watch_state_notifier.dart +++ b/lib/utils/watch_state_notifier.dart @@ -40,6 +40,10 @@ class WatchStateEvent with HierarchicalEventMixin { /// Whether item is now considered watched (>90% progress or marked) final bool? isNowWatched; + /// Library section this item belongs to — used for per-tracker library + /// filtering. Null when emitted without full metadata. + final int? librarySectionID; + WatchStateEvent({ required this.ratingKey, required this.serverId, @@ -48,8 +52,14 @@ class WatchStateEvent with HierarchicalEventMixin { required this.mediaType, this.viewOffset, this.isNowWatched, + this.librarySectionID, }) : globalKey = buildGlobalKey(serverId, ratingKey); + /// `serverId:librarySectionID`, matching [PlexLibrary.globalKey]. Null when + /// the library section is unknown. + String? get librarySectionGlobalKey => + librarySectionID != null ? buildGlobalKey(serverId, librarySectionID!.toString()) : null; + @override String toString() => 'WatchStateEvent($changeType, $globalKey, parents: $parentChain)'; } @@ -88,6 +98,7 @@ class WatchStateNotifier extends BaseNotifier { parentChain: metadata.parentChain, mediaType: metadata.type ?? '', isNowWatched: isNowWatched, + librarySectionID: metadata.librarySectionID, ), ); } @@ -112,6 +123,7 @@ class WatchStateNotifier extends BaseNotifier { mediaType: metadata.type ?? '', viewOffset: viewOffset, isNowWatched: isNowWatched, + librarySectionID: metadata.librarySectionID, ), ); }