-
Notifications
You must be signed in to change notification settings - Fork 1
/
ThemeEditor.swift
116 lines (98 loc) · 3.53 KB
/
ThemeEditor.swift
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
//
// ThemeEditor.swift
// Memorize
//
// Created by Ilya Zavidny on 24.09.2021.
//
import SwiftUI
import SwiftUI
// L12 a View which edits the info in a bound-to Palette
struct ThemeEditor: View {
@Binding var theme: Theme
var body: some View {
Form {
nameSection
addEmojisSection
editNumberOfPairs
editThemeColor
removeEmojiSection
}
.navigationTitle("Edit \(theme.name)")
.frame(minWidth: 300, minHeight: 350)
}
var nameSection: some View {
Section(header: Text("Name")) {
TextField("Name", text: $theme.name)
}
}
@State private var emojisToAdd = ""
var addEmojisSection: some View {
Section(header: Text("Add Emojis")) {
TextField("", text: $emojisToAdd)
.onChange(of: emojisToAdd) { emojis in
addEmojis(emojis)
}
}
}
func addEmojis(_ emojis: String) {
withAnimation {
emojis.forEach { emoji in
if emoji.isEmoji && !theme.items.contains(String(emoji)) {
theme.items.insert(String(emoji), at: 0)
}
}
}
}
var editNumberOfPairs: some View {
Section(header: Text("Playable Pairs")) {
Stepper("\(theme.pairsToShow)", value: $theme.pairsToShow, in: min(2, theme.items.count)...(theme.items.count))
}
}
var editThemeColor: some View {
Section(header: Text("Theme Color")) {
ColorPicker("Color", selection: $theme.cColor)
}
}
var removeEmojiSection: some View {
Section(header: Text("Remove Emoji")) {
LazyVGrid(columns: [GridItem(.adaptive(minimum: 40))]) {
ForEach(theme.items, id: \.self) { emoji in
Text(emoji)
.onTapGesture {
withAnimation {
theme.items.removeAll(where: { $0 == emoji })
}
}
}
}
.font(.system(size: 40))
}
}
}
struct PaletteEditor_Previews: PreviewProvider {
static var previews: some View {
ThemeEditor(theme: .constant(ThemeStore(named: "Preview").themes[4]))
.previewLayout(.fixed(width: 300, height: 350))
ThemeEditor(theme: .constant(ThemeStore(named: "Preview").themes[2]))
.previewLayout(.fixed(width: 300, height: 600))
}
}
extension Character {
var isEmoji: Bool {
// Swift does not have a way to ask if a Character isEmoji
// but it does let us check to see if our component scalars isEmoji
// unfortunately unicode allows certain scalars (like 1)
// to be modified by another scalar to become emoji (e.g. 1️⃣)
// so the scalar "1" will report isEmoji = true
// so we can't just check to see if the first scalar isEmoji
// the quick and dirty here is to see if the scalar is at least the first true emoji we know of
// (the start of the "miscellaneous items" section)
// or check to see if this is a multiple scalar unicode sequence
// (e.g. a 1 with a unicode modifier to force it to be presented as emoji 1️⃣)
if let firstScalar = unicodeScalars.first, firstScalar.properties.isEmoji {
return (firstScalar.value >= 0x238d || unicodeScalars.count > 1)
} else {
return false
}
}
}