mirror of
https://github.com/zjs81/meshcore-open.git
synced 2026-04-20 22:13:48 +00:00
Enhance BLE connection handling and improve USB connection messaging
- Wrapped BLE scan and connection methods in try-catch blocks to handle errors gracefully and provide debug output. - Added retry logic for service discovery on web platforms after transient disconnections. - Updated USB connection messages in multiple languages to reflect active support on Android and desktop platforms. - Improved loading indicators for contacts screen to show a spinner during data loading.
This commit is contained in:
parent
ee3af52c0f
commit
2d1160d992
31 changed files with 240 additions and 140 deletions
|
|
@ -37,6 +37,7 @@ class MainActivity : FlutterActivity() {
|
|||
private var usbConnection: UsbDeviceConnection? = null
|
||||
private var usbPort: UsbSerialPort? = null
|
||||
private var ioManager: SerialInputOutputManager? = null
|
||||
private var connectedDeviceName: String? = null
|
||||
|
||||
private var pendingConnectResult: MethodChannel.Result? = null
|
||||
private var pendingConnectPortName: String? = null
|
||||
|
|
@ -45,7 +46,19 @@ class MainActivity : FlutterActivity() {
|
|||
private val permissionReceiver =
|
||||
object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
if (intent?.action != usbPermissionAction) {
|
||||
when (intent?.action) {
|
||||
UsbManager.ACTION_USB_DEVICE_DETACHED -> {
|
||||
handleUsbDetached(intent)
|
||||
return
|
||||
}
|
||||
usbPermissionAction -> {
|
||||
}
|
||||
else -> {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (intent.action != usbPermissionAction) {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -116,12 +129,19 @@ class MainActivity : FlutterActivity() {
|
|||
override fun onDestroy() {
|
||||
closeUsbConnection()
|
||||
usbIoExecutor.shutdownNow()
|
||||
unregisterReceiver(permissionReceiver)
|
||||
try {
|
||||
unregisterReceiver(permissionReceiver)
|
||||
} catch (_: IllegalArgumentException) {
|
||||
}
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
private fun registerUsbPermissionReceiver() {
|
||||
val filter = IntentFilter(usbPermissionAction)
|
||||
val filter =
|
||||
IntentFilter().apply {
|
||||
addAction(usbPermissionAction)
|
||||
addAction(UsbManager.ACTION_USB_DEVICE_DETACHED)
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
registerReceiver(permissionReceiver, filter, RECEIVER_NOT_EXPORTED)
|
||||
} else {
|
||||
|
|
@ -256,6 +276,7 @@ class MainActivity : FlutterActivity() {
|
|||
|
||||
usbConnection = connection
|
||||
usbPort = port
|
||||
connectedDeviceName = device.deviceName
|
||||
|
||||
ioManager =
|
||||
SerialInputOutputManager(
|
||||
|
|
@ -311,6 +332,38 @@ class MainActivity : FlutterActivity() {
|
|||
} catch (_: Exception) {
|
||||
}
|
||||
usbConnection = null
|
||||
connectedDeviceName = null
|
||||
}
|
||||
|
||||
private fun handleUsbDetached(intent: Intent) {
|
||||
val detachedDevice =
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
intent.getParcelableExtra(UsbManager.EXTRA_DEVICE, UsbDevice::class.java)
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)
|
||||
}
|
||||
|
||||
val detachedName = detachedDevice?.deviceName ?: return
|
||||
|
||||
if (pendingConnectPortName == detachedName) {
|
||||
pendingConnectResult?.error(
|
||||
"usb_device_detached",
|
||||
"USB device was removed before the connection completed",
|
||||
null,
|
||||
)
|
||||
pendingConnectResult = null
|
||||
pendingConnectPortName = null
|
||||
}
|
||||
|
||||
if (connectedDeviceName == detachedName) {
|
||||
closeUsbConnection()
|
||||
eventSink?.error(
|
||||
"usb_device_detached",
|
||||
"USB device was disconnected",
|
||||
null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun pendingIntentFlags(): Int {
|
||||
|
|
|
|||
|
|
@ -738,12 +738,18 @@ class MeshCoreConnector extends ChangeNotifier {
|
|||
notifyListeners();
|
||||
});
|
||||
|
||||
await FlutterBluePlus.startScan(
|
||||
withKeywords: ["MeshCore-", "Whisper-"],
|
||||
webOptionalServices: [Guid(MeshCoreUuids.service)],
|
||||
timeout: timeout,
|
||||
androidScanMode: AndroidScanMode.lowLatency,
|
||||
);
|
||||
try {
|
||||
await FlutterBluePlus.startScan(
|
||||
withKeywords: ["MeshCore-", "Whisper-"],
|
||||
webOptionalServices: [Guid(MeshCoreUuids.service)],
|
||||
timeout: timeout,
|
||||
androidScanMode: AndroidScanMode.lowLatency,
|
||||
);
|
||||
} catch (error) {
|
||||
debugPrint('[BLE Scan] Scan/picker failure: $error');
|
||||
_setState(MeshCoreConnectionState.disconnected);
|
||||
rethrow;
|
||||
}
|
||||
|
||||
await Future.delayed(timeout);
|
||||
await stopScan();
|
||||
|
|
@ -791,17 +797,24 @@ class MeshCoreConnector extends ChangeNotifier {
|
|||
notifyListeners();
|
||||
|
||||
try {
|
||||
final connectLabel = _deviceDisplayName ?? _deviceId;
|
||||
debugPrint('[BLE Connect] Starting connect to $connectLabel');
|
||||
_connectionSubscription = device.connectionState.listen((state) {
|
||||
if (state == BluetoothConnectionState.disconnected && isConnected) {
|
||||
_handleDisconnection();
|
||||
}
|
||||
});
|
||||
|
||||
await device.connect(
|
||||
timeout: const Duration(seconds: 15),
|
||||
mtu: null,
|
||||
license: License.free,
|
||||
);
|
||||
try {
|
||||
await device.connect(
|
||||
timeout: const Duration(seconds: 15),
|
||||
mtu: null,
|
||||
license: License.free,
|
||||
);
|
||||
} catch (error) {
|
||||
debugPrint('[BLE Connect] device.connect() failure: $error');
|
||||
rethrow;
|
||||
}
|
||||
|
||||
// Request larger MTU only on native platforms; web does not support it.
|
||||
if (!PlatformInfo.isWeb) {
|
||||
|
|
@ -813,7 +826,27 @@ class MeshCoreConnector extends ChangeNotifier {
|
|||
}
|
||||
}
|
||||
|
||||
List<BluetoothService> services = await device.discoverServices();
|
||||
late final List<BluetoothService> services;
|
||||
try {
|
||||
services = await device.discoverServices();
|
||||
} catch (error) {
|
||||
debugPrint('[BLE Connect] service discovery failure: $error');
|
||||
if (PlatformInfo.isWeb &&
|
||||
error.toString().contains('GATT Server is disconnected')) {
|
||||
debugPrint(
|
||||
'[BLE Connect] retrying service discovery after transient web disconnect',
|
||||
);
|
||||
await Future<void>.delayed(const Duration(milliseconds: 300));
|
||||
await device.connect(
|
||||
timeout: const Duration(seconds: 15),
|
||||
mtu: null,
|
||||
license: License.free,
|
||||
);
|
||||
services = await device.discoverServices();
|
||||
} else {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
BluetoothService? uartService;
|
||||
for (var service in services) {
|
||||
|
|
@ -847,6 +880,7 @@ class MeshCoreConnector extends ChangeNotifier {
|
|||
try {
|
||||
await _txCharacteristic!.setNotifyValue(true);
|
||||
} catch (error) {
|
||||
debugPrint('[BLE Connect] notify failure (web, ignored): $error');
|
||||
debugPrint('Web setNotifyValue error (ignoring): $error');
|
||||
}
|
||||
}());
|
||||
|
|
@ -861,6 +895,7 @@ class MeshCoreConnector extends ChangeNotifier {
|
|||
await _txCharacteristic!.setNotifyValue(true);
|
||||
notifySet = true;
|
||||
} catch (e) {
|
||||
debugPrint('[BLE Connect] notify failure: $e');
|
||||
debugPrint('setNotifyValue attempt ${attempt + 1}/3 failed: $e');
|
||||
if (attempt == 2) rethrow;
|
||||
}
|
||||
|
|
@ -1231,6 +1266,15 @@ class MeshCoreConnector extends ChangeNotifier {
|
|||
_selfInfoRetryTimer?.cancel();
|
||||
if (PlatformInfo.isWeb &&
|
||||
_activeTransport == MeshCoreTransportType.bluetooth) {
|
||||
_selfInfoRetryTimer = Timer(const Duration(seconds: 10), () {
|
||||
if (!isConnected || !_awaitingSelfInfo) {
|
||||
return;
|
||||
}
|
||||
if (_isLoadingContacts || _isSyncingChannels || _channelSyncInFlight) {
|
||||
return;
|
||||
}
|
||||
unawaited(sendFrame(buildAppStartFrame()));
|
||||
});
|
||||
return;
|
||||
}
|
||||
_selfInfoRetryTimer = Timer.periodic(const Duration(milliseconds: 3500), (
|
||||
|
|
|
|||
|
|
@ -1806,9 +1806,9 @@
|
|||
"connectionChoiceBluetoothLabel": "Bluetooth",
|
||||
"connectionChoiceTitle": "Изберете метода на връзка.",
|
||||
"connectionChoiceSubtitle": "Изберете как искате да получите вашия устройство MeshCore.",
|
||||
"usbScreenTitle": "Връзката чрез USB ще бъде налична скоро.",
|
||||
"usbScreenSubtitle": "Създаваме път за комуникация, базиран на последователно предаване на данни, за Android и настолни компютри.",
|
||||
"usbScreenStatus": "Ще бъде достъпно скоро",
|
||||
"usbScreenNote": "След като бъде внедрена поддръжката за USB, ще изберете сериен порт и ще се свържете директно към вашето устройство MeshCore.",
|
||||
"usbScreenNote": "USB серийната връзка е активна на поддържаните Android устройства и настолни платформи.",
|
||||
"usbScreenStatus": "Изберете USB устройство",
|
||||
"usbScreenTitle": "Свързване чрез USB",
|
||||
"usbScreenSubtitle": "Изберете открития сериен уред и свържете директно към вашия MeshCore възел.",
|
||||
"usbScreenEmptyState": "Няма открити USB устройства. Включете едно и опитайте отново."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1834,9 +1834,9 @@
|
|||
"connectionChoiceUsbLabel": "USB",
|
||||
"connectionChoiceBluetoothLabel": "Bluetooth",
|
||||
"connectionChoiceTitle": "Wählen Sie Ihre bevorzugte Verbindungsmethode.",
|
||||
"usbScreenTitle": "Die USB-Verbindung wird bald verfügbar sein.",
|
||||
"usbScreenSubtitle": "Wir entwickeln eine Verbindung, die sowohl für Android- als auch für Desktop-Geräte geeignet ist und auf einer seriellen Schnittstelle basiert.",
|
||||
"usbScreenStatus": "Bald verfügbar",
|
||||
"usbScreenNote": "Sobald die USB-Unterstützung implementiert ist, wählen Sie einen seriellen Anschluss und verbinden Sie ihn direkt mit Ihrem MeshCore-Gerät.",
|
||||
"usbScreenSubtitle": "Wählen Sie ein erkannten serielles Gerät aus und verbinden Sie es direkt mit Ihrem MeshCore-Knoten.",
|
||||
"usbScreenNote": "USB-Serielle Schnittstelle ist auf unterstützten Android-Geräten und Desktop-Plattformen aktiv.",
|
||||
"usbScreenTitle": "Über USB verbinden",
|
||||
"usbScreenStatus": "Wählen Sie ein USB-Gerät aus",
|
||||
"usbScreenEmptyState": "Keine USB-Geräte gefunden. Schließen Sie eines an und aktualisieren Sie."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1834,9 +1834,9 @@
|
|||
"connectionChoiceSubtitle": "Seleccione la forma en que desea acceder a su dispositivo MeshCore.",
|
||||
"connectionChoiceBluetoothLabel": "Bluetooth",
|
||||
"connectionChoiceUsbLabel": "USB",
|
||||
"usbScreenTitle": "La conexión USB estará disponible próximamente.",
|
||||
"usbScreenSubtitle": "Estamos creando una conexión en serie para dispositivos Android y de escritorio.",
|
||||
"usbScreenStatus": "Próximamente",
|
||||
"usbScreenNote": "Una vez que se implemente el soporte para USB, seleccionará un puerto serie y se conectará directamente a su dispositivo MeshCore.",
|
||||
"usbScreenEmptyState": "No se detectaron dispositivos USB. Conecte uno y vuelva a intentar."
|
||||
"usbScreenStatus": "Seleccione un dispositivo USB",
|
||||
"usbScreenNote": "La comunicación serial a través de USB está activa en dispositivos Android compatibles y en plataformas de escritorio.",
|
||||
"usbScreenTitle": "Conecte mediante USB",
|
||||
"usbScreenSubtitle": "Seleccione un dispositivo de serie detectado y conéctelo directamente a su nodo MeshCore.",
|
||||
"usbScreenEmptyState": "No se encontraron dispositivos USB. Conecte uno y vuelva a cargar."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1806,9 +1806,9 @@
|
|||
"connectionChoiceBluetoothLabel": "Bluetooth",
|
||||
"connectionChoiceUsbLabel": "USB",
|
||||
"connectionChoiceSubtitle": "Choisissez la méthode de livraison que vous préférez pour votre appareil MeshCore.",
|
||||
"usbScreenTitle": "La connexion USB sera disponible prochainement.",
|
||||
"usbScreenSubtitle": "Nous mettons en place un chemin de connexion basé sur une série pour les appareils Android et les ordinateurs de bureau.",
|
||||
"usbScreenStatus": "Bientôt",
|
||||
"usbScreenNote": "Une fois que le support USB sera disponible, vous sélectionnerez un port série et vous connecterez directement à votre appareil MeshCore.",
|
||||
"usbScreenEmptyState": "Aucun périphérique USB n'a été trouvé. Connectez-en un et rafraîchissez."
|
||||
"usbScreenStatus": "Sélectionnez un périphérique USB",
|
||||
"usbScreenSubtitle": "Sélectionnez un périphérique série détecté et connectez-vous directement à votre nœud MeshCore.",
|
||||
"usbScreenNote": "La communication série USB est active sur les appareils Android et les plateformes de bureau pris en charge.",
|
||||
"usbScreenTitle": "Connectez via USB",
|
||||
"usbScreenEmptyState": "Aucun périphérique USB n'a été trouvé. Veuillez connecter un périphérique et rafraîchir la page."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1806,9 +1806,9 @@
|
|||
"connectionChoiceSubtitle": "Seleziona il metodo che preferisci per accedere al tuo dispositivo MeshCore.",
|
||||
"connectionChoiceBluetoothLabel": "Bluetooth",
|
||||
"connectionChoiceUsbLabel": "USB",
|
||||
"usbScreenTitle": "La connessione USB sarà disponibile a breve.",
|
||||
"usbScreenSubtitle": "Stiamo sviluppando un percorso di connessione basato su serie per Android e per i desktop.",
|
||||
"usbScreenStatus": "Arriverà presto",
|
||||
"usbScreenNote": "Una volta che il supporto USB sarà disponibile, selezionerete una porta seriale e vi connetterete direttamente al vostro dispositivo MeshCore.",
|
||||
"usbScreenNote": "La comunicazione seriale USB è attiva sui dispositivi Android supportati e sulle piattaforme desktop.",
|
||||
"usbScreenStatus": "Seleziona un dispositivo USB",
|
||||
"usbScreenSubtitle": "Seleziona il dispositivo seriale rilevato e connettilo direttamente al tuo nodo MeshCore.",
|
||||
"usbScreenTitle": "Connessione tramite USB",
|
||||
"usbScreenEmptyState": "Nessun dispositivo USB rilevato. Collegare uno e riavviare."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,18 +122,18 @@ class AppLocalizationsBg extends AppLocalizations {
|
|||
String get connectionChoiceBluetoothLabel => 'Bluetooth';
|
||||
|
||||
@override
|
||||
String get usbScreenTitle => 'Връзката чрез USB ще бъде налична скоро.';
|
||||
String get usbScreenTitle => 'Свързване чрез USB';
|
||||
|
||||
@override
|
||||
String get usbScreenSubtitle =>
|
||||
'Създаваме път за комуникация, базиран на последователно предаване на данни, за Android и настолни компютри.';
|
||||
'Изберете открития сериен уред и свържете директно към вашия MeshCore възел.';
|
||||
|
||||
@override
|
||||
String get usbScreenStatus => 'Ще бъде достъпно скоро';
|
||||
String get usbScreenStatus => 'Изберете USB устройство';
|
||||
|
||||
@override
|
||||
String get usbScreenNote =>
|
||||
'След като бъде внедрена поддръжката за USB, ще изберете сериен порт и ще се свържете директно към вашето устройство MeshCore.';
|
||||
'USB серийната връзка е активна на поддържаните Android устройства и настолни платформи.';
|
||||
|
||||
@override
|
||||
String get usbScreenEmptyState =>
|
||||
|
|
|
|||
|
|
@ -123,18 +123,18 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||
String get connectionChoiceBluetoothLabel => 'Bluetooth';
|
||||
|
||||
@override
|
||||
String get usbScreenTitle => 'Die USB-Verbindung wird bald verfügbar sein.';
|
||||
String get usbScreenTitle => 'Über USB verbinden';
|
||||
|
||||
@override
|
||||
String get usbScreenSubtitle =>
|
||||
'Wir entwickeln eine Verbindung, die sowohl für Android- als auch für Desktop-Geräte geeignet ist und auf einer seriellen Schnittstelle basiert.';
|
||||
'Wählen Sie ein erkannten serielles Gerät aus und verbinden Sie es direkt mit Ihrem MeshCore-Knoten.';
|
||||
|
||||
@override
|
||||
String get usbScreenStatus => 'Bald verfügbar';
|
||||
String get usbScreenStatus => 'Wählen Sie ein USB-Gerät aus';
|
||||
|
||||
@override
|
||||
String get usbScreenNote =>
|
||||
'Sobald die USB-Unterstützung implementiert ist, wählen Sie einen seriellen Anschluss und verbinden Sie ihn direkt mit Ihrem MeshCore-Gerät.';
|
||||
'USB-Serielle Schnittstelle ist auf unterstützten Android-Geräten und Desktop-Plattformen aktiv.';
|
||||
|
||||
@override
|
||||
String get usbScreenEmptyState =>
|
||||
|
|
|
|||
|
|
@ -122,23 +122,22 @@ class AppLocalizationsEs extends AppLocalizations {
|
|||
String get connectionChoiceBluetoothLabel => 'Bluetooth';
|
||||
|
||||
@override
|
||||
String get usbScreenTitle =>
|
||||
'La conexión USB estará disponible próximamente.';
|
||||
String get usbScreenTitle => 'Conecte mediante USB';
|
||||
|
||||
@override
|
||||
String get usbScreenSubtitle =>
|
||||
'Estamos creando una conexión en serie para dispositivos Android y de escritorio.';
|
||||
'Seleccione un dispositivo de serie detectado y conéctelo directamente a su nodo MeshCore.';
|
||||
|
||||
@override
|
||||
String get usbScreenStatus => 'Próximamente';
|
||||
String get usbScreenStatus => 'Seleccione un dispositivo USB';
|
||||
|
||||
@override
|
||||
String get usbScreenNote =>
|
||||
'Una vez que se implemente el soporte para USB, seleccionará un puerto serie y se conectará directamente a su dispositivo MeshCore.';
|
||||
'La comunicación serial a través de USB está activa en dispositivos Android compatibles y en plataformas de escritorio.';
|
||||
|
||||
@override
|
||||
String get usbScreenEmptyState =>
|
||||
'No se detectaron dispositivos USB. Conecte uno y vuelva a intentar.';
|
||||
'No se encontraron dispositivos USB. Conecte uno y vuelva a cargar.';
|
||||
|
||||
@override
|
||||
String get scanner_scanning => 'Escaneando dispositivos...';
|
||||
|
|
|
|||
|
|
@ -122,23 +122,22 @@ class AppLocalizationsFr extends AppLocalizations {
|
|||
String get connectionChoiceBluetoothLabel => 'Bluetooth';
|
||||
|
||||
@override
|
||||
String get usbScreenTitle =>
|
||||
'La connexion USB sera disponible prochainement.';
|
||||
String get usbScreenTitle => 'Connectez via USB';
|
||||
|
||||
@override
|
||||
String get usbScreenSubtitle =>
|
||||
'Nous mettons en place un chemin de connexion basé sur une série pour les appareils Android et les ordinateurs de bureau.';
|
||||
'Sélectionnez un périphérique série détecté et connectez-vous directement à votre nœud MeshCore.';
|
||||
|
||||
@override
|
||||
String get usbScreenStatus => 'Bientôt';
|
||||
String get usbScreenStatus => 'Sélectionnez un périphérique USB';
|
||||
|
||||
@override
|
||||
String get usbScreenNote =>
|
||||
'Une fois que le support USB sera disponible, vous sélectionnerez un port série et vous connecterez directement à votre appareil MeshCore.';
|
||||
'La communication série USB est active sur les appareils Android et les plateformes de bureau pris en charge.';
|
||||
|
||||
@override
|
||||
String get usbScreenEmptyState =>
|
||||
'Aucun périphérique USB n\'a été trouvé. Connectez-en un et rafraîchissez.';
|
||||
'Aucun périphérique USB n\'a été trouvé. Veuillez connecter un périphérique et rafraîchir la page.';
|
||||
|
||||
@override
|
||||
String get scanner_scanning => 'Recherche de périphériques...';
|
||||
|
|
|
|||
|
|
@ -123,18 +123,18 @@ class AppLocalizationsIt extends AppLocalizations {
|
|||
String get connectionChoiceBluetoothLabel => 'Bluetooth';
|
||||
|
||||
@override
|
||||
String get usbScreenTitle => 'La connessione USB sarà disponibile a breve.';
|
||||
String get usbScreenTitle => 'Connessione tramite USB';
|
||||
|
||||
@override
|
||||
String get usbScreenSubtitle =>
|
||||
'Stiamo sviluppando un percorso di connessione basato su serie per Android e per i desktop.';
|
||||
'Seleziona il dispositivo seriale rilevato e connettilo direttamente al tuo nodo MeshCore.';
|
||||
|
||||
@override
|
||||
String get usbScreenStatus => 'Arriverà presto';
|
||||
String get usbScreenStatus => 'Seleziona un dispositivo USB';
|
||||
|
||||
@override
|
||||
String get usbScreenNote =>
|
||||
'Una volta che il supporto USB sarà disponibile, selezionerete una porta seriale e vi connetterete direttamente al vostro dispositivo MeshCore.';
|
||||
'La comunicazione seriale USB è attiva sui dispositivi Android supportati e sulle piattaforme desktop.';
|
||||
|
||||
@override
|
||||
String get usbScreenEmptyState =>
|
||||
|
|
|
|||
|
|
@ -122,18 +122,18 @@ class AppLocalizationsNl extends AppLocalizations {
|
|||
String get connectionChoiceBluetoothLabel => 'Bluetooth';
|
||||
|
||||
@override
|
||||
String get usbScreenTitle => 'USB-verbinding is binnenkort beschikbaar.';
|
||||
String get usbScreenTitle => 'Verbind via USB';
|
||||
|
||||
@override
|
||||
String get usbScreenSubtitle =>
|
||||
'We ontwikkelen een verbindingspad op basis van seriële communicatie, zowel voor Android als voor desktop-computers.';
|
||||
'Kies een gedetecteerd seriële apparaat en verbind deze direct met uw MeshCore-node.';
|
||||
|
||||
@override
|
||||
String get usbScreenStatus => 'Komende week';
|
||||
String get usbScreenStatus => 'Selecteer een USB-apparaat';
|
||||
|
||||
@override
|
||||
String get usbScreenNote =>
|
||||
'Zodra de USB-ondersteuning is geïnstalleerd, selecteert u een seriële poort en verbindt u direct met uw MeshCore-apparaat.';
|
||||
'USB-serieel is actief op ondersteunde Android-apparaten en desktop-platforms.';
|
||||
|
||||
@override
|
||||
String get usbScreenEmptyState =>
|
||||
|
|
|
|||
|
|
@ -122,18 +122,18 @@ class AppLocalizationsPl extends AppLocalizations {
|
|||
String get connectionChoiceBluetoothLabel => 'Bluetooth';
|
||||
|
||||
@override
|
||||
String get usbScreenTitle => 'Połączenie USB będzie dostępne wkrótce.';
|
||||
String get usbScreenTitle => 'Połącz przez USB';
|
||||
|
||||
@override
|
||||
String get usbScreenSubtitle =>
|
||||
'Tworzymy ścieżkę połączenia opartą na protokole szeregowym, przeznaczoną zarówno dla urządzeń z systemem Android, jak i dla komputerów stacjonarnych.';
|
||||
'Wybierz wykryty urządzenie szeregowe i podłącz je bezpośrednio do swojego węzła MeshCore.';
|
||||
|
||||
@override
|
||||
String get usbScreenStatus => 'Wkrótce';
|
||||
String get usbScreenStatus => 'Wybierz urządzenie USB';
|
||||
|
||||
@override
|
||||
String get usbScreenNote =>
|
||||
'Po wdrożeniu wsparcia dla USB, wybierzesz port szeregowy i połączysz się bezpośrednio z urządzeniem MeshCore.';
|
||||
'Port szeregowy USB jest aktywny na urządzeniach z Androidem i platformach stacjonarnych, które obsługują tę funkcję.';
|
||||
|
||||
@override
|
||||
String get usbScreenEmptyState =>
|
||||
|
|
|
|||
|
|
@ -122,18 +122,18 @@ class AppLocalizationsPt extends AppLocalizations {
|
|||
String get connectionChoiceBluetoothLabel => 'Bluetooth';
|
||||
|
||||
@override
|
||||
String get usbScreenTitle => 'A conexão USB estará disponível em breve.';
|
||||
String get usbScreenTitle => 'Conecte via USB';
|
||||
|
||||
@override
|
||||
String get usbScreenSubtitle =>
|
||||
'Estamos criando um caminho de conexão baseado em série para dispositivos Android e de desktop.';
|
||||
'Selecione o dispositivo serial detectado e conecte-o diretamente ao seu nó MeshCore.';
|
||||
|
||||
@override
|
||||
String get usbScreenStatus => 'Em breve';
|
||||
String get usbScreenStatus => 'Selecione um dispositivo USB';
|
||||
|
||||
@override
|
||||
String get usbScreenNote =>
|
||||
'Assim que o suporte USB for implementado, você poderá selecionar uma porta serial e conectar-se diretamente ao seu dispositivo MeshCore.';
|
||||
'A comunicação serial USB está ativa em dispositivos Android e plataformas de desktop compatíveis.';
|
||||
|
||||
@override
|
||||
String get usbScreenEmptyState =>
|
||||
|
|
|
|||
|
|
@ -122,23 +122,22 @@ class AppLocalizationsRu extends AppLocalizations {
|
|||
String get connectionChoiceBluetoothLabel => 'Bluetooth';
|
||||
|
||||
@override
|
||||
String get usbScreenTitle =>
|
||||
'Подключение через USB будет доступно в ближайшее время.';
|
||||
String get usbScreenTitle => 'Подключение через USB';
|
||||
|
||||
@override
|
||||
String get usbScreenSubtitle =>
|
||||
'Мы создаем последовательную схему подключения для устройств на базе Android и настольных компьютеров.';
|
||||
'Выберите обнаруженное устройство с последовательным интерфейсом и подключите его напрямую к вашему узлу MeshCore.';
|
||||
|
||||
@override
|
||||
String get usbScreenStatus => 'Скоро';
|
||||
String get usbScreenStatus => 'Выберите USB-устройство';
|
||||
|
||||
@override
|
||||
String get usbScreenNote =>
|
||||
'Как только появится поддержка USB, вы сможете выбрать последовательный порт и напрямую подключиться к вашему устройству MeshCore.';
|
||||
'USB-серийный порт активен на поддерживаемых устройствах Android и на настольных платформах.';
|
||||
|
||||
@override
|
||||
String get usbScreenEmptyState =>
|
||||
'Не обнаружено никаких устройств USB. Подключите одно из них и обновите список.';
|
||||
'Не обнаружено устройств USB. Подключите одно из них и обновите список.';
|
||||
|
||||
@override
|
||||
String get scanner_scanning => 'Поиск устройств...';
|
||||
|
|
|
|||
|
|
@ -122,18 +122,18 @@ class AppLocalizationsSk extends AppLocalizations {
|
|||
String get connectionChoiceBluetoothLabel => 'Bluetooth';
|
||||
|
||||
@override
|
||||
String get usbScreenTitle => 'Pripojenie cez USB bude k dispozícii čoskoro.';
|
||||
String get usbScreenTitle => 'Pripojte cez USB';
|
||||
|
||||
@override
|
||||
String get usbScreenSubtitle =>
|
||||
'Vytvárajeme komunikačný systém založený na sériovej komunikácii pre Android a stolné počítače.';
|
||||
'Vyberte detekovaný sériový zariadenie a pripojte ho priamo k vašej MeshCore uzlu.';
|
||||
|
||||
@override
|
||||
String get usbScreenStatus => 'Čoskoro';
|
||||
String get usbScreenStatus => 'Vyberte USB zariadenie';
|
||||
|
||||
@override
|
||||
String get usbScreenNote =>
|
||||
'Po implementácii podpory pre USB, budete môcť vybrať sériový port a priamo sa pripojiť k vašmu zariadeniu MeshCore.';
|
||||
'USB sériová komunikácia je aktívna na podporovaných zariadeniach s Androidom a na desktopových platformách.';
|
||||
|
||||
@override
|
||||
String get usbScreenEmptyState =>
|
||||
|
|
|
|||
|
|
@ -122,22 +122,22 @@ class AppLocalizationsSl extends AppLocalizations {
|
|||
String get connectionChoiceBluetoothLabel => 'Bluetooth';
|
||||
|
||||
@override
|
||||
String get usbScreenTitle => 'Vnos preko USB-ja bo v kratkem na voljo.';
|
||||
String get usbScreenTitle => 'Povežite preko USB';
|
||||
|
||||
@override
|
||||
String get usbScreenSubtitle =>
|
||||
'Gradimo pot za serijsko povezavo za Android in računalnike.';
|
||||
'Izberite zaznano serijsko napravo in se neposredno povežite z vašim MeshCore-om.';
|
||||
|
||||
@override
|
||||
String get usbScreenStatus => 'Čez kratko časa';
|
||||
String get usbScreenStatus => 'Izberite USB naprave.';
|
||||
|
||||
@override
|
||||
String get usbScreenNote =>
|
||||
'Ko bo podpora za USB na voljo, boste izbrali serijsko vrata in se neposredno povezali z vašim napravem MeshCore.';
|
||||
'USB serijska povezava je aktivna na podprtih napravah Android in na desktop platformah.';
|
||||
|
||||
@override
|
||||
String get usbScreenEmptyState =>
|
||||
'Niti en USB naprave niso bilo najdeno. Povežite eno in posodobite.';
|
||||
'Niti en USB naprave niso najdeni. Povežite eno in posodobite.';
|
||||
|
||||
@override
|
||||
String get scanner_scanning => 'Skeniram za naprave...';
|
||||
|
|
|
|||
|
|
@ -122,18 +122,18 @@ class AppLocalizationsSv extends AppLocalizations {
|
|||
String get connectionChoiceBluetoothLabel => 'Bluetooth';
|
||||
|
||||
@override
|
||||
String get usbScreenTitle => 'USB-anslutning kommer snart';
|
||||
String get usbScreenTitle => 'Anslut via USB';
|
||||
|
||||
@override
|
||||
String get usbScreenSubtitle =>
|
||||
'Vi skapar en seriebaserad anslutningsväg för både Android- och skrivbordsenheter.';
|
||||
'Välj en detekterad seriell enhet och anslut direkt till din MeshCore-nod.';
|
||||
|
||||
@override
|
||||
String get usbScreenStatus => 'Kommer snart';
|
||||
String get usbScreenStatus => 'Välj en USB-enhet';
|
||||
|
||||
@override
|
||||
String get usbScreenNote =>
|
||||
'När USB-stöd är implementerat, kommer du att välja en seriell port och ansluta direkt till din MeshCore-enhet.';
|
||||
'USB-seriell kommunikation är aktiv på stöderliga Android-enheter och skrivbordsplattformar.';
|
||||
|
||||
@override
|
||||
String get usbScreenEmptyState =>
|
||||
|
|
|
|||
|
|
@ -122,19 +122,18 @@ class AppLocalizationsUk extends AppLocalizations {
|
|||
String get connectionChoiceBluetoothLabel => 'Bluetooth';
|
||||
|
||||
@override
|
||||
String get usbScreenTitle =>
|
||||
'Підключення через USB буде доступне найближчим часом.';
|
||||
String get usbScreenTitle => 'Підключити через USB';
|
||||
|
||||
@override
|
||||
String get usbScreenSubtitle =>
|
||||
'Ми створюємо серійний шлях з\'єднання для Android та десктопних комп\'ютерів.';
|
||||
'Виберіть виявлене серійне пристрій і підключіть його безпосередньо до вашого вузла MeshCore.';
|
||||
|
||||
@override
|
||||
String get usbScreenStatus => 'Скоро';
|
||||
String get usbScreenStatus => 'Виберіть пристрій USB';
|
||||
|
||||
@override
|
||||
String get usbScreenNote =>
|
||||
'Після того, як буде реалізовано підтримку USB, ви виберете серійний порт і підключитесь безпосередньо до вашого пристрою MeshCore.';
|
||||
'USB-серіальний інтерфейс активний на підтримуваних пристроях на базі Android та на десктопних платформах.';
|
||||
|
||||
@override
|
||||
String get usbScreenEmptyState =>
|
||||
|
|
|
|||
|
|
@ -121,16 +121,16 @@ class AppLocalizationsZh extends AppLocalizations {
|
|||
String get connectionChoiceBluetoothLabel => '蓝牙';
|
||||
|
||||
@override
|
||||
String get usbScreenTitle => 'USB 连接即将推出';
|
||||
String get usbScreenTitle => '通过USB连接';
|
||||
|
||||
@override
|
||||
String get usbScreenSubtitle => '我们正在构建一个基于串行的连接路径,用于Android和桌面设备。';
|
||||
String get usbScreenSubtitle => '选择已检测到的串行设备,并直接连接到您的 MeshCore 节点。';
|
||||
|
||||
@override
|
||||
String get usbScreenStatus => '即将推出';
|
||||
String get usbScreenStatus => '选择一个 USB 设备';
|
||||
|
||||
@override
|
||||
String get usbScreenNote => '一旦USB支持功能上线,您就可以选择一个串口,并直接连接到您的MeshCore设备。';
|
||||
String get usbScreenNote => '在支持的 Android 设备和桌面平台上,USB 串行通信功能已启用。';
|
||||
|
||||
@override
|
||||
String get usbScreenEmptyState => '未找到任何 USB 设备。请插入一个,然后刷新。';
|
||||
|
|
|
|||
|
|
@ -1806,9 +1806,9 @@
|
|||
"connectionChoiceUsbLabel": "USB",
|
||||
"connectionChoiceSubtitle": "Kies hoe u uw MeshCore-apparaat wilt bereiken.",
|
||||
"connectionChoiceBluetoothLabel": "Bluetooth",
|
||||
"usbScreenTitle": "USB-verbinding is binnenkort beschikbaar.",
|
||||
"usbScreenSubtitle": "We ontwikkelen een verbindingspad op basis van seriële communicatie, zowel voor Android als voor desktop-computers.",
|
||||
"usbScreenStatus": "Komende week",
|
||||
"usbScreenNote": "Zodra de USB-ondersteuning is geïnstalleerd, selecteert u een seriële poort en verbindt u direct met uw MeshCore-apparaat.",
|
||||
"usbScreenSubtitle": "Kies een gedetecteerd seriële apparaat en verbind deze direct met uw MeshCore-node.",
|
||||
"usbScreenStatus": "Selecteer een USB-apparaat",
|
||||
"usbScreenNote": "USB-serieel is actief op ondersteunde Android-apparaten en desktop-platforms.",
|
||||
"usbScreenTitle": "Verbind via USB",
|
||||
"usbScreenEmptyState": "Geen USB-apparaten gevonden. Sluit er een aan en herlaad."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1806,9 +1806,9 @@
|
|||
"connectionChoiceSubtitle": "Wybierz, w jaki sposób chcesz uzyskać dostęp do swojego urządzenia MeshCore.",
|
||||
"connectionChoiceTitle": "Wybierz metodę połączenia.",
|
||||
"connectionChoiceUsbLabel": "USB",
|
||||
"usbScreenTitle": "Połączenie USB będzie dostępne wkrótce.",
|
||||
"usbScreenSubtitle": "Tworzymy ścieżkę połączenia opartą na protokole szeregowym, przeznaczoną zarówno dla urządzeń z systemem Android, jak i dla komputerów stacjonarnych.",
|
||||
"usbScreenStatus": "Wkrótce",
|
||||
"usbScreenNote": "Po wdrożeniu wsparcia dla USB, wybierzesz port szeregowy i połączysz się bezpośrednio z urządzeniem MeshCore.",
|
||||
"usbScreenTitle": "Połącz przez USB",
|
||||
"usbScreenNote": "Port szeregowy USB jest aktywny na urządzeniach z Androidem i platformach stacjonarnych, które obsługują tę funkcję.",
|
||||
"usbScreenSubtitle": "Wybierz wykryty urządzenie szeregowe i podłącz je bezpośrednio do swojego węzła MeshCore.",
|
||||
"usbScreenStatus": "Wybierz urządzenie USB",
|
||||
"usbScreenEmptyState": "Nie znaleziono żadnych urządzeń USB. Podłącz jedno i zaktualizuj."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1806,9 +1806,9 @@
|
|||
"connectionChoiceUsbLabel": "USB",
|
||||
"connectionChoiceBluetoothLabel": "Bluetooth",
|
||||
"connectionChoiceTitle": "Escolha o método de conexão desejado.",
|
||||
"usbScreenTitle": "A conexão USB estará disponível em breve.",
|
||||
"usbScreenSubtitle": "Estamos criando um caminho de conexão baseado em série para dispositivos Android e de desktop.",
|
||||
"usbScreenStatus": "Em breve",
|
||||
"usbScreenNote": "Assim que o suporte USB for implementado, você poderá selecionar uma porta serial e conectar-se diretamente ao seu dispositivo MeshCore.",
|
||||
"usbScreenNote": "A comunicação serial USB está ativa em dispositivos Android e plataformas de desktop compatíveis.",
|
||||
"usbScreenSubtitle": "Selecione o dispositivo serial detectado e conecte-o diretamente ao seu nó MeshCore.",
|
||||
"usbScreenStatus": "Selecione um dispositivo USB",
|
||||
"usbScreenTitle": "Conecte via USB",
|
||||
"usbScreenEmptyState": "Nenhum dispositivo USB encontrado. Conecte um e atualize."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1046,9 +1046,9 @@
|
|||
"connectionChoiceTitle": "Выберите способ подключения",
|
||||
"connectionChoiceUsbLabel": "USB",
|
||||
"connectionChoiceBluetoothLabel": "Bluetooth",
|
||||
"usbScreenTitle": "Подключение через USB будет доступно в ближайшее время.",
|
||||
"usbScreenSubtitle": "Мы создаем последовательную схему подключения для устройств на базе Android и настольных компьютеров.",
|
||||
"usbScreenStatus": "Скоро",
|
||||
"usbScreenNote": "Как только появится поддержка USB, вы сможете выбрать последовательный порт и напрямую подключиться к вашему устройству MeshCore.",
|
||||
"usbScreenEmptyState": "Не обнаружено никаких устройств USB. Подключите одно из них и обновите список."
|
||||
"usbScreenSubtitle": "Выберите обнаруженное устройство с последовательным интерфейсом и подключите его напрямую к вашему узлу MeshCore.",
|
||||
"usbScreenNote": "USB-серийный порт активен на поддерживаемых устройствах Android и на настольных платформах.",
|
||||
"usbScreenStatus": "Выберите USB-устройство",
|
||||
"usbScreenTitle": "Подключение через USB",
|
||||
"usbScreenEmptyState": "Не обнаружено устройств USB. Подключите одно из них и обновите список."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1806,9 +1806,9 @@
|
|||
"connectionChoiceUsbLabel": "USB",
|
||||
"connectionChoiceTitle": "Vyberte si metódu prepojenia.",
|
||||
"connectionChoiceSubtitle": "Vyberte si, ako chcete dosiahnuť váš zariadenie MeshCore.",
|
||||
"usbScreenTitle": "Pripojenie cez USB bude k dispozícii čoskoro.",
|
||||
"usbScreenSubtitle": "Vytvárajeme komunikačný systém založený na sériovej komunikácii pre Android a stolné počítače.",
|
||||
"usbScreenStatus": "Čoskoro",
|
||||
"usbScreenNote": "Po implementácii podpory pre USB, budete môcť vybrať sériový port a priamo sa pripojiť k vašmu zariadeniu MeshCore.",
|
||||
"usbScreenStatus": "Vyberte USB zariadenie",
|
||||
"usbScreenSubtitle": "Vyberte detekovaný sériový zariadenie a pripojte ho priamo k vašej MeshCore uzlu.",
|
||||
"usbScreenNote": "USB sériová komunikácia je aktívna na podporovaných zariadeniach s Androidom a na desktopových platformách.",
|
||||
"usbScreenTitle": "Pripojte cez USB",
|
||||
"usbScreenEmptyState": "Nenašli sa žiadne USB zariadenia. Pripojte jedno a obnovte."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1806,9 +1806,9 @@
|
|||
"connectionChoiceUsbLabel": "USB",
|
||||
"connectionChoiceTitle": "Izberite svoj način povezave.",
|
||||
"connectionChoiceSubtitle": "Izberite, kako želite dostopati do svojega naprave MeshCore.",
|
||||
"usbScreenTitle": "Vnos preko USB-ja bo v kratkem na voljo.",
|
||||
"usbScreenSubtitle": "Gradimo pot za serijsko povezavo za Android in računalnike.",
|
||||
"usbScreenStatus": "Čez kratko časa",
|
||||
"usbScreenNote": "Ko bo podpora za USB na voljo, boste izbrali serijsko vrata in se neposredno povezali z vašim napravem MeshCore.",
|
||||
"usbScreenEmptyState": "Niti en USB naprave niso bilo najdeno. Povežite eno in posodobite."
|
||||
"usbScreenSubtitle": "Izberite zaznano serijsko napravo in se neposredno povežite z vašim MeshCore-om.",
|
||||
"usbScreenTitle": "Povežite preko USB",
|
||||
"usbScreenStatus": "Izberite USB naprave.",
|
||||
"usbScreenNote": "USB serijska povezava je aktivna na podprtih napravah Android in na desktop platformah.",
|
||||
"usbScreenEmptyState": "Niti en USB naprave niso najdeni. Povežite eno in posodobite."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1806,9 +1806,9 @@
|
|||
"connectionChoiceBluetoothLabel": "Bluetooth",
|
||||
"connectionChoiceSubtitle": "Välj hur du vill komma åt din MeshCore-enhet.",
|
||||
"connectionChoiceTitle": "Välj din anslutningsmetod",
|
||||
"usbScreenTitle": "USB-anslutning kommer snart",
|
||||
"usbScreenSubtitle": "Vi skapar en seriebaserad anslutningsväg för både Android- och skrivbordsenheter.",
|
||||
"usbScreenStatus": "Kommer snart",
|
||||
"usbScreenNote": "När USB-stöd är implementerat, kommer du att välja en seriell port och ansluta direkt till din MeshCore-enhet.",
|
||||
"usbScreenTitle": "Anslut via USB",
|
||||
"usbScreenNote": "USB-seriell kommunikation är aktiv på stöderliga Android-enheter och skrivbordsplattformar.",
|
||||
"usbScreenSubtitle": "Välj en detekterad seriell enhet och anslut direkt till din MeshCore-nod.",
|
||||
"usbScreenStatus": "Välj en USB-enhet",
|
||||
"usbScreenEmptyState": "Inga USB-enheter hittades. Anslut en och uppdatera."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1806,9 +1806,9 @@
|
|||
"connectionChoiceUsbLabel": "USB",
|
||||
"connectionChoiceTitle": "Виберіть спосіб зв'язку",
|
||||
"connectionChoiceBluetoothLabel": "Bluetooth",
|
||||
"usbScreenTitle": "Підключення через USB буде доступне найближчим часом.",
|
||||
"usbScreenSubtitle": "Ми створюємо серійний шлях з'єднання для Android та десктопних комп'ютерів.",
|
||||
"usbScreenStatus": "Скоро",
|
||||
"usbScreenNote": "Після того, як буде реалізовано підтримку USB, ви виберете серійний порт і підключитесь безпосередньо до вашого пристрою MeshCore.",
|
||||
"usbScreenSubtitle": "Виберіть виявлене серійне пристрій і підключіть його безпосередньо до вашого вузла MeshCore.",
|
||||
"usbScreenTitle": "Підключити через USB",
|
||||
"usbScreenStatus": "Виберіть пристрій USB",
|
||||
"usbScreenNote": "USB-серіальний інтерфейс активний на підтримуваних пристроях на базі Android та на десктопних платформах.",
|
||||
"usbScreenEmptyState": "Не знайдено жодних пристроїв USB. Підключіть один і перезавантажте."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1811,9 +1811,9 @@
|
|||
"connectionChoiceBluetoothLabel": "蓝牙",
|
||||
"connectionChoiceTitle": "选择您的连接方式",
|
||||
"connectionChoiceUsbLabel": "USB",
|
||||
"usbScreenTitle": "USB 连接即将推出",
|
||||
"usbScreenSubtitle": "我们正在构建一个基于串行的连接路径,用于Android和桌面设备。",
|
||||
"usbScreenStatus": "即将推出",
|
||||
"usbScreenNote": "一旦USB支持功能上线,您就可以选择一个串口,并直接连接到您的MeshCore设备。",
|
||||
"usbScreenTitle": "通过USB连接",
|
||||
"usbScreenSubtitle": "选择已检测到的串行设备,并直接连接到您的 MeshCore 节点。",
|
||||
"usbScreenStatus": "选择一个 USB 设备",
|
||||
"usbScreenNote": "在支持的 Android 设备和桌面平台上,USB 串行通信功能已启用。",
|
||||
"usbScreenEmptyState": "未找到任何 USB 设备。请插入一个,然后刷新。"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -384,8 +384,15 @@ class _ContactsScreenState extends State<ContactsScreen>
|
|||
|
||||
Widget _buildContactsBody(BuildContext context, MeshCoreConnector connector) {
|
||||
final contacts = connector.contacts;
|
||||
final shouldShowStartupSpinner =
|
||||
contacts.isEmpty &&
|
||||
_groups.isEmpty &&
|
||||
connector.isConnected &&
|
||||
(connector.isLoadingContacts ||
|
||||
connector.isLoadingChannels ||
|
||||
connector.selfPublicKey == null);
|
||||
|
||||
if (contacts.isEmpty && connector.isLoadingContacts && _groups.isEmpty) {
|
||||
if (shouldShowStartupSpinner) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue