diff --git a/Example/KeyboardShortcutsExample/App.swift b/Example/KeyboardShortcutsExample/App.swift index cfda6006..5451af0e 100644 --- a/Example/KeyboardShortcutsExample/App.swift +++ b/Example/KeyboardShortcutsExample/App.swift @@ -2,13 +2,11 @@ import SwiftUI @main struct AppMain: App { - @StateObject private var state = AppState() - var body: some Scene { WindowGroup { MainScreen() .task { - state.createMenus() + AppState.shared.createMenus() } } } diff --git a/Example/KeyboardShortcutsExample/AppState.swift b/Example/KeyboardShortcutsExample/AppState.swift index 6edf4521..7327506d 100644 --- a/Example/KeyboardShortcutsExample/AppState.swift +++ b/Example/KeyboardShortcutsExample/AppState.swift @@ -1,7 +1,11 @@ import SwiftUI @MainActor -final class AppState: ObservableObject { +final class AppState { + static let shared = AppState() + + private init() {} + func createMenus() { let testMenuItem = NSMenuItem() NSApp.mainMenu?.addItem(testMenuItem) @@ -13,22 +17,22 @@ final class AppState: ObservableObject { testMenu.addCallbackItem("Shortcut 1") { [weak self] in self?.alert(1) } - .setShortcut(for: .testShortcut1) + .setShortcut(for: .testShortcut1) testMenu.addCallbackItem("Shortcut 2") { [weak self] in self?.alert(2) } - .setShortcut(for: .testShortcut2) + .setShortcut(for: .testShortcut2) testMenu.addCallbackItem("Shortcut 3") { [weak self] in self?.alert(3) } - .setShortcut(for: .testShortcut3) + .setShortcut(for: .testShortcut3) testMenu.addCallbackItem("Shortcut 4") { [weak self] in self?.alert(4) } - .setShortcut(for: .testShortcut4) + .setShortcut(for: .testShortcut4) } private func alert(_ number: Int) { diff --git a/Example/KeyboardShortcutsExample/MainScreen.swift b/Example/KeyboardShortcutsExample/MainScreen.swift index 0ab97ef2..79e4d85c 100644 --- a/Example/KeyboardShortcutsExample/MainScreen.swift +++ b/Example/KeyboardShortcutsExample/MainScreen.swift @@ -22,9 +22,9 @@ private struct DynamicShortcutRecorder: View { Text("Pressed? \(isPressed ? "👍" : "👎")") .frame(width: 100, alignment: .leading) } - .onChange(of: name) { - isFocused = true - } + .onChange(of: name) { + isFocused = true + } } } @@ -58,12 +58,12 @@ private struct DynamicShortcut: View { DynamicShortcutRecorder(name: $shortcut.name, isPressed: $isPressed) } } - .frame(maxWidth: 300) - .padding() - .padding(.bottom, 20) - .onChange(of: shortcut) { oldValue, newValue in - onShortcutChange(oldValue: oldValue, newValue: newValue) - } + .frame(maxWidth: 300) + .padding() + .padding(.bottom, 20) + .onChange(of: shortcut) { oldValue, newValue in + onShortcutChange(oldValue: oldValue, newValue: newValue) + } } private func onShortcutChange(oldValue: Shortcut, newValue: Shortcut) { @@ -93,30 +93,30 @@ private struct DoubleShortcut: View { KeyboardShortcuts.Recorder(for: .testShortcut2) { Text("Shortcut 2:") // Intentionally using the verbose initializer for testing. } - .overlay(alignment: .trailing) { - Text("Pressed? \(isPressed2 ? "👍" : "👎")") - .offset(x: 90) - } + .overlay(alignment: .trailing) { + Text("Pressed? \(isPressed2 ? "👍" : "👎")") + .offset(x: 90) + } Spacer() Button("Reset All") { KeyboardShortcuts.reset(.testShortcut1, .testShortcut2) } } - .offset(x: -40) - .frame(maxWidth: 300) - .padding() - .padding() - .onGlobalKeyboardShortcut(.testShortcut1) { - isPressed1 = $0 == .keyDown - } - .onGlobalKeyboardShortcut(.testShortcut2, type: .keyDown) { - isPressed2 = true - } - .task { - KeyboardShortcuts.onKeyUp(for: .testShortcut2) { - isPressed2 = false - } + .offset(x: -40) + .frame(maxWidth: 300) + .padding() + .padding() + .onGlobalKeyboardShortcut(.testShortcut1) { + isPressed1 = $0 == .keyDown + } + .onGlobalKeyboardShortcut(.testShortcut2, type: .keyDown) { + isPressed2 = true + } + .task { + KeyboardShortcuts.onKeyUp(for: .testShortcut2) { + isPressed2 = false } + } } } @@ -127,7 +127,7 @@ struct MainScreen: View { Divider() DynamicShortcut() } - .frame(width: 400, height: 320) + .frame(width: 400, height: 320) } } diff --git a/Sources/KeyboardShortcuts/Recorder.swift b/Sources/KeyboardShortcuts/Recorder.swift index f3cdfc5b..8575db03 100644 --- a/Sources/KeyboardShortcuts/Recorder.swift +++ b/Sources/KeyboardShortcuts/Recorder.swift @@ -38,6 +38,8 @@ extension KeyboardShortcuts { } } ``` + + - Note: Since macOS 15, for sandboxed apps, it's [no longer possible](https://developer.apple.com/forums/thread/763878?answerId=804374022#804374022) to specify the `Option` key without also using `Command` or `Control`. */ public struct Recorder: View { // swiftlint:disable:this type_name private let name: Name diff --git a/Sources/KeyboardShortcuts/Utilities.swift b/Sources/KeyboardShortcuts/Utilities.swift index 0377d6b4..3b9d308c 100644 --- a/Sources/KeyboardShortcuts/Utilities.swift +++ b/Sources/KeyboardShortcuts/Utilities.swift @@ -477,7 +477,7 @@ extension View { labelsHidden() .alignmentGuide(.controlAlignment) { $0[.leading] } } - .alignmentGuide(.leading) { $0[.controlAlignment] } + .alignmentGuide(.leading) { $0[.controlAlignment] } } } diff --git a/readme.md b/readme.md index dd38054c..04f03de8 100644 --- a/readme.md +++ b/readme.md @@ -65,7 +65,7 @@ import KeyboardShortcuts @main struct YourApp: App { - @StateObject private var appState = AppState() + @State private var appState = AppState() var body: some Scene { WindowGroup { @@ -78,7 +78,8 @@ struct YourApp: App { } @MainActor -final class AppState: ObservableObject { +@Observable +final class AppState { init() { KeyboardShortcuts.onKeyUp(for: .toggleUnicornMode) { [self] in isUnicornMode.toggle()