mirror of
https://github.com/zjs81/meshcore-open.git
synced 2026-06-20 01:15:35 +10:00
refactor(tcp): promote MeshCoreTcpConnector, fix translations, harden UI
- Replace thin MeshCoreTcpManager facade with a proper MeshCoreTcpConnector
that owns TcpTransportService and the frame subscription, mirroring
MeshCoreUsbManager. The connector no longer holds a raw TcpTransportService
or a _tcpFrameSubscription field.
- Remove hardcoded default host IP from TcpScreen (keep port 5000 hint).
- Disable connect button during scanning state, not just connecting state.
- Fix tcpPortLabel mistranslated as nautical "port/harbor" in de, it, pt,
nl, sv, sk, sl, zh; fix corrupted Slovak tcpPortHint ("5 000" → "5000").
- Remove unused tcpStatus_connecting string from all 15 locale arb files
and all generated app_localizations_*.dart files.
- Add extendedPadding to TCP screen FABs to match USB screen.
- Add Key to connect button; update tests to use byKey and assert
onPressed == null when button is disabled during scanning.
This commit is contained in:
@@ -116,8 +116,7 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
bool _manualDisconnect = false;
|
||||
final MeshCoreUsbManager _usbManager = MeshCoreUsbManager();
|
||||
StreamSubscription<Uint8List>? _usbFrameSubscription;
|
||||
final MeshCoreTcpManager _tcpManager = MeshCoreTcpManager();
|
||||
StreamSubscription<Uint8List>? _tcpFrameSubscription;
|
||||
final MeshCoreTcpConnector _tcpConnector = MeshCoreTcpConnector();
|
||||
MeshCoreTransportType _activeTransport = MeshCoreTransportType.bluetooth;
|
||||
|
||||
final List<ScanResult> _scanResults = [];
|
||||
@@ -257,7 +256,7 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
bool get isUsbTransportConnected =>
|
||||
_state == MeshCoreConnectionState.connected &&
|
||||
_activeTransport == MeshCoreTransportType.usb;
|
||||
String? get activeTcpEndpoint => _tcpManager.activeEndpoint;
|
||||
String? get activeTcpEndpoint => _tcpConnector.activeEndpoint;
|
||||
bool get isTcpTransportConnected =>
|
||||
_state == MeshCoreConnectionState.connected &&
|
||||
_activeTransport == MeshCoreTransportType.tcp;
|
||||
@@ -666,7 +665,7 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
_appDebugLogService = appDebugLogService;
|
||||
_backgroundService = backgroundService;
|
||||
_usbManager.setDebugLogService(_appDebugLogService);
|
||||
_tcpManager.setDebugLogService(_appDebugLogService);
|
||||
_tcpConnector.setDebugLogService(_appDebugLogService);
|
||||
|
||||
// Initialize notification service
|
||||
_notificationService.initialize();
|
||||
@@ -1002,22 +1001,21 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
await disconnect(manual: false);
|
||||
return;
|
||||
}
|
||||
if (_tcpManager.isConnected) {
|
||||
await _tcpManager.disconnect();
|
||||
if (_tcpConnector.isConnected) {
|
||||
await _tcpConnector.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
await _tcpFrameSubscription?.cancel();
|
||||
_tcpFrameSubscription = null;
|
||||
await _tcpManager.connect(host: host, port: port);
|
||||
await _tcpConnector.cancelFrameSubscription();
|
||||
await _tcpConnector.connect(host: host, port: port);
|
||||
final isTcpConnectCancelled =
|
||||
_activeTransport != MeshCoreTransportType.tcp ||
|
||||
_state != MeshCoreConnectionState.connecting ||
|
||||
!_tcpManager.isConnected;
|
||||
!_tcpConnector.isConnected;
|
||||
if (isTcpConnectCancelled) {
|
||||
await handleTcpConnectAbort(
|
||||
message:
|
||||
'connectTcp aborted before handshake: state=$_state transport=$_activeTransport connected=${_tcpManager.isConnected}',
|
||||
'connectTcp aborted before handshake: state=$_state transport=$_activeTransport connected=${_tcpConnector.isConnected}',
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -1027,16 +1025,16 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
final isTcpConnectCancelledAfterDelay =
|
||||
_activeTransport != MeshCoreTransportType.tcp ||
|
||||
_state != MeshCoreConnectionState.connecting ||
|
||||
!_tcpManager.isConnected;
|
||||
!_tcpConnector.isConnected;
|
||||
if (isTcpConnectCancelledAfterDelay) {
|
||||
await handleTcpConnectAbort(
|
||||
message:
|
||||
'connectTcp aborted after connect delay: state=$_state transport=$_activeTransport connected=${_tcpManager.isConnected}',
|
||||
'connectTcp aborted after connect delay: state=$_state transport=$_activeTransport connected=${_tcpConnector.isConnected}',
|
||||
);
|
||||
return;
|
||||
}
|
||||
_tcpFrameSubscription = _tcpManager.frameStream.listen(
|
||||
_handleFrame,
|
||||
_tcpConnector.listenFrames(
|
||||
onFrame: _handleFrame,
|
||||
onError: (error, stackTrace) {
|
||||
_appDebugLogService?.error('TCP transport error: $error', tag: 'TCP');
|
||||
unawaited(disconnect(manual: false));
|
||||
@@ -1073,7 +1071,7 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
manualDisconnect: _manualDisconnect,
|
||||
state: _state,
|
||||
activeTransport: _activeTransport,
|
||||
tcpManagerConnected: _tcpManager.isConnected,
|
||||
tcpManagerConnected: _tcpConnector.isConnected,
|
||||
);
|
||||
if (tcpConnectCancelledBeforeHandshake) {
|
||||
_appDebugLogService?.info(
|
||||
@@ -1445,9 +1443,7 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
await _usbFrameSubscription?.cancel();
|
||||
_usbFrameSubscription = null;
|
||||
await _usbManager.disconnect();
|
||||
await _tcpFrameSubscription?.cancel();
|
||||
_tcpFrameSubscription = null;
|
||||
await _tcpManager.disconnect();
|
||||
await _tcpConnector.disconnect();
|
||||
|
||||
await _notifySubscription?.cancel();
|
||||
_notifySubscription = null;
|
||||
@@ -1530,7 +1526,7 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
if (_activeTransport == MeshCoreTransportType.usb) {
|
||||
await _usbManager.write(data);
|
||||
} else if (_activeTransport == MeshCoreTransportType.tcp) {
|
||||
await _tcpManager.write(data);
|
||||
await _tcpConnector.write(data);
|
||||
} else {
|
||||
if (_rxCharacteristic == null) {
|
||||
throw Exception("MeshCore RX characteristic not available");
|
||||
@@ -4484,14 +4480,13 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
_scanSubscription?.cancel();
|
||||
_connectionSubscription?.cancel();
|
||||
_usbFrameSubscription?.cancel();
|
||||
_tcpFrameSubscription?.cancel();
|
||||
_notifySubscription?.cancel();
|
||||
_notifyListenersTimer?.cancel();
|
||||
_reconnectTimer?.cancel();
|
||||
_batteryPollTimer?.cancel();
|
||||
_receivedFramesController.close();
|
||||
_usbManager.dispose();
|
||||
_tcpManager.dispose();
|
||||
_tcpConnector.dispose();
|
||||
|
||||
// Flush pending unread writes before disposal
|
||||
_unreadStore.flush();
|
||||
|
||||
@@ -1,34 +1,70 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import '../services/app_debug_log_service.dart';
|
||||
import '../services/tcp_transport_service.dart';
|
||||
|
||||
class MeshCoreTcpManager {
|
||||
/// Manages TCP transport for MeshCore devices.
|
||||
///
|
||||
/// Owns the [TcpTransportService] and TCP-specific connection state.
|
||||
/// The main [MeshCoreConnector] delegates all TCP operations here.
|
||||
class MeshCoreTcpConnector {
|
||||
final TcpTransportService _service = TcpTransportService();
|
||||
AppDebugLogService? _debugLog;
|
||||
StreamSubscription<Uint8List>? _frameSubscription;
|
||||
|
||||
// --- Getters ---
|
||||
String? get activeEndpoint => _service.activeEndpoint;
|
||||
bool get isConnected => _service.isConnected;
|
||||
Stream<Uint8List> get frameStream => _service.frameStream;
|
||||
|
||||
// --- Configuration ---
|
||||
void setDebugLogService(AppDebugLogService? service) {
|
||||
_debugLog = service;
|
||||
_service.setDebugLogService(service);
|
||||
}
|
||||
|
||||
// --- Connection lifecycle ---
|
||||
Future<void> connect({required String host, required int port}) async {
|
||||
_debugLog?.info('TcpManager.connect endpoint=$host:$port', tag: 'TCP');
|
||||
_debugLog?.info('TcpConnector.connect endpoint=$host:$port', tag: 'TCP');
|
||||
await _frameSubscription?.cancel();
|
||||
_frameSubscription = null;
|
||||
await _service.connect(host: host, port: port);
|
||||
_debugLog?.info(
|
||||
'TcpConnector.connect done, endpoint=${_service.activeEndpoint}',
|
||||
tag: 'TCP',
|
||||
);
|
||||
}
|
||||
|
||||
StreamSubscription<Uint8List> listenFrames({
|
||||
required void Function(Uint8List) onFrame,
|
||||
required void Function(Object, StackTrace?) onError,
|
||||
required void Function() onDone,
|
||||
}) {
|
||||
_frameSubscription = _service.frameStream.listen(
|
||||
onFrame,
|
||||
onError: onError,
|
||||
onDone: onDone,
|
||||
);
|
||||
return _frameSubscription!;
|
||||
}
|
||||
|
||||
Future<void> cancelFrameSubscription() async {
|
||||
await _frameSubscription?.cancel();
|
||||
_frameSubscription = null;
|
||||
}
|
||||
|
||||
Future<void> disconnect() async {
|
||||
_debugLog?.info('TcpManager.disconnect', tag: 'TCP');
|
||||
if (!_service.isConnected && _frameSubscription == null) return;
|
||||
_debugLog?.info('TcpConnector.disconnect', tag: 'TCP');
|
||||
await _frameSubscription?.cancel();
|
||||
_frameSubscription = null;
|
||||
await _service.disconnect();
|
||||
}
|
||||
|
||||
Future<void> write(Uint8List data) => _service.write(data);
|
||||
|
||||
void dispose() {
|
||||
_frameSubscription?.cancel();
|
||||
_service.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1881,7 +1881,6 @@
|
||||
"tcpPortLabel": "Пристанище",
|
||||
"tcpPortHint": "5000",
|
||||
"tcpStatus_notConnected": "Въведете крайната точка и свържете се.",
|
||||
"tcpStatus_connecting": "Свързване към TCP крайния пункт...",
|
||||
"tcpStatus_connectingTo": "Свързване към {endpoint}...",
|
||||
"tcpErrorHostRequired": "Необходим е IP адрес.",
|
||||
"tcpErrorPortInvalid": "Портът трябва да бъде между 1 и 65535.",
|
||||
|
||||
+1
-2
@@ -1906,10 +1906,9 @@
|
||||
"connectionChoiceTcpLabel": "TCP",
|
||||
"tcpHostHint": "192.168.40.10",
|
||||
"tcpScreenTitle": "Verbinden über TCP",
|
||||
"tcpPortLabel": "Hafen",
|
||||
"tcpPortLabel": "Port",
|
||||
"tcpPortHint": "5000",
|
||||
"tcpStatus_notConnected": "Geben Sie den Endpunkt ein und verbinden Sie sich.",
|
||||
"tcpStatus_connecting": "Verbindung zum TCP-Endpunkt hergestellt...",
|
||||
"tcpStatus_connectingTo": "Verbindung zu {endpoint}...",
|
||||
"tcpErrorHostRequired": "Eine IP-Adresse ist erforderlich.",
|
||||
"tcpErrorPortInvalid": "Die Portnummer muss zwischen 1 und 65535 liegen.",
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
"tcpPortLabel": "Port",
|
||||
"tcpPortHint": "5000",
|
||||
"tcpStatus_notConnected": "Enter endpoint and connect",
|
||||
"tcpStatus_connecting": "Connecting to TCP endpoint...",
|
||||
"tcpStatus_connectingTo": "Connecting to {endpoint}...",
|
||||
"@tcpStatus_connectingTo": {
|
||||
"placeholders": {
|
||||
|
||||
@@ -1909,7 +1909,6 @@
|
||||
"tcpPortLabel": "Puerto",
|
||||
"tcpPortHint": "5000",
|
||||
"tcpStatus_notConnected": "Ingrese la dirección final y conecte.",
|
||||
"tcpStatus_connecting": "Conectándose al punto final TCP...",
|
||||
"tcpStatus_connectingTo": "Conectándose a {endpoint}...",
|
||||
"tcpErrorHostRequired": "Se requiere la dirección IP.",
|
||||
"tcpErrorPortInvalid": "El puerto debe estar entre 1 y 65535.",
|
||||
|
||||
@@ -1881,7 +1881,6 @@
|
||||
"tcpPortLabel": "Port",
|
||||
"tcpPortHint": "5000",
|
||||
"tcpStatus_notConnected": "Entrez l'adresse de destination et connectez-vous.",
|
||||
"tcpStatus_connecting": "Connexion au point de terminaison TCP...",
|
||||
"tcpStatus_connectingTo": "Connexion à {endpoint}...",
|
||||
"tcpErrorHostRequired": "Une adresse IP est obligatoire.",
|
||||
"tcpErrorPortInvalid": "La taille du port doit être comprise entre 1 et 65535.",
|
||||
|
||||
+1
-2
@@ -1878,10 +1878,9 @@
|
||||
"tcpHostHint": "192.168.40.10",
|
||||
"connectionChoiceTcpLabel": "TCP",
|
||||
"tcpScreenTitle": "Stabilire una connessione tramite TCP",
|
||||
"tcpPortLabel": "Porto",
|
||||
"tcpPortLabel": "Porta",
|
||||
"tcpPortHint": "5000",
|
||||
"tcpStatus_notConnected": "Inserisci l'endpoint e connettiti.",
|
||||
"tcpStatus_connecting": "Connessione al punto finale TCP...",
|
||||
"tcpStatus_connectingTo": "Connessione a {endpoint}...",
|
||||
"tcpErrorHostRequired": "È necessario fornire un indirizzo IP.",
|
||||
"tcpErrorPortInvalid": "La dimensione della porta deve essere compresa tra 1 e 65535.",
|
||||
|
||||
@@ -376,12 +376,6 @@ abstract class AppLocalizations {
|
||||
/// **'Enter endpoint and connect'**
|
||||
String get tcpStatus_notConnected;
|
||||
|
||||
/// No description provided for @tcpStatus_connecting.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Connecting to TCP endpoint...'**
|
||||
String get tcpStatus_connecting;
|
||||
|
||||
/// No description provided for @tcpStatus_connectingTo.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
||||
@@ -138,9 +138,6 @@ class AppLocalizationsBg extends AppLocalizations {
|
||||
@override
|
||||
String get tcpStatus_notConnected => 'Въведете крайната точка и свържете се.';
|
||||
|
||||
@override
|
||||
String get tcpStatus_connecting => 'Свързване към TCP крайния пункт...';
|
||||
|
||||
@override
|
||||
String tcpStatus_connectingTo(String endpoint) {
|
||||
return 'Свързване към $endpoint...';
|
||||
|
||||
@@ -130,7 +130,7 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||
String get tcpHostHint => '192.168.40.10';
|
||||
|
||||
@override
|
||||
String get tcpPortLabel => 'Hafen';
|
||||
String get tcpPortLabel => 'Port';
|
||||
|
||||
@override
|
||||
String get tcpPortHint => '5000';
|
||||
@@ -139,10 +139,6 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||
String get tcpStatus_notConnected =>
|
||||
'Geben Sie den Endpunkt ein und verbinden Sie sich.';
|
||||
|
||||
@override
|
||||
String get tcpStatus_connecting =>
|
||||
'Verbindung zum TCP-Endpunkt hergestellt...';
|
||||
|
||||
@override
|
||||
String tcpStatus_connectingTo(String endpoint) {
|
||||
return 'Verbindung zu $endpoint...';
|
||||
|
||||
@@ -138,9 +138,6 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
@override
|
||||
String get tcpStatus_notConnected => 'Enter endpoint and connect';
|
||||
|
||||
@override
|
||||
String get tcpStatus_connecting => 'Connecting to TCP endpoint...';
|
||||
|
||||
@override
|
||||
String tcpStatus_connectingTo(String endpoint) {
|
||||
return 'Connecting to $endpoint...';
|
||||
|
||||
@@ -138,9 +138,6 @@ class AppLocalizationsEs extends AppLocalizations {
|
||||
@override
|
||||
String get tcpStatus_notConnected => 'Ingrese la dirección final y conecte.';
|
||||
|
||||
@override
|
||||
String get tcpStatus_connecting => 'Conectándose al punto final TCP...';
|
||||
|
||||
@override
|
||||
String tcpStatus_connectingTo(String endpoint) {
|
||||
return 'Conectándose a $endpoint...';
|
||||
|
||||
@@ -139,9 +139,6 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
String get tcpStatus_notConnected =>
|
||||
'Entrez l\'adresse de destination et connectez-vous.';
|
||||
|
||||
@override
|
||||
String get tcpStatus_connecting => 'Connexion au point de terminaison TCP...';
|
||||
|
||||
@override
|
||||
String tcpStatus_connectingTo(String endpoint) {
|
||||
return 'Connexion à $endpoint...';
|
||||
|
||||
@@ -130,7 +130,7 @@ class AppLocalizationsIt extends AppLocalizations {
|
||||
String get tcpHostHint => '192.168.40.10';
|
||||
|
||||
@override
|
||||
String get tcpPortLabel => 'Porto';
|
||||
String get tcpPortLabel => 'Porta';
|
||||
|
||||
@override
|
||||
String get tcpPortHint => '5000';
|
||||
@@ -138,9 +138,6 @@ class AppLocalizationsIt extends AppLocalizations {
|
||||
@override
|
||||
String get tcpStatus_notConnected => 'Inserisci l\'endpoint e connettiti.';
|
||||
|
||||
@override
|
||||
String get tcpStatus_connecting => 'Connessione al punto finale TCP...';
|
||||
|
||||
@override
|
||||
String tcpStatus_connectingTo(String endpoint) {
|
||||
return 'Connessione a $endpoint...';
|
||||
|
||||
@@ -130,7 +130,7 @@ class AppLocalizationsNl extends AppLocalizations {
|
||||
String get tcpHostHint => '192.168.40.10';
|
||||
|
||||
@override
|
||||
String get tcpPortLabel => 'Haven';
|
||||
String get tcpPortLabel => 'Poort';
|
||||
|
||||
@override
|
||||
String get tcpPortHint => '5000';
|
||||
@@ -138,9 +138,6 @@ class AppLocalizationsNl extends AppLocalizations {
|
||||
@override
|
||||
String get tcpStatus_notConnected => 'Voer het eindpunt in en verbind';
|
||||
|
||||
@override
|
||||
String get tcpStatus_connecting => 'Verbinding maken met TCP-eindpunt...';
|
||||
|
||||
@override
|
||||
String tcpStatus_connectingTo(String endpoint) {
|
||||
return 'Verbinding maken met $endpoint...';
|
||||
|
||||
@@ -138,9 +138,6 @@ class AppLocalizationsPl extends AppLocalizations {
|
||||
@override
|
||||
String get tcpStatus_notConnected => 'Wprowadź adres URL i połącz';
|
||||
|
||||
@override
|
||||
String get tcpStatus_connecting => 'Połączenie z punktem TCP...';
|
||||
|
||||
@override
|
||||
String tcpStatus_connectingTo(String endpoint) {
|
||||
return 'Połączenie z $endpoint...';
|
||||
|
||||
@@ -130,7 +130,7 @@ class AppLocalizationsPt extends AppLocalizations {
|
||||
String get tcpHostHint => '192.168.40.10';
|
||||
|
||||
@override
|
||||
String get tcpPortLabel => 'Porto';
|
||||
String get tcpPortLabel => 'Porta';
|
||||
|
||||
@override
|
||||
String get tcpPortHint => '5000';
|
||||
@@ -138,10 +138,6 @@ class AppLocalizationsPt extends AppLocalizations {
|
||||
@override
|
||||
String get tcpStatus_notConnected => 'Insira o endereço final e conecte-se.';
|
||||
|
||||
@override
|
||||
String get tcpStatus_connecting =>
|
||||
'Conectando ao ponto de extremidade TCP...';
|
||||
|
||||
@override
|
||||
String tcpStatus_connectingTo(String endpoint) {
|
||||
return 'Conectando a $endpoint...';
|
||||
|
||||
@@ -138,9 +138,6 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
@override
|
||||
String get tcpStatus_notConnected => 'Введите адрес и подключитесь.';
|
||||
|
||||
@override
|
||||
String get tcpStatus_connecting => 'Установление соединения с TCP-портом...';
|
||||
|
||||
@override
|
||||
String tcpStatus_connectingTo(String endpoint) {
|
||||
return 'Подключение к $endpoint...';
|
||||
|
||||
@@ -130,17 +130,14 @@ class AppLocalizationsSk extends AppLocalizations {
|
||||
String get tcpHostHint => '192.168.40.10';
|
||||
|
||||
@override
|
||||
String get tcpPortLabel => 'Pri항';
|
||||
String get tcpPortLabel => 'Port';
|
||||
|
||||
@override
|
||||
String get tcpPortHint => '5 000';
|
||||
String get tcpPortHint => '5000';
|
||||
|
||||
@override
|
||||
String get tcpStatus_notConnected => 'Zadajte cieľovú adresu a pripojte sa.';
|
||||
|
||||
@override
|
||||
String get tcpStatus_connecting => 'Pripojenie k TCP endpointu...';
|
||||
|
||||
@override
|
||||
String tcpStatus_connectingTo(String endpoint) {
|
||||
return 'Pripojenie k $endpoint...';
|
||||
|
||||
@@ -130,7 +130,7 @@ class AppLocalizationsSl extends AppLocalizations {
|
||||
String get tcpHostHint => '192.168.40.10';
|
||||
|
||||
@override
|
||||
String get tcpPortLabel => 'Pril';
|
||||
String get tcpPortLabel => 'Vrata';
|
||||
|
||||
@override
|
||||
String get tcpPortHint => '5000';
|
||||
@@ -138,9 +138,6 @@ class AppLocalizationsSl extends AppLocalizations {
|
||||
@override
|
||||
String get tcpStatus_notConnected => 'Vnesite končni naslov in se povežite';
|
||||
|
||||
@override
|
||||
String get tcpStatus_connecting => 'Povezava z TCP koncem...';
|
||||
|
||||
@override
|
||||
String tcpStatus_connectingTo(String endpoint) {
|
||||
return 'Povezava z $endpoint...';
|
||||
|
||||
@@ -130,7 +130,7 @@ class AppLocalizationsSv extends AppLocalizations {
|
||||
String get tcpHostHint => '192.168.40.10';
|
||||
|
||||
@override
|
||||
String get tcpPortLabel => 'Hamn';
|
||||
String get tcpPortLabel => 'Port';
|
||||
|
||||
@override
|
||||
String get tcpPortHint => '5000';
|
||||
@@ -138,9 +138,6 @@ class AppLocalizationsSv extends AppLocalizations {
|
||||
@override
|
||||
String get tcpStatus_notConnected => 'Ange slutpunkt och anslut';
|
||||
|
||||
@override
|
||||
String get tcpStatus_connecting => 'Anslutning till TCP-slutpunkt...';
|
||||
|
||||
@override
|
||||
String tcpStatus_connectingTo(String endpoint) {
|
||||
return 'Anslutning till $endpoint...';
|
||||
|
||||
@@ -138,9 +138,6 @@ class AppLocalizationsUk extends AppLocalizations {
|
||||
@override
|
||||
String get tcpStatus_notConnected => 'Введіть кінцеву точку та підключіться';
|
||||
|
||||
@override
|
||||
String get tcpStatus_connecting => 'Підключення до TCP-кінцевої точки...';
|
||||
|
||||
@override
|
||||
String tcpStatus_connectingTo(String endpoint) {
|
||||
return 'Підключення до $endpoint...';
|
||||
|
||||
@@ -130,7 +130,7 @@ class AppLocalizationsZh extends AppLocalizations {
|
||||
String get tcpHostHint => '192.168.40.10';
|
||||
|
||||
@override
|
||||
String get tcpPortLabel => '港';
|
||||
String get tcpPortLabel => '端口';
|
||||
|
||||
@override
|
||||
String get tcpPortHint => '5000';
|
||||
@@ -138,9 +138,6 @@ class AppLocalizationsZh extends AppLocalizations {
|
||||
@override
|
||||
String get tcpStatus_notConnected => '输入目标地址,然后连接';
|
||||
|
||||
@override
|
||||
String get tcpStatus_connecting => '连接到 TCP 终点...';
|
||||
|
||||
@override
|
||||
String tcpStatus_connectingTo(String endpoint) {
|
||||
return '连接到 $endpoint...';
|
||||
|
||||
+1
-2
@@ -1878,10 +1878,9 @@
|
||||
"tcpHostLabel": "IP-adres",
|
||||
"tcpHostHint": "192.168.40.10",
|
||||
"connectionChoiceTcpLabel": "TCP",
|
||||
"tcpPortLabel": "Haven",
|
||||
"tcpPortLabel": "Poort",
|
||||
"tcpPortHint": "5000",
|
||||
"tcpStatus_notConnected": "Voer het eindpunt in en verbind",
|
||||
"tcpStatus_connecting": "Verbinding maken met TCP-eindpunt...",
|
||||
"tcpStatus_connectingTo": "Verbinding maken met {endpoint}...",
|
||||
"tcpErrorHostRequired": "Een IP-adres is vereist.",
|
||||
"tcpErrorPortInvalid": "De poortwaarde moet tussen 1 en 65535 liggen.",
|
||||
|
||||
@@ -1881,7 +1881,6 @@
|
||||
"tcpPortLabel": "Port",
|
||||
"tcpPortHint": "5000",
|
||||
"tcpStatus_notConnected": "Wprowadź adres URL i połącz",
|
||||
"tcpStatus_connecting": "Połączenie z punktem TCP...",
|
||||
"tcpStatus_connectingTo": "Połączenie z {endpoint}...",
|
||||
"tcpErrorHostRequired": "Wymagana jest adresa IP.",
|
||||
"tcpErrorPortInvalid": "Numer portu musi mieścić się w zakresie od 1 do 65535.",
|
||||
|
||||
+1
-2
@@ -1878,10 +1878,9 @@
|
||||
"connectionChoiceTcpLabel": "TCP",
|
||||
"tcpScreenTitle": "Estabelecer conexão via TCP",
|
||||
"tcpHostHint": "192.168.40.10",
|
||||
"tcpPortLabel": "Porto",
|
||||
"tcpPortLabel": "Porta",
|
||||
"tcpPortHint": "5000",
|
||||
"tcpStatus_notConnected": "Insira o endereço final e conecte-se.",
|
||||
"tcpStatus_connecting": "Conectando ao ponto de extremidade TCP...",
|
||||
"tcpStatus_connectingTo": "Conectando a {endpoint}...",
|
||||
"tcpErrorHostRequired": "É necessário fornecer um endereço IP.",
|
||||
"tcpErrorPortInvalid": "O valor do porto deve estar entre 1 e 65535.",
|
||||
|
||||
@@ -1121,7 +1121,6 @@
|
||||
"tcpPortLabel": "Порт",
|
||||
"tcpPortHint": "5000",
|
||||
"tcpStatus_notConnected": "Введите адрес и подключитесь.",
|
||||
"tcpStatus_connecting": "Установление соединения с TCP-портом...",
|
||||
"tcpStatus_connectingTo": "Подключение к {endpoint}...",
|
||||
"tcpErrorHostRequired": "Необходимо указать IP-адрес.",
|
||||
"tcpErrorPortInvalid": "Порт должен находиться в диапазоне от 1 до 65535.",
|
||||
|
||||
+2
-3
@@ -1878,10 +1878,9 @@
|
||||
"tcpHostLabel": "IP adresa",
|
||||
"tcpScreenTitle": "Spojte sa pomocou protokolu TCP",
|
||||
"connectionChoiceTcpLabel": "TCP",
|
||||
"tcpPortLabel": "Pri항",
|
||||
"tcpPortHint": "5 000",
|
||||
"tcpPortLabel": "Port",
|
||||
"tcpPortHint": "5000",
|
||||
"tcpStatus_notConnected": "Zadajte cieľovú adresu a pripojte sa.",
|
||||
"tcpStatus_connecting": "Pripojenie k TCP endpointu...",
|
||||
"tcpStatus_connectingTo": "Pripojenie k {endpoint}...",
|
||||
"tcpErrorHostRequired": "Je potrebné zadať IP adresu.",
|
||||
"tcpErrorPortInvalid": "Číslo portu musí byť medzi 1 a 65535.",
|
||||
|
||||
+1
-2
@@ -1878,10 +1878,9 @@
|
||||
"tcpHostLabel": "IP naslov",
|
||||
"tcpHostHint": "192.168.40.10",
|
||||
"tcpScreenTitle": "Komunicirajte preko protokola TCP",
|
||||
"tcpPortLabel": "Pril",
|
||||
"tcpPortLabel": "Vrata",
|
||||
"tcpPortHint": "5000",
|
||||
"tcpStatus_notConnected": "Vnesite končni naslov in se povežite",
|
||||
"tcpStatus_connecting": "Povezava z TCP koncem...",
|
||||
"tcpStatus_connectingTo": "Povezava z {endpoint}...",
|
||||
"tcpErrorHostRequired": "Potrebna je IP-naslov.",
|
||||
"tcpErrorPortInvalid": "Port mora biti med 1 in 65535.",
|
||||
|
||||
+1
-2
@@ -1878,10 +1878,9 @@
|
||||
"tcpHostLabel": "IP-adress",
|
||||
"tcpScreenTitle": "Anslut via TCP",
|
||||
"connectionChoiceTcpLabel": "TCP",
|
||||
"tcpPortLabel": "Hamn",
|
||||
"tcpPortLabel": "Port",
|
||||
"tcpPortHint": "5000",
|
||||
"tcpStatus_notConnected": "Ange slutpunkt och anslut",
|
||||
"tcpStatus_connecting": "Anslutning till TCP-slutpunkt...",
|
||||
"tcpStatus_connectingTo": "Anslutning till {endpoint}...",
|
||||
"tcpErrorHostRequired": "IP-adress krävs.",
|
||||
"tcpErrorPortInvalid": "Porten måste vara mellan 1 och 65535.",
|
||||
|
||||
@@ -1881,7 +1881,6 @@
|
||||
"tcpPortLabel": "Порт",
|
||||
"tcpPortHint": "5000",
|
||||
"tcpStatus_notConnected": "Введіть кінцеву точку та підключіться",
|
||||
"tcpStatus_connecting": "Підключення до TCP-кінцевої точки...",
|
||||
"tcpStatus_connectingTo": "Підключення до {endpoint}...",
|
||||
"tcpErrorHostRequired": "Необхідно вказати IP-адресу.",
|
||||
"tcpErrorPortInvalid": "Порт повинен бути в межах від 1 до 65535.",
|
||||
|
||||
+1
-2
@@ -1883,10 +1883,9 @@
|
||||
"tcpHostHint": "192.168.40.10",
|
||||
"tcpScreenTitle": "通过 TCP 连接",
|
||||
"connectionChoiceTcpLabel": "TCP",
|
||||
"tcpPortLabel": "港",
|
||||
"tcpPortLabel": "端口",
|
||||
"tcpPortHint": "5000",
|
||||
"tcpStatus_notConnected": "输入目标地址,然后连接",
|
||||
"tcpStatus_connecting": "连接到 TCP 终点...",
|
||||
"tcpStatus_connectingTo": "连接到 {endpoint}...",
|
||||
"tcpErrorHostRequired": "需要提供IP地址。",
|
||||
"tcpErrorPortInvalid": "端口号必须在 1 到 65535 之间。",
|
||||
|
||||
@@ -27,7 +27,7 @@ class _TcpScreenState extends State<TcpScreen> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_hostController = TextEditingController(text: '192.168.40.10');
|
||||
_hostController = TextEditingController();
|
||||
_portController = TextEditingController(text: '5000');
|
||||
_connector = context.read<MeshCoreConnector>();
|
||||
|
||||
@@ -81,6 +81,9 @@ class _TcpScreenState extends State<TcpScreen> {
|
||||
final isConnecting =
|
||||
connector.state == MeshCoreConnectionState.connecting &&
|
||||
connector.activeTransport == MeshCoreTransportType.tcp;
|
||||
final isButtonDisabled =
|
||||
isConnecting ||
|
||||
connector.state == MeshCoreConnectionState.scanning;
|
||||
return Column(
|
||||
children: [
|
||||
_buildStatusBar(context, connector),
|
||||
@@ -112,7 +115,8 @@ class _TcpScreenState extends State<TcpScreen> {
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
FilledButton.icon(
|
||||
onPressed: isConnecting ? null : _connectTcp,
|
||||
key: const Key('tcp_connect_button'),
|
||||
onPressed: isButtonDisabled ? null : _connectTcp,
|
||||
icon: isConnecting
|
||||
? const SizedBox(
|
||||
width: 18,
|
||||
@@ -153,6 +157,7 @@ class _TcpScreenState extends State<TcpScreen> {
|
||||
);
|
||||
},
|
||||
heroTag: 'tcp_usb_action',
|
||||
extendedPadding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
icon: const Icon(Icons.usb),
|
||||
label: Text(context.l10n.connectionChoiceUsbLabel),
|
||||
),
|
||||
@@ -162,6 +167,7 @@ class _TcpScreenState extends State<TcpScreen> {
|
||||
Navigator.of(context).maybePop();
|
||||
},
|
||||
heroTag: 'tcp_ble_action',
|
||||
extendedPadding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
icon: const Icon(Icons.bluetooth),
|
||||
label: Text(context.l10n.connectionChoiceBluetoothLabel),
|
||||
),
|
||||
|
||||
@@ -93,7 +93,7 @@ void main() {
|
||||
final l10n = AppLocalizations.of(context);
|
||||
|
||||
await tester.enterText(find.byType(TextField).first, '');
|
||||
await tester.tap(find.widgetWithText(FilledButton, 'Connect'));
|
||||
await tester.tap(find.byKey(const Key('tcp_connect_button')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text(l10n.tcpErrorHostRequired), findsOneWidget);
|
||||
@@ -101,7 +101,7 @@ void main() {
|
||||
|
||||
await tester.enterText(find.byType(TextField).first, '192.168.1.50');
|
||||
await tester.enterText(find.byType(TextField).at(1), '99999');
|
||||
await tester.tap(find.widgetWithText(FilledButton, 'Connect'));
|
||||
await tester.tap(find.byKey(const Key('tcp_connect_button')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(connector.connectTcpCalls, 0);
|
||||
@@ -135,7 +135,7 @@ void main() {
|
||||
await tester.pump(const Duration(milliseconds: 60));
|
||||
});
|
||||
|
||||
testWidgets('TcpScreen allows connect while connector is scanning', (
|
||||
testWidgets('TcpScreen disables connect button while connector is scanning', (
|
||||
tester,
|
||||
) async {
|
||||
final connector = _FakeMeshCoreConnector()
|
||||
@@ -150,12 +150,11 @@ void main() {
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.widgetWithText(FilledButton, 'Connect'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(connector.connectTcpCalls, 1);
|
||||
expect(connector.lastHost, '192.168.40.10');
|
||||
expect(connector.lastPort, 5000);
|
||||
final button = tester.widget<ButtonStyleButton>(
|
||||
find.byKey(const Key('tcp_connect_button')),
|
||||
);
|
||||
expect(button.onPressed, isNull);
|
||||
expect(connector.connectTcpCalls, 0);
|
||||
});
|
||||
|
||||
testWidgets('TcpScreen narrow width long status text does not overflow', (
|
||||
|
||||
Reference in New Issue
Block a user