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 */; };
0C64A4B7288903880079976D /* KeychainSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 0C64A4B6288903880079976D /* KeychainSwift */; };
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 */; };
0C750745289B003E004B3906 /* SourceRssParser+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C750743289B003E004B3906 /* SourceRssParser+CoreDataProperties.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 */; };
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 */; };
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 */; };
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 */; };
@ -35,7 +38,6 @@
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 */; };
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 */; };
0C95D8DA28A55BB6005E22B3 /* SettingsModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C95D8D928A55BB6005E22B3 /* SettingsModels.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>"; };
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>"; };
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>"; };
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>"; };
@ -134,9 +138,9 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
0C90E32C2888E5D000C0BC89 /* ActivityView in Frameworks */,
0C64A4B4288903680079976D /* Base32 in Frameworks */,
0C4CFC462897030D00AD9FAD /* Regex in Frameworks */,
0C7376F028A97D1400D60918 /* SwiftUIX in Frameworks */,
0C64A4B7288903880079976D /* KeychainSwift in Frameworks */,
0CAF1C7B286F5C8600296F86 /* SwiftSoup in Frameworks */,
);
@ -221,6 +225,7 @@
0CA148C1288903F000DE2211 /* NavView.swift */,
0CFEFCFC288A006200B3F490 /* GroupBoxStyle.swift */,
0C32FB562890D1F2002BD219 /* ListRowViews.swift */,
0C7D11FB28AA01E900ED92DB /* DynamicAccentColor.swift */,
);
path = CommonViews;
sourceTree = "<group>";
@ -240,6 +245,7 @@
0CA148CA288903F000DE2211 /* Data.swift */,
0CA148CB288903F000DE2211 /* Task.swift */,
0C32FB542890D1BF002BD219 /* UIApplication.swift */,
0C7D11FD28AA03FE00ED92DB /* View.swift */,
);
path = Extensions;
sourceTree = "<group>";
@ -338,10 +344,10 @@
name = Ferrite;
packageProductDependencies = (
0CAF1C7A286F5C8600296F86 /* SwiftSoup */,
0C90E32B2888E5D000C0BC89 /* ActivityView */,
0C64A4B3288903680079976D /* Base32 */,
0C64A4B6288903880079976D /* KeychainSwift */,
0C4CFC452897030D00AD9FAD /* Regex */,
0C7376EF28A97D1400D60918 /* SwiftUIX */,
);
productName = Torrenter;
productReference = 0CAF1C68286F5C0E00296F86 /* Ferrite.app */;
@ -373,10 +379,10 @@
mainGroup = 0CAF1C5F286F5C0D00296F86;
packageReferences = (
0CAF1C79286F5C8600296F86 /* XCRemoteSwiftPackageReference "SwiftSoup" */,
0C90E32A2888E5D000C0BC89 /* XCRemoteSwiftPackageReference "ActivityView" */,
0C64A4B2288903680079976D /* XCRemoteSwiftPackageReference "Base32" */,
0C64A4B5288903880079976D /* XCRemoteSwiftPackageReference "keychain-swift" */,
0C4CFC442897030D00AD9FAD /* XCRemoteSwiftPackageReference "Regex" */,
0C7376EE28A97D1400D60918 /* XCRemoteSwiftPackageReference "SwiftUIX" */,
);
productRefGroup = 0CAF1C69286F5C0E00296F86 /* Products */;
projectDirPath = "";
@ -419,6 +425,7 @@
0CBC76FD288D914F0054BE44 /* BatchChoiceView.swift in Sources */,
0CF501F2289AE06A0099C785 /* SourceTracker+CoreDataClass.swift in Sources */,
0C32FB552890D1BF002BD219 /* UIApplication.swift in Sources */,
0C7D11FE28AA03FE00ED92DB /* View.swift in Sources */,
0C0D50E7288DFF850035ECC8 /* SourcesView.swift in Sources */,
0CA148EC288903F000DE2211 /* ContentView.swift in Sources */,
0C95D8D828A55B03005E22B3 /* DefaultActionsPickerViews.swift in Sources */,
@ -439,6 +446,7 @@
0C4CFC4E28970C8B00AD9FAD /* SourceComplexQuery+CoreDataProperties.swift in Sources */,
0CA148E2288903F000DE2211 /* Data.swift in Sources */,
0C57D4CC289032ED008534E8 /* SearchResultRDView.swift in Sources */,
0C7D11FC28AA01E900ED92DB /* DynamicAccentColor.swift in Sources */,
0CA05459288EE9E600850554 /* SourceManager.swift in Sources */,
0C84F4772895BE680074B7C9 /* FerriteDB.xcdatamodeld in Sources */,
0C733287289C4C820058D1FE /* SourceSettingsView.swift in Sources */,
@ -513,7 +521,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
@ -567,7 +575,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
@ -596,6 +604,7 @@
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -628,6 +637,7 @@
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -689,12 +699,12 @@
kind = branch;
};
};
0C90E32A2888E5D000C0BC89 /* XCRemoteSwiftPackageReference "ActivityView" */ = {
0C7376EE28A97D1400D60918 /* XCRemoteSwiftPackageReference "SwiftUIX" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/SwiftUI-Plus/ActivityView.git";
repositoryURL = "https://github.com/SwiftUIX/SwiftUIX";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 1.0.0;
branch = master;
kind = branch;
};
};
0CAF1C79286F5C8600296F86 /* XCRemoteSwiftPackageReference "SwiftSoup" */ = {
@ -723,10 +733,10 @@
package = 0C64A4B5288903880079976D /* XCRemoteSwiftPackageReference "keychain-swift" */;
productName = KeychainSwift;
};
0C90E32B2888E5D000C0BC89 /* ActivityView */ = {
0C7376EF28A97D1400D60918 /* SwiftUIX */ = {
isa = XCSwiftPackageProductDependency;
package = 0C90E32A2888E5D000C0BC89 /* XCRemoteSwiftPackageReference "ActivityView" */;
productName = ActivityView;
package = 0C7376EE28A97D1400D60918 /* XCRemoteSwiftPackageReference "SwiftUIX" */;
productName = SwiftUIX;
};
0CAF1C7A286F5C8600296F86 /* SwiftSoup */ = {
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.
//
import ActivityView
import SwiftUI
enum ViewTab {
@ -28,8 +27,14 @@ class NavigationViewModel: ObservableObject {
case batch
}
@Published var isEditingSearch: Bool = false
@Published var isSearching: Bool = false
@Published var hideNavigationBar = false
@Published var currentChoiceSheet: ChoiceSheetType?
@Published var currentActivityItem: ActivityItem?
@Published var activityItems: [Any] = []
@Published var showActivityView: Bool = false
@Published var selectedTab: ViewTab = .search
@Published var showSearchProgress: Bool = false
@ -70,7 +75,8 @@ class NavigationViewModel: ObservableObject {
}
case .shareDownload:
if let downloadUrl = URL(string: urlString), currentChoiceSheet == nil {
currentActivityItem = ActivityItem(items: downloadUrl)
activityItems = [downloadUrl]
showActivityView.toggle()
} else {
toastModel?.toastDescription = "Could not create object for sharing"
}
@ -91,7 +97,8 @@ class NavigationViewModel: ObservableObject {
}
case .shareMagnet:
if let magnetUrl = URL(string: searchResult.magnetLink), currentChoiceSheet == nil {
currentActivityItem = ActivityItem(items: magnetUrl)
activityItems = [magnetUrl]
showActivityView.toggle()
} else {
toastModel?.toastDescription = "Could not create object for sharing"
}

View file

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

View file

@ -8,7 +8,7 @@
import SwiftUI
struct BatchChoiceView: View {
@Environment(\.dismiss) var dismiss
@Environment(\.presentationMode) var presentationMode
@EnvironmentObject var debridManager: DebridManager
@EnvironmentObject var scrapingModel: ScrapingViewModel
@ -34,10 +34,11 @@ struct BatchChoiceView: View {
}
}
dismiss()
presentationMode.wrappedValue.dismiss()
}
}
}
.listStyle(.insetGrouped)
.navigationTitle("Select a file")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
@ -45,7 +46,7 @@ struct BatchChoiceView: View {
Button("Done") {
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
}
.padding(10)
.background(Color(uiColor: .secondarySystemGroupedBackground))
.background(Color(UIColor.secondarySystemGroupedBackground))
.clipShape(RoundedRectangle(cornerRadius: 8, style: .continuous))
}
}

