From 7f0666afbc745cf0a902ad6288a73fd2822e45f9 Mon Sep 17 00:00:00 2001 From: edde746 <86283021+edde746@users.noreply.github.com> Date: Sun, 8 Feb 2026 12:07:16 +0100 Subject: [PATCH] feat: require profile selection on app open close #417 --- lib/i18n/de.i18n.json | 4 ++- lib/i18n/en.i18n.json | 4 ++- lib/i18n/es.i18n.json | 4 ++- lib/i18n/fr.i18n.json | 4 ++- lib/i18n/it.i18n.json | 4 ++- lib/i18n/ko.i18n.json | 4 ++- lib/i18n/nl.i18n.json | 4 ++- lib/i18n/strings.g.dart | 4 +-- lib/i18n/strings_de.g.dart | 8 +++-- lib/i18n/strings_en.g.dart | 12 +++++-- lib/i18n/strings_es.g.dart | 8 +++-- lib/i18n/strings_fr.g.dart | 8 +++-- lib/i18n/strings_it.g.dart | 8 +++-- lib/i18n/strings_ko.g.dart | 8 +++-- lib/i18n/strings_nl.g.dart | 8 +++-- lib/i18n/strings_sv.g.dart | 8 +++-- lib/i18n/strings_zh.g.dart | 8 +++-- lib/i18n/sv.i18n.json | 4 ++- lib/i18n/zh.i18n.json | 4 ++- lib/screens/main_screen.dart | 42 +++++++++++++++++++++-- lib/screens/settings/settings_screen.dart | 20 +++++++++++ lib/services/settings_service.dart | 11 ++++++ 22 files changed, 158 insertions(+), 31 deletions(-) diff --git a/lib/i18n/de.i18n.json b/lib/i18n/de.i18n.json index 34467559..51b57488 100644 --- a/lib/i18n/de.i18n.json +++ b/lib/i18n/de.i18n.json @@ -172,7 +172,9 @@ "discordRichPresence": "Discord Rich Presence", "discordRichPresenceDescription": "Zeige auf Discord, was du gerade schaust", "matchContentFrameRate": "Inhalts-Bildrate anpassen", - "matchContentFrameRateDescription": "Bildwiederholfrequenz des Displays an den Videoinhalt anpassen, reduziert Ruckeln und spart Akku" + "matchContentFrameRateDescription": "Bildwiederholfrequenz des Displays an den Videoinhalt anpassen, reduziert Ruckeln und spart Akku", + "requireProfileSelectionOnOpen": "Profil beim Öffnen abfragen", + "requireProfileSelectionOnOpenDescription": "Profilauswahl bei jedem Öffnen der App anzeigen" }, "search": { "hint": "Filme, Serien, Musik suchen...", diff --git a/lib/i18n/en.i18n.json b/lib/i18n/en.i18n.json index 13c2e681..de1b761c 100644 --- a/lib/i18n/en.i18n.json +++ b/lib/i18n/en.i18n.json @@ -172,7 +172,9 @@ "discordRichPresence": "Discord Rich Presence", "discordRichPresenceDescription": "Show what you're watching on Discord", "matchContentFrameRate": "Match Content Frame Rate", - "matchContentFrameRateDescription": "Adjust display refresh rate to match video content, reducing judder and saving battery" + "matchContentFrameRateDescription": "Adjust display refresh rate to match video content, reducing judder and saving battery", + "requireProfileSelectionOnOpen": "Ask for profile on app open", + "requireProfileSelectionOnOpenDescription": "Show profile selection every time the app is opened" }, "search": { "hint": "Search movies, shows, music...", diff --git a/lib/i18n/es.i18n.json b/lib/i18n/es.i18n.json index d74e5f42..3751319c 100644 --- a/lib/i18n/es.i18n.json +++ b/lib/i18n/es.i18n.json @@ -172,7 +172,9 @@ "discordRichPresence": "Presencia de Discord", "discordRichPresenceDescription": "Mostrar lo que estás viendo en Discord", "matchContentFrameRate": "Ajustar frecuencia de actualización", - "matchContentFrameRateDescription": "Ajustar la frecuencia de actualización de la pantalla para que coincida con el video, reduciendo tirones y ahorrando batería" + "matchContentFrameRateDescription": "Ajustar la frecuencia de actualización de la pantalla para que coincida con el video, reduciendo tirones y ahorrando batería", + "requireProfileSelectionOnOpen": "Pedir perfil al abrir la app", + "requireProfileSelectionOnOpenDescription": "Mostrar selección de perfil cada vez que se abre la aplicación" }, "search": { "hint": "Buscar películas, series, música...", diff --git a/lib/i18n/fr.i18n.json b/lib/i18n/fr.i18n.json index a3f7700f..b1db909b 100644 --- a/lib/i18n/fr.i18n.json +++ b/lib/i18n/fr.i18n.json @@ -172,7 +172,9 @@ "discordRichPresence": "Discord Rich Presence", "discordRichPresenceDescription": "Montrez ce que vous regardez sur Discord", "matchContentFrameRate": "Fréquence d'images du contenu correspondant", - "matchContentFrameRateDescription": "Ajustez la fréquence de rafraîchissement de l'écran en fonction du contenu vidéo, ce qui réduit les saccades et économise la batterie" + "matchContentFrameRateDescription": "Ajustez la fréquence de rafraîchissement de l'écran en fonction du contenu vidéo, ce qui réduit les saccades et économise la batterie", + "requireProfileSelectionOnOpen": "Demander le profil à l'ouverture", + "requireProfileSelectionOnOpenDescription": "Afficher la sélection de profil à chaque ouverture de l'application" }, "search": { "hint": "Rechercher des films, des séries, de la musique...", diff --git a/lib/i18n/it.i18n.json b/lib/i18n/it.i18n.json index d9502c4d..66d95807 100644 --- a/lib/i18n/it.i18n.json +++ b/lib/i18n/it.i18n.json @@ -172,7 +172,9 @@ "discordRichPresence": "Discord Rich Presence", "discordRichPresenceDescription": "Mostra su Discord cosa stai guardando", "matchContentFrameRate": "Adatta frequenza fotogrammi", - "matchContentFrameRateDescription": "Regola la frequenza di aggiornamento del display in base al contenuto video, riducendo i tremolii e risparmiando batteria" + "matchContentFrameRateDescription": "Regola la frequenza di aggiornamento del display in base al contenuto video, riducendo i tremolii e risparmiando batteria", + "requireProfileSelectionOnOpen": "Chiedi profilo all'apertura", + "requireProfileSelectionOnOpenDescription": "Mostra la selezione del profilo ogni volta che l'app viene aperta" }, "search": { "hint": "Cerca film. spettacoli, musica...", diff --git a/lib/i18n/ko.i18n.json b/lib/i18n/ko.i18n.json index 7dc3a577..79f6a243 100644 --- a/lib/i18n/ko.i18n.json +++ b/lib/i18n/ko.i18n.json @@ -172,7 +172,9 @@ "discordRichPresence": "Discord Rich Presence", "discordRichPresenceDescription": "Discord에서 시청 중인 콘텐츠 표시", "matchContentFrameRate": "콘텐츠 프레임 레이트 맞춤", - "matchContentFrameRateDescription": "비디오 콘텐츠에 맞게 디스플레이 주사율을 조정하여 떨림을 줄이고 배터리를 절약합니다" + "matchContentFrameRateDescription": "비디오 콘텐츠에 맞게 디스플레이 주사율을 조정하여 떨림을 줄이고 배터리를 절약합니다", + "requireProfileSelectionOnOpen": "앱 실행 시 프로필 선택", + "requireProfileSelectionOnOpenDescription": "앱을 열 때마다 프로필 선택 화면을 표시합니다" }, "search": { "hint": "영화, 시리즈, 음악 등을 검색하세요...", diff --git a/lib/i18n/nl.i18n.json b/lib/i18n/nl.i18n.json index 44d36e86..4cf9ada8 100644 --- a/lib/i18n/nl.i18n.json +++ b/lib/i18n/nl.i18n.json @@ -172,7 +172,9 @@ "discordRichPresence": "Discord Rich Presence", "discordRichPresenceDescription": "Toon op Discord wat je aan het kijken bent", "matchContentFrameRate": "Inhoudsframesnelheid afstemmen", - "matchContentFrameRateDescription": "Pas de schermverversingssnelheid aan op de video-inhoud, vermindert haperingen en bespaart batterij" + "matchContentFrameRateDescription": "Pas de schermverversingssnelheid aan op de video-inhoud, vermindert haperingen en bespaart batterij", + "requireProfileSelectionOnOpen": "Vraag om profiel bij openen", + "requireProfileSelectionOnOpenDescription": "Toon profielselectie telkens wanneer de app wordt geopend" }, "search": { "hint": "Zoek films, series, muziek...", diff --git a/lib/i18n/strings.g.dart b/lib/i18n/strings.g.dart index f5759b1b..8445caca 100644 --- a/lib/i18n/strings.g.dart +++ b/lib/i18n/strings.g.dart @@ -4,9 +4,9 @@ /// To regenerate, run: `dart run slang` /// /// Locales: 9 -/// Strings: 5103 (567 per locale) +/// Strings: 5121 (569 per locale) /// -/// Built on 2026-02-07 at 18:57 UTC +/// Built on 2026-02-08 at 11:03 UTC // coverage:ignore-file // ignore_for_file: type=lint, unused_import diff --git a/lib/i18n/strings_de.g.dart b/lib/i18n/strings_de.g.dart index 38fbf84b..00bcdbfc 100644 --- a/lib/i18n/strings_de.g.dart +++ b/lib/i18n/strings_de.g.dart @@ -287,6 +287,8 @@ class _TranslationsSettingsDe implements TranslationsSettingsEn { @override String get discordRichPresenceDescription => 'Zeige auf Discord, was du gerade schaust'; @override String get matchContentFrameRate => 'Inhalts-Bildrate anpassen'; @override String get matchContentFrameRateDescription => 'Bildwiederholfrequenz des Displays an den Videoinhalt anpassen, reduziert Ruckeln und spart Akku'; + @override String get requireProfileSelectionOnOpen => 'Profil beim Öffnen abfragen'; + @override String get requireProfileSelectionOnOpenDescription => 'Profilauswahl bei jedem Öffnen der App anzeigen'; } // Path: search @@ -1147,6 +1149,8 @@ extension on TranslationsDe { 'settings.discordRichPresenceDescription' => 'Zeige auf Discord, was du gerade schaust', 'settings.matchContentFrameRate' => 'Inhalts-Bildrate anpassen', 'settings.matchContentFrameRateDescription' => 'Bildwiederholfrequenz des Displays an den Videoinhalt anpassen, reduziert Ruckeln und spart Akku', + 'settings.requireProfileSelectionOnOpen' => 'Profil beim Öffnen abfragen', + 'settings.requireProfileSelectionOnOpenDescription' => 'Profilauswahl bei jedem Öffnen der App anzeigen', 'search.hint' => 'Filme, Serien, Musik suchen...', 'search.tryDifferentTerm' => 'Anderen Suchbegriff versuchen', 'search.searchYourMedia' => 'In den eigenen Medien suchen', @@ -1494,10 +1498,10 @@ extension on TranslationsDe { 'collections.selectCollection' => 'Sammlung auswählen', 'collections.createNewCollection' => 'Neue Sammlung erstellen', 'collections.collectionName' => 'Sammlungsname', - 'collections.enterCollectionName' => 'Sammlungsnamen eingeben', - 'collections.addedToCollection' => 'Zur Sammlung hinzugefügt', _ => null, } ?? switch (path) { + 'collections.enterCollectionName' => 'Sammlungsnamen eingeben', + 'collections.addedToCollection' => 'Zur Sammlung hinzugefügt', 'collections.errorAddingToCollection' => 'Fehler beim Hinzufügen zur Sammlung', 'collections.created' => 'Sammlung erstellt', 'collections.removeFromCollection' => 'Aus Sammlung entfernen', diff --git a/lib/i18n/strings_en.g.dart b/lib/i18n/strings_en.g.dart index 20669614..4e321619 100644 --- a/lib/i18n/strings_en.g.dart +++ b/lib/i18n/strings_en.g.dart @@ -616,6 +616,12 @@ class TranslationsSettingsEn { /// en: 'Adjust display refresh rate to match video content, reducing judder and saving battery' String get matchContentFrameRateDescription => 'Adjust display refresh rate to match video content, reducing judder and saving battery'; + + /// en: 'Ask for profile on app open' + String get requireProfileSelectionOnOpen => 'Ask for profile on app open'; + + /// en: 'Show profile selection every time the app is opened' + String get requireProfileSelectionOnOpenDescription => 'Show profile selection every time the app is opened'; } // Path: search @@ -2287,6 +2293,8 @@ extension on Translations { 'settings.discordRichPresenceDescription' => 'Show what you\'re watching on Discord', 'settings.matchContentFrameRate' => 'Match Content Frame Rate', 'settings.matchContentFrameRateDescription' => 'Adjust display refresh rate to match video content, reducing judder and saving battery', + 'settings.requireProfileSelectionOnOpen' => 'Ask for profile on app open', + 'settings.requireProfileSelectionOnOpenDescription' => 'Show profile selection every time the app is opened', 'search.hint' => 'Search movies, shows, music...', 'search.tryDifferentTerm' => 'Try a different search term', 'search.searchYourMedia' => 'Search your media', @@ -2634,10 +2642,10 @@ extension on Translations { 'watchTogether.createSession' => 'Create Session', 'watchTogether.creating' => 'Creating...', 'watchTogether.joinSession' => 'Join Session', - 'watchTogether.joining' => 'Joining...', - 'watchTogether.controlMode' => 'Control Mode', _ => null, } ?? switch (path) { + 'watchTogether.joining' => 'Joining...', + 'watchTogether.controlMode' => 'Control Mode', 'watchTogether.controlModeQuestion' => 'Who can control playback?', 'watchTogether.hostOnly' => 'Host Only', 'watchTogether.anyone' => 'Anyone', diff --git a/lib/i18n/strings_es.g.dart b/lib/i18n/strings_es.g.dart index 6c39d247..e80bbf6c 100644 --- a/lib/i18n/strings_es.g.dart +++ b/lib/i18n/strings_es.g.dart @@ -287,6 +287,8 @@ class _TranslationsSettingsEs implements TranslationsSettingsEn { @override String get discordRichPresenceDescription => 'Mostrar lo que estás viendo en Discord'; @override String get matchContentFrameRate => 'Ajustar frecuencia de actualización'; @override String get matchContentFrameRateDescription => 'Ajustar la frecuencia de actualización de la pantalla para que coincida con el video, reduciendo tirones y ahorrando batería'; + @override String get requireProfileSelectionOnOpen => 'Pedir perfil al abrir la app'; + @override String get requireProfileSelectionOnOpenDescription => 'Mostrar selección de perfil cada vez que se abre la aplicación'; } // Path: search @@ -1147,6 +1149,8 @@ extension on TranslationsEs { 'settings.discordRichPresenceDescription' => 'Mostrar lo que estás viendo en Discord', 'settings.matchContentFrameRate' => 'Ajustar frecuencia de actualización', 'settings.matchContentFrameRateDescription' => 'Ajustar la frecuencia de actualización de la pantalla para que coincida con el video, reduciendo tirones y ahorrando batería', + 'settings.requireProfileSelectionOnOpen' => 'Pedir perfil al abrir la app', + 'settings.requireProfileSelectionOnOpenDescription' => 'Mostrar selección de perfil cada vez que se abre la aplicación', 'search.hint' => 'Buscar películas, series, música...', 'search.tryDifferentTerm' => 'Prueba con un término de búsqueda diferente', 'search.searchYourMedia' => 'Busca en tu contenido', @@ -1494,10 +1498,10 @@ extension on TranslationsEs { 'watchTogether.createSession' => 'Crear Sesión', 'watchTogether.creating' => 'Creando...', 'watchTogether.joinSession' => 'Unirse a Sesión', - 'watchTogether.joining' => 'Uniendo...', - 'watchTogether.controlMode' => 'Modo de Control', _ => null, } ?? switch (path) { + 'watchTogether.joining' => 'Uniendo...', + 'watchTogether.controlMode' => 'Modo de Control', 'watchTogether.controlModeQuestion' => '¿Quién puede controlar la reproducción?', 'watchTogether.hostOnly' => 'Solo el Anfitrión', 'watchTogether.anyone' => 'Cualquiera', diff --git a/lib/i18n/strings_fr.g.dart b/lib/i18n/strings_fr.g.dart index 157135c2..966798a4 100644 --- a/lib/i18n/strings_fr.g.dart +++ b/lib/i18n/strings_fr.g.dart @@ -287,6 +287,8 @@ class _TranslationsSettingsFr implements TranslationsSettingsEn { @override String get discordRichPresenceDescription => 'Montrez ce que vous regardez sur Discord'; @override String get matchContentFrameRate => 'Fréquence d\'images du contenu correspondant'; @override String get matchContentFrameRateDescription => 'Ajustez la fréquence de rafraîchissement de l\'écran en fonction du contenu vidéo, ce qui réduit les saccades et économise la batterie'; + @override String get requireProfileSelectionOnOpen => 'Demander le profil à l\'ouverture'; + @override String get requireProfileSelectionOnOpenDescription => 'Afficher la sélection de profil à chaque ouverture de l\'application'; } // Path: search @@ -1147,6 +1149,8 @@ extension on TranslationsFr { 'settings.discordRichPresenceDescription' => 'Montrez ce que vous regardez sur Discord', 'settings.matchContentFrameRate' => 'Fréquence d\'images du contenu correspondant', 'settings.matchContentFrameRateDescription' => 'Ajustez la fréquence de rafraîchissement de l\'écran en fonction du contenu vidéo, ce qui réduit les saccades et économise la batterie', + 'settings.requireProfileSelectionOnOpen' => 'Demander le profil à l\'ouverture', + 'settings.requireProfileSelectionOnOpenDescription' => 'Afficher la sélection de profil à chaque ouverture de l\'application', 'search.hint' => 'Rechercher des films, des séries, de la musique...', 'search.tryDifferentTerm' => 'Essayez un autre terme de recherche', 'search.searchYourMedia' => 'Rechercher dans vos médias', @@ -1494,10 +1498,10 @@ extension on TranslationsFr { 'watchTogether.createSession' => 'Créer une session', 'watchTogether.creating' => 'Création...', 'watchTogether.joinSession' => 'Rejoindre la session', - 'watchTogether.joining' => 'Rejoindre...', - 'watchTogether.controlMode' => 'Mode de contrôle', _ => null, } ?? switch (path) { + 'watchTogether.joining' => 'Rejoindre...', + 'watchTogether.controlMode' => 'Mode de contrôle', 'watchTogether.controlModeQuestion' => 'Qui peut contrôler la lecture ?', 'watchTogether.hostOnly' => 'Hôte uniquement', 'watchTogether.anyone' => 'N\'importe qui', diff --git a/lib/i18n/strings_it.g.dart b/lib/i18n/strings_it.g.dart index e4f8543c..aa563644 100644 --- a/lib/i18n/strings_it.g.dart +++ b/lib/i18n/strings_it.g.dart @@ -287,6 +287,8 @@ class _TranslationsSettingsIt implements TranslationsSettingsEn { @override String get discordRichPresenceDescription => 'Mostra su Discord cosa stai guardando'; @override String get matchContentFrameRate => 'Adatta frequenza fotogrammi'; @override String get matchContentFrameRateDescription => 'Regola la frequenza di aggiornamento del display in base al contenuto video, riducendo i tremolii e risparmiando batteria'; + @override String get requireProfileSelectionOnOpen => 'Chiedi profilo all\'apertura'; + @override String get requireProfileSelectionOnOpenDescription => 'Mostra la selezione del profilo ogni volta che l\'app viene aperta'; } // Path: search @@ -1147,6 +1149,8 @@ extension on TranslationsIt { 'settings.discordRichPresenceDescription' => 'Mostra su Discord cosa stai guardando', 'settings.matchContentFrameRate' => 'Adatta frequenza fotogrammi', 'settings.matchContentFrameRateDescription' => 'Regola la frequenza di aggiornamento del display in base al contenuto video, riducendo i tremolii e risparmiando batteria', + 'settings.requireProfileSelectionOnOpen' => 'Chiedi profilo all\'apertura', + 'settings.requireProfileSelectionOnOpenDescription' => 'Mostra la selezione del profilo ogni volta che l\'app viene aperta', 'search.hint' => 'Cerca film. spettacoli, musica...', 'search.tryDifferentTerm' => 'Prova altri termini di ricerca', 'search.searchYourMedia' => 'Cerca nei tuoi media', @@ -1494,10 +1498,10 @@ extension on TranslationsIt { 'collections.selectCollection' => 'Seleziona raccolta', 'collections.createNewCollection' => 'Crea nuova raccolta', 'collections.collectionName' => 'Nome raccolta', - 'collections.enterCollectionName' => 'Inserisci nome raccolta', - 'collections.addedToCollection' => 'Aggiunto alla raccolta', _ => null, } ?? switch (path) { + 'collections.enterCollectionName' => 'Inserisci nome raccolta', + 'collections.addedToCollection' => 'Aggiunto alla raccolta', 'collections.errorAddingToCollection' => 'Errore nell\'aggiunta alla raccolta', 'collections.created' => 'Raccolta creata', 'collections.removeFromCollection' => 'Rimuovi dalla raccolta', diff --git a/lib/i18n/strings_ko.g.dart b/lib/i18n/strings_ko.g.dart index c104f099..d83efca9 100644 --- a/lib/i18n/strings_ko.g.dart +++ b/lib/i18n/strings_ko.g.dart @@ -287,6 +287,8 @@ class _TranslationsSettingsKo implements TranslationsSettingsEn { @override String get discordRichPresenceDescription => 'Discord에서 시청 중인 콘텐츠 표시'; @override String get matchContentFrameRate => '콘텐츠 프레임 레이트 맞춤'; @override String get matchContentFrameRateDescription => '비디오 콘텐츠에 맞게 디스플레이 주사율을 조정하여 떨림을 줄이고 배터리를 절약합니다'; + @override String get requireProfileSelectionOnOpen => '앱 실행 시 프로필 선택'; + @override String get requireProfileSelectionOnOpenDescription => '앱을 열 때마다 프로필 선택 화면을 표시합니다'; } // Path: search @@ -1147,6 +1149,8 @@ extension on TranslationsKo { 'settings.discordRichPresenceDescription' => 'Discord에서 시청 중인 콘텐츠 표시', 'settings.matchContentFrameRate' => '콘텐츠 프레임 레이트 맞춤', 'settings.matchContentFrameRateDescription' => '비디오 콘텐츠에 맞게 디스플레이 주사율을 조정하여 떨림을 줄이고 배터리를 절약합니다', + 'settings.requireProfileSelectionOnOpen' => '앱 실행 시 프로필 선택', + 'settings.requireProfileSelectionOnOpenDescription' => '앱을 열 때마다 프로필 선택 화면을 표시합니다', 'search.hint' => '영화, 시리즈, 음악 등을 검색하세요...', 'search.tryDifferentTerm' => '다른 검색어를 시도해 보세요', 'search.searchYourMedia' => '미디어 검색', @@ -1494,10 +1498,10 @@ extension on TranslationsKo { 'watchTogether.createSession' => '세션 생성', 'watchTogether.creating' => '생성 중...', 'watchTogether.joinSession' => '세션 참여', - 'watchTogether.joining' => '참가 중...', - 'watchTogether.controlMode' => '제어 모드', _ => null, } ?? switch (path) { + 'watchTogether.joining' => '참가 중...', + 'watchTogether.controlMode' => '제어 모드', 'watchTogether.controlModeQuestion' => '누가 재생을 제어할 수 있나요?', 'watchTogether.hostOnly' => '호스트만', 'watchTogether.anyone' => '누구나', diff --git a/lib/i18n/strings_nl.g.dart b/lib/i18n/strings_nl.g.dart index e7f37679..72c61e84 100644 --- a/lib/i18n/strings_nl.g.dart +++ b/lib/i18n/strings_nl.g.dart @@ -287,6 +287,8 @@ class _TranslationsSettingsNl implements TranslationsSettingsEn { @override String get discordRichPresenceDescription => 'Toon op Discord wat je aan het kijken bent'; @override String get matchContentFrameRate => 'Inhoudsframesnelheid afstemmen'; @override String get matchContentFrameRateDescription => 'Pas de schermverversingssnelheid aan op de video-inhoud, vermindert haperingen en bespaart batterij'; + @override String get requireProfileSelectionOnOpen => 'Vraag om profiel bij openen'; + @override String get requireProfileSelectionOnOpenDescription => 'Toon profielselectie telkens wanneer de app wordt geopend'; } // Path: search @@ -1147,6 +1149,8 @@ extension on TranslationsNl { 'settings.discordRichPresenceDescription' => 'Toon op Discord wat je aan het kijken bent', 'settings.matchContentFrameRate' => 'Inhoudsframesnelheid afstemmen', 'settings.matchContentFrameRateDescription' => 'Pas de schermverversingssnelheid aan op de video-inhoud, vermindert haperingen en bespaart batterij', + 'settings.requireProfileSelectionOnOpen' => 'Vraag om profiel bij openen', + 'settings.requireProfileSelectionOnOpenDescription' => 'Toon profielselectie telkens wanneer de app wordt geopend', 'search.hint' => 'Zoek films, series, muziek...', 'search.tryDifferentTerm' => 'Probeer een andere zoekterm', 'search.searchYourMedia' => 'Zoek in je media', @@ -1494,10 +1498,10 @@ extension on TranslationsNl { 'collections.selectCollection' => 'Selecteer collectie', 'collections.createNewCollection' => 'Nieuwe collectie maken', 'collections.collectionName' => 'Collectienaam', - 'collections.enterCollectionName' => 'Voer collectienaam in', - 'collections.addedToCollection' => 'Toegevoegd aan collectie', _ => null, } ?? switch (path) { + 'collections.enterCollectionName' => 'Voer collectienaam in', + 'collections.addedToCollection' => 'Toegevoegd aan collectie', 'collections.errorAddingToCollection' => 'Fout bij toevoegen aan collectie', 'collections.created' => 'Collectie gemaakt', 'collections.removeFromCollection' => 'Verwijderen uit collectie', diff --git a/lib/i18n/strings_sv.g.dart b/lib/i18n/strings_sv.g.dart index 14716e92..af03f7a3 100644 --- a/lib/i18n/strings_sv.g.dart +++ b/lib/i18n/strings_sv.g.dart @@ -287,6 +287,8 @@ class _TranslationsSettingsSv implements TranslationsSettingsEn { @override String get discordRichPresenceDescription => 'Visa vad du tittar på i Discord'; @override String get matchContentFrameRate => 'Matcha innehållets bildfrekvens'; @override String get matchContentFrameRateDescription => 'Justera skärmens uppdateringsfrekvens för att matcha videoinnehållet, minskar hackighet och sparar batteri'; + @override String get requireProfileSelectionOnOpen => 'Fråga efter profil vid appstart'; + @override String get requireProfileSelectionOnOpenDescription => 'Visa profilval varje gång appen öppnas'; } // Path: search @@ -1147,6 +1149,8 @@ extension on TranslationsSv { 'settings.discordRichPresenceDescription' => 'Visa vad du tittar på i Discord', 'settings.matchContentFrameRate' => 'Matcha innehållets bildfrekvens', 'settings.matchContentFrameRateDescription' => 'Justera skärmens uppdateringsfrekvens för att matcha videoinnehållet, minskar hackighet och sparar batteri', + 'settings.requireProfileSelectionOnOpen' => 'Fråga efter profil vid appstart', + 'settings.requireProfileSelectionOnOpenDescription' => 'Visa profilval varje gång appen öppnas', 'search.hint' => 'Sök filmer, serier, musik...', 'search.tryDifferentTerm' => 'Prova en annan sökterm', 'search.searchYourMedia' => 'Sök i dina media', @@ -1494,10 +1498,10 @@ extension on TranslationsSv { 'collections.selectCollection' => 'Välj samling', 'collections.createNewCollection' => 'Skapa ny samling', 'collections.collectionName' => 'Samlingsnamn', - 'collections.enterCollectionName' => 'Ange samlingsnamn', - 'collections.addedToCollection' => 'Tillagd i samling', _ => null, } ?? switch (path) { + 'collections.enterCollectionName' => 'Ange samlingsnamn', + 'collections.addedToCollection' => 'Tillagd i samling', 'collections.errorAddingToCollection' => 'Fel vid tillägg i samling', 'collections.created' => 'Samling skapad', 'collections.removeFromCollection' => 'Ta bort från samling', diff --git a/lib/i18n/strings_zh.g.dart b/lib/i18n/strings_zh.g.dart index 3ea256fe..1cbddee6 100644 --- a/lib/i18n/strings_zh.g.dart +++ b/lib/i18n/strings_zh.g.dart @@ -287,6 +287,8 @@ class _TranslationsSettingsZh implements TranslationsSettingsEn { @override String get discordRichPresenceDescription => '在 Discord 上显示您正在观看的内容'; @override String get matchContentFrameRate => '匹配内容帧率'; @override String get matchContentFrameRateDescription => '调整显示刷新率以匹配视频内容,减少画面抖动并节省电量'; + @override String get requireProfileSelectionOnOpen => '打开应用时询问配置文件'; + @override String get requireProfileSelectionOnOpenDescription => '每次打开应用时显示配置文件选择'; } // Path: search @@ -1147,6 +1149,8 @@ extension on TranslationsZh { 'settings.discordRichPresenceDescription' => '在 Discord 上显示您正在观看的内容', 'settings.matchContentFrameRate' => '匹配内容帧率', 'settings.matchContentFrameRateDescription' => '调整显示刷新率以匹配视频内容,减少画面抖动并节省电量', + 'settings.requireProfileSelectionOnOpen' => '打开应用时询问配置文件', + 'settings.requireProfileSelectionOnOpenDescription' => '每次打开应用时显示配置文件选择', 'search.hint' => '搜索电影、系列、音乐...', 'search.tryDifferentTerm' => '尝试不同的搜索词', 'search.searchYourMedia' => '搜索媒体', @@ -1494,10 +1498,10 @@ extension on TranslationsZh { 'collections.selectCollection' => '选择合集', 'collections.createNewCollection' => '创建新合集', 'collections.collectionName' => '合集名称', - 'collections.enterCollectionName' => '输入合集名称', - 'collections.addedToCollection' => '已添加到合集', _ => null, } ?? switch (path) { + 'collections.enterCollectionName' => '输入合集名称', + 'collections.addedToCollection' => '已添加到合集', 'collections.errorAddingToCollection' => '添加到合集失败', 'collections.created' => '已创建合集', 'collections.removeFromCollection' => '从合集移除', diff --git a/lib/i18n/sv.i18n.json b/lib/i18n/sv.i18n.json index 61b81b37..07eca9fd 100644 --- a/lib/i18n/sv.i18n.json +++ b/lib/i18n/sv.i18n.json @@ -172,7 +172,9 @@ "discordRichPresence": "Discord Rich Presence", "discordRichPresenceDescription": "Visa vad du tittar på i Discord", "matchContentFrameRate": "Matcha innehållets bildfrekvens", - "matchContentFrameRateDescription": "Justera skärmens uppdateringsfrekvens för att matcha videoinnehållet, minskar hackighet och sparar batteri" + "matchContentFrameRateDescription": "Justera skärmens uppdateringsfrekvens för att matcha videoinnehållet, minskar hackighet och sparar batteri", + "requireProfileSelectionOnOpen": "Fråga efter profil vid appstart", + "requireProfileSelectionOnOpenDescription": "Visa profilval varje gång appen öppnas" }, "search": { "hint": "Sök filmer, serier, musik...", diff --git a/lib/i18n/zh.i18n.json b/lib/i18n/zh.i18n.json index f14a93d4..5ccec267 100644 --- a/lib/i18n/zh.i18n.json +++ b/lib/i18n/zh.i18n.json @@ -172,7 +172,9 @@ "discordRichPresence": "Discord 动态状态", "discordRichPresenceDescription": "在 Discord 上显示您正在观看的内容", "matchContentFrameRate": "匹配内容帧率", - "matchContentFrameRateDescription": "调整显示刷新率以匹配视频内容,减少画面抖动并节省电量" + "matchContentFrameRateDescription": "调整显示刷新率以匹配视频内容,减少画面抖动并节省电量", + "requireProfileSelectionOnOpen": "打开应用时询问配置文件", + "requireProfileSelectionOnOpenDescription": "每次打开应用时显示配置文件选择" }, "search": { "hint": "搜索电影、系列、音乐...", diff --git a/lib/screens/main_screen.dart b/lib/screens/main_screen.dart index 15b8e536..22b61c35 100644 --- a/lib/screens/main_screen.dart +++ b/lib/screens/main_screen.dart @@ -24,6 +24,7 @@ import '../providers/playback_state_provider.dart'; import '../providers/settings_provider.dart'; import '../providers/user_profile_provider.dart'; import '../services/offline_watch_sync_service.dart'; +import '../services/settings_service.dart'; import '../providers/offline_mode_provider.dart'; import '../services/plex_auth_service.dart'; import '../services/storage_service.dart'; @@ -74,7 +75,7 @@ class MainScreen extends StatefulWidget { State createState() => _MainScreenState(); } -class _MainScreenState extends State with RouteAware, WindowListener { +class _MainScreenState extends State with RouteAware, WindowListener, WidgetsBindingObserver { late int _currentIndex; String? _selectedLibraryGlobalKey; @@ -89,6 +90,9 @@ class _MainScreenState extends State with RouteAware, WindowListener OfflineModeProvider? _offlineModeProvider; + /// Prevents double-pushing the profile selection screen + bool _isShowingProfileSelection = false; + late List _screens; final GlobalKey> _discoverKey = GlobalKey(); final GlobalKey> _librariesKey = GlobalKey(); @@ -107,6 +111,8 @@ class _MainScreenState extends State with RouteAware, WindowListener super.initState(); _isOffline = widget.isOfflineMode; + WidgetsBinding.instance.addObserver(this); + if (Platform.isLinux || Platform.isWindows || Platform.isMacOS) { windowManager.addListener(this); windowManager.setPreventClose(true); @@ -152,11 +158,20 @@ class _MainScreenState extends State with RouteAware, WindowListener } Future _promptForInitialProfileSelection(UserProfileProvider userProfileProvider) async { - if (!mounted || !userProfileProvider.needsInitialProfileSelection) return; + if (!mounted || _isShowingProfileSelection) return; + final needsInitial = userProfileProvider.needsInitialProfileSelection; + final settingsService = await SettingsService.getInstance(); + if (!mounted) return; + final requireOnOpen = settingsService.getRequireProfileSelectionOnOpen() && userProfileProvider.hasMultipleUsers; + + if (!needsInitial && !requireOnOpen) return; + + _isShowingProfileSelection = true; await Navigator.of( context, ).push(MaterialPageRoute(builder: (context) => const ProfileSwitchScreen(requireSelection: true))); + _isShowingProfileSelection = false; } Future _checkForUpdatesOnStartup() async { @@ -368,6 +383,7 @@ class _MainScreenState extends State with RouteAware, WindowListener @override void dispose() { + WidgetsBinding.instance.removeObserver(this); routeObserver.unsubscribe(this); if (Platform.isLinux || Platform.isWindows || Platform.isMacOS) { windowManager.removeListener(this); @@ -384,6 +400,28 @@ class _MainScreenState extends State with RouteAware, WindowListener exit(0); } + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + if (state == AppLifecycleState.resumed && !_isOffline && !_isShowingProfileSelection) { + _showProfileSelectionOnResume(); + } + } + + Future _showProfileSelectionOnResume() async { + final settingsService = await SettingsService.getInstance(); + if (!settingsService.getRequireProfileSelectionOnOpen()) return; + if (!mounted) return; + + final userProfileProvider = context.read(); + if (!userProfileProvider.hasMultipleUsers) return; + + _isShowingProfileSelection = true; + await Navigator.of( + context, + ).push(MaterialPageRoute(builder: (context) => const ProfileSwitchScreen(requireSelection: true))); + _isShowingProfileSelection = false; + } + List _buildScreens(bool offline) { // In offline mode, only show Downloads and Settings // In online mode, show all 5 screens diff --git a/lib/screens/settings/settings_screen.dart b/lib/screens/settings/settings_screen.dart index 3e057f87..a7ae977f 100644 --- a/lib/screens/settings/settings_screen.dart +++ b/lib/screens/settings/settings_screen.dart @@ -18,6 +18,7 @@ import '../../services/download_storage_service.dart'; import '../../services/saf_storage_service.dart'; import '../../providers/settings_provider.dart'; import '../../providers/theme_provider.dart'; +import '../../providers/user_profile_provider.dart'; import '../../services/keyboard_shortcuts_service.dart'; import '../../services/settings_service.dart' as settings; import '../../services/update_service.dart'; @@ -62,6 +63,7 @@ class _SettingsScreenState extends State 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 _kRequireProfileSelectionOnOpen = 'require_profile_selection_on_open'; static const _kPlayerBackend = 'player_backend'; static const _kHardwareDecoding = 'hardware_decoding'; static const _kMatchContentFrameRate = 'match_content_frame_rate'; @@ -109,6 +111,7 @@ class _SettingsScreenState extends State with FocusableTab { bool _enableDiscordRPC = false; bool _matchContentFrameRate = false; bool _useExoPlayer = true; // Android only: ExoPlayer vs MPV + bool _requireProfileSelectionOnOpen = false; // Update checking state bool _isCheckingForUpdate = false; @@ -175,6 +178,7 @@ class _SettingsScreenState extends State with FocusableTab { _enableDiscordRPC = _settingsService.getEnableDiscordRPC(); _matchContentFrameRate = _settingsService.getMatchContentFrameRate(); _useExoPlayer = _settingsService.getUseExoPlayer(); + _requireProfileSelectionOnOpen = _settingsService.getRequireProfileSelectionOnOpen(); _isLoading = false; }); } @@ -357,6 +361,22 @@ class _SettingsScreenState extends State with FocusableTab { ); }, ), + Consumer( + builder: (context, userProfileProvider, child) { + if (!userProfileProvider.hasMultipleUsers) return const SizedBox.shrink(); + return SwitchListTile( + focusNode: _focusTracker.get(_kRequireProfileSelectionOnOpen), + secondary: const AppIcon(Symbols.person_rounded, fill: 1), + title: Text(t.settings.requireProfileSelectionOnOpen), + subtitle: Text(t.settings.requireProfileSelectionOnOpenDescription), + value: _requireProfileSelectionOnOpen, + onChanged: (value) async { + setState(() => _requireProfileSelectionOnOpen = value); + await _settingsService.setRequireProfileSelectionOnOpen(value); + }, + ); + }, + ), ], ), ); diff --git a/lib/services/settings_service.dart b/lib/services/settings_service.dart index 97c3b6d3..3fd2b561 100644 --- a/lib/services/settings_service.dart +++ b/lib/services/settings_service.dart @@ -68,6 +68,7 @@ class SettingsService extends BaseSharedPreferencesService { static const String _keyAlwaysKeepSidebarOpen = 'always_keep_sidebar_open'; static const String _keyShowUnwatchedCount = 'show_unwatched_count'; static const String _keyGlobalShaderPreset = 'global_shader_preset'; + static const String _keyRequireProfileSelectionOnOpen = 'require_profile_selection_on_open'; SettingsService._(); @@ -1027,6 +1028,15 @@ class SettingsService extends BaseSharedPreferencesService { return prefs.getString(_keyGlobalShaderPreset) ?? 'none'; // Default: no shader } + // Require Profile Selection on App Open + Future setRequireProfileSelectionOnOpen(bool enabled) async { + await prefs.setBool(_keyRequireProfileSelectionOnOpen, enabled); + } + + bool getRequireProfileSelectionOnOpen() { + return prefs.getBool(_keyRequireProfileSelectionOnOpen) ?? false; + } + // Reset all settings to defaults Future resetAllSettings() async { await Future.wait([ @@ -1075,6 +1085,7 @@ class SettingsService extends BaseSharedPreferencesService { prefs.remove(_keyAlwaysKeepSidebarOpen), prefs.remove(_keyShowUnwatchedCount), prefs.remove(_keyGlobalShaderPreset), + prefs.remove(_keyRequireProfileSelectionOnOpen), ]); }