ux: float close button outside bubble and reduce hover flicker
This commit is contained in:
@@ -89,7 +89,7 @@ final class VoiceWakeOverlayController: ObservableObject {
|
|||||||
self.updateWindowFrame(animate: true)
|
self.updateWindowFrame(animate: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendNow() {
|
func sendNow(sendChime: VoiceWakeChime = .none) {
|
||||||
self.autoSendTask?.cancel()
|
self.autoSendTask?.cancel()
|
||||||
self.model.isEditing = false
|
self.model.isEditing = false
|
||||||
guard let forwardConfig, forwardConfig.enabled else {
|
guard let forwardConfig, forwardConfig.enabled else {
|
||||||
@@ -102,6 +102,10 @@ final class VoiceWakeOverlayController: ObservableObject {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if sendChime != .none {
|
||||||
|
VoiceWakeChimePlayer.play(sendChime)
|
||||||
|
}
|
||||||
|
|
||||||
self.model.isSending = true
|
self.model.isSending = true
|
||||||
let payload = VoiceWakeForwarder.prefixedTranscript(text)
|
let payload = VoiceWakeForwarder.prefixedTranscript(text)
|
||||||
Task.detached {
|
Task.detached {
|
||||||
@@ -256,13 +260,17 @@ final class VoiceWakeOverlayController: ObservableObject {
|
|||||||
|
|
||||||
private func scheduleAutoSend(after delay: TimeInterval, sendChime: VoiceWakeChime) {
|
private func scheduleAutoSend(after delay: TimeInterval, sendChime: VoiceWakeChime) {
|
||||||
guard let forwardConfig, forwardConfig.enabled else { return }
|
guard let forwardConfig, forwardConfig.enabled else { return }
|
||||||
self.autoSendTask = Task { [weak self] in
|
self.autoSendTask?.cancel()
|
||||||
let nanos = UInt64(delay * 1_000_000_000)
|
self.autoSendTask = Task { [weak self, sendChime] in
|
||||||
try? await Task.sleep(nanoseconds: nanos)
|
do {
|
||||||
if sendChime != .none {
|
let nanos = UInt64(delay * 1_000_000_000)
|
||||||
VoiceWakeChimePlayer.play(sendChime)
|
try await Task.sleep(nanoseconds: nanos)
|
||||||
|
try Task.checkCancellation()
|
||||||
|
guard let self else { return }
|
||||||
|
await self.sendNow(sendChime: sendChime)
|
||||||
|
} catch is CancellationError {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
self?.sendNow()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,9 +293,9 @@ private struct CloseHoverButton: View {
|
|||||||
.font(.system(size: 12, weight: .bold))
|
.font(.system(size: 12, weight: .bold))
|
||||||
.foregroundColor(Color.white.opacity(0.85))
|
.foregroundColor(Color.white.opacity(0.85))
|
||||||
.frame(width: 22, height: 22)
|
.frame(width: 22, height: 22)
|
||||||
.background(Color.black.opacity(0.35))
|
.background(Color.black.opacity(0.42))
|
||||||
.clipShape(Circle())
|
.clipShape(Circle())
|
||||||
.shadow(color: Color.black.opacity(0.35), radius: 6, y: 2)
|
.shadow(color: Color.black.opacity(0.4), radius: 8, y: 2)
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
.focusable(false)
|
.focusable(false)
|
||||||
@@ -365,16 +373,17 @@ private struct VoiceWakeOverlayView: View {
|
|||||||
.padding(.vertical, 8)
|
.padding(.vertical, 8)
|
||||||
.padding(.horizontal, 10)
|
.padding(.horizontal, 10)
|
||||||
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
|
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
|
||||||
.background(.regularMaterial)
|
.background(
|
||||||
.clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous))
|
.regularMaterial,
|
||||||
|
in: RoundedRectangle(cornerRadius: 12, style: .continuous))
|
||||||
.onHover { self.isHovering = $0 }
|
.onHover { self.isHovering = $0 }
|
||||||
|
|
||||||
if self.controller.model.isEditing || self.isHovering {
|
if self.controller.model.isEditing || self.isHovering {
|
||||||
CloseHoverButton(onClose: {
|
CloseHoverButton(onClose: {
|
||||||
self.controller.cancelEditingAndDismiss()
|
self.controller.cancelEditingAndDismiss()
|
||||||
})
|
})
|
||||||
.offset(x: -10, y: -10)
|
.offset(x: -8, y: -8)
|
||||||
.transition(AnyTransition.scale.combined(with: .opacity))
|
.transition(.opacity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onAppear { self.textFocused = false }
|
.onAppear { self.textFocused = false }
|
||||||
|
|||||||
Reference in New Issue
Block a user