Power Mode Keyboard Shortcuts: - Add hotkeyShortcut property to PowerModeConfig for storing custom shortcuts - Implement keyboard shortcut UI in Power Mode configuration view - Add hotkey registration system in HotkeyManager to manage Power Mode shortcuts - Support cleanup of shortcuts when Power Mode configurations are removed - Post notifications when Power Mode configurations change Explicit Power Mode Activation: - Add optional powerModeId parameter to toggleRecord and toggleMiniRecorder - Refactor ActiveWindowService.applyConfigurationForCurrentApp to applyConfiguration - Support direct Power Mode activation via powerModeId instead of auto-detection - Pass powerModeId through recording flow for explicit mode selection Session Management Improvements: - Fix auto-restore to preserve baseline when switching Power Modes mid-recording - Only capture baseline state on first session creation - Prevent subsequent beginSession calls from overwriting original baseline - Ensure auto-restore returns to settings from before recording started UI Refinements: - Remove redundant "Record" label from keyboard shortcut recorder
153 lines
4.6 KiB
Swift
153 lines
4.6 KiB
Swift
import Foundation
|
|
import SwiftUI
|
|
import os
|
|
|
|
// MARK: - UI Management Extension
|
|
extension WhisperState {
|
|
|
|
// MARK: - Recorder Panel Management
|
|
|
|
func showRecorderPanel() {
|
|
logger.notice("📱 Showing \(self.recorderType) recorder")
|
|
if recorderType == "notch" {
|
|
if notchWindowManager == nil {
|
|
notchWindowManager = NotchWindowManager(whisperState: self, recorder: recorder)
|
|
}
|
|
notchWindowManager?.show()
|
|
} else {
|
|
if miniWindowManager == nil {
|
|
miniWindowManager = MiniWindowManager(whisperState: self, recorder: recorder)
|
|
}
|
|
miniWindowManager?.show()
|
|
}
|
|
}
|
|
|
|
func hideRecorderPanel() {
|
|
if recorderType == "notch" {
|
|
notchWindowManager?.hide()
|
|
} else {
|
|
miniWindowManager?.hide()
|
|
}
|
|
}
|
|
|
|
// MARK: - Mini Recorder Management
|
|
|
|
func toggleMiniRecorder(powerModeId: UUID? = nil) async {
|
|
if isMiniRecorderVisible {
|
|
if recordingState == .recording {
|
|
await toggleRecord(powerModeId: powerModeId)
|
|
} else {
|
|
await cancelRecording()
|
|
}
|
|
} else {
|
|
SoundManager.shared.playStartSound()
|
|
|
|
await MainActor.run {
|
|
isMiniRecorderVisible = true // This will call showRecorderPanel() via didSet
|
|
}
|
|
|
|
await toggleRecord(powerModeId: powerModeId)
|
|
}
|
|
}
|
|
|
|
func dismissMiniRecorder() async {
|
|
if recordingState == .busy { return }
|
|
|
|
let wasRecording = recordingState == .recording
|
|
|
|
await MainActor.run {
|
|
self.recordingState = .busy
|
|
}
|
|
|
|
if wasRecording {
|
|
await recorder.stopRecording()
|
|
}
|
|
|
|
hideRecorderPanel()
|
|
|
|
// Clear captured context when the recorder is dismissed
|
|
if let enhancementService = enhancementService {
|
|
await MainActor.run {
|
|
enhancementService.clearCapturedContexts()
|
|
}
|
|
}
|
|
|
|
await MainActor.run {
|
|
isMiniRecorderVisible = false
|
|
}
|
|
|
|
await cleanupModelResources()
|
|
|
|
if UserDefaults.standard.bool(forKey: PowerModeDefaults.autoRestoreKey) {
|
|
await PowerModeSessionManager.shared.endSession()
|
|
await MainActor.run {
|
|
PowerModeManager.shared.setActiveConfiguration(nil)
|
|
}
|
|
}
|
|
|
|
await MainActor.run {
|
|
recordingState = .idle
|
|
}
|
|
}
|
|
|
|
func resetOnLaunch() async {
|
|
logger.notice("🔄 Resetting recording state on launch")
|
|
await recorder.stopRecording()
|
|
hideRecorderPanel()
|
|
await MainActor.run {
|
|
isMiniRecorderVisible = false
|
|
shouldCancelRecording = false
|
|
miniRecorderError = nil
|
|
recordingState = .idle
|
|
}
|
|
await cleanupModelResources()
|
|
}
|
|
|
|
func cancelRecording() async {
|
|
SoundManager.shared.playEscSound()
|
|
shouldCancelRecording = true
|
|
await dismissMiniRecorder()
|
|
}
|
|
|
|
// MARK: - Notification Handling
|
|
|
|
func setupNotifications() {
|
|
NotificationCenter.default.addObserver(self, selector: #selector(handleToggleMiniRecorder), name: .toggleMiniRecorder, object: nil)
|
|
NotificationCenter.default.addObserver(self, selector: #selector(handleDismissMiniRecorder), name: .dismissMiniRecorder, object: nil)
|
|
NotificationCenter.default.addObserver(self, selector: #selector(handleLicenseStatusChanged), name: .licenseStatusChanged, object: nil)
|
|
NotificationCenter.default.addObserver(self, selector: #selector(handlePromptChange), name: .promptDidChange, object: nil)
|
|
}
|
|
|
|
@objc public func handleToggleMiniRecorder() {
|
|
Task {
|
|
await toggleMiniRecorder()
|
|
}
|
|
}
|
|
|
|
@objc public func handleDismissMiniRecorder() {
|
|
Task {
|
|
await dismissMiniRecorder()
|
|
}
|
|
}
|
|
|
|
@objc func handleLicenseStatusChanged() {
|
|
self.licenseViewModel = LicenseViewModel()
|
|
}
|
|
|
|
@objc func handlePromptChange() {
|
|
// Update the whisper context with the new prompt
|
|
Task {
|
|
await updateContextPrompt()
|
|
}
|
|
}
|
|
|
|
private func updateContextPrompt() async {
|
|
// Always reload the prompt from UserDefaults to ensure we have the latest
|
|
let currentPrompt = UserDefaults.standard.string(forKey: "TranscriptionPrompt") ?? whisperPrompt.transcriptionPrompt
|
|
|
|
if let context = whisperContext {
|
|
await context.setPrompt(currentPrompt)
|
|
}
|
|
}
|
|
}
|