mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
feat: Add repeater discovery onboarding flow
This commit is contained in:
@@ -2285,7 +2285,7 @@
|
|||||||
"@change": {
|
"@change": {
|
||||||
"description": "Generic change action"
|
"description": "Generic change action"
|
||||||
},
|
},
|
||||||
"wizardOverviewDescription": "This app combines MeshCore messaging, SAR field updates, mapping, and device tools in one place.",
|
"wizardOverviewDescription": "This app combines MeshCore messaging, SAR field updates, discovery, mapping, and device tools in one place.",
|
||||||
"@wizardOverviewDescription": {
|
"@wizardOverviewDescription": {
|
||||||
"description": "Updated onboarding overview description"
|
"description": "Updated onboarding overview description"
|
||||||
},
|
},
|
||||||
@@ -2297,7 +2297,7 @@
|
|||||||
"@wizardOverviewFeature2": {
|
"@wizardOverviewFeature2": {
|
||||||
"description": "Updated onboarding overview feature 2"
|
"description": "Updated onboarding overview feature 2"
|
||||||
},
|
},
|
||||||
"wizardOverviewFeature3": "Connect over BLE or TCP, then manage the companion radio from inside the app.",
|
"wizardOverviewFeature3": "Connect over BLE, WiFi, or Serial, then manage the companion radio from inside the app.",
|
||||||
"@wizardOverviewFeature3": {
|
"@wizardOverviewFeature3": {
|
||||||
"description": "Updated onboarding overview feature 3"
|
"description": "Updated onboarding overview feature 3"
|
||||||
},
|
},
|
||||||
@@ -2410,11 +2410,11 @@
|
|||||||
"@wizardNetworkTitle": {
|
"@wizardNetworkTitle": {
|
||||||
"description": "Updated onboarding network page title"
|
"description": "Updated onboarding network page title"
|
||||||
},
|
},
|
||||||
"wizardNetworkDescription": "The Contacts tab organizes the network you discover and the routes you learn over time.",
|
"wizardNetworkDescription": "The Contacts and Discovery flows help you find nearby nodes, store repeaters, and manage the routes you learn over time.",
|
||||||
"@wizardNetworkDescription": {
|
"@wizardNetworkDescription": {
|
||||||
"description": "Updated onboarding network page description"
|
"description": "Updated onboarding network page description"
|
||||||
},
|
},
|
||||||
"wizardNetworkFeature1": "Review team members, repeaters, rooms, channels, and pending adverts in one list.",
|
"wizardNetworkFeature1": "Discover repeaters and sensors, then review team members, rooms, channels, and pending adverts in one list.",
|
||||||
"@wizardNetworkFeature1": {
|
"@wizardNetworkFeature1": {
|
||||||
"description": "Updated onboarding network feature 1"
|
"description": "Updated onboarding network feature 1"
|
||||||
},
|
},
|
||||||
@@ -2422,7 +2422,7 @@
|
|||||||
"@wizardNetworkFeature2": {
|
"@wizardNetworkFeature2": {
|
||||||
"description": "Updated onboarding network feature 2"
|
"description": "Updated onboarding network feature 2"
|
||||||
},
|
},
|
||||||
"wizardNetworkFeature3": "Create channels and manage network destinations without leaving the app.",
|
"wizardNetworkFeature3": "Add new repeaters right after you connect, then create channels and manage network destinations without leaving the app.",
|
||||||
"@wizardNetworkFeature3": {
|
"@wizardNetworkFeature3": {
|
||||||
"description": "Updated onboarding network feature 3"
|
"description": "Updated onboarding network feature 3"
|
||||||
},
|
},
|
||||||
@@ -2462,10 +2462,18 @@
|
|||||||
"@wizardToolsFeature2": {
|
"@wizardToolsFeature2": {
|
||||||
"description": "Updated onboarding tools feature 2"
|
"description": "Updated onboarding tools feature 2"
|
||||||
},
|
},
|
||||||
"wizardToolsFeature3": "Use packet logs, spectrum scan, and developer diagnostics when troubleshooting the mesh.",
|
"wizardToolsFeature3": "Use live traffic, packet logs, spectrum scan, and developer diagnostics when troubleshooting the mesh.",
|
||||||
"@wizardToolsFeature3": {
|
"@wizardToolsFeature3": {
|
||||||
"description": "Updated onboarding tools feature 3"
|
"description": "Updated onboarding tools feature 3"
|
||||||
},
|
},
|
||||||
|
"postConnectDiscoveryTitle": "Discover repeaters now?",
|
||||||
|
"@postConnectDiscoveryTitle": {
|
||||||
|
"description": "Title for the prompt shown after a successful device connection"
|
||||||
|
},
|
||||||
|
"postConnectDiscoveryDescription": "Run repeater discovery right after connecting so you can see nearby MeshCore nodes and add them to your network faster.",
|
||||||
|
"@postConnectDiscoveryDescription": {
|
||||||
|
"description": "Body text for the prompt shown after a successful device connection"
|
||||||
|
},
|
||||||
"contactInSensors": "In Sensors",
|
"contactInSensors": "In Sensors",
|
||||||
"@contactInSensors": {
|
"@contactInSensors": {
|
||||||
"description": "Contact actions label when already in sensors"
|
"description": "Contact actions label when already in sensors"
|
||||||
|
|||||||
@@ -3219,7 +3219,7 @@ abstract class AppLocalizations {
|
|||||||
/// Updated onboarding overview description
|
/// Updated onboarding overview description
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'This app combines MeshCore messaging, SAR field updates, mapping, and device tools in one place.'**
|
/// **'This app combines MeshCore messaging, SAR field updates, discovery, mapping, and device tools in one place.'**
|
||||||
String get wizardOverviewDescription;
|
String get wizardOverviewDescription;
|
||||||
|
|
||||||
/// Updated onboarding overview feature 1
|
/// Updated onboarding overview feature 1
|
||||||
@@ -3237,7 +3237,7 @@ abstract class AppLocalizations {
|
|||||||
/// Updated onboarding overview feature 3
|
/// Updated onboarding overview feature 3
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Connect over BLE or TCP, then manage the companion radio from inside the app.'**
|
/// **'Connect over BLE, WiFi, or Serial, then manage the companion radio from inside the app.'**
|
||||||
String get wizardOverviewFeature3;
|
String get wizardOverviewFeature3;
|
||||||
|
|
||||||
/// Updated onboarding messaging page title
|
/// Updated onboarding messaging page title
|
||||||
@@ -3387,13 +3387,13 @@ abstract class AppLocalizations {
|
|||||||
/// Updated onboarding network page description
|
/// Updated onboarding network page description
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'The Contacts tab organizes the network you discover and the routes you learn over time.'**
|
/// **'The Contacts and Discovery flows help you find nearby nodes, store repeaters, and manage the routes you learn over time.'**
|
||||||
String get wizardNetworkDescription;
|
String get wizardNetworkDescription;
|
||||||
|
|
||||||
/// Updated onboarding network feature 1
|
/// Updated onboarding network feature 1
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Review team members, repeaters, rooms, channels, and pending adverts in one list.'**
|
/// **'Discover repeaters and sensors, then review team members, rooms, channels, and pending adverts in one list.'**
|
||||||
String get wizardNetworkFeature1;
|
String get wizardNetworkFeature1;
|
||||||
|
|
||||||
/// Updated onboarding network feature 2
|
/// Updated onboarding network feature 2
|
||||||
@@ -3405,7 +3405,7 @@ abstract class AppLocalizations {
|
|||||||
/// Updated onboarding network feature 3
|
/// Updated onboarding network feature 3
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Create channels and manage network destinations without leaving the app.'**
|
/// **'Add new repeaters right after you connect, then create channels and manage network destinations without leaving the app.'**
|
||||||
String get wizardNetworkFeature3;
|
String get wizardNetworkFeature3;
|
||||||
|
|
||||||
/// Updated onboarding map page title
|
/// Updated onboarding map page title
|
||||||
@@ -3465,9 +3465,21 @@ abstract class AppLocalizations {
|
|||||||
/// Updated onboarding tools feature 3
|
/// Updated onboarding tools feature 3
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Use packet logs, spectrum scan, and developer diagnostics when troubleshooting the mesh.'**
|
/// **'Use live traffic, packet logs, spectrum scan, and developer diagnostics when troubleshooting the mesh.'**
|
||||||
String get wizardToolsFeature3;
|
String get wizardToolsFeature3;
|
||||||
|
|
||||||
|
/// Title for the prompt shown after a successful device connection
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Discover repeaters now?'**
|
||||||
|
String get postConnectDiscoveryTitle;
|
||||||
|
|
||||||
|
/// Body text for the prompt shown after a successful device connection
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Run repeater discovery right after connecting so you can see nearby MeshCore nodes and add them to your network faster.'**
|
||||||
|
String get postConnectDiscoveryDescription;
|
||||||
|
|
||||||
/// Contact actions label when already in sensors
|
/// Contact actions label when already in sensors
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|||||||
@@ -1898,6 +1898,13 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
String get wizardToolsFeature3 =>
|
String get wizardToolsFeature3 =>
|
||||||
'Nutze Paketprotokolle, Spektrumsuche und Entwicklerdiagnosen zur Fehlersuche im Mesh.';
|
'Nutze Paketprotokolle, Spektrumsuche und Entwicklerdiagnosen zur Fehlersuche im Mesh.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryTitle => 'Discover repeaters now?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryDescription =>
|
||||||
|
'Run repeater discovery right after connecting so you can see nearby MeshCore nodes and add them to your network faster.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contactInSensors => 'In Sensoren';
|
String get contactInSensors => 'In Sensoren';
|
||||||
|
|
||||||
|
|||||||
@@ -1905,6 +1905,13 @@ class AppLocalizationsEl extends AppLocalizations {
|
|||||||
String get wizardToolsFeature3 =>
|
String get wizardToolsFeature3 =>
|
||||||
'Χρησιμοποιήστε καταγραφές πακέτων, σάρωση φάσματος και διαγνωστικά προγραμματιστή κατά την αντιμετώπιση προβλημάτων του mesh.';
|
'Χρησιμοποιήστε καταγραφές πακέτων, σάρωση φάσματος και διαγνωστικά προγραμματιστή κατά την αντιμετώπιση προβλημάτων του mesh.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryTitle => 'Discover repeaters now?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryDescription =>
|
||||||
|
'Run repeater discovery right after connecting so you can see nearby MeshCore nodes and add them to your network faster.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contactInSensors => 'Στους αισθητήρες';
|
String get contactInSensors => 'Στους αισθητήρες';
|
||||||
|
|
||||||
|
|||||||
@@ -1717,7 +1717,7 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get wizardOverviewDescription =>
|
String get wizardOverviewDescription =>
|
||||||
'This app combines MeshCore messaging, SAR field updates, mapping, and device tools in one place.';
|
'This app combines MeshCore messaging, SAR field updates, discovery, mapping, and device tools in one place.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get wizardOverviewFeature1 =>
|
String get wizardOverviewFeature1 =>
|
||||||
@@ -1729,7 +1729,7 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get wizardOverviewFeature3 =>
|
String get wizardOverviewFeature3 =>
|
||||||
'Connect over BLE or TCP, then manage the companion radio from inside the app.';
|
'Connect over BLE, WiFi, or Serial, then manage the companion radio from inside the app.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get wizardMessagingTitle => 'Messaging and Field Reports';
|
String get wizardMessagingTitle => 'Messaging and Field Reports';
|
||||||
@@ -1819,11 +1819,11 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get wizardNetworkDescription =>
|
String get wizardNetworkDescription =>
|
||||||
'The Contacts tab organizes the network you discover and the routes you learn over time.';
|
'The Contacts and Discovery flows help you find nearby nodes, store repeaters, and manage the routes you learn over time.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get wizardNetworkFeature1 =>
|
String get wizardNetworkFeature1 =>
|
||||||
'Review team members, repeaters, rooms, channels, and pending adverts in one list.';
|
'Discover repeaters and sensors, then review team members, rooms, channels, and pending adverts in one list.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get wizardNetworkFeature2 =>
|
String get wizardNetworkFeature2 =>
|
||||||
@@ -1831,7 +1831,7 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get wizardNetworkFeature3 =>
|
String get wizardNetworkFeature3 =>
|
||||||
'Create channels and manage network destinations without leaving the app.';
|
'Add new repeaters right after you connect, then create channels and manage network destinations without leaving the app.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get wizardMapOpsTitle => 'Map, Trails, and Shared Geometry';
|
String get wizardMapOpsTitle => 'Map, Trails, and Shared Geometry';
|
||||||
@@ -1869,7 +1869,14 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get wizardToolsFeature3 =>
|
String get wizardToolsFeature3 =>
|
||||||
'Use packet logs, spectrum scan, and developer diagnostics when troubleshooting the mesh.';
|
'Use live traffic, packet logs, spectrum scan, and developer diagnostics when troubleshooting the mesh.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryTitle => 'Discover repeaters now?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryDescription =>
|
||||||
|
'Run repeater discovery right after connecting so you can see nearby MeshCore nodes and add them to your network faster.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contactInSensors => 'In Sensors';
|
String get contactInSensors => 'In Sensors';
|
||||||
|
|||||||
@@ -1901,6 +1901,13 @@ class AppLocalizationsEs extends AppLocalizations {
|
|||||||
String get wizardToolsFeature3 =>
|
String get wizardToolsFeature3 =>
|
||||||
'Usa registros de paquetes, escaneo de espectro y diagnósticos de desarrollador al solucionar problemas de la malla.';
|
'Usa registros de paquetes, escaneo de espectro y diagnósticos de desarrollador al solucionar problemas de la malla.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryTitle => 'Discover repeaters now?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryDescription =>
|
||||||
|
'Run repeater discovery right after connecting so you can see nearby MeshCore nodes and add them to your network faster.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contactInSensors => 'En Sensores';
|
String get contactInSensors => 'En Sensores';
|
||||||
|
|
||||||
|
|||||||
@@ -1905,6 +1905,13 @@ class AppLocalizationsFr extends AppLocalizations {
|
|||||||
String get wizardToolsFeature3 =>
|
String get wizardToolsFeature3 =>
|
||||||
'Utilisez les journaux de paquets, le balayage du spectre et les diagnostics développeur pour dépanner le réseau maillé.';
|
'Utilisez les journaux de paquets, le balayage du spectre et les diagnostics développeur pour dépanner le réseau maillé.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryTitle => 'Discover repeaters now?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryDescription =>
|
||||||
|
'Run repeater discovery right after connecting so you can see nearby MeshCore nodes and add them to your network faster.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contactInSensors => 'Dans Capteurs';
|
String get contactInSensors => 'Dans Capteurs';
|
||||||
|
|
||||||
|
|||||||
@@ -1881,6 +1881,13 @@ class AppLocalizationsHr extends AppLocalizations {
|
|||||||
String get wizardToolsFeature3 =>
|
String get wizardToolsFeature3 =>
|
||||||
'Koristite zapisnike paketa, skeniranje spektra i razvojnu dijagnostiku pri rješavanju problema s mesh mrežom.';
|
'Koristite zapisnike paketa, skeniranje spektra i razvojnu dijagnostiku pri rješavanju problema s mesh mrežom.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryTitle => 'Discover repeaters now?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryDescription =>
|
||||||
|
'Run repeater discovery right after connecting so you can see nearby MeshCore nodes and add them to your network faster.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contactInSensors => 'U Senzorima';
|
String get contactInSensors => 'U Senzorima';
|
||||||
|
|
||||||
|
|||||||
@@ -1896,6 +1896,13 @@ class AppLocalizationsIt extends AppLocalizations {
|
|||||||
String get wizardToolsFeature3 =>
|
String get wizardToolsFeature3 =>
|
||||||
'Usa log dei pacchetti, scansione dello spettro e diagnostica sviluppatore per risolvere problemi della mesh.';
|
'Usa log dei pacchetti, scansione dello spettro e diagnostica sviluppatore per risolvere problemi della mesh.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryTitle => 'Discover repeaters now?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryDescription =>
|
||||||
|
'Run repeater discovery right after connecting so you can see nearby MeshCore nodes and add them to your network faster.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contactInSensors => 'Nei Sensori';
|
String get contactInSensors => 'Nei Sensori';
|
||||||
|
|
||||||
|
|||||||
@@ -1893,6 +1893,13 @@ class AppLocalizationsPl extends AppLocalizations {
|
|||||||
String get wizardToolsFeature3 =>
|
String get wizardToolsFeature3 =>
|
||||||
'Używaj logów pakietów, skanowania widma i diagnostyki deweloperskiej podczas rozwiązywania problemów z mesh.';
|
'Używaj logów pakietów, skanowania widma i diagnostyki deweloperskiej podczas rozwiązywania problemów z mesh.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryTitle => 'Discover repeaters now?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryDescription =>
|
||||||
|
'Run repeater discovery right after connecting so you can see nearby MeshCore nodes and add them to your network faster.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contactInSensors => 'W Czujnikach';
|
String get contactInSensors => 'W Czujnikach';
|
||||||
|
|
||||||
|
|||||||
@@ -1900,6 +1900,13 @@ class AppLocalizationsPt extends AppLocalizations {
|
|||||||
String get wizardToolsFeature3 =>
|
String get wizardToolsFeature3 =>
|
||||||
'Use logs de pacotes, varredura de espectro e diagnóstico de desenvolvedor ao solucionar problemas da malha.';
|
'Use logs de pacotes, varredura de espectro e diagnóstico de desenvolvedor ao solucionar problemas da malha.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryTitle => 'Discover repeaters now?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryDescription =>
|
||||||
|
'Run repeater discovery right after connecting so you can see nearby MeshCore nodes and add them to your network faster.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contactInSensors => 'Nos Sensores';
|
String get contactInSensors => 'Nos Sensores';
|
||||||
|
|
||||||
|
|||||||
@@ -1890,6 +1890,13 @@ class AppLocalizationsRu extends AppLocalizations {
|
|||||||
String get wizardToolsFeature3 =>
|
String get wizardToolsFeature3 =>
|
||||||
'Используйте журналы пакетов, сканирование спектра и диагностику разработчика для устранения проблем mesh-сети.';
|
'Используйте журналы пакетов, сканирование спектра и диагностику разработчика для устранения проблем mesh-сети.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryTitle => 'Discover repeaters now?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryDescription =>
|
||||||
|
'Run repeater discovery right after connecting so you can see nearby MeshCore nodes and add them to your network faster.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contactInSensors => 'В датчиках';
|
String get contactInSensors => 'В датчиках';
|
||||||
|
|
||||||
|
|||||||
@@ -1881,6 +1881,13 @@ class AppLocalizationsSl extends AppLocalizations {
|
|||||||
String get wizardToolsFeature3 =>
|
String get wizardToolsFeature3 =>
|
||||||
'Uporabite dnevnik paketov, pregled spektra in razvojno diagnostiko pri odpravljanju težav v mesh omrežju.';
|
'Uporabite dnevnik paketov, pregled spektra in razvojno diagnostiko pri odpravljanju težav v mesh omrežju.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryTitle => 'Discover repeaters now?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryDescription =>
|
||||||
|
'Run repeater discovery right after connecting so you can see nearby MeshCore nodes and add them to your network faster.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contactInSensors => 'V senzorjih';
|
String get contactInSensors => 'V senzorjih';
|
||||||
|
|
||||||
|
|||||||
@@ -1883,6 +1883,13 @@ class AppLocalizationsTr extends AppLocalizations {
|
|||||||
String get wizardToolsFeature3 =>
|
String get wizardToolsFeature3 =>
|
||||||
'Mesh sorunlarını giderirken paket günlükleri, spektrum taraması ve geliştirici tanılamalarını kullanın.';
|
'Mesh sorunlarını giderirken paket günlükleri, spektrum taraması ve geliştirici tanılamalarını kullanın.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryTitle => 'Discover repeaters now?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryDescription =>
|
||||||
|
'Run repeater discovery right after connecting so you can see nearby MeshCore nodes and add them to your network faster.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contactInSensors => 'Sensörlerde';
|
String get contactInSensors => 'Sensörlerde';
|
||||||
|
|
||||||
|
|||||||
@@ -1896,6 +1896,13 @@ class AppLocalizationsUk extends AppLocalizations {
|
|||||||
String get wizardToolsFeature3 =>
|
String get wizardToolsFeature3 =>
|
||||||
'Використовуйте журнали пакетів, сканування спектра та діагностику розробника для усунення проблем mesh-мережі.';
|
'Використовуйте журнали пакетів, сканування спектра та діагностику розробника для усунення проблем mesh-мережі.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryTitle => 'Discover repeaters now?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryDescription =>
|
||||||
|
'Run repeater discovery right after connecting so you can see nearby MeshCore nodes and add them to your network faster.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contactInSensors => 'У датчиках';
|
String get contactInSensors => 'У датчиках';
|
||||||
|
|
||||||
|
|||||||
@@ -1796,6 +1796,13 @@ class AppLocalizationsZh extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get wizardToolsFeature3 => '在排查 mesh 网络问题时使用数据包日志、频谱扫描和开发者诊断。';
|
String get wizardToolsFeature3 => '在排查 mesh 网络问题时使用数据包日志、频谱扫描和开发者诊断。';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryTitle => 'Discover repeaters now?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get postConnectDiscoveryDescription =>
|
||||||
|
'Run repeater discovery right after connecting so you can see nearby MeshCore nodes and add them to your network faster.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get contactInSensors => '在传感器中';
|
String get contactInSensors => '在传感器中';
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1,66 @@
|
|||||||
{}
|
{
|
||||||
|
"de": [
|
||||||
|
"postConnectDiscoveryTitle",
|
||||||
|
"postConnectDiscoveryDescription"
|
||||||
|
],
|
||||||
|
|
||||||
|
"el": [
|
||||||
|
"postConnectDiscoveryTitle",
|
||||||
|
"postConnectDiscoveryDescription"
|
||||||
|
],
|
||||||
|
|
||||||
|
"es": [
|
||||||
|
"postConnectDiscoveryTitle",
|
||||||
|
"postConnectDiscoveryDescription"
|
||||||
|
],
|
||||||
|
|
||||||
|
"fr": [
|
||||||
|
"postConnectDiscoveryTitle",
|
||||||
|
"postConnectDiscoveryDescription"
|
||||||
|
],
|
||||||
|
|
||||||
|
"hr": [
|
||||||
|
"postConnectDiscoveryTitle",
|
||||||
|
"postConnectDiscoveryDescription"
|
||||||
|
],
|
||||||
|
|
||||||
|
"it": [
|
||||||
|
"postConnectDiscoveryTitle",
|
||||||
|
"postConnectDiscoveryDescription"
|
||||||
|
],
|
||||||
|
|
||||||
|
"pl": [
|
||||||
|
"postConnectDiscoveryTitle",
|
||||||
|
"postConnectDiscoveryDescription"
|
||||||
|
],
|
||||||
|
|
||||||
|
"pt": [
|
||||||
|
"postConnectDiscoveryTitle",
|
||||||
|
"postConnectDiscoveryDescription"
|
||||||
|
],
|
||||||
|
|
||||||
|
"ru": [
|
||||||
|
"postConnectDiscoveryTitle",
|
||||||
|
"postConnectDiscoveryDescription"
|
||||||
|
],
|
||||||
|
|
||||||
|
"sl": [
|
||||||
|
"postConnectDiscoveryTitle",
|
||||||
|
"postConnectDiscoveryDescription"
|
||||||
|
],
|
||||||
|
|
||||||
|
"tr": [
|
||||||
|
"postConnectDiscoveryTitle",
|
||||||
|
"postConnectDiscoveryDescription"
|
||||||
|
],
|
||||||
|
|
||||||
|
"uk": [
|
||||||
|
"postConnectDiscoveryTitle",
|
||||||
|
"postConnectDiscoveryDescription"
|
||||||
|
],
|
||||||
|
|
||||||
|
"zh": [
|
||||||
|
"postConnectDiscoveryTitle",
|
||||||
|
"postConnectDiscoveryDescription"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ import '../widgets/compact_signal_indicator.dart' show SignalMetric;
|
|||||||
enum _DiscoveryListFilter { all, repeaters, sensors, others }
|
enum _DiscoveryListFilter { all, repeaters, sensors, others }
|
||||||
|
|
||||||
class DiscoveryScreen extends StatefulWidget {
|
class DiscoveryScreen extends StatefulWidget {
|
||||||
const DiscoveryScreen({super.key});
|
final bool autoDiscoverRepeatersOnOpen;
|
||||||
|
|
||||||
|
const DiscoveryScreen({super.key, this.autoDiscoverRepeatersOnOpen = false});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<DiscoveryScreen> createState() => _DiscoveryScreenState();
|
State<DiscoveryScreen> createState() => _DiscoveryScreenState();
|
||||||
@@ -25,6 +27,7 @@ class _DiscoveryScreenState extends State<DiscoveryScreen> {
|
|||||||
final Set<int> _runningDiscoveryTypes = <int>{};
|
final Set<int> _runningDiscoveryTypes = <int>{};
|
||||||
final TextEditingController _searchController = TextEditingController();
|
final TextEditingController _searchController = TextEditingController();
|
||||||
bool _isResolvingAll = false;
|
bool _isResolvingAll = false;
|
||||||
|
bool _hasQueuedAutoRepeaterDiscovery = false;
|
||||||
String _searchQuery = '';
|
String _searchQuery = '';
|
||||||
_DiscoveryListFilter _selectedFilter = _DiscoveryListFilter.all;
|
_DiscoveryListFilter _selectedFilter = _DiscoveryListFilter.all;
|
||||||
late final Future<List<MeshMapNode>> _cachedNodesFuture;
|
late final Future<List<MeshMapNode>> _cachedNodesFuture;
|
||||||
@@ -35,6 +38,13 @@ class _DiscoveryScreenState extends State<DiscoveryScreen> {
|
|||||||
_cachedNodesFuture = MeshMapNodesService.loadCachedNodes(
|
_cachedNodesFuture = MeshMapNodesService.loadCachedNodes(
|
||||||
cacheTtl: MeshMapNodesService.traceCacheTtl,
|
cacheTtl: MeshMapNodesService.traceCacheTtl,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (widget.autoDiscoverRepeatersOnOpen) {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
if (!mounted) return;
|
||||||
|
_autoDiscoverRepeaters();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -96,9 +106,10 @@ class _DiscoveryScreenState extends State<DiscoveryScreen> {
|
|||||||
advertType: advertType,
|
advertType: advertType,
|
||||||
);
|
);
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
|
final l10n = AppLocalizations.of(context)!;
|
||||||
final label = switch (advertType) {
|
final label = switch (advertType) {
|
||||||
_repeaterAdvertType => 'Repeater discovery sent',
|
_repeaterAdvertType => l10n.repeaterDiscoverySent,
|
||||||
_sensorAdvertType => 'Sensor discovery sent',
|
_sensorAdvertType => l10n.sensorDiscoverySent,
|
||||||
_ => 'Discovery sent',
|
_ => 'Discovery sent',
|
||||||
};
|
};
|
||||||
ScaffoldMessenger.of(
|
ScaffoldMessenger.of(
|
||||||
@@ -113,6 +124,14 @@ class _DiscoveryScreenState extends State<DiscoveryScreen> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _autoDiscoverRepeaters() async {
|
||||||
|
if (_hasQueuedAutoRepeaterDiscovery) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_hasQueuedAutoRepeaterDiscovery = true;
|
||||||
|
await _discoverNodeType(_repeaterAdvertType);
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _resolveAdvert(PendingAdvert advert) async {
|
Future<void> _resolveAdvert(PendingAdvert advert) async {
|
||||||
final keyHex = advert.publicKeyHex;
|
final keyHex = advert.publicKeyHex;
|
||||||
if (_resolvingAdvertKeys.contains(keyHex)) return;
|
if (_resolvingAdvertKeys.contains(keyHex)) return;
|
||||||
|
|||||||
@@ -737,12 +737,10 @@ class _HomeScreenState extends State<HomeScreen>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showConnectionDialog(BuildContext context) {
|
Future<void> _showConnectionDialog(BuildContext context) async {
|
||||||
showModalBottomSheet(
|
await showConnectionDialogFlow(
|
||||||
context: context,
|
context,
|
||||||
isScrollControlled: true,
|
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
builder: (context) => const ConnectionDialog(),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -221,14 +221,13 @@ class _WelcomeWizardScreenState extends State<WelcomeWizardScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _openConnectionDialog() async {
|
Future<void> _openConnectionDialog() async {
|
||||||
await showModalBottomSheet(
|
final connected = await showConnectionDialogFlow(
|
||||||
context: context,
|
context,
|
||||||
isScrollControlled: true,
|
offerPostConnectRepeaterDiscovery: true,
|
||||||
builder: (context) => const ConnectionDialog(),
|
|
||||||
);
|
);
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
final connectionProvider = context.read<ConnectionProvider>();
|
final connectionProvider = context.read<ConnectionProvider>();
|
||||||
if (connectionProvider.deviceInfo.isConnected) {
|
if (connected) {
|
||||||
await connectionProvider.refreshDeviceInfo();
|
await connectionProvider.refreshDeviceInfo();
|
||||||
}
|
}
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
|
|||||||
@@ -4,10 +4,14 @@ import 'package:provider/provider.dart';
|
|||||||
import '../l10n/app_localizations.dart';
|
import '../l10n/app_localizations.dart';
|
||||||
import '../providers/app_provider.dart';
|
import '../providers/app_provider.dart';
|
||||||
import '../providers/connection_provider.dart';
|
import '../providers/connection_provider.dart';
|
||||||
|
import '../providers/contacts_provider.dart';
|
||||||
|
import '../screens/discovery_screen.dart';
|
||||||
import '../services/network_scanner_service.dart';
|
import '../services/network_scanner_service.dart';
|
||||||
import '../services/profile_workspace_coordinator.dart';
|
import '../services/profile_workspace_coordinator.dart';
|
||||||
import '../services/serial/serial_transport.dart';
|
import '../services/serial/serial_transport.dart';
|
||||||
|
|
||||||
|
enum _ConnectionDialogResult { connected }
|
||||||
|
|
||||||
Future<void> _initializeConnectedWorkspace({
|
Future<void> _initializeConnectedWorkspace({
|
||||||
required ProfileWorkspaceCoordinator profileWorkspaceCoordinator,
|
required ProfileWorkspaceCoordinator profileWorkspaceCoordinator,
|
||||||
required AppProvider appProvider,
|
required AppProvider appProvider,
|
||||||
@@ -16,6 +20,64 @@ Future<void> _initializeConnectedWorkspace({
|
|||||||
await appProvider.initialize();
|
await appProvider.initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> showConnectionDialogFlow(
|
||||||
|
BuildContext context, {
|
||||||
|
Color? backgroundColor,
|
||||||
|
bool offerPostConnectRepeaterDiscovery = false,
|
||||||
|
}) async {
|
||||||
|
final result = await showModalBottomSheet<_ConnectionDialogResult>(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
backgroundColor: backgroundColor,
|
||||||
|
builder: (context) => const ConnectionDialog(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result != _ConnectionDialogResult.connected || !context.mounted) {
|
||||||
|
return result == _ConnectionDialogResult.connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!offerPostConnectRepeaterDiscovery) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final contactsProvider = context.read<ContactsProvider>();
|
||||||
|
if (contactsProvider.repeaters.isNotEmpty) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final l10n = AppLocalizations.of(context)!;
|
||||||
|
final openDiscovery = await showDialog<bool>(
|
||||||
|
context: context,
|
||||||
|
builder: (dialogContext) => AlertDialog(
|
||||||
|
title: Text(l10n.postConnectDiscoveryTitle),
|
||||||
|
content: Text(l10n.postConnectDiscoveryDescription),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(dialogContext).pop(false),
|
||||||
|
child: Text(l10n.continue_),
|
||||||
|
),
|
||||||
|
FilledButton.icon(
|
||||||
|
onPressed: () => Navigator.of(dialogContext).pop(true),
|
||||||
|
icon: const Icon(Icons.router_outlined),
|
||||||
|
label: Text(l10n.discoverRepeaters),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (openDiscovery != true || !context.mounted) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
await Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) =>
|
||||||
|
const DiscoveryScreen(autoDiscoverRepeatersOnOpen: true),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// Connection Dialog with tabs for BLE devices and Network servers
|
/// Connection Dialog with tabs for BLE devices and Network servers
|
||||||
class ConnectionDialog extends StatefulWidget {
|
class ConnectionDialog extends StatefulWidget {
|
||||||
const ConnectionDialog({super.key});
|
const ConnectionDialog({super.key});
|
||||||
@@ -33,6 +95,7 @@ class _ConnectionDialogState extends State<ConnectionDialog>
|
|||||||
int _scannedCount = 0;
|
int _scannedCount = 0;
|
||||||
int _totalToScan = 0;
|
int _totalToScan = 0;
|
||||||
int _lastTabIndex = 0;
|
int _lastTabIndex = 0;
|
||||||
|
bool _hasRequestedBleScan = false;
|
||||||
String? _connectingToServerKey;
|
String? _connectingToServerKey;
|
||||||
String? _connectingBleDeviceId;
|
String? _connectingBleDeviceId;
|
||||||
|
|
||||||
@@ -40,10 +103,6 @@ class _ConnectionDialogState extends State<ConnectionDialog>
|
|||||||
if (_tabController.index == _lastTabIndex) return;
|
if (_tabController.index == _lastTabIndex) return;
|
||||||
_lastTabIndex = _tabController.index;
|
_lastTabIndex = _tabController.index;
|
||||||
|
|
||||||
if (_tabController.index == 0) {
|
|
||||||
_refreshBleDevices();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_tabController.index == 1) {
|
if (_tabController.index == 1) {
|
||||||
if (_networkScanner.hasCachedResults && _discoveredServers.isEmpty) {
|
if (_networkScanner.hasCachedResults && _discoveredServers.isEmpty) {
|
||||||
setState(() {
|
setState(() {
|
||||||
@@ -65,11 +124,6 @@ class _ConnectionDialogState extends State<ConnectionDialog>
|
|||||||
listen: false,
|
listen: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
if (!mounted) return;
|
|
||||||
_refreshBleDevices();
|
|
||||||
});
|
|
||||||
|
|
||||||
_networkScanner.onServerDiscovered = (server) {
|
_networkScanner.onServerDiscovered = (server) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
setState(() {
|
setState(() {
|
||||||
@@ -110,6 +164,13 @@ class _ConnectionDialogState extends State<ConnectionDialog>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _refreshBleDevices() async {
|
Future<void> _refreshBleDevices() async {
|
||||||
|
if (!_hasRequestedBleScan && mounted) {
|
||||||
|
setState(() {
|
||||||
|
_hasRequestedBleScan = true;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
_hasRequestedBleScan = true;
|
||||||
|
}
|
||||||
await _connectionProvider.stopScan();
|
await _connectionProvider.stopScan();
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
await _connectionProvider.startScan();
|
await _connectionProvider.startScan();
|
||||||
@@ -121,6 +182,45 @@ class _ConnectionDialogState extends State<ConnectionDialog>
|
|||||||
return Colors.red;
|
return Colors.red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _handleSuccessfulConnection() async {
|
||||||
|
final appProvider = context.read<AppProvider>();
|
||||||
|
final profileWorkspaceCoordinator = context
|
||||||
|
.read<ProfileWorkspaceCoordinator>();
|
||||||
|
|
||||||
|
await _initializeConnectedWorkspace(
|
||||||
|
profileWorkspaceCoordinator: profileWorkspaceCoordinator,
|
||||||
|
appProvider: appProvider,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!mounted) return;
|
||||||
|
Navigator.of(context).pop(_ConnectionDialogResult.connected);
|
||||||
|
}
|
||||||
|
|
||||||
|
String _normalizeConnectionError(Object error) {
|
||||||
|
var message = error.toString();
|
||||||
|
if (message.startsWith('Exception: ')) {
|
||||||
|
message = message.substring('Exception: '.length);
|
||||||
|
}
|
||||||
|
if (message.startsWith('Connection failed: Exception: ')) {
|
||||||
|
return message.substring('Connection failed: Exception: '.length);
|
||||||
|
}
|
||||||
|
if (message.startsWith('Connection failed: ')) {
|
||||||
|
return message.substring('Connection failed: '.length);
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showConnectionError(Object error) {
|
||||||
|
if (!mounted) return;
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(_normalizeConnectionError(error)),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
duration: const Duration(seconds: 5),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final connectionProvider = context.watch<ConnectionProvider>();
|
final connectionProvider = context.watch<ConnectionProvider>();
|
||||||
@@ -401,11 +501,13 @@ class _ConnectionDialogState extends State<ConnectionDialog>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildBleDevicesTab(ConnectionProvider connectionProvider) {
|
Widget _buildBleDevicesTab(ConnectionProvider connectionProvider) {
|
||||||
|
final l10n = AppLocalizations.of(context)!;
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
_buildSectionBanner(
|
_buildSectionBanner(
|
||||||
icon: Icons.bluetooth_searching_rounded,
|
icon: Icons.bluetooth_searching_rounded,
|
||||||
message: AppLocalizations.of(context)!.defaultPinInfo,
|
message: l10n.defaultPinInfo,
|
||||||
onRefresh: _refreshBleDevices,
|
onRefresh: _refreshBleDevices,
|
||||||
),
|
),
|
||||||
if (connectionProvider.error != null)
|
if (connectionProvider.error != null)
|
||||||
@@ -418,8 +520,10 @@ class _ConnectionDialogState extends State<ConnectionDialog>
|
|||||||
: connectionProvider.scannedDevices.isEmpty
|
: connectionProvider.scannedDevices.isEmpty
|
||||||
? _buildEmptyState(
|
? _buildEmptyState(
|
||||||
icon: Icons.bluetooth_searching_rounded,
|
icon: Icons.bluetooth_searching_rounded,
|
||||||
title: AppLocalizations.of(context)!.noDevicesFound,
|
title: _hasRequestedBleScan
|
||||||
actionLabel: AppLocalizations.of(context)!.scanAgain,
|
? l10n.noDevicesFound
|
||||||
|
: 'Press scan to search for nearby devices',
|
||||||
|
actionLabel: _hasRequestedBleScan ? l10n.scanAgain : 'Scan',
|
||||||
onAction: _refreshBleDevices,
|
onAction: _refreshBleDevices,
|
||||||
)
|
)
|
||||||
: ListView.builder(
|
: ListView.builder(
|
||||||
@@ -434,25 +538,25 @@ class _ConnectionDialogState extends State<ConnectionDialog>
|
|||||||
final isConnecting = _connectingBleDeviceId == deviceId;
|
final isConnecting = _connectingBleDeviceId == deviceId;
|
||||||
|
|
||||||
Future<void> connectBle() async {
|
Future<void> connectBle() async {
|
||||||
final appProvider = context.read<AppProvider>();
|
|
||||||
final profileWorkspaceCoordinator = context
|
|
||||||
.read<ProfileWorkspaceCoordinator>();
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_connectingBleDeviceId = deviceId;
|
_connectingBleDeviceId = deviceId;
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
Navigator.pop(context);
|
|
||||||
final success = await connectionProvider.connect(
|
final success = await connectionProvider.connect(
|
||||||
device,
|
device,
|
||||||
);
|
);
|
||||||
if (success &&
|
if (!success) {
|
||||||
connectionProvider.deviceInfo.isConnected) {
|
final name = device.platformName.isNotEmpty
|
||||||
await _initializeConnectedWorkspace(
|
? device.platformName
|
||||||
profileWorkspaceCoordinator:
|
: 'device';
|
||||||
profileWorkspaceCoordinator,
|
throw Exception(
|
||||||
appProvider: appProvider,
|
connectionProvider.error ??
|
||||||
|
'Failed to connect to $name',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
await _handleSuccessfulConnection();
|
||||||
|
} catch (error) {
|
||||||
|
_showConnectionError(error);
|
||||||
} finally {
|
} finally {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
@@ -547,11 +651,6 @@ class _ConnectionDialogState extends State<ConnectionDialog>
|
|||||||
Future<void> connectServer() async {
|
Future<void> connectServer() async {
|
||||||
final connectionProvider = context
|
final connectionProvider = context
|
||||||
.read<ConnectionProvider>();
|
.read<ConnectionProvider>();
|
||||||
final appProvider = context.read<AppProvider>();
|
|
||||||
final profileWorkspaceCoordinator = context
|
|
||||||
.read<ProfileWorkspaceCoordinator>();
|
|
||||||
final navigator = Navigator.of(context);
|
|
||||||
final messenger = ScaffoldMessenger.of(context);
|
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_connectingToServerKey = serverKey;
|
_connectingToServerKey = serverKey;
|
||||||
@@ -567,52 +666,23 @@ class _ConnectionDialogState extends State<ConnectionDialog>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
await connectionProvider.connectTcp(
|
final success = await connectionProvider.connectTcp(
|
||||||
server.ipAddress,
|
server.ipAddress,
|
||||||
server.port,
|
server.port,
|
||||||
);
|
);
|
||||||
await _initializeConnectedWorkspace(
|
if (!success) {
|
||||||
profileWorkspaceCoordinator:
|
throw Exception(
|
||||||
profileWorkspaceCoordinator,
|
connectionProvider.error ??
|
||||||
appProvider: appProvider,
|
'Failed to connect to ${server.ipAddress}:${server.port}',
|
||||||
);
|
);
|
||||||
|
|
||||||
if (mounted) {
|
|
||||||
navigator.pop();
|
|
||||||
}
|
}
|
||||||
|
await _handleSuccessfulConnection();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
setState(() {
|
setState(() {
|
||||||
_connectingToServerKey = null;
|
_connectingToServerKey = null;
|
||||||
});
|
});
|
||||||
|
_showConnectionError(e);
|
||||||
var errorMessage = e.toString();
|
|
||||||
if (errorMessage.startsWith('Exception: ')) {
|
|
||||||
errorMessage = errorMessage.substring(
|
|
||||||
'Exception: '.length,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (errorMessage.startsWith(
|
|
||||||
'Connection failed: Exception: ',
|
|
||||||
)) {
|
|
||||||
errorMessage = errorMessage.substring(
|
|
||||||
'Connection failed: Exception: '.length,
|
|
||||||
);
|
|
||||||
} else if (errorMessage.startsWith(
|
|
||||||
'Connection failed: ',
|
|
||||||
)) {
|
|
||||||
errorMessage = errorMessage.substring(
|
|
||||||
'Connection failed: '.length,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
messenger.showSnackBar(
|
|
||||||
SnackBar(
|
|
||||||
content: Text(errorMessage),
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
duration: const Duration(seconds: 5),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -679,8 +749,10 @@ class _ConnectionDialogState extends State<ConnectionDialog>
|
|||||||
actionLabel: actionLabel,
|
actionLabel: actionLabel,
|
||||||
onAction: onAction,
|
onAction: onAction,
|
||||||
),
|
),
|
||||||
onConnected: () {
|
onConnected: (result) {
|
||||||
if (mounted) Navigator.of(context).pop();
|
if (mounted) {
|
||||||
|
Navigator.of(context).pop(result);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -706,7 +778,7 @@ typedef _EmptyStateBuilder =
|
|||||||
});
|
});
|
||||||
|
|
||||||
class _SerialDeviceList extends StatefulWidget {
|
class _SerialDeviceList extends StatefulWidget {
|
||||||
final VoidCallback onConnected;
|
final ValueChanged<_ConnectionDialogResult> onConnected;
|
||||||
final _TransportCardBuilder buildTransportCard;
|
final _TransportCardBuilder buildTransportCard;
|
||||||
final _EmptyStateBuilder buildEmptyState;
|
final _EmptyStateBuilder buildEmptyState;
|
||||||
|
|
||||||
@@ -801,9 +873,6 @@ class _SerialDeviceListState extends State<_SerialDeviceList> {
|
|||||||
setState(() => _isConnecting = true);
|
setState(() => _isConnecting = true);
|
||||||
try {
|
try {
|
||||||
final connectionProvider = context.read<ConnectionProvider>();
|
final connectionProvider = context.read<ConnectionProvider>();
|
||||||
final appProvider = context.read<AppProvider>();
|
|
||||||
final profileWorkspaceCoordinator = context
|
|
||||||
.read<ProfileWorkspaceCoordinator>();
|
|
||||||
final connection = await _transport.connect(device);
|
final connection = await _transport.connect(device);
|
||||||
final success = await connectionProvider.connectSerial(
|
final success = await connectionProvider.connectSerial(
|
||||||
service: connection.service,
|
service: connection.service,
|
||||||
@@ -815,10 +884,11 @@ class _SerialDeviceListState extends State<_SerialDeviceList> {
|
|||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
await _initializeConnectedWorkspace(
|
await _initializeConnectedWorkspace(
|
||||||
profileWorkspaceCoordinator: profileWorkspaceCoordinator,
|
profileWorkspaceCoordinator: context
|
||||||
appProvider: appProvider,
|
.read<ProfileWorkspaceCoordinator>(),
|
||||||
|
appProvider: context.read<AppProvider>(),
|
||||||
);
|
);
|
||||||
widget.onConnected();
|
widget.onConnected(_ConnectionDialogResult.connected);
|
||||||
} else {
|
} else {
|
||||||
await connection.disconnect();
|
await connection.disconnect();
|
||||||
connection.service.dispose();
|
connection.service.dispose();
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ Future<void> _pumpDiscoveryScreen(
|
|||||||
WidgetTester tester, {
|
WidgetTester tester, {
|
||||||
ContactsProvider? contactsProvider,
|
ContactsProvider? contactsProvider,
|
||||||
ConnectionProvider? connectionProvider,
|
ConnectionProvider? connectionProvider,
|
||||||
|
DiscoveryScreen screen = const DiscoveryScreen(),
|
||||||
}) async {
|
}) async {
|
||||||
final resolvedContactsProvider = contactsProvider ?? ContactsProvider();
|
final resolvedContactsProvider = contactsProvider ?? ContactsProvider();
|
||||||
final resolvedConnectionProvider =
|
final resolvedConnectionProvider =
|
||||||
@@ -56,7 +57,7 @@ Future<void> _pumpDiscoveryScreen(
|
|||||||
child: MaterialApp(
|
child: MaterialApp(
|
||||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||||
supportedLocales: AppLocalizations.supportedLocales,
|
supportedLocales: AppLocalizations.supportedLocales,
|
||||||
home: const DiscoveryScreen(),
|
home: screen,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -113,6 +114,21 @@ void main() {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
testWidgets('auto discovery can trigger repeater discovery on open', (
|
||||||
|
tester,
|
||||||
|
) async {
|
||||||
|
final connectionProvider = _FakeConnectionProvider(isConnected: true);
|
||||||
|
|
||||||
|
await _pumpDiscoveryScreen(
|
||||||
|
tester,
|
||||||
|
connectionProvider: connectionProvider,
|
||||||
|
screen: const DiscoveryScreen(autoDiscoverRepeatersOnOpen: true),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(connectionProvider.discoveredAdvertTypes, [2]);
|
||||||
|
expect(find.text('Repeater discovery sent'), findsOneWidget);
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('search and inline type filters narrow discovered nodes', (
|
testWidgets('search and inline type filters narrow discovered nodes', (
|
||||||
tester,
|
tester,
|
||||||
) async {
|
) async {
|
||||||
|
|||||||
67
test/widgets/connection_dialog_test.dart
Normal file
67
test/widgets/connection_dialog_test.dart
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:meshcore_sar_app/l10n/app_localizations.dart';
|
||||||
|
import 'package:meshcore_sar_app/providers/connection_provider.dart';
|
||||||
|
import 'package:meshcore_sar_app/widgets/connection_dialog.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class _FakeConnectionProvider extends ConnectionProvider {
|
||||||
|
int startScanCalls = 0;
|
||||||
|
int stopScanCalls = 0;
|
||||||
|
bool _isScanning = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isScanning => _isScanning;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<ScannedDevice> get scannedDevices => const [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? get error => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> startScan() async {
|
||||||
|
startScanCalls += 1;
|
||||||
|
_isScanning = true;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> stopScan() async {
|
||||||
|
stopScanCalls += 1;
|
||||||
|
_isScanning = false;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
testWidgets('BLE scan waits for explicit user action', (tester) async {
|
||||||
|
final connectionProvider = _FakeConnectionProvider();
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
ChangeNotifierProvider<ConnectionProvider>.value(
|
||||||
|
value: connectionProvider,
|
||||||
|
child: MaterialApp(
|
||||||
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||||
|
supportedLocales: AppLocalizations.supportedLocales,
|
||||||
|
home: const Scaffold(body: ConnectionDialog()),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
expect(connectionProvider.startScanCalls, 0);
|
||||||
|
expect(
|
||||||
|
find.text('Press scan to search for nearby devices'),
|
||||||
|
findsOneWidget,
|
||||||
|
);
|
||||||
|
expect(find.text('Scan'), findsOneWidget);
|
||||||
|
|
||||||
|
await tester.tap(find.widgetWithText(FilledButton, 'Scan'));
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
expect(connectionProvider.stopScanCalls, 1);
|
||||||
|
expect(connectionProvider.startScanCalls, 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user