From 1f5e5967edb4146b10f077dd7d38e73385b2ebfd Mon Sep 17 00:00:00 2001
From: Matthias Nott <mnott@mnsoft.org>
Date: Wed, 01 Apr 2026 18:29:13 +0200
Subject: [PATCH] feat: show connection method (Local/VPN/Remote/Discovered) in app bar and settings
---
lib/screens/settings_screen.dart | 21 ++++++++++++++++++---
lib/providers/providers.dart | 1 +
lib/services/mqtt_service.dart | 21 +++++++++++++++++++--
lib/screens/chat_screen.dart | 8 ++++++++
4 files changed, 46 insertions(+), 5 deletions(-)
diff --git a/lib/providers/providers.dart b/lib/providers/providers.dart
index fdfe4ae..6393124 100644
--- a/lib/providers/providers.dart
+++ b/lib/providers/providers.dart
@@ -62,6 +62,7 @@
StateProvider<ConnectionStatus>((ref) => ConnectionStatus.disconnected);
final connectionDetailProvider = StateProvider<String>((ref) => '');
+final connectedViaProvider = StateProvider<String>((ref) => '');
// --- Sessions ---
diff --git a/lib/screens/chat_screen.dart b/lib/screens/chat_screen.dart
index 7d8503a..f51862a 100644
--- a/lib/screens/chat_screen.dart
+++ b/lib/screens/chat_screen.dart
@@ -196,6 +196,9 @@
ref.read(wsStatusProvider.notifier).state = status;
if (status == ConnectionStatus.connected) {
ref.read(connectionDetailProvider.notifier).state = '';
+ ref.read(connectedViaProvider.notifier).state = _ws?.connectedVia ?? '';
+ } else {
+ ref.read(connectedViaProvider.notifier).state = '';
}
}
};
@@ -1417,6 +1420,11 @@
connectionDetail,
style: TextStyle(fontSize: 11, color: Colors.grey.shade400),
),
+ if (wsStatus == ConnectionStatus.connected && ref.watch(connectedViaProvider).isNotEmpty)
+ Text(
+ 'via ${ref.watch(connectedViaProvider)}',
+ style: TextStyle(fontSize: 11, color: Colors.grey.shade500),
+ ),
],
),
actions: [
diff --git a/lib/screens/settings_screen.dart b/lib/screens/settings_screen.dart
index c0d9580..840db79 100644
--- a/lib/screens/settings_screen.dart
+++ b/lib/screens/settings_screen.dart
@@ -138,9 +138,24 @@
children: [
StatusDot(status: wsStatus),
const SizedBox(width: 12),
- Text(
- _statusText(wsStatus),
- style: Theme.of(context).textTheme.bodyLarge,
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ _statusText(wsStatus),
+ style: Theme.of(context).textTheme.bodyLarge,
+ ),
+ if (ref.watch(connectedViaProvider).isNotEmpty)
+ Text(
+ 'via ${ref.watch(connectedViaProvider)}',
+ style: TextStyle(
+ fontSize: 12,
+ color: Colors.grey.shade500,
+ ),
+ ),
+ ],
+ ),
),
],
),
diff --git a/lib/services/mqtt_service.dart b/lib/services/mqtt_service.dart
index a872fd7..e50adcf 100644
--- a/lib/services/mqtt_service.dart
+++ b/lib/services/mqtt_service.dart
@@ -60,6 +60,8 @@
// Callbacks
void Function(ConnectionStatus status)? onStatusChanged;
void Function(String detail)? onStatusDetail; // "Probing local...", "Scanning network..."
+ String? connectedHost; // The host we're currently connected to
+ String? connectedVia; // "Local", "VPN", "Remote", "Bonjour", "Scan"
void Function(Map<String, dynamic> message)? onMessage;
void Function()? onOpen;
void Function()? onClose;
@@ -158,12 +160,27 @@
}
if (winner != null && !_intentionalClose) {
- _mqttLog('MQTT: winner: $winner, connecting...');
- onStatusDetail?.call('Connecting to $winner...');
+ // Determine connection method label
+ if (winner == config.localHost) {
+ connectedVia = 'Local';
+ } else if (winner == config.vpnHost) {
+ connectedVia = 'VPN';
+ } else if (winner == config.host) {
+ connectedVia = 'Remote';
+ } else if (winner == _lastDiscoveredHost) {
+ connectedVia = 'Discovered';
+ } else {
+ connectedVia = winner;
+ }
+ connectedHost = winner;
+ _mqttLog('MQTT: winner: $winner ($connectedVia), connecting...');
+ onStatusDetail?.call('Connecting via $connectedVia...');
try {
if (await _tryConnect(winner, clientId, timeout: 5000)) return;
} catch (e) {
_mqttLog('MQTT: connect to $winner failed: $e');
+ connectedHost = null;
+ connectedVia = null;
}
}
--
Gitblit v1.3.1