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