Files
OSGKeyboard/OSGKeyboardShared/Typing/TypingLayoutProviding.swift
T
Rocky 31f5937a7f 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.
2026-08-05 21:39:31 +08:00

101 lines
3.3 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// TypingLayoutProviding.swift
// OSGKeyboard · Shared
//
// Phase 2 escape hatch: replace the in-repo SwiftUI key shell with a
// KeyboardKit-based (or other) layout without changing the engine bridge.
import Foundation
/// Page shown by the typing key shell.
public enum TypingKeyPage: String, CaseIterable, Sendable {
case letters
case numbers
case symbols
}
/// Abstraction over “which characters the current page shows”.
/// 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,
language: TypingInputLanguage,
shiftActive: Bool
) -> [[String]]
}
/// 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,
language: TypingInputLanguage,
shiftActive: Bool
) -> [[String]] {
switch page {
case .letters:
return letterRows(shiftActive: shiftActive)
case .numbers:
return language == .chinese ? chineseNumberRows : englishNumberRows
case .symbols:
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", "。", "", "、", "", "", ".", "⌫"]
]
}
}