Settings: Add default options when opening a search result

Signed-off-by: kingbri <bdashore3@gmail.com>
This commit is contained in:
kingbri 2022-08-11 12:43:59 -04:00
parent 59ee4f7a2a
commit 2792b61e9b
11 changed files with 227 additions and 28 deletions

View file

@ -36,6 +36,8 @@
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 */; };
0CA05459288EE9E600850554 /* SourceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CA05458288EE9E600850554 /* SourceManager.swift */; };
0CA0545B288EEA4E00850554 /* SourceListEditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CA0545A288EEA4E00850554 /* SourceListEditorView.swift */; };
@ -93,6 +95,8 @@
0C84F47D2895BFED0074B7C9 /* SourceHtmlParser+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SourceHtmlParser+CoreDataProperties.swift"; sourceTree = "<group>"; };
0C84F47E2895BFED0074B7C9 /* SourceList+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SourceList+CoreDataClass.swift"; sourceTree = "<group>"; };
0C84F47F2895BFED0074B7C9 /* SourceList+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SourceList+CoreDataProperties.swift"; sourceTree = "<group>"; };
0C95D8D728A55B03005E22B3 /* DefaultActionsPickerViews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultActionsPickerViews.swift; sourceTree = "<group>"; };
0C95D8D928A55BB6005E22B3 /* SettingsModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsModels.swift; sourceTree = "<group>"; };
0CA05456288EE58200850554 /* SettingsSourceListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsSourceListView.swift; sourceTree = "<group>"; };
0CA05458288EE9E600850554 /* SourceManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceManager.swift; sourceTree = "<group>"; };
0CA0545A288EEA4E00850554 /* SourceListEditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceListEditorView.swift; sourceTree = "<group>"; };
@ -167,6 +171,7 @@
children = (
0CA148C4288903F000DE2211 /* RealDebridModels.swift */,
0C0D50E4288DFE7F0035ECC8 /* SourceModels.swift */,
0C95D8D928A55BB6005E22B3 /* SettingsModels.swift */,
);
path = Models;
sourceTree = "<group>";
@ -187,6 +192,7 @@
children = (
0CA05456288EE58200850554 /* SettingsSourceListView.swift */,
0CA0545A288EEA4E00850554 /* SourceListEditorView.swift */,
0C95D8D728A55B03005E22B3 /* DefaultActionsPickerViews.swift */,
);
path = SettingsViews;
sourceTree = "<group>";
@ -415,6 +421,7 @@
0C32FB552890D1BF002BD219 /* UIApplication.swift in Sources */,
0C0D50E7288DFF850035ECC8 /* SourcesView.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 */,
@ -422,6 +429,7 @@
0CA148DD288903F000DE2211 /* ScrapingViewModel.swift in Sources */,
0CA148D8288903F000DE2211 /* MagnetChoiceView.swift in Sources */,
0C84F4862895BFED0074B7C9 /* SourceList+CoreDataClass.swift in Sources */,
0C95D8DA28A55BB6005E22B3 /* SettingsModels.swift in Sources */,
0CA148E3288903F000DE2211 /* Task.swift in Sources */,
0CA148E7288903F000DE2211 /* ToastViewModel.swift in Sources */,
0CFEFCFD288A006200B3F490 /* GroupBoxStyle.swift in Sources */,

View file

@ -14,7 +14,7 @@ struct FerriteApp: App {
@StateObject var scrapingModel: ScrapingViewModel = .init()
@StateObject var toastModel: ToastViewModel = .init()
@StateObject var debridManager: DebridManager = .init()
@StateObject var navigationModel: NavigationViewModel = .init()
@StateObject var navModel: NavigationViewModel = .init()
@StateObject var sourceManager: SourceManager = .init()
var body: some Scene {
@ -24,11 +24,12 @@ struct FerriteApp: App {
scrapingModel.toastModel = toastModel
debridManager.toastModel = toastModel
sourceManager.toastModel = toastModel
navModel.toastModel = toastModel
}
.environmentObject(debridManager)
.environmentObject(scrapingModel)
.environmentObject(toastModel)
.environmentObject(navigationModel)
.environmentObject(navModel)
.environmentObject(sourceManager)
.environment(\.managedObjectContext, persistenceController.container.viewContext)
}

View file

@ -0,0 +1,32 @@
//
// SettingsModels.swift
// Ferrite
//
// Created by Brian Dashore on 8/11/22.
//
import Foundation
public enum DefaultMagnetActionType: Int {
// Let the user choose
case none = 0
// Open in actions come first
case webtor = 1
// Sharing actions come last
case shareMagnet = 2
}
public enum DefaultDebridActionType: Int {
// Let the user choose
case none = 0
// Open in actions come first
case outplayer = 1
case vlc = 2
case infuse = 3
// Sharing actions come last
case shareDownload = 4
}

View file

@ -124,9 +124,12 @@ public class DebridManager: ObservableObject {
let torrentLink = try await realDebrid.torrentInfo(debridID: realDebridId, selectedIndex: iaFile == nil ? 0 : iaFile?.batchFileIndex)
let downloadLink = try await realDebrid.unrestrictLink(debridDownloadLink: torrentLink)
Task { @MainActor in
let downloadUrlTask = Task { @MainActor in
realDebridDownloadUrl = downloadLink
}
// Prevent a race condition when setting the published variable
await downloadUrlTask.value
} catch {
Task { @MainActor in
toastModel?.toastDescription = "RealDebrid download error: \(error)"

View file

@ -5,6 +5,7 @@
// Created by Brian Dashore on 7/24/22.
//
import ActivityView
import SwiftUI
enum ViewTab {
@ -13,7 +14,10 @@ enum ViewTab {
case settings
}
@MainActor
class NavigationViewModel: ObservableObject {
var toastModel: ToastViewModel?
// Used between SearchResultsView and MagnetChoiceView
enum ChoiceSheetType: Identifiable {
var id: Int {
@ -25,6 +29,7 @@ class NavigationViewModel: ObservableObject {
}
@Published var currentChoiceSheet: ChoiceSheetType?
@Published var currentActivityItem: ActivityItem?
@Published var selectedTab: ViewTab = .search
@Published var showSearchProgress: Bool = false
@ -35,4 +40,61 @@ class NavigationViewModel: ObservableObject {
@Published var showSourceListEditor: Bool = false
@Published var selectedSourceList: SourceList?
@AppStorage("Actions.DefaultDebrid") var defaultDebridAction: DefaultDebridActionType = .none
@AppStorage("Actions.DefaultMagnet") var defaultMagnetAction: DefaultMagnetActionType = .none
public func runDebridAction(action: DefaultDebridActionType?, urlString: String) {
let selectedAction = action ?? defaultDebridAction
switch selectedAction {
case .none:
currentChoiceSheet = .magnet
case .outplayer:
if let downloadUrl = URL(string: "outplayer://\(urlString)") {
UIApplication.shared.open(downloadUrl)
} else {
toastModel?.toastDescription = "Could not create an Outplayer URL"
}
case .vlc:
if let downloadUrl = URL(string: "vlc://\(urlString)") {
UIApplication.shared.open(downloadUrl)
} else {
toastModel?.toastDescription = "Could not create a VLC URL"
}
case .infuse:
if let downloadUrl = URL(string: "infuse://x-callback-url/play?url=\(urlString)") {
UIApplication.shared.open(downloadUrl)
} else {
toastModel?.toastDescription = "Could not create a Infuse URL"
}
case .shareDownload:
if let downloadUrl = URL(string: urlString), currentChoiceSheet == nil {
currentActivityItem = ActivityItem(items: downloadUrl)
} else {
toastModel?.toastDescription = "Could not create object for sharing"
}
}
}
public func runMagnetAction(action: DefaultMagnetActionType?, searchResult: SearchResult) {
let selectedAction = action ?? defaultMagnetAction
switch selectedAction {
case .none:
currentChoiceSheet = .magnet
case .webtor:
if let url = URL(string: "https://webtor.io/#/show?magnet=\(searchResult.magnetLink)") {
UIApplication.shared.open(url)
} else {
toastModel?.toastDescription = "Could not create a WebTor URL"
}
case .shareMagnet:
if let magnetUrl = URL(string: searchResult.magnetLink), currentChoiceSheet == nil {
currentActivityItem = ActivityItem(items: magnetUrl)
} else {
toastModel?.toastDescription = "Could not create object for sharing"
}
}
}
}

View file

@ -12,7 +12,7 @@ struct BatchChoiceView: View {
@EnvironmentObject var debridManager: DebridManager
@EnvironmentObject var scrapingModel: ScrapingViewModel
@EnvironmentObject var navigationModel: NavigationViewModel
@EnvironmentObject var navModel: NavigationViewModel
var body: some View {
NavView {
@ -27,7 +27,7 @@ struct BatchChoiceView: View {
// The download may complete before this sheet dismisses
try? await Task.sleep(seconds: 1)
navigationModel.currentChoiceSheet = .magnet
navModel.runDebridAction(action: nil, urlString: debridManager.realDebridDownloadUrl)
debridManager.selectedRealDebridFile = nil
debridManager.selectedRealDebridItem = nil

View file

@ -5,6 +5,7 @@
// Created by Brian Dashore on 7/1/22.
//
import ActivityView
import SwiftUI
struct ContentView: View {
@ -96,6 +97,7 @@ struct ContentView: View {
}
.tint(.primary)
}
.activitySheet($navModel.currentActivityItem)
}
}

View file

@ -13,6 +13,7 @@ struct MagnetChoiceView: View {
@EnvironmentObject var scrapingModel: ScrapingViewModel
@EnvironmentObject var debridManager: DebridManager
@EnvironmentObject var navModel: NavigationViewModel
@AppStorage("RealDebrid.Enabled") var realDebridEnabled = false
@ -27,27 +28,15 @@ struct MagnetChoiceView: View {
if realDebridEnabled, debridManager.matchSearchResult(result: scrapingModel.selectedSearchResult) != .none {
Section("Real Debrid options") {
ListRowButtonView("Play on Outplayer", systemImage: "arrow.up.forward.app.fill") {
guard let downloadUrl = URL(string: "outplayer://\(debridManager.realDebridDownloadUrl)") else {
return
}
UIApplication.shared.open(downloadUrl)
navModel.runDebridAction(action: .outplayer, urlString: debridManager.realDebridDownloadUrl)
}
ListRowButtonView("Play on VLC", systemImage: "arrow.up.forward.app.fill") {
guard let downloadUrl = URL(string: "vlc://\(debridManager.realDebridDownloadUrl)") else {
return
}
UIApplication.shared.open(downloadUrl)
navModel.runDebridAction(action: .vlc, urlString: debridManager.realDebridDownloadUrl)
}
ListRowButtonView("Play on Infuse", systemImage: "arrow.up.forward.app.fill") {
guard let downloadUrl = URL(string: "infuse://x-callback-url/play?url=\(debridManager.realDebridDownloadUrl)") else {
return
}
UIApplication.shared.open(downloadUrl)
navModel.runDebridAction(action: .infuse, urlString: debridManager.realDebridDownloadUrl)
}
ListRowButtonView("Copy download URL", systemImage: "doc.on.doc.fill") {
@ -68,7 +57,6 @@ struct MagnetChoiceView: View {
}
activityItem = ActivityItem(items: url)
showActivityView.toggle()
}
}
}
@ -89,15 +77,12 @@ 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)
showActivityView.toggle()
}
}
ListRowButtonView("Open in WebTor", systemImage: "arrow.up.forward.app.fill") {
if let result = scrapingModel.selectedSearchResult,
let url = URL(string: "https://webtor.io/#/show?magnet=\(result.magnetLink)")
{
UIApplication.shared.open(url)
if let result = scrapingModel.selectedSearchResult {
navModel.runMagnetAction(action: .webtor, searchResult: result)
}
}
}

View file

@ -29,14 +29,14 @@ struct SearchResultsView: View {
case .full:
Task {
await debridManager.fetchRdDownload(searchResult: result)
navModel.currentChoiceSheet = .magnet
navModel.runDebridAction(action: nil, urlString: debridManager.realDebridDownloadUrl)
}
case .partial:
if debridManager.setSelectedRdResult(result: result) {
navModel.currentChoiceSheet = .batch
}
case .none:
navModel.currentChoiceSheet = .magnet
navModel.runMagnetAction(action: nil, searchResult: result)
}
} label: {
Text(result.title)

View file

@ -14,6 +14,8 @@ struct SettingsView: View {
let backgroundContext = PersistenceController.shared.backgroundContext
@AppStorage("RealDebrid.Enabled") var realDebridEnabled = false
@AppStorage("Actions.DefaultDebrid") var defaultDebridAction: DefaultDebridActionType = .none
@AppStorage("Actions.DefaultMagnet") var defaultMagnetAction: DefaultMagnetActionType = .none
@State private var isProcessing = false
@ -44,6 +46,56 @@ struct SettingsView: View {
NavigationLink("Source lists", destination: SettingsSourceListView())
}
Section("Default actions") {
if realDebridEnabled {
NavigationLink(
destination: DebridActionPickerView(),
label: {
HStack {
Text("Default debrid action")
Spacer()
Group {
switch defaultDebridAction {
case .none:
Text("User choice")
case .outplayer:
Text("Outplayer")
case .vlc:
Text("VLC")
case .infuse:
Text("Infuse")
case .shareDownload:
Text("Share")
}
}
.foregroundColor(.gray)
}
}
)
}
NavigationLink(
destination: MagnetActionPickerView(),
label: {
HStack {
Text("Default magnet action")
Spacer()
Group {
switch defaultMagnetAction {
case .none:
Text("User choice")
case .webtor:
Text("Webtor")
case .shareMagnet:
Text("Share")
}
}
.foregroundColor(.gray)
}
}
)
}
Section {
ListRowLinkView(text: "Report issues", link: "https://github.com/bdashore3/Ferrite/issues")

View file

@ -0,0 +1,54 @@
//
// DefaultActionsPickerViews.swift
// Ferrite
//
// Created by Brian Dashore on 8/11/22.
//
import SwiftUI
struct MagnetActionPickerView: View {
@AppStorage("Actions.DefaultMagnet") var defaultMagnetAction: DefaultMagnetActionType = .none
var body: some View {
List {
Picker(selection: $defaultMagnetAction, label: EmptyView()) {
Text("Let me choose")
.tag(DefaultMagnetActionType.none)
Text("Open in Webtor")
.tag(DefaultMagnetActionType.webtor)
Text("Share magnet link")
.tag(DefaultMagnetActionType.shareMagnet)
}
}
.pickerStyle(.inline)
.listStyle(.insetGrouped)
.navigationTitle("Default magnet action")
.navigationBarTitleDisplayMode(.inline)
}
}
struct DebridActionPickerView: View {
@AppStorage("Actions.DefaultDebrid") var defaultDebridAction: DefaultDebridActionType = .none
var body: some View {
List {
Picker(selection: $defaultDebridAction, label: EmptyView()) {
Text("Let me choose")
.tag(DefaultDebridActionType.none)
Text("Open in Outplayer")
.tag(DefaultDebridActionType.outplayer)
Text("Open in VLC")
.tag(DefaultDebridActionType.vlc)
Text("Open in Infuse")
.tag(DefaultDebridActionType.infuse)
Text("Share download link")
.tag(DefaultDebridActionType.shareDownload)
}
}
.pickerStyle(.inline)
.listStyle(.insetGrouped)
.navigationTitle("Default debrid action")
.navigationBarTitleDisplayMode(.inline)
}
}