mirror of
https://github.com/zjs81/meshcore-open.git
synced 2026-06-19 00:45:33 +10:00
Refactor USB port handling to introduce display labels and improve state management
This commit is contained in:
committed by
just-stuff-tm
parent
a0feb129e1
commit
5216e00807
@@ -115,7 +115,8 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
final UsbSerialService _usbSerialService = UsbSerialService();
|
||||
StreamSubscription<Uint8List>? _usbFrameSubscription;
|
||||
MeshCoreTransportType _activeTransport = MeshCoreTransportType.bluetooth;
|
||||
String? _activeUsbPort;
|
||||
String? _activeUsbPortKey;
|
||||
String? _activeUsbPortLabel;
|
||||
|
||||
final List<ScanResult> _scanResults = [];
|
||||
final List<Contact> _contacts = [];
|
||||
@@ -229,7 +230,9 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
String get deviceIdLabel => _deviceId ?? 'Unknown';
|
||||
|
||||
MeshCoreTransportType get activeTransport => _activeTransport;
|
||||
String? get activeUsbPort => _activeUsbPort;
|
||||
String? get activeUsbPort => _activeUsbPortKey;
|
||||
String? get activeUsbPortDisplayLabel =>
|
||||
_activeUsbPortLabel ?? _activeUsbPortKey;
|
||||
bool get isUsbTransportConnected =>
|
||||
_state == MeshCoreConnectionState.connected &&
|
||||
_activeTransport == MeshCoreTransportType.usb;
|
||||
@@ -778,7 +781,8 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
}
|
||||
|
||||
_activeTransport = MeshCoreTransportType.bluetooth;
|
||||
_activeUsbPort = null;
|
||||
_activeUsbPortKey = null;
|
||||
_activeUsbPortLabel = null;
|
||||
|
||||
await stopScan();
|
||||
_setState(MeshCoreConnectionState.connecting);
|
||||
@@ -955,14 +959,16 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
}
|
||||
|
||||
_activeTransport = MeshCoreTransportType.bluetooth;
|
||||
_activeUsbPort = null;
|
||||
_activeUsbPortKey = null;
|
||||
_activeUsbPortLabel = null;
|
||||
|
||||
await stopScan();
|
||||
_cancelReconnectTimer();
|
||||
_manualDisconnect = false;
|
||||
_resetConnectionHandshakeState();
|
||||
_activeTransport = MeshCoreTransportType.usb;
|
||||
_activeUsbPort = portName;
|
||||
_activeUsbPortKey = portName;
|
||||
_activeUsbPortLabel = portName;
|
||||
unawaited(_backgroundService?.start());
|
||||
_setState(MeshCoreConnectionState.connecting);
|
||||
|
||||
@@ -1178,7 +1184,8 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
_reactionSendQueueSequence = 0;
|
||||
|
||||
_activeTransport = MeshCoreTransportType.bluetooth;
|
||||
_activeUsbPort = null;
|
||||
_activeUsbPortKey = null;
|
||||
_activeUsbPortLabel = null;
|
||||
|
||||
_setState(MeshCoreConnectionState.disconnected);
|
||||
if (!manual && transportAtDisconnect == MeshCoreTransportType.bluetooth) {
|
||||
@@ -2218,7 +2225,8 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
selfName != null &&
|
||||
selfName.isNotEmpty) {
|
||||
_usbSerialService.updateConnectedLabel(selfName);
|
||||
_activeUsbPort = _usbSerialService.activePortName ?? _activeUsbPort;
|
||||
_activeUsbPortLabel =
|
||||
_usbSerialService.activePortDisplayLabel ?? _activeUsbPortLabel;
|
||||
}
|
||||
_awaitingSelfInfo = false;
|
||||
_selfInfoRetryTimer?.cancel();
|
||||
|
||||
+18
-14
@@ -23,6 +23,7 @@ class _UsbScreenState extends State<UsbScreen> {
|
||||
bool _navigatedToContacts = false;
|
||||
bool _didScheduleInitialLoad = false;
|
||||
String? _selectedPort;
|
||||
String? _connectedPortDisplayLabel;
|
||||
String? _errorText;
|
||||
late final MeshCoreConnector _connector;
|
||||
late final VoidCallback _connectionListener;
|
||||
@@ -33,21 +34,19 @@ class _UsbScreenState extends State<UsbScreen> {
|
||||
_connector = context.read<MeshCoreConnector>();
|
||||
_connectionListener = () {
|
||||
if (!mounted) return;
|
||||
final activeUsbPort = _connector.activeUsbPort;
|
||||
if (activeUsbPort != null &&
|
||||
activeUsbPort.isNotEmpty &&
|
||||
activeUsbPort != _selectedPort) {
|
||||
setState(() {
|
||||
_selectedPort = activeUsbPort;
|
||||
});
|
||||
}
|
||||
final activeUsbPortDisplayLabel = _connector.activeUsbPortDisplayLabel;
|
||||
final shouldUpdateDisplayLabel =
|
||||
activeUsbPortDisplayLabel != _connectedPortDisplayLabel;
|
||||
if (_connector.state == MeshCoreConnectionState.disconnected) {
|
||||
_navigatedToContacts = false;
|
||||
if (_isConnecting) {
|
||||
setState(() {
|
||||
_isConnecting = false;
|
||||
});
|
||||
}
|
||||
setState(() {
|
||||
_isConnecting = false;
|
||||
_connectedPortDisplayLabel = activeUsbPortDisplayLabel;
|
||||
});
|
||||
} else if (shouldUpdateDisplayLabel) {
|
||||
setState(() {
|
||||
_connectedPortDisplayLabel = activeUsbPortDisplayLabel;
|
||||
});
|
||||
}
|
||||
if (_connector.state == MeshCoreConnectionState.connected &&
|
||||
_connector.isUsbTransportConnected &&
|
||||
@@ -167,7 +166,12 @@ class _UsbScreenState extends State<UsbScreen> {
|
||||
fit: BoxFit.scaleDown,
|
||||
child: Chip(
|
||||
label: Text(
|
||||
_selectedPort == null
|
||||
_connectedPortDisplayLabel != null &&
|
||||
_connectedPortDisplayLabel!.isNotEmpty
|
||||
? _friendlyPortName(
|
||||
_connectedPortDisplayLabel!,
|
||||
)
|
||||
: _selectedPort == null
|
||||
? l10n.usbScreenStatus
|
||||
: _friendlyPortName(_selectedPort!),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
|
||||
@@ -26,11 +26,14 @@ class UsbSerialService {
|
||||
StreamSubscription<dynamic>? _androidDataSubscription;
|
||||
StreamSubscription<FlSerialEventArgs>? _dataSubscription;
|
||||
UsbSerialStatus _status = UsbSerialStatus.disconnected;
|
||||
String? _connectedPortName;
|
||||
String? _connectedPortKey;
|
||||
String? _connectedPortLabel;
|
||||
FlSerial? _serial;
|
||||
|
||||
UsbSerialStatus get status => _status;
|
||||
String? get activePortName => _connectedPortName;
|
||||
String? get activePortKey => _connectedPortKey;
|
||||
String? get activePortDisplayLabel =>
|
||||
_connectedPortLabel ?? _connectedPortKey;
|
||||
Stream<Uint8List> get frameStream => _frameController.stream;
|
||||
bool get _useAndroidUsbHost =>
|
||||
!kIsWeb && defaultTargetPlatform == TargetPlatform.android;
|
||||
@@ -126,7 +129,8 @@ class UsbSerialService {
|
||||
}
|
||||
}
|
||||
|
||||
_connectedPortName = normalizedPortName;
|
||||
_connectedPortKey = normalizedPortName;
|
||||
_connectedPortLabel = normalizedPortName;
|
||||
if (_useAndroidUsbHost) {
|
||||
_androidDataSubscription = _androidEventChannel
|
||||
.receiveBroadcastStream()
|
||||
@@ -168,7 +172,8 @@ class UsbSerialService {
|
||||
if (_status == UsbSerialStatus.disconnected) return;
|
||||
|
||||
_status = UsbSerialStatus.disconnecting;
|
||||
_connectedPortName = null;
|
||||
_connectedPortKey = null;
|
||||
_connectedPortLabel = null;
|
||||
await _androidDataSubscription?.cancel();
|
||||
_androidDataSubscription = null;
|
||||
await _dataSubscription?.cancel();
|
||||
@@ -204,7 +209,10 @@ class UsbSerialService {
|
||||
if (trimmed.isEmpty) {
|
||||
return;
|
||||
}
|
||||
_connectedPortName = trimmed;
|
||||
_connectedPortLabel = buildUsbDisplayLabel(
|
||||
basePortLabel: _connectedPortKey ?? trimmed,
|
||||
deviceName: trimmed,
|
||||
);
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
|
||||
@@ -29,7 +29,8 @@ class UsbSerialService {
|
||||
String _requestPortLabel = 'Choose USB Device';
|
||||
|
||||
UsbSerialStatus get status => _status;
|
||||
String? get activePortName => _connectedPortName;
|
||||
String? get activePortKey => _connectedPortKey;
|
||||
String? get activePortDisplayLabel => _connectedPortName ?? _connectedPortKey;
|
||||
Stream<Uint8List> get frameStream => _frameController.stream;
|
||||
bool get isConnected => _status == UsbSerialStatus.connected;
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ class _FakeMeshCoreConnector extends MeshCoreConnector {
|
||||
int connectUsbCalls = 0;
|
||||
String? lastConnectPortName;
|
||||
String? fakeActiveUsbPort;
|
||||
String? fakeActiveUsbPortDisplayLabel;
|
||||
bool fakeUsbTransportConnected = false;
|
||||
|
||||
@override
|
||||
@@ -29,6 +30,10 @@ class _FakeMeshCoreConnector extends MeshCoreConnector {
|
||||
@override
|
||||
String? get activeUsbPort => fakeActiveUsbPort;
|
||||
|
||||
@override
|
||||
String? get activeUsbPortDisplayLabel =>
|
||||
fakeActiveUsbPortDisplayLabel ?? fakeActiveUsbPort;
|
||||
|
||||
@override
|
||||
bool get isUsbTransportConnected => fakeUsbTransportConnected;
|
||||
|
||||
@@ -99,6 +104,33 @@ void main() {
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
'UsbScreen keeps raw selection while showing connector USB display label',
|
||||
(tester) async {
|
||||
final connector = _FakeMeshCoreConnector(
|
||||
ports: <String>['COM6 - USB Serial Device (COM6)'],
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
_buildTestApp(connector: connector, child: const UsbScreen()),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
connector.fakeActiveUsbPortDisplayLabel =
|
||||
'COM6 - KD3CGK mesh-utility.org';
|
||||
connector.notifyListeners();
|
||||
await tester.pump();
|
||||
|
||||
expect(find.text('KD3CGK mesh-utility.org'), findsOneWidget);
|
||||
|
||||
await tester.tap(find.widgetWithText(FilledButton, 'Connect'));
|
||||
await tester.pump();
|
||||
|
||||
expect(connector.connectUsbCalls, 1);
|
||||
expect(connector.lastConnectPortName, 'COM6');
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets('ConnectionChoiceScreen USB button reflects platform support', (
|
||||
tester,
|
||||
) async {
|
||||
|
||||
Reference in New Issue
Block a user