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 <bdashore3@proton.me>
This commit is contained in:
parent
b85752c92c
commit
a89e832d1c
41 changed files with 304 additions and 292 deletions
|
|
@ -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 = "<group>"; };
|
||||
0C31133B28B1ABFA004DCB0D /* SourceJsonParser+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SourceJsonParser+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
0C32FB522890D19D002BD219 /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = "<group>"; };
|
||||
0C32FB542890D1BF002BD219 /* UIApplication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIApplication.swift; sourceTree = "<group>"; };
|
||||
0C32FB562890D1F2002BD219 /* ListRowViews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRowViews.swift; sourceTree = "<group>"; };
|
||||
0C360C5B28C7DF1400884ED3 /* DynamicFetchRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicFetchRequest.swift; sourceTree = "<group>"; };
|
||||
0C391EC828CA63F0009F1CA1 /* DynamicActionSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicActionSheet.swift; sourceTree = "<group>"; };
|
||||
0C391ECA28CAA44B009F1CA1 /* AlertButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertButton.swift; sourceTree = "<group>"; };
|
||||
0C41BC6228C2AD0F00B47DD6 /* SearchResultButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultButtonView.swift; sourceTree = "<group>"; };
|
||||
0C41BC6428C2AEB900B47DD6 /* SearchModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchModels.swift; sourceTree = "<group>"; };
|
||||
0C44E2A728D4DDDC007711AE /* Application.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = "<group>"; };
|
||||
0C4CFC4728970C8B00AD9FAD /* SourceComplexQuery+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SourceComplexQuery+CoreDataClass.swift"; sourceTree = "<group>"; };
|
||||
0C4CFC4828970C8B00AD9FAD /* SourceComplexQuery+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SourceComplexQuery+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
0C54D36128C5086E00BFEEE2 /* History+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "History+CoreDataClass.swift"; sourceTree = "<group>"; };
|
||||
|
|
@ -131,8 +130,8 @@
|
|||
0C750743289B003E004B3906 /* SourceRssParser+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SourceRssParser+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
0C78041C28BFB3EA001E8CA3 /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = "<group>"; };
|
||||
0C794B66289DACB600DD1CC8 /* SourceUpdateButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceUpdateButtonView.swift; sourceTree = "<group>"; };
|
||||
0C794B68289DACC800DD1CC8 /* InstalledSourceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstalledSourceView.swift; sourceTree = "<group>"; };
|
||||
0C794B6A289DACF100DD1CC8 /* SourceCatalogView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceCatalogView.swift; sourceTree = "<group>"; };
|
||||
0C794B68289DACC800DD1CC8 /* InstalledSourceButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstalledSourceButtonView.swift; sourceTree = "<group>"; };
|
||||
0C794B6A289DACF100DD1CC8 /* SourceCatalogButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceCatalogButtonView.swift; sourceTree = "<group>"; };
|
||||
0C794B6C289EFA2E00DD1CC8 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
0C79DC052899AF3C003F1C5A /* SourceSeedLeech+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SourceSeedLeech+CoreDataClass.swift"; sourceTree = "<group>"; };
|
||||
0C79DC062899AF3C003F1C5A /* SourceSeedLeech+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SourceSeedLeech+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
|
|
@ -188,7 +187,6 @@
|
|||
0CD4CAC528C980EB0046E1DC /* HistoryActionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryActionsView.swift; sourceTree = "<group>"; };
|
||||
0CD5E78828CD932B001BF684 /* DisabledAppearance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisabledAppearance.swift; sourceTree = "<group>"; };
|
||||
0CDCB91728C662640098B513 /* EmptyInstructionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyInstructionView.swift; sourceTree = "<group>"; };
|
||||
0CFEFCFC288A006200B3F490 /* GroupBoxStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupBoxStyle.swift; sourceTree = "<group>"; };
|
||||
/* 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 = "<group>";
|
||||
};
|
||||
0C44E2A628D4DDC6007711AE /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0C44E2A728D4DDDC007711AE /* Application.swift */,
|
||||
);
|
||||
path = Classes;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
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 = "<group>";
|
||||
};
|
||||
0C44E2AA28D4E09B007711AE /* Buttons */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0C794B68289DACC800DD1CC8 /* InstalledSourceButtonView.swift */,
|
||||
0C794B6A289DACF100DD1CC8 /* SourceCatalogButtonView.swift */,
|
||||
0C794B66289DACB600DD1CC8 /* SourceUpdateButtonView.swift */,
|
||||
);
|
||||
path = Buttons;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0C44E2AB28D4E126007711AE /* SearchResultViews */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0C41BC6228C2AD0F00B47DD6 /* SearchResultButtonView.swift */,
|
||||
0C57D4CB289032ED008534E8 /* SearchResultRDView.swift */,
|
||||
);
|
||||
path = SearchResultViews;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0C794B65289DAC9F00DD1CC8 /* SourceViews */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0C44E2AA28D4E09B007711AE /* Buttons */,
|
||||
0C733286289C4C820058D1FE /* SourceSettingsView.swift */,
|
||||
0C794B66289DACB600DD1CC8 /* SourceUpdateButtonView.swift */,
|
||||
0C794B68289DACC800DD1CC8 /* InstalledSourceView.swift */,
|
||||
0C794B6A289DACF100DD1CC8 /* SourceCatalogView.swift */,
|
||||
);
|
||||
path = SourceViews;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -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 = "<group>";
|
||||
|
|
@ -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 = "<group>";
|
||||
|
|
@ -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 = "<group>";
|
||||
|
|
@ -379,8 +408,8 @@
|
|||
0CA148F12889066000DE2211 /* API */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0CA148D0288903F000DE2211 /* RealDebridWrapper.swift */,
|
||||
0C68134F28BC1A2D00FAD890 /* GithubWrapper.swift */,
|
||||
0CA148D0288903F000DE2211 /* RealDebridWrapper.swift */,
|
||||
);
|
||||
path = API;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -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 */,
|
||||
|
|
|
|||
|
|
@ -255,7 +255,8 @@ public class RealDebrid {
|
|||
hash: hash,
|
||||
expiryTimeStamp: Date().timeIntervalSince1970 + 300,
|
||||
files: files,
|
||||
batches: batches)
|
||||
batches: batches
|
||||
)
|
||||
)
|
||||
} else {
|
||||
availableHashes.append(
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
|
|
@ -6,27 +6,22 @@
|
|||
//
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
import Foundation
|
||||
|
||||
|
||||
extension Bookmark {
|
||||
|
||||
@nonobjc public class func fetchRequest() -> NSFetchRequest<Bookmark> {
|
||||
return NSFetchRequest<Bookmark>(entityName: "Bookmark")
|
||||
public extension Bookmark {
|
||||
@nonobjc class func fetchRequest() -> NSFetchRequest<Bookmark> {
|
||||
NSFetchRequest<Bookmark>(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 {}
|
||||
|
|
|
|||
|
|
@ -6,10 +6,8 @@
|
|||
//
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
import Foundation
|
||||
|
||||
@objc(History)
|
||||
public class History: NSManagedObject {
|
||||
|
||||
}
|
||||
public class History: NSManagedObject {}
|
||||
|
|
|
|||
|
|
@ -6,21 +6,19 @@
|
|||
//
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
import Foundation
|
||||
|
||||
|
||||
extension History {
|
||||
|
||||
@nonobjc public class func fetchRequest() -> NSFetchRequest<History> {
|
||||
return NSFetchRequest<History>(entityName: "History")
|
||||
public extension History {
|
||||
@nonobjc class func fetchRequest() -> NSFetchRequest<History> {
|
||||
NSFetchRequest<History>(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<HistoryEntry> ?? []
|
||||
|
||||
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 {}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -9,6 +9,6 @@ import Foundation
|
|||
|
||||
extension Notification.Name {
|
||||
static var didDeleteBookmark: Notification.Name {
|
||||
return Notification.Name("Deleted bookmark")
|
||||
Notification.Name("Deleted bookmark")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,8 +25,10 @@ extension View {
|
|||
|
||||
// MARK: Modifiers
|
||||
|
||||
func dynamicAccentColor(_ color: Color) -> some View {
|
||||
modifier(DynamicAccentColor(color: color))
|
||||
func conditionalContextMenu<InternalContent: View, ID: Hashable>(id: ID,
|
||||
@ViewBuilder _ internalContent: @escaping () -> InternalContent) -> some View
|
||||
{
|
||||
modifier(ConditionalContextMenu(internalContent, id: id))
|
||||
}
|
||||
|
||||
func conditionalId<ID: Hashable>(_ 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<InternalContent: View, ID: Hashable>(
|
||||
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<Bool>,
|
||||
title: String,
|
||||
message: String? = nil,
|
||||
buttons: [AlertButton]) -> some View
|
||||
func dynamicActionSheet(isPresented: Binding<Bool>,
|
||||
title: String,
|
||||
message: String? = nil,
|
||||
buttons: [AlertButton]) -> some View
|
||||
{
|
||||
modifier(DynamicActionSheet(isPresented: isPresented, title: title, message: message, buttons: buttons))
|
||||
}
|
||||
|
||||
func dynamicAlert(
|
||||
isPresented: Binding<Bool>,
|
||||
title: String,
|
||||
message: String? = nil,
|
||||
buttons: [AlertButton]) -> some View
|
||||
func dynamicAlert(isPresented: Binding<Bool>,
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
public struct GithubRelease: Codable, Hashable {
|
||||
public struct GithubRelease: Codable, Hashable, Sendable {
|
||||
let htmlUrl: String
|
||||
let tagName: String
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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: {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -4,6 +4,8 @@
|
|||
//
|
||||
// Created by Brian Dashore on 9/10/22.
|
||||
//
|
||||
// Adds opacity transitions to the disabled modifier
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,8 @@
|
|||
//
|
||||
// Created by Brian Dashore on 9/8/22.
|
||||
//
|
||||
// Switches between iOS 15 and 14 alert initalizers
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// Library.swift
|
||||
// LibraryView.swift
|
||||
// Ferrite
|
||||
//
|
||||
// Created by Brian Dashore on 9/2/22.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ struct MagnetChoiceView: View {
|
|||
showLinkCopyAlert.toggle()
|
||||
}
|
||||
.dynamicAlert(
|
||||
isPresented: $showLinkCopyAlert ,
|
||||
isPresented: $showLinkCopyAlert,
|
||||
title: "Copied",
|
||||
message: "Download link copied successfully",
|
||||
buttons: [AlertButton("OK")]
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 = %@",
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue