Removed session management & use power mode with a new default mode.
This commit is contained in:
parent
d96fbb1ba2
commit
6ad4d70760
@ -27,7 +27,6 @@ class ActiveWindowService: ObservableObject {
|
||||
func applyConfigurationForCurrentApp() async {
|
||||
guard let frontmostApp = NSWorkspace.shared.frontmostApplication,
|
||||
let bundleIdentifier = frontmostApp.bundleIdentifier else {
|
||||
await PowerModeSessionManager.shared.endSession()
|
||||
return
|
||||
}
|
||||
|
||||
@ -53,7 +52,7 @@ class ActiveWindowService: ObservableObject {
|
||||
}
|
||||
|
||||
if configToApply == nil {
|
||||
configToApply = PowerModeManager.shared.getWildcardConfiguration()
|
||||
configToApply = PowerModeManager.shared.getDefaultConfiguration()
|
||||
}
|
||||
|
||||
if let config = configToApply {
|
||||
@ -61,11 +60,7 @@ class ActiveWindowService: ObservableObject {
|
||||
PowerModeManager.shared.setActiveConfiguration(config)
|
||||
}
|
||||
await PowerModeSessionManager.shared.beginSession(with: config)
|
||||
} else {
|
||||
await MainActor.run {
|
||||
PowerModeManager.shared.setActiveConfiguration(nil)
|
||||
}
|
||||
await PowerModeSessionManager.shared.endSession()
|
||||
}
|
||||
// If no config found, keep the current active configuration (don't clear it)
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,9 +15,10 @@ struct PowerModeConfig: Codable, Identifiable, Equatable {
|
||||
var selectedAIModel: String?
|
||||
var isAutoSendEnabled: Bool = false
|
||||
var isEnabled: Bool = true
|
||||
var isDefault: Bool = false
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id, name, emoji, appConfigs, urlConfigs, isAIEnhancementEnabled, selectedPrompt, selectedLanguage, useScreenCapture, selectedAIProvider, selectedAIModel, isAutoSendEnabled, isEnabled
|
||||
case id, name, emoji, appConfigs, urlConfigs, isAIEnhancementEnabled, selectedPrompt, selectedLanguage, useScreenCapture, selectedAIProvider, selectedAIModel, isAutoSendEnabled, isEnabled, isDefault
|
||||
case selectedWhisperModel
|
||||
case selectedTranscriptionModelName
|
||||
}
|
||||
@ -25,7 +26,7 @@ struct PowerModeConfig: Codable, Identifiable, Equatable {
|
||||
init(id: UUID = UUID(), name: String, emoji: String, appConfigs: [AppConfig]? = nil,
|
||||
urlConfigs: [URLConfig]? = nil, isAIEnhancementEnabled: Bool, selectedPrompt: String? = nil,
|
||||
selectedTranscriptionModelName: String? = nil, selectedLanguage: String? = nil, useScreenCapture: Bool = false,
|
||||
selectedAIProvider: String? = nil, selectedAIModel: String? = nil, isAutoSendEnabled: Bool = false, isEnabled: Bool = true) {
|
||||
selectedAIProvider: String? = nil, selectedAIModel: String? = nil, isAutoSendEnabled: Bool = false, isEnabled: Bool = true, isDefault: Bool = false) {
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.emoji = emoji
|
||||
@ -40,6 +41,7 @@ struct PowerModeConfig: Codable, Identifiable, Equatable {
|
||||
self.selectedTranscriptionModelName = selectedTranscriptionModelName ?? UserDefaults.standard.string(forKey: "CurrentTranscriptionModel")
|
||||
self.selectedLanguage = selectedLanguage ?? UserDefaults.standard.string(forKey: "SelectedLanguage") ?? "en"
|
||||
self.isEnabled = isEnabled
|
||||
self.isDefault = isDefault
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
@ -57,6 +59,7 @@ struct PowerModeConfig: Codable, Identifiable, Equatable {
|
||||
selectedAIModel = try container.decodeIfPresent(String.self, forKey: .selectedAIModel)
|
||||
isAutoSendEnabled = try container.decodeIfPresent(Bool.self, forKey: .isAutoSendEnabled) ?? false
|
||||
isEnabled = try container.decodeIfPresent(Bool.self, forKey: .isEnabled) ?? true
|
||||
isDefault = try container.decodeIfPresent(Bool.self, forKey: .isDefault) ?? false
|
||||
|
||||
if let newModelName = try container.decodeIfPresent(String.self, forKey: .selectedTranscriptionModelName) {
|
||||
selectedTranscriptionModelName = newModelName
|
||||
@ -83,6 +86,7 @@ struct PowerModeConfig: Codable, Identifiable, Equatable {
|
||||
try container.encode(isAutoSendEnabled, forKey: .isAutoSendEnabled)
|
||||
try container.encodeIfPresent(selectedTranscriptionModelName, forKey: .selectedTranscriptionModelName)
|
||||
try container.encode(isEnabled, forKey: .isEnabled)
|
||||
try container.encode(isDefault, forKey: .isDefault)
|
||||
}
|
||||
|
||||
|
||||
@ -204,15 +208,26 @@ class PowerModeManager: ObservableObject {
|
||||
return nil
|
||||
}
|
||||
|
||||
func getWildcardConfiguration() -> PowerModeConfig? {
|
||||
for config in configurations.filter({ $0.isEnabled }) {
|
||||
if let urlConfigs = config.urlConfigs {
|
||||
if urlConfigs.contains(where: { $0.url == "*" }) {
|
||||
return config
|
||||
}
|
||||
}
|
||||
func getDefaultConfiguration() -> PowerModeConfig? {
|
||||
return configurations.first { $0.isEnabled && $0.isDefault }
|
||||
}
|
||||
|
||||
func hasDefaultConfiguration() -> Bool {
|
||||
return configurations.contains { $0.isDefault }
|
||||
}
|
||||
|
||||
func setAsDefault(configId: UUID) {
|
||||
// Clear any existing default
|
||||
for index in configurations.indices {
|
||||
configurations[index].isDefault = false
|
||||
}
|
||||
return nil
|
||||
|
||||
// Set the specified config as default
|
||||
if let index = configurations.firstIndex(where: { $0.id == configId }) {
|
||||
configurations[index].isDefault = true
|
||||
}
|
||||
|
||||
saveConfigurations()
|
||||
}
|
||||
|
||||
func enableConfiguration(with id: UUID) {
|
||||
|
||||
@ -36,6 +36,7 @@ struct ConfigurationView: View {
|
||||
// New state for screen capture toggle
|
||||
@State private var useScreenCapture = false
|
||||
@State private var isAutoSendEnabled = false
|
||||
@State private var isDefault = false
|
||||
|
||||
// State for prompt editing (similar to EnhancementSettingsView)
|
||||
@State private var isEditingPrompt = false
|
||||
@ -44,6 +45,14 @@ struct ConfigurationView: View {
|
||||
// Whisper state for model selection
|
||||
@EnvironmentObject private var whisperState: WhisperState
|
||||
|
||||
// Computed property to check if current config is the default
|
||||
private var isCurrentConfigDefault: Bool {
|
||||
if case .edit(let config) = mode {
|
||||
return config.isDefault
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private var filteredApps: [(url: URL, name: String, bundleId: String, icon: NSImage)] {
|
||||
if searchText.isEmpty {
|
||||
return installedApps
|
||||
@ -77,6 +86,7 @@ struct ConfigurationView: View {
|
||||
_selectedEmoji = State(initialValue: "✏️")
|
||||
_useScreenCapture = State(initialValue: false)
|
||||
_isAutoSendEnabled = State(initialValue: false)
|
||||
_isDefault = State(initialValue: false)
|
||||
// Default to current global AI provider/model for new configurations - use UserDefaults only
|
||||
_selectedAIProvider = State(initialValue: UserDefaults.standard.string(forKey: "selectedAIProvider"))
|
||||
_selectedAIModel = State(initialValue: nil) // Initialize to nil and set it after view appears
|
||||
@ -93,6 +103,7 @@ struct ConfigurationView: View {
|
||||
_websiteConfigs = State(initialValue: latestConfig.urlConfigs ?? [])
|
||||
_useScreenCapture = State(initialValue: latestConfig.useScreenCapture)
|
||||
_isAutoSendEnabled = State(initialValue: latestConfig.isAutoSendEnabled)
|
||||
_isDefault = State(initialValue: latestConfig.isDefault)
|
||||
_selectedAIProvider = State(initialValue: latestConfig.selectedAIProvider)
|
||||
_selectedAIModel = State(initialValue: latestConfig.selectedAIModel)
|
||||
}
|
||||
@ -131,33 +142,50 @@ struct ConfigurationView: View {
|
||||
ScrollView {
|
||||
VStack(spacing: 20) {
|
||||
// Main Input Section
|
||||
HStack(spacing: 16) {
|
||||
Button(action: {
|
||||
isShowingEmojiPicker.toggle()
|
||||
}) {
|
||||
ZStack {
|
||||
Circle()
|
||||
.fill(Color.accentColor.opacity(0.15))
|
||||
.frame(width: 48, height: 48)
|
||||
|
||||
Text(selectedEmoji)
|
||||
.font(.system(size: 24))
|
||||
VStack(spacing: 16) {
|
||||
HStack(spacing: 16) {
|
||||
Button(action: {
|
||||
isShowingEmojiPicker.toggle()
|
||||
}) {
|
||||
ZStack {
|
||||
Circle()
|
||||
.fill(Color.accentColor.opacity(0.15))
|
||||
.frame(width: 48, height: 48)
|
||||
|
||||
Text(selectedEmoji)
|
||||
.font(.system(size: 24))
|
||||
}
|
||||
}
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.popover(isPresented: $isShowingEmojiPicker, arrowEdge: .bottom) {
|
||||
EmojiPickerView(
|
||||
selectedEmoji: $selectedEmoji,
|
||||
isPresented: $isShowingEmojiPicker
|
||||
)
|
||||
.buttonStyle(.plain)
|
||||
.popover(isPresented: $isShowingEmojiPicker, arrowEdge: .bottom) {
|
||||
EmojiPickerView(
|
||||
selectedEmoji: $selectedEmoji,
|
||||
isPresented: $isShowingEmojiPicker
|
||||
)
|
||||
}
|
||||
|
||||
TextField("Name your power mode", text: $configName)
|
||||
.font(.system(size: 18, weight: .bold))
|
||||
.textFieldStyle(.plain)
|
||||
.foregroundColor(.primary)
|
||||
.tint(.accentColor)
|
||||
.focused($isNameFieldFocused)
|
||||
}
|
||||
|
||||
TextField("Name your power mode", text: $configName)
|
||||
.font(.system(size: 18, weight: .bold))
|
||||
.textFieldStyle(.plain)
|
||||
.foregroundColor(.primary)
|
||||
.tint(.accentColor)
|
||||
.focused($isNameFieldFocused)
|
||||
// Default Power Mode Toggle
|
||||
if !powerModeManager.hasDefaultConfiguration() || isCurrentConfigDefault {
|
||||
HStack {
|
||||
Toggle("Set as default power mode", isOn: $isDefault)
|
||||
.font(.system(size: 14))
|
||||
|
||||
InfoTip(
|
||||
title: "Default Power Mode",
|
||||
message: "Default power mode is used when no specific app or website matches are found"
|
||||
)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 20)
|
||||
.padding(.vertical, 16)
|
||||
@ -649,7 +677,8 @@ struct ConfigurationView: View {
|
||||
useScreenCapture: useScreenCapture,
|
||||
selectedAIProvider: selectedAIProvider,
|
||||
selectedAIModel: selectedAIModel,
|
||||
isAutoSendEnabled: isAutoSendEnabled
|
||||
isAutoSendEnabled: isAutoSendEnabled,
|
||||
isDefault: isDefault
|
||||
)
|
||||
case .edit(let config):
|
||||
var updatedConfig = config
|
||||
@ -665,6 +694,7 @@ struct ConfigurationView: View {
|
||||
updatedConfig.isAutoSendEnabled = isAutoSendEnabled
|
||||
updatedConfig.selectedAIProvider = selectedAIProvider
|
||||
updatedConfig.selectedAIModel = selectedAIModel
|
||||
updatedConfig.isDefault = isDefault
|
||||
return updatedConfig
|
||||
}
|
||||
}
|
||||
@ -753,6 +783,11 @@ struct ConfigurationView: View {
|
||||
powerModeManager.updateConfiguration(config)
|
||||
}
|
||||
|
||||
// Handle default flag separately to ensure only one config is default
|
||||
if isDefault {
|
||||
powerModeManager.setAsDefault(configId: config.id)
|
||||
}
|
||||
|
||||
presentationMode.wrappedValue.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,6 +158,12 @@ struct ConfigurationRow: View {
|
||||
HStack(spacing: 6) {
|
||||
Text(config.name)
|
||||
.font(.system(size: 15, weight: .semibold))
|
||||
|
||||
if config.isDefault {
|
||||
Image(systemName: "star.fill")
|
||||
.font(.system(size: 12))
|
||||
.foregroundColor(.accentColor)
|
||||
}
|
||||
}
|
||||
|
||||
HStack(spacing: 12) {
|
||||
|
||||
@ -220,7 +220,6 @@ class WhisperState: NSObject, ObservableObject {
|
||||
await MainActor.run {
|
||||
recordingState = .idle
|
||||
}
|
||||
await PowerModeSessionManager.shared.endSession()
|
||||
await cleanupModelResources()
|
||||
return
|
||||
}
|
||||
@ -377,7 +376,6 @@ class WhisperState: NSObject, ObservableObject {
|
||||
}
|
||||
|
||||
await self.dismissMiniRecorder()
|
||||
await PowerModeSessionManager.shared.endSession()
|
||||
|
||||
} catch {
|
||||
do {
|
||||
@ -412,7 +410,6 @@ class WhisperState: NSObject, ObservableObject {
|
||||
}
|
||||
|
||||
await self.dismissMiniRecorder()
|
||||
await PowerModeSessionManager.shared.endSession()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user