Skip to content

Commit

Permalink
Merge pull request #7 from Kyome22/xcode-16
Browse files Browse the repository at this point in the history
Migrate to Xcode 16 & Swift 6
  • Loading branch information
Kyome22 authored Jan 5, 2025
2 parents 704750a + d4a1064 commit 5afc91d
Show file tree
Hide file tree
Showing 11 changed files with 225 additions and 197 deletions.
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

0 comments on commit 5afc91d

Please sign in to comment.