Browse Source

feat: add AppIntents support, disable AppNap, and export physical key status

main
Ali Alavi 5 days ago
parent
commit
f41df96ce7
  1. 2
      Info.plist
  2. 6
      package.sh
  3. 1
      resources/Metadata.appintents/extract.actionsdata
  4. 4
      resources/Metadata.appintents/version.json
  5. 4
      src/HotkeyManager.swift
  6. 85
      src/Intents.swift

2
Info.plist

@ -26,6 +26,8 @@
<string>13.0</string> <string>13.0</string>
<key>LSUIElement</key> <key>LSUIElement</key>
<true/> <true/>
<key>NSSupportsAppNap</key>
<false/>
<key>NSHighResolutionCapable</key> <key>NSHighResolutionCapable</key>
<true/> <true/>
<key>NSMicrophoneUsageDescription</key> <key>NSMicrophoneUsageDescription</key>

6
package.sh

@ -13,7 +13,7 @@ rm -rf "$APP_BUNDLE"
# 1. Compile Swift sources (Pure Native Swift) # 1. Compile Swift sources (Pure Native Swift)
swiftc -O -target arm64-apple-macosx13.0 \ swiftc -O -target arm64-apple-macosx13.0 \
-framework Cocoa -framework AVFoundation -framework Carbon \
-framework Cocoa -framework AVFoundation -framework Carbon -framework AppIntents \
"$PROJECT_DIR"/src/*.swift \ "$PROJECT_DIR"/src/*.swift \
-o "$BUILD_DIR/SonioxVoice" -o "$BUILD_DIR/SonioxVoice"
@ -29,6 +29,10 @@ cp "$BUILD_DIR/SonioxVoice" "$APP_BUNDLE/Contents/MacOS/SonioxVoice"
cp "$PROJECT_DIR/Info.plist" "$APP_BUNDLE/Contents/Info.plist" cp "$PROJECT_DIR/Info.plist" "$APP_BUNDLE/Contents/Info.plist"
cp "$PROJECT_DIR/resources/AppIcon.icns" "$APP_BUNDLE/Contents/Resources/AppIcon.icns" cp "$PROJECT_DIR/resources/AppIcon.icns" "$APP_BUNDLE/Contents/Resources/AppIcon.icns"
if [ -d "$PROJECT_DIR/resources/Metadata.appintents" ]; then
cp -R "$PROJECT_DIR/resources/Metadata.appintents" "$APP_BUNDLE/Contents/Resources/"
fi
# 3. Ad-hoc Codesign # 3. Ad-hoc Codesign
codesign --force --deep --sign - "$APP_BUNDLE" codesign --force --deep --sign - "$APP_BUNDLE"

1
resources/Metadata.appintents/extract.actionsdata

@ -0,0 +1 @@
{"actions": {"StartRecordingIntent": {"actionConfiguration": {"actionSummary": {"wrapper": {"otherParameterIdentifiers": []}}}, "assistantDefinedSchemaTraits": [], "assistantDefinedSchemas": [], "authenticationPolicy": 0, "availabilityAnnotations": {"LNPlatformNameIOS": {"introducedVersion": "16.0"}, "LNPlatformNameMACOS": {"introducedVersion": "13.0"}, "LNPlatformNameWildcard": {"introducedVersion": "*"}}, "customIntentClassName": "StartRecordingIntent", "descriptionMetadata": {"descriptionText": {"alternatives": [], "key": "Starts voice recording and real-time word-by-word streaming."}, "searchKeywords": []}, "effectiveBundleIdentifiers": [], "fullyQualifiedTypeName": "SonioxVoice.StartRecordingIntent", "identifier": "StartRecordingIntent", "isAuthPolExplicit": false, "isDiscoverable": true, "mangledTypeName": "11SonioxVoice20StartRecordingIntentV", "mangledTypeNameByBundleIdentifier": {}, "mangledTypeNameByBundleIdentifierV2": {}, "mangledTypeNameV2": "11SonioxVoice20StartRecordingIntentV", "openAppWhenRun": false, "outputFlags": 0, "parameters": [], "presentationStyle": 0, "requiredCapabilities": [], "supportedModes": 1, "systemProtocolMetadata": [], "systemProtocolMetadataV2": [], "systemProtocols": [], "title": {"alternatives": [], "key": "Start Recording"}, "typeSpecificMetadata": [], "visibilityMetadata": {"assistantOnly": false, "isDiscoverable": true}}, "StopRecordingIntent": {"actionConfiguration": {"actionSummary": {"wrapper": {"otherParameterIdentifiers": []}}}, "assistantDefinedSchemaTraits": [], "assistantDefinedSchemas": [], "authenticationPolicy": 0, "availabilityAnnotations": {"LNPlatformNameIOS": {"introducedVersion": "16.0"}, "LNPlatformNameMACOS": {"introducedVersion": "13.0"}, "LNPlatformNameWildcard": {"introducedVersion": "*"}}, "customIntentClassName": "StopRecordingIntent", "descriptionMetadata": {"descriptionText": {"alternatives": [], "key": "Stops active recording and finalizes text paste."}, "searchKeywords": []}, "effectiveBundleIdentifiers": [], "fullyQualifiedTypeName": "SonioxVoice.StopRecordingIntent", "identifier": "StopRecordingIntent", "isAuthPolExplicit": false, "isDiscoverable": true, "mangledTypeName": "11SonioxVoice19StopRecordingIntentV", "mangledTypeNameByBundleIdentifier": {}, "mangledTypeNameByBundleIdentifierV2": {}, "mangledTypeNameV2": "11SonioxVoice19StopRecordingIntentV", "openAppWhenRun": false, "outputFlags": 0, "parameters": [], "presentationStyle": 0, "requiredCapabilities": [], "supportedModes": 1, "systemProtocolMetadata": [], "systemProtocolMetadataV2": [], "systemProtocols": [], "title": {"alternatives": [], "key": "Stop Recording"}, "typeSpecificMetadata": [], "visibilityMetadata": {"assistantOnly": false, "isDiscoverable": true}}, "ToggleRecordingIntent": {"actionConfiguration": {"actionSummary": {"wrapper": {"otherParameterIdentifiers": []}}}, "assistantDefinedSchemaTraits": [], "assistantDefinedSchemas": [], "authenticationPolicy": 0, "availabilityAnnotations": {"LNPlatformNameIOS": {"introducedVersion": "16.0"}, "LNPlatformNameMACOS": {"introducedVersion": "13.0"}, "LNPlatformNameWildcard": {"introducedVersion": "*"}}, "customIntentClassName": "ToggleRecordingIntent", "descriptionMetadata": {"descriptionText": {"alternatives": [], "key": "Toggles voice recording on or off."}, "searchKeywords": []}, "effectiveBundleIdentifiers": [], "fullyQualifiedTypeName": "SonioxVoice.ToggleRecordingIntent", "identifier": "ToggleRecordingIntent", "isAuthPolExplicit": false, "isDiscoverable": true, "mangledTypeName": "11SonioxVoice21ToggleRecordingIntentV", "mangledTypeNameByBundleIdentifier": {}, "mangledTypeNameByBundleIdentifierV2": {}, "mangledTypeNameV2": "11SonioxVoice21ToggleRecordingIntentV", "openAppWhenRun": false, "outputFlags": 0, "parameters": [], "presentationStyle": 0, "requiredCapabilities": [], "supportedModes": 1, "systemProtocolMetadata": [], "systemProtocolMetadataV2": [], "systemProtocols": [], "title": {"alternatives": [], "key": "Toggle Recording"}, "typeSpecificMetadata": [], "visibilityMetadata": {"assistantOnly": false, "isDiscoverable": true}}}, "assistantEntities": [], "assistantIntentNegativePhrases": [], "assistantIntents": [], "autoShortcutProviderMangledName": "", "autoShortcuts": [], "entities": {}, "enums": [], "generator": {"name": "xcode-tools", "version": "17C52"}, "negativePhrases": [], "queries": {}, "shortcutTileColor": 14, "version": 1}

4
resources/Metadata.appintents/version.json

@ -0,0 +1,4 @@
{
"version" : "3.0",
"toolsVersion" : "17C52"
}

4
src/HotkeyManager.swift

@ -74,6 +74,10 @@ public final class HotkeyManager {
private var isCapsLockPhysicallyDown = false private var isCapsLockPhysicallyDown = false
private var isF5PhysicallyDown = false private var isF5PhysicallyDown = false
private var isFnPhysicallyDown = false private var isFnPhysicallyDown = false
public var isPhysicalKeyDown: Bool {
return isOptionPhysicallyDown || isCapsLockPhysicallyDown || isF5PhysicallyDown || isFnPhysicallyDown
}
private var lastFnPressTime: TimeInterval = 0 private var lastFnPressTime: TimeInterval = 0
private var lastTriggerTime: TimeInterval = 0 private var lastTriggerTime: TimeInterval = 0

85
src/Intents.swift

@ -0,0 +1,85 @@
import Foundation
import AppIntents
@available(macOS 13.0, *)
public struct StartRecordingIntent: AppIntent {
public static var title: LocalizedStringResource = "Start Recording"
public static var description = IntentDescription("Starts voice recording with Soniox Voice")
public static var openAppWhenRun: Bool = false
public init() {}
@MainActor
public func perform() async throws -> some IntentResult {
print("StartRecordingIntent: Executing startRecording via AppIntent...")
// 1. In-process direct execution if running in the main app
if let app = AppDelegate.shared {
app.startRecording()
}
// 2. Out-of-process IPC notification (for when Shortcuts runner executes this)
DistributedNotificationCenter.default().postNotificationName(
NSNotification.Name("com.soniox.voice.start"),
object: nil,
userInfo: nil,
deliverImmediately: true
)
return .result()
}
}
@available(macOS 13.0, *)
public struct StopRecordingIntent: AppIntent {
public static var title: LocalizedStringResource = "Stop Recording"
public static var description = IntentDescription("Stops active voice recording and finalizes text paste")
public static var openAppWhenRun: Bool = false
public init() {}
@MainActor
public func perform() async throws -> some IntentResult {
print("StopRecordingIntent: Executing stopRecording via AppIntent...")
if let app = AppDelegate.shared {
app.stopRecording()
}
DistributedNotificationCenter.default().postNotificationName(
NSNotification.Name("com.soniox.voice.stop"),
object: nil,
userInfo: nil,
deliverImmediately: true
)
return .result()
}
}
@available(macOS 13.0, *)
public struct ToggleRecordingIntent: AppIntent {
public static var title: LocalizedStringResource = "Toggle Recording"
public static var description = IntentDescription("Toggles voice recording on or off")
public static var openAppWhenRun: Bool = false
public init() {}
@MainActor
public func perform() async throws -> some IntentResult {
print("ToggleRecordingIntent: Executing toggleRecording via AppIntent...")
if let app = AppDelegate.shared {
app.toggleRecording()
}
DistributedNotificationCenter.default().postNotificationName(
NSNotification.Name("com.soniox.voice.toggle"),
object: nil,
userInfo: nil,
deliverImmediately: true
)
return .result()
}
}
Loading…
Cancel
Save