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
import SwiftUI
struct ContentLabelPicker: View {
@Environment(LabelDefinitionsCache.self) private var labelDefs
@Binding var selectedLabels: Set<String>
/// Start with the label rows showing rather than folded behind the
/// disclosure. Used where the picker is the whole screen.
var initiallyExpanded = false
private static let selfLabelValues = ["nudity", "sexual", "gore"]
private var options: [(value: String, label: String)] {
Self.selfLabelValues.map { value in
let name = labelDefs.definitions
.first(where: { $0.identifier == value })?
.displayName ?? value.capitalized
return (value: value, label: name)
}
}
@State private var isExpanded = false
var body: some View {
Section {
DisclosureGroup(isExpanded: $isExpanded) {
ForEach(options, id: \.value) { option in
Button {
if selectedLabels.contains(option.value) {
selectedLabels.remove(option.value)
} else {
selectedLabels.insert(option.value)
}
} label: {
HStack {
Text(option.label)
.foregroundStyle(.primary)
Spacer()
if selectedLabels.contains(option.value) {
Image(systemName: "checkmark")
.fontWeight(.semibold)
}
}
}
}
} label: {
Text("Content warning")
.foregroundStyle(.primary)
}
}
.onAppear {
if initiallyExpanded {
isExpanded = true
}
}
.onChange(of: selectedLabels) {
if !selectedLabels.isEmpty {
isExpanded = true
}
}
}
}
#Preview {
// Pre-select "sexual" so the disclosure group auto-expands on first render
// and the checkmark row is immediately visible. The cache has no network
// definitions, so labels fall back to .capitalized ("Nudity", "Sexual", "Gore").
@Previewable @State var labelsWithSelection: Set = ["sexual"]
@Previewable @State var labelsEmpty: Set<String> = []
Form {
// Expanded — one item pre-checked
Section(header: Text("Pre-selected (expanded)")) {
ContentLabelPicker(selectedLabels: $labelsWithSelection)
}
// Collapsed — nothing selected
Section(header: Text("Empty (collapsed)")) {
ContentLabelPicker(selectedLabels: $labelsEmpty)
}
}
.previewEnvironments()
.preferredColorScheme(.dark)
.tint(Color.accentColor)
}