149 lines
4.6 KiB
Swift
149 lines
4.6 KiB
Swift
//
|
|
// CustomizeTimelinesView.swift
|
|
// Tusker
|
|
//
|
|
// Created by Shadowfacts on 11/30/22.
|
|
// Copyright © 2022 Shadowfacts. All rights reserved.
|
|
//
|
|
|
|
import SwiftUI
|
|
import Pachyderm
|
|
|
|
struct CustomizeTimelinesView: View {
|
|
let mastodonController: MastodonController
|
|
|
|
var body: some View {
|
|
CustomizeTimelinesList()
|
|
.environmentObject(mastodonController)
|
|
.environment(\.managedObjectContext, mastodonController.persistentContainer.viewContext)
|
|
}
|
|
|
|
}
|
|
|
|
struct CustomizeTimelinesList: View {
|
|
@EnvironmentObject private var mastodonController: MastodonController
|
|
@ObservedObject private var preferences = Preferences.shared
|
|
@FetchRequest(sortDescriptors: []) private var filters: FetchedResults<FilterMO>
|
|
@Environment(\.dismiss) private var dismiss
|
|
@State private var deletionError: (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(\.titleOrKeyword))
|
|
}
|
|
|
|
private var expiredFilters: [FilterMO] {
|
|
filters.filter { $0.expiresAt != nil && $0.expiresAt! <= Date() }.sorted(using: SemiCaseSensitiveComparator.keyPath(\.titleOrKeyword))
|
|
}
|
|
|
|
private var navigationBody: some View {
|
|
List {
|
|
PinnedTimelinesView(accountPreferences: mastodonController.accountPreferences)
|
|
|
|
Section {
|
|
Toggle(isOn: $preferences.hideReblogsInTimelines) {
|
|
Text("Hide Reblogs")
|
|
}
|
|
Toggle(isOn: $preferences.hideRepliesInTimelines) {
|
|
Text("Hide Replies")
|
|
}
|
|
} header: {
|
|
Text("Home Timeline")
|
|
}
|
|
|
|
Section {
|
|
filtersForEach(unexpiredFilters)
|
|
|
|
NavigationLink {
|
|
EditFilterView(filter: EditedFilter(), create: true, originallyExpired: false)
|
|
} label: {
|
|
Label("Add Filter", systemImage: "plus")
|
|
.foregroundColor(.accentColor)
|
|
}
|
|
} header: {
|
|
Text("Active Filters")
|
|
}
|
|
|
|
if !expiredFilters.isEmpty {
|
|
Section {
|
|
filtersForEach(expiredFilters)
|
|
} header: {
|
|
Text("Expired Filters")
|
|
}
|
|
}
|
|
}
|
|
.navigationTitle(Text("Customize Timelines"))
|
|
.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)
|
|
})
|
|
.task {
|
|
await mastodonController.loadFilters()
|
|
}
|
|
}
|
|
|
|
@ViewBuilder
|
|
private func filtersForEach(_ filters: [FilterMO]) -> some View {
|
|
if !filters.isEmpty {
|
|
ForEach(filters, id: \.id) { filter in
|
|
NavigationLink {
|
|
EditFilterView(filter: EditedFilter(filter), create: false, originallyExpired: filter.expiresAt != nil && filter.expiresAt! <= Date())
|
|
} label: {
|
|
FilterRow(filter: filter)
|
|
}
|
|
.contextMenu {
|
|
Button(role: .destructive) {
|
|
deleteFilter(filter)
|
|
} label: {
|
|
Label("Delete Filter", systemImage: "trash")
|
|
}
|
|
}
|
|
}
|
|
.onDelete { indices in
|
|
for filter in indices.map({ filters[$0] }) {
|
|
deleteFilter(filter)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private func deleteFilter(_ filter: FilterMO) {
|
|
Task {
|
|
do {
|
|
try await DeleteFilterService(filter: filter, mastodonController: mastodonController).run()
|
|
} catch {
|
|
self.deletionError = error
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//struct FiltersView_Previews: PreviewProvider {
|
|
// static var previews: some View {
|
|
// FiltersView()
|
|
// }
|
|
//}
|