From 282783c46064ee7323c54e24a11575fc2ff58bbe Mon Sep 17 00:00:00 2001 From: kingbri Date: Thu, 2 Mar 2023 11:06:57 -0500 Subject: [PATCH] Plugins: Fix list sync in view Plugin entries were not syncing properly inside the plugins view. Instead of adding events to update filtered lists, make it so that these filtered lists are updated on state changes. This is the intended method of reactive programming and removes complexity from filtering logic. Signed-off-by: kingbri --- Ferrite/Extensions/NotificationCenter.swift | 4 -- Ferrite/ViewModels/PluginManager.swift | 24 ++++++++---- .../Buttons/InstalledPluginButtonView.swift | 2 - .../Plugin/PluginListView.swift | 39 ++++++++----------- 4 files changed, 34 insertions(+), 35 deletions(-) diff --git a/Ferrite/Extensions/NotificationCenter.swift b/Ferrite/Extensions/NotificationCenter.swift index 63599a9..7bc0db5 100644 --- a/Ferrite/Extensions/NotificationCenter.swift +++ b/Ferrite/Extensions/NotificationCenter.swift @@ -11,8 +11,4 @@ extension Notification.Name { static var didDeleteBookmark: Notification.Name { Notification.Name("Deleted bookmark") } - - static var didDeletePlugin: Notification.Name { - Notification.Name("Deleted plugin") - } } diff --git a/Ferrite/ViewModels/PluginManager.swift b/Ferrite/ViewModels/PluginManager.swift index f1fdd29..b370b64 100644 --- a/Ferrite/ViewModels/PluginManager.swift +++ b/Ferrite/ViewModels/PluginManager.swift @@ -89,12 +89,16 @@ public class PluginManager: ObservableObject { } print("Plugin fetch error: \(error)") - } + } } - // Check if underlying type is Source or Action - func fetchFilteredPlugins(installedPlugins: FetchedResults

