Extract filter create/update/delete logic into separate services
This commit is contained in:
parent
83ca7f1321
commit
f71804f094
|
@ -61,6 +61,9 @@
|
||||||
D61F75AB293AF11400C0B37F /* FilterKeywordMO.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61F75AA293AF11400C0B37F /* FilterKeywordMO.swift */; };
|
D61F75AB293AF11400C0B37F /* FilterKeywordMO.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61F75AA293AF11400C0B37F /* FilterKeywordMO.swift */; };
|
||||||
D61F75AD293AF39000C0B37F /* Filter+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61F75AC293AF39000C0B37F /* Filter+Helpers.swift */; };
|
D61F75AD293AF39000C0B37F /* Filter+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61F75AC293AF39000C0B37F /* Filter+Helpers.swift */; };
|
||||||
D61F75AF293AF50C00C0B37F /* EditedFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61F75AE293AF50C00C0B37F /* EditedFilter.swift */; };
|
D61F75AF293AF50C00C0B37F /* EditedFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61F75AE293AF50C00C0B37F /* EditedFilter.swift */; };
|
||||||
|
D61F75B1293BD85300C0B37F /* CreateFilterService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61F75B0293BD85300C0B37F /* CreateFilterService.swift */; };
|
||||||
|
D61F75B3293BD89C00C0B37F /* UpdateFilterService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61F75B2293BD89C00C0B37F /* UpdateFilterService.swift */; };
|
||||||
|
D61F75B5293BD97400C0B37F /* DeleteFilterService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61F75B4293BD97400C0B37F /* DeleteFilterService.swift */; };
|
||||||
D620483423D3801D008A63EF /* LinkTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D620483323D3801D008A63EF /* LinkTextView.swift */; };
|
D620483423D3801D008A63EF /* LinkTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D620483323D3801D008A63EF /* LinkTextView.swift */; };
|
||||||
D620483623D38075008A63EF /* ContentTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D620483523D38075008A63EF /* ContentTextView.swift */; };
|
D620483623D38075008A63EF /* ContentTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D620483523D38075008A63EF /* ContentTextView.swift */; };
|
||||||
D620483823D38190008A63EF /* StatusContentTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D620483723D38190008A63EF /* StatusContentTextView.swift */; };
|
D620483823D38190008A63EF /* StatusContentTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D620483723D38190008A63EF /* StatusContentTextView.swift */; };
|
||||||
|
@ -438,6 +441,9 @@
|
||||||
D61F75AA293AF11400C0B37F /* FilterKeywordMO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterKeywordMO.swift; sourceTree = "<group>"; };
|
D61F75AA293AF11400C0B37F /* FilterKeywordMO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterKeywordMO.swift; sourceTree = "<group>"; };
|
||||||
D61F75AC293AF39000C0B37F /* Filter+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Filter+Helpers.swift"; sourceTree = "<group>"; };
|
D61F75AC293AF39000C0B37F /* Filter+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Filter+Helpers.swift"; sourceTree = "<group>"; };
|
||||||
D61F75AE293AF50C00C0B37F /* EditedFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditedFilter.swift; sourceTree = "<group>"; };
|
D61F75AE293AF50C00C0B37F /* EditedFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditedFilter.swift; sourceTree = "<group>"; };
|
||||||
|
D61F75B0293BD85300C0B37F /* CreateFilterService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateFilterService.swift; sourceTree = "<group>"; };
|
||||||
|
D61F75B2293BD89C00C0B37F /* UpdateFilterService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateFilterService.swift; sourceTree = "<group>"; };
|
||||||
|
D61F75B4293BD97400C0B37F /* DeleteFilterService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteFilterService.swift; sourceTree = "<group>"; };
|
||||||
D620483323D3801D008A63EF /* LinkTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkTextView.swift; sourceTree = "<group>"; };
|
D620483323D3801D008A63EF /* LinkTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkTextView.swift; sourceTree = "<group>"; };
|
||||||
D620483523D38075008A63EF /* ContentTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentTextView.swift; sourceTree = "<group>"; };
|
D620483523D38075008A63EF /* ContentTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentTextView.swift; sourceTree = "<group>"; };
|
||||||
D620483723D38190008A63EF /* StatusContentTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusContentTextView.swift; sourceTree = "<group>"; };
|
D620483723D38190008A63EF /* StatusContentTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusContentTextView.swift; sourceTree = "<group>"; };
|
||||||
|
@ -1567,6 +1573,9 @@
|
||||||
D6F6A551291F098700F496A8 /* RenameListService.swift */,
|
D6F6A551291F098700F496A8 /* RenameListService.swift */,
|
||||||
D6F6A553291F0D9600F496A8 /* DeleteListService.swift */,
|
D6F6A553291F0D9600F496A8 /* DeleteListService.swift */,
|
||||||
D61F75952937037800C0B37F /* ToggleFollowHashtagService.swift */,
|
D61F75952937037800C0B37F /* ToggleFollowHashtagService.swift */,
|
||||||
|
D61F75B0293BD85300C0B37F /* CreateFilterService.swift */,
|
||||||
|
D61F75B2293BD89C00C0B37F /* UpdateFilterService.swift */,
|
||||||
|
D61F75B4293BD97400C0B37F /* DeleteFilterService.swift */,
|
||||||
);
|
);
|
||||||
path = API;
|
path = API;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1949,6 +1958,7 @@
|
||||||
D6DF95C12533F5DE0027A9B6 /* RelationshipMO.swift in Sources */,
|
D6DF95C12533F5DE0027A9B6 /* RelationshipMO.swift in Sources */,
|
||||||
D6ADB6EE28EA74E8009924AB /* UIView+Configure.swift in Sources */,
|
D6ADB6EE28EA74E8009924AB /* UIView+Configure.swift in Sources */,
|
||||||
D623A5412635FB3C0095BD04 /* PollOptionView.swift in Sources */,
|
D623A5412635FB3C0095BD04 /* PollOptionView.swift in Sources */,
|
||||||
|
D61F75B1293BD85300C0B37F /* CreateFilterService.swift in Sources */,
|
||||||
D65C6BF525478A9C00A6E89C /* BackgroundableViewController.swift in Sources */,
|
D65C6BF525478A9C00A6E89C /* BackgroundableViewController.swift in Sources */,
|
||||||
D6AEBB4A23216F0400E5038B /* UnfollowAccountActivity.swift in Sources */,
|
D6AEBB4A23216F0400E5038B /* UnfollowAccountActivity.swift in Sources */,
|
||||||
D61DC84D28F500D200B82C6E /* ProfileViewController.swift in Sources */,
|
D61DC84D28F500D200B82C6E /* ProfileViewController.swift in Sources */,
|
||||||
|
@ -2055,6 +2065,7 @@
|
||||||
D67C57AF21E28EAD00C3118B /* Array+Uniques.swift in Sources */,
|
D67C57AF21E28EAD00C3118B /* Array+Uniques.swift in Sources */,
|
||||||
D6945C3223AC4D36005C403C /* HashtagTimelineViewController.swift in Sources */,
|
D6945C3223AC4D36005C403C /* HashtagTimelineViewController.swift in Sources */,
|
||||||
D647D92824257BEB0005044F /* AttachmentPreviewViewController.swift in Sources */,
|
D647D92824257BEB0005044F /* AttachmentPreviewViewController.swift in Sources */,
|
||||||
|
D61F75B5293BD97400C0B37F /* DeleteFilterService.swift in Sources */,
|
||||||
D66362752137068A00C9CBA2 /* Visibility+Helpers.swift in Sources */,
|
D66362752137068A00C9CBA2 /* Visibility+Helpers.swift in Sources */,
|
||||||
D6DFC6A0242C4CCC00ACC392 /* Weak.swift in Sources */,
|
D6DFC6A0242C4CCC00ACC392 /* Weak.swift in Sources */,
|
||||||
D6C693FC2162FE6F007D6A6D /* LoadingViewController.swift in Sources */,
|
D6C693FC2162FE6F007D6A6D /* LoadingViewController.swift in Sources */,
|
||||||
|
@ -2101,6 +2112,7 @@
|
||||||
D663625F2135C75500C9CBA2 /* ConversationMainStatusTableViewCell.swift in Sources */,
|
D663625F2135C75500C9CBA2 /* ConversationMainStatusTableViewCell.swift in Sources */,
|
||||||
D6E426B325337C7000C02E1C /* CustomEmojiImageView.swift in Sources */,
|
D6E426B325337C7000C02E1C /* CustomEmojiImageView.swift in Sources */,
|
||||||
D6D4DDD0212518A000E1C4BB /* AppDelegate.swift in Sources */,
|
D6D4DDD0212518A000E1C4BB /* AppDelegate.swift in Sources */,
|
||||||
|
D61F75B3293BD89C00C0B37F /* UpdateFilterService.swift in Sources */,
|
||||||
D6412B0924B0291E00F5412E /* MyProfileViewController.swift in Sources */,
|
D6412B0924B0291E00F5412E /* MyProfileViewController.swift in Sources */,
|
||||||
D6D12B56292D57E800D528E1 /* AccountCollectionViewCell.swift in Sources */,
|
D6D12B56292D57E800D528E1 /* AccountCollectionViewCell.swift in Sources */,
|
||||||
D6A6C10525B6138A00298D0F /* StatusTablePrefetching.swift in Sources */,
|
D6A6C10525B6138A00298D0F /* StatusTablePrefetching.swift in Sources */,
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
//
|
||||||
|
// CreateFilterService.swift
|
||||||
|
// Tusker
|
||||||
|
//
|
||||||
|
// Created by Shadowfacts on 12/3/22.
|
||||||
|
// Copyright © 2022 Shadowfacts. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Pachyderm
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
class CreateFilterService {
|
||||||
|
private let filter: EditedFilter
|
||||||
|
private let mastodonController: MastodonController
|
||||||
|
|
||||||
|
init(filter: EditedFilter, mastodonController: MastodonController) {
|
||||||
|
self.filter = filter
|
||||||
|
self.mastodonController = mastodonController
|
||||||
|
}
|
||||||
|
|
||||||
|
func run() async throws {
|
||||||
|
let updateFrom: AnyFilter
|
||||||
|
if mastodonController.instanceFeatures.filtersV2 {
|
||||||
|
let updates = filter.keywords.map {
|
||||||
|
FilterV2.KeywordUpdate.add(keyword: $0.keyword, wholeWord: $0.wholeWord)
|
||||||
|
}
|
||||||
|
let req = FilterV2.create(title: filter.title!, context: filter.contexts, expiresIn: filter.expiresIn, action: filter.action, keywords: updates)
|
||||||
|
let (updated, _) = try await mastodonController.run(req)
|
||||||
|
updateFrom = .v2(updated)
|
||||||
|
} else {
|
||||||
|
let req = Client.createFilterV1(phrase: filter.keywords.first!.keyword, context: filter.contexts, irreversible: nil, wholeWord: filter.keywords.first!.wholeWord, expiresIn: filter.expiresIn)
|
||||||
|
let (updated, _) = try await mastodonController.run(req)
|
||||||
|
updateFrom = .v1(updated)
|
||||||
|
}
|
||||||
|
let context = mastodonController.persistentContainer.viewContext
|
||||||
|
let mo = FilterMO(context: context)
|
||||||
|
mo.updateFrom(apiFilter: updateFrom, context: context)
|
||||||
|
mastodonController.persistentContainer.save(context: context)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
//
|
||||||
|
// DeleteFilterService.swift
|
||||||
|
// Tusker
|
||||||
|
//
|
||||||
|
// Created by Shadowfacts on 12/3/22.
|
||||||
|
// Copyright © 2022 Shadowfacts. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Pachyderm
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
class DeleteFilterService {
|
||||||
|
private let filter: FilterMO
|
||||||
|
private let mastodonController: MastodonController
|
||||||
|
|
||||||
|
init(filter: FilterMO, mastodonController: MastodonController) {
|
||||||
|
self.filter = filter
|
||||||
|
self.mastodonController = mastodonController
|
||||||
|
}
|
||||||
|
|
||||||
|
func run() async throws {
|
||||||
|
let req = FilterV1.delete(filter.id)
|
||||||
|
_ = try await mastodonController.run(req)
|
||||||
|
let context = mastodonController.persistentContainer.viewContext
|
||||||
|
context.delete(filter)
|
||||||
|
mastodonController.persistentContainer.save(context: context)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
//
|
||||||
|
// UpdateFilterService.swift
|
||||||
|
// Tusker
|
||||||
|
//
|
||||||
|
// Created by Shadowfacts on 12/3/22.
|
||||||
|
// Copyright © 2022 Shadowfacts. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Pachyderm
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
class UpdateFilterService {
|
||||||
|
private let filter: EditedFilter
|
||||||
|
private let mastodonController: MastodonController
|
||||||
|
|
||||||
|
init(filter: EditedFilter, mastodonController: MastodonController) {
|
||||||
|
self.filter = filter
|
||||||
|
self.mastodonController = mastodonController
|
||||||
|
}
|
||||||
|
|
||||||
|
func run() async throws {
|
||||||
|
let context = mastodonController.persistentContainer.viewContext
|
||||||
|
let mo = try context.fetch(FilterMO.fetchRequest(id: filter.id!)).first!
|
||||||
|
|
||||||
|
let updateFrom: AnyFilter
|
||||||
|
if mastodonController.instanceFeatures.filtersV2 {
|
||||||
|
var updates = filter.keywords.map {
|
||||||
|
if let id = $0.id {
|
||||||
|
return FilterV2.KeywordUpdate.update(id: id, keyword: $0.keyword, wholeWord: $0.wholeWord)
|
||||||
|
} else {
|
||||||
|
return FilterV2.KeywordUpdate.add(keyword: $0.keyword, wholeWord: $0.wholeWord)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for existing in mo.keywordMOs where !filter.keywords.contains(where: { existing.id == $0.id }) {
|
||||||
|
if let id = existing.id {
|
||||||
|
updates.append(.destroy(id: id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let req = FilterV2.update(filter.id!, title: filter.title ?? "", context: filter.contexts, expiresIn: filter.expiresIn, action: filter.action, keywords: updates)
|
||||||
|
let (updated, _) = try await mastodonController.run(req)
|
||||||
|
updateFrom = .v2(updated)
|
||||||
|
} else {
|
||||||
|
let req = FilterV1.update(filter.id!, phrase: filter.keywords.first!.keyword, context: filter.contexts, irreversible: false, wholeWord: filter.keywords.first!.wholeWord, expiresIn: filter.expiresIn)
|
||||||
|
let (updated, _) = try await mastodonController.run(req)
|
||||||
|
updateFrom = .v1(updated)
|
||||||
|
}
|
||||||
|
|
||||||
|
mo.updateFrom(apiFilter: updateFrom, context: context)
|
||||||
|
mastodonController.persistentContainer.save(context: context)
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,12 @@ public final class FilterMO: NSManagedObject {
|
||||||
return NSFetchRequest(entityName: "Filter")
|
return NSFetchRequest(entityName: "Filter")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@nonobjc public class func fetchRequest(id: String) -> NSFetchRequest<FilterMO> {
|
||||||
|
let req = NSFetchRequest<FilterMO>(entityName: "Filter")
|
||||||
|
req.predicate = NSPredicate(format: "id = %@", id)
|
||||||
|
return req
|
||||||
|
}
|
||||||
|
|
||||||
@NSManaged public var id: String
|
@NSManaged public var id: String
|
||||||
@NSManaged public var title: String?
|
@NSManaged public var title: String?
|
||||||
@NSManaged private var context: String
|
@NSManaged private var context: String
|
||||||
|
|
|
@ -29,7 +29,6 @@ struct EditFilterView: View {
|
||||||
|
|
||||||
@ObservedObject var filter: EditedFilter
|
@ObservedObject var filter: EditedFilter
|
||||||
let create: Bool
|
let create: Bool
|
||||||
let saveFilter: (EditedFilter) async throws -> Void
|
|
||||||
@EnvironmentObject private var mastodonController: MastodonController
|
@EnvironmentObject private var mastodonController: MastodonController
|
||||||
@Environment(\.dismiss) private var dismiss
|
@Environment(\.dismiss) private var dismiss
|
||||||
@State private var originalFilter: EditedFilter
|
@State private var originalFilter: EditedFilter
|
||||||
|
@ -37,10 +36,9 @@ struct EditFilterView: View {
|
||||||
@State private var isSaving = false
|
@State private var isSaving = false
|
||||||
@State private var saveError: (any Error)?
|
@State private var saveError: (any Error)?
|
||||||
|
|
||||||
init(filter: EditedFilter, create: Bool, saveFilter: @escaping (EditedFilter) async throws -> Void) {
|
init(filter: EditedFilter, create: Bool) {
|
||||||
self.filter = filter
|
self.filter = filter
|
||||||
self.create = create
|
self.create = create
|
||||||
self.saveFilter = saveFilter
|
|
||||||
self._originalFilter = State(wrappedValue: EditedFilter(copying: filter))
|
self._originalFilter = State(wrappedValue: EditedFilter(copying: filter))
|
||||||
if let expiresIn = filter.expiresIn {
|
if let expiresIn = filter.expiresIn {
|
||||||
self._expiresIn = State(wrappedValue: Self.expiresInOptions.min(by: { a, b in
|
self._expiresIn = State(wrappedValue: Self.expiresInOptions.min(by: { a, b in
|
||||||
|
@ -158,16 +156,7 @@ struct EditFilterView: View {
|
||||||
.progressViewStyle(.circular)
|
.progressViewStyle(.circular)
|
||||||
} else {
|
} else {
|
||||||
Button(create ? "Create" : "Save") {
|
Button(create ? "Create" : "Save") {
|
||||||
Task {
|
saveFilter()
|
||||||
do {
|
|
||||||
isSaving = true
|
|
||||||
try await saveFilter(filter)
|
|
||||||
dismiss()
|
|
||||||
} catch {
|
|
||||||
isSaving = false
|
|
||||||
saveError = error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.disabled(!filter.isValid(for: mastodonController) || !edited)
|
.disabled(!filter.isValid(for: mastodonController) || !edited)
|
||||||
}
|
}
|
||||||
|
@ -182,6 +171,23 @@ struct EditFilterView: View {
|
||||||
edited = true
|
edited = true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func saveFilter() {
|
||||||
|
Task {
|
||||||
|
do {
|
||||||
|
isSaving = true
|
||||||
|
if create {
|
||||||
|
try await CreateFilterService(filter: filter, mastodonController: mastodonController).run()
|
||||||
|
} else {
|
||||||
|
try await UpdateFilterService(filter: filter, mastodonController: mastodonController).run()
|
||||||
|
}
|
||||||
|
dismiss()
|
||||||
|
} catch {
|
||||||
|
isSaving = false
|
||||||
|
saveError = error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct FilterContextToggleStyle: ToggleStyle {
|
private struct FilterContextToggleStyle: ToggleStyle {
|
||||||
|
|
|
@ -25,7 +25,6 @@ struct FiltersList: View {
|
||||||
@FetchRequest(sortDescriptors: []) private var filters: FetchedResults<FilterMO>
|
@FetchRequest(sortDescriptors: []) private var filters: FetchedResults<FilterMO>
|
||||||
@Environment(\.dismiss) private var dismiss
|
@Environment(\.dismiss) private var dismiss
|
||||||
@State private var deletionError: (any Error)?
|
@State private var deletionError: (any Error)?
|
||||||
@State private var updatingError: (any Error)?
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if #available(iOS 16.0, *) {
|
if #available(iOS 16.0, *) {
|
||||||
|
@ -52,15 +51,15 @@ struct FiltersList: View {
|
||||||
List {
|
List {
|
||||||
Section {
|
Section {
|
||||||
NavigationLink {
|
NavigationLink {
|
||||||
EditFilterView(filter: EditedFilter(), create: true, saveFilter: createFilter)
|
EditFilterView(filter: EditedFilter(), create: true)
|
||||||
} label: {
|
} label: {
|
||||||
Label("Add Filter", systemImage: "plus")
|
Label("Add Filter", systemImage: "plus")
|
||||||
.foregroundColor(.accentColor)
|
.foregroundColor(.accentColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
filtersSection(unexpiredFilters)
|
filtersSection(unexpiredFilters, header: Text("Active"))
|
||||||
filtersSection(expiredFilters)
|
filtersSection(expiredFilters, header: Text("Expired"))
|
||||||
}
|
}
|
||||||
.navigationTitle(Text("Filters"))
|
.navigationTitle(Text("Filters"))
|
||||||
.navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
|
@ -78,23 +77,16 @@ struct FiltersList: View {
|
||||||
}, message: { error in
|
}, message: { error in
|
||||||
Text(error.localizedDescription)
|
Text(error.localizedDescription)
|
||||||
})
|
})
|
||||||
.alertWithData("Error Update Filter", data: $updatingError, actions: { _ in
|
|
||||||
Button("OK") {
|
|
||||||
self.updatingError = nil
|
|
||||||
}
|
|
||||||
}, message: { error in
|
|
||||||
Text(error.localizedDescription)
|
|
||||||
})
|
|
||||||
.task {
|
.task {
|
||||||
await mastodonController.loadFilters()
|
await mastodonController.loadFilters()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func filtersSection(_ filters: [FilterMO]) -> some View {
|
private func filtersSection(_ filters: [FilterMO], header: some View) -> some View {
|
||||||
Section {
|
Section {
|
||||||
ForEach(filters, id: \.id) { filter in
|
ForEach(filters, id: \.id) { filter in
|
||||||
NavigationLink {
|
NavigationLink {
|
||||||
EditFilterView(filter: EditedFilter(filter), create: false, saveFilter: updateFilter)
|
EditFilterView(filter: EditedFilter(filter), create: false)
|
||||||
} label: {
|
} label: {
|
||||||
FilterRow(filter: filter)
|
FilterRow(filter: filter)
|
||||||
}
|
}
|
||||||
|
@ -112,73 +104,20 @@ struct FiltersList: View {
|
||||||
deleteFilter(filter)
|
deleteFilter(filter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
header
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func deleteFilter(_ filter: FilterMO) {
|
private func deleteFilter(_ filter: FilterMO) {
|
||||||
Task { @MainActor in
|
Task {
|
||||||
let req = FilterV1.delete(filter.id)
|
|
||||||
do {
|
do {
|
||||||
_ = try await mastodonController.run(req)
|
try await DeleteFilterService(filter: filter, mastodonController: mastodonController).run()
|
||||||
let context = mastodonController.persistentContainer.viewContext
|
|
||||||
context.delete(filter)
|
|
||||||
mastodonController.persistentContainer.save(context: context)
|
|
||||||
} catch {
|
} catch {
|
||||||
self.deletionError = error
|
self.deletionError = error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateFilter(_ filter: EditedFilter) async throws {
|
|
||||||
let mo = filters.first(where: { $0.id == filter.id })!
|
|
||||||
|
|
||||||
let updateFrom: AnyFilter
|
|
||||||
if mastodonController.instanceFeatures.filtersV2 {
|
|
||||||
var updates = filter.keywords.map {
|
|
||||||
if let id = $0.id {
|
|
||||||
return FilterV2.KeywordUpdate.update(id: id, keyword: $0.keyword, wholeWord: $0.wholeWord)
|
|
||||||
} else {
|
|
||||||
return FilterV2.KeywordUpdate.add(keyword: $0.keyword, wholeWord: $0.wholeWord)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for existing in mo.keywordMOs where !filter.keywords.contains(where: { existing.id == $0.id }) {
|
|
||||||
if let id = existing.id {
|
|
||||||
updates.append(.destroy(id: id))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let req = FilterV2.update(filter.id!, title: filter.title ?? "", context: filter.contexts, expiresIn: filter.expiresIn, action: filter.action, keywords: updates)
|
|
||||||
let (updated, _) = try await mastodonController.run(req)
|
|
||||||
updateFrom = .v2(updated)
|
|
||||||
} else {
|
|
||||||
let req = FilterV1.update(filter.id!, phrase: filter.keywords.first!.keyword, context: filter.contexts, irreversible: false, wholeWord: filter.keywords.first!.wholeWord, expiresIn: filter.expiresIn)
|
|
||||||
let (updated, _) = try await mastodonController.run(req)
|
|
||||||
updateFrom = .v1(updated)
|
|
||||||
}
|
|
||||||
|
|
||||||
let context = mastodonController.persistentContainer.viewContext
|
|
||||||
mo.updateFrom(apiFilter: updateFrom, context: context)
|
|
||||||
mastodonController.persistentContainer.save(context: context)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func createFilter(_ filter: EditedFilter) async throws {
|
|
||||||
let updateFrom: AnyFilter
|
|
||||||
if mastodonController.instanceFeatures.filtersV2 {
|
|
||||||
let updates = filter.keywords.map {
|
|
||||||
FilterV2.KeywordUpdate.add(keyword: $0.keyword, wholeWord: $0.wholeWord)
|
|
||||||
}
|
|
||||||
let req = FilterV2.create(title: filter.title!, context: filter.contexts, expiresIn: filter.expiresIn, action: filter.action, keywords: updates)
|
|
||||||
let (updated, _) = try await mastodonController.run(req)
|
|
||||||
updateFrom = .v2(updated)
|
|
||||||
} else {
|
|
||||||
let req = Client.createFilterV1(phrase: filter.keywords.first!.keyword, context: filter.contexts, irreversible: nil, wholeWord: filter.keywords.first!.wholeWord, expiresIn: filter.expiresIn)
|
|
||||||
let (updated, _) = try await mastodonController.run(req)
|
|
||||||
updateFrom = .v1(updated)
|
|
||||||
}
|
|
||||||
let context = mastodonController.persistentContainer.viewContext
|
|
||||||
let mo = FilterMO(context: context)
|
|
||||||
mo.updateFrom(apiFilter: updateFrom, context: context)
|
|
||||||
mastodonController.persistentContainer.save(context: context)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//struct FiltersView_Previews: PreviewProvider {
|
//struct FiltersView_Previews: PreviewProvider {
|
||||||
|
|
Loading…
Reference in New Issue