From 488f1a14b2e3b4027036ccda594cb3d18726f03c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= <49094811+leonboe1@users.noreply.github.com> Date: Sat, 16 May 2026 14:51:07 +0200 Subject: [PATCH] Only poll clipboard if clipboard sync was enabled --- NearbyShare/Util/TrustStore.swift | 7 ++ QuickDrop/Util/ClipboardSyncCoordinator.swift | 65 +++++++++++++++++-- 2 files changed, 65 insertions(+), 7 deletions(-) diff --git a/NearbyShare/Util/TrustStore.swift b/NearbyShare/Util/TrustStore.swift index 3f9f613..86cc967 100644 --- a/NearbyShare/Util/TrustStore.swift +++ b/NearbyShare/Util/TrustStore.swift @@ -11,6 +11,7 @@ import CryptoKit class TrustStore: ObservableObject { static let shared = TrustStore() + static let trustedCertificatesDidChange = Notification.Name("TrustStore.trustedCertificatesDidChange") @Published private(set) var trustedCertificates: [String: TrustedCertificate] = [:] @@ -58,10 +59,16 @@ class TrustStore: ObservableObject { do { try persistTrustedCertificates() AppGroup.appGroupUD.removeObject(forKey: trustedKeysKey) + notifyTrustedCertificatesDidChange() } catch { print("[TrustStore] Failed to save trusted certificates to keychain: \(error.localizedDescription)") } } + + + private func notifyTrustedCertificatesDidChange() { + NotificationCenter.default.post(name: Self.trustedCertificatesDidChange, object: self) + } // MARK: - Public API diff --git a/QuickDrop/Util/ClipboardSyncCoordinator.swift b/QuickDrop/Util/ClipboardSyncCoordinator.swift index 9c56472..b61373d 100644 --- a/QuickDrop/Util/ClipboardSyncCoordinator.swift +++ b/QuickDrop/Util/ClipboardSyncCoordinator.swift @@ -15,7 +15,9 @@ final class ClipboardSyncCoordinator { private let pollInterval: TimeInterval = 1 private let transferTimeout: TimeInterval = 75 + private var isStarted = false private var pollTimer: Timer? + private var trustStoreObserver: NSObjectProtocol? private var lastObservedChangeCount: Int private var suppressedClipboardText: String? private var startedOwnDiscovery = false @@ -27,6 +29,56 @@ final class ClipboardSyncCoordinator { } func start() { + guard !isStarted else { + refreshPollingState() + return + } + + isStarted = true + trustStoreObserver = NotificationCenter.default.addObserver( + forName: TrustStore.trustedCertificatesDidChange, + object: TrustStore.shared, + queue: .main + ) { [weak self] _ in + self?.refreshPollingState() + } + + refreshPollingState() + } + + func stop() { + guard isStarted || pollTimer != nil else { return } + + log("[ClipboardSyncCoordinator] Stopping clipboard watcher") + isStarted = false + if let trustStoreObserver { + NotificationCenter.default.removeObserver(trustStoreObserver) + self.trustStoreObserver = nil + } + stopPolling(clearTransfers: true) + } + + private func refreshPollingState() { + guard isStarted else { return } + + guard hasTrustedClipboardSyncDevice else { + if pollTimer != nil { + log("[ClipboardSyncCoordinator] Pausing clipboard watcher because no trusted clipboard sync device is saved") + } + stopPolling(clearTransfers: true) + return + } + + startPollingIfNeeded() + } + + private var hasTrustedClipboardSyncDevice: Bool { + TrustStore.shared.trustedCertificates.values.contains { + $0.grantedUseCases.contains(.clipboardSync) + } + } + + private func startPollingIfNeeded() { guard pollTimer == nil else { return } let manager = NearbyConnectionManager.shared @@ -42,16 +94,15 @@ final class ClipboardSyncCoordinator { } } - func stop() { - guard pollTimer != nil else { return } - - log("[ClipboardSyncCoordinator] Stopping clipboard watcher") + private func stopPolling(clearTransfers: Bool) { pollTimer?.invalidate() pollTimer = nil suppressedClipboardText = nil - activeTransfersByFingerprint.values.forEach { $0.cancelTimeout() } - activeTransfersByFingerprint.removeAll() - queuedTextByFingerprint.removeAll() + if clearTransfers { + activeTransfersByFingerprint.values.forEach { $0.cancelTimeout() } + activeTransfersByFingerprint.removeAll() + queuedTextByFingerprint.removeAll() + } guard startedOwnDiscovery else { return } startedOwnDiscovery = false