Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to Xcode 16 & Swift 6 #7

Merged
merged 2 commits into from
Jan 5, 2025
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
4 changes: 2 additions & 2 deletions Demo/SpiceKeyDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.kyome.SpiceKeyDemo-SwiftUI";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
SWIFT_VERSION = 6.0;
};
name = Debug;
};
Expand Down Expand Up @@ -335,7 +335,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.kyome.SpiceKeyDemo-SwiftUI";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
SWIFT_VERSION = 6.0;
};
name = Release;
};
Expand Down
43 changes: 28 additions & 15 deletions Demo/SpiceKeyDemo_SwiftUI/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,15 @@ struct ContentView: View {
SpiceKeyField(keyCombination: $keyCombination)
.onChange(of: keyCombination) { newValue in
if let keyCombination = newValue {
keyComboSpiceKey = SpiceKey(keyCombination, keyDownHandler: {
state = "Key Combo: Key Down"
}, keyUpHandler: {
state = "Key Combo: Key Up"
})
keyComboSpiceKey = SpiceKey(
keyCombination,
keyDownHandler: {
await MainActor.run { state = "Key Combo: Key Down" }
},
keyUpHandler: {
await MainActor.run { state = "Key Combo: Key Up" }
}
)
keyComboSpiceKey?.register()
state = "Key Combo: Registered"
} else {
Expand All @@ -50,11 +54,15 @@ struct ContentView: View {
}
.onChange(of: bothSideSelection) { newValue in
if let modifierFlag = newValue {
bothSideSpiceKey = SpiceKey(modifierFlag, bothModifierKeysPressHandler: {
state = "Both Side: Press"
}, releaseKeyHandler: {
state = "Both Side: Release"
})
bothSideSpiceKey = SpiceKey(
modifierFlag,
bothModifierKeysPressHandler: {
await MainActor.run { state = "Both Side: Press" }
},
releaseKeyHandler: {
await MainActor.run { state = "Both Side: Release" }
}
)
bothSideSpiceKey?.register()
state = "Both Side: Registered"
} else {
Expand All @@ -74,11 +82,16 @@ struct ContentView: View {
}
.onChange(of: longPressSelection) { newValue in
if let modifierFlags = newValue {
longPressSpiceKey = SpiceKey(modifierFlags, 0.5, modifierKeysLongPressHandler: {
state = "Long Press: Press"
}, releaseKeyHandler: {
state = "Long Press: Release"
})
longPressSpiceKey = SpiceKey(
modifierFlags,
interval: 0.5,
modifierKeysLongPressHandler: {
await MainActor.run { state = "Long Press: Press" }
},
releaseKeyHandler: {
await MainActor.run { state = "Long Press: Release" }
}
)
longPressSpiceKey?.register()
state = "Long Press: Registered"
} else {
Expand Down
12 changes: 9 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
// swift-tools-version:5.10
// swift-tools-version: 6.0

import PackageDescription

let swiftSettings: [SwiftSetting] = [
.enableUpcomingFeature("ExistentialAny"),
]

let package = Package(
name: "SpiceKey",
defaultLocalization: "en",
Expand All @@ -17,11 +21,13 @@ let package = Package(
targets: [
.target(
name: "SpiceKey",
resources: [.process("Resources")]
resources: [.process("Resources")],
swiftSettings: swiftSettings
),
.testTarget(
name: "SpiceKeyTests",
dependencies: ["SpiceKey"]
dependencies: ["SpiceKey"],
swiftSettings: swiftSettings
)
]
)
24 changes: 8 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ Global Shortcuts for macOS written in Swift.

## Requirements

- Development with Xcode 15.2+
- Written in Swift 5.9
- swift-tools-version: 5.9
- Compatible with macOS 12.0+
- Development with Xcode 16.0+
- Written in Swift 6.0
- Compatible with macOS 13.5+

## Privacy Manifest

Expand Down Expand Up @@ -55,7 +54,7 @@ Set `long press ⌘` shortcut.
```swift
// run after 0.6 sec
let flags = ModifierFlags.cmd
let spiceKey = SpiceKey(flags, 0.6, modifierKeysLongPressHandler: {
let spiceKey = SpiceKey(flags, interval: 0.6, modifierKeysLongPressHandler: {
// process (press)
}, releaseKeyHandler: {
// process (release)
Expand Down Expand Up @@ -120,8 +119,10 @@ let spiceKeyData = SpiceKeyData(
)

// NSCoding
let data = try! NSKeyedArchiver.archivedData(withRootObject: spiceKeyData,
requiringSecureCoding: false)
let data = try! NSKeyedArchiver.archivedData(
withRootObject: spiceKeyData,
requiringSecureCoding: false
)
UserDefaults.standard.set(data, forKey: "spiceKeyData")

// Codable
Expand All @@ -141,12 +142,3 @@ let spiceKeyData = try! NSKeyedUnarchiver
let data = UserDefaults.standard.data(forKey: "spiceKeyData")!
let spiceKeyData = try! JSONDecoder().decode(SpiceKeyData.self, from: data)
```

## SpiceKeyField & SKTextField

A special text field that can be used to register SpiceKey.

- SpiceKeyField is for AppKit only.
- SKTextField is a SpiceKeyField made available from SwiftUI.

Please see the Demo App for detailed instructions.
2 changes: 1 addition & 1 deletion Sources/SpiceKey/Key.swift
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ public enum Key: Sendable {
return CGKeyCode(keyCode)
}

internal var keyCode32: UInt32 {
var keyCode32: UInt32 {
return UInt32(self.keyCode)
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/SpiceKey/ModifierFlags.swift
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ public enum ModifierFlags: Int, CaseIterable, Sendable {
flags.contains(NSEvent.ModifierFlags.command)
}

internal var flags32: UInt32 {
var flags32: UInt32 {
var _flags: UInt32 = 0
if flags.contains(.control) {
_flags |= UInt32(controlKey)
Expand Down
8 changes: 4 additions & 4 deletions Sources/SpiceKey/RawSpiceKeyField.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
import AppKit

protocol RawSpiceKeyFieldDelegate: NSTextFieldDelegate {
func didRegisterSpiceKey(_ field: RawSpiceKeyField, _ key: Key, _ flags: ModifierFlags)
func didDelete(_ field: RawSpiceKeyField)
@MainActor func didRegisterSpiceKey(_ field: RawSpiceKeyField, _ key: Key, _ flags: ModifierFlags)
@MainActor func didDelete(_ field: RawSpiceKeyField)
}

public final class RawSpiceKeyField: NSTextField {
private var isTyping: Bool = false
private var skfDelegate: RawSpiceKeyFieldDelegate? {
delegate as? RawSpiceKeyFieldDelegate
private var skfDelegate: (any RawSpiceKeyFieldDelegate)? {
delegate as? (any RawSpiceKeyFieldDelegate)
}
private var deleteButton: SpiceKeyDeleteButton!

Expand Down
34 changes: 17 additions & 17 deletions Sources/SpiceKey/SpiceKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,22 @@

import Carbon

public typealias Handler = () async -> Void
public typealias Handler = @Sendable () async -> Void

public final class SpiceKey {
internal let id: SpiceKeyID!
internal var eventHotKey: EventHotKeyRef?
internal var invoked: Bool = false
public let keyCombination: KeyCombination?
public let modifierFlags: ModifierFlags?
public let keyDownHandler: Handler?
public let keyUpHandler: Handler?
public let bothModifierKeysPressHandler: Handler?
public let modifierKeysLongPressHandler: Handler?
public let releaseKeyHandler: Handler?
public struct SpiceKey: Sendable {
var id: SpiceKeyID
var invoked = false

public private(set) var interval: Double = 0.0
public private(set) var isBothSide: Bool = false
public var keyCombination: KeyCombination?
public var modifierFlags: ModifierFlags?
public var keyDownHandler: Handler?
public var keyUpHandler: Handler?
public var bothModifierKeysPressHandler: Handler?
public var modifierKeysLongPressHandler: Handler?
public var releaseKeyHandler: Handler?

public private(set) var interval = Double.zero
public private(set) var isBothSide = false

public init(
_ keyCombination: KeyCombination,
Expand Down Expand Up @@ -58,7 +58,7 @@ public final class SpiceKey {

public init?(
_ modifierFlags: ModifierFlags,
_ interval: Double,
interval: Double,
modifierKeysLongPressHandler: Handler? = nil,
releaseKeyHandler: Handler? = nil
) {
Expand All @@ -84,9 +84,9 @@ public final class SpiceKey {

public var string: String {
if let keyCombination = keyCombination {
return keyCombination.string
keyCombination.string
} else if let modifierFlags = modifierFlags {
return modifierFlags.string
modifierFlags.string
} else {
fatalError("Impossible")
}
Expand Down
8 changes: 4 additions & 4 deletions Sources/SpiceKey/SpiceKeyData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ open class SpiceKeyData: NSObject, NSCoding, Codable, @unchecked Sendable {
self.init(primaryKey, keyCombination.key, keyCombination.modifierFlags, spiceKey)
}

// NSCoding
// MARK: NSCoding
required public init?(coder: NSCoder) {
primaryKey = (coder.decodeObject(forKey: "primaryKey") as? String) ?? ""
keyCode = coder.decodeObject(forKey: "keyCode") as! CGKeyCode
Expand All @@ -98,8 +98,8 @@ open class SpiceKeyData: NSObject, NSCoding, Codable, @unchecked Sendable {
coder.encode(command, forKey: "command")
}

// Codable
public required init(from decoder: Decoder) throws {
// MARK: Codable
public required init(from decoder: any Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
primaryKey = try container.decode(String.self, forKey: .primaryKey)
keyCode = try container.decode(CGKeyCode.self, forKey: .keyCode)
Expand All @@ -109,7 +109,7 @@ open class SpiceKeyData: NSObject, NSCoding, Codable, @unchecked Sendable {
command = try container.decode(Bool.self, forKey: .command)
}

public func encode(to encoder: Encoder) throws {
public func encode(to encoder: any Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(primaryKey, forKey: .primaryKey)
try container.encode(keyCode, forKey: .keyCode)
Expand Down
2 changes: 1 addition & 1 deletion Sources/SpiceKey/SpiceKeyField.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public struct SpiceKeyField: NSViewRepresentable {
Coordinator(self)
}

public class Coordinator: NSObject, RawSpiceKeyFieldDelegate {
@MainActor public class Coordinator: NSObject, RawSpiceKeyFieldDelegate {
let parent: SpiceKeyField
var registeredHandler: ((String?, KeyCombination) -> Void)?
var deletedHandler: ((String?) -> Void)?
Expand Down
Loading