, searchText: String) -> [PJ] { - let availablePlugins: [PJ] = fetchCastedPlugins(PJ.self) + // forType required to guide generic inferences + func fetchFilteredPlugins( + forType: PJ.Type, + installedPlugins: FetchedResults

, + searchText: String + ) -> [PJ] { + let availablePlugins: [PJ] = fetchCastedPlugins(forType) return availablePlugins .filter { availablePlugin in @@ -112,13 +116,19 @@ public class PluginManager: ObservableObject { } } - func fetchUpdatedPlugins(installedPlugins: FetchedResults

, searchText: String) -> [PJ] { + func fetchUpdatedPlugins( + forType: PJ.Type, + installedPlugins: FetchedResults

, + searchText: String + ) -> [PJ] { var updatedPlugins: [PJ] = [] - let availablePlugins: [PJ] = fetchCastedPlugins(PJ.self) + let availablePlugins: [PJ] = fetchCastedPlugins(forType) for plugin in installedPlugins { if let availablePlugin = availablePlugins.first(where: { - plugin.listId == $0.listId && plugin.name == $0.name && plugin.author == $0.author + plugin.listId == $0.listId && + plugin.name == $0.name && + plugin.author == $0.author }), availablePlugin.version > plugin.version { diff --git a/Ferrite/Views/ComponentViews/Plugin/Buttons/InstalledPluginButtonView.swift b/Ferrite/Views/ComponentViews/Plugin/Buttons/InstalledPluginButtonView.swift index 0efdce4..b99061d 100644 --- a/Ferrite/Views/ComponentViews/Plugin/Buttons/InstalledPluginButtonView.swift +++ b/Ferrite/Views/ComponentViews/Plugin/Buttons/InstalledPluginButtonView.swift @@ -54,7 +54,6 @@ struct InstalledPluginButtonView: View { if #available(iOS 15.0, *) { Button(role: .destructive) { PersistenceController.shared.delete(installedPlugin, context: backgroundContext) - NotificationCenter.default.post(name: .didDeletePlugin, object: nil) } label: { Text("Remove") Image(systemName: "trash") @@ -62,7 +61,6 @@ struct InstalledPluginButtonView: View { } else { Button { PersistenceController.shared.delete(installedPlugin, context: backgroundContext) - NotificationCenter.default.post(name: .didDeletePlugin, object: nil) } label: { Text("Remove") Image(systemName: "trash") diff --git a/Ferrite/Views/ComponentViews/Plugin/PluginListView.swift b/Ferrite/Views/ComponentViews/Plugin/PluginListView.swift index cc8232d..9c5c5f6 100644 --- a/Ferrite/Views/ComponentViews/Plugin/PluginListView.swift +++ b/Ferrite/Views/ComponentViews/Plugin/PluginListView.swift @@ -4,7 +4,6 @@ // // Created by Brian Dashore on 7/24/22. // - import SwiftUI struct PluginListView: View { @@ -20,14 +19,19 @@ struct PluginListView: View { @State private var isEditingSearch = false @State private var isSearching = false - @State private var filteredUpdatedPlugins: [PJ] = [] - @State private var filteredAvailablePlugins: [PJ] = [] @State private var sourcePredicate: NSPredicate? var body: some View { DynamicFetchRequest(predicate: sourcePredicate) { (installedPlugins: FetchedResults

) in List { - if !filteredUpdatedPlugins.isEmpty { + if + let filteredUpdatedPlugins = pluginManager.fetchUpdatedPlugins( + forType: PJ.self, + installedPlugins: installedPlugins, + searchText: searchText + ), + !filteredUpdatedPlugins.isEmpty + { Section(header: InlineHeader("Updates")) { ForEach(filteredUpdatedPlugins, id: \.self) { (updatedPlugin: PJ) in PluginCatalogButtonView(availablePlugin: updatedPlugin, doUpsert: true) @@ -43,16 +47,17 @@ struct PluginListView: View { } } - if !filteredAvailablePlugins.isEmpty { + if + let filteredAvailablePlugins = pluginManager.fetchFilteredPlugins( + forType: PJ.self, + installedPlugins: installedPlugins, + searchText: searchText + ), + !filteredAvailablePlugins.isEmpty + { Section(header: InlineHeader("Catalog")) { ForEach(filteredAvailablePlugins, id: \.self) { availablePlugin in - if !installedPlugins.contains(where: { - availablePlugin.name == $0.name && - availablePlugin.listId == $0.listId && - availablePlugin.author == $0.author - }) { - PluginCatalogButtonView(availablePlugin: availablePlugin, doUpsert: false) - } + PluginCatalogButtonView(availablePlugin: availablePlugin, doUpsert: false) } } } @@ -65,18 +70,8 @@ struct PluginListView: View { .environmentObject(navModel) } } - .backport.onAppear { - filteredAvailablePlugins = pluginManager.fetchFilteredPlugins(installedPlugins: installedPlugins, searchText: searchText) - filteredUpdatedPlugins = pluginManager.fetchUpdatedPlugins(installedPlugins: installedPlugins, searchText: searchText) - } .onChange(of: searchText) { _ in sourcePredicate = searchText.isEmpty ? nil : NSPredicate(format: "name CONTAINS[cd] %@", searchText) - filteredAvailablePlugins = pluginManager.fetchFilteredPlugins(installedPlugins: installedPlugins, searchText: searchText) - filteredUpdatedPlugins = pluginManager.fetchUpdatedPlugins(installedPlugins: installedPlugins, searchText: searchText) - } - .onReceive(NotificationCenter.default.publisher(for: .didDeletePlugin)) { _ in - filteredAvailablePlugins = pluginManager.fetchFilteredPlugins(installedPlugins: installedPlugins, searchText: searchText) - filteredUpdatedPlugins = pluginManager.fetchUpdatedPlugins(installedPlugins: installedPlugins, searchText: searchText) } } }