Ferrite: WIP iOS 14 backport

Signed-off-by: kingbri <bdashore3@gmail.com>
This commit is contained in:
kingbri 2022-08-14 21:36:34 -04:00 committed by Brian Dashore
parent 9b12671a97
commit d7d01465d8
15 changed files with 209 additions and 131 deletions

View file

@ -20,6 +20,7 @@
0C64A4B4288903680079976D /* Base32 in Frameworks */ = {isa = PBXBuildFile; productRef = 0C64A4B3288903680079976D /* Base32 */; }; 0C64A4B4288903680079976D /* Base32 in Frameworks */ = {isa = PBXBuildFile; productRef = 0C64A4B3288903680079976D /* Base32 */; };
0C64A4B7288903880079976D /* KeychainSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 0C64A4B6288903880079976D /* KeychainSwift */; }; 0C64A4B7288903880079976D /* KeychainSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 0C64A4B6288903880079976D /* KeychainSwift */; };
0C733287289C4C820058D1FE /* SourceSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C733286289C4C820058D1FE /* SourceSettingsView.swift */; }; 0C733287289C4C820058D1FE /* SourceSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C733286289C4C820058D1FE /* SourceSettingsView.swift */; };
0C7376F028A97D1400D60918 /* SwiftUIX in Frameworks */ = {isa = PBXBuildFile; productRef = 0C7376EF28A97D1400D60918 /* SwiftUIX */; };
0C750744289B003E004B3906 /* SourceRssParser+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C750742289B003E004B3906 /* SourceRssParser+CoreDataClass.swift */; }; 0C750744289B003E004B3906 /* SourceRssParser+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C750742289B003E004B3906 /* SourceRssParser+CoreDataClass.swift */; };
0C750745289B003E004B3906 /* SourceRssParser+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C750743289B003E004B3906 /* SourceRssParser+CoreDataProperties.swift */; }; 0C750745289B003E004B3906 /* SourceRssParser+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C750743289B003E004B3906 /* SourceRssParser+CoreDataProperties.swift */; };
0C794B67289DACB600DD1CC8 /* SourceUpdateButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C794B66289DACB600DD1CC8 /* SourceUpdateButtonView.swift */; }; 0C794B67289DACB600DD1CC8 /* SourceUpdateButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C794B66289DACB600DD1CC8 /* SourceUpdateButtonView.swift */; };
@ -28,6 +29,8 @@
0C794B6D289EFA2E00DD1CC8 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0C794B6C289EFA2E00DD1CC8 /* LaunchScreen.storyboard */; }; 0C794B6D289EFA2E00DD1CC8 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0C794B6C289EFA2E00DD1CC8 /* LaunchScreen.storyboard */; };
0C79DC072899AF3C003F1C5A /* SourceSeedLeech+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C79DC052899AF3C003F1C5A /* SourceSeedLeech+CoreDataClass.swift */; }; 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 */; }; 0C79DC082899AF3C003F1C5A /* SourceSeedLeech+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C79DC062899AF3C003F1C5A /* SourceSeedLeech+CoreDataProperties.swift */; };
0C7D11FC28AA01E900ED92DB /* DynamicAccentColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C7D11FB28AA01E900ED92DB /* DynamicAccentColor.swift */; };
0C7D11FE28AA03FE00ED92DB /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C7D11FD28AA03FE00ED92DB /* View.swift */; };
0C84F4772895BE680074B7C9 /* FerriteDB.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 0C84F4752895BE680074B7C9 /* FerriteDB.xcdatamodeld */; }; 0C84F4772895BE680074B7C9 /* FerriteDB.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 0C84F4752895BE680074B7C9 /* FerriteDB.xcdatamodeld */; };
0C84F4822895BFED0074B7C9 /* Source+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C84F47A2895BFED0074B7C9 /* Source+CoreDataClass.swift */; }; 0C84F4822895BFED0074B7C9 /* Source+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C84F47A2895BFED0074B7C9 /* Source+CoreDataClass.swift */; };
0C84F4832895BFED0074B7C9 /* Source+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C84F47B2895BFED0074B7C9 /* Source+CoreDataProperties.swift */; }; 0C84F4832895BFED0074B7C9 /* Source+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C84F47B2895BFED0074B7C9 /* Source+CoreDataProperties.swift */; };
@ -35,7 +38,6 @@
0C84F4852895BFED0074B7C9 /* SourceHtmlParser+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C84F47D2895BFED0074B7C9 /* SourceHtmlParser+CoreDataProperties.swift */; }; 0C84F4852895BFED0074B7C9 /* SourceHtmlParser+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C84F47D2895BFED0074B7C9 /* SourceHtmlParser+CoreDataProperties.swift */; };
0C84F4862895BFED0074B7C9 /* SourceList+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C84F47E2895BFED0074B7C9 /* SourceList+CoreDataClass.swift */; }; 0C84F4862895BFED0074B7C9 /* SourceList+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C84F47E2895BFED0074B7C9 /* SourceList+CoreDataClass.swift */; };
0C84F4872895BFED0074B7C9 /* SourceList+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C84F47F2895BFED0074B7C9 /* SourceList+CoreDataProperties.swift */; }; 0C84F4872895BFED0074B7C9 /* SourceList+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C84F47F2895BFED0074B7C9 /* SourceList+CoreDataProperties.swift */; };
0C90E32C2888E5D000C0BC89 /* ActivityView in Frameworks */ = {isa = PBXBuildFile; productRef = 0C90E32B2888E5D000C0BC89 /* ActivityView */; };
0C95D8D828A55B03005E22B3 /* DefaultActionsPickerViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C95D8D728A55B03005E22B3 /* DefaultActionsPickerViews.swift */; }; 0C95D8D828A55B03005E22B3 /* DefaultActionsPickerViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C95D8D728A55B03005E22B3 /* DefaultActionsPickerViews.swift */; };
0C95D8DA28A55BB6005E22B3 /* SettingsModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C95D8D928A55BB6005E22B3 /* SettingsModels.swift */; }; 0C95D8DA28A55BB6005E22B3 /* SettingsModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C95D8D928A55BB6005E22B3 /* SettingsModels.swift */; };
0CA05457288EE58200850554 /* SettingsSourceListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CA05456288EE58200850554 /* SettingsSourceListView.swift */; }; 0CA05457288EE58200850554 /* SettingsSourceListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CA05456288EE58200850554 /* SettingsSourceListView.swift */; };
@ -88,6 +90,8 @@
0C794B6C289EFA2E00DD1CC8 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; 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>"; }; 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>"; }; 0C79DC062899AF3C003F1C5A /* SourceSeedLeech+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SourceSeedLeech+CoreDataProperties.swift"; sourceTree = "<group>"; };
0C7D11FB28AA01E900ED92DB /* DynamicAccentColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicAccentColor.swift; sourceTree = "<group>"; };
0C7D11FD28AA03FE00ED92DB /* View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = View.swift; sourceTree = "<group>"; };
0C84F4762895BE680074B7C9 /* FerriteDB.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = FerriteDB.xcdatamodel; sourceTree = "<group>"; }; 0C84F4762895BE680074B7C9 /* FerriteDB.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = FerriteDB.xcdatamodel; sourceTree = "<group>"; };
0C84F47A2895BFED0074B7C9 /* Source+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Source+CoreDataClass.swift"; sourceTree = "<group>"; }; 0C84F47A2895BFED0074B7C9 /* Source+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Source+CoreDataClass.swift"; sourceTree = "<group>"; };
0C84F47B2895BFED0074B7C9 /* Source+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Source+CoreDataProperties.swift"; sourceTree = "<group>"; }; 0C84F47B2895BFED0074B7C9 /* Source+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Source+CoreDataProperties.swift"; sourceTree = "<group>"; };
@ -134,9 +138,9 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
0C90E32C2888E5D000C0BC89 /* ActivityView in Frameworks */,
0C64A4B4288903680079976D /* Base32 in Frameworks */, 0C64A4B4288903680079976D /* Base32 in Frameworks */,
0C4CFC462897030D00AD9FAD /* Regex in Frameworks */, 0C4CFC462897030D00AD9FAD /* Regex in Frameworks */,
0C7376F028A97D1400D60918 /* SwiftUIX in Frameworks */,
0C64A4B7288903880079976D /* KeychainSwift in Frameworks */, 0C64A4B7288903880079976D /* KeychainSwift in Frameworks */,
0CAF1C7B286F5C8600296F86 /* SwiftSoup in Frameworks */, 0CAF1C7B286F5C8600296F86 /* SwiftSoup in Frameworks */,
); );
@ -221,6 +225,7 @@
0CA148C1288903F000DE2211 /* NavView.swift */, 0CA148C1288903F000DE2211 /* NavView.swift */,
0CFEFCFC288A006200B3F490 /* GroupBoxStyle.swift */, 0CFEFCFC288A006200B3F490 /* GroupBoxStyle.swift */,
0C32FB562890D1F2002BD219 /* ListRowViews.swift */, 0C32FB562890D1F2002BD219 /* ListRowViews.swift */,
0C7D11FB28AA01E900ED92DB /* DynamicAccentColor.swift */,
); );
path = CommonViews; path = CommonViews;
sourceTree = "<group>"; sourceTree = "<group>";
@ -240,6 +245,7 @@
0CA148CA288903F000DE2211 /* Data.swift */, 0CA148CA288903F000DE2211 /* Data.swift */,
0CA148CB288903F000DE2211 /* Task.swift */, 0CA148CB288903F000DE2211 /* Task.swift */,
0C32FB542890D1BF002BD219 /* UIApplication.swift */, 0C32FB542890D1BF002BD219 /* UIApplication.swift */,
0C7D11FD28AA03FE00ED92DB /* View.swift */,
); );
path = Extensions; path = Extensions;
sourceTree = "<group>"; sourceTree = "<group>";
@ -338,10 +344,10 @@
name = Ferrite; name = Ferrite;
packageProductDependencies = ( packageProductDependencies = (
0CAF1C7A286F5C8600296F86 /* SwiftSoup */, 0CAF1C7A286F5C8600296F86 /* SwiftSoup */,
0C90E32B2888E5D000C0BC89 /* ActivityView */,
0C64A4B3288903680079976D /* Base32 */, 0C64A4B3288903680079976D /* Base32 */,
0C64A4B6288903880079976D /* KeychainSwift */, 0C64A4B6288903880079976D /* KeychainSwift */,
0C4CFC452897030D00AD9FAD /* Regex */, 0C4CFC452897030D00AD9FAD /* Regex */,
0C7376EF28A97D1400D60918 /* SwiftUIX */,
); );
productName = Torrenter; productName = Torrenter;
productReference = 0CAF1C68286F5C0E00296F86 /* Ferrite.app */; productReference = 0CAF1C68286F5C0E00296F86 /* Ferrite.app */;
@ -373,10 +379,10 @@
mainGroup = 0CAF1C5F286F5C0D00296F86; mainGroup = 0CAF1C5F286F5C0D00296F86;
packageReferences = ( packageReferences = (
0CAF1C79286F5C8600296F86 /* XCRemoteSwiftPackageReference "SwiftSoup" */, 0CAF1C79286F5C8600296F86 /* XCRemoteSwiftPackageReference "SwiftSoup" */,
0C90E32A2888E5D000C0BC89 /* XCRemoteSwiftPackageReference "ActivityView" */,
0C64A4B2288903680079976D /* XCRemoteSwiftPackageReference "Base32" */, 0C64A4B2288903680079976D /* XCRemoteSwiftPackageReference "Base32" */,
0C64A4B5288903880079976D /* XCRemoteSwiftPackageReference "keychain-swift" */, 0C64A4B5288903880079976D /* XCRemoteSwiftPackageReference "keychain-swift" */,
0C4CFC442897030D00AD9FAD /* XCRemoteSwiftPackageReference "Regex" */, 0C4CFC442897030D00AD9FAD /* XCRemoteSwiftPackageReference "Regex" */,
0C7376EE28A97D1400D60918 /* XCRemoteSwiftPackageReference "SwiftUIX" */,
); );
productRefGroup = 0CAF1C69286F5C0E00296F86 /* Products */; productRefGroup = 0CAF1C69286F5C0E00296F86 /* Products */;
projectDirPath = ""; projectDirPath = "";
@ -419,6 +425,7 @@
0CBC76FD288D914F0054BE44 /* BatchChoiceView.swift in Sources */, 0CBC76FD288D914F0054BE44 /* BatchChoiceView.swift in Sources */,
0CF501F2289AE06A0099C785 /* SourceTracker+CoreDataClass.swift in Sources */, 0CF501F2289AE06A0099C785 /* SourceTracker+CoreDataClass.swift in Sources */,
0C32FB552890D1BF002BD219 /* UIApplication.swift in Sources */, 0C32FB552890D1BF002BD219 /* UIApplication.swift in Sources */,
0C7D11FE28AA03FE00ED92DB /* View.swift in Sources */,
0C0D50E7288DFF850035ECC8 /* SourcesView.swift in Sources */, 0C0D50E7288DFF850035ECC8 /* SourcesView.swift in Sources */,
0CA148EC288903F000DE2211 /* ContentView.swift in Sources */, 0CA148EC288903F000DE2211 /* ContentView.swift in Sources */,
0C95D8D828A55B03005E22B3 /* DefaultActionsPickerViews.swift in Sources */, 0C95D8D828A55B03005E22B3 /* DefaultActionsPickerViews.swift in Sources */,
@ -439,6 +446,7 @@
0C4CFC4E28970C8B00AD9FAD /* SourceComplexQuery+CoreDataProperties.swift in Sources */, 0C4CFC4E28970C8B00AD9FAD /* SourceComplexQuery+CoreDataProperties.swift in Sources */,
0CA148E2288903F000DE2211 /* Data.swift in Sources */, 0CA148E2288903F000DE2211 /* Data.swift in Sources */,
0C57D4CC289032ED008534E8 /* SearchResultRDView.swift in Sources */, 0C57D4CC289032ED008534E8 /* SearchResultRDView.swift in Sources */,
0C7D11FC28AA01E900ED92DB /* DynamicAccentColor.swift in Sources */,
0CA05459288EE9E600850554 /* SourceManager.swift in Sources */, 0CA05459288EE9E600850554 /* SourceManager.swift in Sources */,
0C84F4772895BE680074B7C9 /* FerriteDB.xcdatamodeld in Sources */, 0C84F4772895BE680074B7C9 /* FerriteDB.xcdatamodeld in Sources */,
0C733287289C4C820058D1FE /* SourceSettingsView.swift in Sources */, 0C733287289C4C820058D1FE /* SourceSettingsView.swift in Sources */,
@ -513,7 +521,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0; IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
@ -567,7 +575,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0; IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -596,6 +604,7 @@
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
@ -628,6 +637,7 @@
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
@ -689,12 +699,12 @@
kind = branch; kind = branch;
}; };
}; };
0C90E32A2888E5D000C0BC89 /* XCRemoteSwiftPackageReference "ActivityView" */ = { 0C7376EE28A97D1400D60918 /* XCRemoteSwiftPackageReference "SwiftUIX" */ = {
isa = XCRemoteSwiftPackageReference; isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/SwiftUI-Plus/ActivityView.git"; repositoryURL = "https://github.com/SwiftUIX/SwiftUIX";
requirement = { requirement = {
kind = upToNextMajorVersion; branch = master;
minimumVersion = 1.0.0; kind = branch;
}; };
}; };
0CAF1C79286F5C8600296F86 /* XCRemoteSwiftPackageReference "SwiftSoup" */ = { 0CAF1C79286F5C8600296F86 /* XCRemoteSwiftPackageReference "SwiftSoup" */ = {
@ -723,10 +733,10 @@
package = 0C64A4B5288903880079976D /* XCRemoteSwiftPackageReference "keychain-swift" */; package = 0C64A4B5288903880079976D /* XCRemoteSwiftPackageReference "keychain-swift" */;
productName = KeychainSwift; productName = KeychainSwift;
}; };
0C90E32B2888E5D000C0BC89 /* ActivityView */ = { 0C7376EF28A97D1400D60918 /* SwiftUIX */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
package = 0C90E32A2888E5D000C0BC89 /* XCRemoteSwiftPackageReference "ActivityView" */; package = 0C7376EE28A97D1400D60918 /* XCRemoteSwiftPackageReference "SwiftUIX" */;
productName = ActivityView; productName = SwiftUIX;
}; };
0CAF1C7A286F5C8600296F86 /* SwiftSoup */ = { 0CAF1C7A286F5C8600296F86 /* SwiftSoup */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;

View file

@ -0,0 +1,16 @@
//
// View.swift
// Ferrite
//
// Created by Brian Dashore on 8/15/22.
//
import SwiftUI
extension View {
// MARK: Modifiers
func dynamicAccentColor(_ color: Color) -> some View {
modifier(DynamicAccentColor(color: color))
}
}

View file

@ -5,7 +5,6 @@
// Created by Brian Dashore on 7/24/22. // Created by Brian Dashore on 7/24/22.
// //
import ActivityView
import SwiftUI import SwiftUI
enum ViewTab { enum ViewTab {
@ -28,8 +27,14 @@ class NavigationViewModel: ObservableObject {
case batch case batch
} }
@Published var isEditingSearch: Bool = false
@Published var isSearching: Bool = false
@Published var hideNavigationBar = false
@Published var currentChoiceSheet: ChoiceSheetType? @Published var currentChoiceSheet: ChoiceSheetType?
@Published var currentActivityItem: ActivityItem? @Published var activityItems: [Any] = []
@Published var showActivityView: Bool = false
@Published var selectedTab: ViewTab = .search @Published var selectedTab: ViewTab = .search
@Published var showSearchProgress: Bool = false @Published var showSearchProgress: Bool = false
@ -70,7 +75,8 @@ class NavigationViewModel: ObservableObject {
} }
case .shareDownload: case .shareDownload:
if let downloadUrl = URL(string: urlString), currentChoiceSheet == nil { if let downloadUrl = URL(string: urlString), currentChoiceSheet == nil {
currentActivityItem = ActivityItem(items: downloadUrl) activityItems = [downloadUrl]
showActivityView.toggle()
} else { } else {
toastModel?.toastDescription = "Could not create object for sharing" toastModel?.toastDescription = "Could not create object for sharing"
} }
@ -91,7 +97,8 @@ class NavigationViewModel: ObservableObject {
} }
case .shareMagnet: case .shareMagnet:
if let magnetUrl = URL(string: searchResult.magnetLink), currentChoiceSheet == nil { if let magnetUrl = URL(string: searchResult.magnetLink), currentChoiceSheet == nil {
currentActivityItem = ActivityItem(items: magnetUrl) activityItems = [magnetUrl]
showActivityView.toggle()
} else { } else {
toastModel?.toastDescription = "Could not create object for sharing" toastModel?.toastDescription = "Could not create object for sharing"
} }

