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 <bdashore3@proton.me>
This commit is contained in:
parent
f622b7af05
commit
282783c460
4 changed files with 34 additions and 35 deletions
|
|
@ -11,8 +11,4 @@ extension Notification.Name {
|
||||||
static var didDeleteBookmark: Notification.Name {
|
static var didDeleteBookmark: Notification.Name {
|
||||||
Notification.Name("Deleted bookmark")
|
Notification.Name("Deleted bookmark")
|
||||||
}
|
}
|
||||||
|
|
||||||
static var didDeletePlugin: Notification.Name {
|
|
||||||
Notification.Name("Deleted plugin")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -89,12 +89,16 @@ public class PluginManager: ObservableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
print("Plugin fetch error: \(error)")
|
print("Plugin fetch error: \(error)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if underlying type is Source or Action
|
// forType required to guide generic inferences
|
||||||
func fetchFilteredPlugins<P: Plugin, PJ: PluginJson>(installedPlugins: FetchedResults<P>, searchText: String) -> [PJ] {
|
func fetchFilteredPlugins<P: Plugin, PJ: PluginJson>(
|
||||||
let availablePlugins: [PJ] = fetchCastedPlugins(PJ.self)
|
forType: PJ.Type,
|
||||||
|
installedPlugins: FetchedResults<P>,
|
||||||
|
searchText: String
|
||||||
|
) -> [PJ] {
|
||||||
|
let availablePlugins: [PJ] = fetchCastedPlugins(forType)
|
||||||
|
|
||||||
return availablePlugins
|
return availablePlugins
|
||||||
.filter { availablePlugin in
|
.filter { availablePlugin in
|
||||||
|
|
@ -112,13 +116,19 @@ public class PluginManager: ObservableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchUpdatedPlugins<P: Plugin, PJ: PluginJson>(installedPlugins: FetchedResults<P>, searchText: String) -> [PJ] {
|
func fetchUpdatedPlugins<P: Plugin, PJ: PluginJson>(
|
||||||
|
forType: PJ.Type,
|
||||||
|
installedPlugins: FetchedResults<P>,
|
||||||
|
searchText: String
|
||||||
|
) -> [PJ] {
|
||||||
var updatedPlugins: [PJ] = []
|
var updatedPlugins: [PJ] = []
|
||||||
let availablePlugins: [PJ] = fetchCastedPlugins(PJ.self)
|
let availablePlugins: [PJ] = fetchCastedPlugins(forType)
|
||||||
|
|
||||||
for plugin in installedPlugins {
|
for plugin in installedPlugins {
|
||||||
if let availablePlugin = availablePlugins.first(where: {
|
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
|
availablePlugin.version > plugin.version
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,6 @@ struct InstalledPluginButtonView<P: Plugin>: View {
|
||||||
if #available(iOS 15.0, *) {
|
if #available(iOS 15.0, *) {
|
||||||
Button(role: .destructive) {
|
Button(role: .destructive) {
|
||||||
PersistenceController.shared.delete(installedPlugin, context: backgroundContext)
|
PersistenceController.shared.delete(installedPlugin, context: backgroundContext)
|
||||||
NotificationCenter.default.post(name: .didDeletePlugin, object: nil)
|
|
||||||
} label: {
|
} label: {
|
||||||
Text("Remove")
|
Text("Remove")
|
||||||
Image(systemName: "trash")
|
Image(systemName: "trash")
|
||||||
|
|
@ -62,7 +61,6 @@ struct InstalledPluginButtonView<P: Plugin>: View {
|
||||||
} else {
|
} else {
|
||||||
Button {
|
Button {
|
||||||
PersistenceController.shared.delete(installedPlugin, context: backgroundContext)
|
PersistenceController.shared.delete(installedPlugin, context: backgroundContext)
|
||||||
NotificationCenter.default.post(name: .didDeletePlugin, object: nil)
|
|
||||||
} label: {
|
} label: {
|
||||||
Text("Remove")
|
Text("Remove")
|
||||||
Image(systemName: "trash")
|
Image(systemName: "trash")
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
//
|
//
|
||||||
// Created by Brian Dashore on 7/24/22.
|
// Created by Brian Dashore on 7/24/22.
|
||||||
//
|
//
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct PluginListView<P: Plugin, PJ: PluginJson>: View {
|
struct PluginListView<P: Plugin, PJ: PluginJson>: View {
|
||||||
|
|
@ -20,14 +19,19 @@ struct PluginListView<P: Plugin, PJ: PluginJson>: View {
|
||||||
@State private var isEditingSearch = false
|
@State private var isEditingSearch = false
|
||||||
@State private var isSearching = false
|
@State private var isSearching = false
|
||||||
|
|
||||||
@State private var filteredUpdatedPlugins: [PJ] = []
|
|
||||||
@State private var filteredAvailablePlugins: [PJ] = []
|
|
||||||
@State private var sourcePredicate: NSPredicate?
|
@State private var sourcePredicate: NSPredicate?
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
DynamicFetchRequest(predicate: sourcePredicate) { (installedPlugins: FetchedResults<P>) in
|
DynamicFetchRequest(predicate: sourcePredicate) { (installedPlugins: FetchedResults<P>) in
|
||||||
List {
|
List {
|
||||||
if !filteredUpdatedPlugins.isEmpty {
|
if
|
||||||
|
let filteredUpdatedPlugins = pluginManager.fetchUpdatedPlugins(
|
||||||
|
forType: PJ.self,
|
||||||
|
installedPlugins: installedPlugins,
|
||||||
|
searchText: searchText
|
||||||
|
),
|
||||||
|
!filteredUpdatedPlugins.isEmpty
|
||||||
|
{
|
||||||
Section(header: InlineHeader("Updates")) {
|
Section(header: InlineHeader("Updates")) {
|
||||||
ForEach(filteredUpdatedPlugins, id: \.self) { (updatedPlugin: PJ) in
|
ForEach(filteredUpdatedPlugins, id: \.self) { (updatedPlugin: PJ) in
|
||||||
PluginCatalogButtonView(availablePlugin: updatedPlugin, doUpsert: true)
|
PluginCatalogButtonView(availablePlugin: updatedPlugin, doUpsert: true)
|
||||||
|
|
@ -43,16 +47,17 @@ struct PluginListView<P: Plugin, PJ: PluginJson>: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !filteredAvailablePlugins.isEmpty {
|
if
|
||||||
|
let filteredAvailablePlugins = pluginManager.fetchFilteredPlugins(
|
||||||
|
forType: PJ.self,
|
||||||
|
installedPlugins: installedPlugins,
|
||||||
|
searchText: searchText
|
||||||
|
),
|
||||||
|
!filteredAvailablePlugins.isEmpty
|
||||||
|
{
|
||||||
Section(header: InlineHeader("Catalog")) {
|
Section(header: InlineHeader("Catalog")) {
|
||||||
ForEach(filteredAvailablePlugins, id: \.self) { availablePlugin in
|
ForEach(filteredAvailablePlugins, id: \.self) { availablePlugin in
|
||||||
if !installedPlugins.contains(where: {
|
PluginCatalogButtonView(availablePlugin: availablePlugin, doUpsert: false)
|
||||||
availablePlugin.name == $0.name &&
|
|
||||||
availablePlugin.listId == $0.listId &&
|
|
||||||
availablePlugin.author == $0.author
|
|
||||||
}) {
|
|
||||||
PluginCatalogButtonView(availablePlugin: availablePlugin, doUpsert: false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -65,18 +70,8 @@ struct PluginListView<P: Plugin, PJ: PluginJson>: View {
|
||||||
.environmentObject(navModel)
|
.environmentObject(navModel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.backport.onAppear {
|
|
||||||
filteredAvailablePlugins = pluginManager.fetchFilteredPlugins(installedPlugins: installedPlugins, searchText: searchText)
|
|
||||||
filteredUpdatedPlugins = pluginManager.fetchUpdatedPlugins(installedPlugins: installedPlugins, searchText: searchText)
|
|
||||||
}
|
|
||||||
.onChange(of: searchText) { _ in
|
.onChange(of: searchText) { _ in
|
||||||
sourcePredicate = searchText.isEmpty ? nil : NSPredicate(format: "name CONTAINS[cd] %@", searchText)
|
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue