feat(keyboard): unify assistant voice and AI workflows

Merge dictation and AI controls into one assistant surface, preserve safe insertion and clipboard actions, and align settings and tests with the new flow.
This commit is contained in:
Rocky
2026-08-16 12:07:06 +08:00
parent 46f6d818b8
commit fb97ec2937
45 changed files with 1969 additions and 2143 deletions
@@ -206,6 +206,7 @@ struct RectangularToolbarButton: View {
let usesCircleGlass: Bool
/// Settings General Haptics; space / return use `.action` role.
var hapticIntensity: KeyboardHapticIntensity = .off
var onPressingChanged: (Bool) -> Void = { _ in }
let action: () -> Void
init(
@@ -215,6 +216,7 @@ struct RectangularToolbarButton: View {
usesLiquidGlass: Bool = false,
usesCircleGlass: Bool = false,
hapticIntensity: KeyboardHapticIntensity = .off,
onPressingChanged: @escaping (Bool) -> Void = { _ in },
action: @escaping () -> Void
) {
self.systemName = systemName
@@ -226,6 +228,7 @@ struct RectangularToolbarButton: View {
self.usesLiquidGlass = usesLiquidGlass
self.usesCircleGlass = usesCircleGlass
self.hapticIntensity = hapticIntensity
self.onPressingChanged = onPressingChanged
self.action = action
}
@@ -236,6 +239,7 @@ struct RectangularToolbarButton: View {
isSend: Bool = false,
usesLiquidGlass: Bool = false,
hapticIntensity: KeyboardHapticIntensity = .off,
onPressingChanged: @escaping (Bool) -> Void = { _ in },
action: @escaping () -> Void
) {
self.systemName = nil
@@ -246,6 +250,7 @@ struct RectangularToolbarButton: View {
self.usesLiquidGlass = usesLiquidGlass
self.usesCircleGlass = false
self.hapticIntensity = hapticIntensity
self.onPressingChanged = onPressingChanged
self.action = action
self.title = title
}
@@ -256,6 +261,7 @@ struct RectangularToolbarButton: View {
disabled: Bool = false,
usesLiquidGlass: Bool = false,
hapticIntensity: KeyboardHapticIntensity = .off,
onPressingChanged: @escaping (Bool) -> Void = { _ in },
action: @escaping () -> Void
) {
self.systemName = nil
@@ -267,6 +273,7 @@ struct RectangularToolbarButton: View {
self.usesLiquidGlass = usesLiquidGlass
self.usesCircleGlass = false
self.hapticIntensity = hapticIntensity
self.onPressingChanged = onPressingChanged
self.action = action
}
@@ -280,6 +287,11 @@ struct RectangularToolbarButton: View {
.allowsHitTesting(!disabled)
.accessibilityLabel(Text(label))
.accessibilityAddTraits(.isButton)
.onDisappear {
guard isPressing else { return }
isPressing = false
onPressingChanged(false)
}
}
@ViewBuilder
@@ -337,12 +349,14 @@ struct RectangularToolbarButton: View {
.onChanged { _ in
guard !disabled, !isPressing else { return }
isPressing = true
onPressingChanged(true)
KeyboardSoundFeedback.keyClick()
KeyboardHapticFeedback.play(role: .action, intensity: hapticIntensity)
action()
}
.onEnded { _ in
isPressing = false
onPressingChanged(false)
}
}
}