View file

@ -8,8 +8,6 @@
import SwiftUI import SwiftUI
struct AboutView: View { struct AboutView: View {
@Environment(\.dismiss) var dismiss
var body: some View { var body: some View {
VStack { VStack {
Image("AppImage") Image("AppImage")

View file

@ -8,7 +8,7 @@
import SwiftUI import SwiftUI
struct BatchChoiceView: View { struct BatchChoiceView: View {
@Environment(\.dismiss) var dismiss @Environment(\.presentationMode) var presentationMode
@EnvironmentObject var debridManager: DebridManager @EnvironmentObject var debridManager: DebridManager
@EnvironmentObject var scrapingModel: ScrapingViewModel @EnvironmentObject var scrapingModel: ScrapingViewModel
@ -34,10 +34,11 @@ struct BatchChoiceView: View {
} }
} }
dismiss() presentationMode.wrappedValue.dismiss()
} }
} }
} }
.listStyle(.insetGrouped)
.navigationTitle("Select a file") .navigationTitle("Select a file")
.navigationBarTitleDisplayMode(.inline) .navigationBarTitleDisplayMode(.inline)
.toolbar { .toolbar {
@ -45,7 +46,7 @@ struct BatchChoiceView: View {
Button("Done") { Button("Done") {
debridManager.selectedRealDebridItem = nil debridManager.selectedRealDebridItem = nil
dismiss() presentationMode.wrappedValue.dismiss()
} }
} }
} }

