Files
Rocky 498f407585 feat(account): add managed credits and cloud gateway
Introduce optional Apple account-backed credits with scoped gateway access while preserving local and BYOK paths. Refresh assistant behavior, tests, privacy disclosures, docs, and the website for the 2.0 experience.
2026-08-20 11:43:21 +08:00

42 lines
1.7 KiB
Swift

// KeyboardSoundFeedback.swift
// OSGKeyboard · Keyboard Extension
//
// Plays the built-in iOS keyboard click sounds so the custom bottom-row
// keys (space / return / delete) sound identical to the stock keyboard.
import AudioToolbox
import UIKit
/// 让键盘扩展支持系统点击音。`UIDevice.playInputClick()` 只有在「某个
/// 可见的输入视图遵循本协议且返回 true」时才会发声。键盘扩展的根视图
/// 由系统包在一个 `UIInputView` 里,因此对它做追溯遵循即可开启点击音。
extension UIInputView: @retroactive UIInputViewAudioFeedback {
public var enableInputClicksWhenVisible: Bool { true }
}
/// 播放系统键盘原声,让空格 / 回车 / 删除键与系统键盘完全一致。
///
/// 空格 / 回车走官方 `playInputClick()`:这是键盘扩展里最可靠的方式,
/// 会自动尊重「键盘咔嗒声」设置与响铃/静音开关。删除键因为 `playInputClick()`
/// 无法选择其专属音色,改用系统删除音 `1155`。两者都要求扩展已开启
/// 「完全访问」才会发声。
enum KeyboardSoundFeedback {
/// 删除键音(单次删除,以及长按连删时的每一次删除)。
private static let deleteSoundID: SystemSoundID = 1155
/// 普通按键点击音(空格、回车)。
@MainActor
static func keyClick() {
UIDevice.current.playInputClick()
}
/// 删除键点击音。
static func deleteClick() {
// 未开「完全访问」时该调用是无效空操作,但仍可能短暂阻塞,
// 放到后台线程可保证连删手感不卡顿。
DispatchQueue.global(qos: .userInteractive).async {
AudioServicesPlaySystemSound(deleteSoundID)
}
}
}