View file

@ -5,8 +5,8 @@
// Created by Brian Dashore on 7/1/22.
//
import ActivityView
import SwiftUI
import SwiftUIX
struct ContentView: View {
@EnvironmentObject var scrapingModel: ScrapingViewModel
@ -66,38 +66,63 @@ struct ContentView: View {
Spacer()
}
.padding(.vertical, 5)
.padding(.horizontal, 20)
SearchResultsView()
}
.searchable(text: $scrapingModel.searchText)
.onSubmit(of: .search) {
scrapingModel.runningSearchTask = Task {
navModel.showSearchProgress = true
await scrapingModel.scanSources(sources: sources.compactMap { $0 })
if realDebridEnabled, !scrapingModel.searchResults.isEmpty {
await debridManager.populateDebridHashes(scrapingModel.searchResults)
.sheet(item: $navModel.currentChoiceSheet) { item in
Group {
switch item {
case .magnet:
MagnetChoiceView()
.environmentObject(debridManager)
.environmentObject(scrapingModel)
.environmentObject(navModel)
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")
}
.sheet(item: $navModel.currentChoiceSheet) { item in
Group {
switch item {
case .magnet:
MagnetChoiceView()
case .batch:
BatchChoiceView()
}
.navigationSearchBar {
SearchBar("Search", text: $scrapingModel.searchText, isEditing: $navModel.isEditingSearch,
onCommit: {
scrapingModel.runningSearchTask = Task {
navModel.isSearching = true
navModel.showSearchProgress = true
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
struct LoginWebView: View {
@Environment(\.dismiss) var dismiss
@Environment(\.presentationMode) var presentationMode
var url: URL
var body: some View {
NavView {
WebView(url: url)
@ -18,7 +19,7 @@ struct LoginWebView: View {
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Done") {
dismiss()
presentationMode.wrappedValue.dismiss()
}
}
}

View file

@ -5,11 +5,11 @@
// Created by Brian Dashore on 7/20/22.
//
import ActivityView
import SwiftUI
import SwiftUIX
struct MagnetChoiceView: View {
@Environment(\.dismiss) var dismiss
@Environment(\.presentationMode) var presentationMode
@EnvironmentObject var scrapingModel: ScrapingViewModel
@EnvironmentObject var debridManager: DebridManager
@ -20,13 +20,13 @@ struct MagnetChoiceView: View {
@State private var showActivityView = false
@State private var showLinkCopyAlert = false
@State private var showMagnetCopyAlert = false
@State private var activityItem: ActivityItem?
@State private var activityItems: [Any] = []
var body: some View {
NavView {
Form {
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") {
navModel.runDebridAction(action: .outplayer, urlString: debridManager.realDebridDownloadUrl)
}
@ -52,16 +52,15 @@ struct MagnetChoiceView: View {
}
ListRowButtonView("Share download URL", systemImage: "square.and.arrow.up.fill") {
guard let url = URL(string: debridManager.realDebridDownloadUrl) else {
return
if let url = URL(string: debridManager.realDebridDownloadUrl) {
activityItems = [url]
navModel.showActivityView.toggle()
}
activityItem = ActivityItem(items: url)
}
}
}
Section("Magnet options") {
Section(header: "Magnet options") {
ListRowButtonView("Copy magnet", systemImage: "doc.on.doc.fill") {
UIPasteboard.general.string = scrapingModel.selectedSearchResult?.magnetLink
showMagnetCopyAlert.toggle()
@ -76,7 +75,8 @@ struct MagnetChoiceView: View {
ListRowButtonView("Share magnet", systemImage: "square.and.arrow.up.fill") {
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")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
@ -95,7 +102,7 @@ struct MagnetChoiceView: View {
Button("Done") {
debridManager.realDebridDownloadUrl = ""
dismiss()
presentationMode.wrappedValue.dismiss()
}
}
}

View file

@ -8,9 +8,6 @@
import SwiftUI
struct SearchResultsView: View {
@Environment(\.isSearching) var isSearching
@Environment(\.dismissSearch) var dismissSearch
@EnvironmentObject var scrapingModel: ScrapingViewModel
@EnvironmentObject var debridManager: DebridManager
@EnvironmentObject var navModel: NavigationViewModel
@ -43,7 +40,7 @@ struct SearchResultsView: View {
.font(.callout)
.fixedSize(horizontal: false, vertical: true)
}
.tint(.primary)
.dynamicAccentColor(.primary)
.padding(.bottom, 5)
SearchResultRDView(result: result)
@ -51,6 +48,7 @@ struct SearchResultsView: View {
}
}
}
.listStyle(.insetGrouped)
.overlay {
if scrapingModel.searchResults.isEmpty {
if navModel.showSearchProgress {
@ -58,7 +56,7 @@ struct SearchResultsView: View {
ProgressView()
Text("Loading \(scrapingModel.currentSourceName ?? "")")
}
} else if isSearching, scrapingModel.runningSearchTask != nil {
} else if navModel.isSearching, scrapingModel.runningSearchTask != nil {
Text("No results found")
}
}
@ -66,25 +64,19 @@ struct SearchResultsView: View {
.onChange(of: navModel.selectedTab) { tab in
// Cancel the search if tab is switched while search is in progress
if tab != .search, navModel.showSearchProgress {
scrapingModel.searchResults = []
scrapingModel.runningSearchTask?.cancel()
scrapingModel.runningSearchTask = nil
dismissSearch()
navModel.isSearching = false
scrapingModel.searchText = ""
}
}
.onChange(of: scrapingModel.searchResults) { _ in
// Cleans up any leftover search results in the event of an abrupt cancellation
if !isSearching {
if !navModel.isSearching {
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 {
NavView {
Form {
Section("Debrid services") {
Section(header: "Debrid services") {
HStack {
Text("Real Debrid")
Spacer()
@ -42,11 +42,11 @@ struct SettingsView: View {
}
}
Section("Source management") {
Section(header: "Source management") {
NavigationLink("Source lists", destination: SettingsSourceListView())
}
Section("Default actions") {
Section(header: "Default actions") {
if realDebridEnabled {
NavigationLink(
destination: DebridActionPickerView(),

View file

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

View file

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

View file

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