fix: idiot proof android tv login

This commit is contained in:
edde746
2026-01-26 03:15:56 +01:00
parent e88d9e0390
commit 1f8dccbba7
19 changed files with 211 additions and 147 deletions
+3 -2
View File
@@ -13,8 +13,9 @@
"plexTokenLabel": "Plex-Auth-Token",
"plexTokenHint": "Plex.tv-Token eingeben",
"authenticationTimeout": "Authentifizierung abgelaufen. Bitte erneut versuchen.",
"scanQRCodeInstruction": "Diesen QR-Code mit einem bei Plex angemeldeten Gerät scannen, um zu authentifizieren.",
"waitingForAuth": "Warte auf Authentifizierung...\nBitte Anmeldung im Browser abschließen."
"scanQRToSignIn": "QR-Code scannen zum Anmelden",
"waitingForAuth": "Warte auf Authentifizierung...\nBitte Anmeldung im Browser abschließen.",
"useBrowser": "Browser verwenden"
},
"common": {
"cancel": "Abbrechen",
+3 -2
View File
@@ -13,8 +13,9 @@
"plexTokenLabel": "Plex Auth Token",
"plexTokenHint": "Enter your Plex.tv token",
"authenticationTimeout": "Authentication timed out. Please try again.",
"scanQRCodeInstruction": "Scan this QR code with a device logged into Plex to authenticate.",
"waitingForAuth": "Waiting for authentication...\nPlease complete sign-in in your browser."
"scanQRToSignIn": "Scan this QR code to sign in",
"waitingForAuth": "Waiting for authentication...\nPlease complete sign-in in your browser.",
"useBrowser": "Use browser"
},
"common": {
"cancel": "Cancel",
+3 -2
View File
@@ -13,8 +13,9 @@
"plexTokenLabel": "Token d'authentification Plex",
"plexTokenHint": "Entrez votre token Plex.tv",
"authenticationTimeout": "Délai d'authentification expiré. Veuillez réessayer.",
"scanQRCodeInstruction": "Scannez ce code QR avec un appareil connecté à Plex pour vous authentifier.",
"waitingForAuth": "En attente d'authentification...\nVeuillez vous connecter dans votre navigateur."
"scanQRToSignIn": "Scannez ce QR code pour vous connecter",
"waitingForAuth": "En attente d'authentification...\nVeuillez vous connecter dans votre navigateur.",
"useBrowser": "Utiliser le navigateur"
},
"common": {
"cancel": "Annuler",
+3 -2
View File
@@ -13,8 +13,9 @@
"plexTokenLabel": "Token Auth Plex",
"plexTokenHint": "Inserisci il tuo token di Plex.tv",
"authenticationTimeout": "Autenticazione scaduta. Riprova.",
"scanQRCodeInstruction": "Scansiona questo QR code con un dispositivo connesso a Plex per autenticarti.",
"waitingForAuth": "In attesa di autenticazione...\nCompleta l'accesso dal tuo browser."
"scanQRToSignIn": "Scansiona il QR code per accedere",
"waitingForAuth": "In attesa di autenticazione...\nCompleta l'accesso dal tuo browser.",
"useBrowser": "Usa browser"
},
"common": {
"cancel": "Cancella",
+3 -2
View File
@@ -13,8 +13,9 @@
"plexTokenLabel": "Plex 인증 토큰",
"plexTokenHint": "Plex.tv 토큰을 입력하세요",
"authenticationTimeout": "인증 시간이 초과되었습니다. 다시 시도해 주세요.",
"scanQRCodeInstruction": "Plex 계정에 로그인된 기기에서 이 QR 코드를 스캔하여 본인 인증을 해주세요.",
"waitingForAuth": "인증 대기 중... 브라우저에서 로그인을 완료해 주세요."
"scanQRToSignIn": "QR 코드를 스캔하여 로그인",
"waitingForAuth": "인증 대기 중... 브라우저에서 로그인을 완료해 주세요.",
"useBrowser": "브라우저 사용"
},
"common": {
"cancel": "취소",
+3 -2
View File
@@ -13,8 +13,9 @@
"plexTokenLabel": "Plex Authenticatietoken",
"plexTokenHint": "Voer je Plex.tv token in",
"authenticationTimeout": "Authenticatie verlopen. Probeer opnieuw.",
"scanQRCodeInstruction": "Scan deze QR-code met een apparaat dat is ingelogd op Plex om te authenticeren.",
"waitingForAuth": "Wachten op authenticatie...\nVoltooi het inloggen in je browser."
"scanQRToSignIn": "Scan deze QR-code om in te loggen",
"waitingForAuth": "Wachten op authenticatie...\nVoltooi het inloggen in je browser.",
"useBrowser": "Gebruik browser"
},
"common": {
"cancel": "Annuleren",
+2 -2
View File
@@ -4,9 +4,9 @@
/// To regenerate, run: `dart run slang`
///
/// Locales: 8
/// Strings: 4436 (554 per locale)
/// Strings: 4444 (555 per locale)
///
/// Built on 2026-01-23 at 22:13 UTC
/// Built on 2026-01-26 at 02:10 UTC
// coverage:ignore-file
// ignore_for_file: type=lint, unused_import
+5 -3
View File
@@ -98,8 +98,9 @@ class _TranslationsAuthDe implements TranslationsAuthEn {
@override String get plexTokenLabel => 'Plex-Auth-Token';
@override String get plexTokenHint => 'Plex.tv-Token eingeben';
@override String get authenticationTimeout => 'Authentifizierung abgelaufen. Bitte erneut versuchen.';
@override String get scanQRCodeInstruction => 'Diesen QR-Code mit einem bei Plex angemeldeten Gerät scannen, um zu authentifizieren.';
@override String get scanQRToSignIn => 'QR-Code scannen zum Anmelden';
@override String get waitingForAuth => 'Warte auf Authentifizierung...\nBitte Anmeldung im Browser abschließen.';
@override String get useBrowser => 'Browser verwenden';
}
// Path: common
@@ -973,8 +974,9 @@ extension on TranslationsDe {
'auth.plexTokenLabel' => 'Plex-Auth-Token',
'auth.plexTokenHint' => 'Plex.tv-Token eingeben',
'auth.authenticationTimeout' => 'Authentifizierung abgelaufen. Bitte erneut versuchen.',
'auth.scanQRCodeInstruction' => 'Diesen QR-Code mit einem bei Plex angemeldeten Gerät scannen, um zu authentifizieren.',
'auth.scanQRToSignIn' => 'QR-Code scannen zum Anmelden',
'auth.waitingForAuth' => 'Warte auf Authentifizierung...\nBitte Anmeldung im Browser abschließen.',
'auth.useBrowser' => 'Browser verwenden',
'common.cancel' => 'Abbrechen',
'common.save' => 'Speichern',
'common.close' => 'Schließen',
@@ -1473,9 +1475,9 @@ extension on TranslationsDe {
'collections.removeFromCollectionConfirm' => ({required Object title}) => '"${title}" aus dieser Sammlung entfernen?',
'collections.removedFromCollection' => 'Aus Sammlung entfernt',
'collections.removeFromCollectionFailed' => 'Entfernen aus Sammlung fehlgeschlagen',
'collections.removeFromCollectionError' => ({required Object error}) => 'Fehler beim Entfernen aus der Sammlung: ${error}',
_ => null,
} ?? switch (path) {
'collections.removeFromCollectionError' => ({required Object error}) => 'Fehler beim Entfernen aus der Sammlung: ${error}',
'watchTogether.title' => 'Gemeinsam Schauen',
'watchTogether.description' => 'Inhalte synchron mit Freunden und Familie schauen',
'watchTogether.createSession' => 'Sitzung Erstellen',
+8 -4
View File
@@ -124,11 +124,14 @@ class TranslationsAuthEn {
/// en: 'Authentication timed out. Please try again.'
String get authenticationTimeout => 'Authentication timed out. Please try again.';
/// en: 'Scan this QR code with a device logged into Plex to authenticate.'
String get scanQRCodeInstruction => 'Scan this QR code with a device logged into Plex to authenticate.';
/// en: 'Scan this QR code to sign in'
String get scanQRToSignIn => 'Scan this QR code to sign in';
/// en: 'Waiting for authentication... Please complete sign-in in your browser.'
String get waitingForAuth => 'Waiting for authentication...\nPlease complete sign-in in your browser.';
/// en: 'Use browser'
String get useBrowser => 'Use browser';
}
// Path: common
@@ -2083,8 +2086,9 @@ extension on Translations {
'auth.plexTokenLabel' => 'Plex Auth Token',
'auth.plexTokenHint' => 'Enter your Plex.tv token',
'auth.authenticationTimeout' => 'Authentication timed out. Please try again.',
'auth.scanQRCodeInstruction' => 'Scan this QR code with a device logged into Plex to authenticate.',
'auth.scanQRToSignIn' => 'Scan this QR code to sign in',
'auth.waitingForAuth' => 'Waiting for authentication...\nPlease complete sign-in in your browser.',
'auth.useBrowser' => 'Use browser',
'common.cancel' => 'Cancel',
'common.save' => 'Save',
'common.close' => 'Close',
@@ -2583,9 +2587,9 @@ extension on Translations {
'watchTogether.sessionCode' => 'Session Code',
'watchTogether.hostControlsPlayback' => 'Host controls playback',
'watchTogether.anyoneCanControl' => 'Anyone can control playback',
'watchTogether.hostControls' => 'Host controls',
_ => null,
} ?? switch (path) {
'watchTogether.hostControls' => 'Host controls',
'watchTogether.anyoneControls' => 'Anyone controls',
'watchTogether.participants' => 'Participants',
'watchTogether.host' => 'Host',
+5 -3
View File
@@ -98,8 +98,9 @@ class _TranslationsAuthFr implements TranslationsAuthEn {
@override String get plexTokenLabel => 'Token d\'authentification Plex';
@override String get plexTokenHint => 'Entrez votre token Plex.tv';
@override String get authenticationTimeout => 'Délai d\'authentification expiré. Veuillez réessayer.';
@override String get scanQRCodeInstruction => 'Scannez ce code QR avec un appareil connecté à Plex pour vous authentifier.';
@override String get scanQRToSignIn => 'Scannez ce QR code pour vous connecter';
@override String get waitingForAuth => 'En attente d\'authentification...\nVeuillez vous connecter dans votre navigateur.';
@override String get useBrowser => 'Utiliser le navigateur';
}
// Path: common
@@ -971,8 +972,9 @@ extension on TranslationsFr {
'auth.plexTokenLabel' => 'Token d\'authentification Plex',
'auth.plexTokenHint' => 'Entrez votre token Plex.tv',
'auth.authenticationTimeout' => 'Délai d\'authentification expiré. Veuillez réessayer.',
'auth.scanQRCodeInstruction' => 'Scannez ce code QR avec un appareil connecté à Plex pour vous authentifier.',
'auth.scanQRToSignIn' => 'Scannez ce QR code pour vous connecter',
'auth.waitingForAuth' => 'En attente d\'authentification...\nVeuillez vous connecter dans votre navigateur.',
'auth.useBrowser' => 'Utiliser le navigateur',
'common.cancel' => 'Annuler',
'common.save' => 'Sauvegarder',
'common.close' => 'Fermer',
@@ -1471,9 +1473,9 @@ extension on TranslationsFr {
'watchTogether.sessionCode' => 'Code de session',
'watchTogether.hostControlsPlayback' => 'L\'hôte contrôle la lecture',
'watchTogether.anyoneCanControl' => 'Tout le monde peut contrôler la lecture',
'watchTogether.hostControls' => 'Commandes de l\'hôte',
_ => null,
} ?? switch (path) {
'watchTogether.hostControls' => 'Commandes de l\'hôte',
'watchTogether.anyoneControls' => 'Tout le monde contrôle',
'watchTogether.participants' => 'Participants',
'watchTogether.host' => 'Hôte',
+5 -3
View File
@@ -98,8 +98,9 @@ class _TranslationsAuthIt implements TranslationsAuthEn {
@override String get plexTokenLabel => 'Token Auth Plex';
@override String get plexTokenHint => 'Inserisci il tuo token di Plex.tv';
@override String get authenticationTimeout => 'Autenticazione scaduta. Riprova.';
@override String get scanQRCodeInstruction => 'Scansiona questo QR code con un dispositivo connesso a Plex per autenticarti.';
@override String get scanQRToSignIn => 'Scansiona il QR code per accedere';
@override String get waitingForAuth => 'In attesa di autenticazione...\nCompleta l\'accesso dal tuo browser.';
@override String get useBrowser => 'Usa browser';
}
// Path: common
@@ -973,8 +974,9 @@ extension on TranslationsIt {
'auth.plexTokenLabel' => 'Token Auth Plex',
'auth.plexTokenHint' => 'Inserisci il tuo token di Plex.tv',
'auth.authenticationTimeout' => 'Autenticazione scaduta. Riprova.',
'auth.scanQRCodeInstruction' => 'Scansiona questo QR code con un dispositivo connesso a Plex per autenticarti.',
'auth.scanQRToSignIn' => 'Scansiona il QR code per accedere',
'auth.waitingForAuth' => 'In attesa di autenticazione...\nCompleta l\'accesso dal tuo browser.',
'auth.useBrowser' => 'Usa browser',
'common.cancel' => 'Cancella',
'common.save' => 'Salva',
'common.close' => 'Chiudi',
@@ -1473,9 +1475,9 @@ extension on TranslationsIt {
'collections.removeFromCollectionConfirm' => ({required Object title}) => 'Rimuovere "${title}" da questa raccolta?',
'collections.removedFromCollection' => 'Rimosso dalla raccolta',
'collections.removeFromCollectionFailed' => 'Impossibile rimuovere dalla raccolta',
'collections.removeFromCollectionError' => ({required Object error}) => 'Errore durante la rimozione dalla raccolta: ${error}',
_ => null,
} ?? switch (path) {
'collections.removeFromCollectionError' => ({required Object error}) => 'Errore durante la rimozione dalla raccolta: ${error}',
'watchTogether.title' => 'Guarda Insieme',
'watchTogether.description' => 'Guarda contenuti in sincronia con amici e familiari',
'watchTogether.createSession' => 'Crea Sessione',
+5 -3
View File
@@ -98,8 +98,9 @@ class _TranslationsAuthKo implements TranslationsAuthEn {
@override String get plexTokenLabel => 'Plex 인증 토큰';
@override String get plexTokenHint => 'Plex.tv 토큰을 입력하세요';
@override String get authenticationTimeout => '인증 시간이 초과되었습니다. 다시 시도해 주세요.';
@override String get scanQRCodeInstruction => 'Plex 계정에 로그인된 기기에서 이 QR 코드를 스캔하여 본인 인증을 해주세요.';
@override String get scanQRToSignIn => 'QR 코드를 스캔하여 로그인';
@override String get waitingForAuth => '인증 대기 중... 브라우저에서 로그인을 완료해 주세요.';
@override String get useBrowser => '브라우저 사용';
}
// Path: common
@@ -973,8 +974,9 @@ extension on TranslationsKo {
'auth.plexTokenLabel' => 'Plex 인증 토큰',
'auth.plexTokenHint' => 'Plex.tv 토큰을 입력하세요',
'auth.authenticationTimeout' => '인증 시간이 초과되었습니다. 다시 시도해 주세요.',
'auth.scanQRCodeInstruction' => 'Plex 계정에 로그인된 기기에서 이 QR 코드를 스캔하여 본인 인증을 해주세요.',
'auth.scanQRToSignIn' => 'QR 코드를 스캔하여 로그인',
'auth.waitingForAuth' => '인증 대기 중... 브라우저에서 로그인을 완료해 주세요.',
'auth.useBrowser' => '브라우저 사용',
'common.cancel' => '취소',
'common.save' => '저장',
'common.close' => '닫기',
@@ -1473,9 +1475,9 @@ extension on TranslationsKo {
'watchTogether.hostingSession' => '세션 호스팅',
'watchTogether.inSession' => '세션 중',
'watchTogether.sessionCode' => '세션 코드',
'watchTogether.hostControlsPlayback' => '호스트 재생 제어',
_ => null,
} ?? switch (path) {
'watchTogether.hostControlsPlayback' => '호스트 재생 제어',
'watchTogether.anyoneCanControl' => '누구나 재생 제어 가능',
'watchTogether.hostControls' => '호스트 제어',
'watchTogether.anyoneControls' => '누구나 제어',
+5 -3
View File
@@ -98,8 +98,9 @@ class _TranslationsAuthNl implements TranslationsAuthEn {
@override String get plexTokenLabel => 'Plex Authenticatietoken';
@override String get plexTokenHint => 'Voer je Plex.tv token in';
@override String get authenticationTimeout => 'Authenticatie verlopen. Probeer opnieuw.';
@override String get scanQRCodeInstruction => 'Scan deze QR-code met een apparaat dat is ingelogd op Plex om te authenticeren.';
@override String get scanQRToSignIn => 'Scan deze QR-code om in te loggen';
@override String get waitingForAuth => 'Wachten op authenticatie...\nVoltooi het inloggen in je browser.';
@override String get useBrowser => 'Gebruik browser';
}
// Path: common
@@ -973,8 +974,9 @@ extension on TranslationsNl {
'auth.plexTokenLabel' => 'Plex Authenticatietoken',
'auth.plexTokenHint' => 'Voer je Plex.tv token in',
'auth.authenticationTimeout' => 'Authenticatie verlopen. Probeer opnieuw.',
'auth.scanQRCodeInstruction' => 'Scan deze QR-code met een apparaat dat is ingelogd op Plex om te authenticeren.',
'auth.scanQRToSignIn' => 'Scan deze QR-code om in te loggen',
'auth.waitingForAuth' => 'Wachten op authenticatie...\nVoltooi het inloggen in je browser.',
'auth.useBrowser' => 'Gebruik browser',
'common.cancel' => 'Annuleren',
'common.save' => 'Opslaan',
'common.close' => 'Sluiten',
@@ -1473,9 +1475,9 @@ extension on TranslationsNl {
'collections.removeFromCollectionConfirm' => ({required Object title}) => '"${title}" uit deze collectie verwijderen?',
'collections.removedFromCollection' => 'Uit collectie verwijderd',
'collections.removeFromCollectionFailed' => 'Verwijderen uit collectie mislukt',
'collections.removeFromCollectionError' => ({required Object error}) => 'Fout bij verwijderen uit collectie: ${error}',
_ => null,
} ?? switch (path) {
'collections.removeFromCollectionError' => ({required Object error}) => 'Fout bij verwijderen uit collectie: ${error}',
'watchTogether.title' => 'Samen Kijken',
'watchTogether.description' => 'Kijk synchroon met vrienden en familie',
'watchTogether.createSession' => 'Sessie Maken',
+5 -3
View File
@@ -98,8 +98,9 @@ class _TranslationsAuthSv implements TranslationsAuthEn {
@override String get plexTokenLabel => 'Plex-autentiseringstoken';
@override String get plexTokenHint => 'Ange din Plex.tv-token';
@override String get authenticationTimeout => 'Autentisering tog för lång tid. Försök igen.';
@override String get scanQRCodeInstruction => 'Skanna denna QR-kod med en enhet inloggad på Plex för att autentisera.';
@override String get scanQRToSignIn => 'Skanna QR-koden för att logga in';
@override String get waitingForAuth => 'Väntar på autentisering...\nVänligen slutför inloggning i din webbläsare.';
@override String get useBrowser => 'Använd webbläsare';
}
// Path: common
@@ -973,8 +974,9 @@ extension on TranslationsSv {
'auth.plexTokenLabel' => 'Plex-autentiseringstoken',
'auth.plexTokenHint' => 'Ange din Plex.tv-token',
'auth.authenticationTimeout' => 'Autentisering tog för lång tid. Försök igen.',
'auth.scanQRCodeInstruction' => 'Skanna denna QR-kod med en enhet inloggad på Plex för att autentisera.',
'auth.scanQRToSignIn' => 'Skanna QR-koden för att logga in',
'auth.waitingForAuth' => 'Väntar på autentisering...\nVänligen slutför inloggning i din webbläsare.',
'auth.useBrowser' => 'Använd webbläsare',
'common.cancel' => 'Avbryt',
'common.save' => 'Spara',
'common.close' => 'Stäng',
@@ -1473,9 +1475,9 @@ extension on TranslationsSv {
'collections.removeFromCollectionConfirm' => ({required Object title}) => 'Ta bort "${title}" från denna samling?',
'collections.removedFromCollection' => 'Borttagen från samling',
'collections.removeFromCollectionFailed' => 'Misslyckades med att ta bort från samling',
'collections.removeFromCollectionError' => ({required Object error}) => 'Fel vid borttagning från samling: ${error}',
_ => null,
} ?? switch (path) {
'collections.removeFromCollectionError' => ({required Object error}) => 'Fel vid borttagning från samling: ${error}',
'watchTogether.title' => 'Titta Tillsammans',
'watchTogether.description' => 'Titta på innehåll synkroniserat med vänner och familj',
'watchTogether.createSession' => 'Skapa Session',
+5 -3
View File
@@ -98,8 +98,9 @@ class _TranslationsAuthZh implements TranslationsAuthEn {
@override String get plexTokenLabel => 'Plex 授权令牌 (Auth Token)';
@override String get plexTokenHint => '输入你的 Plex.tv 令牌';
@override String get authenticationTimeout => '验证超时。请重试。';
@override String get scanQRCodeInstruction => '请使用已登录 Plex 的设备扫描二维码进行验证。';
@override String get scanQRToSignIn => '扫描二维码登录';
@override String get waitingForAuth => '等待验证中...\n请在你的浏览器中完成登录。';
@override String get useBrowser => '使用浏览器';
}
// Path: common
@@ -973,8 +974,9 @@ extension on TranslationsZh {
'auth.plexTokenLabel' => 'Plex 授权令牌 (Auth Token)',
'auth.plexTokenHint' => '输入你的 Plex.tv 令牌',
'auth.authenticationTimeout' => '验证超时。请重试。',
'auth.scanQRCodeInstruction' => '请使用已登录 Plex 的设备扫描二维码进行验证。',
'auth.scanQRToSignIn' => '扫描二维码登录',
'auth.waitingForAuth' => '等待验证中...\n请在你的浏览器中完成登录。',
'auth.useBrowser' => '使用浏览器',
'common.cancel' => '取消',
'common.save' => '保存',
'common.close' => '关闭',
@@ -1473,9 +1475,9 @@ extension on TranslationsZh {
'collections.removeFromCollectionConfirm' => ({required Object title}) => '将“${title}”从此合集移除?',
'collections.removedFromCollection' => '已从合集移除',
'collections.removeFromCollectionFailed' => '从合集移除失败',
'collections.removeFromCollectionError' => ({required Object error}) => '从合集移除时出错:${error}',
_ => null,
} ?? switch (path) {
'collections.removeFromCollectionError' => ({required Object error}) => '从合集移除时出错:${error}',
'watchTogether.title' => '一起看',
'watchTogether.description' => '与朋友和家人同步观看内容',
'watchTogether.createSession' => '创建会话',
+3 -2
View File
@@ -13,8 +13,9 @@
"plexTokenLabel": "Plex-autentiseringstoken",
"plexTokenHint": "Ange din Plex.tv-token",
"authenticationTimeout": "Autentisering tog för lång tid. Försök igen.",
"scanQRCodeInstruction": "Skanna denna QR-kod med en enhet inloggad på Plex för att autentisera.",
"waitingForAuth": "Väntar på autentisering...\nVänligen slutför inloggning i din webbläsare."
"scanQRToSignIn": "Skanna QR-koden för att logga in",
"waitingForAuth": "Väntar på autentisering...\nVänligen slutför inloggning i din webbläsare.",
"useBrowser": "Använd webbläsare"
},
"common": {
"cancel": "Avbryt",
+3 -2
View File
@@ -13,8 +13,9 @@
"plexTokenLabel": "Plex 授权令牌 (Auth Token)",
"plexTokenHint": "输入你的 Plex.tv 令牌",
"authenticationTimeout": "验证超时。请重试。",
"scanQRCodeInstruction": "请使用已登录 Plex 的设备扫描二维码进行验证。",
"waitingForAuth": "等待验证中...\n请在你的浏览器中完成登录。"
"scanQRToSignIn": "扫描二维码登录",
"waitingForAuth": "等待验证中...\n请在你的浏览器中完成登录。",
"useBrowser": "使用浏览器"
},
"common": {
"cancel": "取消",
+141 -103
View File
@@ -14,6 +14,7 @@ import '../services/offline_watch_sync_service.dart';
import '../i18n/strings.g.dart';
import '../theme/mono_tokens.dart';
import '../utils/app_logger.dart';
import '../utils/platform_detector.dart';
import 'main_screen.dart';
class AuthScreen extends StatefulWidget {
@@ -39,6 +40,14 @@ class _AuthScreenState extends State<AuthScreen> {
Future<void> _initializeAuthService() async {
_authService = await PlexAuthService.create();
// On Android TV, auto-start QR code flow
if (PlatformDetector.isTV()) {
setState(() {
_useQrFlow = true;
});
_startAuthentication();
}
}
/// Connect to all available servers and navigate to main screen
@@ -325,120 +334,122 @@ class _AuthScreenState extends State<AuthScreen> {
const SizedBox(width: 48),
// Second column - All authentication content
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (_isAuthenticating) ...[
if (_useQrFlow && _qrAuthUrl != null)
_buildQrAuthWidget(qrSize: 300)
else
_buildBrowserAuthWidget(),
] else ...[
// Initial state buttons
ElevatedButton(
onPressed: _startAuthentication,
style: ElevatedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 16)),
child: Text(t.auth.signInWithPlex),
),
const SizedBox(height: 12),
OutlinedButton(
onPressed: () {
setState(() {
_useQrFlow = true;
});
_startAuthentication();
},
style: OutlinedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 16)),
child: Text(t.auth.showQRCode),
),
if (kDebugMode) ...[
const SizedBox(height: 12),
OutlinedButton(
onPressed: _handleDebugTap,
style: OutlinedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 12),
side: BorderSide(color: Theme.of(context).colorScheme.outline.withValues(alpha: 0.5)),
),
child: Text(t.auth.debugEnterToken, style: TextStyle(fontSize: 12)),
),
child: Center(
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (_isAuthenticating) ...[
if (_useQrFlow && _qrAuthUrl != null)
_buildQrAuthWidget(qrSize: 300)
else
_buildBrowserAuthWidget(),
] else
_buildInitialButtons(),
],
if (_errorMessage != null) ...[
const SizedBox(height: 16),
Text(
_errorMessage!,
style: TextStyle(color: Theme.of(context).colorScheme.error),
textAlign: TextAlign.center,
),
],
],
],
),
),
),
),
],
)
: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Image.asset('assets/plezy.png', width: 120, height: 120),
const SizedBox(height: 24),
Text(
t.app.title,
style: Theme.of(context).textTheme.headlineMedium?.copyWith(fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
const SizedBox(height: 48),
if (_isAuthenticating) ...[
if (_useQrFlow && _qrAuthUrl != null)
_buildQrAuthWidget(qrSize: 200)
else
_buildBrowserAuthWidget(),
] else ...[
// add QR button here
ElevatedButton(
onPressed: _startAuthentication,
style: ElevatedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 16)),
child: Text(t.auth.signInWithPlex),
: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Image.asset('assets/plezy.png', width: 120, height: 120),
const SizedBox(height: 24),
Text(
t.app.title,
style: Theme.of(context).textTheme.headlineMedium?.copyWith(fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
const SizedBox(height: 12),
OutlinedButton(
onPressed: () {
setState(() {
_useQrFlow = true;
});
_startAuthentication();
},
style: OutlinedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 16)),
child: Text(t.auth.showQRCode),
),
if (kDebugMode) ...[
const SizedBox(height: 12),
OutlinedButton(
onPressed: _handleDebugTap,
style: OutlinedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 12),
side: BorderSide(color: Theme.of(context).colorScheme.outline.withValues(alpha: 0.5)),
),
child: Text(t.auth.debugEnterToken, style: TextStyle(fontSize: 12)),
),
],
if (_errorMessage != null) ...[
const SizedBox(height: 16),
Text(
_errorMessage!,
style: TextStyle(color: Theme.of(context).colorScheme.error),
textAlign: TextAlign.center,
),
],
const SizedBox(height: 48),
if (_isAuthenticating) ...[
if (_useQrFlow && _qrAuthUrl != null)
_buildQrAuthWidget(qrSize: 200)
else
_buildBrowserAuthWidget(),
] else
_buildInitialButtons(),
],
],
),
),
),
),
);
}
/// Builds the initial authentication buttons (before auth starts)
Widget _buildInitialButtons() {
final isTV = PlatformDetector.isTV();
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (isTV) ...[
// On TV: QR is primary, browser is secondary
ElevatedButton(
autofocus: true,
onPressed: () {
setState(() {
_useQrFlow = true;
});
_startAuthentication();
},
style: ElevatedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 16)),
child: Text(t.auth.showQRCode),
),
const SizedBox(height: 12),
OutlinedButton(
onPressed: _startAuthentication,
style: OutlinedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 16)),
child: Text(t.auth.useBrowser),
),
] else ...[
// On other platforms: Browser is primary, QR is secondary
ElevatedButton(
onPressed: _startAuthentication,
style: ElevatedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 16)),
child: Text(t.auth.signInWithPlex),
),
const SizedBox(height: 12),
OutlinedButton(
onPressed: () {
setState(() {
_useQrFlow = true;
});
_startAuthentication();
},
style: OutlinedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 16)),
child: Text(t.auth.showQRCode),
),
],
if (kDebugMode) ...[
const SizedBox(height: 12),
OutlinedButton(
onPressed: _handleDebugTap,
style: OutlinedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 12),
side: BorderSide(color: Theme.of(context).colorScheme.outline.withValues(alpha: 0.5)),
),
child: Text(t.auth.debugEnterToken, style: TextStyle(fontSize: 12)),
),
],
if (_errorMessage != null) ...[
const SizedBox(height: 16),
Text(
_errorMessage!,
style: TextStyle(color: Theme.of(context).colorScheme.error),
textAlign: TextAlign.center,
),
],
],
);
}
Widget _buildRetryButton() {
return Column(
mainAxisSize: MainAxisSize.min,
@@ -455,11 +466,12 @@ class _AuthScreenState extends State<AuthScreen> {
/// Builds the QR code authentication widget
Widget _buildQrAuthWidget({required double qrSize}) {
final isTV = PlatformDetector.isTV();
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
t.auth.scanQRCodeInstruction,
t.auth.scanQRToSignIn,
textAlign: TextAlign.center,
style: const TextStyle(color: Colors.grey),
),
@@ -475,7 +487,33 @@ class _AuthScreenState extends State<AuthScreen> {
),
),
),
_buildRetryButton(),
// On TV, show retry and browser buttons in a row
if (isTV) ...[
const SizedBox(height: 24),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
OutlinedButton(
autofocus: true,
onPressed: _retryAuthentication,
style: OutlinedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 24)),
child: Text(t.auth.retry),
),
const SizedBox(width: 16),
OutlinedButton(
onPressed: () {
setState(() {
_useQrFlow = false;
});
_startAuthentication();
},
style: OutlinedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 24)),
child: Text(t.auth.useBrowser),
),
],
),
] else
_buildRetryButton(),
],
);
}
+1 -1
View File
@@ -1,7 +1,7 @@
name: plezy
description: "A beautiful Plex client for Flutter"
publish_to: "none"
version: 1.15.0+32
version: 1.15.1+33
environment:
sdk: ^3.8.1