ux: keep window in edit, add escape to cancel; fix lint drift
This commit is contained in:
@@ -65,6 +65,13 @@ final class VoiceWakeOverlayController: ObservableObject {
|
|||||||
self.model.isEditing = true
|
self.model.isEditing = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cancelEditingAndDismiss() {
|
||||||
|
self.autoSendTask?.cancel()
|
||||||
|
self.model.isSending = false
|
||||||
|
self.model.isEditing = false
|
||||||
|
self.dismiss(reason: .explicit)
|
||||||
|
}
|
||||||
|
|
||||||
func endEditing() {
|
func endEditing() {
|
||||||
self.model.isEditing = false
|
self.model.isEditing = false
|
||||||
}
|
}
|
||||||
@@ -277,6 +284,9 @@ private struct VoiceWakeOverlayView: View {
|
|||||||
onBeginEditing: {
|
onBeginEditing: {
|
||||||
self.controller.userBeganEditing()
|
self.controller.userBeganEditing()
|
||||||
},
|
},
|
||||||
|
onEscape: {
|
||||||
|
self.controller.cancelEditingAndDismiss()
|
||||||
|
},
|
||||||
onEndEditing: {
|
onEndEditing: {
|
||||||
self.controller.endEditing()
|
self.controller.endEditing()
|
||||||
},
|
},
|
||||||
@@ -348,6 +358,7 @@ private struct TranscriptTextView: NSViewRepresentable {
|
|||||||
var isFinal: Bool
|
var isFinal: Bool
|
||||||
var isOverflowing: Bool
|
var isOverflowing: Bool
|
||||||
var onBeginEditing: () -> Void
|
var onBeginEditing: () -> Void
|
||||||
|
var onEscape: () -> Void
|
||||||
var onEndEditing: () -> Void
|
var onEndEditing: () -> Void
|
||||||
var onSend: () -> Void
|
var onSend: () -> Void
|
||||||
|
|
||||||
@@ -380,11 +391,12 @@ private struct TranscriptTextView: NSViewRepresentable {
|
|||||||
.font: NSFont.systemFont(ofSize: 13, weight: .regular),
|
.font: NSFont.systemFont(ofSize: 13, weight: .regular),
|
||||||
]
|
]
|
||||||
textView.focusRingType = .none
|
textView.focusRingType = .none
|
||||||
textView.onSend = { [weak textView] in
|
textView.onSend = { [weak textView] in
|
||||||
textView?.window?.makeFirstResponder(nil)
|
textView?.window?.makeFirstResponder(nil)
|
||||||
self.onSend()
|
self.onSend()
|
||||||
}
|
}
|
||||||
textView.onBeginEditing = self.onBeginEditing
|
textView.onBeginEditing = self.onBeginEditing
|
||||||
|
textView.onEscape = self.onEscape
|
||||||
textView.onEndEditing = self.onEndEditing
|
textView.onEndEditing = self.onEndEditing
|
||||||
|
|
||||||
let scroll = NSScrollView()
|
let scroll = NSScrollView()
|
||||||
@@ -504,6 +516,7 @@ private final class TranscriptNSTextView: NSTextView {
|
|||||||
var onSend: (() -> Void)?
|
var onSend: (() -> Void)?
|
||||||
var onBeginEditing: (() -> Void)?
|
var onBeginEditing: (() -> Void)?
|
||||||
var onEndEditing: (() -> Void)?
|
var onEndEditing: (() -> Void)?
|
||||||
|
var onEscape: (() -> Void)?
|
||||||
|
|
||||||
override func becomeFirstResponder() -> Bool {
|
override func becomeFirstResponder() -> Bool {
|
||||||
self.onBeginEditing?()
|
self.onBeginEditing?()
|
||||||
@@ -518,6 +531,11 @@ private final class TranscriptNSTextView: NSTextView {
|
|||||||
|
|
||||||
override func keyDown(with event: NSEvent) {
|
override func keyDown(with event: NSEvent) {
|
||||||
let isReturn = event.keyCode == 36
|
let isReturn = event.keyCode == 36
|
||||||
|
let isEscape = event.keyCode == 53
|
||||||
|
if isEscape {
|
||||||
|
self.onEscape?()
|
||||||
|
return
|
||||||
|
}
|
||||||
if isReturn && event.modifierFlags.contains(.command) {
|
if isReturn && event.modifierFlags.contains(.command) {
|
||||||
self.onSend?()
|
self.onSend?()
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ import { statusCommand } from "../commands/status.js";
|
|||||||
import { loadConfig } from "../config/config.js";
|
import { loadConfig } from "../config/config.js";
|
||||||
import { danger, info, setVerbose } from "../globals.js";
|
import { danger, info, setVerbose } from "../globals.js";
|
||||||
import { getResolvedLoggerSettings } from "../logging.js";
|
import { getResolvedLoggerSettings } from "../logging.js";
|
||||||
|
import {
|
||||||
|
readLatestHeartbeat,
|
||||||
|
tailHeartbeatEvents,
|
||||||
|
} from "../process/heartbeat-events.js";
|
||||||
import {
|
import {
|
||||||
loginWeb,
|
loginWeb,
|
||||||
logoutWeb,
|
logoutWeb,
|
||||||
@@ -23,10 +27,6 @@ import {
|
|||||||
resolveHeartbeatSeconds,
|
resolveHeartbeatSeconds,
|
||||||
resolveReconnectPolicy,
|
resolveReconnectPolicy,
|
||||||
} from "../web/reconnect.js";
|
} from "../web/reconnect.js";
|
||||||
import {
|
|
||||||
readLatestHeartbeat,
|
|
||||||
tailHeartbeatEvents,
|
|
||||||
} from "../process/heartbeat-events.js";
|
|
||||||
import {
|
import {
|
||||||
ensureWebChatServerFromConfig,
|
ensureWebChatServerFromConfig,
|
||||||
startWebChatServer,
|
startWebChatServer,
|
||||||
|
|||||||
@@ -6,12 +6,7 @@ import readline from "node:readline";
|
|||||||
export type HeartbeatEvent = {
|
export type HeartbeatEvent = {
|
||||||
type: "heartbeat";
|
type: "heartbeat";
|
||||||
ts: number; // epoch ms
|
ts: number; // epoch ms
|
||||||
status:
|
status: "sent" | "ok-empty" | "ok-token" | "skipped" | "failed";
|
||||||
| "sent"
|
|
||||||
| "ok-empty"
|
|
||||||
| "ok-token"
|
|
||||||
| "skipped"
|
|
||||||
| "failed";
|
|
||||||
to?: string;
|
to?: string;
|
||||||
preview?: string;
|
preview?: string;
|
||||||
durationMs?: number;
|
durationMs?: number;
|
||||||
|
|||||||
Reference in New Issue
Block a user