Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  VoiceWakeOverlay.swift   Sprache: unbekannt

 
Spracherkennung für: .swift vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

import AppKit
import Observation
import SwiftUI

/// Lightweight, borderless panel that shows the current voice wake transcript near the menu bar.
@MainActor
@Observable
final class VoiceWakeOverlayController {
    static let shared = VoiceWakeOverlayController()

    let logger = Logger(subsystem: "ai.openclaw", category: "voicewake.overlay")
    let enableUI: Bool

    /// Keep the voice wake overlay above any other OpenClaw windows, but below the system’s pop-up menus.
    /// (Menu bar menus typically live at `.popUpMenu`.)
    static let preferredWindowLevel = NSWindow.Level(rawValue: NSWindow.Level.popUpMenu.rawValue - 4)

    enum Source: String { case wakeWord, pushToTalk }

    var model = Model()
    var isVisible: Bool {
        self.model.isVisible
    }

    struct Model {
        var text: String = ""
        var isFinal: Bool = false
        var isVisible: Bool = false
        var forwardEnabled: Bool = false
        var isSending: Bool = false
        var attributed: NSAttributedString = .init(string: "")
        var isOverflowing: Bool = false
        var isEditing: Bool = false
        var level: Double = 0 // normalized 0...1 speech level for UI
    }

    var window: NSPanel?
    var hostingView: NSHostingView<VoiceWakeOverlayView>?
    var autoSendTask: Task<Void, Never>?
    var autoSendToken: UUID?
    var activeToken: UUID?
    var activeSource: Source?
    var lastLevelUpdate: TimeInterval = 0

    let width: CGFloat = 360
    let padding: CGFloat = 10
    let buttonWidth: CGFloat = 36
    let spacing: CGFloat = 8
    let verticalPadding: CGFloat = 8
    let maxHeight: CGFloat = 400
    let minHeight: CGFloat = 48
    let closeOverflow: CGFloat = 10
    let levelUpdateInterval: TimeInterval = 1.0 / 12.0

    enum DismissReason { case explicit, empty }
    enum SendOutcome { case sent, empty }
    enum GuardOutcome { case accept, dropMismatch, dropNoActive }

    init(enableUI: Bool = true) {
        self.enableUI = enableUI
    }
}

[Dauer der Verarbeitung: 0.25 Sekunden, vorverarbeitet 2026-04-27]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge