diff --git a/lib/l10n/app_bg.arb b/lib/l10n/app_bg.arb index 7a3216d..377e0f5 100644 --- a/lib/l10n/app_bg.arb +++ b/lib/l10n/app_bg.arb @@ -1352,5 +1352,7 @@ "settings_locationIntervalSec": "Интервал за GPS (Секунди)", "settings_locationGPSEnable": "Активиране на GPS", "settings_locationGPSEnableSubtitle": "Активирайте автоматичното актуализиране на местоположението чрез GPS.", - "settings_locationIntervalInvalid": "Интервалът трябва да бъде поне 60 секунди и по-малко от 86400 секунди." + "settings_locationIntervalInvalid": "Интервалът трябва да бъде поне 60 секунди и по-малко от 86400 секунди.", + "room_management": "Управление на сървъра за стая", + "contacts_manageRoom": "Управление на сървър за стая" } diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index a208393..ba8f4d0 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -1348,9 +1348,5 @@ "channels_scanQrCode": "Scannen Sie einen QR-Code", "channels_scanQrCodeComingSoon": "Bald verfügbar", "channels_enterHashtag": "Gib Hashtag ein", - "channels_hashtagHint": "z.B. #team", - "settings_locationGPSEnable": "GPS aktivieren", - "settings_locationGPSEnableSubtitle": "Aktivieren Sie die automatische Aktualisierung der Standortdaten per GPS.", - "settings_locationIntervalInvalid": "Der Zeitraum muss mindestens 60 Sekunden betragen und weniger als 86400 Sekunden sein.", - "settings_locationIntervalSec": "Zeitintervall für GPS (Sekunden)" + "channels_hashtagHint": "z.B. #team" } diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 988a876..7224b22 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -258,7 +258,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", @@ -702,7 +703,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", @@ -765,6 +766,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 3c4453a..03ea4dd 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -1353,4 +1353,6 @@ "settings_locationGPSEnableSubtitle": "Habilita la actualización automática de la ubicación mediante GPS.", "settings_locationIntervalSec": "Intervalo para GPS (Segundos)", "settings_locationIntervalInvalid": "El intervalo debe ser de al menos 60 segundos y menor que 86400 segundos." + "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 13cde8e..d7f4b22 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -1349,8 +1349,10 @@ "channels_scanQrCodeComingSoon": "Bientôt disponible", "channels_enterHashtag": "Entrez le hashtag", "channels_hashtagHint": "ex. #équipe", - "settings_locationGPSEnableSubtitle": "Activer la mise à jour automatique de la position grâce au GPS.", - "settings_locationIntervalInvalid": "L'intervalle doit être d’au moins 60 secondes et inférieur à 86400 secondes.", - "settings_locationGPSEnable": "Activer le GPS", - "settings_locationIntervalSec": "Intervalle GPS (Secondes)" + "settings_locationGPSEnable": "Habilita GPS", + "settings_locationGPSEnableSubtitle": "Habilita la actualización automática de la ubicación mediante GPS.", + "settings_locationIntervalSec": "Intervalo pour GPS (Segundos)", + "settings_locationIntervalInvalid": "El intervalo debe ser de al menos 60 segundos y menor que 86400 segundos.", + "contacts_manageRoom": "Gestionar Servidor de Habitación", + "room_management": "Administración del Servidor de Habitación" } diff --git a/lib/l10n/app_it.arb b/lib/l10n/app_it.arb index d447c50..f2f5d28 100644 --- a/lib/l10n/app_it.arb +++ b/lib/l10n/app_it.arb @@ -1352,5 +1352,7 @@ "settings_locationGPSEnable": "Abilita GPS", "settings_locationGPSEnableSubtitle": "Abilita l'aggiornamento automatico della posizione tramite GPS.", "settings_locationIntervalSec": "Intervallo GPS (Secondi)", - "settings_locationIntervalInvalid": "L'intervallo deve essere di almeno 60 secondi e inferiore a 86400 secondi." + "settings_locationIntervalInvalid": "L'intervallo deve essere di almeno 60 secondi e inferiore a 86400 secondi.", + "contacts_manageRoom": "Gestisci Server Camera", + "room_management": "Gestione del Server di Camera" } diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index 2916b91..fc0e8e7 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -1308,10 +1308,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. @@ -2696,7 +2702,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. @@ -2891,6 +2897,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 2b5d9c7..5627eea 100644 --- a/lib/l10n/app_localizations_bg.dart +++ b/lib/l10n/app_localizations_bg.dart @@ -664,6 +664,9 @@ class AppLocalizationsBg extends AppLocalizations { @override String get contacts_manageRepeater => 'Управление на Повтарящ се Елемент'; + @override + String get contacts_manageRoom => 'Управление на сървър за стая'; + @override String get contacts_roomLogin => 'Вход в стаята'; @@ -1601,6 +1604,9 @@ class AppLocalizationsBg extends AppLocalizations { @override String get repeater_management => 'Управление на повторители'; + @override + 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 0161533..09290c5 100644 --- a/lib/l10n/app_localizations_de.dart +++ b/lib/l10n/app_localizations_de.dart @@ -661,6 +661,9 @@ class AppLocalizationsDe extends AppLocalizations { @override String get contacts_manageRepeater => 'Wiederholungen verwalten'; + @override + String get contacts_manageRoom => 'Verwalten Sie den Raumserver'; + @override String get contacts_roomLogin => 'Raum-Login'; @@ -1600,6 +1603,9 @@ class AppLocalizationsDe extends AppLocalizations { @override String get repeater_management => 'Repeater-Verwaltung'; + @override + String get room_management => 'Raumserververwaltung'; + @override String get repeater_managementTools => 'Verwaltungs-Tools'; diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index a7e88cb..6dcaebf 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -655,7 +655,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'; @@ -1453,7 +1456,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'; @@ -1575,6 +1578,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 497dd2a..e70fc6a 100644 --- a/lib/l10n/app_localizations_es.dart +++ b/lib/l10n/app_localizations_es.dart @@ -662,6 +662,9 @@ class AppLocalizationsEs extends AppLocalizations { @override String get contacts_manageRepeater => 'Gestionar Repetidor'; + @override + String get contacts_manageRoom => 'Gestionar Servidor de Habitación'; + @override String get contacts_roomLogin => 'Inicio de Sala'; @@ -1599,6 +1602,9 @@ class AppLocalizationsEs extends AppLocalizations { @override String get repeater_management => 'Gestión de Repetidores'; + @override + 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 50beba2..587043d 100644 --- a/lib/l10n/app_localizations_fr.dart +++ b/lib/l10n/app_localizations_fr.dart @@ -663,6 +663,9 @@ class AppLocalizationsFr extends AppLocalizations { @override String get contacts_manageRepeater => 'Gérer le répétiteur'; + @override + String get contacts_manageRoom => 'Gérer le serveur de salle'; + @override String get contacts_roomLogin => 'Connexion Salle'; @@ -1605,6 +1608,9 @@ class AppLocalizationsFr extends AppLocalizations { @override String get repeater_management => 'Gestion des répétiteurs'; + @override + 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 875e793..c103eb5 100644 --- a/lib/l10n/app_localizations_it.dart +++ b/lib/l10n/app_localizations_it.dart @@ -660,6 +660,9 @@ class AppLocalizationsIt extends AppLocalizations { @override String get contacts_manageRepeater => 'Gestisci Ripetitore'; + @override + String get contacts_manageRoom => 'Gestisci Server Camera'; + @override String get contacts_roomLogin => 'Login Camera'; @@ -1597,6 +1600,9 @@ class AppLocalizationsIt extends AppLocalizations { @override String get repeater_management => 'Gestione Ripetitori'; + @override + 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 a7112bd..0b75744 100644 --- a/lib/l10n/app_localizations_nl.dart +++ b/lib/l10n/app_localizations_nl.dart @@ -658,6 +658,9 @@ class AppLocalizationsNl extends AppLocalizations { @override String get contacts_manageRepeater => 'Beheer Repeater'; + @override + String get contacts_manageRoom => 'Beheer Ruimte Server'; + @override String get contacts_roomLogin => 'Ruimte Inloggen'; @@ -1592,6 +1595,9 @@ class AppLocalizationsNl extends AppLocalizations { @override String get repeater_management => 'Beheer Repeaters'; + @override + 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 3e727c0..c8a11f6 100644 --- a/lib/l10n/app_localizations_pl.dart +++ b/lib/l10n/app_localizations_pl.dart @@ -663,6 +663,9 @@ class AppLocalizationsPl extends AppLocalizations { @override String get contacts_manageRepeater => 'Zarządzaj Powtórzami'; + @override + String get contacts_manageRoom => 'Zarządzaj Serwerem Pokoju'; + @override String get contacts_roomLogin => 'Logowanie do pokoju'; @@ -1601,6 +1604,9 @@ class AppLocalizationsPl extends AppLocalizations { @override String get repeater_management => 'Zarządzanie Powtórzami'; + @override + 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 769853e..339a77c 100644 --- a/lib/l10n/app_localizations_pt.dart +++ b/lib/l10n/app_localizations_pt.dart @@ -663,6 +663,9 @@ class AppLocalizationsPt extends AppLocalizations { @override String get contacts_manageRepeater => 'Gerenciar Repetidor'; + @override + String get contacts_manageRoom => 'Gerenciar Servidor de Sala'; + @override String get contacts_roomLogin => 'Login no Quarto'; @@ -1599,6 +1602,9 @@ class AppLocalizationsPt extends AppLocalizations { @override String get repeater_management => 'Gerenciamento de Repetidor'; + @override + 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 aac0ced..20a7943 100644 --- a/lib/l10n/app_localizations_sk.dart +++ b/lib/l10n/app_localizations_sk.dart @@ -656,6 +656,9 @@ class AppLocalizationsSk extends AppLocalizations { @override String get contacts_manageRepeater => 'Spravovať opakované zoznamy'; + @override + String get contacts_manageRoom => 'Spravovať server miestnosti'; + @override String get contacts_roomLogin => 'Prihlásenie do miestnosti'; @@ -1594,6 +1597,9 @@ class AppLocalizationsSk extends AppLocalizations { @override String get repeater_management => 'Správa opakérov'; + @override + 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 61e4033..571ddcf 100644 --- a/lib/l10n/app_localizations_sl.dart +++ b/lib/l10n/app_localizations_sl.dart @@ -658,6 +658,9 @@ class AppLocalizationsSl extends AppLocalizations { @override String get contacts_manageRepeater => 'Upravljajte Ponovitve'; + @override + String get contacts_manageRoom => 'Upravljajte strežnik sobe'; + @override String get contacts_roomLogin => 'Vnos v sobo'; @@ -1594,6 +1597,9 @@ class AppLocalizationsSl extends AppLocalizations { @override String get repeater_management => 'Upravljanje ponovitve'; + @override + 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 2348e95..59b322a 100644 --- a/lib/l10n/app_localizations_sv.dart +++ b/lib/l10n/app_localizations_sv.dart @@ -652,6 +652,9 @@ class AppLocalizationsSv extends AppLocalizations { @override String get contacts_manageRepeater => 'Hantera Upprepare'; + @override + String get contacts_manageRoom => 'Hantera Rumserver'; + @override String get contacts_roomLogin => 'Rum Inloggning'; @@ -1583,6 +1586,9 @@ class AppLocalizationsSv extends AppLocalizations { @override String get repeater_management => 'Återuppspelarens Hantering'; + @override + 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 c68a38b..0a60655 100644 --- a/lib/l10n/app_localizations_zh.dart +++ b/lib/l10n/app_localizations_zh.dart @@ -623,6 +623,9 @@ class AppLocalizationsZh extends AppLocalizations { @override String get contacts_manageRepeater => '管理重复项'; + @override + String get contacts_manageRoom => '管理房间服务器'; + @override String get contacts_roomLogin => '房间登录'; @@ -1525,6 +1528,9 @@ class AppLocalizationsZh extends AppLocalizations { @override String get repeater_management => '重复器管理'; + @override + String get room_management => '房间服务器管理'; + @override String get repeater_managementTools => '管理工具'; diff --git a/lib/l10n/app_nl.arb b/lib/l10n/app_nl.arb index 5f2e2f7..9131b4e 100644 --- a/lib/l10n/app_nl.arb +++ b/lib/l10n/app_nl.arb @@ -1350,7 +1350,9 @@ "channels_enterHashtag": "Voer hashtag in", "channels_hashtagHint": "bijv. #team", "settings_locationGPSEnable": "GPS inschakelen", + "settings_locationGPSEnableSubtitle": "Activeer automatisch locatieupdates via GPS.", "settings_locationIntervalSec": "Interval voor GPS (Seconden)", "settings_locationIntervalInvalid": "De intervallen moeten minstens 60 seconden zijn en minder dan 86400 seconden.", - "settings_locationGPSEnableSubtitle": "Activeer automatisch locatieupdates via GPS." + "contacts_manageRoom": "Beheer Ruimte Server", + "room_management": "Beheer Server Kamer" } diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb index 15ce2b8..81d4df0 100644 --- a/lib/l10n/app_pl.arb +++ b/lib/l10n/app_pl.arb @@ -1350,7 +1350,9 @@ "channels_enterHashtag": "Wprowadź hashtag", "channels_hashtagHint": "np. #zespół", "settings_locationGPSEnable": "Włącz GPS", - "settings_locationIntervalSec": "Interwał dla GPS (Sekundy)", "settings_locationGPSEnableSubtitle": "Włącza automatyczne aktualizowanie pozycji za pomocą GPS.", - "settings_locationIntervalInvalid": "Interwał musi wynosić co najmniej 60 sekund i mniej niż 86400 sekund." + "settings_locationIntervalSec": "Interwał dla GPS (Sekundy)", + "settings_locationIntervalInvalid": "Interwał musi wynosić co najmniej 60 sekund i mniej niż 86400 sekund.", + "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 0b09582..8b95769 100644 --- a/lib/l10n/app_pt.arb +++ b/lib/l10n/app_pt.arb @@ -1353,4 +1353,6 @@ "settings_locationGPSEnableSubtitle": "Habilita a atualização automática da localização via GPS.", "settings_locationIntervalInvalid": "O intervalo deve ser de pelo menos 60 segundos e inferior a 86400 segundos.", "settings_locationIntervalSec": "Intervalo para GPS (Segundos)" + "contacts_manageRoom": "Gerenciar Servidor de Sala", + "room_management": "Gerenciamento de Servidor de Sala" } diff --git a/lib/l10n/app_sk.arb b/lib/l10n/app_sk.arb index 06de024..7b23791 100644 --- a/lib/l10n/app_sk.arb +++ b/lib/l10n/app_sk.arb @@ -559,7 +559,7 @@ "chat_setCustomPath": "Nastaviť vlastnú cestu", "chat_setCustomPathSubtitle": "Ručne zadajte trasu.", "chat_clearPath": "Vyčistiš cestu", - "chat_clearPathSubtitle": "Znovu nájsť vynútene pri nasledujacej pošlite", + "chat_clearPathSubtitle": "Znovu nájsť vynútene pri nasledujúcej pošlite", "chat_pathCleared": "Cesta vyčistená. Nasledujúce prepočetné získa trasu znova.", "chat_floodModeSubtitle": "Použite prepínanie trasy v navigačnom paneli.", "chat_floodModeEnabled": "Odosporňovacia prevádzka je zapnutá. Vypnite ju znova cez ikonu routovania v navigačnom páse.", @@ -1352,5 +1352,7 @@ "settings_locationGPSEnable": "Aktivovať GPS", "settings_locationGPSEnableSubtitle": "Povolí automatické aktualizovanie polohy pomocou GPS.", "settings_locationIntervalSec": "Interval pre GPS (Sekundy)", - "settings_locationIntervalInvalid": "Interval musí byť aspoň 60 sekúnd a menej ako 86400 sekúnd." + "settings_locationIntervalInvalid": "Interval musí byť aspoň 60 sekúnd a menej ako 86400 sekúnd.", + "contacts_manageRoom": "Spravovať server miestnosti", + "room_management": "Správa servera miestnosti" } diff --git a/lib/l10n/app_sl.arb b/lib/l10n/app_sl.arb index 05e99b7..e07b1f2 100644 --- a/lib/l10n/app_sl.arb +++ b/lib/l10n/app_sl.arb @@ -176,7 +176,7 @@ "appSettings_languageBg": "Български", "appSettings_notifications": "Obveščanja", "appSettings_enableNotifications": "Omogoči obveščanje", - "appSettings_enableNotificationsSubtitle": "Prejmujte obvestila o sporočilih in oglasih", + "appSettings_enableNotificationsSubtitle": "Prejmite obvestila o sporočilih in oglasih", "appSettings_notificationPermissionDenied": "Odobritev obvestila zavrnjena", "appSettings_notificationsEnabled": "Obvestila omogočena", "appSettings_notificationsDisabled": "Obvestila so izklopljena", @@ -256,7 +256,7 @@ "contacts_contactsWillAppear": "Kontakti se bodo prikazali, ko naprave oglasijo.", "contacts_searchContacts": "Iskanje kontaktov...", "contacts_noUnreadContacts": "Nerešeno kontaktov.", - "contacts_noContactsFound": "Niti ena osebe ali skupine ni najdena.", + "contacts_noContactsFound": "Niti ena oseba ali skupine ni najdena.", "contacts_deleteContact": "Izbrisati Kontakt", "contacts_removeConfirm": "Izbrisati {contactName} iz kontaktov?", "@contacts_removeConfirm": { @@ -291,7 +291,7 @@ } }, "contacts_filterContacts": "Filtri kontakt\\,...", - "contacts_noContactsMatchFilter": "Niti ena osebe ne ustreza vašemu kriteriju.", + "contacts_noContactsMatchFilter": "Niti ena oseba ne ustreza vašemu kriteriju.", "contacts_noMembers": "Nič članov.", "contacts_lastSeenNow": "Datum zadnjega vpisa zdaj", "contacts_lastSeenMinsAgo": "Zadnjič videti {minutes} minut nazaj", @@ -606,7 +606,7 @@ }, "map_title": "Mapa omrežja", "map_noNodesWithLocation": "Nihče od notranjih elementov nima podatkov o lokaciji.", - "map_nodesNeedGps": "Omrežje morajo deliti svoje GPS koordinate,\nda se prikazajo na zemljeobrazniku.", + "map_nodesNeedGps": "Omrežje morajo deliti svoje GPS koordinate,\nda se prikazao na zemljeobrazniku.", "map_nodesCount": "Omize: {count}", "@map_nodesCount": { "placeholders": { @@ -1351,6 +1351,8 @@ "channels_hashtagHint": "npr. #ekipa", "settings_locationGPSEnable": "Omogoči GPS", "settings_locationGPSEnableSubtitle": "Omogoči samodejno posodabljanje lokacije z GPS-jem.", + "settings_locationIntervalSec": "Interval za GPS (Sekunde)", "settings_locationIntervalInvalid": "Intervallo mora biti vsaj 60 sekund in manj kot 86400 sekund.", - "settings_locationIntervalSec": "Interval za GPS (Sekunde)" + "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 deef6c6..020e8b2 100644 --- a/lib/l10n/app_sv.arb +++ b/lib/l10n/app_sv.arb @@ -1349,8 +1349,10 @@ "channels_scanQrCodeComingSoon": "Kommer snart", "channels_enterHashtag": "Ange hashtag", "channels_hashtagHint": "t.ex. #team", - "settings_locationGPSEnableSubtitle": "Aktiverar automatiska uppdateringar av platsen med hjälp av GPS.", "settings_locationGPSEnable": "Aktivera GPS", + "settings_locationGPSEnableSubtitle": "Aktivera automatiska uppdateringar av platsen med hjälp av GPS.", "settings_locationIntervalSec": "Interval för GPS (Sekunder)", - "settings_locationIntervalInvalid": "Intervalet måste vara minst 60 sekunder och mindre än 86400 sekunder." + "settings_locationIntervalInvalid": "Intervalet måste vara minst 60 sekunder och mindre än 86400 sekunder.", + "contacts_manageRoom": "Hantera Rumserver", + "room_management": "Rumserverhantering" } diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index d0f4dce..52973fa 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -1352,5 +1352,7 @@ "settings_locationGPSEnable": "启用GPS", "settings_locationGPSEnableSubtitle": "启用GPS自动更新位置。", "settings_locationIntervalSec": "GPS 间隔(秒)", - "settings_locationIntervalInvalid": "时间间隔必须至少为60秒,且小于86400秒。" + "settings_locationIntervalInvalid": "时间间隔必须至少为60秒,且小于86400秒。", + "contacts_manageRoom": "管理房间服务器", + "room_management": "房间服务器管理" } diff --git a/lib/screens/contacts_screen.dart b/lib/screens/contacts_screen.dart index b9ceb84..e91cd94 100644 --- a/lib/screens/contacts_screen.dart +++ b/lib/screens/contacts_screen.dart @@ -27,13 +27,15 @@ import 'map_screen.dart'; import 'repeater_hub_screen.dart'; import 'settings_screen.dart'; +enum RoomLoginDestination { + chat, + management, +} + 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 +116,8 @@ class _ContactsScreenState extends State top: false, child: QuickSwitchBar( selectedIndex: 0, - onDestinationSelected: (index) => _handleQuickSwitch(index, context), + onDestinationSelected: (index) => + _handleQuickSwitch(index, context), ), ), ), @@ -168,8 +171,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 +203,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 +245,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 +266,48 @@ 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 +325,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 +372,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 +395,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 +410,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 +428,7 @@ class _ContactsScreenState extends State if (contact.type == advTypeRepeater) { _showRepeaterLogin(context, contact); } else if (contact.type == advTypeRoom) { - _showRoomLogin(context, contact); + _showRoomLogin(context, contact, RoomLoginDestination.chat); } else { context.read().markContactRead(contact.publicKeyHex); Navigator.push( @@ -403,17 +444,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 +466,8 @@ class _ContactsScreenState extends State Navigator.push( context, MaterialPageRoute( - builder: (context) => RepeaterHubScreen( - repeater: repeater, - password: password, - ), + builder: (context) => + RepeaterHubScreen(repeater: repeater, password: password), ), ); }, @@ -440,18 +475,23 @@ class _ContactsScreenState extends State ); } - void _showRoomLogin(BuildContext context, Contact room) { + 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) => ChatScreen(contact: room), + builder: (context) => destination == RoomLoginDestination.management + ? RepeaterHubScreen(repeater: room, password: password) + : ChatScreen(contact: room), ), ); }, @@ -459,7 +499,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 +522,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 +569,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 +598,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 +638,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 +680,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 +692,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 +712,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 +725,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, + ), ), ], ); @@ -682,16 +761,24 @@ class _ContactsScreenState extends State _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, RoomLoginDestination.chat); }, - ) - else + ), + ListTile( + leading: const Icon(Icons.room_preferences, color: Colors.orange), + title: Text(context.l10n.room_management), + onTap: () { + Navigator.pop(sheetContext); + _showRoomLogin(context, contact, RoomLoginDestination.management); + }, + ), + ] else ListTile( leading: const Icon(Icons.chat), title: Text(context.l10n.contacts_openChat), @@ -702,7 +789,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 +824,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 +852,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 +887,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 +926,21 @@ 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/map_screen.dart b/lib/screens/map_screen.dart index 2aa3daa..5b804eb 100644 --- a/lib/screens/map_screen.dart +++ b/lib/screens/map_screen.dart @@ -273,6 +273,9 @@ class _MapScreenState extends State { initialZoom: initialZoom, minZoom: 2.0, maxZoom: 18.0, + interactionOptions: InteractionOptions( + flags: ~InteractiveFlag.rotate + ), onTap: (_, latLng) { if (_isSelectingPoi) { setState(() { 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]), ), ], ),