feat(keyboard): improve typing, voice flow, and polish reliability
Reduce extension memory pressure and delivery races while adding richer candidates, tactile feedback, and safer two-level creative polishing.
This commit is contained in:
@@ -17,36 +17,84 @@ public enum TypingKeyPage: String, CaseIterable, Sendable {
|
||||
/// The Phase 1 SwiftUI keyboard reads this; a future Kit-backed shell
|
||||
/// can feed the same consumer.
|
||||
public protocol TypingLayoutProviding: Sendable {
|
||||
func rows(for page: TypingKeyPage, shiftActive: Bool) -> [[String]]
|
||||
func rows(
|
||||
for page: TypingKeyPage,
|
||||
language: TypingInputLanguage,
|
||||
shiftActive: Bool
|
||||
) -> [[String]]
|
||||
}
|
||||
|
||||
/// Standard phone QWERTY + 123 + light symbols (NanoMouse / system-like).
|
||||
/// Phone QWERTY + 123 / #+= pages aligned with iOS system keyboards
|
||||
/// (English US and Simplified Chinese Pinyin).
|
||||
public struct StandardTypingLayout: TypingLayoutProviding {
|
||||
public init() {}
|
||||
|
||||
public func rows(for page: TypingKeyPage, shiftActive: Bool) -> [[String]] {
|
||||
public func rows(
|
||||
for page: TypingKeyPage,
|
||||
language: TypingInputLanguage,
|
||||
shiftActive: Bool
|
||||
) -> [[String]] {
|
||||
switch page {
|
||||
case .letters:
|
||||
let upper = shiftActive
|
||||
let map: (String) -> String = { upper ? $0.uppercased() : $0 }
|
||||
return [
|
||||
["q", "w", "e", "r", "t", "y", "u", "i", "o", "p"].map(map),
|
||||
["a", "s", "d", "f", "g", "h", "j", "k", "l"].map(map),
|
||||
["⇧", "z", "x", "c", "v", "b", "n", "m", "⌫"].map { $0.count == 1 ? map($0) : $0 }
|
||||
]
|
||||
return letterRows(shiftActive: shiftActive)
|
||||
case .numbers:
|
||||
return [
|
||||
["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"],
|
||||
["-", "/", ":", ";", "(", ")", "$", "&", "@", "\""],
|
||||
["#+=", ".", ",", "?", "!", "'", "⌫"]
|
||||
]
|
||||
return language == .chinese ? chineseNumberRows : englishNumberRows
|
||||
case .symbols:
|
||||
return [
|
||||
["[", "]", "{", "}", "#", "%", "^", "*", "+", "="],
|
||||
["_", "\\", "|", "~", "<", ">", "€", "£", "¥", "·"],
|
||||
["123", ".", ",", "?", "!", "'", "⌫"],
|
||||
[",", "。", "、", "?", "!", ":", ";"]
|
||||
]
|
||||
return language == .chinese ? chineseSymbolRows : englishSymbolRows
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Letters (shared)
|
||||
|
||||
private func letterRows(shiftActive: Bool) -> [[String]] {
|
||||
let upper = shiftActive
|
||||
let map: (String) -> String = { upper ? $0.uppercased() : $0 }
|
||||
return [
|
||||
["q", "w", "e", "r", "t", "y", "u", "i", "o", "p"].map(map),
|
||||
["a", "s", "d", "f", "g", "h", "j", "k", "l"].map(map),
|
||||
["⇧", "z", "x", "c", "v", "b", "n", "m", "⌫"].map { $0.count == 1 ? map($0) : $0 }
|
||||
]
|
||||
}
|
||||
|
||||
// MARK: - English (iOS US)
|
||||
|
||||
/// iOS English US · Numbers
|
||||
private var englishNumberRows: [[String]] {
|
||||
[
|
||||
["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"],
|
||||
["-", "/", ":", ";", "(", ")", "$", "&", "@", "\""],
|
||||
["#+=", ".", ",", "?", "!", "'", "⌫"]
|
||||
]
|
||||
}
|
||||
|
||||
/// iOS English US · Symbols
|
||||
private var englishSymbolRows: [[String]] {
|
||||
[
|
||||
["[", "]", "{", "}", "#", "%", "^", "*", "+", "="],
|
||||
["_", "\\", "|", "~", "<", ">", "€", "£", "¥", "·"],
|
||||
["123", ".", ",", "?", "!", "'", "⌫"]
|
||||
]
|
||||
}
|
||||
|
||||
// MARK: - Chinese (iOS 简体拼音)
|
||||
|
||||
/// iOS Simplified Chinese · Numbers (fullwidth punctuation where system uses it)
|
||||
private var chineseNumberRows: [[String]] {
|
||||
[
|
||||
["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"],
|
||||
// System 123 page uses curly double quotes “ ” (not corner brackets).
|
||||
["-", "/", ":", ";", "(", ")", "¥", "@", "“", "”"],
|
||||
["#+=", "。", ",", "、", "?", "!", ".", "⌫"]
|
||||
]
|
||||
}
|
||||
|
||||
/// iOS Simplified Chinese · Symbols
|
||||
private var chineseSymbolRows: [[String]] {
|
||||
[
|
||||
// 「」 live on #+= so they remain reachable after numbers use “ ”.
|
||||
["【", "】", "「", "」", "#", "%", "^", "*", "+", "="],
|
||||
["_", "\\", "|", "~", "《", "》", "€", "£", "¥", "·"],
|
||||
["123", "。", ",", "、", "?", "!", ".", "⌫"]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user