refactor(macos): dedupe UI, pairing, and runtime helpers

This commit is contained in:
Peter Steinberger
2026-03-02 11:32:04 +00:00
parent cd011897d0
commit cf67e374c0
92 changed files with 1769 additions and 1802 deletions

View File

@@ -13,50 +13,29 @@ extension VoiceWakeOverlayController {
self.ensureWindow()
self.hostingView?.rootView = VoiceWakeOverlayView(controller: self)
let target = self.targetFrame()
guard let window else { return }
if !self.model.isVisible {
self.model.isVisible = true
self.logger.log(
level: .info,
"overlay present windowShown textLen=\(self.model.text.count, privacy: .public)")
// Keep the status item in listening mode until we explicitly dismiss the overlay.
AppStateStore.shared.triggerVoiceEars(ttl: nil)
let start = target.offsetBy(dx: 0, dy: -6)
window.setFrame(start, display: true)
window.alphaValue = 0
window.orderFrontRegardless()
NSAnimationContext.runAnimationGroup { context in
context.duration = 0.18
context.timingFunction = CAMediaTimingFunction(name: .easeOut)
window.animator().setFrame(target, display: true)
window.animator().alphaValue = 1
}
} else {
self.updateWindowFrame(animate: true)
window.orderFrontRegardless()
OverlayPanelFactory.present(
window: self.window,
isVisible: &self.model.isVisible,
target: target,
onFirstPresent: {
self.logger.log(
level: .info,
"overlay present windowShown textLen=\(self.model.text.count, privacy: .public)")
// Keep the status item in listening mode until we explicitly dismiss the overlay.
AppStateStore.shared.triggerVoiceEars(ttl: nil)
}) { window in
self.updateWindowFrame(animate: true)
window.orderFrontRegardless()
}
}
private func ensureWindow() {
if self.window != nil { return }
let borderPad = self.closeOverflow
let panel = NSPanel(
let panel = OverlayPanelFactory.makePanel(
contentRect: NSRect(x: 0, y: 0, width: self.width + borderPad * 2, height: 60 + borderPad * 2),
styleMask: [.nonactivatingPanel, .borderless],
backing: .buffered,
defer: false)
panel.isOpaque = false
panel.backgroundColor = .clear
panel.hasShadow = false
panel.level = Self.preferredWindowLevel
panel.collectionBehavior = [.canJoinAllSpaces, .fullScreenAuxiliary, .transient]
panel.hidesOnDeactivate = false
panel.isMovable = false
panel.isFloatingPanel = true
panel.becomesKeyOnlyIfNeeded = true
panel.titleVisibility = .hidden
panel.titlebarAppearsTransparent = true
level: Self.preferredWindowLevel,
hasShadow: false)
let host = NSHostingView(rootView: VoiceWakeOverlayView(controller: self))
host.translatesAutoresizingMaskIntoConstraints = false
@@ -84,17 +63,7 @@ extension VoiceWakeOverlayController {
}
func updateWindowFrame(animate: Bool = false) {
guard let window else { return }
let frame = self.targetFrame()
if animate {
NSAnimationContext.runAnimationGroup { context in
context.duration = 0.12
context.timingFunction = CAMediaTimingFunction(name: .easeOut)
window.animator().setFrame(frame, display: true)
}
} else {
window.setFrame(frame, display: true)
}
OverlayPanelFactory.applyFrame(window: self.window, target: self.targetFrame(), animate: animate)
}
func measuredHeight() -> CGFloat {