feat: add hide spoilers setting for unwatched episodes
This commit is contained in:
@@ -117,6 +117,8 @@
|
||||
"alwaysKeepSidebarOpenDescription": "Seitenleiste bleibt erweitert und Inhaltsbereich passt sich an",
|
||||
"showUnwatchedCount": "Anzahl nicht gesehener Folgen anzeigen",
|
||||
"showUnwatchedCountDescription": "Zeigt die Anzahl nicht gesehener Episoden bei Serien und Staffeln an",
|
||||
"hideSpoilers": "Spoiler für nicht gesehene Episoden verbergen",
|
||||
"hideSpoilersDescription": "Vorschaubilder unscharf machen und Beschreibungen für noch nicht gesehene Episoden ausblenden",
|
||||
"playerBackend": "Player-Backend",
|
||||
"exoPlayer": "ExoPlayer (Empfohlen)",
|
||||
"exoPlayerDescription": "Android-nativer Player mit besserer Hardware-Unterstützung",
|
||||
|
||||
@@ -117,6 +117,8 @@
|
||||
"alwaysKeepSidebarOpenDescription": "Sidebar stays expanded and content area adjusts to fit",
|
||||
"showUnwatchedCount": "Show Unwatched Count",
|
||||
"showUnwatchedCountDescription": "Display unwatched episode count on shows and seasons",
|
||||
"hideSpoilers": "Hide Spoilers for Unwatched Episodes",
|
||||
"hideSpoilersDescription": "Blur thumbnails and hide descriptions for episodes you haven't watched yet",
|
||||
"playerBackend": "Player Backend",
|
||||
"exoPlayer": "ExoPlayer (Recommended)",
|
||||
"exoPlayerDescription": "Android native player with better hardware support",
|
||||
|
||||
@@ -117,6 +117,8 @@
|
||||
"alwaysKeepSidebarOpenDescription": "La barra lateral permanece expandida y el área de contenido se ajusta para adaptarse",
|
||||
"showUnwatchedCount": "Mostrar conteo de no vistos",
|
||||
"showUnwatchedCountDescription": "Mostrar el conteo de episodios no vistos en series y temporadas",
|
||||
"hideSpoilers": "Ocultar spoilers de episodios no vistos",
|
||||
"hideSpoilersDescription": "Difuminar miniaturas y ocultar descripciones de episodios que aún no has visto",
|
||||
"playerBackend": "Reproductor",
|
||||
"exoPlayer": "ExoPlayer (Recomendado)",
|
||||
"exoPlayerDescription": "Reproductor nativo de Android con mejor soporte de hardware",
|
||||
|
||||
@@ -117,6 +117,8 @@
|
||||
"alwaysKeepSidebarOpenDescription": "La barre latérale reste étendue et la zone de contenu s'adapte",
|
||||
"showUnwatchedCount": "Afficher le nombre non visionné",
|
||||
"showUnwatchedCountDescription": "Afficher le nombre d'épisodes non visionnés pour les séries et saisons",
|
||||
"hideSpoilers": "Masquer les spoilers des épisodes non vus",
|
||||
"hideSpoilersDescription": "Flouter les miniatures et masquer les descriptions des épisodes que vous n'avez pas encore regardés",
|
||||
"playerBackend": "Moteur de lecture",
|
||||
"exoPlayer": "ExoPlayer (Recommandé)",
|
||||
"exoPlayerDescription": "Lecteur natif Android avec meilleur support matériel",
|
||||
|
||||
@@ -117,6 +117,8 @@
|
||||
"alwaysKeepSidebarOpenDescription": "La barra laterale rimane espansa e l'area del contenuto si adatta",
|
||||
"showUnwatchedCount": "Mostra conteggio non visti",
|
||||
"showUnwatchedCountDescription": "Mostra il numero di episodi non visti per serie e stagioni",
|
||||
"hideSpoilers": "Nascondi spoiler per episodi non visti",
|
||||
"hideSpoilersDescription": "Sfoca le miniature e nascondi le descrizioni degli episodi che non hai ancora guardato",
|
||||
"playerBackend": "Motore di riproduzione",
|
||||
"exoPlayer": "ExoPlayer (Consigliato)",
|
||||
"exoPlayerDescription": "Lettore nativo Android con migliore supporto hardware",
|
||||
|
||||
@@ -117,6 +117,8 @@
|
||||
"alwaysKeepSidebarOpenDescription": "사이드바가 확장된 상태로 유지되고 콘텐츠 영역이 맞춰집니다",
|
||||
"showUnwatchedCount": "미시청 수 표시",
|
||||
"showUnwatchedCountDescription": "시리즈 및 시즌에 미시청 에피소드 수 표시",
|
||||
"hideSpoilers": "미시청 에피소드 스포일러 숨기기",
|
||||
"hideSpoilersDescription": "아직 시청하지 않은 에피소드의 썸네일을 흐리게 하고 설명을 숨깁니다",
|
||||
"playerBackend": "플레이어 백엔드",
|
||||
"exoPlayer": "ExoPlayer (권장)",
|
||||
"exoPlayerDescription": "더 나은 하드웨어 지원을 제공하는 Android 네이티브 플레이어",
|
||||
|
||||
@@ -117,6 +117,8 @@
|
||||
"alwaysKeepSidebarOpenDescription": "Zijbalk blijft uitgevouwen en inhoudsgebied past zich aan",
|
||||
"showUnwatchedCount": "Aantal ongekeken tonen",
|
||||
"showUnwatchedCountDescription": "Toon aantal ongekeken afleveringen bij series en seizoenen",
|
||||
"hideSpoilers": "Spoilers voor ongekeken afleveringen verbergen",
|
||||
"hideSpoilersDescription": "Miniaturen vervagen en beschrijvingen verbergen voor afleveringen die je nog niet hebt gezien",
|
||||
"playerBackend": "Speler backend",
|
||||
"exoPlayer": "ExoPlayer (Aanbevolen)",
|
||||
"exoPlayerDescription": "Android-native speler met betere hardware-ondersteuning",
|
||||
|
||||
@@ -236,6 +236,8 @@ class _TranslationsSettingsDe implements TranslationsSettingsEn {
|
||||
@override String get alwaysKeepSidebarOpenDescription => 'Seitenleiste bleibt erweitert und Inhaltsbereich passt sich an';
|
||||
@override String get showUnwatchedCount => 'Anzahl nicht gesehener Folgen anzeigen';
|
||||
@override String get showUnwatchedCountDescription => 'Zeigt die Anzahl nicht gesehener Episoden bei Serien und Staffeln an';
|
||||
@override String get hideSpoilers => 'Spoiler für nicht gesehene Episoden verbergen';
|
||||
@override String get hideSpoilersDescription => 'Vorschaubilder unscharf machen und Beschreibungen für noch nicht gesehene Episoden ausblenden';
|
||||
@override String get playerBackend => 'Player-Backend';
|
||||
@override String get exoPlayer => 'ExoPlayer (Empfohlen)';
|
||||
@override String get exoPlayerDescription => 'Android-nativer Player mit besserer Hardware-Unterstützung';
|
||||
@@ -1394,6 +1396,8 @@ extension on TranslationsDe {
|
||||
'settings.alwaysKeepSidebarOpenDescription' => 'Seitenleiste bleibt erweitert und Inhaltsbereich passt sich an',
|
||||
'settings.showUnwatchedCount' => 'Anzahl nicht gesehener Folgen anzeigen',
|
||||
'settings.showUnwatchedCountDescription' => 'Zeigt die Anzahl nicht gesehener Episoden bei Serien und Staffeln an',
|
||||
'settings.hideSpoilers' => 'Spoiler für nicht gesehene Episoden verbergen',
|
||||
'settings.hideSpoilersDescription' => 'Vorschaubilder unscharf machen und Beschreibungen für noch nicht gesehene Episoden ausblenden',
|
||||
'settings.playerBackend' => 'Player-Backend',
|
||||
'settings.exoPlayer' => 'ExoPlayer (Empfohlen)',
|
||||
'settings.exoPlayerDescription' => 'Android-nativer Player mit besserer Hardware-Unterstützung',
|
||||
|
||||
@@ -454,6 +454,12 @@ class TranslationsSettingsEn {
|
||||
/// en: 'Display unwatched episode count on shows and seasons'
|
||||
String get showUnwatchedCountDescription => 'Display unwatched episode count on shows and seasons';
|
||||
|
||||
/// en: 'Hide Spoilers for Unwatched Episodes'
|
||||
String get hideSpoilers => 'Hide Spoilers for Unwatched Episodes';
|
||||
|
||||
/// en: 'Blur thumbnails and hide descriptions for episodes you haven\'t watched yet'
|
||||
String get hideSpoilersDescription => 'Blur thumbnails and hide descriptions for episodes you haven\'t watched yet';
|
||||
|
||||
/// en: 'Player Backend'
|
||||
String get playerBackend => 'Player Backend';
|
||||
|
||||
@@ -2982,6 +2988,8 @@ extension on Translations {
|
||||
'settings.alwaysKeepSidebarOpenDescription' => 'Sidebar stays expanded and content area adjusts to fit',
|
||||
'settings.showUnwatchedCount' => 'Show Unwatched Count',
|
||||
'settings.showUnwatchedCountDescription' => 'Display unwatched episode count on shows and seasons',
|
||||
'settings.hideSpoilers' => 'Hide Spoilers for Unwatched Episodes',
|
||||
'settings.hideSpoilersDescription' => 'Blur thumbnails and hide descriptions for episodes you haven\'t watched yet',
|
||||
'settings.playerBackend' => 'Player Backend',
|
||||
'settings.exoPlayer' => 'ExoPlayer (Recommended)',
|
||||
'settings.exoPlayerDescription' => 'Android native player with better hardware support',
|
||||
|
||||
@@ -236,6 +236,8 @@ class _TranslationsSettingsEs implements TranslationsSettingsEn {
|
||||
@override String get alwaysKeepSidebarOpenDescription => 'La barra lateral permanece expandida y el área de contenido se ajusta para adaptarse';
|
||||
@override String get showUnwatchedCount => 'Mostrar conteo de no vistos';
|
||||
@override String get showUnwatchedCountDescription => 'Mostrar el conteo de episodios no vistos en series y temporadas';
|
||||
@override String get hideSpoilers => 'Ocultar spoilers de episodios no vistos';
|
||||
@override String get hideSpoilersDescription => 'Difuminar miniaturas y ocultar descripciones de episodios que aún no has visto';
|
||||
@override String get playerBackend => 'Reproductor';
|
||||
@override String get exoPlayer => 'ExoPlayer (Recomendado)';
|
||||
@override String get exoPlayerDescription => 'Reproductor nativo de Android con mejor soporte de hardware';
|
||||
@@ -1394,6 +1396,8 @@ extension on TranslationsEs {
|
||||
'settings.alwaysKeepSidebarOpenDescription' => 'La barra lateral permanece expandida y el área de contenido se ajusta para adaptarse',
|
||||
'settings.showUnwatchedCount' => 'Mostrar conteo de no vistos',
|
||||
'settings.showUnwatchedCountDescription' => 'Mostrar el conteo de episodios no vistos en series y temporadas',
|
||||
'settings.hideSpoilers' => 'Ocultar spoilers de episodios no vistos',
|
||||
'settings.hideSpoilersDescription' => 'Difuminar miniaturas y ocultar descripciones de episodios que aún no has visto',
|
||||
'settings.playerBackend' => 'Reproductor',
|
||||
'settings.exoPlayer' => 'ExoPlayer (Recomendado)',
|
||||
'settings.exoPlayerDescription' => 'Reproductor nativo de Android con mejor soporte de hardware',
|
||||
|
||||
@@ -236,6 +236,8 @@ class _TranslationsSettingsFr implements TranslationsSettingsEn {
|
||||
@override String get alwaysKeepSidebarOpenDescription => 'La barre latérale reste étendue et la zone de contenu s\'adapte';
|
||||
@override String get showUnwatchedCount => 'Afficher le nombre non visionné';
|
||||
@override String get showUnwatchedCountDescription => 'Afficher le nombre d\'épisodes non visionnés pour les séries et saisons';
|
||||
@override String get hideSpoilers => 'Masquer les spoilers des épisodes non vus';
|
||||
@override String get hideSpoilersDescription => 'Flouter les miniatures et masquer les descriptions des épisodes que vous n\'avez pas encore regardés';
|
||||
@override String get playerBackend => 'Moteur de lecture';
|
||||
@override String get exoPlayer => 'ExoPlayer (Recommandé)';
|
||||
@override String get exoPlayerDescription => 'Lecteur natif Android avec meilleur support matériel';
|
||||
@@ -1394,6 +1396,8 @@ extension on TranslationsFr {
|
||||
'settings.alwaysKeepSidebarOpenDescription' => 'La barre latérale reste étendue et la zone de contenu s\'adapte',
|
||||
'settings.showUnwatchedCount' => 'Afficher le nombre non visionné',
|
||||
'settings.showUnwatchedCountDescription' => 'Afficher le nombre d\'épisodes non visionnés pour les séries et saisons',
|
||||
'settings.hideSpoilers' => 'Masquer les spoilers des épisodes non vus',
|
||||
'settings.hideSpoilersDescription' => 'Flouter les miniatures et masquer les descriptions des épisodes que vous n\'avez pas encore regardés',
|
||||
'settings.playerBackend' => 'Moteur de lecture',
|
||||
'settings.exoPlayer' => 'ExoPlayer (Recommandé)',
|
||||
'settings.exoPlayerDescription' => 'Lecteur natif Android avec meilleur support matériel',
|
||||
|
||||
@@ -236,6 +236,8 @@ class _TranslationsSettingsIt implements TranslationsSettingsEn {
|
||||
@override String get alwaysKeepSidebarOpenDescription => 'La barra laterale rimane espansa e l\'area del contenuto si adatta';
|
||||
@override String get showUnwatchedCount => 'Mostra conteggio non visti';
|
||||
@override String get showUnwatchedCountDescription => 'Mostra il numero di episodi non visti per serie e stagioni';
|
||||
@override String get hideSpoilers => 'Nascondi spoiler per episodi non visti';
|
||||
@override String get hideSpoilersDescription => 'Sfoca le miniature e nascondi le descrizioni degli episodi che non hai ancora guardato';
|
||||
@override String get playerBackend => 'Motore di riproduzione';
|
||||
@override String get exoPlayer => 'ExoPlayer (Consigliato)';
|
||||
@override String get exoPlayerDescription => 'Lettore nativo Android con migliore supporto hardware';
|
||||
@@ -1394,6 +1396,8 @@ extension on TranslationsIt {
|
||||
'settings.alwaysKeepSidebarOpenDescription' => 'La barra laterale rimane espansa e l\'area del contenuto si adatta',
|
||||
'settings.showUnwatchedCount' => 'Mostra conteggio non visti',
|
||||
'settings.showUnwatchedCountDescription' => 'Mostra il numero di episodi non visti per serie e stagioni',
|
||||
'settings.hideSpoilers' => 'Nascondi spoiler per episodi non visti',
|
||||
'settings.hideSpoilersDescription' => 'Sfoca le miniature e nascondi le descrizioni degli episodi che non hai ancora guardato',
|
||||
'settings.playerBackend' => 'Motore di riproduzione',
|
||||
'settings.exoPlayer' => 'ExoPlayer (Consigliato)',
|
||||
'settings.exoPlayerDescription' => 'Lettore nativo Android con migliore supporto hardware',
|
||||
|
||||
@@ -236,6 +236,8 @@ class _TranslationsSettingsKo implements TranslationsSettingsEn {
|
||||
@override String get alwaysKeepSidebarOpenDescription => '사이드바가 확장된 상태로 유지되고 콘텐츠 영역이 맞춰집니다';
|
||||
@override String get showUnwatchedCount => '미시청 수 표시';
|
||||
@override String get showUnwatchedCountDescription => '시리즈 및 시즌에 미시청 에피소드 수 표시';
|
||||
@override String get hideSpoilers => '미시청 에피소드 스포일러 숨기기';
|
||||
@override String get hideSpoilersDescription => '아직 시청하지 않은 에피소드의 썸네일을 흐리게 하고 설명을 숨깁니다';
|
||||
@override String get playerBackend => '플레이어 백엔드';
|
||||
@override String get exoPlayer => 'ExoPlayer (권장)';
|
||||
@override String get exoPlayerDescription => '더 나은 하드웨어 지원을 제공하는 Android 네이티브 플레이어';
|
||||
@@ -1394,6 +1396,8 @@ extension on TranslationsKo {
|
||||
'settings.alwaysKeepSidebarOpenDescription' => '사이드바가 확장된 상태로 유지되고 콘텐츠 영역이 맞춰집니다',
|
||||
'settings.showUnwatchedCount' => '미시청 수 표시',
|
||||
'settings.showUnwatchedCountDescription' => '시리즈 및 시즌에 미시청 에피소드 수 표시',
|
||||
'settings.hideSpoilers' => '미시청 에피소드 스포일러 숨기기',
|
||||
'settings.hideSpoilersDescription' => '아직 시청하지 않은 에피소드의 썸네일을 흐리게 하고 설명을 숨깁니다',
|
||||
'settings.playerBackend' => '플레이어 백엔드',
|
||||
'settings.exoPlayer' => 'ExoPlayer (권장)',
|
||||
'settings.exoPlayerDescription' => '더 나은 하드웨어 지원을 제공하는 Android 네이티브 플레이어',
|
||||
|
||||
@@ -236,6 +236,8 @@ class _TranslationsSettingsNl implements TranslationsSettingsEn {
|
||||
@override String get alwaysKeepSidebarOpenDescription => 'Zijbalk blijft uitgevouwen en inhoudsgebied past zich aan';
|
||||
@override String get showUnwatchedCount => 'Aantal ongekeken tonen';
|
||||
@override String get showUnwatchedCountDescription => 'Toon aantal ongekeken afleveringen bij series en seizoenen';
|
||||
@override String get hideSpoilers => 'Spoilers voor ongekeken afleveringen verbergen';
|
||||
@override String get hideSpoilersDescription => 'Miniaturen vervagen en beschrijvingen verbergen voor afleveringen die je nog niet hebt gezien';
|
||||
@override String get playerBackend => 'Speler backend';
|
||||
@override String get exoPlayer => 'ExoPlayer (Aanbevolen)';
|
||||
@override String get exoPlayerDescription => 'Android-native speler met betere hardware-ondersteuning';
|
||||
@@ -1394,6 +1396,8 @@ extension on TranslationsNl {
|
||||
'settings.alwaysKeepSidebarOpenDescription' => 'Zijbalk blijft uitgevouwen en inhoudsgebied past zich aan',
|
||||
'settings.showUnwatchedCount' => 'Aantal ongekeken tonen',
|
||||
'settings.showUnwatchedCountDescription' => 'Toon aantal ongekeken afleveringen bij series en seizoenen',
|
||||
'settings.hideSpoilers' => 'Spoilers voor ongekeken afleveringen verbergen',
|
||||
'settings.hideSpoilersDescription' => 'Miniaturen vervagen en beschrijvingen verbergen voor afleveringen die je nog niet hebt gezien',
|
||||
'settings.playerBackend' => 'Speler backend',
|
||||
'settings.exoPlayer' => 'ExoPlayer (Aanbevolen)',
|
||||
'settings.exoPlayerDescription' => 'Android-native speler met betere hardware-ondersteuning',
|
||||
|
||||
@@ -236,6 +236,8 @@ class _TranslationsSettingsSv implements TranslationsSettingsEn {
|
||||
@override String get alwaysKeepSidebarOpenDescription => 'Sidofältet förblir expanderat och innehållsytan anpassas';
|
||||
@override String get showUnwatchedCount => 'Visa antal osedda';
|
||||
@override String get showUnwatchedCountDescription => 'Visa antal osedda avsnitt för serier och säsonger';
|
||||
@override String get hideSpoilers => 'Dölj spoilers för osedda avsnitt';
|
||||
@override String get hideSpoilersDescription => 'Gör miniatyrer suddiga och dölj beskrivningar för avsnitt du inte har sett ännu';
|
||||
@override String get playerBackend => 'Spelarmotor';
|
||||
@override String get exoPlayer => 'ExoPlayer (Rekommenderad)';
|
||||
@override String get exoPlayerDescription => 'Android-nativ spelare med bättre hårdvarustöd';
|
||||
@@ -1394,6 +1396,8 @@ extension on TranslationsSv {
|
||||
'settings.alwaysKeepSidebarOpenDescription' => 'Sidofältet förblir expanderat och innehållsytan anpassas',
|
||||
'settings.showUnwatchedCount' => 'Visa antal osedda',
|
||||
'settings.showUnwatchedCountDescription' => 'Visa antal osedda avsnitt för serier och säsonger',
|
||||
'settings.hideSpoilers' => 'Dölj spoilers för osedda avsnitt',
|
||||
'settings.hideSpoilersDescription' => 'Gör miniatyrer suddiga och dölj beskrivningar för avsnitt du inte har sett ännu',
|
||||
'settings.playerBackend' => 'Spelarmotor',
|
||||
'settings.exoPlayer' => 'ExoPlayer (Rekommenderad)',
|
||||
'settings.exoPlayerDescription' => 'Android-nativ spelare med bättre hårdvarustöd',
|
||||
|
||||
@@ -236,6 +236,8 @@ class _TranslationsSettingsZh implements TranslationsSettingsEn {
|
||||
@override String get alwaysKeepSidebarOpenDescription => '侧边栏保持展开状态,内容区域自动调整';
|
||||
@override String get showUnwatchedCount => '显示未观看数量';
|
||||
@override String get showUnwatchedCountDescription => '在剧集和季上显示未观看的集数';
|
||||
@override String get hideSpoilers => '隐藏未看剧集的剧透内容';
|
||||
@override String get hideSpoilersDescription => '模糊未观看剧集的缩略图并隐藏其描述';
|
||||
@override String get playerBackend => '播放器引擎';
|
||||
@override String get exoPlayer => 'ExoPlayer(推荐)';
|
||||
@override String get exoPlayerDescription => 'Android 原生播放器,硬件支持更好';
|
||||
@@ -1394,6 +1396,8 @@ extension on TranslationsZh {
|
||||
'settings.alwaysKeepSidebarOpenDescription' => '侧边栏保持展开状态,内容区域自动调整',
|
||||
'settings.showUnwatchedCount' => '显示未观看数量',
|
||||
'settings.showUnwatchedCountDescription' => '在剧集和季上显示未观看的集数',
|
||||
'settings.hideSpoilers' => '隐藏未看剧集的剧透内容',
|
||||
'settings.hideSpoilersDescription' => '模糊未观看剧集的缩略图并隐藏其描述',
|
||||
'settings.playerBackend' => '播放器引擎',
|
||||
'settings.exoPlayer' => 'ExoPlayer(推荐)',
|
||||
'settings.exoPlayerDescription' => 'Android 原生播放器,硬件支持更好',
|
||||
|
||||
@@ -117,6 +117,8 @@
|
||||
"alwaysKeepSidebarOpenDescription": "Sidofältet förblir expanderat och innehållsytan anpassas",
|
||||
"showUnwatchedCount": "Visa antal osedda",
|
||||
"showUnwatchedCountDescription": "Visa antal osedda avsnitt för serier och säsonger",
|
||||
"hideSpoilers": "Dölj spoilers för osedda avsnitt",
|
||||
"hideSpoilersDescription": "Gör miniatyrer suddiga och dölj beskrivningar för avsnitt du inte har sett ännu",
|
||||
"playerBackend": "Spelarmotor",
|
||||
"exoPlayer": "ExoPlayer (Rekommenderad)",
|
||||
"exoPlayerDescription": "Android-nativ spelare med bättre hårdvarustöd",
|
||||
|
||||
@@ -117,6 +117,8 @@
|
||||
"alwaysKeepSidebarOpenDescription": "侧边栏保持展开状态,内容区域自动调整",
|
||||
"showUnwatchedCount": "显示未观看数量",
|
||||
"showUnwatchedCountDescription": "在剧集和季上显示未观看的集数",
|
||||
"hideSpoilers": "隐藏未看剧集的剧透内容",
|
||||
"hideSpoilersDescription": "模糊未观看剧集的缩略图并隐藏其描述",
|
||||
"playerBackend": "播放器引擎",
|
||||
"exoPlayer": "ExoPlayer(推荐)",
|
||||
"exoPlayerDescription": "Android 原生播放器,硬件支持更好",
|
||||
|
||||
@@ -12,6 +12,7 @@ class SettingsProvider extends ChangeNotifier {
|
||||
bool _showServerNameOnHubs = false;
|
||||
bool _alwaysKeepSidebarOpen = false;
|
||||
bool _showUnwatchedCount = true;
|
||||
bool _hideSpoilers = false;
|
||||
bool _isInitialized = false;
|
||||
Future<void>? _initFuture;
|
||||
|
||||
@@ -36,6 +37,7 @@ class SettingsProvider extends ChangeNotifier {
|
||||
_showServerNameOnHubs = _settingsService!.getShowServerNameOnHubs();
|
||||
_alwaysKeepSidebarOpen = _settingsService!.getAlwaysKeepSidebarOpen();
|
||||
_showUnwatchedCount = _settingsService!.getShowUnwatchedCount();
|
||||
_hideSpoilers = _settingsService!.getHideSpoilers();
|
||||
_isInitialized = true;
|
||||
notifyListeners();
|
||||
}
|
||||
@@ -59,6 +61,8 @@ class SettingsProvider extends ChangeNotifier {
|
||||
|
||||
bool get showUnwatchedCount => _showUnwatchedCount;
|
||||
|
||||
bool get hideSpoilers => _hideSpoilers;
|
||||
|
||||
/// Helper to update a setting: ensures init, deduplicates, persists, notifies.
|
||||
Future<void> _updateSetting<T>({
|
||||
required T current,
|
||||
@@ -122,6 +126,12 @@ class SettingsProvider extends ChangeNotifier {
|
||||
persist: _settingsService!.setShowUnwatchedCount,
|
||||
);
|
||||
|
||||
Future<void> setHideSpoilers(bool value) => _updateSetting(
|
||||
current: _hideSpoilers, value: value,
|
||||
setLocal: (v) => _hideSpoilers = v,
|
||||
persist: _settingsService!.setHideSpoilers,
|
||||
);
|
||||
|
||||
String get libraryDensityDisplayName {
|
||||
switch (_libraryDensity) {
|
||||
case LibraryDensity.compact:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'dart:io';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
@@ -14,6 +15,8 @@ import '../focus/dpad_navigator.dart';
|
||||
import '../focus/input_mode_tracker.dart';
|
||||
import '../models/download_models.dart';
|
||||
import '../providers/download_provider.dart';
|
||||
import '../providers/settings_provider.dart';
|
||||
import '../utils/content_utils.dart';
|
||||
import '../services/download_storage_service.dart';
|
||||
import '../widgets/plex_optimized_image.dart';
|
||||
import '../models/plex_metadata.dart';
|
||||
@@ -383,6 +386,9 @@ class _EpisodeCardState extends State<_EpisodeCard> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final hideSpoilers = context.watch<SettingsProvider>().hideSpoilers;
|
||||
final shouldBlur = hideSpoilers && widget.episode.shouldHideSpoiler;
|
||||
|
||||
// Hide progress when offline (not tracked)
|
||||
final hasProgress =
|
||||
!widget.isOffline &&
|
||||
@@ -430,7 +436,17 @@ class _EpisodeCardState extends State<_EpisodeCard> {
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
||||
child: AspectRatio(aspectRatio: 16 / 9, child: _buildEpisodeThumbnail()),
|
||||
child: AspectRatio(
|
||||
aspectRatio: 16 / 9,
|
||||
child: shouldBlur
|
||||
? ClipRect(
|
||||
child: ImageFiltered(
|
||||
imageFilter: ImageFilter.blur(sigmaX: 12, sigmaY: 12),
|
||||
child: _buildEpisodeThumbnail(),
|
||||
),
|
||||
)
|
||||
: _buildEpisodeThumbnail(),
|
||||
),
|
||||
),
|
||||
|
||||
// Play overlay
|
||||
@@ -634,8 +650,8 @@ class _EpisodeCardState extends State<_EpisodeCard> {
|
||||
},
|
||||
),
|
||||
|
||||
// Summary
|
||||
if (widget.episode.summary != null && widget.episode.summary!.isNotEmpty) ...[
|
||||
// Summary (hidden when spoiler protection is active)
|
||||
if (!shouldBlur && widget.episode.summary != null && widget.episode.summary!.isNotEmpty) ...[
|
||||
const SizedBox(height: 6),
|
||||
Text(
|
||||
widget.episode.summary!,
|
||||
|
||||
@@ -71,6 +71,7 @@ class _SettingsScreenState extends State<SettingsScreen> with FocusableTab {
|
||||
static const _kShowServerNameOnHubs = 'show_server_name_on_hubs';
|
||||
static const _kAlwaysKeepSidebarOpen = 'always_keep_sidebar_open';
|
||||
static const _kShowUnwatchedCount = 'show_unwatched_count';
|
||||
static const _kHideSpoilers = 'hide_spoilers';
|
||||
static const _kRequireProfileSelectionOnOpen = 'require_profile_selection_on_open';
|
||||
static const _kConfirmExitOnBack = 'confirm_exit_on_back';
|
||||
static const _kPlayerBackend = 'player_backend';
|
||||
@@ -383,6 +384,20 @@ class _SettingsScreenState extends State<SettingsScreen> with FocusableTab {
|
||||
);
|
||||
},
|
||||
),
|
||||
Consumer<SettingsProvider>(
|
||||
builder: (context, settingsProvider, child) {
|
||||
return SwitchListTile(
|
||||
focusNode: _focusTracker.get(_kHideSpoilers),
|
||||
secondary: const AppIcon(Symbols.visibility_off_rounded, fill: 1),
|
||||
title: Text(t.settings.hideSpoilers),
|
||||
subtitle: Text(t.settings.hideSpoilersDescription),
|
||||
value: settingsProvider.hideSpoilers,
|
||||
onChanged: (value) async {
|
||||
await settingsProvider.setHideSpoilers(value);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
Consumer<UserProfileProvider>(
|
||||
builder: (context, userProfileProvider, child) {
|
||||
if (!userProfileProvider.hasMultipleUsers) return const SizedBox.shrink();
|
||||
|
||||
@@ -70,6 +70,7 @@ class SettingsService extends BaseSharedPreferencesService {
|
||||
static const String _keyUseExoPlayer = 'use_exoplayer';
|
||||
static const String _keyAlwaysKeepSidebarOpen = 'always_keep_sidebar_open';
|
||||
static const String _keyShowUnwatchedCount = 'show_unwatched_count';
|
||||
static const String _keyHideSpoilers = 'hide_spoilers';
|
||||
static const String _keyGlobalShaderPreset = 'global_shader_preset';
|
||||
static const String _keyRequireProfileSelectionOnOpen = 'require_profile_selection_on_open';
|
||||
static const String _keyUseExternalPlayer = 'use_external_player';
|
||||
@@ -1037,6 +1038,15 @@ class SettingsService extends BaseSharedPreferencesService {
|
||||
return prefs.getBool(_keyShowUnwatchedCount) ?? true; // Default: enabled (show counts)
|
||||
}
|
||||
|
||||
// Hide Spoilers (blur thumbnails and hide descriptions for unwatched episodes)
|
||||
Future<void> setHideSpoilers(bool enabled) async {
|
||||
await prefs.setBool(_keyHideSpoilers, enabled);
|
||||
}
|
||||
|
||||
bool getHideSpoilers() {
|
||||
return prefs.getBool(_keyHideSpoilers) ?? false; // Default: disabled
|
||||
}
|
||||
|
||||
// Global Shader Preset (for MPV video enhancement)
|
||||
Future<void> setGlobalShaderPreset(String presetId) async {
|
||||
await prefs.setString(_keyGlobalShaderPreset, presetId);
|
||||
@@ -1187,6 +1197,7 @@ class SettingsService extends BaseSharedPreferencesService {
|
||||
prefs.remove(_keyUseExoPlayer),
|
||||
prefs.remove(_keyAlwaysKeepSidebarOpen),
|
||||
prefs.remove(_keyShowUnwatchedCount),
|
||||
prefs.remove(_keyHideSpoilers),
|
||||
prefs.remove(_keyGlobalShaderPreset),
|
||||
prefs.remove(_keyRequireProfileSelectionOnOpen),
|
||||
prefs.remove(_keyUseExternalPlayer),
|
||||
|
||||
@@ -100,4 +100,13 @@ extension PlexMetadataType on PlexMetadata {
|
||||
bool get isClip => _lowerType == ContentTypes.clip;
|
||||
bool get isMusicContent => ContentTypes.musicTypes.contains(_lowerType);
|
||||
bool get isVideoContent => ContentTypes.videoTypes.contains(_lowerType);
|
||||
|
||||
/// Whether this episode should have spoiler protection applied.
|
||||
/// True when the item is an unwatched episode with no active progress.
|
||||
bool get shouldHideSpoiler {
|
||||
if (!isEpisode) return false;
|
||||
if (isWatched) return false;
|
||||
if (viewOffset != null && viewOffset! > 0) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+28
-12
@@ -1,3 +1,5 @@
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:plezy/utils/content_utils.dart';
|
||||
import 'package:plezy/widgets/app_icon.dart';
|
||||
@@ -557,8 +559,8 @@ class _MediaCardList extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
],
|
||||
// Summary
|
||||
if (item.summary != null) ...[
|
||||
// Summary (hidden when spoiler protection is active)
|
||||
if (!(item is PlexMetadata && context.watch<SettingsProvider>().hideSpoilers && (item as PlexMetadata).shouldHideSpoiler) && item.summary != null) ...[
|
||||
Text(
|
||||
item.summary!,
|
||||
maxLines: _summaryMaxLines,
|
||||
@@ -605,12 +607,25 @@ Widget _buildPosterImage(
|
||||
localFilePath: localPosterPath,
|
||||
);
|
||||
} else if (item is PlexMetadata) {
|
||||
final episodePosterMode = context.watch<SettingsProvider>().episodePosterMode;
|
||||
final settingsProvider = context.watch<SettingsProvider>();
|
||||
final episodePosterMode = settingsProvider.episodePosterMode;
|
||||
final shouldBlur = settingsProvider.hideSpoilers && item.shouldHideSpoiler;
|
||||
posterUrl = item.posterThumb(mode: episodePosterMode, mixedHubContext: mixedHubContext);
|
||||
|
||||
Widget image;
|
||||
|
||||
// Use thumb image type for 16:9 content (episodes, or movies in mixed hubs)
|
||||
if (item.usesWideAspectRatio(episodePosterMode, mixedHubContext: mixedHubContext)) {
|
||||
return PlexOptimizedImage.thumb(
|
||||
image = PlexOptimizedImage.thumb(
|
||||
client: isOffline ? null : context.getClientWithFallback(item.serverId),
|
||||
imagePath: posterUrl,
|
||||
width: knownWidth ?? double.infinity,
|
||||
height: knownHeight ?? double.infinity,
|
||||
fit: BoxFit.cover,
|
||||
localFilePath: localPosterPath,
|
||||
);
|
||||
} else {
|
||||
image = PlexOptimizedImage.poster(
|
||||
client: isOffline ? null : context.getClientWithFallback(item.serverId),
|
||||
imagePath: posterUrl,
|
||||
width: knownWidth ?? double.infinity,
|
||||
@@ -620,14 +635,15 @@ Widget _buildPosterImage(
|
||||
);
|
||||
}
|
||||
|
||||
return PlexOptimizedImage.poster(
|
||||
client: isOffline ? null : context.getClientWithFallback(item.serverId),
|
||||
imagePath: posterUrl,
|
||||
width: knownWidth ?? double.infinity,
|
||||
height: knownHeight ?? double.infinity,
|
||||
fit: BoxFit.cover,
|
||||
localFilePath: localPosterPath,
|
||||
);
|
||||
if (shouldBlur) {
|
||||
return ClipRect(
|
||||
child: ImageFiltered(
|
||||
imageFilter: ImageFilter.blur(sigmaX: 12, sigmaY: 12),
|
||||
child: image,
|
||||
),
|
||||
);
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
return SkeletonLoader(
|
||||
|
||||
Reference in New Issue
Block a user