From a89e832d1c2a49055653eb3333f3e44de0a17d53 Mon Sep 17 00:00:00 2001 From: kingbri Date: Fri, 16 Sep 2022 13:07:28 -0400 Subject: [PATCH] Ferrite: Concurrency, cleanup, and format Use strict concurrency checking in Xcode 14 to find misuses with Swift concurrency. Cleanup files and rearrange them along with fixing comment headers. Signed-off-by: kingbri --- Ferrite.xcodeproj/project.pbxproj | 120 +++++++---- Ferrite/API/RealDebridWrapper.swift | 3 +- .../Application.swift} | 13 +- .../Classes/Bookmark+CoreDataProperties.swift | 31 ++- .../Classes/History+CoreDataClass.swift | 6 +- .../Classes/History+CoreDataProperties.swift | 35 ++- .../PersistenceController.swift | 3 +- Ferrite/Extensions/NotificationCenter.swift | 2 +- Ferrite/Extensions/View.swift | 39 ++-- Ferrite/Models/GithubModels.swift | 2 +- Ferrite/Models/RealDebridModels.swift | 200 +++++++++--------- Ferrite/Models/SearchModels.swift | 2 +- Ferrite/Models/SourceModels.swift | 24 +-- Ferrite/ViewModels/DebridManager.swift | 2 +- Ferrite/ViewModels/SourceManager.swift | 4 +- Ferrite/Views/AboutView.swift | 6 +- Ferrite/Views/CommonViews/AlertButton.swift | 16 +- .../CommonViews/DynamicFetchRequest.swift | 3 + Ferrite/Views/CommonViews/GroupBoxStyle.swift | 20 -- Ferrite/Views/CommonViews/ListRowViews.swift | 4 +- .../ConditionalContextMenu.swift | 0 .../{ => Modifiers}/ConditionalId.swift | 2 +- .../{ => Modifiers}/DisableInteraction.swift | 2 +- .../{ => Modifiers}/DisabledAppearance.swift | 2 + .../{ => Modifiers}/DynamicAccentColor.swift | 4 +- .../{ => Modifiers}/DynamicActionSheet.swift | 4 +- .../{ => Modifiers}/DynamicAlert.swift | 2 + .../{ => Modifiers}/InlinedList.swift | 4 +- Ferrite/Views/CommonViews/NavView.swift | 3 + Ferrite/Views/LibraryView.swift | 2 +- .../Views/LibraryViews/BookmarksView.swift | 4 +- .../LibraryViews/HistoryButtonView.swift | 10 +- Ferrite/Views/MagnetChoiceView.swift | 2 +- Ferrite/Views/MainView.swift | 2 +- .../Views/RepresentableViews/WebView.swift | 2 +- .../SearchResultButtonView.swift | 10 +- .../SearchResultRDView.swift | 0 .../InstalledSourceButtonView.swift} | 4 +- .../SourceCatalogButtonView.swift} | 0 .../SourceUpdateButtonView.swift | 0 Ferrite/Views/SourcesView.swift | 2 +- 41 files changed, 304 insertions(+), 292 deletions(-) rename Ferrite/{Extensions/UIApplication.swift => Classes/Application.swift} (64%) delete mode 100644 Ferrite/Views/CommonViews/GroupBoxStyle.swift rename Ferrite/Views/CommonViews/{ => Modifiers}/ConditionalContextMenu.swift (100%) rename Ferrite/Views/CommonViews/{ => Modifiers}/ConditionalId.swift (91%) rename Ferrite/Views/CommonViews/{ => Modifiers}/DisableInteraction.swift (87%) rename Ferrite/Views/CommonViews/{ => Modifiers}/DisabledAppearance.swift (89%) rename Ferrite/Views/CommonViews/{ => Modifiers}/DynamicAccentColor.swift (80%) rename Ferrite/Views/CommonViews/{ => Modifiers}/DynamicActionSheet.swift (92%) rename Ferrite/Views/CommonViews/{ => Modifiers}/DynamicAlert.swift (96%) rename Ferrite/Views/CommonViews/{ => Modifiers}/InlinedList.swift (81%) rename Ferrite/Views/{ => SearchResultViews}/SearchResultButtonView.swift (97%) rename Ferrite/Views/{ => SearchResultViews}/SearchResultRDView.swift (100%) rename Ferrite/Views/SourceViews/{InstalledSourceView.swift => Buttons/InstalledSourceButtonView.swift} (95%) rename Ferrite/Views/SourceViews/{SourceCatalogView.swift => Buttons/SourceCatalogButtonView.swift} (100%) rename Ferrite/Views/SourceViews/{ => Buttons}/SourceUpdateButtonView.swift (100%) diff --git a/Ferrite.xcodeproj/project.pbxproj b/Ferrite.xcodeproj/project.pbxproj index 051a2e8..1027ccc 100644 --- a/Ferrite.xcodeproj/project.pbxproj +++ b/Ferrite.xcodeproj/project.pbxproj @@ -14,13 +14,13 @@ 0C31133C28B1ABFA004DCB0D /* SourceJsonParser+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C31133A28B1ABFA004DCB0D /* SourceJsonParser+CoreDataClass.swift */; }; 0C31133D28B1ABFA004DCB0D /* SourceJsonParser+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C31133B28B1ABFA004DCB0D /* SourceJsonParser+CoreDataProperties.swift */; }; 0C32FB532890D19D002BD219 /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C32FB522890D19D002BD219 /* AboutView.swift */; }; - 0C32FB552890D1BF002BD219 /* UIApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C32FB542890D1BF002BD219 /* UIApplication.swift */; }; 0C32FB572890D1F2002BD219 /* ListRowViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C32FB562890D1F2002BD219 /* ListRowViews.swift */; }; 0C360C5C28C7DF1400884ED3 /* DynamicFetchRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C360C5B28C7DF1400884ED3 /* DynamicFetchRequest.swift */; }; 0C391EC928CA63F0009F1CA1 /* DynamicActionSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C391EC828CA63F0009F1CA1 /* DynamicActionSheet.swift */; }; 0C391ECB28CAA44B009F1CA1 /* AlertButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C391ECA28CAA44B009F1CA1 /* AlertButton.swift */; }; 0C41BC6328C2AD0F00B47DD6 /* SearchResultButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C41BC6228C2AD0F00B47DD6 /* SearchResultButtonView.swift */; }; 0C41BC6528C2AEB900B47DD6 /* SearchModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C41BC6428C2AEB900B47DD6 /* SearchModels.swift */; }; + 0C44E2A828D4DDDC007711AE /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C44E2A728D4DDDC007711AE /* Application.swift */; }; 0C4CFC462897030D00AD9FAD /* Regex in Frameworks */ = {isa = PBXBuildFile; productRef = 0C4CFC452897030D00AD9FAD /* Regex */; }; 0C4CFC4D28970C8B00AD9FAD /* SourceComplexQuery+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C4CFC4728970C8B00AD9FAD /* SourceComplexQuery+CoreDataClass.swift */; }; 0C4CFC4E28970C8B00AD9FAD /* SourceComplexQuery+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C4CFC4828970C8B00AD9FAD /* SourceComplexQuery+CoreDataProperties.swift */; }; @@ -41,8 +41,8 @@ 0C750745289B003E004B3906 /* SourceRssParser+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C750743289B003E004B3906 /* SourceRssParser+CoreDataProperties.swift */; }; 0C78041D28BFB3EA001E8CA3 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C78041C28BFB3EA001E8CA3 /* String.swift */; }; 0C794B67289DACB600DD1CC8 /* SourceUpdateButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C794B66289DACB600DD1CC8 /* SourceUpdateButtonView.swift */; }; - 0C794B69289DACC800DD1CC8 /* InstalledSourceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C794B68289DACC800DD1CC8 /* InstalledSourceView.swift */; }; - 0C794B6B289DACF100DD1CC8 /* SourceCatalogView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C794B6A289DACF100DD1CC8 /* SourceCatalogView.swift */; }; + 0C794B69289DACC800DD1CC8 /* InstalledSourceButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C794B68289DACC800DD1CC8 /* InstalledSourceButtonView.swift */; }; + 0C794B6B289DACF100DD1CC8 /* SourceCatalogButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C794B6A289DACF100DD1CC8 /* SourceCatalogButtonView.swift */; }; 0C794B6D289EFA2E00DD1CC8 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0C794B6C289EFA2E00DD1CC8 /* LaunchScreen.storyboard */; }; 0C79DC072899AF3C003F1C5A /* SourceSeedLeech+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C79DC052899AF3C003F1C5A /* SourceSeedLeech+CoreDataClass.swift */; }; 0C79DC082899AF3C003F1C5A /* SourceSeedLeech+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C79DC062899AF3C003F1C5A /* SourceSeedLeech+CoreDataProperties.swift */; }; @@ -98,7 +98,6 @@ 0CD4CAC628C980EB0046E1DC /* HistoryActionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CD4CAC528C980EB0046E1DC /* HistoryActionsView.swift */; }; 0CD5E78928CD932B001BF684 /* DisabledAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CD5E78828CD932B001BF684 /* DisabledAppearance.swift */; }; 0CDCB91828C662640098B513 /* EmptyInstructionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CDCB91728C662640098B513 /* EmptyInstructionView.swift */; }; - 0CFEFCFD288A006200B3F490 /* GroupBoxStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CFEFCFC288A006200B3F490 /* GroupBoxStyle.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -109,13 +108,13 @@ 0C31133A28B1ABFA004DCB0D /* SourceJsonParser+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SourceJsonParser+CoreDataClass.swift"; sourceTree = ""; }; 0C31133B28B1ABFA004DCB0D /* SourceJsonParser+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SourceJsonParser+CoreDataProperties.swift"; sourceTree = ""; }; 0C32FB522890D19D002BD219 /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = ""; }; - 0C32FB542890D1BF002BD219 /* UIApplication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIApplication.swift; sourceTree = ""; }; 0C32FB562890D1F2002BD219 /* ListRowViews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRowViews.swift; sourceTree = ""; }; 0C360C5B28C7DF1400884ED3 /* DynamicFetchRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicFetchRequest.swift; sourceTree = ""; }; 0C391EC828CA63F0009F1CA1 /* DynamicActionSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicActionSheet.swift; sourceTree = ""; }; 0C391ECA28CAA44B009F1CA1 /* AlertButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertButton.swift; sourceTree = ""; }; 0C41BC6228C2AD0F00B47DD6 /* SearchResultButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultButtonView.swift; sourceTree = ""; }; 0C41BC6428C2AEB900B47DD6 /* SearchModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchModels.swift; sourceTree = ""; }; + 0C44E2A728D4DDDC007711AE /* Application.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = ""; }; 0C4CFC4728970C8B00AD9FAD /* SourceComplexQuery+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SourceComplexQuery+CoreDataClass.swift"; sourceTree = ""; }; 0C4CFC4828970C8B00AD9FAD /* SourceComplexQuery+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SourceComplexQuery+CoreDataProperties.swift"; sourceTree = ""; }; 0C54D36128C5086E00BFEEE2 /* History+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "History+CoreDataClass.swift"; sourceTree = ""; }; @@ -131,8 +130,8 @@ 0C750743289B003E004B3906 /* SourceRssParser+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SourceRssParser+CoreDataProperties.swift"; sourceTree = ""; }; 0C78041C28BFB3EA001E8CA3 /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = ""; }; 0C794B66289DACB600DD1CC8 /* SourceUpdateButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceUpdateButtonView.swift; sourceTree = ""; }; - 0C794B68289DACC800DD1CC8 /* InstalledSourceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstalledSourceView.swift; sourceTree = ""; }; - 0C794B6A289DACF100DD1CC8 /* SourceCatalogView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceCatalogView.swift; sourceTree = ""; }; + 0C794B68289DACC800DD1CC8 /* InstalledSourceButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstalledSourceButtonView.swift; sourceTree = ""; }; + 0C794B6A289DACF100DD1CC8 /* SourceCatalogButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceCatalogButtonView.swift; sourceTree = ""; }; 0C794B6C289EFA2E00DD1CC8 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; 0C79DC052899AF3C003F1C5A /* SourceSeedLeech+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SourceSeedLeech+CoreDataClass.swift"; sourceTree = ""; }; 0C79DC062899AF3C003F1C5A /* SourceSeedLeech+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SourceSeedLeech+CoreDataProperties.swift"; sourceTree = ""; }; @@ -188,7 +187,6 @@ 0CD4CAC528C980EB0046E1DC /* HistoryActionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryActionsView.swift; sourceTree = ""; }; 0CD5E78828CD932B001BF684 /* DisabledAppearance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisabledAppearance.swift; sourceTree = ""; }; 0CDCB91728C662640098B513 /* EmptyInstructionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyInstructionView.swift; sourceTree = ""; }; - 0CFEFCFC288A006200B3F490 /* GroupBoxStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupBoxStyle.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -237,22 +235,62 @@ 0C0D50E3288DFE6E0035ECC8 /* Models */ = { isa = PBXGroup; children = ( - 0CA148C4288903F000DE2211 /* RealDebridModels.swift */, - 0C0D50E4288DFE7F0035ECC8 /* SourceModels.swift */, - 0C95D8D928A55BB6005E22B3 /* SettingsModels.swift */, 0C68135128BC1A7C00FAD890 /* GithubModels.swift */, + 0CA148C4288903F000DE2211 /* RealDebridModels.swift */, 0C41BC6428C2AEB900B47DD6 /* SearchModels.swift */, + 0C95D8D928A55BB6005E22B3 /* SettingsModels.swift */, + 0C0D50E4288DFE7F0035ECC8 /* SourceModels.swift */, ); path = Models; sourceTree = ""; }; + 0C44E2A628D4DDC6007711AE /* Classes */ = { + isa = PBXGroup; + children = ( + 0C44E2A728D4DDDC007711AE /* Application.swift */, + ); + path = Classes; + sourceTree = ""; + }; + 0C44E2A928D4DFC4007711AE /* Modifiers */ = { + isa = PBXGroup; + children = ( + 0C70E40128C3CE9C00A5C72D /* ConditionalContextMenu.swift */, + 0CB6516228C5A57300DCA721 /* ConditionalId.swift */, + 0CD5E78828CD932B001BF684 /* DisabledAppearance.swift */, + 0CBAB83528D12ED500AC903E /* DisableInteraction.swift */, + 0C7D11FB28AA01E900ED92DB /* DynamicAccentColor.swift */, + 0C391EC828CA63F0009F1CA1 /* DynamicActionSheet.swift */, + 0C626A9428CADB25003C7129 /* DynamicAlert.swift */, + 0CB6516428C5A5D700DCA721 /* InlinedList.swift */, + ); + path = Modifiers; + sourceTree = ""; + }; + 0C44E2AA28D4E09B007711AE /* Buttons */ = { + isa = PBXGroup; + children = ( + 0C794B68289DACC800DD1CC8 /* InstalledSourceButtonView.swift */, + 0C794B6A289DACF100DD1CC8 /* SourceCatalogButtonView.swift */, + 0C794B66289DACB600DD1CC8 /* SourceUpdateButtonView.swift */, + ); + path = Buttons; + sourceTree = ""; + }; + 0C44E2AB28D4E126007711AE /* SearchResultViews */ = { + isa = PBXGroup; + children = ( + 0C41BC6228C2AD0F00B47DD6 /* SearchResultButtonView.swift */, + 0C57D4CB289032ED008534E8 /* SearchResultRDView.swift */, + ); + path = SearchResultViews; + sourceTree = ""; + }; 0C794B65289DAC9F00DD1CC8 /* SourceViews */ = { isa = PBXGroup; children = ( + 0C44E2AA28D4E09B007711AE /* Buttons */, 0C733286289C4C820058D1FE /* SourceSettingsView.swift */, - 0C794B66289DACB600DD1CC8 /* SourceUpdateButtonView.swift */, - 0C794B68289DACC800DD1CC8 /* InstalledSourceView.swift */, - 0C794B6A289DACF100DD1CC8 /* SourceCatalogView.swift */, ); path = SourceViews; sourceTree = ""; @@ -277,6 +315,7 @@ 0C0D50E3288DFE6E0035ECC8 /* Models */, 0CA148EF2889061600DE2211 /* ViewModels */, 0CA148EE2889061200DE2211 /* Views */, + 0C44E2A628D4DDC6007711AE /* Classes */, 0CA148C8288903F000DE2211 /* Extensions */, 0CA148C5288903F000DE2211 /* Preview Content */, 0CA148C7288903F000DE2211 /* FerriteApp.swift */, @@ -289,22 +328,14 @@ 0CA148C0288903F000DE2211 /* CommonViews */ = { isa = PBXGroup; children = ( - 0CA148C1288903F000DE2211 /* NavView.swift */, - 0CFEFCFC288A006200B3F490 /* GroupBoxStyle.swift */, - 0C32FB562890D1F2002BD219 /* ListRowViews.swift */, - 0C7D11FB28AA01E900ED92DB /* DynamicAccentColor.swift */, - 0CA3FB1F28B91D9500FA10A8 /* IndeterminateProgressView.swift */, - 0CB6516228C5A57300DCA721 /* ConditionalId.swift */, - 0CB6516428C5A5D700DCA721 /* InlinedList.swift */, - 0CB6516928C5B4A600DCA721 /* InlineHeader.swift */, - 0CDCB91728C662640098B513 /* EmptyInstructionView.swift */, - 0C360C5B28C7DF1400884ED3 /* DynamicFetchRequest.swift */, - 0C70E40128C3CE9C00A5C72D /* ConditionalContextMenu.swift */, - 0C391EC828CA63F0009F1CA1 /* DynamicActionSheet.swift */, + 0C44E2A928D4DFC4007711AE /* Modifiers */, 0C391ECA28CAA44B009F1CA1 /* AlertButton.swift */, - 0C626A9428CADB25003C7129 /* DynamicAlert.swift */, - 0CD5E78828CD932B001BF684 /* DisabledAppearance.swift */, - 0CBAB83528D12ED500AC903E /* DisableInteraction.swift */, + 0C360C5B28C7DF1400884ED3 /* DynamicFetchRequest.swift */, + 0CDCB91728C662640098B513 /* EmptyInstructionView.swift */, + 0CA148C1288903F000DE2211 /* NavView.swift */, + 0CA3FB1F28B91D9500FA10A8 /* IndeterminateProgressView.swift */, + 0CB6516928C5B4A600DCA721 /* InlineHeader.swift */, + 0C32FB562890D1F2002BD219 /* ListRowViews.swift */, ); path = CommonViews; sourceTree = ""; @@ -322,12 +353,11 @@ children = ( 0CA148C9288903F000DE2211 /* Collection.swift */, 0CA148CA288903F000DE2211 /* Data.swift */, - 0CA148CB288903F000DE2211 /* Task.swift */, - 0C32FB542890D1BF002BD219 /* UIApplication.swift */, - 0C7D11FD28AA03FE00ED92DB /* View.swift */, - 0C78041C28BFB3EA001E8CA3 /* String.swift */, - 0C70E40528C40C4E00A5C72D /* NotificationCenter.swift */, 0CA429F728C5098D000D0610 /* DateFormatter.swift */, + 0C70E40528C40C4E00A5C72D /* NotificationCenter.swift */, + 0C78041C28BFB3EA001E8CA3 /* String.swift */, + 0CA148CB288903F000DE2211 /* Task.swift */, + 0C7D11FD28AA03FE00ED92DB /* View.swift */, ); path = Extensions; sourceTree = ""; @@ -339,19 +369,18 @@ 0C794B65289DAC9F00DD1CC8 /* SourceViews */, 0CA148F02889062700DE2211 /* RepresentableViews */, 0CA148C0288903F000DE2211 /* CommonViews */, + 0C44E2AB28D4E126007711AE /* SearchResultViews */, 0CA0545C288F7CB200850554 /* SettingsViews */, - 0CA148D3288903F000DE2211 /* SearchResultsView.swift */, - 0C41BC6228C2AD0F00B47DD6 /* SearchResultButtonView.swift */, - 0C57D4CB289032ED008534E8 /* SearchResultRDView.swift */, - 0CA148D4288903F000DE2211 /* ContentView.swift */, 0CA148D1288903F000DE2211 /* MainView.swift */, + 0CA148D4288903F000DE2211 /* ContentView.swift */, + 0CA148D3288903F000DE2211 /* SearchResultsView.swift */, + 0CA3B23328C2658700616D3A /* LibraryView.swift */, + 0C0D50E6288DFF850035ECC8 /* SourcesView.swift */, 0CA148BB288903F000DE2211 /* SettingsView.swift */, + 0C32FB522890D19D002BD219 /* AboutView.swift */, 0CA148BC288903F000DE2211 /* LoginWebView.swift */, 0CBC76FC288D914F0054BE44 /* BatchChoiceView.swift */, 0CA148BD288903F000DE2211 /* MagnetChoiceView.swift */, - 0C0D50E6288DFF850035ECC8 /* SourcesView.swift */, - 0C32FB522890D19D002BD219 /* AboutView.swift */, - 0CA3B23328C2658700616D3A /* LibraryView.swift */, ); path = Views; sourceTree = ""; @@ -379,8 +408,8 @@ 0CA148F12889066000DE2211 /* API */ = { isa = PBXGroup; children = ( - 0CA148D0288903F000DE2211 /* RealDebridWrapper.swift */, 0C68134F28BC1A2D00FAD890 /* GithubWrapper.swift */, + 0CA148D0288903F000DE2211 /* RealDebridWrapper.swift */, ); path = API; sourceTree = ""; @@ -528,21 +557,21 @@ 0C360C5C28C7DF1400884ED3 /* DynamicFetchRequest.swift in Sources */, 0CA429F828C5098D000D0610 /* DateFormatter.swift in Sources */, 0C84F4872895BFED0074B7C9 /* SourceList+CoreDataProperties.swift in Sources */, - 0C794B6B289DACF100DD1CC8 /* SourceCatalogView.swift in Sources */, + 0C794B6B289DACF100DD1CC8 /* SourceCatalogButtonView.swift in Sources */, 0C54D36428C5086E00BFEEE2 /* History+CoreDataProperties.swift in Sources */, 0CA148E9288903F000DE2211 /* MainView.swift in Sources */, 0CBC76FD288D914F0054BE44 /* BatchChoiceView.swift in Sources */, - 0C32FB552890D1BF002BD219 /* UIApplication.swift in Sources */, 0C7D11FE28AA03FE00ED92DB /* View.swift in Sources */, 0CA3B23728C2660700616D3A /* HistoryView.swift in Sources */, 0C70E40228C3CE9C00A5C72D /* ConditionalContextMenu.swift in Sources */, 0C0D50E7288DFF850035ECC8 /* SourcesView.swift in Sources */, 0CA3B23428C2658700616D3A /* LibraryView.swift in Sources */, + 0C44E2A828D4DDDC007711AE /* Application.swift in Sources */, 0CA148EC288903F000DE2211 /* ContentView.swift in Sources */, 0C95D8D828A55B03005E22B3 /* DefaultActionsPickerViews.swift in Sources */, 0CA148E1288903F000DE2211 /* Collection.swift in Sources */, 0C750744289B003E004B3906 /* SourceRssParser+CoreDataClass.swift in Sources */, - 0C794B69289DACC800DD1CC8 /* InstalledSourceView.swift in Sources */, + 0C794B69289DACC800DD1CC8 /* InstalledSourceButtonView.swift in Sources */, 0C79DC082899AF3C003F1C5A /* SourceSeedLeech+CoreDataProperties.swift in Sources */, 0CD4CAC628C980EB0046E1DC /* HistoryActionsView.swift in Sources */, 0CA148DD288903F000DE2211 /* ScrapingViewModel.swift in Sources */, @@ -556,7 +585,6 @@ 0C626A9528CADB25003C7129 /* DynamicAlert.swift in Sources */, 0CA148E7288903F000DE2211 /* ToastViewModel.swift in Sources */, 0C68135228BC1A7C00FAD890 /* GithubModels.swift in Sources */, - 0CFEFCFD288A006200B3F490 /* GroupBoxStyle.swift in Sources */, 0C391EC928CA63F0009F1CA1 /* DynamicActionSheet.swift in Sources */, 0CA3B23928C2660D00616D3A /* BookmarksView.swift in Sources */, 0C79DC072899AF3C003F1C5A /* SourceSeedLeech+CoreDataClass.swift in Sources */, diff --git a/Ferrite/API/RealDebridWrapper.swift b/Ferrite/API/RealDebridWrapper.swift index fb60a5f..ecefd2a 100644 --- a/Ferrite/API/RealDebridWrapper.swift +++ b/Ferrite/API/RealDebridWrapper.swift @@ -255,7 +255,8 @@ public class RealDebrid { hash: hash, expiryTimeStamp: Date().timeIntervalSince1970 + 300, files: files, - batches: batches) + batches: batches + ) ) } else { availableHashes.append( diff --git a/Ferrite/Extensions/UIApplication.swift b/Ferrite/Classes/Application.swift similarity index 64% rename from Ferrite/Extensions/UIApplication.swift rename to Ferrite/Classes/Application.swift index 3490ab4..6ebdbab 100644 --- a/Ferrite/Extensions/UIApplication.swift +++ b/Ferrite/Classes/Application.swift @@ -1,14 +1,17 @@ // -// UIApplication.swift +// Application.swift // Ferrite // -// Created by Brian Dashore on 7/26/22. +// Created by Brian Dashore on 9/16/22. +// +// A thread-safe UIApplication alternative for specifying app properties // -import SwiftUI +import Foundation + +public class Application { + static let shared = Application() -// Extensions to get the version/build number for AboutView -extension UIApplication { var appVersion: String { Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "0.0.0" } diff --git a/Ferrite/DataManagement/Classes/Bookmark+CoreDataProperties.swift b/Ferrite/DataManagement/Classes/Bookmark+CoreDataProperties.swift index 6528695..36f2e9e 100644 --- a/Ferrite/DataManagement/Classes/Bookmark+CoreDataProperties.swift +++ b/Ferrite/DataManagement/Classes/Bookmark+CoreDataProperties.swift @@ -6,27 +6,22 @@ // // -import Foundation import CoreData +import Foundation - -extension Bookmark { - - @nonobjc public class func fetchRequest() -> NSFetchRequest { - return NSFetchRequest(entityName: "Bookmark") +public extension Bookmark { + @nonobjc class func fetchRequest() -> NSFetchRequest { + NSFetchRequest(entityName: "Bookmark") } - @NSManaged public var leechers: String? - @NSManaged public var magnetHash: String? - @NSManaged public var magnetLink: String? - @NSManaged public var seeders: String? - @NSManaged public var size: String? - @NSManaged public var source: String - @NSManaged public var title: String? - @NSManaged public var orderNum: Int16 - + @NSManaged var leechers: String? + @NSManaged var magnetHash: String? + @NSManaged var magnetLink: String? + @NSManaged var seeders: String? + @NSManaged var size: String? + @NSManaged var source: String + @NSManaged var title: String? + @NSManaged var orderNum: Int16 } -extension Bookmark : Identifiable { - -} +extension Bookmark: Identifiable {} diff --git a/Ferrite/DataManagement/Classes/History+CoreDataClass.swift b/Ferrite/DataManagement/Classes/History+CoreDataClass.swift index b7108b3..18677e1 100644 --- a/Ferrite/DataManagement/Classes/History+CoreDataClass.swift +++ b/Ferrite/DataManagement/Classes/History+CoreDataClass.swift @@ -6,10 +6,8 @@ // // -import Foundation import CoreData +import Foundation @objc(History) -public class History: NSManagedObject { - -} +public class History: NSManagedObject {} diff --git a/Ferrite/DataManagement/Classes/History+CoreDataProperties.swift b/Ferrite/DataManagement/Classes/History+CoreDataProperties.swift index 7e384ab..cc8ad58 100644 --- a/Ferrite/DataManagement/Classes/History+CoreDataProperties.swift +++ b/Ferrite/DataManagement/Classes/History+CoreDataProperties.swift @@ -6,21 +6,19 @@ // // -import Foundation import CoreData +import Foundation - -extension History { - - @nonobjc public class func fetchRequest() -> NSFetchRequest { - return NSFetchRequest(entityName: "History") +public extension History { + @nonobjc class func fetchRequest() -> NSFetchRequest { + NSFetchRequest(entityName: "History") } - @NSManaged public var date: Date? - @NSManaged public var dateString: String? - @NSManaged public var entries: NSSet? - - var entryArray: [HistoryEntry] { + @NSManaged var date: Date? + @NSManaged var dateString: String? + @NSManaged var entries: NSSet? + + internal var entryArray: [HistoryEntry] { let entrySet = entries as? Set ?? [] return entrySet.sorted { @@ -30,22 +28,19 @@ extension History { } // MARK: Generated accessors for entries -extension History { +public extension History { @objc(addEntriesObject:) - @NSManaged public func addToEntries(_ value: HistoryEntry) + @NSManaged func addToEntries(_ value: HistoryEntry) @objc(removeEntriesObject:) - @NSManaged public func removeFromEntries(_ value: HistoryEntry) + @NSManaged func removeFromEntries(_ value: HistoryEntry) @objc(addEntries:) - @NSManaged public func addToEntries(_ values: NSSet) + @NSManaged func addToEntries(_ values: NSSet) @objc(removeEntries:) - @NSManaged public func removeFromEntries(_ values: NSSet) - + @NSManaged func removeFromEntries(_ values: NSSet) } -extension History : Identifiable { - -} +extension History: Identifiable {} diff --git a/Ferrite/DataManagement/PersistenceController.swift b/Ferrite/DataManagement/PersistenceController.swift index 1fecdc2..92c34a2 100644 --- a/Ferrite/DataManagement/PersistenceController.swift +++ b/Ferrite/DataManagement/PersistenceController.swift @@ -21,7 +21,7 @@ enum HistoryDeleteError: Error { // No iCloud until finalized sources struct PersistenceController { - static var shared = PersistenceController() + static let shared = PersistenceController() // Coredata storage let container: NSPersistentContainer @@ -91,7 +91,6 @@ struct PersistenceController { save() } - func getHistoryPredicate(range: HistoryDeleteRange) -> NSPredicate? { if range == .allTime { return nil diff --git a/Ferrite/Extensions/NotificationCenter.swift b/Ferrite/Extensions/NotificationCenter.swift index be21d68..7bc0db5 100644 --- a/Ferrite/Extensions/NotificationCenter.swift +++ b/Ferrite/Extensions/NotificationCenter.swift @@ -9,6 +9,6 @@ import Foundation extension Notification.Name { static var didDeleteBookmark: Notification.Name { - return Notification.Name("Deleted bookmark") + Notification.Name("Deleted bookmark") } } diff --git a/Ferrite/Extensions/View.swift b/Ferrite/Extensions/View.swift index 2226805..5f07409 100644 --- a/Ferrite/Extensions/View.swift +++ b/Ferrite/Extensions/View.swift @@ -25,8 +25,10 @@ extension View { // MARK: Modifiers - func dynamicAccentColor(_ color: Color) -> some View { - modifier(DynamicAccentColor(color: color)) + func conditionalContextMenu(id: ID, + @ViewBuilder _ internalContent: @escaping () -> InternalContent) -> some View + { + modifier(ConditionalContextMenu(internalContent, id: id)) } func conditionalId(_ id: ID) -> some View { @@ -37,36 +39,31 @@ extension View { modifier(DisabledAppearance(disabled: disabled, dimmedOpacity: dimmedOpacity, animation: animation)) } - func inlinedList() -> some View { - modifier(InlinedList()) + func disableInteraction(_ disabled: Bool) -> some View { + modifier(DisableInteraction(disabled: disabled)) } - func conditionalContextMenu( - id: ID, - @ViewBuilder _ internalContent: @escaping () -> InternalContent - ) -> some View { - modifier(ConditionalContextMenu(internalContent, id: id)) + func dynamicAccentColor(_ color: Color) -> some View { + modifier(DynamicAccentColor(color: color)) } - func dynamicActionSheet( - isPresented: Binding, - title: String, - message: String? = nil, - buttons: [AlertButton]) -> some View + func dynamicActionSheet(isPresented: Binding, + title: String, + message: String? = nil, + buttons: [AlertButton]) -> some View { modifier(DynamicActionSheet(isPresented: isPresented, title: title, message: message, buttons: buttons)) } - func dynamicAlert( - isPresented: Binding, - title: String, - message: String? = nil, - buttons: [AlertButton]) -> some View + func dynamicAlert(isPresented: Binding, + title: String, + message: String? = nil, + buttons: [AlertButton]) -> some View { modifier(DynamicAlert(isPresented: isPresented, title: title, message: message, buttons: buttons)) } - func disableInteraction(_ disabled: Bool) -> some View { - modifier(DisableInteraction(disabled: disabled)) + func inlinedList() -> some View { + modifier(InlinedList()) } } diff --git a/Ferrite/Models/GithubModels.swift b/Ferrite/Models/GithubModels.swift index 575dba5..fb4a066 100644 --- a/Ferrite/Models/GithubModels.swift +++ b/Ferrite/Models/GithubModels.swift @@ -7,7 +7,7 @@ import Foundation -public struct GithubRelease: Codable, Hashable { +public struct GithubRelease: Codable, Hashable, Sendable { let htmlUrl: String let tagName: String diff --git a/Ferrite/Models/RealDebridModels.swift b/Ferrite/Models/RealDebridModels.swift index 39506f0..208f253 100644 --- a/Ferrite/Models/RealDebridModels.swift +++ b/Ferrite/Models/RealDebridModels.swift @@ -10,138 +10,138 @@ import Foundation // MARK: - device code endpoint -public struct DeviceCodeResponse: Codable { - let deviceCode, userCode: String - let interval, expiresIn: Int - let verificationURL, directVerificationURL: String +public struct DeviceCodeResponse: Codable, Sendable { + let deviceCode, userCode: String + let interval, expiresIn: Int + let verificationURL, directVerificationURL: String - enum CodingKeys: String, CodingKey { - case deviceCode = "device_code" - case userCode = "user_code" - case interval - case expiresIn = "expires_in" - case verificationURL = "verification_url" - case directVerificationURL = "direct_verification_url" - } + enum CodingKeys: String, CodingKey { + case deviceCode = "device_code" + case userCode = "user_code" + case interval + case expiresIn = "expires_in" + case verificationURL = "verification_url" + case directVerificationURL = "direct_verification_url" + } } // MARK: - device credentials endpoint -public struct DeviceCredentialsResponse: Codable { - let clientID, clientSecret: String? +public struct DeviceCredentialsResponse: Codable, Sendable { + let clientID, clientSecret: String? - enum CodingKeys: String, CodingKey { - case clientID = "client_id" - case clientSecret = "client_secret" - } + enum CodingKeys: String, CodingKey { + case clientID = "client_id" + case clientSecret = "client_secret" + } } // MARK: - token endpoint -public struct TokenResponse: Codable { - let accessToken: String - let expiresIn: Int - let refreshToken, tokenType: String +public struct TokenResponse: Codable, Sendable { + let accessToken: String + let expiresIn: Int + let refreshToken, tokenType: String - enum CodingKeys: String, CodingKey { - case accessToken = "access_token" - case expiresIn = "expires_in" - case refreshToken = "refresh_token" - case tokenType = "token_type" - } + enum CodingKeys: String, CodingKey { + case accessToken = "access_token" + case expiresIn = "expires_in" + case refreshToken = "refresh_token" + case tokenType = "token_type" + } } // MARK: - instantAvailability endpoint // Thanks Skitty! -public struct InstantAvailabilityResponse: Codable { - var data: InstantAvailabilityData? +public struct InstantAvailabilityResponse: Codable, Sendable { + var data: InstantAvailabilityData? - public init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() - if let data = try? container.decode(InstantAvailabilityData.self) { - self.data = data - } - } + if let data = try? container.decode(InstantAvailabilityData.self) { + self.data = data + } + } } -struct InstantAvailabilityData: Codable { - var rd: [[String: InstantAvailabilityInfo]] +struct InstantAvailabilityData: Codable, Sendable { + var rd: [[String: InstantAvailabilityInfo]] } -struct InstantAvailabilityInfo: Codable { - var filename: String - var filesize: Int +struct InstantAvailabilityInfo: Codable, Sendable { + var filename: String + var filesize: Int } // MARK: - Instant Availability client side structures -public struct RealDebridIA: Codable, Hashable { - let hash: String - let expiryTimeStamp: Double - var files: [RealDebridIAFile] = [] - var batches: [RealDebridIABatch] = [] +public struct RealDebridIA: Codable, Hashable, Sendable { + let hash: String + let expiryTimeStamp: Double + var files: [RealDebridIAFile] = [] + var batches: [RealDebridIABatch] = [] } -public struct RealDebridIABatch: Codable, Hashable { - let files: [RealDebridIABatchFile] +public struct RealDebridIABatch: Codable, Hashable, Sendable { + let files: [RealDebridIABatchFile] } -public struct RealDebridIABatchFile: Codable, Hashable { - let id: Int - let fileName: String +public struct RealDebridIABatchFile: Codable, Hashable, Sendable { + let id: Int + let fileName: String } -public struct RealDebridIAFile: Codable, Hashable { - let name: String - let batchIndex: Int - let batchFileIndex: Int +public struct RealDebridIAFile: Codable, Hashable, Sendable { + let name: String + let batchIndex: Int + let batchFileIndex: Int } -public enum RealDebridIAStatus: Codable, Hashable { - case full - case partial - case none +public enum RealDebridIAStatus: Codable, Hashable, Sendable { + case full + case partial + case none } // MARK: - addMagnet endpoint -public struct AddMagnetResponse: Codable { - let id: String - let uri: String +public struct AddMagnetResponse: Codable, Sendable { + let id: String + let uri: String } // MARK: - torrentInfo endpoint -struct TorrentInfoResponse: Codable { - let id, filename, originalFilename, hash: String - let bytes, originalBytes: Int - let host: String - let split, progress: Int - let status, added: String - let files: [TorrentInfoFile] - let links: [String] - let ended: String? - let speed: Int? - let seeders: Int? +struct TorrentInfoResponse: Codable, Sendable { + let id, filename, originalFilename, hash: String + let bytes, originalBytes: Int + let host: String + let split, progress: Int + let status, added: String + let files: [TorrentInfoFile] + let links: [String] + let ended: String? + let speed: Int? + let seeders: Int? - enum CodingKeys: String, CodingKey { - case id, filename - case originalFilename = "original_filename" - case hash, bytes - case originalBytes = "original_bytes" - case host, split, progress, status, added, files, links, ended, speed, seeders - } + enum CodingKeys: String, CodingKey { + case id, filename + case originalFilename = "original_filename" + case hash, bytes + case originalBytes = "original_bytes" + case host, split, progress, status, added, files, links, ended, speed, seeders + } } -struct TorrentInfoFile: Codable { - let id: Int - let path: String - let bytes, selected: Int +struct TorrentInfoFile: Codable, Sendable { + let id: Int + let path: String + let bytes, selected: Int } -public struct UserTorrentsResponse: Codable { +public struct UserTorrentsResponse: Codable, Sendable { let id, filename, hash: String let bytes: Int let host: String @@ -154,26 +154,26 @@ public struct UserTorrentsResponse: Codable { // MARK: - unrestrictLink endpoint -struct UnrestrictLinkResponse: Codable { - let id, filename, mimeType: String - let filesize: Int - let link: String - let host: String - let hostIcon: String - let chunks, crc: Int - let download: String - let streamable: Int +struct UnrestrictLinkResponse: Codable, Sendable { + let id, filename, mimeType: String + let filesize: Int + let link: String + let host: String + let hostIcon: String + let chunks, crc: Int + let download: String + let streamable: Int - enum CodingKeys: String, CodingKey { - case id, filename, mimeType, filesize, link, host - case hostIcon = "host_icon" - case chunks, crc, download, streamable - } + enum CodingKeys: String, CodingKey { + case id, filename, mimeType, filesize, link, host + case hostIcon = "host_icon" + case chunks, crc, download, streamable + } } // MARK: - User downloads list -public struct UserDownloadsResponse: Codable { +public struct UserDownloadsResponse: Codable, Sendable { let id, filename, mimeType: String let filesize: Int let link: String diff --git a/Ferrite/Models/SearchModels.swift b/Ferrite/Models/SearchModels.swift index 2751a82..4f7fb59 100644 --- a/Ferrite/Models/SearchModels.swift +++ b/Ferrite/Models/SearchModels.swift @@ -7,7 +7,7 @@ import Foundation -public struct SearchResult: Hashable, Codable { +public struct SearchResult: Hashable, Codable, Sendable { let title: String? let source: String let size: String? diff --git a/Ferrite/Models/SourceModels.swift b/Ferrite/Models/SourceModels.swift index 558af84..8cf3221 100644 --- a/Ferrite/Models/SourceModels.swift +++ b/Ferrite/Models/SourceModels.swift @@ -7,18 +7,18 @@ import Foundation -public enum ApiCredentialResponseType: String, Codable, Hashable { +public enum ApiCredentialResponseType: String, Codable, Hashable, Sendable { case json case text } -public struct SourceListJson: Codable { +public struct SourceListJson: Codable, Sendable { let name: String let author: String var sources: [SourceJson] } -public struct SourceJson: Codable, Hashable { +public struct SourceJson: Codable, Hashable, Sendable { let name: String let version: Int16 let minVersion: String? @@ -34,20 +34,20 @@ public struct SourceJson: Codable, Hashable { let htmlParser: SourceHtmlParserJson? } -public enum SourcePreferredParser: Int16, CaseIterable { +public enum SourcePreferredParser: Int16, CaseIterable, Sendable { // case none = 0 case scraping = 1 case rss = 2 case siteApi = 3 } -public struct SourceApiJson: Codable, Hashable { +public struct SourceApiJson: Codable, Hashable, Sendable { let apiUrl: String? let clientId: SourceApiCredentialJson? let clientSecret: SourceApiCredentialJson? } -public struct SourceApiCredentialJson: Codable, Hashable { +public struct SourceApiCredentialJson: Codable, Hashable, Sendable { let query: String? let value: String? let dynamic: Bool? @@ -56,7 +56,7 @@ public struct SourceApiCredentialJson: Codable, Hashable { let expiryLength: Double? } -public struct SourceJsonParserJson: Codable, Hashable { +public struct SourceJsonParserJson: Codable, Hashable, Sendable { let searchUrl: String let results: String? let subResults: String? @@ -67,7 +67,7 @@ public struct SourceJsonParserJson: Codable, Hashable { let sl: SourceSLJson? } -public struct SourceRssParserJson: Codable, Hashable { +public struct SourceRssParserJson: Codable, Hashable, Sendable { let rssUrl: String? let searchUrl: String let items: String @@ -78,7 +78,7 @@ public struct SourceRssParserJson: Codable, Hashable { let sl: SourceSLJson? } -public struct SourceHtmlParserJson: Codable, Hashable { +public struct SourceHtmlParserJson: Codable, Hashable, Sendable { let searchUrl: String let rows: String let magnet: SourceMagnetJson @@ -87,21 +87,21 @@ public struct SourceHtmlParserJson: Codable, Hashable { let sl: SourceSLJson? } -public struct SouceComplexQueryJson: Codable, Hashable { +public struct SouceComplexQueryJson: Codable, Hashable, Sendable { let query: String let discriminator: String? let attribute: String? let regex: String? } -public struct SourceMagnetJson: Codable, Hashable { +public struct SourceMagnetJson: Codable, Hashable, Sendable { let query: String let attribute: String let regex: String? let externalLinkQuery: String? } -public struct SourceSLJson: Codable, Hashable { +public struct SourceSLJson: Codable, Hashable, Sendable { let seeders: String? let leechers: String? let combined: String? diff --git a/Ferrite/ViewModels/DebridManager.swift b/Ferrite/ViewModels/DebridManager.swift index fc6457e..42ccccd 100644 --- a/Ferrite/ViewModels/DebridManager.swift +++ b/Ferrite/ViewModels/DebridManager.swift @@ -174,7 +174,7 @@ public class DebridManager: ObservableObject { // If the links match from a user's downloads, no need to re-run a download if let existingTorrent = existingTorrents[safe: 0], - let torrentLink = existingTorrent.links[safe: selectedRealDebridFile?.batchFileIndex ?? 0] + let torrentLink = existingTorrent.links[safe: selectedRealDebridFile?.batchFileIndex ?? 0] { let existingLinks = try await realDebrid.userDownloads().filter { $0.link == torrentLink } if let existingLink = existingLinks[safe: 0]?.download { diff --git a/Ferrite/ViewModels/SourceManager.swift b/Ferrite/ViewModels/SourceManager.swift index 2484bfb..8c8d0e2 100644 --- a/Ferrite/ViewModels/SourceManager.swift +++ b/Ferrite/ViewModels/SourceManager.swift @@ -1,5 +1,5 @@ // -// SourceViewModel.swift +// SourceManager.swift // Ferrite // // Created by Brian Dashore on 7/25/22. @@ -75,7 +75,7 @@ public class SourceManager: ObservableObject { return true } - return UIApplication.shared.appVersion >= minVersion + return Application.shared.appVersion >= minVersion } // Fetches sources using the background context diff --git a/Ferrite/Views/AboutView.swift b/Ferrite/Views/AboutView.swift index 2933955..1b1bed5 100644 --- a/Ferrite/Views/AboutView.swift +++ b/Ferrite/Views/AboutView.swift @@ -11,9 +11,9 @@ struct AboutView: View { var body: some View { List { Section { - ListRowTextView(leftText: "Version", rightText: UIApplication.shared.appVersion) - ListRowTextView(leftText: "Build number", rightText: UIApplication.shared.appBuild) - ListRowTextView(leftText: "Build type", rightText: UIApplication.shared.buildType) + ListRowTextView(leftText: "Version", rightText: Application.shared.appVersion) + ListRowTextView(leftText: "Build number", rightText: Application.shared.appBuild) + ListRowTextView(leftText: "Build type", rightText: Application.shared.buildType) ListRowLinkView(text: "Discord server", link: "https://discord.gg/sYQxnuD7Fj") ListRowLinkView(text: "GitHub repository", link: "https://github.com/bdashore3/Ferrite") } header: { diff --git a/Ferrite/Views/CommonViews/AlertButton.swift b/Ferrite/Views/CommonViews/AlertButton.swift index 8d6922e..19cf66d 100644 --- a/Ferrite/Views/CommonViews/AlertButton.swift +++ b/Ferrite/Views/CommonViews/AlertButton.swift @@ -4,6 +4,8 @@ // // Created by Brian Dashore on 9/8/22. // +// Universal alert button for dynamic alert views +// import SwiftUI @@ -20,7 +22,7 @@ struct AlertButton: Identifiable { // Used for all buttons init(_ label: String, role: Role? = nil, action: @escaping () -> Void) { - self.id = UUID() + id = UUID() self.label = label self.action = action self.role = role @@ -28,19 +30,19 @@ struct AlertButton: Identifiable { // Used for buttons with no action init(_ label: String = "Cancel", role: Role? = nil) { - self.id = UUID() + id = UUID() self.label = label - self.action = { } + action = {} self.role = role } func toActionButton() -> Alert.Button { if let role = role { switch role { - case .cancel: - return .cancel(Text(label)) - case .destructive: - return .destructive(Text(label), action: action) + case .cancel: + return .cancel(Text(label)) + case .destructive: + return .destructive(Text(label), action: action) } } else { return .default(Text(label), action: action) diff --git a/Ferrite/Views/CommonViews/DynamicFetchRequest.swift b/Ferrite/Views/CommonViews/DynamicFetchRequest.swift index 02ccac8..145addb 100644 --- a/Ferrite/Views/CommonViews/DynamicFetchRequest.swift +++ b/Ferrite/Views/CommonViews/DynamicFetchRequest.swift @@ -4,6 +4,9 @@ // // Created by Brian Dashore on 9/6/22. // +// Used for FetchRequests with a dynamic predicate +// iOS 14 compatible view +// import CoreData import SwiftUI diff --git a/Ferrite/Views/CommonViews/GroupBoxStyle.swift b/Ferrite/Views/CommonViews/GroupBoxStyle.swift deleted file mode 100644 index 6398a3b..0000000 --- a/Ferrite/Views/CommonViews/GroupBoxStyle.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// GroupBoxStyle.swift -// Ferrite -// -// Created by Brian Dashore on 7/21/22. -// - -import SwiftUI - -struct ErrorGroupBoxStyle: GroupBoxStyle { - func makeBody(configuration: Configuration) -> some View { - VStack { - configuration.label - configuration.content - } - .padding(10) - .background(Color(UIColor.secondarySystemGroupedBackground)) - .clipShape(RoundedRectangle(cornerRadius: 8, style: .continuous)) - } -} diff --git a/Ferrite/Views/CommonViews/ListRowViews.swift b/Ferrite/Views/CommonViews/ListRowViews.swift index 770c4be..80e736f 100644 --- a/Ferrite/Views/CommonViews/ListRowViews.swift +++ b/Ferrite/Views/CommonViews/ListRowViews.swift @@ -4,11 +4,11 @@ // // Created by Brian Dashore on 7/26/22. // +// List row button, text, and link boilerplate +// import SwiftUI -// These views were imported from Asobi -// View alias for a list row with an external link struct ListRowLinkView: View { let text: String let link: String diff --git a/Ferrite/Views/CommonViews/ConditionalContextMenu.swift b/Ferrite/Views/CommonViews/Modifiers/ConditionalContextMenu.swift similarity index 100% rename from Ferrite/Views/CommonViews/ConditionalContextMenu.swift rename to Ferrite/Views/CommonViews/Modifiers/ConditionalContextMenu.swift diff --git a/Ferrite/Views/CommonViews/ConditionalId.swift b/Ferrite/Views/CommonViews/Modifiers/ConditionalId.swift similarity index 91% rename from Ferrite/Views/CommonViews/ConditionalId.swift rename to Ferrite/Views/CommonViews/Modifiers/ConditionalId.swift index 53a033d..146f87f 100644 --- a/Ferrite/Views/CommonViews/ConditionalId.swift +++ b/Ferrite/Views/CommonViews/Modifiers/ConditionalId.swift @@ -4,7 +4,7 @@ // // Created by Brian Dashore on 9/4/22. // -// Only applies an ID for below iOS 16 +// Applies an ID below iOS 16 // This is due to ID workarounds making iOS 16 apps crash // diff --git a/Ferrite/Views/CommonViews/DisableInteraction.swift b/Ferrite/Views/CommonViews/Modifiers/DisableInteraction.swift similarity index 87% rename from Ferrite/Views/CommonViews/DisableInteraction.swift rename to Ferrite/Views/CommonViews/Modifiers/DisableInteraction.swift index a8073d8..97d428c 100644 --- a/Ferrite/Views/CommonViews/DisableInteraction.swift +++ b/Ferrite/Views/CommonViews/Modifiers/DisableInteraction.swift @@ -4,7 +4,7 @@ // // Created by Brian Dashore on 9/13/22. // -// Disables interaction without applying the appearance +// Disables interaction on any view without applying the appearance // import SwiftUI diff --git a/Ferrite/Views/CommonViews/DisabledAppearance.swift b/Ferrite/Views/CommonViews/Modifiers/DisabledAppearance.swift similarity index 89% rename from Ferrite/Views/CommonViews/DisabledAppearance.swift rename to Ferrite/Views/CommonViews/Modifiers/DisabledAppearance.swift index 132d23e..1caeaf6 100644 --- a/Ferrite/Views/CommonViews/DisabledAppearance.swift +++ b/Ferrite/Views/CommonViews/Modifiers/DisabledAppearance.swift @@ -4,6 +4,8 @@ // // Created by Brian Dashore on 9/10/22. // +// Adds opacity transitions to the disabled modifier +// import SwiftUI diff --git a/Ferrite/Views/CommonViews/DynamicAccentColor.swift b/Ferrite/Views/CommonViews/Modifiers/DynamicAccentColor.swift similarity index 80% rename from Ferrite/Views/CommonViews/DynamicAccentColor.swift rename to Ferrite/Views/CommonViews/Modifiers/DynamicAccentColor.swift index 02a2e79..ab1fd3c 100644 --- a/Ferrite/Views/CommonViews/DynamicAccentColor.swift +++ b/Ferrite/Views/CommonViews/Modifiers/DynamicAccentColor.swift @@ -1,9 +1,11 @@ // -// dynamicAccentColor.swift +// DynamicAccentColor.swift // Ferrite // // Created by Brian Dashore on 8/15/22. // +// Wrapper that switches between tint and accentColor +// import SwiftUI diff --git a/Ferrite/Views/CommonViews/DynamicActionSheet.swift b/Ferrite/Views/CommonViews/Modifiers/DynamicActionSheet.swift similarity index 92% rename from Ferrite/Views/CommonViews/DynamicActionSheet.swift rename to Ferrite/Views/CommonViews/Modifiers/DynamicActionSheet.swift index 9e2a3c5..9d9d4dd 100644 --- a/Ferrite/Views/CommonViews/DynamicActionSheet.swift +++ b/Ferrite/Views/CommonViews/Modifiers/DynamicActionSheet.swift @@ -4,6 +4,8 @@ // // Created by Brian Dashore on 9/8/22. // +// Switches between confirmationDialog and actionSheet +// import SwiftUI @@ -36,7 +38,7 @@ struct DynamicActionSheet: ViewModifier { ActionSheet( title: Text(title), message: message.map { Text($0) } ?? nil, - buttons: [buttons.map { $0.toActionButton() }, [.cancel()]].flatMap{ $0 } + buttons: [buttons.map { $0.toActionButton() }, [.cancel()]].flatMap { $0 } ) } } diff --git a/Ferrite/Views/CommonViews/DynamicAlert.swift b/Ferrite/Views/CommonViews/Modifiers/DynamicAlert.swift similarity index 96% rename from Ferrite/Views/CommonViews/DynamicAlert.swift rename to Ferrite/Views/CommonViews/Modifiers/DynamicAlert.swift index 2a15546..7f39cfe 100644 --- a/Ferrite/Views/CommonViews/DynamicAlert.swift +++ b/Ferrite/Views/CommonViews/Modifiers/DynamicAlert.swift @@ -4,6 +4,8 @@ // // Created by Brian Dashore on 9/8/22. // +// Switches between iOS 15 and 14 alert initalizers +// import SwiftUI diff --git a/Ferrite/Views/CommonViews/InlinedList.swift b/Ferrite/Views/CommonViews/Modifiers/InlinedList.swift similarity index 81% rename from Ferrite/Views/CommonViews/InlinedList.swift rename to Ferrite/Views/CommonViews/Modifiers/InlinedList.swift index a0eb034..3e2cac2 100644 --- a/Ferrite/Views/CommonViews/InlinedList.swift +++ b/Ferrite/Views/CommonViews/Modifiers/InlinedList.swift @@ -4,8 +4,8 @@ // // Created by Brian Dashore on 9/4/22. // -// Removes the top padding on lists for iOS 16 -// Use UITableView.appearance().contentInset.top = -20 for iOS 15 and below in the App file +// Removes the top padding on unsectioned lists +// If a list is sectioned, see InlineHeader // import Introspect diff --git a/Ferrite/Views/CommonViews/NavView.swift b/Ferrite/Views/CommonViews/NavView.swift index cd8ffd4..b89b95f 100644 --- a/Ferrite/Views/CommonViews/NavView.swift +++ b/Ferrite/Views/CommonViews/NavView.swift @@ -3,6 +3,9 @@ // Ferrite // // Created by Brian Dashore on 7/4/22. +// Contributed by Mantton +// +// A wrapper that switches between NavigationStack and the legacy NavigationView // import SwiftUI diff --git a/Ferrite/Views/LibraryView.swift b/Ferrite/Views/LibraryView.swift index 90d560e..3d1b88e 100644 --- a/Ferrite/Views/LibraryView.swift +++ b/Ferrite/Views/LibraryView.swift @@ -1,5 +1,5 @@ // -// Library.swift +// LibraryView.swift // Ferrite // // Created by Brian Dashore on 9/2/22. diff --git a/Ferrite/Views/LibraryViews/BookmarksView.swift b/Ferrite/Views/LibraryViews/BookmarksView.swift index 3ed4b51..aea6c9e 100644 --- a/Ferrite/Views/LibraryViews/BookmarksView.swift +++ b/Ferrite/Views/LibraryViews/BookmarksView.swift @@ -37,7 +37,7 @@ struct BookmarksView: View { } } } - .onMove { (source, destination) in + .onMove { source, destination in var changedBookmarks = bookmarks.map { $0 } changedBookmarks.move(fromOffsets: source, toOffset: destination) @@ -56,7 +56,7 @@ struct BookmarksView: View { .onAppear { if realDebridEnabled { viewTask = Task { - let hashes = bookmarks.compactMap { $0.magnetHash } + let hashes = bookmarks.compactMap(\.magnetHash) await debridManager.populateDebridHashes(hashes) } } diff --git a/Ferrite/Views/LibraryViews/HistoryButtonView.swift b/Ferrite/Views/LibraryViews/HistoryButtonView.swift index cf607c3..681f970 100644 --- a/Ferrite/Views/LibraryViews/HistoryButtonView.swift +++ b/Ferrite/Views/LibraryViews/HistoryButtonView.swift @@ -21,7 +21,7 @@ struct HistoryButtonView: View { Task { debridManager.realDebridDownloadUrl = url navModel.runDebridAction(urlString: url) - + if navModel.currentChoiceSheet != .magnet { debridManager.realDebridDownloadUrl = "" } @@ -37,19 +37,19 @@ struct HistoryButtonView: View { VStack(alignment: .leading, spacing: 3) { Text(entry.name ?? "Unknown title") .font(entry.subName == nil ? .body : .subheadline) - + if let subName = entry.subName { Text(subName) .foregroundColor(.gray) .font(.subheadline) } } - + HStack { Text(entry.source ?? "Unknown source") - + Spacer() - + Text("DEBRID") .fontWeight(.bold) .padding(3) diff --git a/Ferrite/Views/MagnetChoiceView.swift b/Ferrite/Views/MagnetChoiceView.swift index 4ab9ab2..bc78d43 100644 --- a/Ferrite/Views/MagnetChoiceView.swift +++ b/Ferrite/Views/MagnetChoiceView.swift @@ -42,7 +42,7 @@ struct MagnetChoiceView: View { showLinkCopyAlert.toggle() } .dynamicAlert( - isPresented: $showLinkCopyAlert , + isPresented: $showLinkCopyAlert, title: "Copied", message: "Download link copied successfully", buttons: [AlertButton("OK")] diff --git a/Ferrite/Views/MainView.swift b/Ferrite/Views/MainView.swift index 3e20efc..3cc2399 100644 --- a/Ferrite/Views/MainView.swift +++ b/Ferrite/Views/MainView.swift @@ -71,7 +71,7 @@ struct MainView: View { } let releaseVersion = String(latestRelease.tagName.dropFirst()) - if releaseVersion > UIApplication.shared.appVersion { + if releaseVersion > Application.shared.appVersion { releaseVersionString = latestRelease.tagName releaseUrlString = latestRelease.htmlUrl showUpdateAlert.toggle() diff --git a/Ferrite/Views/RepresentableViews/WebView.swift b/Ferrite/Views/RepresentableViews/WebView.swift index 89301bb..9ef07fd 100644 --- a/Ferrite/Views/RepresentableViews/WebView.swift +++ b/Ferrite/Views/RepresentableViews/WebView.swift @@ -13,7 +13,7 @@ struct WebView: UIViewRepresentable { func makeUIView(context: Context) -> WKWebView { let webView = WKWebView() - webView.load(URLRequest(url: url)) + let _ = webView.load(URLRequest(url: url)) return webView } diff --git a/Ferrite/Views/SearchResultButtonView.swift b/Ferrite/Views/SearchResultViews/SearchResultButtonView.swift similarity index 97% rename from Ferrite/Views/SearchResultButtonView.swift rename to Ferrite/Views/SearchResultViews/SearchResultButtonView.swift index e4b6e82..cb177e8 100644 --- a/Ferrite/Views/SearchResultButtonView.swift +++ b/Ferrite/Views/SearchResultViews/SearchResultButtonView.swift @@ -25,13 +25,13 @@ struct SearchResultButtonView: View { Button { if debridManager.currentDebridTask == nil { navModel.selectedSearchResult = result - + switch debridManager.matchSearchResult(result: result) { case .full: if debridManager.setSelectedRdResult(result: result) { debridManager.currentDebridTask = Task { await debridManager.fetchRdDownload(searchResult: result) - + if !debridManager.realDebridDownloadUrl.isEmpty { navModel.addToHistory(name: result.title, source: result.source, url: debridManager.realDebridDownloadUrl) navModel.runDebridAction(urlString: debridManager.realDebridDownloadUrl) @@ -83,9 +83,9 @@ struct SearchResultButtonView: View { newBookmark.magnetLink = result.magnetLink newBookmark.seeders = result.seeders newBookmark.leechers = result.leechers - + existingBookmark = newBookmark - + PersistenceController.shared.save(backgroundContext) } label: { Text("Bookmark") @@ -111,7 +111,7 @@ struct SearchResultButtonView: View { } .onAppear { // Only run a exists request if a bookmark isn't passed to the view - if existingBookmark == nil && !runOnce { + if existingBookmark == nil, !runOnce { let bookmarkRequest = Bookmark.fetchRequest() bookmarkRequest.predicate = NSPredicate( format: "title == %@ AND source == %@ AND magnetLink == %@ AND magnetHash = %@", diff --git a/Ferrite/Views/SearchResultRDView.swift b/Ferrite/Views/SearchResultViews/SearchResultRDView.swift similarity index 100% rename from Ferrite/Views/SearchResultRDView.swift rename to Ferrite/Views/SearchResultViews/SearchResultRDView.swift diff --git a/Ferrite/Views/SourceViews/InstalledSourceView.swift b/Ferrite/Views/SourceViews/Buttons/InstalledSourceButtonView.swift similarity index 95% rename from Ferrite/Views/SourceViews/InstalledSourceView.swift rename to Ferrite/Views/SourceViews/Buttons/InstalledSourceButtonView.swift index 88065f3..3564629 100644 --- a/Ferrite/Views/SourceViews/InstalledSourceView.swift +++ b/Ferrite/Views/SourceViews/Buttons/InstalledSourceButtonView.swift @@ -1,5 +1,5 @@ // -// InstalledSourceView.swift +// InstalledSourceButtonView.swift // Ferrite // // Created by Brian Dashore on 8/5/22. @@ -7,7 +7,7 @@ import SwiftUI -struct InstalledSourceView: View { +struct InstalledSourceButtonView: View { let backgroundContext = PersistenceController.shared.backgroundContext @EnvironmentObject var navModel: NavigationViewModel diff --git a/Ferrite/Views/SourceViews/SourceCatalogView.swift b/Ferrite/Views/SourceViews/Buttons/SourceCatalogButtonView.swift similarity index 100% rename from Ferrite/Views/SourceViews/SourceCatalogView.swift rename to Ferrite/Views/SourceViews/Buttons/SourceCatalogButtonView.swift diff --git a/Ferrite/Views/SourceViews/SourceUpdateButtonView.swift b/Ferrite/Views/SourceViews/Buttons/SourceUpdateButtonView.swift similarity index 100% rename from Ferrite/Views/SourceViews/SourceUpdateButtonView.swift rename to Ferrite/Views/SourceViews/Buttons/SourceUpdateButtonView.swift diff --git a/Ferrite/Views/SourcesView.swift b/Ferrite/Views/SourcesView.swift index c57e8f5..aa60a27 100644 --- a/Ferrite/Views/SourcesView.swift +++ b/Ferrite/Views/SourcesView.swift @@ -50,7 +50,7 @@ struct SourcesView: View { if !installedSources.isEmpty { Section(header: InlineHeader("Installed")) { ForEach(installedSources, id: \.self) { source in - InstalledSourceView(installedSource: source) + InstalledSourceButtonView(installedSource: source) } } }