Tusker/Tusker/Screens/Filters/FiltersView.swift

143 lines
4.3 KiB
Swift

//
// FiltersView.swift
// Tusker
//
// Created by Shadowfacts on 11/30/22.
// Copyright © 2022 Shadowfacts. All rights reserved.
//
import SwiftUI
import Pachyderm
struct FiltersView: View {
let mastodonController: MastodonController
var body: some View {
FiltersList(mastodonController: mastodonController)
.environment(\.managedObjectContext, mastodonController.persistentContainer.viewContext)
}
}
struct FiltersList: View {
let mastodonController: MastodonController
@FetchRequest(sortDescriptors: []) private var filters: FetchedResults<FilterMO>
@Environment(\.dismiss) private var dismiss
@State private var deletionError: (any Error)?
@State private var updatingError: (any Error)?
var body: some View {
if #available(iOS 16.0, *) {
NavigationStack {
navigationBody
}
} else {
NavigationView {
navigationBody
}
.navigationViewStyle(.stack)
}
}
private var unexpiredFilters: [FilterMO] {
filters.filter { $0.expiresAt == nil || $0.expiresAt! > Date() }.sorted(using: SemiCaseSensitiveComparator.keyPath(\.phrase))
}
private var expiredFilters: [FilterMO] {
filters.filter { $0.expiresAt != nil && $0.expiresAt! <= Date() }.sorted(using: SemiCaseSensitiveComparator.keyPath(\.phrase))
}
private var navigationBody: some View {
List {
filtersSection(unexpiredFilters)
filtersSection(expiredFilters)
}
.navigationTitle(Text("Filters"))
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .confirmationAction) {
Button("Done") {
dismiss()
}
}
}
.alertWithData("Error Deleting Filter", data: $deletionError, actions: { _ in
Button("OK") {
self.deletionError = nil
}
}, message: { error in
Text(error.localizedDescription)
})
.alertWithData("Error Update Filter", data: $updatingError, actions: { _ in
Button("OK") {
self.updatingError = nil
}
}, message: { error in
Text(error.localizedDescription)
})
.task {
await mastodonController.loadFilters()
}
}
private func filtersSection(_ filters: [FilterMO]) -> some View {
Section {
ForEach(filters, id: \.id) { filter in
NavigationLink {
EditFilterView(filter: filter) {
updateFilter(filter)
}
} label: {
FilterRow(filter: filter)
}
.contextMenu {
Button(role: .destructive) {
deleteFilter(filter)
} label: {
Text("Delete Filter")
}
}
}
.onDelete { indices in
for filter in indices.map({ filters[$0] }) {
deleteFilter(filter)
}
}
}
}
private func deleteFilter(_ filter: FilterMO) {
Task { @MainActor in
let req = Filter.delete(filter.id)
do {
_ = try await mastodonController.run(req)
let context = mastodonController.persistentContainer.viewContext
context.delete(filter)
mastodonController.persistentContainer.save(context: context)
} catch {
self.deletionError = error
}
}
}
private func updateFilter(_ filter: FilterMO) {
Task { @MainActor in
let req = Filter.update(filter)
do {
let (updated, _) = try await mastodonController.run(req)
filter.updateFrom(apiFilter: updated)
mastodonController.persistentContainer.save(context: mastodonController.persistentContainer.viewContext)
} catch {
self.updatingError = error
}
}
}
}
//struct FiltersView_Previews: PreviewProvider {
// static var previews: some View {
// FiltersView()
// }
//}