mirror of
https://github.com/Ferrite-iOS/Ferrite.git
synced 2026-01-11 20:10:27 +00:00
Actions: Fix default action settings
Since actions use a new API, update default actions to use the same API rather than the legacy models. If an action is removed, a prompt will tell the user to change their default debrid/magnet action and default to the choice sheet. Also add extra UI fixes and cleanup. Signed-off-by: kingbri <bdashore3@proton.me>
This commit is contained in:
parent
0661ed66f3
commit
f622b7af05
19 changed files with 301 additions and 299 deletions
|
|
@ -81,8 +81,7 @@
|
|||
0C84F4842895BFED0074B7C9 /* SourceHtmlParser+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C84F47C2895BFED0074B7C9 /* SourceHtmlParser+CoreDataClass.swift */; };
|
||||
0C84F4852895BFED0074B7C9 /* SourceHtmlParser+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C84F47D2895BFED0074B7C9 /* SourceHtmlParser+CoreDataProperties.swift */; };
|
||||
0C871BDF29994D9D005279AC /* FilterLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C871BDE29994D9D005279AC /* FilterLabelView.swift */; };
|
||||
0C95D8D828A55B03005E22B3 /* DefaultActionsPickerViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C95D8D728A55B03005E22B3 /* DefaultActionsPickerViews.swift */; };
|
||||
0C95D8DA28A55BB6005E22B3 /* SettingsModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C95D8D928A55BB6005E22B3 /* SettingsModels.swift */; };
|
||||
0C95D8D828A55B03005E22B3 /* DefaultActionPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C95D8D728A55B03005E22B3 /* DefaultActionPickerView.swift */; };
|
||||
0CA05457288EE58200850554 /* SettingsPluginListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CA05456288EE58200850554 /* SettingsPluginListView.swift */; };
|
||||
0CA05459288EE9E600850554 /* PluginManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CA05458288EE9E600850554 /* PluginManager.swift */; };
|
||||
0CA0545B288EEA4E00850554 /* PluginListEditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CA0545A288EEA4E00850554 /* PluginListEditorView.swift */; };
|
||||
|
|
@ -204,8 +203,7 @@
|
|||
0C84F47C2895BFED0074B7C9 /* SourceHtmlParser+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SourceHtmlParser+CoreDataClass.swift"; sourceTree = "<group>"; };
|
||||
0C84F47D2895BFED0074B7C9 /* SourceHtmlParser+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SourceHtmlParser+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
0C871BDE29994D9D005279AC /* FilterLabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterLabelView.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>"; };
|
||||
0C95D8D728A55B03005E22B3 /* DefaultActionPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultActionPickerView.swift; sourceTree = "<group>"; };
|
||||
0CA05456288EE58200850554 /* SettingsPluginListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsPluginListView.swift; sourceTree = "<group>"; };
|
||||
0CA05458288EE9E600850554 /* PluginManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PluginManager.swift; sourceTree = "<group>"; };
|
||||
0CA0545A288EEA4E00850554 /* PluginListEditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PluginListEditorView.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -346,7 +344,6 @@
|
|||
0C422E7F293542F300486D65 /* PremiumizeModels.swift */,
|
||||
0C0167DB29293FA900B65783 /* RealDebridModels.swift */,
|
||||
0C41BC6428C2AEB900B47DD6 /* SearchModels.swift */,
|
||||
0C95D8D928A55BB6005E22B3 /* SettingsModels.swift */,
|
||||
0C0D50E4288DFE7F0035ECC8 /* SourceModels.swift */,
|
||||
0C3E00D7296F5B9A00ECECB2 /* PluginModels.swift */,
|
||||
);
|
||||
|
|
@ -438,7 +435,7 @@
|
|||
0C44E2AE28D52E8A007711AE /* BackupsView.swift */,
|
||||
0CA05456288EE58200850554 /* SettingsPluginListView.swift */,
|
||||
0CA0545A288EEA4E00850554 /* PluginListEditorView.swift */,
|
||||
0C95D8D728A55B03005E22B3 /* DefaultActionsPickerViews.swift */,
|
||||
0C95D8D728A55B03005E22B3 /* DefaultActionPickerView.swift */,
|
||||
0C10848A28BD9A38008F0BA6 /* SettingsAppVersionView.swift */,
|
||||
);
|
||||
path = Settings;
|
||||
|
|
@ -763,7 +760,7 @@
|
|||
0CC389532970AD900066D06F /* Action+CoreDataClass.swift in Sources */,
|
||||
0C03EB72296F619900162E9A /* PluginList+CoreDataProperties.swift in Sources */,
|
||||
0C572D4C2993FC2A003EEC05 /* ViewDidAppearHandler.swift in Sources */,
|
||||
0C95D8D828A55B03005E22B3 /* DefaultActionsPickerViews.swift in Sources */,
|
||||
0C95D8D828A55B03005E22B3 /* DefaultActionPickerView.swift in Sources */,
|
||||
0C44E2AF28D52E8A007711AE /* BackupsView.swift in Sources */,
|
||||
0CA148E1288903F000DE2211 /* Collection.swift in Sources */,
|
||||
0C750744289B003E004B3906 /* SourceRssParser+CoreDataClass.swift in Sources */,
|
||||
|
|
@ -778,7 +775,6 @@
|
|||
0CA148D8288903F000DE2211 /* ActionChoiceView.swift in Sources */,
|
||||
0C41BC6528C2AEB900B47DD6 /* SearchModels.swift in Sources */,
|
||||
0C68135028BC1A2D00FAD890 /* GithubWrapper.swift in Sources */,
|
||||
0C95D8DA28A55BB6005E22B3 /* SettingsModels.swift in Sources */,
|
||||
0CA148E3288903F000DE2211 /* Task.swift in Sources */,
|
||||
0CA148E7288903F000DE2211 /* ToastViewModel.swift in Sources */,
|
||||
0C6C7C9D29315292002DF910 /* AllDebridModels.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
//
|
||||
// SettingsModels.swift
|
||||
// Ferrite
|
||||
//
|
||||
// Created by Brian Dashore on 8/11/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public enum DefaultMagnetActionType: Int, CaseIterable {
|
||||
// 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, CaseIterable {
|
||||
// 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
|
||||
}
|
||||
|
|
@ -8,16 +8,16 @@
|
|||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
class NavigationViewModel: ObservableObject {
|
||||
public class NavigationViewModel: ObservableObject {
|
||||
var toastModel: ToastViewModel?
|
||||
|
||||
// Used between SearchResultsView and MagnetChoiceView
|
||||
enum ChoiceSheetType: Identifiable {
|
||||
var id: Int {
|
||||
public enum ChoiceSheetType: Identifiable {
|
||||
public var id: Int {
|
||||
hashValue
|
||||
}
|
||||
|
||||
case magnet
|
||||
case action
|
||||
case batch
|
||||
case activity
|
||||
}
|
||||
|
|
@ -66,82 +66,4 @@ class NavigationViewModel: ObservableObject {
|
|||
|
||||
@Published var libraryPickerSelection: LibraryPickerSegment = .bookmarks
|
||||
@Published var pluginPickerSelection: PluginPickerSegment = .sources
|
||||
|
||||
@AppStorage("Actions.DefaultDebrid") var defaultDebridAction: DefaultDebridActionType = .none
|
||||
@AppStorage("Actions.DefaultMagnet") var defaultMagnetAction: DefaultMagnetActionType = .none
|
||||
|
||||
// TODO: Fix for new Actions API
|
||||
public func runDebridAction(urlString: String, _ action: DefaultDebridActionType? = nil) {
|
||||
currentChoiceSheet = .magnet
|
||||
/*
|
||||
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?.updateToastDescription("Could not create an Outplayer URL")
|
||||
}
|
||||
case .vlc:
|
||||
if let downloadUrl = URL(string: "vlc://\(urlString)") {
|
||||
UIApplication.shared.open(downloadUrl)
|
||||
} else {
|
||||
toastModel?.updateToastDescription("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?.updateToastDescription("Could not create a Infuse URL")
|
||||
}
|
||||
case .shareDownload:
|
||||
if let downloadUrl = URL(string: urlString), currentChoiceSheet == nil {
|
||||
activityItems = [downloadUrl]
|
||||
currentChoiceSheet = .activity
|
||||
} else {
|
||||
toastModel?.updateToastDescription("Could not create object for sharing")
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// TODO: Fix for new Actions API
|
||||
public func runMagnetAction(magnet: Magnet?, _ action: DefaultMagnetActionType? = nil) {
|
||||
currentChoiceSheet = .magnet
|
||||
// Fall back to selected magnet if the provided magnet is nil
|
||||
/*
|
||||
let magnet = magnet ?? selectedMagnet
|
||||
guard let magnetLink = magnet?.link else {
|
||||
toastModel?.updateToastDescription("Could not run your action because the magnet link is invalid.")
|
||||
print("Magnet action error: The magnet link is invalid.")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
let selectedAction = action ?? defaultMagnetAction
|
||||
|
||||
switch selectedAction {
|
||||
case .none:
|
||||
currentChoiceSheet = .magnet
|
||||
case .webtor:
|
||||
if let url = URL(string: "https://webtor.io/#/show?magnet=\(magnetLink)") {
|
||||
UIApplication.shared.open(url)
|
||||
} else {
|
||||
toastModel?.updateToastDescription("Could not create a WebTor URL")
|
||||
}
|
||||
case .shareMagnet:
|
||||
if let magnetUrl = URL(string: magnetLink),
|
||||
currentChoiceSheet == nil
|
||||
{
|
||||
activityItems = [magnetUrl]
|
||||
currentChoiceSheet = .activity
|
||||
} else {
|
||||
toastModel?.updateToastDescription("Could not create object for sharing")
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ public class PluginManager: ObservableObject {
|
|||
@Published var availableSources: [SourceJson] = []
|
||||
@Published var availableActions: [ActionJson] = []
|
||||
|
||||
@Published var showBrokenDefaultActionAlert = false
|
||||
|
||||
@MainActor
|
||||
public func fetchPluginsFromUrl() async {
|
||||
let pluginListRequest = PluginList.fetchRequest()
|
||||
|
|
@ -162,6 +164,58 @@ public class PluginManager: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
public func runDebridAction(urlString: String?, currentChoiceSheet: inout NavigationViewModel.ChoiceSheetType?) {
|
||||
let context = PersistenceController.shared.backgroundContext
|
||||
|
||||
if
|
||||
let defaultDebridActionName = UserDefaults.standard.string(forKey: "Actions.DefaultDebridName"),
|
||||
let defaultDebridActionList = UserDefaults.standard.string(forKey: "Actions.DefaultDebridList")
|
||||
{
|
||||
let actionFetchRequest = Action.fetchRequest()
|
||||
actionFetchRequest.fetchLimit = 1
|
||||
actionFetchRequest.predicate = NSPredicate(format: "name == %@ AND listId == %@", defaultDebridActionName, defaultDebridActionList)
|
||||
|
||||
if let fetchedAction = try? context.fetch(actionFetchRequest).first {
|
||||
runDeeplinkAction(fetchedAction, urlString: urlString)
|
||||
} else {
|
||||
currentChoiceSheet = .action
|
||||
UserDefaults.standard.set(nil, forKey: "Actions.DefaultDebridName")
|
||||
UserDefaults.standard.set(nil, forKey: "Action.DefaultDebridList")
|
||||
|
||||
showBrokenDefaultActionAlert.toggle()
|
||||
}
|
||||
} else {
|
||||
currentChoiceSheet = .action
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
public func runMagnetAction(urlString: String?, currentChoiceSheet: inout NavigationViewModel.ChoiceSheetType?) {
|
||||
let context = PersistenceController.shared.backgroundContext
|
||||
|
||||
if
|
||||
let defaultMagnetActionName = UserDefaults.standard.string(forKey: "Actions.DefaultMagnetName"),
|
||||
let defaultMagnetActionList = UserDefaults.standard.string(forKey: "Actions.DefaultMagnetList")
|
||||
{
|
||||
let actionFetchRequest = Action.fetchRequest()
|
||||
actionFetchRequest.fetchLimit = 1
|
||||
actionFetchRequest.predicate = NSPredicate(format: "name == %@ AND listId == %@", defaultMagnetActionName, defaultMagnetActionList)
|
||||
|
||||
if let fetchedAction = try? context.fetch(actionFetchRequest).first {
|
||||
runDeeplinkAction(fetchedAction, urlString: urlString)
|
||||
} else {
|
||||
currentChoiceSheet = .action
|
||||
UserDefaults.standard.set(nil, forKey: "Actions.DefaultMagnetName")
|
||||
UserDefaults.standard.set(nil, forKey: "Actions.DefaultMagnetList")
|
||||
|
||||
showBrokenDefaultActionAlert.toggle()
|
||||
}
|
||||
} else {
|
||||
currentChoiceSheet = .action
|
||||
}
|
||||
}
|
||||
|
||||
// The iOS version of Ferrite only runs deeplink actions
|
||||
@MainActor
|
||||
public func runDeeplinkAction(_ action: Action, urlString: String?) {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import SwiftUI
|
|||
struct AllDebridCloudView: View {
|
||||
@EnvironmentObject var debridManager: DebridManager
|
||||
@EnvironmentObject var navModel: NavigationViewModel
|
||||
@EnvironmentObject var pluginManager: PluginManager
|
||||
|
||||
@Binding var searchText: String
|
||||
|
||||
|
|
@ -38,7 +39,10 @@ struct AllDebridCloudView: View {
|
|||
if !debridManager.downloadUrl.isEmpty {
|
||||
historyInfo.url = debridManager.downloadUrl
|
||||
PersistenceController.shared.createHistory(historyInfo, performSave: true)
|
||||
navModel.runDebridAction(urlString: debridManager.downloadUrl)
|
||||
pluginManager.runDebridAction(
|
||||
urlString: debridManager.downloadUrl,
|
||||
currentChoiceSheet: &navModel.currentChoiceSheet
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import SwiftUIX
|
|||
struct PremiumizeCloudView: View {
|
||||
@EnvironmentObject var debridManager: DebridManager
|
||||
@EnvironmentObject var navModel: NavigationViewModel
|
||||
@EnvironmentObject var pluginManager: PluginManager
|
||||
|
||||
@Binding var searchText: String
|
||||
|
||||
|
|
@ -38,7 +39,10 @@ struct PremiumizeCloudView: View {
|
|||
performSave: true
|
||||
)
|
||||
|
||||
navModel.runDebridAction(urlString: debridManager.downloadUrl)
|
||||
pluginManager.runDebridAction(
|
||||
urlString: debridManager.downloadUrl,
|
||||
currentChoiceSheet: &navModel.currentChoiceSheet
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import SwiftUI
|
|||
struct RealDebridCloudView: View {
|
||||
@EnvironmentObject var navModel: NavigationViewModel
|
||||
@EnvironmentObject var debridManager: DebridManager
|
||||
@EnvironmentObject var pluginManager: PluginManager
|
||||
|
||||
@Binding var searchText: String
|
||||
|
||||
|
|
@ -35,7 +36,10 @@ struct RealDebridCloudView: View {
|
|||
performSave: true
|
||||
)
|
||||
|
||||
navModel.runDebridAction(urlString: debridManager.downloadUrl)
|
||||
pluginManager.runDebridAction(
|
||||
urlString: debridManager.downloadUrl,
|
||||
currentChoiceSheet: &navModel.currentChoiceSheet
|
||||
)
|
||||
}
|
||||
.backport.tint(.primary)
|
||||
}
|
||||
|
|
@ -72,7 +76,10 @@ struct RealDebridCloudView: View {
|
|||
historyInfo.url = debridManager.downloadUrl
|
||||
PersistenceController.shared.createHistory(historyInfo, performSave: true)
|
||||
|
||||
navModel.runDebridAction(urlString: debridManager.downloadUrl)
|
||||
pluginManager.runDebridAction(
|
||||
urlString: debridManager.downloadUrl,
|
||||
currentChoiceSheet: &navModel.currentChoiceSheet
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ struct HistoryButtonView: View {
|
|||
@EnvironmentObject var toastModel: ToastViewModel
|
||||
@EnvironmentObject var navModel: NavigationViewModel
|
||||
@EnvironmentObject var debridManager: DebridManager
|
||||
@EnvironmentObject var pluginManager: PluginManager
|
||||
|
||||
let entry: HistoryEntry
|
||||
|
||||
|
|
@ -23,14 +24,20 @@ struct HistoryButtonView: View {
|
|||
if url.starts(with: "https://") {
|
||||
Task {
|
||||
debridManager.downloadUrl = url
|
||||
navModel.runDebridAction(urlString: url)
|
||||
pluginManager.runDebridAction(
|
||||
urlString: url,
|
||||
currentChoiceSheet: &navModel.currentChoiceSheet
|
||||
)
|
||||
|
||||
if navModel.currentChoiceSheet != .magnet {
|
||||
if navModel.currentChoiceSheet != .action {
|
||||
debridManager.downloadUrl = ""
|
||||
}
|
||||
}
|
||||
} else {
|
||||
navModel.runMagnetAction(magnet: Magnet(hash: nil, link: url))
|
||||
pluginManager.runMagnetAction(
|
||||
urlString: url,
|
||||
currentChoiceSheet: &navModel.currentChoiceSheet
|
||||
)
|
||||
}
|
||||
} else {
|
||||
toastModel.updateToastDescription("URL invalid. Cannot load this history entry. Please delete it.")
|
||||
|
|
|
|||
|
|
@ -12,6 +12,11 @@ struct SourceSettingsView: View {
|
|||
|
||||
@EnvironmentObject var navModel: NavigationViewModel
|
||||
|
||||
@FetchRequest(
|
||||
entity: PluginList.entity(),
|
||||
sortDescriptors: []
|
||||
) var pluginLists: FetchedResults<PluginList>
|
||||
|
||||
var body: some View {
|
||||
NavView {
|
||||
List {
|
||||
|
|
@ -32,10 +37,12 @@ struct SourceSettingsView: View {
|
|||
Group {
|
||||
Text("ID: \(selectedSource.id)")
|
||||
|
||||
if let listId = selectedSource.listId {
|
||||
Text("List ID: \(listId)")
|
||||
if let pluginList = pluginLists.first(where: { $0.id == selectedSource.listId })
|
||||
{
|
||||
Text("List: \(pluginList.name)")
|
||||
Text("List ID: \(pluginList.id.uuidString)")
|
||||
} else {
|
||||
Text("No list ID found. This source should be removed.")
|
||||
Text("No plugin list found. This source should be removed.")
|
||||
}
|
||||
}
|
||||
.foregroundColor(.secondary)
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ struct SearchResultButtonView: View {
|
|||
|
||||
@EnvironmentObject var navModel: NavigationViewModel
|
||||
@EnvironmentObject var debridManager: DebridManager
|
||||
@EnvironmentObject var pluginManager: PluginManager
|
||||
|
||||
var result: SearchResult
|
||||
|
||||
|
|
@ -42,9 +43,12 @@ struct SearchResultButtonView: View {
|
|||
performSave: true
|
||||
)
|
||||
|
||||
navModel.runDebridAction(urlString: debridManager.downloadUrl)
|
||||
pluginManager.runDebridAction(
|
||||
urlString: debridManager.downloadUrl,
|
||||
currentChoiceSheet: &navModel.currentChoiceSheet
|
||||
)
|
||||
|
||||
if navModel.currentChoiceSheet != .magnet {
|
||||
if navModel.currentChoiceSheet != .action {
|
||||
debridManager.downloadUrl = ""
|
||||
}
|
||||
}
|
||||
|
|
@ -68,7 +72,10 @@ struct SearchResultButtonView: View {
|
|||
performSave: true
|
||||
)
|
||||
|
||||
navModel.runMagnetAction(magnet: result.magnet)
|
||||
pluginManager.runMagnetAction(
|
||||
urlString: result.magnet.link,
|
||||
currentChoiceSheet: &navModel.currentChoiceSheet
|
||||
)
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,109 @@
|
|||
//
|
||||
// DefaultActionsPickerViews.swift
|
||||
// Ferrite
|
||||
//
|
||||
// Created by Brian Dashore on 8/11/22.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct DefaultActionPickerView: View {
|
||||
@EnvironmentObject var toastModel: ToastViewModel
|
||||
|
||||
let actionRequirement: ActionRequirement
|
||||
@Binding var defaultActionName: String?
|
||||
@Binding var defaultActionList: String?
|
||||
|
||||
@FetchRequest(
|
||||
entity: Action.entity(),
|
||||
sortDescriptors: []
|
||||
) var actions: FetchedResults<Action>
|
||||
|
||||
@FetchRequest(
|
||||
entity: PluginList.entity(),
|
||||
sortDescriptors: []
|
||||
) var pluginLists: FetchedResults<PluginList>
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
UserChoiceButton(
|
||||
defaultActionName: $defaultActionName,
|
||||
defaultActionList: $defaultActionList,
|
||||
pluginLists: pluginLists
|
||||
)
|
||||
|
||||
ForEach(actions.filter { $0.requires.contains(actionRequirement.rawValue) }, id: \.id) { action in
|
||||
Button {
|
||||
if let actionListId = action.listId?.uuidString {
|
||||
defaultActionName = action.name
|
||||
defaultActionList = actionListId
|
||||
} else {
|
||||
toastModel.updateToastDescription(
|
||||
"Default action error: This action doesn't have a corresponding plugin list! Please uninstall the action"
|
||||
)
|
||||
}
|
||||
} label: {
|
||||
HStack {
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text(action.name)
|
||||
|
||||
Group {
|
||||
if let pluginList = pluginLists.first(where: { $0.id == action.listId }) {
|
||||
Text("List: \(pluginList.name)")
|
||||
|
||||
Text(pluginList.id.uuidString)
|
||||
.font(.caption)
|
||||
} else {
|
||||
Text("No plugin list found")
|
||||
.font(.caption)
|
||||
}
|
||||
}
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
Spacer()
|
||||
|
||||
if
|
||||
let defaultActionList,
|
||||
action.listId?.uuidString == defaultActionList,
|
||||
action.name == defaultActionName
|
||||
{
|
||||
Image(systemName: "checkmark")
|
||||
.foregroundColor(.blue)
|
||||
}
|
||||
}
|
||||
}
|
||||
.backport.tint(.primary)
|
||||
}
|
||||
}
|
||||
.listStyle(.insetGrouped)
|
||||
.inlinedList(inset: -20)
|
||||
.navigationTitle("Default \(actionRequirement == .debrid ? "debrid" : "magnet") action")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
}
|
||||
|
||||
private struct UserChoiceButton: View {
|
||||
@Binding var defaultActionName: String?
|
||||
@Binding var defaultActionList: String?
|
||||
var pluginLists: FetchedResults<PluginList>
|
||||
|
||||
var body: some View {
|
||||
Button {
|
||||
defaultActionName = nil
|
||||
defaultActionList = nil
|
||||
} label: {
|
||||
HStack {
|
||||
Text("Let me choose")
|
||||
Spacer()
|
||||
|
||||
// Force "Let me choose" if the name OR list ID is nil
|
||||
// Prevents any mismatches
|
||||
if defaultActionName == nil || pluginLists.contains(where: { $0.id.uuidString == defaultActionList }) {
|
||||
Image(systemName: "checkmark")
|
||||
.foregroundColor(.blue)
|
||||
}
|
||||
}
|
||||
}
|
||||
.backport.tint(.primary)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
//
|
||||
// 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 {
|
||||
ForEach(DefaultMagnetActionType.allCases, id: \.self) { action in
|
||||
Button {
|
||||
defaultMagnetAction = action
|
||||
} label: {
|
||||
HStack {
|
||||
Text(fetchPickerChoiceName(choice: action))
|
||||
Spacer()
|
||||
if action == defaultMagnetAction {
|
||||
Image(systemName: "checkmark")
|
||||
.foregroundColor(.blue)
|
||||
}
|
||||
}
|
||||
}
|
||||
.backport.tint(.primary)
|
||||
}
|
||||
}
|
||||
.listStyle(.insetGrouped)
|
||||
.inlinedList(inset: -20)
|
||||
.navigationTitle("Default magnet action")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
|
||||
func fetchPickerChoiceName(choice: DefaultMagnetActionType) -> String {
|
||||
switch choice {
|
||||
case .none:
|
||||
return "Let me choose"
|
||||
case .webtor:
|
||||
return "Open in Webtor"
|
||||
case .shareMagnet:
|
||||
return "Share magnet link"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct DebridActionPickerView: View {
|
||||
@AppStorage("Actions.DefaultDebrid") var defaultDebridAction: DefaultDebridActionType = .none
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
ForEach(DefaultDebridActionType.allCases, id: \.self) { action in
|
||||
Button {
|
||||
defaultDebridAction = action
|
||||
} label: {
|
||||
HStack {
|
||||
Text(fetchPickerChoiceName(choice: action))
|
||||
Spacer()
|
||||
if action == defaultDebridAction {
|
||||
Image(systemName: "checkmark")
|
||||
.foregroundColor(.blue)
|
||||
}
|
||||
}
|
||||
}
|
||||
.backport.tint(.primary)
|
||||
}
|
||||
}
|
||||
.listStyle(.insetGrouped)
|
||||
.inlinedList(inset: -20)
|
||||
.navigationTitle("Default debrid action")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
|
||||
func fetchPickerChoiceName(choice: DefaultDebridActionType) -> String {
|
||||
switch choice {
|
||||
case .none:
|
||||
return "Let me choose"
|
||||
case .outplayer:
|
||||
return "Open in Outplayer"
|
||||
case .vlc:
|
||||
return "Open in VLC"
|
||||
case .infuse:
|
||||
return "Open in Infuse"
|
||||
case .shareDownload:
|
||||
return "Share download link"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -30,12 +30,13 @@ struct SettingsPluginListView: View {
|
|||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text(pluginList.name)
|
||||
|
||||
Text(pluginList.author)
|
||||
.foregroundColor(.gray)
|
||||
Group {
|
||||
Text(pluginList.author)
|
||||
|
||||
Text("ID: \(pluginList.id)")
|
||||
.font(.caption)
|
||||
.foregroundColor(.gray)
|
||||
Text("ID: \(pluginList.id)")
|
||||
.font(.caption)
|
||||
}
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
.padding(.vertical, 2)
|
||||
.contextMenu {
|
||||
|
|
|
|||
|
|
@ -44,6 +44,22 @@ struct LibraryView: View {
|
|||
DebridCloudView(searchText: $searchText)
|
||||
}
|
||||
}
|
||||
.overlay {
|
||||
switch navModel.libraryPickerSelection {
|
||||
case .bookmarks:
|
||||
if bookmarks.isEmpty {
|
||||
EmptyInstructionView(title: "No Bookmarks", message: "Add a bookmark from search results")
|
||||
}
|
||||
case .history:
|
||||
if history.isEmpty {
|
||||
EmptyInstructionView(title: "No History", message: "Start watching to build history")
|
||||
}
|
||||
case .debridCloud:
|
||||
if debridManager.selectedDebridType == nil {
|
||||
EmptyInstructionView(title: "Cloud Unavailable", message: "Listing is not available for this service")
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("Library")
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
|
|
@ -83,22 +99,6 @@ struct LibraryView: View {
|
|||
}
|
||||
.environment(\.editMode, $editMode)
|
||||
}
|
||||
.overlay {
|
||||
switch navModel.libraryPickerSelection {
|
||||
case .bookmarks:
|
||||
if bookmarks.isEmpty {
|
||||
EmptyInstructionView(title: "No Bookmarks", message: "Add a bookmark from search results")
|
||||
}
|
||||
case .history:
|
||||
if history.isEmpty {
|
||||
EmptyInstructionView(title: "No History", message: "Start watching to build history")
|
||||
}
|
||||
case .debridCloud:
|
||||
if debridManager.selectedDebridType == nil {
|
||||
EmptyInstructionView(title: "Cloud Unavailable", message: "Listing is not available for this service")
|
||||
}
|
||||
}
|
||||
}
|
||||
.onChange(of: navModel.libraryPickerSelection) { _ in
|
||||
editMode = .inactive
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ struct MainView: View {
|
|||
}
|
||||
.sheet(item: $navModel.currentChoiceSheet) { item in
|
||||
switch item {
|
||||
case .magnet:
|
||||
case .action:
|
||||
ActionChoiceView()
|
||||
.environmentObject(debridManager)
|
||||
.environmentObject(scrapingModel)
|
||||
|
|
@ -139,7 +139,9 @@ struct MainView: View {
|
|||
.backport.alert(
|
||||
isPresented: $showUpdateAlert,
|
||||
title: "Update available",
|
||||
message: "Ferrite \(releaseVersionString) can be downloaded. \n\nThis alert can be disabled in Settings.",
|
||||
message:
|
||||
"Ferrite \(releaseVersionString) can be downloaded. \n\n" +
|
||||
"This alert can be disabled in Settings.",
|
||||
buttons: [
|
||||
.init("Download") {
|
||||
guard let releaseUrl = URL(string: releaseUrlString) else {
|
||||
|
|
|
|||
|
|
@ -44,6 +44,22 @@ struct PluginsView: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
.overlay {
|
||||
if checkedForPlugins {
|
||||
switch navModel.pluginPickerSelection {
|
||||
case .sources:
|
||||
if sources.isEmpty && pluginManager.availableSources.isEmpty {
|
||||
EmptyInstructionView(title: "No Sources", message: "Add a plugin list in Settings")
|
||||
}
|
||||
case .actions:
|
||||
if actions.isEmpty && pluginManager.availableActions.isEmpty {
|
||||
EmptyInstructionView(title: "No Actions", message: "Add a plugin list in Settings")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ProgressView()
|
||||
}
|
||||
}
|
||||
.backport.onAppear {
|
||||
viewTask = Task {
|
||||
await pluginManager.fetchPluginsFromUrl()
|
||||
|
|
@ -71,22 +87,6 @@ struct PluginsView: View {
|
|||
.environmentObject(navModel)
|
||||
}
|
||||
}
|
||||
.overlay {
|
||||
if checkedForPlugins {
|
||||
switch navModel.pluginPickerSelection {
|
||||
case .sources:
|
||||
if sources.isEmpty && pluginManager.availableSources.isEmpty {
|
||||
EmptyInstructionView(title: "No Sources", message: "Add a plugin list in Settings")
|
||||
}
|
||||
case .actions:
|
||||
if actions.isEmpty && pluginManager.availableActions.isEmpty {
|
||||
EmptyInstructionView(title: "No Actions", message: "Add a plugin list in Settings")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ProgressView()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,11 @@ struct SettingsView: View {
|
|||
|
||||
@AppStorage("Updates.AutomaticNotifs") var autoUpdateNotifs = true
|
||||
|
||||
@AppStorage("Actions.DefaultDebrid") var defaultDebridAction: DefaultDebridActionType = .none
|
||||
@AppStorage("Actions.DefaultMagnet") var defaultMagnetAction: DefaultMagnetActionType = .none
|
||||
@AppStorage("Actions.DefaultDebridName") var defaultDebridActionName: String?
|
||||
@AppStorage("Actions.DefaultDebridList") var defaultDebridActionList: String?
|
||||
|
||||
@AppStorage("Actions.DefaultMagnetName") var defaultMagnetActionName: String?
|
||||
@AppStorage("Actions.DefaultMagnetList") var defaultMagnetActionList: String?
|
||||
|
||||
var body: some View {
|
||||
NavView {
|
||||
|
|
@ -94,50 +97,40 @@ struct SettingsView: View {
|
|||
}
|
||||
|
||||
Section(header: InlineHeader("Default actions")) {
|
||||
if debridManager.enabledDebrids.count > 0 {
|
||||
//if debridManager.enabledDebrids.count > 0 {
|
||||
NavigationLink(
|
||||
destination: DebridActionPickerView(),
|
||||
destination: DefaultActionPickerView(
|
||||
actionRequirement: .debrid,
|
||||
defaultActionName: $defaultDebridActionName,
|
||||
defaultActionList: $defaultDebridActionList
|
||||
),
|
||||
label: {
|
||||
HStack {
|
||||
Text("Default debrid action")
|
||||
Text("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)
|
||||
|
||||
// TODO: Maybe make this check for nil list as well?
|
||||
Text(defaultDebridActionName.map { $0 } ?? "User choice")
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
//}
|
||||
|
||||
NavigationLink(
|
||||
destination: MagnetActionPickerView(),
|
||||
destination: DefaultActionPickerView(
|
||||
actionRequirement: .magnet,
|
||||
defaultActionName: $defaultMagnetActionName,
|
||||
defaultActionList: $defaultMagnetActionList
|
||||
),
|
||||
label: {
|
||||
HStack {
|
||||
Text("Default magnet action")
|
||||
Text("Magnet action")
|
||||
Spacer()
|
||||
Group {
|
||||
switch defaultMagnetAction {
|
||||
case .none:
|
||||
Text("User choice")
|
||||
case .webtor:
|
||||
Text("Webtor")
|
||||
case .shareMagnet:
|
||||
Text("Share")
|
||||
}
|
||||
}
|
||||
.foregroundColor(.gray)
|
||||
|
||||
// TODO: Maybe make this check for nil list as well?
|
||||
Text(defaultMagnetActionName.map { $0 } ?? "User choice")
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -112,6 +112,13 @@ struct ActionChoiceView: View {
|
|||
AppActivityView(activityItems: navModel.activityItems)
|
||||
}
|
||||
}
|
||||
.backport.alert(
|
||||
isPresented: $pluginManager.showBrokenDefaultActionAlert,
|
||||
title: "Action not found",
|
||||
message:
|
||||
"The default action could not be run. The action choice sheet has been opened. \n\n" +
|
||||
"Please check your default actions in Settings"
|
||||
)
|
||||
.onDisappear {
|
||||
debridManager.downloadUrl = ""
|
||||
navModel.selectedTitle = ""
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ struct BatchChoiceView: View {
|
|||
@EnvironmentObject var debridManager: DebridManager
|
||||
@EnvironmentObject var scrapingModel: ScrapingViewModel
|
||||
@EnvironmentObject var navModel: NavigationViewModel
|
||||
@EnvironmentObject var pluginManager: PluginManager
|
||||
|
||||
let backgroundContext = PersistenceController.shared.backgroundContext
|
||||
|
||||
|
|
@ -83,7 +84,10 @@ struct BatchChoiceView: View {
|
|||
PersistenceController.shared.createHistory(selectedHistoryInfo, performSave: true)
|
||||
}
|
||||
|
||||
navModel.runDebridAction(urlString: debridManager.downloadUrl, nil)
|
||||
pluginManager.runDebridAction(
|
||||
urlString: debridManager.downloadUrl,
|
||||
currentChoiceSheet: &navModel.currentChoiceSheet
|
||||
)
|
||||
}
|
||||
|
||||
debridManager.clearSelectedDebridItems()
|
||||
|
|
|
|||
Loading…
Reference in a new issue