diff --git a/README.md b/README.md index fc3f1588..3c065780 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ Git migration to iTorrent 2.0 in progress +iTorrent 2.0 app is it beta preview state, expect to see some bugs and be ready report about them. + [![AltStore Button]][AltStore Link] [![SideStore Button]][SideStore Link] [![Jailbreak Button]][Jailbreak Link] diff --git a/Submodules/LibTorrent-Swift b/Submodules/LibTorrent-Swift index cdc34f10..eceff8ae 160000 --- a/Submodules/LibTorrent-Swift +++ b/Submodules/LibTorrent-Swift @@ -1 +1 @@ -Subproject commit cdc34f1083187eb533073d30b6b8d7784a28f1b6 +Subproject commit eceff8aeaff158b4581726b22b19b8fba87f9f78 diff --git a/Submodules/MVVMFoundation b/Submodules/MVVMFoundation index 74194bf1..1b0b1654 160000 --- a/Submodules/MVVMFoundation +++ b/Submodules/MVVMFoundation @@ -1 +1 @@ -Subproject commit 74194bf191ee89482dd086fbd3a78167fc82c22d +Subproject commit 1b0b1654515aa9cb090670b972892abe9f6f4e42 diff --git a/iTorrent.xcodeproj/project.pbxproj b/iTorrent.xcodeproj/project.pbxproj index 27dc0c49..cc977d4f 100644 --- a/iTorrent.xcodeproj/project.pbxproj +++ b/iTorrent.xcodeproj/project.pbxproj @@ -25,6 +25,8 @@ 7C4ED0942BE961A20034B62C /* UIModernBarButtonItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C4ED0932BE961A20034B62C /* UIModernBarButtonItem.swift */; }; 7C4ED0962BE961DF0034B62C /* BaseControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C4ED0952BE961DF0034B62C /* BaseControl.swift */; }; 7C4ED0982BEF8B8E0034B62C /* PatreonCredentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C4ED0972BEF8B8E0034B62C /* PatreonCredentials.swift */; }; + 7C519C882C427E9A00E353A9 /* FirebaseAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = 7C519C872C427E9A00E353A9 /* FirebaseAnalytics */; }; + 7C519C8C2C427F4C00E353A9 /* FirebaseRemoteConfigSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 7C519C8B2C427F4C00E353A9 /* FirebaseRemoteConfigSwift */; }; 7C5FBE0F2BBB227D0069E5A0 /* UISegmentedProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5FBE0E2BBB227D0069E5A0 /* UISegmentedProgressView.swift */; }; 7C5FBE122BBB63C80069E5A0 /* MarqueeLabel in Frameworks */ = {isa = PBXBuildFile; productRef = 7C5FBE112BBB63C80069E5A0 /* MarqueeLabel */; }; 7C5FBE192BBC91E70069E5A0 /* NetworkMonitoringService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5FBE182BBC91E70069E5A0 /* NetworkMonitoringService.swift */; }; @@ -63,9 +65,6 @@ 7CBDBAAD2C31EF0C008C986B /* UserDefaults+AppGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CBDBAAC2C31EF0C008C986B /* UserDefaults+AppGroup.swift */; }; 7CBDBAAE2C31EF52008C986B /* UserDefaults+AppGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CBDBAAC2C31EF0C008C986B /* UserDefaults+AppGroup.swift */; }; 7CC411582BD2DCF800CA8B13 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7CC411572BD2DCF800CA8B13 /* GoogleService-Info.plist */; }; - 7CC4115B2BD2DE3800CA8B13 /* FirebaseAnalyticsWithoutAdIdSupport in Frameworks */ = {isa = PBXBuildFile; platformFilters = (ios, xros, ); productRef = 7CC4115A2BD2DE3800CA8B13 /* FirebaseAnalyticsWithoutAdIdSupport */; }; - 7CC4115D2BD2DE3800CA8B13 /* FirebaseCrashlytics in Frameworks */ = {isa = PBXBuildFile; platformFilters = (ios, xros, ); productRef = 7CC4115C2BD2DE3800CA8B13 /* FirebaseCrashlytics */; }; - 7CC411602BD2FE8700CA8B13 /* FirebaseRemoteConfigSwift in Frameworks */ = {isa = PBXBuildFile; platformFilters = (ios, xros, ); productRef = 7CC4115F2BD2FE8700CA8B13 /* FirebaseRemoteConfigSwift */; }; 7CC411622BD319AE00CA8B13 /* AppDelegate+RemoteConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CC411612BD319AE00CA8B13 /* AppDelegate+RemoteConfig.swift */; }; 7CC411642BD326C300CA8B13 /* AppDelegate+Firebase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CC411632BD326C300CA8B13 /* AppDelegate+Firebase.swift */; }; 7CE25BA72C24A848007B2FD7 /* CircularAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CE25BA62C24A848007B2FD7 /* CircularAnimation.swift */; }; @@ -468,12 +467,11 @@ 7CF6DA332C0F112B0033D03F /* OpenSSL in Frameworks */, 7C4ED08B2BE642A50034B62C /* AppTrackingTransparency.framework in Frameworks */, 7C5FBE122BBB63C80069E5A0 /* MarqueeLabel in Frameworks */, - 7CC411602BD2FE8700CA8B13 /* FirebaseRemoteConfigSwift in Frameworks */, + 7C519C882C427E9A00E353A9 /* FirebaseAnalytics in Frameworks */, 7CF9C2C72AF7F235009BBFA0 /* MvvmFoundation in Frameworks */, D1DB71832BD80318007F9267 /* GCDWebServers in Frameworks */, + 7C519C8C2C427F4C00E353A9 /* FirebaseRemoteConfigSwift in Frameworks */, D135C58C2AEF158000440680 /* CombineCocoa in Frameworks */, - 7CC4115D2BD2DE3800CA8B13 /* FirebaseCrashlytics in Frameworks */, - 7CC4115B2BD2DE3800CA8B13 /* FirebaseAnalyticsWithoutAdIdSupport in Frameworks */, D1ACFDDA2AF7D55F0098FF56 /* MvvmFoundation in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -528,6 +526,13 @@ path = AdView; sourceTree = ""; }; + 7C519C8D2C4282F000E353A9 /* Foundation */ = { + isa = PBXGroup; + children = ( + ); + path = Foundation; + sourceTree = ""; + }; 7C5FBE0D2BBB206B0069E5A0 /* Views */ = { isa = PBXGroup; children = ( @@ -555,6 +560,7 @@ 7C5FBE2F2BBF5C990069E5A0 /* SwiftUI */ = { isa = PBXGroup; children = ( + D1D1279A2BC7CA7600C04533 /* SwiftUILayoutGuides.swift */, D17871FE2AF2C0A700F11F9F /* UIKitSwiftUIInarop.swift */, 7C5FBE302BBF5CAB0069E5A0 /* MinHeightModifier.swift */, 7CF6DA342C0F3DB90033D03F /* BCHostingConfiguration.swift */, @@ -600,6 +606,7 @@ 7C5FBE722BC2F0940069E5A0 /* MvvmFoundation */ = { isa = PBXGroup; children = ( + D1F8BC842AFC405A00A6258C /* MvvmViewModel+Alert.swift */, 7C5FBE732BC2F0A30069E5A0 /* MvvmViewModelProtocol+Alert.swift */, ); path = MvvmFoundation; @@ -616,7 +623,10 @@ 7C95B7B52C385B8E000EC50F /* UIKit */ = { isa = PBXGroup; children = ( + D173D9DF2BC0285800E4F9EB /* UIMenu */, 7C95B7B62C385B97000EC50F /* UICellAccessory+Image.swift */, + 7C5FBE2B2BBDD6B40069E5A0 /* UIView+LayerColors.swift */, + D1352D2D2BBD6ED300104E7B /* UIColor+Hex.swift */, ); path = UIKit; sourceTree = ""; @@ -1024,21 +1034,17 @@ D19E00242AF045DF000A17A2 /* Extensions */ = { isa = PBXGroup; children = ( + 7C519C8D2C4282F000E353A9 /* Foundation */, 7C95B7B52C385B8E000EC50F /* UIKit */, 7C5FBE722BC2F0940069E5A0 /* MvvmFoundation */, - D173D9DF2BC0285800E4F9EB /* UIMenu */, 7C5FBE2F2BBF5C990069E5A0 /* SwiftUI */, D173D9DA2BBEED1E00E4F9EB /* Codable */, D1048D872BBEA23C0027EF2F /* Combine */, D1352D282BBD418200104E7B /* UIViewController */, - D1D1279A2BC7CA7600C04533 /* SwiftUILayoutGuides.swift */, D1FFC9642C38135F00233C2F /* URL+Extensions.swift */, D19E00252AF045F9000A17A2 /* SpeedFormat.swift */, D1ACFDC82AF6ED200098FF56 /* UIImage+File.swift */, D1AA00D12AFAC95500B74629 /* String+Localized.swift */, - D1F8BC842AFC405A00A6258C /* MvvmViewModel+Alert.swift */, - D1352D2D2BBD6ED300104E7B /* UIColor+Hex.swift */, - 7C5FBE2B2BBDD6B40069E5A0 /* UIView+LayerColors.swift */, 7CFEBE8C2BC440350013233F /* Array+MutableForEach.swift */, 7CFEBE9F2BC6F3CD0013233F /* Date+Extensions.swift */, D1DB71872BD8FF60007F9267 /* Scheduler+Main.swift */, @@ -1388,11 +1394,10 @@ 7CF9C2C62AF7F235009BBFA0 /* MvvmFoundation */, 7C5FBE112BBB63C80069E5A0 /* MarqueeLabel */, 7CAD30182BC3455800592990 /* SWXMLHash */, - 7CC4115A2BD2DE3800CA8B13 /* FirebaseAnalyticsWithoutAdIdSupport */, - 7CC4115C2BD2DE3800CA8B13 /* FirebaseCrashlytics */, - 7CC4115F2BD2FE8700CA8B13 /* FirebaseRemoteConfigSwift */, D1DB71822BD80318007F9267 /* GCDWebServers */, 7CF6DA322C0F112B0033D03F /* OpenSSL */, + 7C519C872C427E9A00E353A9 /* FirebaseAnalytics */, + 7C519C8B2C427F4C00E353A9 /* FirebaseRemoteConfigSwift */, ); productName = iTorrent; productReference = D1A2269A2AEEEFCC00669D6D /* iTorrent.app */; @@ -1431,10 +1436,10 @@ 7CF9C2C52AF7F235009BBFA0 /* XCLocalSwiftPackageReference "Submodules/MVVMFoundation" */, 7C5FBE102BBB63C80069E5A0 /* XCRemoteSwiftPackageReference "MarqueeLabel" */, 7CAD30172BC3455800592990 /* XCRemoteSwiftPackageReference "SWXMLHash" */, - 7CC411592BD2DE3800CA8B13 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */, D1DB71812BD80318007F9267 /* XCLocalSwiftPackageReference "Submodules/GCDWebServer" */, 7CF6DA312C0F112A0033D03F /* XCRemoteSwiftPackageReference "OpenSSL" */, 7C3142CE2C317E6400397E82 /* XCRemoteSwiftPackageReference "MarqueeText" */, + 7C519C862C427E9A00E353A9 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */, ); productRefGroup = D1A2269B2AEEEFCC00669D6D /* Products */; projectDirPath = ""; @@ -1849,6 +1854,7 @@ "@executable_path/Frameworks", ); MARKETPLACES = ""; + OTHER_LDFLAGS = "-ObjC"; PRODUCT_BUNDLE_IDENTIFIER = "$(APPLICATION_ID)"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1989,6 +1995,7 @@ "@executable_path/Frameworks", ); MARKETPLACES = ""; + OTHER_LDFLAGS = "-ObjC"; PRODUCT_BUNDLE_IDENTIFIER = "$(APPLICATION_ID)"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2134,6 +2141,7 @@ "@executable_path/Frameworks", ); MARKETPLACES = ""; + OTHER_LDFLAGS = "-ObjC"; PRODUCT_BUNDLE_IDENTIFIER = "$(APPLICATION_ID)"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2204,6 +2212,14 @@ kind = branch; }; }; + 7C519C862C427E9A00E353A9 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/firebase/firebase-ios-sdk"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 10.29.0; + }; + }; 7C5FBE102BBB63C80069E5A0 /* XCRemoteSwiftPackageReference "MarqueeLabel" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/cbpowell/MarqueeLabel.git"; @@ -2220,14 +2236,6 @@ minimumVersion = 7.0.2; }; }; - 7CC411592BD2DE3800CA8B13 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/firebase/firebase-ios-sdk"; - requirement = { - kind = upToNextMajorVersion; - minimumVersion = 10.24.0; - }; - }; 7CF6DA312C0F112A0033D03F /* XCRemoteSwiftPackageReference "OpenSSL" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/krzyzanowskim/OpenSSL.git"; @@ -2252,6 +2260,16 @@ package = 7C3142CE2C317E6400397E82 /* XCRemoteSwiftPackageReference "MarqueeText" */; productName = MarqueeText; }; + 7C519C872C427E9A00E353A9 /* FirebaseAnalytics */ = { + isa = XCSwiftPackageProductDependency; + package = 7C519C862C427E9A00E353A9 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */; + productName = FirebaseAnalytics; + }; + 7C519C8B2C427F4C00E353A9 /* FirebaseRemoteConfigSwift */ = { + isa = XCSwiftPackageProductDependency; + package = 7C519C862C427E9A00E353A9 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */; + productName = FirebaseRemoteConfigSwift; + }; 7C5FBE112BBB63C80069E5A0 /* MarqueeLabel */ = { isa = XCSwiftPackageProductDependency; package = 7C5FBE102BBB63C80069E5A0 /* XCRemoteSwiftPackageReference "MarqueeLabel" */; @@ -2262,21 +2280,6 @@ package = 7CAD30172BC3455800592990 /* XCRemoteSwiftPackageReference "SWXMLHash" */; productName = SWXMLHash; }; - 7CC4115A2BD2DE3800CA8B13 /* FirebaseAnalyticsWithoutAdIdSupport */ = { - isa = XCSwiftPackageProductDependency; - package = 7CC411592BD2DE3800CA8B13 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */; - productName = FirebaseAnalyticsWithoutAdIdSupport; - }; - 7CC4115C2BD2DE3800CA8B13 /* FirebaseCrashlytics */ = { - isa = XCSwiftPackageProductDependency; - package = 7CC411592BD2DE3800CA8B13 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */; - productName = FirebaseCrashlytics; - }; - 7CC4115F2BD2FE8700CA8B13 /* FirebaseRemoteConfigSwift */ = { - isa = XCSwiftPackageProductDependency; - package = 7CC411592BD2DE3800CA8B13 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */; - productName = FirebaseRemoteConfigSwift; - }; 7CF6DA322C0F112B0033D03F /* OpenSSL */ = { isa = XCSwiftPackageProductDependency; package = 7CF6DA312C0F112A0033D03F /* XCRemoteSwiftPackageReference "OpenSSL" */; diff --git a/iTorrent.xcworkspace/xcshareddata/swiftpm/Package.resolved b/iTorrent.xcworkspace/xcshareddata/swiftpm/Package.resolved index 914ee4c8..0d9a1670 100644 --- a/iTorrent.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/iTorrent.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "44b544b185235ec15216e26ccc849f4038f673959944f92ed64af199c9d4bf6f", + "originHash" : "7bc0d46fb180803d8f7dc610bf256ad6e564c23daa917119278ae7ce0b814310", "pins" : [ { "identity" : "abseil-cpp-binary", @@ -33,8 +33,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/firebase/firebase-ios-sdk", "state" : { - "revision" : "e57841b296d04370ea23580f908881b0ccab17b9", - "version" : "10.28.1" + "revision" : "eca84fd638116dd6adb633b5a3f31cc7befcbb7d", + "version" : "10.29.0" } }, { diff --git a/iTorrent/Screens/TorrentDetails/TorrentDetailsViewModel.swift b/iTorrent/Screens/TorrentDetails/TorrentDetailsViewModel.swift index 07faa7a7..2388ba79 100644 --- a/iTorrent/Screens/TorrentDetails/TorrentDetailsViewModel.swift +++ b/iTorrent/Screens/TorrentDetails/TorrentDetailsViewModel.swift @@ -245,10 +245,10 @@ private extension TorrentDetailsViewModel { seedersModel.detail = "\(torrentHandle.snapshot.numberOfSeeds)(\(torrentHandle.snapshot.numberOfTotalSeeds))" leechersModel.detail = "\(torrentHandle.snapshot.numberOfLeechers)(\(torrentHandle.snapshot.numberOfTotalLeechers))" - downloadPath2Model.detail = torrentHandle.snapshot.downloadPath.path() + downloadPath2Model.detail = torrentHandle.snapshot.downloadPath?.path() ?? "" downloadPathModel.value = torrentHandle.snapshot.storage.name - filesModel.isEnabled = torrentHandle.snapshot.friendlyState != .storageError + filesModel.isEnabled = torrentHandle.snapshot.friendlyState != .storageError && torrentHandle.snapshot.hasMetadata } func reload() { diff --git a/iTorrent/Screens/TorrentFiles/Cells/TorrentFilesFileItem/TorrentFilesFileItemViewModel.swift b/iTorrent/Screens/TorrentFiles/Cells/TorrentFilesFileItem/TorrentFilesFileItemViewModel.swift index 5b1d392c..118006cf 100644 --- a/iTorrent/Screens/TorrentFiles/Cells/TorrentFilesFileItem/TorrentFilesFileItemViewModel.swift +++ b/iTorrent/Screens/TorrentFiles/Cells/TorrentFilesFileItem/TorrentFilesFileItemViewModel.swift @@ -56,7 +56,12 @@ class TorrentFilesFileItemViewModel: BaseViewModelWith<(TorrentHandle, Int)>, Mv } var path: URL { - torrentHandle.snapshot.downloadPath.appending(path: file.path) + guard let downloadPath = torrentHandle.snapshot.downloadPath + else { + assertionFailure("downloadPath cannot be nil for this object") + return URL(string: "/")! + } + return downloadPath.appending(path: file.path) } func setPriority(_ priority: FileEntry.Priority) { diff --git a/iTorrent/Screens/TorrentFiles/TorrentFilesViewModel.swift b/iTorrent/Screens/TorrentFiles/TorrentFilesViewModel.swift index 6827d70f..cd38ef59 100644 --- a/iTorrent/Screens/TorrentFiles/TorrentFilesViewModel.swift +++ b/iTorrent/Screens/TorrentFiles/TorrentFilesViewModel.swift @@ -103,7 +103,13 @@ extension TorrentFilesViewModel { } var downloadPath: URL { - torrentHandle.snapshot.downloadPath + guard let downloadPath = torrentHandle.snapshot.downloadPath + else { + assertionFailure("downloadPath cannot be nil for this object") + return URL(string: "/")! + } + + return downloadPath } var filesForPreview: [FileEntry] { diff --git a/iTorrent/Screens/TorrentTrackers/TorrentTrackersViewModel.swift b/iTorrent/Screens/TorrentTrackers/TorrentTrackersViewModel.swift index ab13de7f..b05cf8e7 100644 --- a/iTorrent/Screens/TorrentTrackers/TorrentTrackersViewModel.swift +++ b/iTorrent/Screens/TorrentTrackers/TorrentTrackersViewModel.swift @@ -91,7 +91,7 @@ private extension TorrentTrackersViewModel { } if trackerListChanged || trackers.count != newTrackers.count { - sections.append(.init(id: "trackers", style: .plain, items: newTrackers)) + sections.append(.init(id: "trackers", style: .plain, items: newTrackers.removingDuplicates())) self.sections = sections } diff --git a/iTorrent/Services/Preferences/PreferencesStorage.swift b/iTorrent/Services/Preferences/PreferencesStorage.swift index 3501c30a..504e9b8b 100644 --- a/iTorrent/Services/Preferences/PreferencesStorage.swift +++ b/iTorrent/Services/Preferences/PreferencesStorage.swift @@ -29,6 +29,8 @@ class PreferencesStorage: Resolvable { // TODO: REMOVE LATER!!! isStorageRulesAccepted = false + + } private var disposeBag: [AnyCancellable] = [] diff --git a/iTorrent/Utils/Extensions/MvvmViewModel+Alert.swift b/iTorrent/Utils/Extensions/MvvmFoundation/MvvmViewModel+Alert.swift similarity index 100% rename from iTorrent/Utils/Extensions/MvvmViewModel+Alert.swift rename to iTorrent/Utils/Extensions/MvvmFoundation/MvvmViewModel+Alert.swift diff --git a/iTorrent/Utils/Extensions/SwiftUILayoutGuides.swift b/iTorrent/Utils/Extensions/SwiftUI/SwiftUILayoutGuides.swift similarity index 100% rename from iTorrent/Utils/Extensions/SwiftUILayoutGuides.swift rename to iTorrent/Utils/Extensions/SwiftUI/SwiftUILayoutGuides.swift diff --git a/iTorrent/Utils/Extensions/UIColor+Hex.swift b/iTorrent/Utils/Extensions/UIKit/UIColor+Hex.swift similarity index 100% rename from iTorrent/Utils/Extensions/UIColor+Hex.swift rename to iTorrent/Utils/Extensions/UIKit/UIColor+Hex.swift diff --git a/iTorrent/Utils/Extensions/UIMenu/UIMenu+Priority.swift b/iTorrent/Utils/Extensions/UIKit/UIMenu/UIMenu+Priority.swift similarity index 100% rename from iTorrent/Utils/Extensions/UIMenu/UIMenu+Priority.swift rename to iTorrent/Utils/Extensions/UIKit/UIMenu/UIMenu+Priority.swift diff --git a/iTorrent/Utils/Extensions/UIView+LayerColors.swift b/iTorrent/Utils/Extensions/UIKit/UIView+LayerColors.swift similarity index 100% rename from iTorrent/Utils/Extensions/UIView+LayerColors.swift rename to iTorrent/Utils/Extensions/UIKit/UIView+LayerColors.swift diff --git a/iTorrent/Utils/NSUserDefaultItem.swift b/iTorrent/Utils/NSUserDefaultItem.swift index 971f0987..8eccdf16 100644 --- a/iTorrent/Utils/NSUserDefaultItem.swift +++ b/iTorrent/Utils/NSUserDefaultItem.swift @@ -5,28 +5,33 @@ // Created by Даниил Виноградов on 01.06.2023. // +import Combine import Foundation import MvvmFoundation @propertyWrapper struct NSUserDefaultItem { - let key: String - let disposeBag = DisposeBag() + private let key: String + private let disposeBag = DisposeBag() + + let projectedValue: CurrentValueSubject var wrappedValue: Value { get { projectedValue.value } - set { projectedValue.send(newValue) } + set { projectedValue.value = newValue } } - let projectedValue: CurrentValueRelay - init(_ key: String, _ defaultValue: Value) { self.key = key + + let loadedValue = Self.value(for: key) + if loadedValue == nil { Self.setValue(defaultValue, for: key) } + projectedValue = .init(Self.value(for: key) ?? defaultValue) - bind(in: disposeBag) { - projectedValue.sink { [key] val in - Self.setValue(val, for: key) + disposeBag.bind { + projectedValue.sink { value in + Self.setValue(value, for: key) } } } diff --git a/iTorrent/Utils/UserDefaultItem.swift b/iTorrent/Utils/UserDefaultItem.swift index ba543e33..d461c127 100644 --- a/iTorrent/Utils/UserDefaultItem.swift +++ b/iTorrent/Utils/UserDefaultItem.swift @@ -10,26 +10,28 @@ import Foundation import MvvmFoundation @propertyWrapper -struct UserDefaultItem { +struct UserDefaultItem { private let key: String - private let defaultValue: T private let disposeBag = DisposeBag() - let projectedValue: CurrentValueSubject + let projectedValue: CurrentValueSubject - var wrappedValue: T { + var wrappedValue: Value { get { projectedValue.value } set { projectedValue.value = newValue } } - init(_ key: String, _ defaultValue: T) { + init(_ key: String, _ defaultValue: Value) { self.key = key - self.defaultValue = defaultValue - projectedValue = CurrentValueSubject(Self.get(by: key) ?? defaultValue) + + let loadedValue = Self.value(for: key) + if loadedValue == nil { Self.setValue(defaultValue, for: key) } + + projectedValue = .init(Self.value(for: key) ?? defaultValue) disposeBag.bind { projectedValue.sink { value in - Self.set(by: key, value) + Self.setValue(value, for: key) } } } @@ -38,14 +40,14 @@ struct UserDefaultItem { private extension UserDefaultItem { static var userDefaults: UserDefaults { .itorrentGroup } - static func get(by key: String) -> T? { + static func value(for key: String) -> Value? { guard let decoded = userDefaults.data(forKey: key), - let res = try? JSONDecoder().decode(T.self, from: decoded) + let res = try? JSONDecoder().decode(Value.self, from: decoded) else { return nil } return res } - static func set(by key: String, _ value: T?) { + static func setValue(_ value: Value?, for key: String) { if let value, let encodedData: Data = try? JSONEncoder().encode(value) { userDefaults.set(encodedData, forKey: key) } else {