View file

@ -0,0 +1,22 @@
//
// dynamicAccentColor.swift
// Ferrite
//
// Created by Brian Dashore on 8/15/22.
//
import SwiftUI
struct DynamicAccentColor: ViewModifier {
let color: Color
func body(content: Content) -> some View {
if #available(iOS 15, *) {
content
.tint(color)
} else {
content
.accentColor(color)
}
}
}

View file

@ -14,7 +14,7 @@ struct ErrorGroupBoxStyle: GroupBoxStyle {
configuration.content configuration.content
} }
.padding(10) .padding(10)
.background(Color(uiColor: .secondarySystemGroupedBackground)) .background(Color(UIColor.secondarySystemGroupedBackground))
.clipShape(RoundedRectangle(cornerRadius: 8, style: .continuous)) .clipShape(RoundedRectangle(cornerRadius: 8, style: .continuous))
} }
} }

View file

@ -5,8 +5,8 @@
// Created by Brian Dashore on 7/1/22. // Created by Brian Dashore on 7/1/22.
// //
import ActivityView
import SwiftUI import SwiftUI
import SwiftUIX
struct ContentView: View { struct ContentView: View {
@EnvironmentObject var scrapingModel: ScrapingViewModel @EnvironmentObject var scrapingModel: ScrapingViewModel
@ -66,38 +66,63 @@ struct ContentView: View {
Spacer() Spacer()
} }
.padding(.vertical, 5)
.padding(.horizontal, 20) .padding(.horizontal, 20)
SearchResultsView() SearchResultsView()
} }
.searchable(text: $scrapingModel.searchText) .sheet(item: $navModel.currentChoiceSheet) { item in
.onSubmit(of: .search) { Group {
scrapingModel.runningSearchTask = Task { switch item {
navModel.showSearchProgress = true case .magnet:
MagnetChoiceView()
await scrapingModel.scanSources(sources: sources.compactMap { $0 }) .environmentObject(debridManager)
.environmentObject(scrapingModel)
if realDebridEnabled, !scrapingModel.searchResults.isEmpty { .environmentObject(navModel)
await debridManager.populateDebridHashes(scrapingModel.searchResults) case .batch:
BatchChoiceView()
.environmentObject(debridManager)
.environmentObject(scrapingModel)
.environmentObject(navModel)
} }
}
navModel.showSearchProgress = false .dynamicAccentColor(.primary)
}
.sheet(isPresented: $navModel.showActivityView) {
if #available(iOS 16, *) {
AppActivityView(activityItems: navModel.activityItems)
.presentationDetents([.medium])
} else {
AppActivityView(activityItems: navModel.activityItems)
} }
} }
.navigationTitle("Search") .navigationTitle("Search")
} .navigationSearchBar {
.sheet(item: $navModel.currentChoiceSheet) { item in SearchBar("Search", text: $scrapingModel.searchText, isEditing: $navModel.isEditingSearch,
Group { onCommit: {
switch item { scrapingModel.runningSearchTask = Task {
case .magnet: navModel.isSearching = true
MagnetChoiceView() navModel.showSearchProgress = true
case .batch:
BatchChoiceView() await scrapingModel.scanSources(sources: sources.compactMap { $0 })
}
if realDebridEnabled, !scrapingModel.searchResults.isEmpty {
await debridManager.populateDebridHashes(scrapingModel.searchResults)
}
navModel.showSearchProgress = false
}
})
.showsCancelButton(navModel.isEditingSearch || navModel.isSearching)
.onCancel {
scrapingModel.searchResults = []
scrapingModel.runningSearchTask?.cancel()
scrapingModel.runningSearchTask = nil
navModel.isSearching = false
scrapingModel.searchText = ""
}
} }
.tint(.primary)
} }
.activitySheet($navModel.currentActivityItem)
} }
} }

