Skip to content

Commit

Permalink
Add OpenAtLogin.swift into MultitouchExtension
Browse files Browse the repository at this point in the history
  • Loading branch information
tekezo committed May 31, 2024
1 parent fb3d244 commit 49a3ed0
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 15 deletions.
21 changes: 11 additions & 10 deletions src/apps/MultitouchExtension/src/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,24 @@ public class AppDelegate: NSObject, NSApplicationDelegate {
NSApplication.shared.disableRelaunchOnLogin()

//
// Handle kHideIconInDock
// Register OpenAtLogin
//

if !UserSettings.shared.hideIconInDock {
var psn = ProcessSerialNumber(highLongOfPSN: 0, lowLongOfPSN: UInt32(kCurrentProcess))
TransformProcessType(
&psn, ProcessApplicationTransformState(kProcessTransformToForegroundApplication))
if !OpenAtLogin.shared.developmentBinary {
if !UserSettings.shared.initialOpenAtLoginRegistered {
OpenAtLogin.shared.update(register: true)
UserSettings.shared.initialOpenAtLoginRegistered = true
}
}

//
// Handle --start-at-login
// Handle kHideIconInDock
//

if CommandLine.arguments.contains("--start-at-login") {
if !UserSettings.shared.openAtLogin {
NSApplication.shared.terminate(self)
}
if !UserSettings.shared.hideIconInDock {
var psn = ProcessSerialNumber(highLongOfPSN: 0, lowLongOfPSN: UInt32(kCurrentProcess))
TransformProcessType(
&psn, ProcessApplicationTransformState(kProcessTransformToForegroundApplication))
}

//
Expand Down
58 changes: 58 additions & 0 deletions src/apps/MultitouchExtension/src/OpenAtLogin.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import Foundation
import ServiceManagement

final class OpenAtLogin: ObservableObject {
static let shared = OpenAtLogin()

@Published var registered = false

var error = ""

init() {
registered = SMAppService.mainApp.status == .enabled
}

var developmentBinary: Bool {
let bundlePath = Bundle.main.bundlePath

// Xcode builds
// - /Build/Products/Debug/*.app
// - /Build/Products/Release/*.app
if bundlePath.contains("/Build/") {
return true
}

// Command line builds
// - /build/Release/*.app
if bundlePath.contains("/build/") {
return true
}

return false
}

@MainActor
func update(register: Bool) {
error = ""

do {
if register {
try SMAppService.mainApp.register()
} else {
// `unregister` throws `Operation not permitted` error in the following cases.
//
// 1. `unregister` is called.
// 2. macOS is restarted to clean up login items entries.
// 3. `unregister` is called again.
//
// So, we ignore the error of `unregister`.

try? SMAppService.mainApp.unregister()
}

registered = register
} catch {
self.error = error.localizedDescription
}
}
}
4 changes: 2 additions & 2 deletions src/apps/MultitouchExtension/src/UserSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import Foundation
final class UserSettings: ObservableObject {
static let shared = UserSettings()

@UserDefault("kStartAtLogin", defaultValue: false)
var openAtLogin: Bool {
@UserDefault("initialOpenAtLoginRegistered", defaultValue: false)
var initialOpenAtLoginRegistered: Bool {
willSet {
objectWillChange.send()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,37 @@ import SwiftUI

struct SettingsMainView: View {
@ObservedObject private var userSettings = UserSettings.shared
@ObservedObject private var openAtLogin = OpenAtLogin.shared

var body: some View {
VStack(alignment: .leading, spacing: 25.0) {
GroupBox(label: Text("Basic")) {
VStack(alignment: .leading, spacing: 25.0) {
HStack {
Toggle(isOn: $userSettings.openAtLogin) {
Toggle(isOn: $openAtLogin.registered) {
Text("Open at login")
}
.switchToggleStyle()

Text("(Default: off)")
.disabled(openAtLogin.developmentBinary)
.onChange(of: openAtLogin.registered) { value in
OpenAtLogin.shared.update(register: value)
}

Spacer()
}

if openAtLogin.error.count > 0 {
VStack {
Label(
openAtLogin.error,
systemImage: "exclamationmark.circle.fill"
)
.padding()
}
.foregroundColor(Color.errorForeground)
.background(Color.errorBackground)
}

VStack(alignment: .leading) {
HStack {
Toggle(isOn: $userSettings.hideIconInDock) {
Expand Down

0 comments on commit 49a3ed0

Please sign in to comment.