From 11afc232ab360e53ab8951dc459167207094eb65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6ttger?= Date: Tue, 9 Sep 2025 11:08:13 +0200 Subject: [PATCH] Refactoring UserDefaults --- .../Connection/InboundNearbyConnection.swift | 2 +- .../Connection/NearbyConnectionManager.swift | 8 +- NearbyShare/Util/Helpers.swift | 21 +---- NearbyShare/Util/SaveFilesManager.swift | 4 +- QuickDrop.xcodeproj/project.pbxproj | 76 ++++++++++++------ QuickDrop/AppDelegate.swift | 10 +-- QuickDrop/Plus/PlusView.swift | 8 +- QuickDrop/Settings.swift | 79 +++++++++++++++++++ QuickDrop/Util/ErrorAlertHandler.swift | 2 +- QuickDrop/View/SettingsView.swift | 16 ++-- QuickDrop/View/TutorialView.swift | 8 +- QuickDropiOS/ReceiveModel.swift | 4 +- 12 files changed, 159 insertions(+), 79 deletions(-) create mode 100644 QuickDrop/Settings.swift diff --git a/NearbyShare/Connection/InboundNearbyConnection.swift b/NearbyShare/Connection/InboundNearbyConnection.swift index b5b493b..6a4ae5a 100644 --- a/NearbyShare/Connection/InboundNearbyConnection.swift +++ b/NearbyShare/Connection/InboundNearbyConnection.swift @@ -524,7 +524,7 @@ class InboundNearbyConnection: NearbyConnection { func checkIfCanProceed(metadata: TransferMetadata) { - let acceptAutomatically = isAuthenticated || UserDefaults.standard.bool(forKey: UserDefaultsKeys.automaticallyAcceptFiles.rawValue) + let acceptAutomatically = isAuthenticated || Settings.shared.automaticallyAcceptFiles DispatchQueue.main.async { self.delegate?.obtainUserConsent(transfer: metadata, device: self.remoteDeviceInfo!, connection: self, acceptAutomatically: acceptAutomatically) diff --git a/NearbyShare/Connection/NearbyConnectionManager.swift b/NearbyShare/Connection/NearbyConnectionManager.swift index 81a3e42..107eee0 100644 --- a/NearbyShare/Connection/NearbyConnectionManager.swift +++ b/NearbyShare/Connection/NearbyConnectionManager.swift @@ -135,12 +135,10 @@ public class NearbyConnectionManager: NSObject, NetServiceDelegate, InboundNearb private static func generateEndpointID() -> [UInt8] { - let userDefaultsKey = UserDefaultsKeys.endpointID.rawValue // Try to retrieve from UserDefaults - if let savedString = UserDefaults.standard.string(forKey: userDefaultsKey), - let savedData = savedString.data(using: .utf8) - { + if let savedString = Settings.shared.endpointID, + let savedData = savedString.data(using: .utf8) { return [UInt8](savedData) } @@ -153,7 +151,7 @@ public class NearbyConnectionManager: NSObject, NetServiceDelegate, InboundNearb // Save to UserDefaults as String let idString = String(bytes: id, encoding: .utf8) ?? "" - UserDefaults.standard.set(idString, forKey: userDefaultsKey) + Settings.shared.endpointID = idString return id } diff --git a/NearbyShare/Util/Helpers.swift b/NearbyShare/Util/Helpers.swift index 6a84270..cf03be9 100644 --- a/NearbyShare/Util/Helpers.swift +++ b/NearbyShare/Util/Helpers.swift @@ -110,23 +110,11 @@ extension String { } -public enum UserDefaultsKeys: String, CaseIterable { - case isEligibleForIap = "isEligibleForIap" - case appLaunchedBefore = "ShowedWelcomeScreen" - case plusVersion = "isPlusVersion" - case transmissionCount = "reviewRequestCountKey" - case automaticallyAcceptFiles = "automaticallyAcceptFiles" - case saveFolderBookmark = "saveFolderBookmark" - case openFinderAfterReceiving = "openFinderAfterReceiving" - case endpointID = "endpointID" -} - - public func isPlusVersion() -> Bool { #if os(macOS) // Enable full functionality if app distributed directly - return DistributionDetector.isDirectDistributionEnabled || UserDefaults.standard.bool(forKey: UserDefaultsKeys.plusVersion.rawValue) + return DistributionDetector.isDirectDistributionEnabled || Settings.shared.isPlusVersion #else // iOS return true @@ -135,10 +123,5 @@ public func isPlusVersion() -> Bool { public func isFileTransferRestricted() -> Bool { - (!isPlusVersion() && incomingTransmissionCount() > 1) -} - - -public func incomingTransmissionCount() -> Int { - return UserDefaults.standard.integer(forKey: UserDefaultsKeys.transmissionCount.rawValue) + (!isPlusVersion() && Settings.shared.incomingTransmissionCount > 1) } diff --git a/NearbyShare/Util/SaveFilesManager.swift b/NearbyShare/Util/SaveFilesManager.swift index 80336be..e51ce44 100644 --- a/NearbyShare/Util/SaveFilesManager.swift +++ b/NearbyShare/Util/SaveFilesManager.swift @@ -119,7 +119,7 @@ public class SaveFilesManager { if !filesFinishedDownloadingSinceLastRun.isEmpty && !isFileTransferRestricted() { #if os(macOS) - if UserDefaults.standard.bool(forKey: UserDefaultsKeys.openFinderAfterReceiving.rawValue) { + if Settings.shared.openFinderAfterReceiving { log("[SaveFilesManager] Opening \(filesFinishedDownloadingSinceLastRun.count) file(s) in Finder.") NSWorkspace.shared.activateFileViewerSelecting(filesFinishedDownloadingSinceLastRun) } @@ -171,7 +171,7 @@ public class SaveFilesManager { return securityScopeUrl } - if let bookmarkData = UserDefaults.standard.data(forKey: UserDefaultsKeys.saveFolderBookmark.rawValue) { + if let bookmarkData = Settings.shared.saveFolderBookmark { var isStale = false do { diff --git a/QuickDrop.xcodeproj/project.pbxproj b/QuickDrop.xcodeproj/project.pbxproj index 668d9b5..37961cf 100644 --- a/QuickDrop.xcodeproj/project.pbxproj +++ b/QuickDrop.xcodeproj/project.pbxproj @@ -17,6 +17,22 @@ EB05DFBE2E59FC8900EF567A /* TrustedDevicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB05DFBD2E59FC8000EF567A /* TrustedDevicesView.swift */; }; EB05DFBF2E59FD0A00EF567A /* TrustedDevicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB05DFBD2E59FC8000EF567A /* TrustedDevicesView.swift */; }; EB05DFC02E5A2EAA00EF567A /* TrustedDevicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB05DFBD2E59FC8000EF567A /* TrustedDevicesView.swift */; }; + EB1325D32E701D8E00FD749C /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325D22E701D8900FD749C /* Settings.swift */; }; + EB1325D42E701D8E00FD749C /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325D22E701D8900FD749C /* Settings.swift */; }; + EB1325D52E701D8E00FD749C /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325D22E701D8900FD749C /* Settings.swift */; }; + EB1325D62E701D8E00FD749C /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325D22E701D8900FD749C /* Settings.swift */; }; + EB1325EB2E7025D900FD749C /* ApIsolationTester.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325E92E7025D900FD749C /* ApIsolationTester.swift */; }; + EB1325EC2E7025D900FD749C /* ActiveNetworkInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325E72E7025D900FD749C /* ActiveNetworkInterface.swift */; }; + EB1325ED2E7025D900FD749C /* ApIsolation6Tester.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325E82E7025D900FD749C /* ApIsolation6Tester.swift */; }; + EB1325EE2E7025D900FD749C /* ApIsolationTester.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325E92E7025D900FD749C /* ApIsolationTester.swift */; }; + EB1325EF2E7025D900FD749C /* ActiveNetworkInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325E72E7025D900FD749C /* ActiveNetworkInterface.swift */; }; + EB1325F02E7025D900FD749C /* ApIsolation6Tester.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325E82E7025D900FD749C /* ApIsolation6Tester.swift */; }; + EB1325F12E7025D900FD749C /* ApIsolationTester.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325E92E7025D900FD749C /* ApIsolationTester.swift */; }; + EB1325F22E7025D900FD749C /* ActiveNetworkInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325E72E7025D900FD749C /* ActiveNetworkInterface.swift */; }; + EB1325F32E7025D900FD749C /* ApIsolation6Tester.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325E82E7025D900FD749C /* ApIsolation6Tester.swift */; }; + EB1325F42E7025D900FD749C /* ApIsolationTester.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325E92E7025D900FD749C /* ApIsolationTester.swift */; }; + EB1325F52E7025D900FD749C /* ActiveNetworkInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325E72E7025D900FD749C /* ActiveNetworkInterface.swift */; }; + EB1325F62E7025D900FD749C /* ApIsolation6Tester.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325E82E7025D900FD749C /* ApIsolation6Tester.swift */; }; EB16B6122E58B4B9007D9792 /* IdentityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB16B6112E58B4B9007D9792 /* IdentityManager.swift */; }; EB16B6132E58B4B9007D9792 /* IdentityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB16B6112E58B4B9007D9792 /* IdentityManager.swift */; }; EB16B6142E58B4B9007D9792 /* IdentityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB16B6112E58B4B9007D9792 /* IdentityManager.swift */; }; @@ -188,11 +204,6 @@ EBC05C712E33B57D00EECC18 /* Converter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C6D2E33B57D00EECC18 /* Converter.swift */; }; EBC05C722E33B57D00EECC18 /* Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C6E2E33B57D00EECC18 /* Helper.swift */; }; EBC05C732E33B57D00EECC18 /* PlusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C6F2E33B57D00EECC18 /* PlusView.swift */; }; - EBC05C782E33B58100EECC18 /* ActiveNetworkInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C742E33B58100EECC18 /* ActiveNetworkInterface.swift */; }; - EBC05C792E33B58100EECC18 /* ApIsolation6Tester.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C752E33B58100EECC18 /* ApIsolation6Tester.swift */; }; - EBC05C7A2E33B58100EECC18 /* ApIsolationTester.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C762E33B58100EECC18 /* ApIsolationTester.swift */; }; - EBC05C7B2E33B58100EECC18 /* ActiveNetworkInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C742E33B58100EECC18 /* ActiveNetworkInterface.swift */; }; - EBC05C7C2E33B58100EECC18 /* ApIsolationTester.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C762E33B58100EECC18 /* ApIsolationTester.swift */; }; EBC05C822E33B58300EECC18 /* ApIsolationIssueView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C7D2E33B58300EECC18 /* ApIsolationIssueView.swift */; }; EBC05C832E33B58300EECC18 /* FirewallIssueView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C7E2E33B58300EECC18 /* FirewallIssueView.swift */; }; EBC05C842E33B58300EECC18 /* IssueView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C7F2E33B58300EECC18 /* IssueView.swift */; }; @@ -303,6 +314,10 @@ 69DA9A2C29E18CB500A442DA /* securegcm.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = securegcm.pb.swift; sourceTree = ""; }; 69DA9A2D29E18CB500A442DA /* securemessage.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = securemessage.pb.swift; sourceTree = ""; }; EB05DFBD2E59FC8000EF567A /* TrustedDevicesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrustedDevicesView.swift; sourceTree = ""; }; + EB1325D22E701D8900FD749C /* Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = ""; }; + EB1325E72E7025D900FD749C /* ActiveNetworkInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActiveNetworkInterface.swift; sourceTree = ""; }; + EB1325E82E7025D900FD749C /* ApIsolation6Tester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApIsolation6Tester.swift; sourceTree = ""; }; + EB1325E92E7025D900FD749C /* ApIsolationTester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApIsolationTester.swift; sourceTree = ""; }; EB16B6112E58B4B9007D9792 /* IdentityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityManager.swift; sourceTree = ""; }; EB16B6162E58B4C8007D9792 /* TrustStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrustStore.swift; sourceTree = ""; }; EB16B7762E59BA9F007D9792 /* AppGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppGroup.swift; sourceTree = ""; }; @@ -364,9 +379,6 @@ EBC05C6D2E33B57D00EECC18 /* Converter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Converter.swift; sourceTree = ""; }; EBC05C6E2E33B57D00EECC18 /* Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Helper.swift; sourceTree = ""; }; EBC05C6F2E33B57D00EECC18 /* PlusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlusView.swift; sourceTree = ""; }; - EBC05C742E33B58100EECC18 /* ActiveNetworkInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActiveNetworkInterface.swift; sourceTree = ""; }; - EBC05C752E33B58100EECC18 /* ApIsolation6Tester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApIsolation6Tester.swift; sourceTree = ""; }; - EBC05C762E33B58100EECC18 /* ApIsolationTester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApIsolationTester.swift; sourceTree = ""; }; EBC05C7D2E33B58300EECC18 /* ApIsolationIssueView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApIsolationIssueView.swift; sourceTree = ""; }; EBC05C7E2E33B58300EECC18 /* FirewallIssueView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirewallIssueView.swift; sourceTree = ""; }; EBC05C7F2E33B58300EECC18 /* IssueView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueView.swift; sourceTree = ""; }; @@ -476,8 +488,9 @@ isa = PBXGroup; children = ( 69DA9A1129E0BF5100A442DA /* AppDelegate.swift */, + EB1325D22E701D8900FD749C /* Settings.swift */, + EB1325EA2E7025D900FD749C /* SelfTest */, EBC05C6A2E33B55100EECC18 /* View */, - EBC05C772E33B58100EECC18 /* SelfTest */, EBC05C6B2E33B57100EECC18 /* Util */, EBC05C702E33B57D00EECC18 /* Plus */, 69DA9A1329E0BF5200A442DA /* Assets.xcassets */, @@ -511,6 +524,16 @@ path = NearbyShare; sourceTree = ""; }; + EB1325EA2E7025D900FD749C /* SelfTest */ = { + isa = PBXGroup; + children = ( + EB1325E72E7025D900FD749C /* ActiveNetworkInterface.swift */, + EB1325E82E7025D900FD749C /* ApIsolation6Tester.swift */, + EB1325E92E7025D900FD749C /* ApIsolationTester.swift */, + ); + path = SelfTest; + sourceTree = ""; + }; EB5C371C2E3669010052EFD7 /* Util */ = { isa = PBXGroup; children = ( @@ -623,16 +646,6 @@ path = Plus; sourceTree = ""; }; - EBC05C772E33B58100EECC18 /* SelfTest */ = { - isa = PBXGroup; - children = ( - EBC05C742E33B58100EECC18 /* ActiveNetworkInterface.swift */, - EBC05C752E33B58100EECC18 /* ApIsolation6Tester.swift */, - EBC05C762E33B58100EECC18 /* ApIsolationTester.swift */, - ); - path = SelfTest; - sourceTree = ""; - }; EBC05C812E33B58300EECC18 /* IssueViews */ = { isa = PBXGroup; children = ( @@ -901,13 +914,12 @@ EB5C37C82E377A780052EFD7 /* ukey.pb.swift in Sources */, EB5C37C92E377A780052EFD7 /* device_to_device_messages.pb.swift in Sources */, EB950B742E520957002D68FA /* Attachments.swift in Sources */, + EB1325D32E701D8E00FD749C /* Settings.swift in Sources */, EB16B7782E59BAA1007D9792 /* AppGroup.swift in Sources */, EB5C383C2E38C2D90052EFD7 /* AudioManager.swift in Sources */, EB5C37CA2E377A780052EFD7 /* offline_wire_formats.pb.swift in Sources */, EB16B6122E58B4B9007D9792 /* IdentityManager.swift in Sources */, EBC05C5C2E3394EF00EECC18 /* ErrorAlertHandler.swift in Sources */, - EBC05C7B2E33B58100EECC18 /* ActiveNetworkInterface.swift in Sources */, - EBC05C7C2E33B58100EECC18 /* ApIsolationTester.swift in Sources */, 691F53BB2ABB70840089FD92 /* DeviceListCell.swift in Sources */, EB5C383F2E38C49D0052EFD7 /* LaunchAtLogin.swift in Sources */, EB5C37BC2E377A700052EFD7 /* SleepManager.swift in Sources */, @@ -918,6 +930,9 @@ EB5C37D32E377A7F0052EFD7 /* InboundNearbyConnection.swift in Sources */, EB5C37D42E377A7F0052EFD7 /* NearbyConnectionManager.swift in Sources */, EB5C37BD2E377A700052EFD7 /* Helpers.swift in Sources */, + EB1325EB2E7025D900FD749C /* ApIsolationTester.swift in Sources */, + EB1325EC2E7025D900FD749C /* ActiveNetworkInterface.swift in Sources */, + EB1325ED2E7025D900FD749C /* ApIsolation6Tester.swift in Sources */, EB5C37BE2E377A700052EFD7 /* SaveFilesManager.swift in Sources */, EB9925822E45D53E00357055 /* sharing_enums.pb.swift in Sources */, ); @@ -936,6 +951,7 @@ EB05DFBE2E59FC8900EF567A /* TrustedDevicesView.swift in Sources */, EB16B6182E58B4C8007D9792 /* TrustStore.swift in Sources */, EBC05C5B2E33937200EECC18 /* ErrorAlertHandler.swift in Sources */, + EB1325D42E701D8E00FD749C /* Settings.swift in Sources */, EBC05C712E33B57D00EECC18 /* Converter.swift in Sources */, EB886E5D2E4F13EB0052B7D9 /* Zip.swift in Sources */, EBC05C722E33B57D00EECC18 /* Helper.swift in Sources */, @@ -948,15 +964,12 @@ EB16B6152E58B4B9007D9792 /* IdentityManager.swift in Sources */, EB5C37C42E377A780052EFD7 /* securegcm.pb.swift in Sources */, EB97A0102E51CD13008B8C5C /* ReceiveModel.swift in Sources */, - EBC05C782E33B58100EECC18 /* ActiveNetworkInterface.swift in Sources */, EB5C37CB2E377A7F0052EFD7 /* NearbyConnection.swift in Sources */, EB5C37CC2E377A7F0052EFD7 /* DataModel.swift in Sources */, EB5C37CD2E377A7F0052EFD7 /* OutboundNearbyConnection.swift in Sources */, EB5C37CE2E377A7F0052EFD7 /* InboundNearbyConnection.swift in Sources */, EB5C37CF2E377A7F0052EFD7 /* NearbyConnectionManager.swift in Sources */, - EBC05C792E33B58100EECC18 /* ApIsolation6Tester.swift in Sources */, EB7654A12E53252D006B4AA3 /* AttachmentDetails.swift in Sources */, - EBC05C7A2E33B58100EECC18 /* ApIsolationTester.swift in Sources */, EB886E522E4E19390052B7D9 /* HKDF.swift in Sources */, EB96ED8C2D7F7E7B004B3FF1 /* SmallSheetView.swift in Sources */, EB886E682E4F2F800052B7D9 /* License.swift in Sources */, @@ -971,6 +984,9 @@ EB16B77A2E59BAA1007D9792 /* AppGroup.swift in Sources */, EBC05C822E33B58300EECC18 /* ApIsolationIssueView.swift in Sources */, EBC05C832E33B58300EECC18 /* FirewallIssueView.swift in Sources */, + EB1325F42E7025D900FD749C /* ApIsolationTester.swift in Sources */, + EB1325F52E7025D900FD749C /* ActiveNetworkInterface.swift in Sources */, + EB1325F62E7025D900FD749C /* ApIsolation6Tester.swift in Sources */, EBC05C842E33B58300EECC18 /* IssueView.swift in Sources */, EBC05C852E33B58300EECC18 /* NetworkFilterIssueView.swift in Sources */, ); @@ -998,6 +1014,7 @@ EB5C37FB2E377CE70052EFD7 /* InboundNearbyConnection.swift in Sources */, EB9925802E45D53E00357055 /* sharing_enums.pb.swift in Sources */, EB5C37FC2E377CE70052EFD7 /* OutboundNearbyConnection.swift in Sources */, + EB1325D62E701D8E00FD749C /* Settings.swift in Sources */, EB5C37FD2E377CE70052EFD7 /* Logger.swift in Sources */, EB97A00F2E511124008B8C5C /* ReceiveModel.swift in Sources */, EB5C37FE2E377CE70052EFD7 /* offline_wire_formats.pb.swift in Sources */, @@ -1015,6 +1032,9 @@ EB16B7792E59BAA1007D9792 /* AppGroup.swift in Sources */, EB5C38402E38C49D0052EFD7 /* LaunchAtLogin.swift in Sources */, EB5C37FF2E377CE70052EFD7 /* wire_format.pb.swift in Sources */, + EB1325EE2E7025D900FD749C /* ApIsolationTester.swift in Sources */, + EB1325EF2E7025D900FD749C /* ActiveNetworkInterface.swift in Sources */, + EB1325F02E7025D900FD749C /* ApIsolation6Tester.swift in Sources */, EB950B792E521717002D68FA /* AttachmentDetails.swift in Sources */, EB5C38002E377CE70052EFD7 /* DataModel.swift in Sources */, ); @@ -1030,6 +1050,9 @@ EB950B472E520436002D68FA /* sharing_enums.pb.swift in Sources */, EB950B482E520436002D68FA /* Localized.swift in Sources */, EB950B492E520436002D68FA /* device_to_device_messages.pb.swift in Sources */, + EB1325F12E7025D900FD749C /* ApIsolationTester.swift in Sources */, + EB1325F22E7025D900FD749C /* ActiveNetworkInterface.swift in Sources */, + EB1325F32E7025D900FD749C /* ApIsolation6Tester.swift in Sources */, EB950B4A2E520436002D68FA /* securegcm.pb.swift in Sources */, EB950B4B2E520436002D68FA /* offline_wire_formats.pb.swift in Sources */, EB950B4C2E520436002D68FA /* InboundNearbyConnection.swift in Sources */, @@ -1044,6 +1067,7 @@ EB05DFC02E5A2EAA00EF567A /* TrustedDevicesView.swift in Sources */, EB950B542E520436002D68FA /* HKDF.swift in Sources */, EB950B552E520436002D68FA /* SaveFilesManager.swift in Sources */, + EB1325D52E701D8E00FD749C /* Settings.swift in Sources */, EB950B562E520436002D68FA /* DataModel.swift in Sources */, EB950B3E2E52038A002D68FA /* SendModel.swift in Sources */, EB950B772E521712002D68FA /* AttachmentDetails.swift in Sources */, @@ -1241,7 +1265,7 @@ MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; - SHARED_BUILD = 68; + SHARED_BUILD = 69; SHARED_VERSION = 2.2.1; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_EMIT_LOC_STRINGS = YES; @@ -1303,7 +1327,7 @@ MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = macosx; - SHARED_BUILD = 68; + SHARED_BUILD = 69; SHARED_VERSION = 2.2.1; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_EMIT_LOC_STRINGS = YES; diff --git a/QuickDrop/AppDelegate.swift b/QuickDrop/AppDelegate.swift index 4631162..0f419bc 100644 --- a/QuickDrop/AppDelegate.swift +++ b/QuickDrop/AppDelegate.swift @@ -70,21 +70,21 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele log("[AppDelegate] Downloaded directly: \(DistributionDetector.isDirectDistributionEnabled)") // app did not lauch before - if !UserDefaults.standard.bool(forKey: UserDefaultsKeys.appLaunchedBefore.rawValue) { + if !Settings.shared.appLaunchedBefore { log("[AppDelegate] Opening Welcome Screen") // open welcome screen openWelcomeScreen() - UserDefaults.standard.set(true, forKey: UserDefaultsKeys.appLaunchedBefore.rawValue) + Settings.shared.appLaunchedBefore = true // user installed the app after the IAP was implemented, set the user as eligible for IAP - UserDefaults.standard.set(true, forKey: UserDefaultsKeys.isEligibleForIap.rawValue) + Settings.shared.isEligibleForIap = true } else { // app launched before // user installed the app before the IAP was implemented, grant the plus version - if !UserDefaults.standard.bool(forKey: UserDefaultsKeys.isEligibleForIap.rawValue) { + if !Settings.shared.isEligibleForIap { log("[AppDelegate] Granting QuickDrop+ for old user") - UserDefaults.standard.set(true, forKey: UserDefaultsKeys.plusVersion.rawValue) + Settings.shared.isPlusVersion = true } else { if !isPlusVersion() { log("[AppDelegate] New user - QuickDrop+ not available") diff --git a/QuickDrop/Plus/PlusView.swift b/QuickDrop/Plus/PlusView.swift index 41e674b..81acbed 100644 --- a/QuickDrop/Plus/PlusView.swift +++ b/QuickDrop/Plus/PlusView.swift @@ -13,7 +13,7 @@ let plusViewHeight: CGFloat = 200 struct PlusView: View { - @AppStorage(UserDefaultsKeys.plusVersion.rawValue) var isPlusVersion = false + @ObservedObject private var settings = Settings.shared @ObservedObject private var iaphelper = IAPManager.sharedInstance let closeView: () -> Void @@ -115,7 +115,7 @@ struct PlusView: View { if success { log("[LUI] Restored purchases successfully") withAnimation { - isPlusVersion = true + settings.isPlusVersion = true } boughtSuccessAlert = true } else { @@ -146,7 +146,7 @@ struct PlusView: View { if success { withAnimation { - isPlusVersion = true + settings.isPlusVersion = true } boughtSuccessAlert = true @@ -193,7 +193,7 @@ struct PlusView: View { case .success(_): withAnimation { - isPlusVersion = true + settings.isPlusVersion = true boughtSuccessAlert = true warning = false } diff --git a/QuickDrop/Settings.swift b/QuickDrop/Settings.swift new file mode 100644 index 0000000..91683bf --- /dev/null +++ b/QuickDrop/Settings.swift @@ -0,0 +1,79 @@ +// +// Settings.swift +// QuickDrop +// +// Created by Leon Böttger on 09.09.25. +// + +import SwiftUI + +class Settings: ObservableObject { + + private init() {} + + static var shared = Settings() + + + // MARK: - Published UserDefaults Backed Properties + + @Published var isPlusVersion = UserDefaults.standard.bool(forKey: UserDefaultsKeys.plusVersion.rawValue) + { didSet { UserDefaults.standard.set(isPlusVersion, forKey: UserDefaultsKeys.plusVersion.rawValue) }} + + + @Published var automaticallyAcceptFiles: Bool = UserDefaults.standard.bool(forKey: UserDefaultsKeys.automaticallyAcceptFiles.rawValue) + { didSet { UserDefaults.standard.set(automaticallyAcceptFiles, forKey: UserDefaultsKeys.automaticallyAcceptFiles.rawValue) }} + + + @Published var openFinderAfterReceiving: Bool = UserDefaults.standard.bool(forKey: UserDefaultsKeys.openFinderAfterReceiving.rawValue) + { didSet { UserDefaults.standard.set(openFinderAfterReceiving, forKey: UserDefaultsKeys.openFinderAfterReceiving.rawValue) }} + + + @Published var saveFolderBookmark: Data? = UserDefaults.standard.data(forKey: UserDefaultsKeys.saveFolderBookmark.rawValue) + { didSet { UserDefaults.standard.set(saveFolderBookmark, forKey: UserDefaultsKeys.saveFolderBookmark.rawValue) }} + + + + // MARK: - Non-Published UserDefaults Backed Properties + + var incomingTransmissionCount: Int = UserDefaults.standard.integer(forKey: UserDefaultsKeys.transmissionCount.rawValue) + { didSet { UserDefaults.standard.set(incomingTransmissionCount, forKey: UserDefaultsKeys.transmissionCount.rawValue) }} + + + var endpointID: String? = UserDefaults.standard.string(forKey: UserDefaultsKeys.endpointID.rawValue) + { didSet { UserDefaults.standard.set(endpointID, forKey: UserDefaultsKeys.endpointID.rawValue) }} + + + var isEligibleForIap: Bool = UserDefaults.standard.bool(forKey: UserDefaultsKeys.isEligibleForIap.rawValue) + { didSet { UserDefaults.standard.set(isEligibleForIap, forKey: UserDefaultsKeys.isEligibleForIap.rawValue) }} + + + var appLaunchedBefore: Bool = UserDefaults.standard.bool(forKey: UserDefaultsKeys.appLaunchedBefore.rawValue) + { didSet { UserDefaults.standard.set(appLaunchedBefore, forKey: UserDefaultsKeys.appLaunchedBefore.rawValue) }} + + + + // MARK: - Debug + + func deleteAllUserDefaults() { + for key in UserDefaultsKeys.allCases { + UserDefaults.standard.removeObject(forKey: key.rawValue) + } + + Settings.shared = Settings() + } + + + + // MARK: - UserDefaults Keys + + public enum UserDefaultsKeys: String, CaseIterable { + case isEligibleForIap = "isEligibleForIap" + case appLaunchedBefore = "ShowedWelcomeScreen" + case plusVersion = "isPlusVersion" + case transmissionCount = "reviewRequestCountKey" + case automaticallyAcceptFiles = "automaticallyAcceptFiles" + case saveFolderBookmark = "saveFolderBookmark" + case openFinderAfterReceiving = "openFinderAfterReceiving" + case endpointID = "endpointID" + } +} diff --git a/QuickDrop/Util/ErrorAlertHandler.swift b/QuickDrop/Util/ErrorAlertHandler.swift index 3166c4a..0991370 100644 --- a/QuickDrop/Util/ErrorAlertHandler.swift +++ b/QuickDrop/Util/ErrorAlertHandler.swift @@ -84,7 +84,7 @@ class ErrorAlertHandler { let title = String(format: "TransferError".localized(), arguments: [deviceName]) log("Showing alert with title: \"\(title)\" and description: \"\(description)\"") - log("Unsuccessful transmission. Already successful transmissions: \(incomingTransmissionCount())") + log("Unsuccessful transmission. Already successful transmissions: \(Settings.shared.incomingTransmissionCount)") #if os(macOS) diff --git a/QuickDrop/View/SettingsView.swift b/QuickDrop/View/SettingsView.swift index a7b0fc9..f69c556 100644 --- a/QuickDrop/View/SettingsView.swift +++ b/QuickDrop/View/SettingsView.swift @@ -10,15 +10,13 @@ import AppKit struct SettingsView: View { - @AppStorage(UserDefaultsKeys.automaticallyAcceptFiles.rawValue) private var automaticallyAcceptFiles = false - @AppStorage(UserDefaultsKeys.openFinderAfterReceiving.rawValue) private var openFinderAfterReceiving = false - @AppStorage(UserDefaultsKeys.saveFolderBookmark.rawValue) private var saveFolderPath: Data = Data() + @ObservedObject var settings = Settings.shared var body: some View { LargeAppIconView(title: "Settings") { Form { - Toggle("AutomaticallyAcceptFiles", isOn: $automaticallyAcceptFiles) + Toggle("AutomaticallyAcceptFiles", isOn: $settings.automaticallyAcceptFiles) .padding(.top, 10) Text("AutomaticallyAcceptFilesFooter") @@ -33,7 +31,7 @@ struct SettingsView: View { Text("SaveFilesTo") Spacer() Text(getSavedFolderPath() ?? "DownloadsFolder".localized()) - .foregroundColor(saveFolderPath.isEmpty ? .gray : .primary) + .foregroundColor((settings.saveFolderBookmark ?? Data()).isEmpty ? .gray : .primary) Button("SaveFilesToButton") { selectFolder() } @@ -42,7 +40,7 @@ struct SettingsView: View { Divider() .padding(.vertical, 10) - Toggle("OpenFinderAfterReceiving", isOn: $openFinderAfterReceiving) + Toggle("OpenFinderAfterReceiving", isOn: $settings.openFinderAfterReceiving) .padding(.top, 5) if #available(macOS 13.0, *) { @@ -72,10 +70,10 @@ struct SettingsView: View { private func getSavedFolderPath() -> String? { - if !saveFolderPath.isEmpty { + if let bookmark = settings.saveFolderBookmark, !bookmark.isEmpty { var isStale = false do { - let url = try URL(resolvingBookmarkData: saveFolderPath, options: [], relativeTo: nil, bookmarkDataIsStale: &isStale) + let url = try URL(resolvingBookmarkData: bookmark, options: [], relativeTo: nil, bookmarkDataIsStale: &isStale) return url.lastPathComponent // Returns the folder path as a string } catch { log("Failed to resolve bookmark: \(error)") @@ -98,7 +96,7 @@ struct SettingsView: View { let bookmarkData = try url.bookmarkData(options: .withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: nil) - UserDefaults.standard.set(bookmarkData, forKey: UserDefaultsKeys.saveFolderBookmark.rawValue) + Settings.shared.saveFolderBookmark = bookmarkData } catch { log("Failed to save security-scoped bookmark: \(error)") } diff --git a/QuickDrop/View/TutorialView.swift b/QuickDrop/View/TutorialView.swift index 5c728d0..87dff6b 100644 --- a/QuickDrop/View/TutorialView.swift +++ b/QuickDrop/View/TutorialView.swift @@ -15,7 +15,7 @@ struct TutorialView: View { let openPlus: () -> Void @State private var licenseWindow: NSWindow? - @AppStorage(UserDefaultsKeys.plusVersion.rawValue) var isPlusVersion = false + @ObservedObject var settings = Settings.shared var body: some View { @@ -40,7 +40,7 @@ struct TutorialView: View { } .buttonStyle(.plain) - if !isPlusVersion { + if !settings.isPlusVersion { Button { openPlus() } label: { @@ -54,9 +54,7 @@ struct TutorialView: View { #if DEBUG Button { - for key in UserDefaultsKeys.allCases { - UserDefaults.standard.removeObject(forKey: key.rawValue) - } + Settings.shared.deleteAllUserDefaults() } label: { Text("Reset UD") .underline() diff --git a/QuickDropiOS/ReceiveModel.swift b/QuickDropiOS/ReceiveModel.swift index 70cfb39..d48dc9a 100644 --- a/QuickDropiOS/ReceiveModel.swift +++ b/QuickDropiOS/ReceiveModel.swift @@ -174,7 +174,7 @@ class ReceiveModel: ObservableObject, InboundAppDelegate { showCopiedToClipboardAlert() } - let currentCount = incomingTransmissionCount() + let currentCount = Settings.shared.incomingTransmissionCount #if os(macOS) if currentCount == 0 { @@ -184,7 +184,7 @@ class ReceiveModel: ObservableObject, InboundAppDelegate { } #endif - UserDefaults.standard.set(currentCount + 1, forKey: UserDefaultsKeys.transmissionCount.rawValue) + Settings.shared.incomingTransmissionCount = currentCount + 1 log("[ReceiveModel] Successful transmission. Current count: \(currentCount)") } }