View file

@ -8,8 +8,9 @@
import SwiftUI import SwiftUI
struct LoginWebView: View { struct LoginWebView: View {
@Environment(\.dismiss) var dismiss @Environment(\.presentationMode) var presentationMode
var url: URL var url: URL
var body: some View { var body: some View {
NavView { NavView {
WebView(url: url) WebView(url: url)
@ -18,7 +19,7 @@ struct LoginWebView: View {
.toolbar { .toolbar {
ToolbarItem(placement: .navigationBarTrailing) { ToolbarItem(placement: .navigationBarTrailing) {
Button("Done") { Button("Done") {
dismiss() presentationMode.wrappedValue.dismiss()
} }
} }
} }

View file

@ -5,11 +5,11 @@
// Created by Brian Dashore on 7/20/22. // Created by Brian Dashore on 7/20/22.
// //
import ActivityView
import SwiftUI import SwiftUI
import SwiftUIX
struct MagnetChoiceView: View { struct MagnetChoiceView: View {
@Environment(\.dismiss) var dismiss @Environment(\.presentationMode) var presentationMode
@EnvironmentObject var scrapingModel: ScrapingViewModel @EnvironmentObject var scrapingModel: ScrapingViewModel
@EnvironmentObject var debridManager: DebridManager @EnvironmentObject var debridManager: DebridManager
@ -20,13 +20,13 @@ struct MagnetChoiceView: View {
@State private var showActivityView = false @State private var showActivityView = false
@State private var showLinkCopyAlert = false @State private var showLinkCopyAlert = false
@State private var showMagnetCopyAlert = false @State private var showMagnetCopyAlert = false
@State private var activityItem: ActivityItem? @State private var activityItems: [Any] = []
var body: some View { var body: some View {
NavView { NavView {
Form { Form {
if realDebridEnabled, debridManager.matchSearchResult(result: scrapingModel.selectedSearchResult) != .none { if realDebridEnabled, debridManager.matchSearchResult(result: scrapingModel.selectedSearchResult) != .none {
Section("Real Debrid options") { Section(header: "Real Debrid options") {
ListRowButtonView("Play on Outplayer", systemImage: "arrow.up.forward.app.fill") { ListRowButtonView("Play on Outplayer", systemImage: "arrow.up.forward.app.fill") {
navModel.runDebridAction(action: .outplayer, urlString: debridManager.realDebridDownloadUrl) navModel.runDebridAction(action: .outplayer, urlString: debridManager.realDebridDownloadUrl)
} }
@ -52,16 +52,15 @@ struct MagnetChoiceView: View {
} }
ListRowButtonView("Share download URL", systemImage: "square.and.arrow.up.fill") { ListRowButtonView("Share download URL", systemImage: "square.and.arrow.up.fill") {
guard let url = URL(string: debridManager.realDebridDownloadUrl) else { if let url = URL(string: debridManager.realDebridDownloadUrl) {
return activityItems = [url]
navModel.showActivityView.toggle()
} }
activityItem = ActivityItem(items: url)
} }
} }
} }
Section("Magnet options") { Section(header: "Magnet options") {
ListRowButtonView("Copy magnet", systemImage: "doc.on.doc.fill") { ListRowButtonView("Copy magnet", systemImage: "doc.on.doc.fill") {
UIPasteboard.general.string = scrapingModel.selectedSearchResult?.magnetLink UIPasteboard.general.string = scrapingModel.selectedSearchResult?.magnetLink
showMagnetCopyAlert.toggle() showMagnetCopyAlert.toggle()
@ -76,7 +75,8 @@ struct MagnetChoiceView: View {
ListRowButtonView("Share magnet", systemImage: "square.and.arrow.up.fill") { ListRowButtonView("Share magnet", systemImage: "square.and.arrow.up.fill") {
if let result = scrapingModel.selectedSearchResult, let url = URL(string: result.magnetLink) { if let result = scrapingModel.selectedSearchResult, let url = URL(string: result.magnetLink) {
activityItem = ActivityItem(items: url) activityItems = [url]
navModel.showActivityView.toggle()
} }
} }
@ -87,7 +87,14 @@ struct MagnetChoiceView: View {
} }
} }
} }
.activitySheet($activityItem) .sheet(isPresented: $navModel.showActivityView) {
if #available(iOS 16, *) {
AppActivityView(activityItems: activityItems)
.presentationDetents([.medium])
} else {
AppActivityView(activityItems: activityItems)
}
}
.navigationTitle("Link actions") .navigationTitle("Link actions")
.navigationBarTitleDisplayMode(.inline) .navigationBarTitleDisplayMode(.inline)
.toolbar { .toolbar {
@ -95,7 +102,7 @@ struct MagnetChoiceView: View {
Button("Done") { Button("Done") {
debridManager.realDebridDownloadUrl = "" debridManager.realDebridDownloadUrl = ""
dismiss() presentationMode.wrappedValue.dismiss()
} }
} }
} }

View file

@ -8,9 +8,6 @@
import SwiftUI import SwiftUI
struct SearchResultsView: View { struct SearchResultsView: View {
@Environment(\.isSearching) var isSearching
@Environment(\.dismissSearch) var dismissSearch
@EnvironmentObject var scrapingModel: ScrapingViewModel @EnvironmentObject var scrapingModel: ScrapingViewModel
@EnvironmentObject var debridManager: DebridManager @EnvironmentObject var debridManager: DebridManager
@EnvironmentObject var navModel: NavigationViewModel @EnvironmentObject var navModel: NavigationViewModel
@ -43,7 +40,7 @@ struct SearchResultsView: View {
.font(.callout) .font(.callout)
.fixedSize(horizontal: false, vertical: true) .fixedSize(horizontal: false, vertical: true)
} }
.tint(.primary) .dynamicAccentColor(.primary)
.padding(.bottom, 5) .padding(.bottom, 5)
SearchResultRDView(result: result) SearchResultRDView(result: result)
@ -51,6 +48,7 @@ struct SearchResultsView: View {
} }
} }
} }
.listStyle(.insetGrouped)
.overlay { .overlay {
if scrapingModel.searchResults.isEmpty { if scrapingModel.searchResults.isEmpty {
if navModel.showSearchProgress { if navModel.showSearchProgress {
@ -58,7 +56,7 @@ struct SearchResultsView: View {
ProgressView() ProgressView()
Text("Loading \(scrapingModel.currentSourceName ?? "")") Text("Loading \(scrapingModel.currentSourceName ?? "")")
} }
} else if isSearching, scrapingModel.runningSearchTask != nil { } else if navModel.isSearching, scrapingModel.runningSearchTask != nil {
Text("No results found") Text("No results found")
} }
} }
@ -66,25 +64,19 @@ struct SearchResultsView: View {
.onChange(of: navModel.selectedTab) { tab in .onChange(of: navModel.selectedTab) { tab in
// Cancel the search if tab is switched while search is in progress // Cancel the search if tab is switched while search is in progress
if tab != .search, navModel.showSearchProgress { if tab != .search, navModel.showSearchProgress {
scrapingModel.searchResults = []
scrapingModel.runningSearchTask?.cancel() scrapingModel.runningSearchTask?.cancel()
scrapingModel.runningSearchTask = nil scrapingModel.runningSearchTask = nil
dismissSearch() navModel.isSearching = false
scrapingModel.searchText = ""
} }
} }
.onChange(of: scrapingModel.searchResults) { _ in .onChange(of: scrapingModel.searchResults) { _ in
// Cleans up any leftover search results in the event of an abrupt cancellation // Cleans up any leftover search results in the event of an abrupt cancellation
if !isSearching { if !navModel.isSearching {
scrapingModel.searchResults = [] scrapingModel.searchResults = []
} }
} }
.onChange(of: isSearching) { changed in
// Clear the results array and cleans up search tasks on cancel
if !changed {
scrapingModel.searchResults = []
scrapingModel.runningSearchTask?.cancel()
scrapingModel.runningSearchTask = nil
}
}
} }
} }

View file

@ -22,7 +22,7 @@ struct SettingsView: View {
var body: some View { var body: some View {
NavView { NavView {
Form { Form {
Section("Debrid services") { Section(header: "Debrid services") {
HStack { HStack {
Text("Real Debrid") Text("Real Debrid")
Spacer() Spacer()
@ -42,11 +42,11 @@ struct SettingsView: View {
} }
} }
Section("Source management") { Section(header: "Source management") {
NavigationLink("Source lists", destination: SettingsSourceListView()) NavigationLink("Source lists", destination: SettingsSourceListView())
} }
Section("Default actions") { Section(header: "Default actions") {
if realDebridEnabled { if realDebridEnabled {
NavigationLink( NavigationLink(
destination: DebridActionPickerView(), destination: DebridActionPickerView(),

View file

@ -8,7 +8,7 @@
import SwiftUI import SwiftUI
struct SourceListEditorView: View { struct SourceListEditorView: View {
@Environment(\.dismiss) var dismiss @Environment(\.presentationMode) var presentationMode
@EnvironmentObject var navModel: NavigationViewModel @EnvironmentObject var navModel: NavigationViewModel
@EnvironmentObject var sourceManager: SourceManager @EnvironmentObject var sourceManager: SourceManager
@ -42,7 +42,7 @@ struct SourceListEditorView: View {
.toolbar { .toolbar {
ToolbarItem(placement: .navigationBarLeading) { ToolbarItem(placement: .navigationBarLeading) {
Button("Cancel") { Button("Cancel") {
dismiss() presentationMode.wrappedValue.dismiss()
} }
} }
@ -53,7 +53,7 @@ struct SourceListEditorView: View {
sourceUrl: sourceUrl, sourceUrl: sourceUrl,
existingSourceList: navModel.selectedSourceList existingSourceList: navModel.selectedSourceList
) { ) {
dismiss() presentationMode.wrappedValue.dismiss()
} }
} }
} }

View file

@ -8,15 +8,15 @@
import SwiftUI import SwiftUI
struct SourceSettingsView: View { struct SourceSettingsView: View {
@Environment(\.dismiss) var dismiss @Environment(\.presentationMode) var presentationMode
@EnvironmentObject var navModel: NavigationViewModel @EnvironmentObject var navModel: NavigationViewModel
var body: some View { var body: some View {
NavView { NavView {
Form { List {
if let selectedSource = navModel.selectedSource { if let selectedSource = navModel.selectedSource {
Section("Info") { Section(header: "Info") {
VStack(alignment: .leading, spacing: 5) { VStack(alignment: .leading, spacing: 5) {
HStack { HStack {
Text(selectedSource.name) Text(selectedSource.name)
@ -53,6 +53,7 @@ struct SourceSettingsView: View {
SourceSettingsMethodView(selectedSource: selectedSource) SourceSettingsMethodView(selectedSource: selectedSource)
} }
} }
.listStyle(.insetGrouped)
.onDisappear { .onDisappear {
PersistenceController.shared.save() PersistenceController.shared.save()
} }
@ -60,7 +61,7 @@ struct SourceSettingsView: View {
.toolbar { .toolbar {
ToolbarItem(placement: .navigationBarTrailing) { ToolbarItem(placement: .navigationBarTrailing) {
Button("Done") { Button("Done") {
dismiss() presentationMode.wrappedValue.dismiss()
} }
} }
} }
@ -71,29 +72,25 @@ struct SourceSettingsView: View {
struct SourceSettingsBaseUrlView: View { struct SourceSettingsBaseUrlView: View {
@ObservedObject var selectedSource: Source @ObservedObject var selectedSource: Source
@FocusState var baseUrlFocused: Bool
@State private var tempBaseUrl: String = "" @State private var tempBaseUrl: String = ""
var body: some View { var body: some View {
Section( Section(
header: Text("Base URL"), header: Text("Base URL"),
footer: Text("Enter the base URL of your server.") footer: Text("Enter the base URL of your server.")
) { ) {
TextField("https://...", text: $tempBaseUrl) TextField("https://...", text: $tempBaseUrl, onEditingChanged: { isFocused in
.keyboardType(.URL) if !isFocused {
.focused($baseUrlFocused) if tempBaseUrl.last == "/" {
.onChange(of: baseUrlFocused) { isFocused in selectedSource.baseUrl = String(tempBaseUrl.dropLast())
if !isFocused { } else {
if tempBaseUrl.last == "/" { selectedSource.baseUrl = tempBaseUrl
selectedSource.baseUrl = String(tempBaseUrl.dropLast())
} else {
selectedSource.baseUrl = tempBaseUrl
}
} }
} }
.onAppear { })
tempBaseUrl = selectedSource.baseUrl ?? "" .keyboardType(.URL)
} .onAppear {
tempBaseUrl = selectedSource.baseUrl ?? ""
}
} }
} }
} }
@ -101,9 +98,6 @@ struct SourceSettingsBaseUrlView: View {
struct SourceSettingsApiView: View { struct SourceSettingsApiView: View {
@ObservedObject var selectedSourceApi: SourceApi @ObservedObject var selectedSourceApi: SourceApi
@FocusState var clientIdFieldFocused: Bool
@FocusState var tokenFieldFocused: Bool
@State private var tempClientId: String = "" @State private var tempClientId: String = ""
@State private var tempClientSecret: String = "" @State private var tempClientSecret: String = ""
@ -117,31 +111,27 @@ struct SourceSettingsApiView: View {
footer: Text("Grab the required API credentials from the website. A client secret can be an API token.") footer: Text("Grab the required API credentials from the website. A client secret can be an API token.")
) { ) {
if selectedSourceApi.dynamicClientId { if selectedSourceApi.dynamicClientId {
TextField("Client ID", text: $tempClientId) TextField("Client ID", text: $tempClientId, onEditingChanged: { isFocused in
.textInputAutocapitalization(.never) if !isFocused {
.focused($clientIdFieldFocused) selectedSourceApi.clientId = tempClientId
.onChange(of: clientIdFieldFocused) { isFocused in
if !isFocused {
selectedSourceApi.clientId = tempClientId
}
}
.onAppear {
tempClientId = selectedSourceApi.clientId ?? ""
} }
})
.autocapitalization(.none)
.onAppear {
tempClientId = selectedSourceApi.clientId ?? ""
}
} }
if selectedSourceApi.clientSecret != nil { if selectedSourceApi.clientSecret != nil {
TextField("Token", text: $tempClientSecret) TextField("Token", text: $tempClientSecret, onEditingChanged: { isFocused in
.textInputAutocapitalization(.never) if !isFocused {
.focused($tokenFieldFocused) selectedSourceApi.clientSecret = tempClientSecret
.onChange(of: clientIdFieldFocused) { isFocused in
if !isFocused {
selectedSourceApi.clientSecret = tempClientSecret
}
}
.onAppear {
tempClientSecret = selectedSourceApi.clientSecret ?? ""
} }
})
.autocapitalization(.none)
.onAppear {
tempClientSecret = selectedSourceApi.clientSecret ?? ""
}
} }
} }
} }

View file

@ -36,11 +36,13 @@ struct SourcesView: View {
return tempSources return tempSources
} }
@State private var viewTask: Task<Void, Never>? = nil
var body: some View { var body: some View {
NavView { NavView {
List { List {
if !updatedSources.isEmpty { if !updatedSources.isEmpty {
Section("Updates") { Section(header: "Updates") {
ForEach(updatedSources, id: \.self) { source in ForEach(updatedSources, id: \.self) { source in
SourceUpdateButtonView(updatedSource: source) SourceUpdateButtonView(updatedSource: source)
} }
@ -48,13 +50,10 @@ struct SourcesView: View {
} }
if !sources.isEmpty { if !sources.isEmpty {
Section("Installed") { Section(header: "Installed") {
ForEach(sources, id: \.self) { source in ForEach(sources, id: \.self) { source in
InstalledSourceView(installedSource: source) InstalledSourceView(installedSource: source)
} }
.sheet(isPresented: $navModel.showSourceSettings) {
SourceSettingsView()
}
} }
} }
@ -67,7 +66,7 @@ struct SourcesView: View {
} }
) )
}) { }) {
Section("Catalog") { Section(header: "Catalog") {
ForEach(sourceManager.availableSources, id: \.self) { availableSource in ForEach(sourceManager.availableSources, id: \.self) { availableSource in
if !sources.contains( if !sources.contains(
where: { where: {
@ -82,8 +81,18 @@ struct SourcesView: View {
} }
} }
} }
.task { .listStyle(.insetGrouped)
await sourceManager.fetchSourcesFromUrl() .sheet(isPresented: $navModel.showSourceSettings) {
SourceSettingsView()
.environmentObject(navModel)
}
.onAppear {
viewTask = Task {
await sourceManager.fetchSourcesFromUrl()
}
}
.onDisappear {
viewTask?.cancel()
} }
.navigationTitle("Sources") .navigationTitle("Sources")
} }