blob: acc8a6e6ae14c378bbab8cfad3b79d82ea142855 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
import SwiftUI
struct GenericListView<T: Identifiable & Hashable & GenericItem>: View {
@EnvironmentObject private var settings: SettingsManager
@EnvironmentObject private var manager: BooruManager
@Binding var selectedTab: Int
@State private var searchText: String = ""
@State private var isShowingRemoveAllConfirmation = false
@Binding var isPresented: Bool
let allowBookmarking: Bool
let title: String
let emptyMessage: String
let emptyIcon: String
let emptyDescription: String
let removeAllMessage: String
let removeAllButtonText: String
let items: [T]
let removeAction: (IndexSet) -> Void
let removeActionUUID: (UUID) -> Void
let removeAllAction: () -> Void
var filteredItems: [T] {
guard !searchText.isEmpty else {
return items
}
return items.filter { item in
item.tags
.joined(separator: " ")
.lowercased()
.contains(searchText.lowercased())
}
}
var body: some View {
NavigationStack {
VStack {
if items.isEmpty {
ContentUnavailableView(
emptyMessage,
systemImage: emptyIcon,
description: Text(emptyDescription)
)
} else {
List {
if filteredItems.isEmpty, !searchText.isEmpty {
Text("No matching items found")
}
ForEach(
filteredItems.sorted { $0.date > $1.date },
id: \.id
) { item in
itemButtonContent(item: item)
}
.onDelete(perform: removeAction)
}
}
}
}
.navigationTitle(title)
.searchable(text: $searchText)
.refreshable { settings.syncFromCloud() }
.toolbar {
ToolbarItem {
Button(action: {
isShowingRemoveAllConfirmation = true
}) {
Label("Remove All", systemImage: "trash")
}
}
}
.confirmationDialog(
removeAllMessage,
isPresented: $isShowingRemoveAllConfirmation
) {
Button(removeAllButtonText) {
removeAllAction()
}
}
}
func itemButtonContent(item: T) -> some View {
Button(action: {
let previousProvider = settings.preferredBooru
settings.preferredBooru = item.provider
manager.searchText = item.tags.joined(separator: " ")
selectedTab = 0
isPresented.toggle()
if previousProvider == settings.preferredBooru {
manager.performSearch(settings: settings)
}
}) {
GenericItemView(
item: item,
removeAction: removeActionUUID
)
}
.contextMenu {
Button(action: {
manager.searchText += " \(item.tags.joined(separator: " "))"
manager.selectedPost = nil
manager.performSearch(settings: settings)
isPresented.toggle()
}) {
Label("Add to Search", systemImage: "plus")
}
if allowBookmarking {
Button(action: {
settings.addBookmark(provider: settings.preferredBooru, tags: item.tags)
}) {
Label("Bookmark Tag\(item.tags.count == 1 ? "" : "s")", systemImage: "bookmark")
}
}
Button {
removeActionUUID(item.id)
} label: {
Label("Remove", systemImage: "trash")
}
}
#if os(macOS)
.buttonStyle(.plain)
#endif
}
}
|