mirror of
https://github.com/zjs81/meshcore-open.git
synced 2026-07-13 12:22:01 +10:00
Merge pull request #51 from wel97459/dev-roomManagement
Added room server management
This commit is contained in:
+3
-2
@@ -822,7 +822,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"login_failedMessage": "Входът не беше успешен. Или паролата е грешна, или повторителят е недостъпен.",
|
"login_failedMessage": "Входът не беше успешен. Или паролата е грешна, или повторителят е недостъпен.",
|
||||||
|
|
||||||
"common_reload": "Презареди",
|
"common_reload": "Презареди",
|
||||||
"common_clear": "Изчисти",
|
"common_clear": "Изчисти",
|
||||||
"path_currentPath": "Текущ път: {path}",
|
"path_currentPath": "Текущ път: {path}",
|
||||||
@@ -1349,5 +1348,7 @@
|
|||||||
"channels_scanQrCode": "Сканирайте QR код",
|
"channels_scanQrCode": "Сканирайте QR код",
|
||||||
"channels_scanQrCodeComingSoon": "Ще излезе скоро",
|
"channels_scanQrCodeComingSoon": "Ще излезе скоро",
|
||||||
"channels_enterHashtag": "Въведете хаштаг",
|
"channels_enterHashtag": "Въведете хаштаг",
|
||||||
"channels_hashtagHint": "напр. #отбор"
|
"channels_hashtagHint": "напр. #отбор",
|
||||||
|
"room_management": "Управление на сървъра за стая",
|
||||||
|
"contacts_manageRoom": "Управление на сървър за стая"
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -822,7 +822,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"login_failedMessage": "Anmeldung fehlgeschlagen. Entweder ist das Passwort falsch oder der Repeater ist nicht erreichbar.",
|
"login_failedMessage": "Anmeldung fehlgeschlagen. Entweder ist das Passwort falsch oder der Repeater ist nicht erreichbar.",
|
||||||
|
|
||||||
"common_reload": "Neu laden",
|
"common_reload": "Neu laden",
|
||||||
"common_clear": "Löschen",
|
"common_clear": "Löschen",
|
||||||
"path_currentPath": "Aktiver Pfad: {path}",
|
"path_currentPath": "Aktiver Pfad: {path}",
|
||||||
@@ -1349,5 +1348,7 @@
|
|||||||
"channels_scanQrCode": "Scannen Sie einen QR-Code",
|
"channels_scanQrCode": "Scannen Sie einen QR-Code",
|
||||||
"channels_scanQrCodeComingSoon": "Bald verfügbar",
|
"channels_scanQrCodeComingSoon": "Bald verfügbar",
|
||||||
"channels_enterHashtag": "Gib Hashtag ein",
|
"channels_enterHashtag": "Gib Hashtag ein",
|
||||||
"channels_hashtagHint": "z.B. #team"
|
"channels_hashtagHint": "z.B. #team",
|
||||||
|
"contacts_manageRoom": "Verwalten Sie den Raumserver",
|
||||||
|
"room_management": "Raumserververwaltung"
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-2
@@ -253,7 +253,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"contacts_manageRepeater": "Manage Repeater",
|
"contacts_manageRepeater": "Manage Repeater",
|
||||||
"contacts_roomLogin": "Room Login",
|
"contacts_manageRoom": "Manage Room Server",
|
||||||
|
"contacts_roomLogin": "Room Server Login",
|
||||||
"contacts_openChat": "Open Chat",
|
"contacts_openChat": "Open Chat",
|
||||||
"contacts_editGroup": "Edit Group",
|
"contacts_editGroup": "Edit Group",
|
||||||
"contacts_deleteGroup": "Delete Group",
|
"contacts_deleteGroup": "Delete Group",
|
||||||
@@ -697,7 +698,7 @@
|
|||||||
"dialog_disconnectConfirm": "Are you sure you want to disconnect from this device?",
|
"dialog_disconnectConfirm": "Are you sure you want to disconnect from this device?",
|
||||||
|
|
||||||
"login_repeaterLogin": "Repeater Login",
|
"login_repeaterLogin": "Repeater Login",
|
||||||
"login_roomLogin": "Room Login",
|
"login_roomLogin": "Room Server Login",
|
||||||
"login_password": "Password",
|
"login_password": "Password",
|
||||||
"login_enterPassword": "Enter password",
|
"login_enterPassword": "Enter password",
|
||||||
"login_savePassword": "Save password",
|
"login_savePassword": "Save password",
|
||||||
@@ -760,6 +761,7 @@
|
|||||||
"path_setPath": "Set Path",
|
"path_setPath": "Set Path",
|
||||||
|
|
||||||
"repeater_management": "Repeater Management",
|
"repeater_management": "Repeater Management",
|
||||||
|
"room_management": "Room Server Management",
|
||||||
"repeater_managementTools": "Management Tools",
|
"repeater_managementTools": "Management Tools",
|
||||||
"repeater_status": "Status",
|
"repeater_status": "Status",
|
||||||
"repeater_statusSubtitle": "View repeater status, stats, and neighbors",
|
"repeater_statusSubtitle": "View repeater status, stats, and neighbors",
|
||||||
|
|||||||
+3
-2
@@ -822,7 +822,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"login_failedMessage": "Inicio fallido. La contraseña es incorrecta o el repetidor no está disponible.",
|
"login_failedMessage": "Inicio fallido. La contraseña es incorrecta o el repetidor no está disponible.",
|
||||||
|
|
||||||
"common_reload": "Recargar",
|
"common_reload": "Recargar",
|
||||||
"common_clear": "Borrar",
|
"common_clear": "Borrar",
|
||||||
"path_currentPath": "Ruta actual: {path}",
|
"path_currentPath": "Ruta actual: {path}",
|
||||||
@@ -1349,5 +1348,7 @@
|
|||||||
"channels_scanQrCode": "Escanear un Código QR",
|
"channels_scanQrCode": "Escanear un Código QR",
|
||||||
"channels_scanQrCodeComingSoon": "Próximamente",
|
"channels_scanQrCodeComingSoon": "Próximamente",
|
||||||
"channels_enterHashtag": "Introducir hashtag",
|
"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"
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -822,7 +822,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"login_failedMessage": "Connexion échouée. Soit le mot de passe est incorrect, soit le relais est injoignable.",
|
"login_failedMessage": "Connexion échouée. Soit le mot de passe est incorrect, soit le relais est injoignable.",
|
||||||
|
|
||||||
"common_reload": "Recharger",
|
"common_reload": "Recharger",
|
||||||
"common_clear": "Effacer",
|
"common_clear": "Effacer",
|
||||||
"path_currentPath": "Chemin actuel : {path}",
|
"path_currentPath": "Chemin actuel : {path}",
|
||||||
@@ -1349,5 +1348,7 @@
|
|||||||
"channels_scanQrCode": "Scanner un code QR",
|
"channels_scanQrCode": "Scanner un code QR",
|
||||||
"channels_scanQrCodeComingSoon": "Bientôt disponible",
|
"channels_scanQrCodeComingSoon": "Bientôt disponible",
|
||||||
"channels_enterHashtag": "Entrez le hashtag",
|
"channels_enterHashtag": "Entrez le hashtag",
|
||||||
"channels_hashtagHint": "ex. #équipe"
|
"channels_hashtagHint": "ex. #équipe",
|
||||||
|
"contacts_manageRoom": "Gérer le serveur de salle",
|
||||||
|
"room_management": "Gestion du serveur de pièce"
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -822,7 +822,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"login_failedMessage": "Accesso fallito. La password non è corretta oppure il ripetitore non è raggiungibile.",
|
"login_failedMessage": "Accesso fallito. La password non è corretta oppure il ripetitore non è raggiungibile.",
|
||||||
|
|
||||||
"common_reload": "Ricaricare",
|
"common_reload": "Ricaricare",
|
||||||
"common_clear": "Cancella",
|
"common_clear": "Cancella",
|
||||||
"path_currentPath": "Percorso corrente: {path}",
|
"path_currentPath": "Percorso corrente: {path}",
|
||||||
@@ -1349,5 +1348,7 @@
|
|||||||
"channels_scanQrCode": "Scansiona un codice QR",
|
"channels_scanQrCode": "Scansiona un codice QR",
|
||||||
"channels_scanQrCodeComingSoon": "Arriverà presto",
|
"channels_scanQrCodeComingSoon": "Arriverà presto",
|
||||||
"channels_enterHashtag": "Inserisci hashtag",
|
"channels_enterHashtag": "Inserisci hashtag",
|
||||||
"channels_hashtagHint": "es. #team"
|
"channels_hashtagHint": "es. #team",
|
||||||
|
"room_management": "Gestione del Server di Camera",
|
||||||
|
"contacts_manageRoom": "Gestisci Server Camera"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1284,10 +1284,16 @@ abstract class AppLocalizations {
|
|||||||
/// **'Manage Repeater'**
|
/// **'Manage Repeater'**
|
||||||
String get contacts_manageRepeater;
|
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.
|
/// No description provided for @contacts_roomLogin.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Room Login'**
|
/// **'Room Server Login'**
|
||||||
String get contacts_roomLogin;
|
String get contacts_roomLogin;
|
||||||
|
|
||||||
/// No description provided for @contacts_openChat.
|
/// No description provided for @contacts_openChat.
|
||||||
@@ -2672,7 +2678,7 @@ abstract class AppLocalizations {
|
|||||||
/// No description provided for @login_roomLogin.
|
/// No description provided for @login_roomLogin.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Room Login'**
|
/// **'Room Server Login'**
|
||||||
String get login_roomLogin;
|
String get login_roomLogin;
|
||||||
|
|
||||||
/// No description provided for @login_password.
|
/// No description provided for @login_password.
|
||||||
@@ -2867,6 +2873,12 @@ abstract class AppLocalizations {
|
|||||||
/// **'Repeater Management'**
|
/// **'Repeater Management'**
|
||||||
String get 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.
|
/// No description provided for @repeater_managementTools.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|||||||
@@ -650,6 +650,9 @@ class AppLocalizationsBg extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get contacts_manageRepeater => 'Управление на Повтарящ се Елемент';
|
String get contacts_manageRepeater => 'Управление на Повтарящ се Елемент';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get contacts_manageRoom => 'Управление на сървър за стая';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contacts_roomLogin => 'Вход в стаята';
|
String get contacts_roomLogin => 'Вход в стаята';
|
||||||
|
|
||||||
@@ -1587,6 +1590,9 @@ class AppLocalizationsBg extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get repeater_management => 'Управление на повторители';
|
String get repeater_management => 'Управление на повторители';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get room_management => 'Управление на сървъра за стая';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_managementTools => 'Инструменти за управление';
|
String get repeater_managementTools => 'Инструменти за управление';
|
||||||
|
|
||||||
|
|||||||
@@ -647,6 +647,9 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get contacts_manageRepeater => 'Wiederholungen verwalten';
|
String get contacts_manageRepeater => 'Wiederholungen verwalten';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get contacts_manageRoom => 'Verwalten Sie den Raumserver';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contacts_roomLogin => 'Raum-Login';
|
String get contacts_roomLogin => 'Raum-Login';
|
||||||
|
|
||||||
@@ -1586,6 +1589,9 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get repeater_management => 'Repeater-Verwaltung';
|
String get repeater_management => 'Repeater-Verwaltung';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get room_management => 'Raumserververwaltung';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_managementTools => 'Verwaltungs-Tools';
|
String get repeater_managementTools => 'Verwaltungs-Tools';
|
||||||
|
|
||||||
|
|||||||
@@ -641,7 +641,10 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
String get contacts_manageRepeater => 'Manage Repeater';
|
String get contacts_manageRepeater => 'Manage Repeater';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contacts_roomLogin => 'Room Login';
|
String get contacts_manageRoom => 'Manage Room Server';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get contacts_roomLogin => 'Room Server Login';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contacts_openChat => 'Open Chat';
|
String get contacts_openChat => 'Open Chat';
|
||||||
@@ -1439,7 +1442,7 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
String get login_repeaterLogin => 'Repeater Login';
|
String get login_repeaterLogin => 'Repeater Login';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get login_roomLogin => 'Room Login';
|
String get login_roomLogin => 'Room Server Login';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get login_password => 'Password';
|
String get login_password => 'Password';
|
||||||
@@ -1561,6 +1564,9 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get repeater_management => 'Repeater Management';
|
String get repeater_management => 'Repeater Management';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get room_management => 'Room Server Management';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_managementTools => 'Management Tools';
|
String get repeater_managementTools => 'Management Tools';
|
||||||
|
|
||||||
|
|||||||
@@ -648,6 +648,9 @@ class AppLocalizationsEs extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get contacts_manageRepeater => 'Gestionar Repetidor';
|
String get contacts_manageRepeater => 'Gestionar Repetidor';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get contacts_manageRoom => 'Gestionar Servidor de Habitación';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contacts_roomLogin => 'Inicio de Sala';
|
String get contacts_roomLogin => 'Inicio de Sala';
|
||||||
|
|
||||||
@@ -1585,6 +1588,9 @@ class AppLocalizationsEs extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get repeater_management => 'Gestión de Repetidores';
|
String get repeater_management => 'Gestión de Repetidores';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get room_management => 'Administración del Servidor de Habitación';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_managementTools => 'Herramientas de Gestión';
|
String get repeater_managementTools => 'Herramientas de Gestión';
|
||||||
|
|
||||||
|
|||||||
@@ -649,6 +649,9 @@ class AppLocalizationsFr extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get contacts_manageRepeater => 'Gérer le répétiteur';
|
String get contacts_manageRepeater => 'Gérer le répétiteur';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get contacts_manageRoom => 'Gérer le serveur de salle';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contacts_roomLogin => 'Connexion Salle';
|
String get contacts_roomLogin => 'Connexion Salle';
|
||||||
|
|
||||||
@@ -1591,6 +1594,9 @@ class AppLocalizationsFr extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get repeater_management => 'Gestion des répétiteurs';
|
String get repeater_management => 'Gestion des répétiteurs';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get room_management => 'Gestion du serveur de pièce';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_managementTools => 'Outils de Gestion';
|
String get repeater_managementTools => 'Outils de Gestion';
|
||||||
|
|
||||||
|
|||||||
@@ -646,6 +646,9 @@ class AppLocalizationsIt extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get contacts_manageRepeater => 'Gestisci Ripetitore';
|
String get contacts_manageRepeater => 'Gestisci Ripetitore';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get contacts_manageRoom => 'Gestisci Server Camera';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contacts_roomLogin => 'Login Camera';
|
String get contacts_roomLogin => 'Login Camera';
|
||||||
|
|
||||||
@@ -1583,6 +1586,9 @@ class AppLocalizationsIt extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get repeater_management => 'Gestione Ripetitori';
|
String get repeater_management => 'Gestione Ripetitori';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get room_management => 'Gestione del Server di Camera';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_managementTools => 'Strumenti di Gestione';
|
String get repeater_managementTools => 'Strumenti di Gestione';
|
||||||
|
|
||||||
|
|||||||
@@ -644,6 +644,9 @@ class AppLocalizationsNl extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get contacts_manageRepeater => 'Beheer Repeater';
|
String get contacts_manageRepeater => 'Beheer Repeater';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get contacts_manageRoom => 'Beheer Ruimte Server';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contacts_roomLogin => 'Ruimte Inloggen';
|
String get contacts_roomLogin => 'Ruimte Inloggen';
|
||||||
|
|
||||||
@@ -1578,6 +1581,9 @@ class AppLocalizationsNl extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get repeater_management => 'Beheer Repeaters';
|
String get repeater_management => 'Beheer Repeaters';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get room_management => 'Beheer Server Kamer';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_managementTools => 'Beheerinstrumenten';
|
String get repeater_managementTools => 'Beheerinstrumenten';
|
||||||
|
|
||||||
|
|||||||
@@ -649,6 +649,9 @@ class AppLocalizationsPl extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get contacts_manageRepeater => 'Zarządzaj Powtórzami';
|
String get contacts_manageRepeater => 'Zarządzaj Powtórzami';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get contacts_manageRoom => 'Zarządzaj Serwerem Pokoju';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contacts_roomLogin => 'Logowanie do pokoju';
|
String get contacts_roomLogin => 'Logowanie do pokoju';
|
||||||
|
|
||||||
@@ -1587,6 +1590,9 @@ class AppLocalizationsPl extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get repeater_management => 'Zarządzanie Powtórzami';
|
String get repeater_management => 'Zarządzanie Powtórzami';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get room_management => 'Zarządzanie Serwerem Pokoju';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_managementTools => 'Narzędzia Zarządzania';
|
String get repeater_managementTools => 'Narzędzia Zarządzania';
|
||||||
|
|
||||||
|
|||||||
@@ -649,6 +649,9 @@ class AppLocalizationsPt extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get contacts_manageRepeater => 'Gerenciar Repetidor';
|
String get contacts_manageRepeater => 'Gerenciar Repetidor';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get contacts_manageRoom => 'Gerenciar Servidor de Sala';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contacts_roomLogin => 'Login no Quarto';
|
String get contacts_roomLogin => 'Login no Quarto';
|
||||||
|
|
||||||
@@ -1585,6 +1588,9 @@ class AppLocalizationsPt extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get repeater_management => 'Gerenciamento de Repetidor';
|
String get repeater_management => 'Gerenciamento de Repetidor';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get room_management => 'Gerenciamento de Servidor de Sala';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_managementTools => 'Ferramentas de Gerenciamento';
|
String get repeater_managementTools => 'Ferramentas de Gerenciamento';
|
||||||
|
|
||||||
|
|||||||
@@ -642,6 +642,9 @@ class AppLocalizationsSk extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get contacts_manageRepeater => 'Spravovať opakované zoznamy';
|
String get contacts_manageRepeater => 'Spravovať opakované zoznamy';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get contacts_manageRoom => 'Spravovať server miestnosti';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contacts_roomLogin => 'Prihlásenie do miestnosti';
|
String get contacts_roomLogin => 'Prihlásenie do miestnosti';
|
||||||
|
|
||||||
@@ -1580,6 +1583,9 @@ class AppLocalizationsSk extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get repeater_management => 'Správa opakérov';
|
String get repeater_management => 'Správa opakérov';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get room_management => 'Správa servera miestnosti';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_managementTools => 'Nástroje na správu';
|
String get repeater_managementTools => 'Nástroje na správu';
|
||||||
|
|
||||||
|
|||||||
@@ -644,6 +644,9 @@ class AppLocalizationsSl extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get contacts_manageRepeater => 'Upravljajte Ponovitve';
|
String get contacts_manageRepeater => 'Upravljajte Ponovitve';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get contacts_manageRoom => 'Upravljajte strežnik sobe';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contacts_roomLogin => 'Vnos v sobo';
|
String get contacts_roomLogin => 'Vnos v sobo';
|
||||||
|
|
||||||
@@ -1580,6 +1583,9 @@ class AppLocalizationsSl extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get repeater_management => 'Upravljanje ponovitve';
|
String get repeater_management => 'Upravljanje ponovitve';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get room_management => 'Upravljanje stremlišča';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_managementTools => 'Upravne orodje';
|
String get repeater_managementTools => 'Upravne orodje';
|
||||||
|
|
||||||
|
|||||||
@@ -638,6 +638,9 @@ class AppLocalizationsSv extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get contacts_manageRepeater => 'Hantera Upprepare';
|
String get contacts_manageRepeater => 'Hantera Upprepare';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get contacts_manageRoom => 'Hantera Rumserver';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contacts_roomLogin => 'Rum Inloggning';
|
String get contacts_roomLogin => 'Rum Inloggning';
|
||||||
|
|
||||||
@@ -1569,6 +1572,9 @@ class AppLocalizationsSv extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get repeater_management => 'Återuppspelarens Hantering';
|
String get repeater_management => 'Återuppspelarens Hantering';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get room_management => 'Rumserverhantering';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_managementTools => 'Administrationsverktyg';
|
String get repeater_managementTools => 'Administrationsverktyg';
|
||||||
|
|
||||||
|
|||||||
@@ -611,6 +611,9 @@ class AppLocalizationsZh extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get contacts_manageRepeater => '管理重复项';
|
String get contacts_manageRepeater => '管理重复项';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get contacts_manageRoom => '管理房间服务器';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contacts_roomLogin => '房间登录';
|
String get contacts_roomLogin => '房间登录';
|
||||||
|
|
||||||
@@ -1513,6 +1516,9 @@ class AppLocalizationsZh extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get repeater_management => '重复器管理';
|
String get repeater_management => '重复器管理';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get room_management => '房间服务器管理';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get repeater_managementTools => '管理工具';
|
String get repeater_managementTools => '管理工具';
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -822,7 +822,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"login_failedMessage": "Inloggen mislukt. Het wachtwoord is onjuist of de repeater is niet bereikbaar.",
|
"login_failedMessage": "Inloggen mislukt. Het wachtwoord is onjuist of de repeater is niet bereikbaar.",
|
||||||
|
|
||||||
"common_reload": "Opnieuw laden",
|
"common_reload": "Opnieuw laden",
|
||||||
"common_clear": "Schoonmaken",
|
"common_clear": "Schoonmaken",
|
||||||
"path_currentPath": "Huidige pad: {path}",
|
"path_currentPath": "Huidige pad: {path}",
|
||||||
@@ -1349,5 +1348,7 @@
|
|||||||
"channels_scanQrCode": "Scan een QR-code",
|
"channels_scanQrCode": "Scan een QR-code",
|
||||||
"channels_scanQrCodeComingSoon": "Komt later",
|
"channels_scanQrCodeComingSoon": "Komt later",
|
||||||
"channels_enterHashtag": "Voer hashtag in",
|
"channels_enterHashtag": "Voer hashtag in",
|
||||||
"channels_hashtagHint": "bijv. #team"
|
"channels_hashtagHint": "bijv. #team",
|
||||||
|
"room_management": "Beheer Server Kamer",
|
||||||
|
"contacts_manageRoom": "Beheer Ruimte Server"
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -822,7 +822,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"login_failedMessage": "Logowanie nie powiodło się. Hasło jest nieprawidłowe albo repeater jest nieosiągalny.",
|
"login_failedMessage": "Logowanie nie powiodło się. Hasło jest nieprawidłowe albo repeater jest nieosiągalny.",
|
||||||
|
|
||||||
"common_reload": "Ponownie załadować",
|
"common_reload": "Ponownie załadować",
|
||||||
"common_clear": "Wyczyść",
|
"common_clear": "Wyczyść",
|
||||||
"path_currentPath": "Aktualny ścieżka: {path}",
|
"path_currentPath": "Aktualny ścieżka: {path}",
|
||||||
@@ -1349,5 +1348,7 @@
|
|||||||
"channels_scanQrCode": "Skanuj kod QR",
|
"channels_scanQrCode": "Skanuj kod QR",
|
||||||
"channels_scanQrCodeComingSoon": "Wkrótce",
|
"channels_scanQrCodeComingSoon": "Wkrótce",
|
||||||
"channels_enterHashtag": "Wprowadź hashtag",
|
"channels_enterHashtag": "Wprowadź hashtag",
|
||||||
"channels_hashtagHint": "np. #zespół"
|
"channels_hashtagHint": "np. #zespół",
|
||||||
|
"contacts_manageRoom": "Zarządzaj Serwerem Pokoju",
|
||||||
|
"room_management": "Zarządzanie Serwerem Pokoju"
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -822,7 +822,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"login_failedMessage": "Falha no login. A senha está incorreta ou o repetidor está inacessível.",
|
"login_failedMessage": "Falha no login. A senha está incorreta ou o repetidor está inacessível.",
|
||||||
|
|
||||||
"common_reload": "Recarregar",
|
"common_reload": "Recarregar",
|
||||||
"common_clear": "Limpar",
|
"common_clear": "Limpar",
|
||||||
"path_currentPath": "Caminho atual: {path}",
|
"path_currentPath": "Caminho atual: {path}",
|
||||||
@@ -1349,5 +1348,7 @@
|
|||||||
"channels_scanQrCode": "Digitalizar um Código QR",
|
"channels_scanQrCode": "Digitalizar um Código QR",
|
||||||
"channels_scanQrCodeComingSoon": "Em breve",
|
"channels_scanQrCodeComingSoon": "Em breve",
|
||||||
"channels_enterHashtag": "Insira hashtag",
|
"channels_enterHashtag": "Insira hashtag",
|
||||||
"channels_hashtagHint": "ex. #equipe"
|
"channels_hashtagHint": "ex. #equipe",
|
||||||
|
"contacts_manageRoom": "Gerenciar Servidor de Sala",
|
||||||
|
"room_management": "Gerenciamento de Servidor de Sala"
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -822,7 +822,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"login_failedMessage": "Prihlásenie zlyhalo. Heslo je nesprávne alebo je opakovač nedostupný.",
|
"login_failedMessage": "Prihlásenie zlyhalo. Heslo je nesprávne alebo je opakovač nedostupný.",
|
||||||
|
|
||||||
"common_reload": "Načítať",
|
"common_reload": "Načítať",
|
||||||
"common_clear": "Zmazať",
|
"common_clear": "Zmazať",
|
||||||
"path_currentPath": "Aktívna cesta: {path}",
|
"path_currentPath": "Aktívna cesta: {path}",
|
||||||
@@ -1349,5 +1348,7 @@
|
|||||||
"channels_scanQrCode": "Skenujte QR kód",
|
"channels_scanQrCode": "Skenujte QR kód",
|
||||||
"channels_scanQrCodeComingSoon": "Čoskoro",
|
"channels_scanQrCodeComingSoon": "Čoskoro",
|
||||||
"channels_enterHashtag": "Zadajte hashtag",
|
"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"
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -822,7 +822,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"login_failedMessage": "Prijava je bila neuspešna. Geslo je napačno ali pa je repetitor nedosegljiv.",
|
"login_failedMessage": "Prijava je bila neuspešna. Geslo je napačno ali pa je repetitor nedosegljiv.",
|
||||||
|
|
||||||
"common_reload": "Ponovno naloži",
|
"common_reload": "Ponovno naloži",
|
||||||
"common_clear": "Ponoviti",
|
"common_clear": "Ponoviti",
|
||||||
"path_currentPath": "Trenutna pot: {path}",
|
"path_currentPath": "Trenutna pot: {path}",
|
||||||
@@ -1349,5 +1348,7 @@
|
|||||||
"channels_scanQrCode": "Skeniraj QR kodo",
|
"channels_scanQrCode": "Skeniraj QR kodo",
|
||||||
"channels_scanQrCodeComingSoon": "Prihajajoča",
|
"channels_scanQrCodeComingSoon": "Prihajajoča",
|
||||||
"channels_enterHashtag": "Vnesite hashtag",
|
"channels_enterHashtag": "Vnesite hashtag",
|
||||||
"channels_hashtagHint": "npr. #ekipa"
|
"channels_hashtagHint": "npr. #ekipa",
|
||||||
|
"contacts_manageRoom": "Upravljajte strežnik sobe",
|
||||||
|
"room_management": "Upravljanje stremlišča"
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -822,7 +822,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"login_failedMessage": "Inloggning misslyckades. Antingen är lösenordet fel eller så går det inte att nå repeatern.",
|
"login_failedMessage": "Inloggning misslyckades. Antingen är lösenordet fel eller så går det inte att nå repeatern.",
|
||||||
|
|
||||||
"common_reload": "Ladda om",
|
"common_reload": "Ladda om",
|
||||||
"common_clear": "Rensa",
|
"common_clear": "Rensa",
|
||||||
"path_currentPath": "Nuvarande sökväg: {path}",
|
"path_currentPath": "Nuvarande sökväg: {path}",
|
||||||
@@ -1349,5 +1348,7 @@
|
|||||||
"channels_scanQrCode": "Skanna en QR-kod",
|
"channels_scanQrCode": "Skanna en QR-kod",
|
||||||
"channels_scanQrCodeComingSoon": "Kommer snart",
|
"channels_scanQrCodeComingSoon": "Kommer snart",
|
||||||
"channels_enterHashtag": "Ange hashtag",
|
"channels_enterHashtag": "Ange hashtag",
|
||||||
"channels_hashtagHint": "t.ex. #team"
|
"channels_hashtagHint": "t.ex. #team",
|
||||||
|
"contacts_manageRoom": "Hantera Rumserver",
|
||||||
|
"room_management": "Rumserverhantering"
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -822,7 +822,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"login_failedMessage": "登录失败。密码不正确或中继器不可达。",
|
"login_failedMessage": "登录失败。密码不正确或中继器不可达。",
|
||||||
|
|
||||||
"common_reload": "重新加载",
|
"common_reload": "重新加载",
|
||||||
"common_clear": "清除",
|
"common_clear": "清除",
|
||||||
"path_currentPath": "当前路径:{path}",
|
"path_currentPath": "当前路径:{path}",
|
||||||
@@ -1349,5 +1348,7 @@
|
|||||||
"channels_scanQrCode": "扫描二维码",
|
"channels_scanQrCode": "扫描二维码",
|
||||||
"channels_scanQrCodeComingSoon": "即将到来",
|
"channels_scanQrCodeComingSoon": "即将到来",
|
||||||
"channels_enterHashtag": "输入标签",
|
"channels_enterHashtag": "输入标签",
|
||||||
"channels_hashtagHint": "例如 #团队"
|
"channels_hashtagHint": "例如 #团队",
|
||||||
|
"contacts_manageRoom": "管理房间服务器",
|
||||||
|
"room_management": "房间服务器管理"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,13 +27,15 @@ import 'map_screen.dart';
|
|||||||
import 'repeater_hub_screen.dart';
|
import 'repeater_hub_screen.dart';
|
||||||
import 'settings_screen.dart';
|
import 'settings_screen.dart';
|
||||||
|
|
||||||
|
enum RoomLoginDestination {
|
||||||
|
chat,
|
||||||
|
management,
|
||||||
|
}
|
||||||
|
|
||||||
class ContactsScreen extends StatefulWidget {
|
class ContactsScreen extends StatefulWidget {
|
||||||
final bool hideBackButton;
|
final bool hideBackButton;
|
||||||
|
|
||||||
const ContactsScreen({
|
const ContactsScreen({super.key, this.hideBackButton = false});
|
||||||
super.key,
|
|
||||||
this.hideBackButton = false,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ContactsScreen> createState() => _ContactsScreenState();
|
State<ContactsScreen> createState() => _ContactsScreenState();
|
||||||
@@ -114,7 +116,8 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
top: false,
|
top: false,
|
||||||
child: QuickSwitchBar(
|
child: QuickSwitchBar(
|
||||||
selectedIndex: 0,
|
selectedIndex: 0,
|
||||||
onDestinationSelected: (index) => _handleQuickSwitch(index, context),
|
onDestinationSelected: (index) =>
|
||||||
|
_handleQuickSwitch(index, context),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -168,8 +171,9 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
}
|
}
|
||||||
|
|
||||||
final filteredAndSorted = _filterAndSortContacts(contacts, connector);
|
final filteredAndSorted = _filterAndSortContacts(contacts, connector);
|
||||||
final filteredGroups =
|
final filteredGroups = _showUnreadOnly
|
||||||
_showUnreadOnly ? const <ContactGroup>[] : _filterAndSortGroups(_groups, contacts);
|
? const <ContactGroup>[]
|
||||||
|
: _filterAndSortGroups(_groups, contacts);
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
@@ -199,7 +203,10 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
border: OutlineInputBorder(
|
border: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
),
|
),
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 16,
|
||||||
|
vertical: 12,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
_searchDebounce?.cancel();
|
_searchDebounce?.cancel();
|
||||||
@@ -238,14 +245,18 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
final group = filteredGroups[index];
|
final group = filteredGroups[index];
|
||||||
return _buildGroupTile(context, group, contacts);
|
return _buildGroupTile(context, group, contacts);
|
||||||
}
|
}
|
||||||
final contact = filteredAndSorted[index - filteredGroups.length];
|
final contact =
|
||||||
final unreadCount = connector.getUnreadCountForContact(contact);
|
filteredAndSorted[index - filteredGroups.length];
|
||||||
|
final unreadCount = connector.getUnreadCountForContact(
|
||||||
|
contact,
|
||||||
|
);
|
||||||
return _ContactTile(
|
return _ContactTile(
|
||||||
contact: contact,
|
contact: contact,
|
||||||
lastSeen: _resolveLastSeen(contact),
|
lastSeen: _resolveLastSeen(contact),
|
||||||
unreadCount: unreadCount,
|
unreadCount: unreadCount,
|
||||||
onTap: () => _openChat(context, contact),
|
onTap: () => _openChat(context, contact),
|
||||||
onLongPress: () => _showContactOptions(context, connector, contact),
|
onLongPress: () =>
|
||||||
|
_showContactOptions(context, connector, contact),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -255,35 +266,48 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ContactGroup> _filterAndSortGroups(List<ContactGroup> groups, List<Contact> contacts) {
|
List<ContactGroup> _filterAndSortGroups(
|
||||||
|
List<ContactGroup> groups,
|
||||||
|
List<Contact> contacts,
|
||||||
|
) {
|
||||||
final query = _searchQuery.trim().toLowerCase();
|
final query = _searchQuery.trim().toLowerCase();
|
||||||
final contactsByKey = <String, Contact>{};
|
final contactsByKey = <String, Contact>{};
|
||||||
for (final contact in contacts) {
|
for (final contact in contacts) {
|
||||||
contactsByKey[contact.publicKeyHex] = contact;
|
contactsByKey[contact.publicKeyHex] = contact;
|
||||||
}
|
}
|
||||||
|
|
||||||
final filtered = groups.where((group) {
|
final filtered = groups
|
||||||
if (query.isEmpty) return true;
|
.where((group) {
|
||||||
if (group.name.toLowerCase().contains(query)) return true;
|
if (query.isEmpty) return true;
|
||||||
for (final key in group.memberKeys) {
|
if (group.name.toLowerCase().contains(query)) return true;
|
||||||
final contact = contactsByKey[key];
|
for (final key in group.memberKeys) {
|
||||||
if (contact != null && matchesContactQuery(contact, query)) return true;
|
final contact = contactsByKey[key];
|
||||||
}
|
if (contact != null && matchesContactQuery(contact, query)) {
|
||||||
return false;
|
return true;
|
||||||
}).where((group) {
|
}
|
||||||
if (_typeFilter == ContactTypeFilter.all) return true;
|
}
|
||||||
for (final key in group.memberKeys) {
|
return false;
|
||||||
final contact = contactsByKey[key];
|
})
|
||||||
if (contact != null && _matchesTypeFilter(contact)) return true;
|
.where((group) {
|
||||||
}
|
if (_typeFilter == ContactTypeFilter.all) return true;
|
||||||
return false;
|
for (final key in group.memberKeys) {
|
||||||
}).toList();
|
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;
|
return filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Contact> _filterAndSortContacts(List<Contact> contacts, MeshCoreConnector connector) {
|
List<Contact> _filterAndSortContacts(
|
||||||
|
List<Contact> contacts,
|
||||||
|
MeshCoreConnector connector,
|
||||||
|
) {
|
||||||
var filtered = contacts.where((contact) {
|
var filtered = contacts.where((contact) {
|
||||||
if (_searchQuery.isEmpty) return true;
|
if (_searchQuery.isEmpty) return true;
|
||||||
return matchesContactQuery(contact, _searchQuery);
|
return matchesContactQuery(contact, _searchQuery);
|
||||||
@@ -301,19 +325,27 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
|
|
||||||
switch (_sortOption) {
|
switch (_sortOption) {
|
||||||
case ContactSortOption.lastSeen:
|
case ContactSortOption.lastSeen:
|
||||||
filtered.sort((a, b) => _resolveLastSeen(b).compareTo(_resolveLastSeen(a)));
|
filtered.sort(
|
||||||
|
(a, b) => _resolveLastSeen(b).compareTo(_resolveLastSeen(a)),
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case ContactSortOption.recentMessages:
|
case ContactSortOption.recentMessages:
|
||||||
filtered.sort((a, b) {
|
filtered.sort((a, b) {
|
||||||
final aMessages = connector.getMessages(a);
|
final aMessages = connector.getMessages(a);
|
||||||
final bMessages = connector.getMessages(b);
|
final bMessages = connector.getMessages(b);
|
||||||
final aLastMsg = aMessages.isEmpty ? DateTime(1970) : aMessages.last.timestamp;
|
final aLastMsg = aMessages.isEmpty
|
||||||
final bLastMsg = bMessages.isEmpty ? DateTime(1970) : bMessages.last.timestamp;
|
? DateTime(1970)
|
||||||
|
: aMessages.last.timestamp;
|
||||||
|
final bLastMsg = bMessages.isEmpty
|
||||||
|
? DateTime(1970)
|
||||||
|
: bMessages.last.timestamp;
|
||||||
return bLastMsg.compareTo(aLastMsg);
|
return bLastMsg.compareTo(aLastMsg);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case ContactSortOption.name:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,7 +372,11 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
: contact.lastSeen;
|
: contact.lastSeen;
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildGroupTile(BuildContext context, ContactGroup group, List<Contact> contacts) {
|
Widget _buildGroupTile(
|
||||||
|
BuildContext context,
|
||||||
|
ContactGroup group,
|
||||||
|
List<Contact> contacts,
|
||||||
|
) {
|
||||||
final memberContacts = _resolveGroupContacts(group, contacts);
|
final memberContacts = _resolveGroupContacts(group, contacts);
|
||||||
final subtitle = _formatGroupMembers(context, memberContacts);
|
final subtitle = _formatGroupMembers(context, memberContacts);
|
||||||
return ListTile(
|
return ListTile(
|
||||||
@@ -359,7 +395,10 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Contact> _resolveGroupContacts(ContactGroup group, List<Contact> contacts) {
|
List<Contact> _resolveGroupContacts(
|
||||||
|
ContactGroup group,
|
||||||
|
List<Contact> contacts,
|
||||||
|
) {
|
||||||
final byKey = <String, Contact>{};
|
final byKey = <String, Contact>{};
|
||||||
for (final contact in contacts) {
|
for (final contact in contacts) {
|
||||||
byKey[contact.publicKeyHex] = contact;
|
byKey[contact.publicKeyHex] = contact;
|
||||||
@@ -371,7 +410,9 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
resolved.add(contact);
|
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;
|
return resolved;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,7 +428,7 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
if (contact.type == advTypeRepeater) {
|
if (contact.type == advTypeRepeater) {
|
||||||
_showRepeaterLogin(context, contact);
|
_showRepeaterLogin(context, contact);
|
||||||
} else if (contact.type == advTypeRoom) {
|
} else if (contact.type == advTypeRoom) {
|
||||||
_showRoomLogin(context, contact);
|
_showRoomLogin(context, contact, RoomLoginDestination.chat);
|
||||||
} else {
|
} else {
|
||||||
context.read<MeshCoreConnector>().markContactRead(contact.publicKeyHex);
|
context.read<MeshCoreConnector>().markContactRead(contact.publicKeyHex);
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
@@ -403,17 +444,13 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
case 1:
|
case 1:
|
||||||
Navigator.pushReplacement(
|
Navigator.pushReplacement(
|
||||||
context,
|
context,
|
||||||
buildQuickSwitchRoute(
|
buildQuickSwitchRoute(const ChannelsScreen(hideBackButton: true)),
|
||||||
const ChannelsScreen(hideBackButton: true),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
Navigator.pushReplacement(
|
Navigator.pushReplacement(
|
||||||
context,
|
context,
|
||||||
buildQuickSwitchRoute(
|
buildQuickSwitchRoute(const MapScreen(hideBackButton: true)),
|
||||||
const MapScreen(hideBackButton: true),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -429,10 +466,8 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => RepeaterHubScreen(
|
builder: (context) =>
|
||||||
repeater: repeater,
|
RepeaterHubScreen(repeater: repeater, password: password),
|
||||||
password: password,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -440,18 +475,23 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showRoomLogin(BuildContext context, Contact room) {
|
void _showRoomLogin(
|
||||||
|
BuildContext context,
|
||||||
|
Contact room,
|
||||||
|
RoomLoginDestination destination,
|
||||||
|
) {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => RoomLoginDialog(
|
builder: (context) => RoomLoginDialog(
|
||||||
room: room,
|
room: room,
|
||||||
onLogin: (password) {
|
onLogin: (password) {
|
||||||
// Navigate to chat screen after successful login
|
|
||||||
context.read<MeshCoreConnector>().markContactRead(room.publicKeyHex);
|
context.read<MeshCoreConnector>().markContactRead(room.publicKeyHex);
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
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<ContactsScreen>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showGroupOptions(BuildContext context, ContactGroup group, List<Contact> contacts) {
|
void _showGroupOptions(
|
||||||
|
BuildContext context,
|
||||||
|
ContactGroup group,
|
||||||
|
List<Contact> contacts,
|
||||||
|
) {
|
||||||
final members = _resolveGroupContacts(group, contacts);
|
final members = _resolveGroupContacts(group, contacts);
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
@@ -478,7 +522,10 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.delete, color: Colors.red),
|
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: () {
|
onTap: () {
|
||||||
Navigator.pop(sheetContext);
|
Navigator.pop(sheetContext);
|
||||||
_confirmDeleteGroup(context, group);
|
_confirmDeleteGroup(context, group);
|
||||||
@@ -522,7 +569,10 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
});
|
});
|
||||||
await _saveGroups();
|
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<ContactsScreen>
|
|||||||
final filteredContacts = filterQuery.isEmpty
|
final filteredContacts = filterQuery.isEmpty
|
||||||
? sortedContacts
|
? sortedContacts
|
||||||
: sortedContacts
|
: sortedContacts
|
||||||
.where((contact) => matchesContactQuery(contact, filterQuery))
|
.where(
|
||||||
.toList();
|
(contact) => matchesContactQuery(contact, filterQuery),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
return AlertDialog(
|
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(
|
content: SizedBox(
|
||||||
width: double.maxFinite,
|
width: double.maxFinite,
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -582,12 +638,18 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
height: 240,
|
height: 240,
|
||||||
child: filteredContacts.isEmpty
|
child: filteredContacts.isEmpty
|
||||||
? Center(child: Text(context.l10n.contacts_noContactsMatchFilter))
|
? Center(
|
||||||
|
child: Text(
|
||||||
|
context.l10n.contacts_noContactsMatchFilter,
|
||||||
|
),
|
||||||
|
)
|
||||||
: ListView.builder(
|
: ListView.builder(
|
||||||
itemCount: filteredContacts.length,
|
itemCount: filteredContacts.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final contact = filteredContacts[index];
|
final contact = filteredContacts[index];
|
||||||
final isSelected = selectedKeys.contains(contact.publicKeyHex);
|
final isSelected = selectedKeys.contains(
|
||||||
|
contact.publicKeyHex,
|
||||||
|
);
|
||||||
return CheckboxListTile(
|
return CheckboxListTile(
|
||||||
value: isSelected,
|
value: isSelected,
|
||||||
title: Text(contact.name),
|
title: Text(contact.name),
|
||||||
@@ -618,7 +680,9 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
final name = nameController.text.trim();
|
final name = nameController.text.trim();
|
||||||
if (name.isEmpty) {
|
if (name.isEmpty) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(content: Text(context.l10n.contacts_groupNameRequired)),
|
SnackBar(
|
||||||
|
content: Text(context.l10n.contacts_groupNameRequired),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -628,13 +692,19 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
});
|
});
|
||||||
if (exists) {
|
if (exists) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(content: Text(context.l10n.contacts_groupAlreadyExists(name))),
|
SnackBar(
|
||||||
|
content: Text(
|
||||||
|
context.l10n.contacts_groupAlreadyExists(name),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setState(() {
|
setState(() {
|
||||||
if (isEditing) {
|
if (isEditing) {
|
||||||
final index = _groups.indexWhere((g) => g.name == group.name);
|
final index = _groups.indexWhere(
|
||||||
|
(g) => g.name == group.name,
|
||||||
|
);
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
_groups[index] = ContactGroup(
|
_groups[index] = ContactGroup(
|
||||||
name: name,
|
name: name,
|
||||||
@@ -642,7 +712,12 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_groups.add(ContactGroup(name: name, memberKeys: selectedKeys.toList()));
|
_groups.add(
|
||||||
|
ContactGroup(
|
||||||
|
name: name,
|
||||||
|
memberKeys: selectedKeys.toList(),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
await _saveGroups();
|
await _saveGroups();
|
||||||
@@ -650,7 +725,11 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
Navigator.pop(dialogContext);
|
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<ContactsScreen>
|
|||||||
_showRepeaterLogin(context, contact);
|
_showRepeaterLogin(context, contact);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
else if (isRoom)
|
else if (isRoom) ...[
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.room, color: Colors.blue),
|
leading: const Icon(Icons.room, color: Colors.blue),
|
||||||
title: Text(context.l10n.contacts_roomLogin),
|
title: Text(context.l10n.contacts_roomLogin),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.pop(sheetContext);
|
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(
|
ListTile(
|
||||||
leading: const Icon(Icons.chat),
|
leading: const Icon(Icons.chat),
|
||||||
title: Text(context.l10n.contacts_openChat),
|
title: Text(context.l10n.contacts_openChat),
|
||||||
@@ -702,7 +789,10 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.delete, color: Colors.red),
|
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: () {
|
onTap: () {
|
||||||
Navigator.pop(sheetContext);
|
Navigator.pop(sheetContext);
|
||||||
_confirmDelete(context, connector, contact);
|
_confirmDelete(context, connector, contact);
|
||||||
@@ -734,7 +824,10 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||||||
Navigator.pop(dialogContext);
|
Navigator.pop(dialogContext);
|
||||||
connector.removeContact(contact);
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
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(
|
return ListTile(
|
||||||
leading: CircleAvatar(
|
leading: CircleAvatar(
|
||||||
backgroundColor: _getTypeColor(contact.type),
|
backgroundColor: _getTypeColor(contact.type),
|
||||||
child: _buildContactAvatar(contact),
|
child: _buildContactAvatar(contact),
|
||||||
),
|
),
|
||||||
title: Text(contact.name),
|
title: Text(contact.name),
|
||||||
subtitle: Text('${contact.typeLabel} • ${contact.pathLabel} $shotPublicKey'),
|
subtitle: Text(
|
||||||
|
'${contact.typeLabel} • ${contact.pathLabel} $shotPublicKey',
|
||||||
|
),
|
||||||
trailing: Column(
|
trailing: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
@@ -791,10 +887,7 @@ class _ContactTile extends StatelessWidget {
|
|||||||
Widget _buildContactAvatar(Contact contact) {
|
Widget _buildContactAvatar(Contact contact) {
|
||||||
final emoji = firstEmoji(contact.name);
|
final emoji = firstEmoji(contact.name);
|
||||||
if (emoji != null) {
|
if (emoji != null) {
|
||||||
return Text(
|
return Text(emoji, style: const TextStyle(fontSize: 18));
|
||||||
emoji,
|
|
||||||
style: const TextStyle(fontSize: 18),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return Icon(_getTypeIcon(contact.type), color: Colors.white, size: 20);
|
return Icon(_getTypeIcon(contact.type), color: Colors.white, size: 20);
|
||||||
}
|
}
|
||||||
@@ -833,13 +926,21 @@ class _ContactTile extends StatelessWidget {
|
|||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
final diff = now.difference(lastSeen);
|
final diff = now.difference(lastSeen);
|
||||||
|
|
||||||
if (diff.isNegative || diff.inMinutes < 5) return context.l10n.contacts_lastSeenNow;
|
if (diff.isNegative || diff.inMinutes < 5) {
|
||||||
if (diff.inMinutes < 60) return context.l10n.contacts_lastSeenMinsAgo(diff.inMinutes);
|
return context.l10n.contacts_lastSeenNow;
|
||||||
|
}
|
||||||
|
if (diff.inMinutes < 60) {
|
||||||
|
return context.l10n.contacts_lastSeenMinsAgo(diff.inMinutes);
|
||||||
|
}
|
||||||
if (diff.inHours < 24) {
|
if (diff.inHours < 24) {
|
||||||
final hours = diff.inHours;
|
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;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:meshcore_open/connector/meshcore_protocol.dart';
|
||||||
import '../l10n/l10n.dart';
|
import '../l10n/l10n.dart';
|
||||||
import '../models/contact.dart';
|
import '../models/contact.dart';
|
||||||
import 'repeater_status_screen.dart';
|
import 'repeater_status_screen.dart';
|
||||||
@@ -25,10 +26,17 @@ class RepeaterHubScreen extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Text(l10n.repeater_management),
|
Text(
|
||||||
|
repeater.type == advTypeRepeater
|
||||||
|
? l10n.repeater_management
|
||||||
|
: l10n.room_management,
|
||||||
|
),
|
||||||
Text(
|
Text(
|
||||||
repeater.name,
|
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(
|
child: ListView(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
children: [
|
children: [
|
||||||
// Repeater info card
|
// Repeater info card
|
||||||
Card(
|
Card(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
CircleAvatar(
|
CircleAvatar(
|
||||||
radius: 40,
|
radius: 40,
|
||||||
backgroundColor: Colors.orange,
|
backgroundColor: Colors.orange,
|
||||||
child: const Icon(Icons.cell_tower, size: 40, color: Colors.white),
|
child: const Icon(
|
||||||
|
Icons.cell_tower,
|
||||||
|
size: 40,
|
||||||
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
),
|
||||||
Text(
|
const SizedBox(height: 16),
|
||||||
repeater.name,
|
Text(
|
||||||
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
|
repeater.name,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
),
|
||||||
Text(
|
const SizedBox(height: 8),
|
||||||
'<${repeater.publicKeyHex.substring(0, 8)}...${repeater.publicKeyHex.substring(repeater.publicKeyHex.length - 8)}>',
|
Text(
|
||||||
style: TextStyle(fontSize: 14, color: Colors.grey[600]),
|
'<${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(
|
const SizedBox(height: 8),
|
||||||
repeater.pathLabel,
|
Text(
|
||||||
style: TextStyle(fontSize: 14, color: Colors.grey[600]),
|
repeater.pathLabel,
|
||||||
),
|
style: TextStyle(fontSize: 14, color: Colors.grey[600]),
|
||||||
if (repeater.hasLocation) ...[
|
),
|
||||||
const SizedBox(height: 4),
|
if (repeater.hasLocation) ...[
|
||||||
Row(
|
const SizedBox(height: 4),
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
Row(
|
||||||
children: [
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
Icon(Icons.location_on, size: 14, color: Colors.grey[600]),
|
children: [
|
||||||
const SizedBox(width: 4),
|
Icon(
|
||||||
Text(
|
Icons.location_on,
|
||||||
'${repeater.latitude?.toStringAsFixed(4)}, ${repeater.longitude?.toStringAsFixed(4)}',
|
size: 14,
|
||||||
style: TextStyle(fontSize: 12, color: Colors.grey[600]),
|
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(
|
const SizedBox(height: 24),
|
||||||
l10n.repeater_managementTools,
|
Text(
|
||||||
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
l10n.repeater_managementTools,
|
||||||
),
|
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||||
const SizedBox(height: 16),
|
),
|
||||||
// Status button
|
const SizedBox(height: 16),
|
||||||
_buildManagementCard(
|
// Status button
|
||||||
context,
|
_buildManagementCard(
|
||||||
icon: Icons.analytics,
|
context,
|
||||||
title: l10n.repeater_status,
|
icon: Icons.analytics,
|
||||||
subtitle: l10n.repeater_statusSubtitle,
|
title: l10n.repeater_status,
|
||||||
color: Colors.blue,
|
subtitle: l10n.repeater_statusSubtitle,
|
||||||
onTap: () {
|
color: Colors.blue,
|
||||||
Navigator.push(
|
onTap: () {
|
||||||
context,
|
Navigator.push(
|
||||||
MaterialPageRoute(
|
context,
|
||||||
builder: (context) => RepeaterStatusScreen(
|
MaterialPageRoute(
|
||||||
repeater: repeater,
|
builder: (context) => RepeaterStatusScreen(
|
||||||
password: password,
|
repeater: repeater,
|
||||||
),
|
password: password,
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
},
|
);
|
||||||
),
|
},
|
||||||
const SizedBox(height: 16),
|
),
|
||||||
// Telemetry button
|
const SizedBox(height: 16),
|
||||||
_buildManagementCard(
|
// Telemetry button
|
||||||
context,
|
_buildManagementCard(
|
||||||
icon: Icons.bar_chart_sharp,
|
context,
|
||||||
title: l10n.repeater_telemetry,
|
icon: Icons.bar_chart_sharp,
|
||||||
subtitle: l10n.repeater_telemetrySubtitle,
|
title: l10n.repeater_telemetry,
|
||||||
color: Colors.teal,
|
subtitle: l10n.repeater_telemetrySubtitle,
|
||||||
onTap: () {
|
color: Colors.teal,
|
||||||
Navigator.push(
|
onTap: () {
|
||||||
context,
|
Navigator.push(
|
||||||
MaterialPageRoute(
|
context,
|
||||||
builder: (context) => TelemetryScreen(
|
MaterialPageRoute(
|
||||||
repeater: repeater,
|
builder: (context) =>
|
||||||
password: password,
|
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
|
const SizedBox(height: 12),
|
||||||
_buildManagementCard(
|
// Settings button
|
||||||
context,
|
_buildManagementCard(
|
||||||
icon: Icons.terminal,
|
context,
|
||||||
title: l10n.repeater_cli,
|
icon: Icons.settings,
|
||||||
subtitle: l10n.repeater_cliSubtitle,
|
title: l10n.repeater_settings,
|
||||||
color: Colors.green,
|
subtitle: l10n.repeater_settingsSubtitle,
|
||||||
onTap: () {
|
color: Colors.orange,
|
||||||
Navigator.push(
|
onTap: () {
|
||||||
context,
|
Navigator.push(
|
||||||
MaterialPageRoute(
|
context,
|
||||||
builder: (context) => RepeaterCliScreen(
|
MaterialPageRoute(
|
||||||
repeater: repeater,
|
builder: (context) => RepeaterSettingsScreen(
|
||||||
password: password,
|
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),
|
const SizedBox(height: 4),
|
||||||
Text(
|
Text(
|
||||||
subtitle,
|
subtitle,
|
||||||
style: TextStyle(
|
style: TextStyle(fontSize: 14, color: Colors.grey[600]),
|
||||||
fontSize: 14,
|
|
||||||
color: Colors.grey[600],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user