From 153736d36e2f6f375f871f7324df31ebd1b2513b Mon Sep 17 00:00:00 2001 From: Winston Lowe Date: Sun, 18 Jan 2026 21:21:33 -0800 Subject: [PATCH 1/2] added roomserver management --- lib/l10n/app_bg.arb | 5 +- lib/l10n/app_de.arb | 5 +- lib/l10n/app_en.arb | 6 +- lib/l10n/app_es.arb | 5 +- lib/l10n/app_fr.arb | 5 +- lib/l10n/app_it.arb | 5 +- lib/l10n/app_localizations.dart | 16 +- lib/l10n/app_localizations_bg.dart | 6 + lib/l10n/app_localizations_de.dart | 6 + lib/l10n/app_localizations_en.dart | 10 +- lib/l10n/app_localizations_es.dart | 6 + lib/l10n/app_localizations_fr.dart | 6 + lib/l10n/app_localizations_it.dart | 6 + lib/l10n/app_localizations_nl.dart | 6 + lib/l10n/app_localizations_pl.dart | 6 + lib/l10n/app_localizations_pt.dart | 6 + lib/l10n/app_localizations_sk.dart | 6 + lib/l10n/app_localizations_sl.dart | 6 + lib/l10n/app_localizations_sv.dart | 6 + lib/l10n/app_localizations_zh.dart | 6 + lib/l10n/app_nl.arb | 5 +- lib/l10n/app_pl.arb | 5 +- lib/l10n/app_pt.arb | 5 +- lib/l10n/app_sk.arb | 5 +- lib/l10n/app_sl.arb | 5 +- lib/l10n/app_sv.arb | 5 +- lib/l10n/app_zh.arb | 5 +- lib/screens/contacts_screen.dart | 250 +++++++++++++++++-------- lib/screens/repeater_hub_screen.dart | 269 ++++++++++++++------------- 29 files changed, 447 insertions(+), 236 deletions(-) diff --git a/lib/l10n/app_bg.arb b/lib/l10n/app_bg.arb index 30a2c1b..1f0f671 100644 --- a/lib/l10n/app_bg.arb +++ b/lib/l10n/app_bg.arb @@ -822,7 +822,6 @@ } }, "login_failedMessage": "Входът не беше успешен. Или паролата е грешна, или повторителят е недостъпен.", - "common_reload": "Презареди", "common_clear": "Изчисти", "path_currentPath": "Текущ път: {path}", @@ -1349,5 +1348,7 @@ "channels_scanQrCode": "Сканирайте QR код", "channels_scanQrCodeComingSoon": "Ще излезе скоро", "channels_enterHashtag": "Въведете хаштаг", - "channels_hashtagHint": "напр. #отбор" + "channels_hashtagHint": "напр. #отбор", + "room_management": "Управление на сървъра за стая", + "contacts_manageRoom": "Управление на сървър за стая" } diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 9d2701f..8b76346 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -822,7 +822,6 @@ } }, "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": "Aktiver Pfad: {path}", @@ -1349,5 +1348,7 @@ "channels_scanQrCode": "Scannen Sie einen QR-Code", "channels_scanQrCodeComingSoon": "Bald verfügbar", "channels_enterHashtag": "Gib Hashtag ein", - "channels_hashtagHint": "z.B. #team" + "channels_hashtagHint": "z.B. #team", + "contacts_manageRoom": "Verwalten Sie den Raumserver", + "room_management": "Raumserververwaltung" } diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 203f64f..cf33b6c 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -253,7 +253,8 @@ } }, "contacts_manageRepeater": "Manage Repeater", - "contacts_roomLogin": "Room Login", + "contacts_manageRoom": "Manage Room Server", + "contacts_roomLogin": "Room Server Login", "contacts_openChat": "Open Chat", "contacts_editGroup": "Edit Group", "contacts_deleteGroup": "Delete Group", @@ -697,7 +698,7 @@ "dialog_disconnectConfirm": "Are you sure you want to disconnect from this device?", "login_repeaterLogin": "Repeater Login", - "login_roomLogin": "Room Login", + "login_roomLogin": "Room Server Login", "login_password": "Password", "login_enterPassword": "Enter password", "login_savePassword": "Save password", @@ -760,6 +761,7 @@ "path_setPath": "Set Path", "repeater_management": "Repeater Management", + "room_management": "Room Server Management", "repeater_managementTools": "Management Tools", "repeater_status": "Status", "repeater_statusSubtitle": "View repeater status, stats, and neighbors", diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index b23cfce..af604e1 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -822,7 +822,6 @@ } }, "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}", @@ -1349,5 +1348,7 @@ "channels_scanQrCode": "Escanear un Código QR", "channels_scanQrCodeComingSoon": "Próximamente", "channels_enterHashtag": "Introducir hashtag", - "channels_hashtagHint": "ej. #equipo" + "channels_hashtagHint": "ej. #equipo", + "contacts_manageRoom": "Gestionar Servidor de Habitación", + "room_management": "Administración del Servidor de Habitación" } diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index 0e7b952..8d14b8f 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -822,7 +822,6 @@ } }, "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}", @@ -1349,5 +1348,7 @@ "channels_scanQrCode": "Scanner un code QR", "channels_scanQrCodeComingSoon": "Bientôt disponible", "channels_enterHashtag": "Entrez le hashtag", - "channels_hashtagHint": "ex. #équipe" + "channels_hashtagHint": "ex. #équipe", + "contacts_manageRoom": "Gérer le serveur de la pièce {name}", + "room_management": "Gestion du serveur de pièce" } diff --git a/lib/l10n/app_it.arb b/lib/l10n/app_it.arb index b77450f..ea8c6ac 100644 --- a/lib/l10n/app_it.arb +++ b/lib/l10n/app_it.arb @@ -822,7 +822,6 @@ } }, "login_failedMessage": "Accesso fallito. La password non è corretta oppure il ripetitore non è raggiungibile.", - "common_reload": "Ricaricare", "common_clear": "Cancella", "path_currentPath": "Percorso corrente: {path}", @@ -1349,5 +1348,7 @@ "channels_scanQrCode": "Scansiona un codice QR", "channels_scanQrCodeComingSoon": "Arriverà presto", "channels_enterHashtag": "Inserisci hashtag", - "channels_hashtagHint": "es. #team" + "channels_hashtagHint": "es. #team", + "room_management": "Gestione del Server di Camera", + "contacts_manageRoom": "Gestisci Server Camera" } diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index bedd407..22c13f8 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -1284,10 +1284,16 @@ abstract class AppLocalizations { /// **'Manage Repeater'** String get contacts_manageRepeater; + /// No description provided for @contacts_manageRoom. + /// + /// In en, this message translates to: + /// **'Manage Room Server'** + String get contacts_manageRoom; + /// No description provided for @contacts_roomLogin. /// /// In en, this message translates to: - /// **'Room Login'** + /// **'Room Server Login'** String get contacts_roomLogin; /// No description provided for @contacts_openChat. @@ -2672,7 +2678,7 @@ abstract class AppLocalizations { /// No description provided for @login_roomLogin. /// /// In en, this message translates to: - /// **'Room Login'** + /// **'Room Server Login'** String get login_roomLogin; /// No description provided for @login_password. @@ -2867,6 +2873,12 @@ abstract class AppLocalizations { /// **'Repeater Management'** String get repeater_management; + /// No description provided for @room_management. + /// + /// In en, this message translates to: + /// **'Room Server Management'** + String get room_management; + /// No description provided for @repeater_managementTools. /// /// In en, this message translates to: diff --git a/lib/l10n/app_localizations_bg.dart b/lib/l10n/app_localizations_bg.dart index cf2b35c..0c666fa 100644 --- a/lib/l10n/app_localizations_bg.dart +++ b/lib/l10n/app_localizations_bg.dart @@ -650,6 +650,9 @@ class AppLocalizationsBg extends AppLocalizations { @override String get contacts_manageRepeater => 'Управление на Повтарящ се Елемент'; + @override + String get contacts_manageRoom => 'Manage Room Server'; + @override String get contacts_roomLogin => 'Вход в стаята'; @@ -1587,6 +1590,9 @@ class AppLocalizationsBg extends AppLocalizations { @override String get repeater_management => 'Управление на повторители'; + @override + String get room_management => 'Room Server Management'; + @override String get repeater_managementTools => 'Инструменти за управление'; diff --git a/lib/l10n/app_localizations_de.dart b/lib/l10n/app_localizations_de.dart index 3d0cbcd..d3edf4e 100644 --- a/lib/l10n/app_localizations_de.dart +++ b/lib/l10n/app_localizations_de.dart @@ -647,6 +647,9 @@ class AppLocalizationsDe extends AppLocalizations { @override String get contacts_manageRepeater => 'Wiederholungen verwalten'; + @override + String get contacts_manageRoom => 'Manage Room Server'; + @override String get contacts_roomLogin => 'Raum-Login'; @@ -1586,6 +1589,9 @@ class AppLocalizationsDe extends AppLocalizations { @override String get repeater_management => 'Repeater-Verwaltung'; + @override + String get room_management => 'Room Server Management'; + @override String get repeater_managementTools => 'Verwaltungs-Tools'; diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index b8c4f90..3051061 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -641,7 +641,10 @@ class AppLocalizationsEn extends AppLocalizations { String get contacts_manageRepeater => 'Manage Repeater'; @override - String get contacts_roomLogin => 'Room Login'; + String get contacts_manageRoom => 'Manage Room Server'; + + @override + String get contacts_roomLogin => 'Room Server Login'; @override String get contacts_openChat => 'Open Chat'; @@ -1439,7 +1442,7 @@ class AppLocalizationsEn extends AppLocalizations { String get login_repeaterLogin => 'Repeater Login'; @override - String get login_roomLogin => 'Room Login'; + String get login_roomLogin => 'Room Server Login'; @override String get login_password => 'Password'; @@ -1561,6 +1564,9 @@ class AppLocalizationsEn extends AppLocalizations { @override String get repeater_management => 'Repeater Management'; + @override + String get room_management => 'Room Server Management'; + @override String get repeater_managementTools => 'Management Tools'; diff --git a/lib/l10n/app_localizations_es.dart b/lib/l10n/app_localizations_es.dart index 21aad2c..9f92ba7 100644 --- a/lib/l10n/app_localizations_es.dart +++ b/lib/l10n/app_localizations_es.dart @@ -648,6 +648,9 @@ class AppLocalizationsEs extends AppLocalizations { @override String get contacts_manageRepeater => 'Gestionar Repetidor'; + @override + String get contacts_manageRoom => 'Manage Room Server'; + @override String get contacts_roomLogin => 'Inicio de Sala'; @@ -1585,6 +1588,9 @@ class AppLocalizationsEs extends AppLocalizations { @override String get repeater_management => 'Gestión de Repetidores'; + @override + String get room_management => 'Room Server Management'; + @override String get repeater_managementTools => 'Herramientas de Gestión'; diff --git a/lib/l10n/app_localizations_fr.dart b/lib/l10n/app_localizations_fr.dart index 21f63b5..ced92dc 100644 --- a/lib/l10n/app_localizations_fr.dart +++ b/lib/l10n/app_localizations_fr.dart @@ -649,6 +649,9 @@ class AppLocalizationsFr extends AppLocalizations { @override String get contacts_manageRepeater => 'Gérer le répétiteur'; + @override + String get contacts_manageRoom => 'Manage Room Server'; + @override String get contacts_roomLogin => 'Connexion Salle'; @@ -1591,6 +1594,9 @@ class AppLocalizationsFr extends AppLocalizations { @override String get repeater_management => 'Gestion des répétiteurs'; + @override + String get room_management => 'Room Server Management'; + @override String get repeater_managementTools => 'Outils de Gestion'; diff --git a/lib/l10n/app_localizations_it.dart b/lib/l10n/app_localizations_it.dart index 1cc567c..1351305 100644 --- a/lib/l10n/app_localizations_it.dart +++ b/lib/l10n/app_localizations_it.dart @@ -646,6 +646,9 @@ class AppLocalizationsIt extends AppLocalizations { @override String get contacts_manageRepeater => 'Gestisci Ripetitore'; + @override + String get contacts_manageRoom => 'Manage Room Server'; + @override String get contacts_roomLogin => 'Login Camera'; @@ -1583,6 +1586,9 @@ class AppLocalizationsIt extends AppLocalizations { @override String get repeater_management => 'Gestione Ripetitori'; + @override + String get room_management => 'Room Server Management'; + @override String get repeater_managementTools => 'Strumenti di Gestione'; diff --git a/lib/l10n/app_localizations_nl.dart b/lib/l10n/app_localizations_nl.dart index db1f68e..baf4668 100644 --- a/lib/l10n/app_localizations_nl.dart +++ b/lib/l10n/app_localizations_nl.dart @@ -644,6 +644,9 @@ class AppLocalizationsNl extends AppLocalizations { @override String get contacts_manageRepeater => 'Beheer Repeater'; + @override + String get contacts_manageRoom => 'Manage Room Server'; + @override String get contacts_roomLogin => 'Ruimte Inloggen'; @@ -1578,6 +1581,9 @@ class AppLocalizationsNl extends AppLocalizations { @override String get repeater_management => 'Beheer Repeaters'; + @override + String get room_management => 'Room Server Management'; + @override String get repeater_managementTools => 'Beheerinstrumenten'; diff --git a/lib/l10n/app_localizations_pl.dart b/lib/l10n/app_localizations_pl.dart index e4373d1..5051b83 100644 --- a/lib/l10n/app_localizations_pl.dart +++ b/lib/l10n/app_localizations_pl.dart @@ -649,6 +649,9 @@ class AppLocalizationsPl extends AppLocalizations { @override String get contacts_manageRepeater => 'Zarządzaj Powtórzami'; + @override + String get contacts_manageRoom => 'Manage Room Server'; + @override String get contacts_roomLogin => 'Logowanie do pokoju'; @@ -1587,6 +1590,9 @@ class AppLocalizationsPl extends AppLocalizations { @override String get repeater_management => 'Zarządzanie Powtórzami'; + @override + String get room_management => 'Room Server Management'; + @override String get repeater_managementTools => 'Narzędzia Zarządzania'; diff --git a/lib/l10n/app_localizations_pt.dart b/lib/l10n/app_localizations_pt.dart index 2aaa940..96cb130 100644 --- a/lib/l10n/app_localizations_pt.dart +++ b/lib/l10n/app_localizations_pt.dart @@ -649,6 +649,9 @@ class AppLocalizationsPt extends AppLocalizations { @override String get contacts_manageRepeater => 'Gerenciar Repetidor'; + @override + String get contacts_manageRoom => 'Manage Room Server'; + @override String get contacts_roomLogin => 'Login no Quarto'; @@ -1585,6 +1588,9 @@ class AppLocalizationsPt extends AppLocalizations { @override String get repeater_management => 'Gerenciamento de Repetidor'; + @override + String get room_management => 'Room Server Management'; + @override String get repeater_managementTools => 'Ferramentas de Gerenciamento'; diff --git a/lib/l10n/app_localizations_sk.dart b/lib/l10n/app_localizations_sk.dart index ffd327a..cdb39c7 100644 --- a/lib/l10n/app_localizations_sk.dart +++ b/lib/l10n/app_localizations_sk.dart @@ -642,6 +642,9 @@ class AppLocalizationsSk extends AppLocalizations { @override String get contacts_manageRepeater => 'Spravovať opakované zoznamy'; + @override + String get contacts_manageRoom => 'Manage Room Server'; + @override String get contacts_roomLogin => 'Prihlásenie do miestnosti'; @@ -1580,6 +1583,9 @@ class AppLocalizationsSk extends AppLocalizations { @override String get repeater_management => 'Správa opakérov'; + @override + String get room_management => 'Room Server Management'; + @override String get repeater_managementTools => 'Nástroje na správu'; diff --git a/lib/l10n/app_localizations_sl.dart b/lib/l10n/app_localizations_sl.dart index 994b7fa..a54282c 100644 --- a/lib/l10n/app_localizations_sl.dart +++ b/lib/l10n/app_localizations_sl.dart @@ -644,6 +644,9 @@ class AppLocalizationsSl extends AppLocalizations { @override String get contacts_manageRepeater => 'Upravljajte Ponovitve'; + @override + String get contacts_manageRoom => 'Manage Room Server'; + @override String get contacts_roomLogin => 'Vnos v sobo'; @@ -1580,6 +1583,9 @@ class AppLocalizationsSl extends AppLocalizations { @override String get repeater_management => 'Upravljanje ponovitve'; + @override + String get room_management => 'Room Server Management'; + @override String get repeater_managementTools => 'Upravne orodje'; diff --git a/lib/l10n/app_localizations_sv.dart b/lib/l10n/app_localizations_sv.dart index a4765a9..2b595a8 100644 --- a/lib/l10n/app_localizations_sv.dart +++ b/lib/l10n/app_localizations_sv.dart @@ -638,6 +638,9 @@ class AppLocalizationsSv extends AppLocalizations { @override String get contacts_manageRepeater => 'Hantera Upprepare'; + @override + String get contacts_manageRoom => 'Manage Room Server'; + @override String get contacts_roomLogin => 'Rum Inloggning'; @@ -1569,6 +1572,9 @@ class AppLocalizationsSv extends AppLocalizations { @override String get repeater_management => 'Återuppspelarens Hantering'; + @override + String get room_management => 'Room Server Management'; + @override String get repeater_managementTools => 'Administrationsverktyg'; diff --git a/lib/l10n/app_localizations_zh.dart b/lib/l10n/app_localizations_zh.dart index 99f4e90..2c0cddb 100644 --- a/lib/l10n/app_localizations_zh.dart +++ b/lib/l10n/app_localizations_zh.dart @@ -611,6 +611,9 @@ class AppLocalizationsZh extends AppLocalizations { @override String get contacts_manageRepeater => '管理重复项'; + @override + String get contacts_manageRoom => 'Manage Room Server'; + @override String get contacts_roomLogin => '房间登录'; @@ -1513,6 +1516,9 @@ class AppLocalizationsZh extends AppLocalizations { @override String get repeater_management => '重复器管理'; + @override + String get room_management => 'Room Server Management'; + @override String get repeater_managementTools => '管理工具'; diff --git a/lib/l10n/app_nl.arb b/lib/l10n/app_nl.arb index b7e1a35..fd069fc 100644 --- a/lib/l10n/app_nl.arb +++ b/lib/l10n/app_nl.arb @@ -822,7 +822,6 @@ } }, "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}", @@ -1349,5 +1348,7 @@ "channels_scanQrCode": "Scan een QR-code", "channels_scanQrCodeComingSoon": "Komt later", "channels_enterHashtag": "Voer hashtag in", - "channels_hashtagHint": "bijv. #team" + "channels_hashtagHint": "bijv. #team", + "room_management": "Beheer Server Kamer", + "contacts_manageRoom": "Beheer Ruimte Server" } diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb index 56fe869..60a6ab5 100644 --- a/lib/l10n/app_pl.arb +++ b/lib/l10n/app_pl.arb @@ -822,7 +822,6 @@ } }, "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}", @@ -1349,5 +1348,7 @@ "channels_scanQrCode": "Skanuj kod QR", "channels_scanQrCodeComingSoon": "Wkrótce", "channels_enterHashtag": "Wprowadź hashtag", - "channels_hashtagHint": "np. #zespół" + "channels_hashtagHint": "np. #zespół", + "contacts_manageRoom": "Zarządzaj Serwerem Pokoju", + "room_management": "Zarządzanie Serwerem Pokoju" } diff --git a/lib/l10n/app_pt.arb b/lib/l10n/app_pt.arb index 99da374..041b479 100644 --- a/lib/l10n/app_pt.arb +++ b/lib/l10n/app_pt.arb @@ -822,7 +822,6 @@ } }, "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}", @@ -1349,5 +1348,7 @@ "channels_scanQrCode": "Digitalizar um Código QR", "channels_scanQrCodeComingSoon": "Em breve", "channels_enterHashtag": "Insira hashtag", - "channels_hashtagHint": "ex. #equipe" + "channels_hashtagHint": "ex. #equipe", + "contacts_manageRoom": "Gerenciar Servidor de Sala {name} ({count})", + "room_management": "Gerenciamento de Servidor de Sala" } diff --git a/lib/l10n/app_sk.arb b/lib/l10n/app_sk.arb index 1ffb197..688a1bb 100644 --- a/lib/l10n/app_sk.arb +++ b/lib/l10n/app_sk.arb @@ -822,7 +822,6 @@ } }, "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}", @@ -1349,5 +1348,7 @@ "channels_scanQrCode": "Skenujte QR kód", "channels_scanQrCodeComingSoon": "Čoskoro", "channels_enterHashtag": "Zadajte hashtag", - "channels_hashtagHint": "napr. #tím" + "channels_hashtagHint": "napr. #tím", + "room_management": "Správa servera miestnosti", + "contacts_manageRoom": "Spravovať server miestnosti" } diff --git a/lib/l10n/app_sl.arb b/lib/l10n/app_sl.arb index bac8b2b..abd55cc 100644 --- a/lib/l10n/app_sl.arb +++ b/lib/l10n/app_sl.arb @@ -822,7 +822,6 @@ } }, "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}", @@ -1349,5 +1348,7 @@ "channels_scanQrCode": "Skeniraj QR kodo", "channels_scanQrCodeComingSoon": "Prihajajoča", "channels_enterHashtag": "Vnesite hashtag", - "channels_hashtagHint": "npr. #ekipa" + "channels_hashtagHint": "npr. #ekipa", + "contacts_manageRoom": "Upravljajte strežnik sobe", + "room_management": "Upravljanje stremlišča" } diff --git a/lib/l10n/app_sv.arb b/lib/l10n/app_sv.arb index 3c8d470..9b70a3e 100644 --- a/lib/l10n/app_sv.arb +++ b/lib/l10n/app_sv.arb @@ -822,7 +822,6 @@ } }, "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}", @@ -1349,5 +1348,7 @@ "channels_scanQrCode": "Skanna en QR-kod", "channels_scanQrCodeComingSoon": "Kommer snart", "channels_enterHashtag": "Ange hashtag", - "channels_hashtagHint": "t.ex. #team" + "channels_hashtagHint": "t.ex. #team", + "contacts_manageRoom": "Hantera Rumserver", + "room_management": "Rumserverhantering" } diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index fc5ac55..56580fa 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -822,7 +822,6 @@ } }, "login_failedMessage": "登录失败。密码不正确或中继器不可达。", - "common_reload": "重新加载", "common_clear": "清除", "path_currentPath": "当前路径:{path}", @@ -1349,5 +1348,7 @@ "channels_scanQrCode": "扫描二维码", "channels_scanQrCodeComingSoon": "即将到来", "channels_enterHashtag": "输入标签", - "channels_hashtagHint": "例如 #团队" + "channels_hashtagHint": "例如 #团队", + "contacts_manageRoom": "管理房间服务器", + "room_management": "房间服务器管理" } diff --git a/lib/screens/contacts_screen.dart b/lib/screens/contacts_screen.dart index b9ceb84..8d15cc3 100644 --- a/lib/screens/contacts_screen.dart +++ b/lib/screens/contacts_screen.dart @@ -30,10 +30,7 @@ import 'settings_screen.dart'; class ContactsScreen extends StatefulWidget { final bool hideBackButton; - const ContactsScreen({ - super.key, - this.hideBackButton = false, - }); + const ContactsScreen({super.key, this.hideBackButton = false}); @override State createState() => _ContactsScreenState(); @@ -114,7 +111,8 @@ class _ContactsScreenState extends State top: false, child: QuickSwitchBar( selectedIndex: 0, - onDestinationSelected: (index) => _handleQuickSwitch(index, context), + onDestinationSelected: (index) => + _handleQuickSwitch(index, context), ), ), ), @@ -168,8 +166,9 @@ class _ContactsScreenState extends State } final filteredAndSorted = _filterAndSortContacts(contacts, connector); - final filteredGroups = - _showUnreadOnly ? const [] : _filterAndSortGroups(_groups, contacts); + final filteredGroups = _showUnreadOnly + ? const [] + : _filterAndSortGroups(_groups, contacts); return Column( children: [ @@ -199,7 +198,10 @@ class _ContactsScreenState extends State border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), ), - contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + contentPadding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 12, + ), ), onChanged: (value) { _searchDebounce?.cancel(); @@ -238,14 +240,18 @@ class _ContactsScreenState extends State final group = filteredGroups[index]; return _buildGroupTile(context, group, contacts); } - final contact = filteredAndSorted[index - filteredGroups.length]; - final unreadCount = connector.getUnreadCountForContact(contact); + final contact = + filteredAndSorted[index - filteredGroups.length]; + final unreadCount = connector.getUnreadCountForContact( + contact, + ); return _ContactTile( contact: contact, lastSeen: _resolveLastSeen(contact), unreadCount: unreadCount, onTap: () => _openChat(context, contact), - onLongPress: () => _showContactOptions(context, connector, contact), + onLongPress: () => + _showContactOptions(context, connector, contact), ); }, ), @@ -255,35 +261,47 @@ class _ContactsScreenState extends State ); } - List _filterAndSortGroups(List groups, List contacts) { + List _filterAndSortGroups( + List groups, + List contacts, + ) { final query = _searchQuery.trim().toLowerCase(); final contactsByKey = {}; for (final contact in contacts) { contactsByKey[contact.publicKeyHex] = contact; } - final filtered = groups.where((group) { - if (query.isEmpty) return true; - if (group.name.toLowerCase().contains(query)) return true; - for (final key in group.memberKeys) { - final contact = contactsByKey[key]; - if (contact != null && matchesContactQuery(contact, query)) return true; - } - return false; - }).where((group) { - if (_typeFilter == ContactTypeFilter.all) return true; - for (final key in group.memberKeys) { - final contact = contactsByKey[key]; - if (contact != null && _matchesTypeFilter(contact)) return true; - } - return false; - }).toList(); + final filtered = groups + .where((group) { + if (query.isEmpty) return true; + if (group.name.toLowerCase().contains(query)) return true; + for (final key in group.memberKeys) { + final contact = contactsByKey[key]; + if (contact != null && matchesContactQuery(contact, query)) + return true; + } + return false; + }) + .where((group) { + if (_typeFilter == ContactTypeFilter.all) return true; + for (final key in group.memberKeys) { + final contact = contactsByKey[key]; + if (contact != null && _matchesTypeFilter(contact)) return true; + } + return false; + }) + .toList(); - filtered.sort((a, b) => a.name.toLowerCase().compareTo(b.name.toLowerCase())); + filtered.sort( + (a, b) => a.name.toLowerCase().compareTo(b.name.toLowerCase()), + ); return filtered; } - List _filterAndSortContacts(List contacts, MeshCoreConnector connector) { + List _filterAndSortContacts( + List contacts, + MeshCoreConnector connector, + ) { var filtered = contacts.where((contact) { if (_searchQuery.isEmpty) return true; return matchesContactQuery(contact, _searchQuery); @@ -301,19 +319,27 @@ class _ContactsScreenState extends State switch (_sortOption) { case ContactSortOption.lastSeen: - filtered.sort((a, b) => _resolveLastSeen(b).compareTo(_resolveLastSeen(a))); + filtered.sort( + (a, b) => _resolveLastSeen(b).compareTo(_resolveLastSeen(a)), + ); break; case ContactSortOption.recentMessages: filtered.sort((a, b) { final aMessages = connector.getMessages(a); final bMessages = connector.getMessages(b); - final aLastMsg = aMessages.isEmpty ? DateTime(1970) : aMessages.last.timestamp; - final bLastMsg = bMessages.isEmpty ? DateTime(1970) : bMessages.last.timestamp; + final aLastMsg = aMessages.isEmpty + ? DateTime(1970) + : aMessages.last.timestamp; + final bLastMsg = bMessages.isEmpty + ? DateTime(1970) + : bMessages.last.timestamp; return bLastMsg.compareTo(aLastMsg); }); break; case ContactSortOption.name: - filtered.sort((a, b) => a.name.toLowerCase().compareTo(b.name.toLowerCase())); + filtered.sort( + (a, b) => a.name.toLowerCase().compareTo(b.name.toLowerCase()), + ); break; } @@ -340,7 +366,11 @@ class _ContactsScreenState extends State : contact.lastSeen; } - Widget _buildGroupTile(BuildContext context, ContactGroup group, List contacts) { + Widget _buildGroupTile( + BuildContext context, + ContactGroup group, + List contacts, + ) { final memberContacts = _resolveGroupContacts(group, contacts); final subtitle = _formatGroupMembers(context, memberContacts); return ListTile( @@ -359,7 +389,10 @@ class _ContactsScreenState extends State ); } - List _resolveGroupContacts(ContactGroup group, List contacts) { + List _resolveGroupContacts( + ContactGroup group, + List contacts, + ) { final byKey = {}; for (final contact in contacts) { byKey[contact.publicKeyHex] = contact; @@ -371,7 +404,9 @@ class _ContactsScreenState extends State resolved.add(contact); } } - resolved.sort((a, b) => a.name.toLowerCase().compareTo(b.name.toLowerCase())); + resolved.sort( + (a, b) => a.name.toLowerCase().compareTo(b.name.toLowerCase()), + ); return resolved; } @@ -387,7 +422,7 @@ class _ContactsScreenState extends State if (contact.type == advTypeRepeater) { _showRepeaterLogin(context, contact); } else if (contact.type == advTypeRoom) { - _showRoomLogin(context, contact); + _showRoomLogin(context, contact, false); } else { context.read().markContactRead(contact.publicKeyHex); Navigator.push( @@ -403,17 +438,13 @@ class _ContactsScreenState extends State case 1: Navigator.pushReplacement( context, - buildQuickSwitchRoute( - const ChannelsScreen(hideBackButton: true), - ), + buildQuickSwitchRoute(const ChannelsScreen(hideBackButton: true)), ); break; case 2: Navigator.pushReplacement( context, - buildQuickSwitchRoute( - const MapScreen(hideBackButton: true), - ), + buildQuickSwitchRoute(const MapScreen(hideBackButton: true)), ); break; } @@ -429,10 +460,8 @@ class _ContactsScreenState extends State Navigator.push( context, MaterialPageRoute( - builder: (context) => RepeaterHubScreen( - repeater: repeater, - password: password, - ), + builder: (context) => + RepeaterHubScreen(repeater: repeater, password: password), ), ); }, @@ -440,7 +469,7 @@ class _ContactsScreenState extends State ); } - void _showRoomLogin(BuildContext context, Contact room) { + void _showRoomLogin(BuildContext context, Contact room, bool settings) { showDialog( context: context, builder: (context) => RoomLoginDialog( @@ -451,7 +480,9 @@ class _ContactsScreenState extends State Navigator.push( context, MaterialPageRoute( - builder: (context) => ChatScreen(contact: room), + builder: (context) => settings + ? RepeaterHubScreen(repeater: room, password: password) + : ChatScreen(contact: room), ), ); }, @@ -459,7 +490,11 @@ class _ContactsScreenState extends State ); } - void _showGroupOptions(BuildContext context, ContactGroup group, List contacts) { + void _showGroupOptions( + BuildContext context, + ContactGroup group, + List contacts, + ) { final members = _resolveGroupContacts(group, contacts); showModalBottomSheet( context: context, @@ -478,7 +513,10 @@ class _ContactsScreenState extends State ), ListTile( leading: const Icon(Icons.delete, color: Colors.red), - title: Text(context.l10n.contacts_deleteGroup, style: const TextStyle(color: Colors.red)), + title: Text( + context.l10n.contacts_deleteGroup, + style: const TextStyle(color: Colors.red), + ), onTap: () { Navigator.pop(sheetContext); _confirmDeleteGroup(context, group); @@ -522,7 +560,10 @@ class _ContactsScreenState extends State }); await _saveGroups(); }, - child: Text(context.l10n.common_delete, style: const TextStyle(color: Colors.red)), + child: Text( + context.l10n.common_delete, + style: const TextStyle(color: Colors.red), + ), ), ], ), @@ -548,10 +589,16 @@ class _ContactsScreenState extends State final filteredContacts = filterQuery.isEmpty ? sortedContacts : sortedContacts - .where((contact) => matchesContactQuery(contact, filterQuery)) - .toList(); + .where( + (contact) => matchesContactQuery(contact, filterQuery), + ) + .toList(); return AlertDialog( - title: Text(isEditing ? context.l10n.contacts_editGroup : context.l10n.contacts_newGroup), + title: Text( + isEditing + ? context.l10n.contacts_editGroup + : context.l10n.contacts_newGroup, + ), content: SizedBox( width: double.maxFinite, child: Column( @@ -582,12 +629,18 @@ class _ContactsScreenState extends State SizedBox( height: 240, child: filteredContacts.isEmpty - ? Center(child: Text(context.l10n.contacts_noContactsMatchFilter)) + ? Center( + child: Text( + context.l10n.contacts_noContactsMatchFilter, + ), + ) : ListView.builder( itemCount: filteredContacts.length, itemBuilder: (context, index) { final contact = filteredContacts[index]; - final isSelected = selectedKeys.contains(contact.publicKeyHex); + final isSelected = selectedKeys.contains( + contact.publicKeyHex, + ); return CheckboxListTile( value: isSelected, title: Text(contact.name), @@ -618,7 +671,9 @@ class _ContactsScreenState extends State final name = nameController.text.trim(); if (name.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(context.l10n.contacts_groupNameRequired)), + SnackBar( + content: Text(context.l10n.contacts_groupNameRequired), + ), ); return; } @@ -628,13 +683,19 @@ class _ContactsScreenState extends State }); if (exists) { ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(context.l10n.contacts_groupAlreadyExists(name))), + SnackBar( + content: Text( + context.l10n.contacts_groupAlreadyExists(name), + ), + ), ); return; } setState(() { if (isEditing) { - final index = _groups.indexWhere((g) => g.name == group.name); + final index = _groups.indexWhere( + (g) => g.name == group.name, + ); if (index != -1) { _groups[index] = ContactGroup( name: name, @@ -642,7 +703,12 @@ class _ContactsScreenState extends State ); } } else { - _groups.add(ContactGroup(name: name, memberKeys: selectedKeys.toList())); + _groups.add( + ContactGroup( + name: name, + memberKeys: selectedKeys.toList(), + ), + ); } }); await _saveGroups(); @@ -650,7 +716,11 @@ class _ContactsScreenState extends State Navigator.pop(dialogContext); } }, - child: Text(isEditing ? context.l10n.common_save : context.l10n.common_create), + child: Text( + isEditing + ? context.l10n.common_save + : context.l10n.common_create, + ), ), ], ); @@ -675,23 +745,31 @@ class _ContactsScreenState extends State children: [ if (isRepeater) ListTile( - leading: const Icon(Icons.cell_tower, color: Colors.orange), + leading: const Icon(Icons.settings, color: Colors.orange), title: Text(context.l10n.contacts_manageRepeater), onTap: () { Navigator.pop(sheetContext); _showRepeaterLogin(context, contact); }, ) - else if (isRoom) + else if (isRoom) ...[ ListTile( leading: const Icon(Icons.room, color: Colors.blue), title: Text(context.l10n.contacts_roomLogin), onTap: () { Navigator.pop(sheetContext); - _showRoomLogin(context, contact); + _showRoomLogin(context, contact, false); }, - ) - else + ), + ListTile( + leading: const Icon(Icons.settings, color: Colors.orange), + title: Text(context.l10n.room_management), + onTap: () { + Navigator.pop(sheetContext); + _showRoomLogin(context, contact, true); + }, + ), + ] else ListTile( leading: const Icon(Icons.chat), title: Text(context.l10n.contacts_openChat), @@ -702,7 +780,10 @@ class _ContactsScreenState extends State ), ListTile( leading: const Icon(Icons.delete, color: Colors.red), - title: Text(context.l10n.contacts_deleteContact, style: const TextStyle(color: Colors.red)), + title: Text( + context.l10n.contacts_deleteContact, + style: const TextStyle(color: Colors.red), + ), onTap: () { Navigator.pop(sheetContext); _confirmDelete(context, connector, contact); @@ -734,7 +815,10 @@ class _ContactsScreenState extends State Navigator.pop(dialogContext); connector.removeContact(contact); }, - child: Text(context.l10n.common_delete, style: const TextStyle(color: Colors.red)), + child: Text( + context.l10n.common_delete, + style: const TextStyle(color: Colors.red), + ), ), ], ), @@ -759,14 +843,17 @@ class _ContactTile extends StatelessWidget { @override Widget build(BuildContext context) { - final shotPublicKey = "<${contact.publicKeyHex.substring(0, 8)}...${contact.publicKeyHex.substring(contact.publicKeyHex.length - 8)}>"; + final shotPublicKey = + "<${contact.publicKeyHex.substring(0, 8)}...${contact.publicKeyHex.substring(contact.publicKeyHex.length - 8)}>"; return ListTile( leading: CircleAvatar( backgroundColor: _getTypeColor(contact.type), child: _buildContactAvatar(contact), ), title: Text(contact.name), - subtitle: Text('${contact.typeLabel} • ${contact.pathLabel} $shotPublicKey'), + subtitle: Text( + '${contact.typeLabel} • ${contact.pathLabel} $shotPublicKey', + ), trailing: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.end, @@ -791,10 +878,7 @@ class _ContactTile extends StatelessWidget { Widget _buildContactAvatar(Contact contact) { final emoji = firstEmoji(contact.name); if (emoji != null) { - return Text( - emoji, - style: const TextStyle(fontSize: 18), - ); + return Text(emoji, style: const TextStyle(fontSize: 18)); } return Icon(_getTypeIcon(contact.type), color: Colors.white, size: 20); } @@ -833,13 +917,19 @@ class _ContactTile extends StatelessWidget { final now = DateTime.now(); final diff = now.difference(lastSeen); - if (diff.isNegative || diff.inMinutes < 5) return context.l10n.contacts_lastSeenNow; - if (diff.inMinutes < 60) return context.l10n.contacts_lastSeenMinsAgo(diff.inMinutes); + if (diff.isNegative || diff.inMinutes < 5) + return context.l10n.contacts_lastSeenNow; + if (diff.inMinutes < 60) + return context.l10n.contacts_lastSeenMinsAgo(diff.inMinutes); if (diff.inHours < 24) { final hours = diff.inHours; - return hours == 1 ? context.l10n.contacts_lastSeenHourAgo : context.l10n.contacts_lastSeenHoursAgo(hours); + return hours == 1 + ? context.l10n.contacts_lastSeenHourAgo + : context.l10n.contacts_lastSeenHoursAgo(hours); } final days = diff.inDays; - return days == 1 ? context.l10n.contacts_lastSeenDayAgo : context.l10n.contacts_lastSeenDaysAgo(days); + return days == 1 + ? context.l10n.contacts_lastSeenDayAgo + : context.l10n.contacts_lastSeenDaysAgo(days); } } diff --git a/lib/screens/repeater_hub_screen.dart b/lib/screens/repeater_hub_screen.dart index b6e6d3f..5089f59 100644 --- a/lib/screens/repeater_hub_screen.dart +++ b/lib/screens/repeater_hub_screen.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:meshcore_open/connector/meshcore_protocol.dart'; import '../l10n/l10n.dart'; import '../models/contact.dart'; import 'repeater_status_screen.dart'; @@ -25,10 +26,17 @@ class RepeaterHubScreen extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - Text(l10n.repeater_management), + Text( + repeater.type == advTypeRepeater + ? l10n.repeater_management + : l10n.room_management, + ), Text( repeater.name, - style: const TextStyle(fontSize: 14, fontWeight: FontWeight.normal), + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.normal, + ), ), ], ), @@ -39,135 +47,147 @@ class RepeaterHubScreen extends StatelessWidget { child: ListView( padding: const EdgeInsets.all(16), children: [ - // Repeater info card - Card( - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - children: [ - CircleAvatar( - radius: 40, - backgroundColor: Colors.orange, - child: const Icon(Icons.cell_tower, size: 40, color: Colors.white), + // Repeater info card + Card( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + children: [ + CircleAvatar( + radius: 40, + backgroundColor: Colors.orange, + child: const Icon( + Icons.cell_tower, + size: 40, + color: Colors.white, ), - const SizedBox(height: 16), - Text( - repeater.name, - style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 16), + Text( + repeater.name, + style: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, ), - const SizedBox(height: 8), - Text( - '<${repeater.publicKeyHex.substring(0, 8)}...${repeater.publicKeyHex.substring(repeater.publicKeyHex.length - 8)}>', - style: TextStyle(fontSize: 14, color: Colors.grey[600]), - ), - const SizedBox(height: 8), - Text( - repeater.pathLabel, - style: TextStyle(fontSize: 14, color: Colors.grey[600]), - ), - if (repeater.hasLocation) ...[ - const SizedBox(height: 4), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(Icons.location_on, size: 14, color: Colors.grey[600]), - const SizedBox(width: 4), - Text( - '${repeater.latitude?.toStringAsFixed(4)}, ${repeater.longitude?.toStringAsFixed(4)}', - style: TextStyle(fontSize: 12, color: Colors.grey[600]), + ), + const SizedBox(height: 8), + Text( + '<${repeater.publicKeyHex.substring(0, 8)}...${repeater.publicKeyHex.substring(repeater.publicKeyHex.length - 8)}>', + style: TextStyle(fontSize: 14, color: Colors.grey[600]), + ), + const SizedBox(height: 8), + Text( + repeater.pathLabel, + style: TextStyle(fontSize: 14, color: Colors.grey[600]), + ), + if (repeater.hasLocation) ...[ + const SizedBox(height: 4), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.location_on, + size: 14, + color: Colors.grey[600], + ), + const SizedBox(width: 4), + Text( + '${repeater.latitude?.toStringAsFixed(4)}, ${repeater.longitude?.toStringAsFixed(4)}', + style: TextStyle( + fontSize: 12, + color: Colors.grey[600], ), - ], - ), - ], + ), + ], + ), ], - ), + ], ), ), - const SizedBox(height: 24), - Text( - l10n.repeater_managementTools, - style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), - ), - const SizedBox(height: 16), - // Status button - _buildManagementCard( - context, - icon: Icons.analytics, - title: l10n.repeater_status, - subtitle: l10n.repeater_statusSubtitle, - color: Colors.blue, - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => RepeaterStatusScreen( - repeater: repeater, - password: password, - ), + ), + const SizedBox(height: 24), + Text( + l10n.repeater_managementTools, + style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 16), + // Status button + _buildManagementCard( + context, + icon: Icons.analytics, + title: l10n.repeater_status, + subtitle: l10n.repeater_statusSubtitle, + color: Colors.blue, + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => RepeaterStatusScreen( + repeater: repeater, + password: password, ), - ); - }, - ), - const SizedBox(height: 16), - // Telemetry button - _buildManagementCard( - context, - icon: Icons.bar_chart_sharp, - title: l10n.repeater_telemetry, - subtitle: l10n.repeater_telemetrySubtitle, - color: Colors.teal, - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => TelemetryScreen( - repeater: repeater, - password: password, - ), + ), + ); + }, + ), + const SizedBox(height: 16), + // Telemetry button + _buildManagementCard( + context, + icon: Icons.bar_chart_sharp, + title: l10n.repeater_telemetry, + subtitle: l10n.repeater_telemetrySubtitle, + color: Colors.teal, + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + TelemetryScreen(repeater: repeater, password: password), + ), + ); + }, + ), + const SizedBox(height: 12), + // CLI button + _buildManagementCard( + context, + icon: Icons.terminal, + title: l10n.repeater_cli, + subtitle: l10n.repeater_cliSubtitle, + color: Colors.green, + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => RepeaterCliScreen( + repeater: repeater, + password: password, ), - ); - }, - ), - const SizedBox(height: 12), - // CLI button - _buildManagementCard( - context, - icon: Icons.terminal, - title: l10n.repeater_cli, - subtitle: l10n.repeater_cliSubtitle, - color: Colors.green, - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => RepeaterCliScreen( - repeater: repeater, - password: password, - ), + ), + ); + }, + ), + const SizedBox(height: 12), + // Settings button + _buildManagementCard( + context, + icon: Icons.settings, + title: l10n.repeater_settings, + subtitle: l10n.repeater_settingsSubtitle, + color: Colors.orange, + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => RepeaterSettingsScreen( + repeater: repeater, + password: password, ), - ); - }, - ), - const SizedBox(height: 12), - // Settings button - _buildManagementCard( - context, - icon: Icons.settings, - title: l10n.repeater_settings, - subtitle: l10n.repeater_settingsSubtitle, - color: Colors.orange, - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => RepeaterSettingsScreen( - repeater: repeater, - password: password, - ), - ), - ); - }, - ), + ), + ); + }, + ), ], ), ), @@ -214,10 +234,7 @@ class RepeaterHubScreen extends StatelessWidget { const SizedBox(height: 4), Text( subtitle, - style: TextStyle( - fontSize: 14, - color: Colors.grey[600], - ), + style: TextStyle(fontSize: 14, color: Colors.grey[600]), ), ], ), From 30ba1799e1bfdf4ffdd3246e431c9f5a6f2dd638 Mon Sep 17 00:00:00 2001 From: zjs81 Date: Mon, 19 Jan 2026 18:29:53 -0700 Subject: [PATCH 2/2] localization: update room management strings in multiple languages and refactor room login handling --- lib/l10n/app_fr.arb | 2 +- lib/l10n/app_localizations_bg.dart | 4 ++-- lib/l10n/app_localizations_de.dart | 4 ++-- lib/l10n/app_localizations_es.dart | 4 ++-- lib/l10n/app_localizations_fr.dart | 4 ++-- lib/l10n/app_localizations_it.dart | 4 ++-- lib/l10n/app_localizations_nl.dart | 4 ++-- lib/l10n/app_localizations_pl.dart | 4 ++-- lib/l10n/app_localizations_pt.dart | 4 ++-- lib/l10n/app_localizations_sk.dart | 4 ++-- lib/l10n/app_localizations_sl.dart | 4 ++-- lib/l10n/app_localizations_sv.dart | 4 ++-- lib/l10n/app_localizations_zh.dart | 4 ++-- lib/l10n/app_pt.arb | 2 +- lib/screens/contacts_screen.dart | 33 ++++++++++++++++++++---------- 15 files changed, 48 insertions(+), 37 deletions(-) diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index 8d14b8f..6513b40 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -1349,6 +1349,6 @@ "channels_scanQrCodeComingSoon": "Bientôt disponible", "channels_enterHashtag": "Entrez le hashtag", "channels_hashtagHint": "ex. #équipe", - "contacts_manageRoom": "Gérer le serveur de la pièce {name}", + "contacts_manageRoom": "Gérer le serveur de salle", "room_management": "Gestion du serveur de pièce" } diff --git a/lib/l10n/app_localizations_bg.dart b/lib/l10n/app_localizations_bg.dart index 0c666fa..dcabe32 100644 --- a/lib/l10n/app_localizations_bg.dart +++ b/lib/l10n/app_localizations_bg.dart @@ -651,7 +651,7 @@ class AppLocalizationsBg extends AppLocalizations { String get contacts_manageRepeater => 'Управление на Повтарящ се Елемент'; @override - String get contacts_manageRoom => 'Manage Room Server'; + String get contacts_manageRoom => 'Управление на сървър за стая'; @override String get contacts_roomLogin => 'Вход в стаята'; @@ -1591,7 +1591,7 @@ class AppLocalizationsBg extends AppLocalizations { String get repeater_management => 'Управление на повторители'; @override - String get room_management => 'Room Server Management'; + String get room_management => 'Управление на сървъра за стая'; @override String get repeater_managementTools => 'Инструменти за управление'; diff --git a/lib/l10n/app_localizations_de.dart b/lib/l10n/app_localizations_de.dart index d3edf4e..c42ed40 100644 --- a/lib/l10n/app_localizations_de.dart +++ b/lib/l10n/app_localizations_de.dart @@ -648,7 +648,7 @@ class AppLocalizationsDe extends AppLocalizations { String get contacts_manageRepeater => 'Wiederholungen verwalten'; @override - String get contacts_manageRoom => 'Manage Room Server'; + String get contacts_manageRoom => 'Verwalten Sie den Raumserver'; @override String get contacts_roomLogin => 'Raum-Login'; @@ -1590,7 +1590,7 @@ class AppLocalizationsDe extends AppLocalizations { String get repeater_management => 'Repeater-Verwaltung'; @override - String get room_management => 'Room Server Management'; + String get room_management => 'Raumserververwaltung'; @override String get repeater_managementTools => 'Verwaltungs-Tools'; diff --git a/lib/l10n/app_localizations_es.dart b/lib/l10n/app_localizations_es.dart index 9f92ba7..a88cccf 100644 --- a/lib/l10n/app_localizations_es.dart +++ b/lib/l10n/app_localizations_es.dart @@ -649,7 +649,7 @@ class AppLocalizationsEs extends AppLocalizations { String get contacts_manageRepeater => 'Gestionar Repetidor'; @override - String get contacts_manageRoom => 'Manage Room Server'; + String get contacts_manageRoom => 'Gestionar Servidor de Habitación'; @override String get contacts_roomLogin => 'Inicio de Sala'; @@ -1589,7 +1589,7 @@ class AppLocalizationsEs extends AppLocalizations { String get repeater_management => 'Gestión de Repetidores'; @override - String get room_management => 'Room Server Management'; + String get room_management => 'Administración del Servidor de Habitación'; @override String get repeater_managementTools => 'Herramientas de Gestión'; diff --git a/lib/l10n/app_localizations_fr.dart b/lib/l10n/app_localizations_fr.dart index ced92dc..ceb2be5 100644 --- a/lib/l10n/app_localizations_fr.dart +++ b/lib/l10n/app_localizations_fr.dart @@ -650,7 +650,7 @@ class AppLocalizationsFr extends AppLocalizations { String get contacts_manageRepeater => 'Gérer le répétiteur'; @override - String get contacts_manageRoom => 'Manage Room Server'; + String get contacts_manageRoom => 'Gérer le serveur de salle'; @override String get contacts_roomLogin => 'Connexion Salle'; @@ -1595,7 +1595,7 @@ class AppLocalizationsFr extends AppLocalizations { String get repeater_management => 'Gestion des répétiteurs'; @override - String get room_management => 'Room Server Management'; + String get room_management => 'Gestion du serveur de pièce'; @override String get repeater_managementTools => 'Outils de Gestion'; diff --git a/lib/l10n/app_localizations_it.dart b/lib/l10n/app_localizations_it.dart index 1351305..50e50de 100644 --- a/lib/l10n/app_localizations_it.dart +++ b/lib/l10n/app_localizations_it.dart @@ -647,7 +647,7 @@ class AppLocalizationsIt extends AppLocalizations { String get contacts_manageRepeater => 'Gestisci Ripetitore'; @override - String get contacts_manageRoom => 'Manage Room Server'; + String get contacts_manageRoom => 'Gestisci Server Camera'; @override String get contacts_roomLogin => 'Login Camera'; @@ -1587,7 +1587,7 @@ class AppLocalizationsIt extends AppLocalizations { String get repeater_management => 'Gestione Ripetitori'; @override - String get room_management => 'Room Server Management'; + String get room_management => 'Gestione del Server di Camera'; @override String get repeater_managementTools => 'Strumenti di Gestione'; diff --git a/lib/l10n/app_localizations_nl.dart b/lib/l10n/app_localizations_nl.dart index baf4668..d928365 100644 --- a/lib/l10n/app_localizations_nl.dart +++ b/lib/l10n/app_localizations_nl.dart @@ -645,7 +645,7 @@ class AppLocalizationsNl extends AppLocalizations { String get contacts_manageRepeater => 'Beheer Repeater'; @override - String get contacts_manageRoom => 'Manage Room Server'; + String get contacts_manageRoom => 'Beheer Ruimte Server'; @override String get contacts_roomLogin => 'Ruimte Inloggen'; @@ -1582,7 +1582,7 @@ class AppLocalizationsNl extends AppLocalizations { String get repeater_management => 'Beheer Repeaters'; @override - String get room_management => 'Room Server Management'; + String get room_management => 'Beheer Server Kamer'; @override String get repeater_managementTools => 'Beheerinstrumenten'; diff --git a/lib/l10n/app_localizations_pl.dart b/lib/l10n/app_localizations_pl.dart index 5051b83..435a589 100644 --- a/lib/l10n/app_localizations_pl.dart +++ b/lib/l10n/app_localizations_pl.dart @@ -650,7 +650,7 @@ class AppLocalizationsPl extends AppLocalizations { String get contacts_manageRepeater => 'Zarządzaj Powtórzami'; @override - String get contacts_manageRoom => 'Manage Room Server'; + String get contacts_manageRoom => 'Zarządzaj Serwerem Pokoju'; @override String get contacts_roomLogin => 'Logowanie do pokoju'; @@ -1591,7 +1591,7 @@ class AppLocalizationsPl extends AppLocalizations { String get repeater_management => 'Zarządzanie Powtórzami'; @override - String get room_management => 'Room Server Management'; + String get room_management => 'Zarządzanie Serwerem Pokoju'; @override String get repeater_managementTools => 'Narzędzia Zarządzania'; diff --git a/lib/l10n/app_localizations_pt.dart b/lib/l10n/app_localizations_pt.dart index 96cb130..2cdd2f3 100644 --- a/lib/l10n/app_localizations_pt.dart +++ b/lib/l10n/app_localizations_pt.dart @@ -650,7 +650,7 @@ class AppLocalizationsPt extends AppLocalizations { String get contacts_manageRepeater => 'Gerenciar Repetidor'; @override - String get contacts_manageRoom => 'Manage Room Server'; + String get contacts_manageRoom => 'Gerenciar Servidor de Sala'; @override String get contacts_roomLogin => 'Login no Quarto'; @@ -1589,7 +1589,7 @@ class AppLocalizationsPt extends AppLocalizations { String get repeater_management => 'Gerenciamento de Repetidor'; @override - String get room_management => 'Room Server Management'; + String get room_management => 'Gerenciamento de Servidor de Sala'; @override String get repeater_managementTools => 'Ferramentas de Gerenciamento'; diff --git a/lib/l10n/app_localizations_sk.dart b/lib/l10n/app_localizations_sk.dart index cdb39c7..2dda317 100644 --- a/lib/l10n/app_localizations_sk.dart +++ b/lib/l10n/app_localizations_sk.dart @@ -643,7 +643,7 @@ class AppLocalizationsSk extends AppLocalizations { String get contacts_manageRepeater => 'Spravovať opakované zoznamy'; @override - String get contacts_manageRoom => 'Manage Room Server'; + String get contacts_manageRoom => 'Spravovať server miestnosti'; @override String get contacts_roomLogin => 'Prihlásenie do miestnosti'; @@ -1584,7 +1584,7 @@ class AppLocalizationsSk extends AppLocalizations { String get repeater_management => 'Správa opakérov'; @override - String get room_management => 'Room Server Management'; + String get room_management => 'Správa servera miestnosti'; @override String get repeater_managementTools => 'Nástroje na správu'; diff --git a/lib/l10n/app_localizations_sl.dart b/lib/l10n/app_localizations_sl.dart index a54282c..122741c 100644 --- a/lib/l10n/app_localizations_sl.dart +++ b/lib/l10n/app_localizations_sl.dart @@ -645,7 +645,7 @@ class AppLocalizationsSl extends AppLocalizations { String get contacts_manageRepeater => 'Upravljajte Ponovitve'; @override - String get contacts_manageRoom => 'Manage Room Server'; + String get contacts_manageRoom => 'Upravljajte strežnik sobe'; @override String get contacts_roomLogin => 'Vnos v sobo'; @@ -1584,7 +1584,7 @@ class AppLocalizationsSl extends AppLocalizations { String get repeater_management => 'Upravljanje ponovitve'; @override - String get room_management => 'Room Server Management'; + String get room_management => 'Upravljanje stremlišča'; @override String get repeater_managementTools => 'Upravne orodje'; diff --git a/lib/l10n/app_localizations_sv.dart b/lib/l10n/app_localizations_sv.dart index 2b595a8..a1d8bd8 100644 --- a/lib/l10n/app_localizations_sv.dart +++ b/lib/l10n/app_localizations_sv.dart @@ -639,7 +639,7 @@ class AppLocalizationsSv extends AppLocalizations { String get contacts_manageRepeater => 'Hantera Upprepare'; @override - String get contacts_manageRoom => 'Manage Room Server'; + String get contacts_manageRoom => 'Hantera Rumserver'; @override String get contacts_roomLogin => 'Rum Inloggning'; @@ -1573,7 +1573,7 @@ class AppLocalizationsSv extends AppLocalizations { String get repeater_management => 'Återuppspelarens Hantering'; @override - String get room_management => 'Room Server Management'; + String get room_management => 'Rumserverhantering'; @override String get repeater_managementTools => 'Administrationsverktyg'; diff --git a/lib/l10n/app_localizations_zh.dart b/lib/l10n/app_localizations_zh.dart index 2c0cddb..57b1a96 100644 --- a/lib/l10n/app_localizations_zh.dart +++ b/lib/l10n/app_localizations_zh.dart @@ -612,7 +612,7 @@ class AppLocalizationsZh extends AppLocalizations { String get contacts_manageRepeater => '管理重复项'; @override - String get contacts_manageRoom => 'Manage Room Server'; + String get contacts_manageRoom => '管理房间服务器'; @override String get contacts_roomLogin => '房间登录'; @@ -1517,7 +1517,7 @@ class AppLocalizationsZh extends AppLocalizations { String get repeater_management => '重复器管理'; @override - String get room_management => 'Room Server Management'; + String get room_management => '房间服务器管理'; @override String get repeater_managementTools => '管理工具'; diff --git a/lib/l10n/app_pt.arb b/lib/l10n/app_pt.arb index 041b479..e05297d 100644 --- a/lib/l10n/app_pt.arb +++ b/lib/l10n/app_pt.arb @@ -1349,6 +1349,6 @@ "channels_scanQrCodeComingSoon": "Em breve", "channels_enterHashtag": "Insira hashtag", "channels_hashtagHint": "ex. #equipe", - "contacts_manageRoom": "Gerenciar Servidor de Sala {name} ({count})", + "contacts_manageRoom": "Gerenciar Servidor de Sala", "room_management": "Gerenciamento de Servidor de Sala" } diff --git a/lib/screens/contacts_screen.dart b/lib/screens/contacts_screen.dart index 8d15cc3..e91cd94 100644 --- a/lib/screens/contacts_screen.dart +++ b/lib/screens/contacts_screen.dart @@ -27,6 +27,11 @@ import 'map_screen.dart'; import 'repeater_hub_screen.dart'; import 'settings_screen.dart'; +enum RoomLoginDestination { + chat, + management, +} + class ContactsScreen extends StatefulWidget { final bool hideBackButton; @@ -277,8 +282,9 @@ class _ContactsScreenState extends State if (group.name.toLowerCase().contains(query)) return true; for (final key in group.memberKeys) { final contact = contactsByKey[key]; - if (contact != null && matchesContactQuery(contact, query)) + if (contact != null && matchesContactQuery(contact, query)) { return true; + } } return false; }) @@ -422,7 +428,7 @@ class _ContactsScreenState extends State if (contact.type == advTypeRepeater) { _showRepeaterLogin(context, contact); } else if (contact.type == advTypeRoom) { - _showRoomLogin(context, contact, false); + _showRoomLogin(context, contact, RoomLoginDestination.chat); } else { context.read().markContactRead(contact.publicKeyHex); Navigator.push( @@ -469,18 +475,21 @@ class _ContactsScreenState extends State ); } - void _showRoomLogin(BuildContext context, Contact room, bool settings) { + void _showRoomLogin( + BuildContext context, + Contact room, + RoomLoginDestination destination, + ) { showDialog( context: context, builder: (context) => RoomLoginDialog( room: room, onLogin: (password) { - // Navigate to chat screen after successful login context.read().markContactRead(room.publicKeyHex); Navigator.push( context, MaterialPageRoute( - builder: (context) => settings + builder: (context) => destination == RoomLoginDestination.management ? RepeaterHubScreen(repeater: room, password: password) : ChatScreen(contact: room), ), @@ -745,7 +754,7 @@ class _ContactsScreenState extends State children: [ if (isRepeater) ListTile( - leading: const Icon(Icons.settings, color: Colors.orange), + leading: const Icon(Icons.cell_tower, color: Colors.orange), title: Text(context.l10n.contacts_manageRepeater), onTap: () { Navigator.pop(sheetContext); @@ -758,15 +767,15 @@ class _ContactsScreenState extends State title: Text(context.l10n.contacts_roomLogin), onTap: () { Navigator.pop(sheetContext); - _showRoomLogin(context, contact, false); + _showRoomLogin(context, contact, RoomLoginDestination.chat); }, ), ListTile( - leading: const Icon(Icons.settings, color: Colors.orange), + leading: const Icon(Icons.room_preferences, color: Colors.orange), title: Text(context.l10n.room_management), onTap: () { Navigator.pop(sheetContext); - _showRoomLogin(context, contact, true); + _showRoomLogin(context, contact, RoomLoginDestination.management); }, ), ] else @@ -917,10 +926,12 @@ class _ContactTile extends StatelessWidget { final now = DateTime.now(); final diff = now.difference(lastSeen); - if (diff.isNegative || diff.inMinutes < 5) + if (diff.isNegative || diff.inMinutes < 5) { return context.l10n.contacts_lastSeenNow; - if (diff.inMinutes < 60) + } + if (diff.inMinutes < 60) { return context.l10n.contacts_lastSeenMinsAgo(diff.inMinutes); + } if (diff.inHours < 24) { final hours = diff.inHours; return hours == 1