Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 0 additions & 24 deletions Sources/MiniWhisper/AppState.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import Foundation
import Observation
import AppKit
import ServiceManagement
import UserNotifications

@Observable
Expand Down Expand Up @@ -38,8 +37,6 @@ final class AppState: Sendable {

var isModelDownloading: Bool { whisper.isDownloading }
var modelDownloadProgress: Double { whisper.downloadProgress }
var launchAtLoginEnabled: Bool { SMAppService.mainApp.status == .enabled }
var launchAtLoginSupported: Bool { SMAppService.mainApp.status != .notFound }

// MARK: - Initialization

Expand Down Expand Up @@ -212,27 +209,6 @@ final class AppState: Sendable {
}
}

func setLaunchAtLogin(_ enabled: Bool) {
let service = SMAppService.mainApp
guard service.status != .notFound else {
toast.showError(
title: "Start on Login Unavailable",
message: "This is available only when running the bundled app."
)
return
}

do {
if enabled {
try service.register()
} else {
try service.unregister()
}
} catch {
toast.showError(title: "Start on Login Failed", message: error.localizedDescription)
}
}

// MARK: - Transcription

private func transcribe(audioURL: URL, recordingId: String, duration: TimeInterval, sampleRate: Double) async {
Expand Down
46 changes: 46 additions & 0 deletions Sources/MiniWhisper/Services/LaunchAtLoginManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import Foundation
import ServiceManagement

@MainActor
final class LaunchAtLoginManager: ObservableObject {
static let shared = LaunchAtLoginManager()

@Published var isEnabled: Bool {
didSet {
if isEnabled {
enableLaunchAtLogin()
} else {
disableLaunchAtLogin()
}
}
}

private init() {
isEnabled = SMAppService.mainApp.status == .enabled
}

private func enableLaunchAtLogin() {
do {
try SMAppService.mainApp.register()
} catch {
Task { @MainActor in
self.isEnabled = false
}
}
}

private func disableLaunchAtLogin() {
do {
try SMAppService.mainApp.unregister()
} catch {
return
}
}

func refresh() {
let newStatus = SMAppService.mainApp.status == .enabled
if newStatus != isEnabled {
_isEnabled = Published(wrappedValue: newStatus)
}
}
}
36 changes: 18 additions & 18 deletions Sources/MiniWhisper/Views/MenuBarView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ private struct PermissionRow: View {

private struct FooterBarView: View {
@Environment(AppState.self) private var appState
@StateObject private var launchManager = LaunchAtLoginManager.shared
@State private var showHistory = false
@State private var showReplacements = false
@State private var showModelPicker = false
Expand Down Expand Up @@ -432,9 +433,9 @@ private struct FooterBarView: View {
Button {
showLaunchAtLogin.toggle()
} label: {
Image(systemName: appState.launchAtLoginEnabled ? "power.circle.fill" : "power.circle")
Image(systemName: launchManager.isEnabled ? "power.circle.fill" : "power.circle")
.font(.system(size: 14))
.foregroundColor(appState.launchAtLoginEnabled ? .accentColor : .secondary)
.foregroundColor(launchManager.isEnabled ? .accentColor : .secondary)
.frame(width: 28, height: 28)
}
.buttonStyle(.plain)
Expand All @@ -456,11 +457,14 @@ private struct FooterBarView: View {
}
.padding(.horizontal, 16)
.padding(.vertical, 8)
.onAppear {
launchManager.refresh()
}
}
}

private struct LaunchAtLoginPopoverView: View {
@Environment(AppState.self) private var appState
@StateObject private var launchManager = LaunchAtLoginManager.shared

var body: some View {
VStack(alignment: .leading, spacing: 10) {
Expand All @@ -470,25 +474,21 @@ private struct LaunchAtLoginPopoverView: View {
.textCase(.uppercase)
.tracking(0.5)

if appState.launchAtLoginSupported {
Toggle(
"Start MiniWhisper when you log in",
isOn: Binding(
get: { appState.launchAtLoginEnabled },
set: { appState.setLaunchAtLogin($0) }
)
Toggle(
"Start MiniWhisper when you log in",
isOn: Binding(
get: { launchManager.isEnabled },
set: { launchManager.isEnabled = $0 }
)
.toggleStyle(.switch)
.font(.system(size: 13))
} else {
Text("Unavailable in this runtime. Build/run the bundled app to enable login item registration.")
.font(.system(size: 12))
.foregroundColor(.secondary)
.fixedSize(horizontal: false, vertical: true)
}
)
.toggleStyle(.switch)
.font(.system(size: 13))
}
.padding(12)
.frame(width: 280)
.onAppear {
launchManager.refresh()
}
}
}

Expand Down
Loading