diff --git a/lib/l10n/app_bg.arb b/lib/l10n/app_bg.arb index c17f117..30a2c1b 100644 --- a/lib/l10n/app_bg.arb +++ b/lib/l10n/app_bg.arb @@ -821,6 +821,8 @@ } } }, + "login_failedMessage": "Входът не беше успешен. Или паролата е грешна, или повторителят е недостъпен.", + "common_reload": "Презареди", "common_clear": "Изчисти", "path_currentPath": "Текущ път: {path}", diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 6c79f2d..b6de02a 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -821,6 +821,8 @@ } } }, + "login_failedMessage": "Anmeldung fehlgeschlagen. Entweder ist das Passwort falsch oder der Repeater ist nicht erreichbar.", + "common_reload": "Neu laden", "common_clear": "Löschen", "path_currentPath": "Aktiger Pfad: {path}", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 8a647b4..203f64f 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -723,6 +723,8 @@ "error": {"type": "String"} } }, + "login_failedMessage": "Login failed. Either the password is incorrect or the repeater is unreachable.", + "common_reload": "Reload", "common_clear": "Clear", diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 5a2672e..b23cfce 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -821,6 +821,8 @@ } } }, + "login_failedMessage": "Inicio fallido. La contraseña es incorrecta o el repetidor no está disponible.", + "common_reload": "Recargar", "common_clear": "Borrar", "path_currentPath": "Ruta actual: {path}", diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index 60ac827..0e7b952 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -821,6 +821,8 @@ } } }, + "login_failedMessage": "Connexion échouée. Soit le mot de passe est incorrect, soit le relais est injoignable.", + "common_reload": "Recharger", "common_clear": "Effacer", "path_currentPath": "Chemin actuel : {path}", diff --git a/lib/l10n/app_it.arb b/lib/l10n/app_it.arb index 08163c6..b77450f 100644 --- a/lib/l10n/app_it.arb +++ b/lib/l10n/app_it.arb @@ -821,6 +821,8 @@ } } }, + "login_failedMessage": "Accesso fallito. La password non è corretta oppure il ripetitore non è raggiungibile.", + "common_reload": "Ricaricare", "common_clear": "Cancella", "path_currentPath": "Percorso corrente: {path}", diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index e0c1f8e..bedd407 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -2759,6 +2759,12 @@ abstract class AppLocalizations { /// **'Login failed: {error}'** String login_failed(String error); + /// No description provided for @login_failedMessage. + /// + /// In en, this message translates to: + /// **'Login failed. Either the password is incorrect or the repeater is unreachable.'** + String get login_failedMessage; + /// No description provided for @common_reload. /// /// In en, this message translates to: diff --git a/lib/l10n/app_localizations_bg.dart b/lib/l10n/app_localizations_bg.dart index 019566a..cf2b35c 100644 --- a/lib/l10n/app_localizations_bg.dart +++ b/lib/l10n/app_localizations_bg.dart @@ -1514,6 +1514,10 @@ class AppLocalizationsBg extends AppLocalizations { return 'Входът не беше успешен: $error'; } + @override + String get login_failedMessage => + 'Входът не беше успешен. Или паролата е грешна, или повторителят е недостъпен.'; + @override String get common_reload => 'Презареди'; diff --git a/lib/l10n/app_localizations_de.dart b/lib/l10n/app_localizations_de.dart index 1ae2fb4..7c3fc93 100644 --- a/lib/l10n/app_localizations_de.dart +++ b/lib/l10n/app_localizations_de.dart @@ -1516,6 +1516,10 @@ class AppLocalizationsDe extends AppLocalizations { return 'Anmeldung fehlgeschlagen: $error'; } + @override + String get login_failedMessage => + 'Anmeldung fehlgeschlagen. Entweder ist das Passwort falsch oder der Repeater ist nicht erreichbar.'; + @override String get common_reload => 'Neu laden'; diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index a98546e..b8c4f90 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -1490,6 +1490,10 @@ class AppLocalizationsEn extends AppLocalizations { return 'Login failed: $error'; } + @override + String get login_failedMessage => + 'Login failed. Either the password is incorrect or the repeater is unreachable.'; + @override String get common_reload => 'Reload'; diff --git a/lib/l10n/app_localizations_es.dart b/lib/l10n/app_localizations_es.dart index aa3926e..21aad2c 100644 --- a/lib/l10n/app_localizations_es.dart +++ b/lib/l10n/app_localizations_es.dart @@ -1512,6 +1512,10 @@ class AppLocalizationsEs extends AppLocalizations { return 'Inicio fallido: $error'; } + @override + String get login_failedMessage => + 'Inicio fallido. La contraseña es incorrecta o el repetidor no está disponible.'; + @override String get common_reload => 'Recargar'; diff --git a/lib/l10n/app_localizations_fr.dart b/lib/l10n/app_localizations_fr.dart index f8e89cc..21f63b5 100644 --- a/lib/l10n/app_localizations_fr.dart +++ b/lib/l10n/app_localizations_fr.dart @@ -1518,6 +1518,10 @@ class AppLocalizationsFr extends AppLocalizations { return 'Connexion échouée : $error'; } + @override + String get login_failedMessage => + 'Connexion échouée. Soit le mot de passe est incorrect, soit le relais est injoignable.'; + @override String get common_reload => 'Recharger'; diff --git a/lib/l10n/app_localizations_it.dart b/lib/l10n/app_localizations_it.dart index 1b15148..1cc567c 100644 --- a/lib/l10n/app_localizations_it.dart +++ b/lib/l10n/app_localizations_it.dart @@ -1510,6 +1510,10 @@ class AppLocalizationsIt extends AppLocalizations { return 'Accesso fallito: $error'; } + @override + String get login_failedMessage => + 'Accesso fallito. La password non è corretta oppure il ripetitore non è raggiungibile.'; + @override String get common_reload => 'Ricaricare'; diff --git a/lib/l10n/app_localizations_nl.dart b/lib/l10n/app_localizations_nl.dart index 0d9f807..db1f68e 100644 --- a/lib/l10n/app_localizations_nl.dart +++ b/lib/l10n/app_localizations_nl.dart @@ -1506,6 +1506,10 @@ class AppLocalizationsNl extends AppLocalizations { return 'Inloggen mislukt: $error'; } + @override + String get login_failedMessage => + 'Inloggen mislukt. Het wachtwoord is onjuist of de repeater is niet bereikbaar.'; + @override String get common_reload => 'Opnieuw laden'; diff --git a/lib/l10n/app_localizations_pl.dart b/lib/l10n/app_localizations_pl.dart index 6626308..e4373d1 100644 --- a/lib/l10n/app_localizations_pl.dart +++ b/lib/l10n/app_localizations_pl.dart @@ -1514,6 +1514,10 @@ class AppLocalizationsPl extends AppLocalizations { return 'Zalogowanie się nie powiodło: $error'; } + @override + String get login_failedMessage => + 'Logowanie nie powiodło się. Hasło jest nieprawidłowe albo repeater jest nieosiągalny.'; + @override String get common_reload => 'Ponownie załadować'; diff --git a/lib/l10n/app_localizations_pt.dart b/lib/l10n/app_localizations_pt.dart index 614ff0d..2aaa940 100644 --- a/lib/l10n/app_localizations_pt.dart +++ b/lib/l10n/app_localizations_pt.dart @@ -1512,6 +1512,10 @@ class AppLocalizationsPt extends AppLocalizations { return 'Login falhou: $error'; } + @override + String get login_failedMessage => + 'Falha no login. A senha está incorreta ou o repetidor está inacessível.'; + @override String get common_reload => 'Recarregar'; diff --git a/lib/l10n/app_localizations_sk.dart b/lib/l10n/app_localizations_sk.dart index e3747f2..ffd327a 100644 --- a/lib/l10n/app_localizations_sk.dart +++ b/lib/l10n/app_localizations_sk.dart @@ -1507,6 +1507,10 @@ class AppLocalizationsSk extends AppLocalizations { return 'Prihlásenie zlyhalo: $error'; } + @override + String get login_failedMessage => + 'Prihlásenie zlyhalo. Heslo je nesprávne alebo je opakovač nedostupný.'; + @override String get common_reload => 'Načítať'; diff --git a/lib/l10n/app_localizations_sl.dart b/lib/l10n/app_localizations_sl.dart index 4d2ad7f..994b7fa 100644 --- a/lib/l10n/app_localizations_sl.dart +++ b/lib/l10n/app_localizations_sl.dart @@ -1508,6 +1508,10 @@ class AppLocalizationsSl extends AppLocalizations { return 'Prijava je bila neuspešna: $error'; } + @override + String get login_failedMessage => + 'Prijava je bila neuspešna. Geslo je napačno ali pa je repetitor nedosegljiv.'; + @override String get common_reload => 'Ponovno naloži'; diff --git a/lib/l10n/app_localizations_sv.dart b/lib/l10n/app_localizations_sv.dart index d170b4a..a4765a9 100644 --- a/lib/l10n/app_localizations_sv.dart +++ b/lib/l10n/app_localizations_sv.dart @@ -1497,6 +1497,10 @@ class AppLocalizationsSv extends AppLocalizations { return 'Inloggning misslyckades: $error'; } + @override + String get login_failedMessage => + 'Inloggning misslyckades. Antingen är lösenordet fel eller så går det inte att nå repeatern.'; + @override String get common_reload => 'Ladda om'; diff --git a/lib/l10n/app_localizations_zh.dart b/lib/l10n/app_localizations_zh.dart index 7d02bf5..99f4e90 100644 --- a/lib/l10n/app_localizations_zh.dart +++ b/lib/l10n/app_localizations_zh.dart @@ -1447,6 +1447,9 @@ class AppLocalizationsZh extends AppLocalizations { return '登录失败:$error'; } + @override + String get login_failedMessage => '登录失败。密码不正确或中继器不可达。'; + @override String get common_reload => '重新加载'; diff --git a/lib/l10n/app_nl.arb b/lib/l10n/app_nl.arb index f78fc68..b7e1a35 100644 --- a/lib/l10n/app_nl.arb +++ b/lib/l10n/app_nl.arb @@ -821,6 +821,8 @@ } } }, + "login_failedMessage": "Inloggen mislukt. Het wachtwoord is onjuist of de repeater is niet bereikbaar.", + "common_reload": "Opnieuw laden", "common_clear": "Schoonmaken", "path_currentPath": "Huidige pad: {path}", diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb index 24edcaf..56fe869 100644 --- a/lib/l10n/app_pl.arb +++ b/lib/l10n/app_pl.arb @@ -821,6 +821,8 @@ } } }, + "login_failedMessage": "Logowanie nie powiodło się. Hasło jest nieprawidłowe albo repeater jest nieosiągalny.", + "common_reload": "Ponownie załadować", "common_clear": "Wyczyść", "path_currentPath": "Aktualny ścieżka: {path}", diff --git a/lib/l10n/app_pt.arb b/lib/l10n/app_pt.arb index 47f9cef..99da374 100644 --- a/lib/l10n/app_pt.arb +++ b/lib/l10n/app_pt.arb @@ -821,6 +821,8 @@ } } }, + "login_failedMessage": "Falha no login. A senha está incorreta ou o repetidor está inacessível.", + "common_reload": "Recarregar", "common_clear": "Limpar", "path_currentPath": "Caminho atual: {path}", diff --git a/lib/l10n/app_sk.arb b/lib/l10n/app_sk.arb index 752c8d4..1ffb197 100644 --- a/lib/l10n/app_sk.arb +++ b/lib/l10n/app_sk.arb @@ -821,6 +821,8 @@ } } }, + "login_failedMessage": "Prihlásenie zlyhalo. Heslo je nesprávne alebo je opakovač nedostupný.", + "common_reload": "Načítať", "common_clear": "Zmazať", "path_currentPath": "Aktívna cesta: {path}", diff --git a/lib/l10n/app_sl.arb b/lib/l10n/app_sl.arb index 3e40f2d..bac8b2b 100644 --- a/lib/l10n/app_sl.arb +++ b/lib/l10n/app_sl.arb @@ -821,6 +821,8 @@ } } }, + "login_failedMessage": "Prijava je bila neuspešna. Geslo je napačno ali pa je repetitor nedosegljiv.", + "common_reload": "Ponovno naloži", "common_clear": "Ponoviti", "path_currentPath": "Trenutna pot: {path}", diff --git a/lib/l10n/app_sv.arb b/lib/l10n/app_sv.arb index 35ec92b..3c8d470 100644 --- a/lib/l10n/app_sv.arb +++ b/lib/l10n/app_sv.arb @@ -821,6 +821,8 @@ } } }, + "login_failedMessage": "Inloggning misslyckades. Antingen är lösenordet fel eller så går det inte att nå repeatern.", + "common_reload": "Ladda om", "common_clear": "Rensa", "path_currentPath": "Nuvarande sökväg: {path}", diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 33cd517..fc5ac55 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -821,6 +821,8 @@ } } }, + "login_failedMessage": "登录失败。密码不正确或中继器不可达。", + "common_reload": "重新加载", "common_clear": "清除", "path_currentPath": "当前路径:{path}", diff --git a/lib/widgets/repeater_login_dialog.dart b/lib/widgets/repeater_login_dialog.dart index f4129cd..54c0150 100644 --- a/lib/widgets/repeater_login_dialog.dart +++ b/lib/widgets/repeater_login_dialog.dart @@ -31,6 +31,7 @@ class _RepeaterLoginDialogState extends State { bool _savePassword = false; bool _isLoading = true; bool _obscurePassword = true; + String? _loginError; late MeshCoreConnector _connector; int _currentAttempt = 0; static const int _maxAttempts = 5; @@ -79,6 +80,7 @@ class _RepeaterLoginDialogState extends State { setState(() { _isLoggingIn = true; _currentAttempt = 0; + _loginError = null; }); try { @@ -134,7 +136,7 @@ class _RepeaterLoginDialogState extends State { 'Login failed for ${repeater.name}', tag: 'RepeaterLogin', ); - throw Exception('Wrong password or node is unreachable'); + break; } appLogger.warn( 'Login attempt ${attempt + 1} timed out after ${timeoutSeconds}s', @@ -156,7 +158,13 @@ class _RepeaterLoginDialogState extends State { } if (loginResult != true) { - throw Exception('Wrong password or node is unreachable'); + if (mounted) { + setState(() { + _isLoggingIn = false; + _loginError = context.l10n.login_failedMessage; + }); + } + return; } // If we got a response, login succeeded @@ -182,13 +190,8 @@ class _RepeaterLoginDialogState extends State { if (mounted) { setState(() { _isLoggingIn = false; + _loginError = context.l10n.login_failedMessage; }); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(context.l10n.login_failed(e.toString())), - backgroundColor: Colors.red, - ), - ); } } } @@ -271,6 +274,25 @@ class _RepeaterLoginDialogState extends State { style: const TextStyle(fontSize: 14), ), const SizedBox(height: 16), + if (_loginError != null) ...[ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Icon(Icons.error, size: 18, color: Theme.of(context).colorScheme.error), + const SizedBox(width: 8), + Expanded( + child: Text( + _loginError!, + style: TextStyle( + color: Theme.of(context).colorScheme.error, + fontSize: 13, + ), + ), + ), + ], + ), + const SizedBox(height: 12), + ], TextField( controller: _passwordController, obscureText: _obscurePassword, @@ -292,6 +314,13 @@ class _RepeaterLoginDialogState extends State { }, ), ), + onChanged: (_) { + if (_loginError != null && mounted) { + setState(() { + _loginError = null; + }); + } + }, onSubmitted: (_) => _handleLogin(), autofocus: _passwordController.text.isEmpty, ),