Overlay: safety dismiss and logging; keep PTT final send
This commit is contained in:
@@ -27,6 +27,7 @@ final class VoiceWakeOverlayController: ObservableObject {
|
||||
private var window: NSPanel?
|
||||
private var hostingView: NSHostingView<VoiceWakeOverlayView>?
|
||||
private var autoSendTask: Task<Void, Never>?
|
||||
private var safetyDismissTask: Task<Void, Never>?
|
||||
private var forwardConfig: VoiceWakeForwardConfig?
|
||||
|
||||
private let width: CGFloat = 360
|
||||
@@ -41,6 +42,7 @@ final class VoiceWakeOverlayController: ObservableObject {
|
||||
func showPartial(transcript: String, attributed: NSAttributedString? = nil) {
|
||||
self.logger.log(level: .info, "overlay showPartial len=\(transcript.count, privacy: .public) visible=\(self.model.isVisible, privacy: .public) isFinal=false")
|
||||
self.autoSendTask?.cancel()
|
||||
self.safetyDismissTask?.cancel()
|
||||
self.forwardConfig = nil
|
||||
self.model.text = transcript
|
||||
self.model.isFinal = false
|
||||
@@ -62,6 +64,7 @@ final class VoiceWakeOverlayController: ObservableObject {
|
||||
{
|
||||
self.logger.log(level: .info, "overlay presentFinal len=\(transcript.count, privacy: .public) autoSendAfter=\(delay ?? -1, privacy: .public) forwardEnabled=\(forwardConfig.enabled, privacy: .public)")
|
||||
self.autoSendTask?.cancel()
|
||||
self.safetyDismissTask?.cancel()
|
||||
self.forwardConfig = forwardConfig
|
||||
self.model.text = transcript
|
||||
self.model.isFinal = true
|
||||
@@ -74,6 +77,8 @@ final class VoiceWakeOverlayController: ObservableObject {
|
||||
if let delay {
|
||||
self.scheduleAutoSend(after: delay, sendChime: sendChime)
|
||||
}
|
||||
// Safety net: ensure the overlay cannot stick around indefinitely.
|
||||
self.scheduleSafetyDismiss()
|
||||
}
|
||||
|
||||
func userBeganEditing() {
|
||||
@@ -104,6 +109,7 @@ final class VoiceWakeOverlayController: ObservableObject {
|
||||
self.logger.log(level: .info, "overlay sendNow called isSending=\(self.model.isSending, privacy: .public) forwardEnabled=\(self.model.forwardEnabled, privacy: .public) textLen=\(self.model.text.count, privacy: .public)")
|
||||
self.autoSendTask?.cancel()
|
||||
self.autoSendTask = nil
|
||||
self.safetyDismissTask?.cancel()
|
||||
if self.model.isSending { return }
|
||||
self.model.isEditing = false
|
||||
guard let forwardConfig, forwardConfig.enabled else {
|
||||
@@ -137,6 +143,7 @@ final class VoiceWakeOverlayController: ObservableObject {
|
||||
func dismiss(reason: DismissReason = .explicit, outcome: SendOutcome = .empty) {
|
||||
self.logger.log(level: .info, "overlay dismiss reason=\(String(describing: reason), privacy: .public) outcome=\(String(describing: outcome), privacy: .public) visible=\(self.model.isVisible, privacy: .public) sending=\(self.model.isSending, privacy: .public)")
|
||||
self.autoSendTask?.cancel()
|
||||
self.safetyDismissTask?.cancel()
|
||||
self.model.isSending = false
|
||||
self.model.isEditing = false
|
||||
guard let window else { return }
|
||||
@@ -308,6 +315,20 @@ final class VoiceWakeOverlayController: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
private func scheduleSafetyDismiss() {
|
||||
self.safetyDismissTask?.cancel()
|
||||
self.safetyDismissTask = Task<Void, Never> { [weak self] in
|
||||
try? await Task.sleep(nanoseconds: 6_000_000_000) // 6s
|
||||
guard !Task.isCancelled else { return }
|
||||
await MainActor.run {
|
||||
guard let self, self.model.isVisible else { return }
|
||||
self.logger.log(level: .info, "overlay safety dismiss firing")
|
||||
self.dismiss(reason: .explicit)
|
||||
self.safetyDismissTask = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func makeAttributed(from text: String) -> NSAttributedString {
|
||||
NSAttributedString(
|
||||
string: text,
|
||||
|
||||
Reference in New Issue
Block a user