From a344d9a513e59c8758ee5d28c37f92c816099344 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= Date: Mon, 25 Aug 2025 10:57:32 +0200 Subject: [PATCH] iOS: Add WiFi disconnected hint --- .../Connection/NearbyConnectionManager.swift | 29 +++++++++++++++++++ .../xcschemes/QuickDropiOS.xcscheme | 1 + QuickDrop/AppDelegate.swift | 28 ++++++++---------- QuickDrop/Localizable.xcstrings | 11 +++++++ QuickDropiOS/ContentView.swift | 12 +++++--- 5 files changed, 61 insertions(+), 20 deletions(-) diff --git a/NearbyShare/Connection/NearbyConnectionManager.swift b/NearbyShare/Connection/NearbyConnectionManager.swift index bd2a21d..647ab2f 100644 --- a/NearbyShare/Connection/NearbyConnectionManager.swift +++ b/NearbyShare/Connection/NearbyConnectionManager.swift @@ -35,6 +35,8 @@ public class NearbyConnectionManager: NSObject, NetServiceDelegate, InboundNearb private var qrCodePrivateKey: ECPrivateKey? private var qrCodeAdvertisingToken: Data? private var qrCodeNameEncryptionKey: SymmetricKey? + private let hasConnectionMonitor = NWPathMonitor() + private let connectionMonitorQueue = DispatchQueue(label: "NetworkConnectionMonitorQueue") public let deviceInfo: EndpointInfo public let endpointID: [UInt8] = generateEndpointID() @@ -43,8 +45,16 @@ public class NearbyConnectionManager: NSObject, NetServiceDelegate, InboundNearb @Published var attachments: AttachmentDetails? = nil @Published var hasLocalNetworkAccess = true + @Published var isConnectedViaWiFi = true + + public var connectionUpdateCallback: (Bool) -> Void = { _ in } { + didSet { + connectionUpdateCallback(isConnectedViaWiFi) + } + } override init() { + #if os(macOS) self.deviceInfo = EndpointInfo(name: Host.current().localizedName ?? "Mac", deviceType: .computer) #else @@ -55,7 +65,26 @@ public class NearbyConnectionManager: NSObject, NetServiceDelegate, InboundNearb #endif tcpListener = try! NWListener(using: NWParameters(tls: .none)) + super.init() + + hasConnectionMonitor.pathUpdateHandler = { path in + if path.usesInterfaceType(.wifi) { + log("[NearbyConnectionManager] Connected via WiFi.") + DispatchQueue.main.async { + self.isConnectedViaWiFi = true + self.connectionUpdateCallback(true) + } + } else { + log("[NearbyConnectionManager] WiFi connection lost.") + DispatchQueue.main.async { + self.isConnectedViaWiFi = false + self.connectionUpdateCallback(false) + } + } + } + + hasConnectionMonitor.start(queue: connectionMonitorQueue) } diff --git a/QuickDrop.xcodeproj/xcshareddata/xcschemes/QuickDropiOS.xcscheme b/QuickDrop.xcodeproj/xcshareddata/xcschemes/QuickDropiOS.xcscheme index e493fbd..7f2fb73 100644 --- a/QuickDrop.xcodeproj/xcshareddata/xcschemes/QuickDropiOS.xcscheme +++ b/QuickDrop.xcodeproj/xcshareddata/xcschemes/QuickDropiOS.xcscheme @@ -34,6 +34,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + language = "en" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/QuickDrop/AppDelegate.swift b/QuickDrop/AppDelegate.swift index 00d2f31..824cc57 100644 --- a/QuickDrop/AppDelegate.swift +++ b/QuickDrop/AppDelegate.swift @@ -30,7 +30,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele var showsFirewallAlert = false var visibleItem: NSMenuItem? = nil - let hasConnectionMonitor = NWPathMonitor() // MARK: NSApplicationDelegate functions @@ -95,21 +94,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele UNUserNotificationCenter.current().delegate = self - hasConnectionMonitor.pathUpdateHandler = { path in - DispatchQueue.main.async { - if path.status == .satisfied { - self.statusItem?.button?.image = NSImage(named: "MenuBarIcon") - self.visibleItem?.title = "VisibleToEveryone".localized() - } else { - self.statusItem?.button?.image = NSImage(named: "MenuBarIconSlash") - self.visibleItem?.title = "NoNetworkConnection".localized() - } - } - } - - let queue2 = DispatchQueue(label: "NetworkConnectionMonitor") - hasConnectionMonitor.start(queue: queue2) - receiveModel = ReceiveModel(controlPlusScreen: { shouldOpen in if shouldOpen { self.openPlusScreen() @@ -123,6 +107,18 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele } }) + + NearbyConnectionManager.shared.connectionUpdateCallback = { isConnected in + if isConnected { + self.statusItem?.button?.image = NSImage(named: "MenuBarIcon") + self.visibleItem?.title = "VisibleToEveryone".localized() + } + else { + self.statusItem?.button?.image = NSImage(named: "MenuBarIconSlash") + self.visibleItem?.title = "NoNetworkConnection".localized() + } + } + log("Application did finish launching") } diff --git a/QuickDrop/Localizable.xcstrings b/QuickDrop/Localizable.xcstrings index 2881805..beaa2d5 100644 --- a/QuickDrop/Localizable.xcstrings +++ b/QuickDrop/Localizable.xcstrings @@ -6416,6 +6416,17 @@ } } }, + "NoWiFiConnectionDescription" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "To transfer files to other devices, please connect this device to a Wi-Fi network." + } + } + } + }, "OpenFinderAfterReceiving" : { "localizations" : { "ar" : { diff --git a/QuickDropiOS/ContentView.swift b/QuickDropiOS/ContentView.swift index 49c6842..9b35fbf 100644 --- a/QuickDropiOS/ContentView.swift +++ b/QuickDropiOS/ContentView.swift @@ -93,14 +93,18 @@ struct DeviceListView: View { CustomSection(header: "NoDevicesFound") { + let hasWifi = nearbyConnectionManager.isConnectedViaWiFi + HStack(spacing: 12) { - Image(systemName: "square.and.arrow.down") + Image(systemName: hasWifi ? "arrow.down.circle.fill" : "wifi.slash") .font(.system(size: 30)) - .foregroundColor(.gray) + .foregroundColor(.blue) .padding(.leading, -10) + .frame(width: 30) - Text("DownloadQuickDropOnPlayStore") + Text(hasWifi ? "DownloadQuickDropOnPlayStore" : "NoWiFiConnectionDescription") } + .animation(.default, value: hasWifi) .padding(.vertical) } @@ -133,7 +137,7 @@ struct DeviceListView: View { } - if nearbyConnectionManager.hasLocalNetworkAccess { + if nearbyConnectionManager.hasLocalNetworkAccess && nearbyConnectionManager.isConnectedViaWiFi { HStack(spacing: 8) { Text("SearchingForDevices") .font(.system(size: 14))