-
Notifications
You must be signed in to change notification settings - Fork 1
/
Keyboard.swift
81 lines (75 loc) · 3.37 KB
/
Keyboard.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
import TokamakShim
import Foundation
/// An interactive keyboard, with an enter button on the left and delete button on the right.
///
/// The grid contains 20 columns so the second row can be offset by half a key (it is one key shorter than the first row).
/// Each key spans 2 columns, and the action buttons span 3.
struct Keyboard: View {
static let rows = [
"qwertyuiop",
"asdfghjkl",
"zxcvbnm"
]
@ObservedObject var manager: GameManager
let onTapLetter: (Character) -> ()
let onEnter: () -> ()
let onDelete: () -> ()
var body: some View {
Grid(horizontalSpacing: 2, verticalSpacing: 2).callAsFunction {
ForEach(Self.rows, id: \.self) { row in
GridRow {
if row.starts(with: "a") {
// The second row of letters is one key shorter than the first,
// so offset it one grid column with an unsized clear color.
Color.clear
.gridCellUnsizedAxes(.vertical)
} else if row.starts(with: "z") {
// The last row contains an enter button on the left.
Key(label: Text("enter"), action: onEnter, fill: .quaternary)
.gridCellColumns(3)
.gridCellUnsizedAxes(.horizontal)
}
ForEach(Array(row), id: \.self) { letter in
// Resolved color for this key, or the default quaternary hierarchical style.
// FIXME: When `AnyShapeStyle` is available in Tokamak, use `HierarchicalShapeStyle.quaternary` directly instead of recreating it from `Color.primary`.
let color = manager.color(for: letter) ?? Color.primary.opacity(0.2)
Key(
label: Text(String(letter))
.foregroundColor(
// Use a white foreground color on a colorful fill.
color == .disabled || color == Color.primary.opacity(0.2)
? nil
: .white
),
action: { onTapLetter(letter) },
fill: color
)
.gridCellColumns(2)
}
if row.starts(with: "z") {
// The last row contains a delete button on the right.
Key(label: Text("delete"), action: onDelete, fill: .quaternary)
.gridCellColumns(3)
.gridCellUnsizedAxes(.horizontal)
}
}
}
}
}
struct Key<Fill: ShapeStyle>: View {
let label: Text
var padding: CGFloat = 15
let action: () -> ()
let fill: Fill
var body: some View {
Button(action: action) {
label
.font(.system(size: 14))
.fontWeight(.medium)
.frame(maxWidth: .infinity)
.padding(.vertical, padding)
.background(fill, in: RoundedRectangle(cornerRadius: 5))
}
}
}
}