From 387640f2ff2242978444d0178e2fe5cb6abe7f5f Mon Sep 17 00:00:00 2001 From: Matt Kiazyk Date: Wed, 8 Dec 2021 15:31:59 -0600 Subject: [PATCH] Intents (WIP) --- Xcodes.xcodeproj/project.pbxproj | 7 + Xcodes/Resources/Info.plist | 10 + Xcodes/Resources/Intents.intentdefinition | 273 ++++++++++++++++++++++ Xcodes/Resources/Licenses.rtf | 2 +- Xcodes/XcodesApp.swift | 55 +++++ 5 files changed, 346 insertions(+), 1 deletion(-) create mode 100644 Xcodes/Resources/Intents.intentdefinition diff --git a/Xcodes.xcodeproj/project.pbxproj b/Xcodes.xcodeproj/project.pbxproj index 609ff3d..5764d05 100644 --- a/Xcodes.xcodeproj/project.pbxproj +++ b/Xcodes.xcodeproj/project.pbxproj @@ -102,6 +102,7 @@ CAFE4ABC25B7D54B0064FE51 /* UpdatesPreferencePane.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAFE4ABB25B7D54B0064FE51 /* UpdatesPreferencePane.swift */; }; CAFFFED8259CDA5000903F81 /* XcodeListViewRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAFFFED7259CDA5000903F81 /* XcodeListViewRow.swift */; }; E87DD6EB25D053FA00D86808 /* Progress+.swift in Sources */ = {isa = PBXBuildFile; fileRef = E87DD6EA25D053FA00D86808 /* Progress+.swift */; }; + E886ED08273D7D2F00CD81A2 /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = E886ED07273D7D2F00CD81A2 /* Intents.intentdefinition */; }; E89342FA25EDCC17007CF557 /* NotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E89342F925EDCC17007CF557 /* NotificationManager.swift */; }; E8977EA325C11E1500835F80 /* PreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8977EA225C11E1500835F80 /* PreferencesView.swift */; }; E8DA461125FAF7FB002E85EF /* NotificationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8DA461025FAF7FB002E85EF /* NotificationsView.swift */; }; @@ -270,6 +271,7 @@ CAFFFED7259CDA5000903F81 /* XcodeListViewRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XcodeListViewRow.swift; sourceTree = ""; }; CAFFFEEE259CEAC400903F81 /* RingProgressViewStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RingProgressViewStyle.swift; sourceTree = ""; }; E87DD6EA25D053FA00D86808 /* Progress+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Progress+.swift"; sourceTree = ""; }; + E886ED07273D7D2F00CD81A2 /* Intents.intentdefinition */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; path = Intents.intentdefinition; sourceTree = ""; }; E89342F925EDCC17007CF557 /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = ""; }; E8977EA225C11E1500835F80 /* PreferencesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesView.swift; sourceTree = ""; }; E8DA461025FAF7FB002E85EF /* NotificationsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsView.swift; sourceTree = ""; }; @@ -484,6 +486,7 @@ CA9FF83E2594FBC000E47BAF /* Licenses.rtf */, CAD2E7AE2449575000113D76 /* Xcodes.entitlements */, CA8FB64D256E17B100469DA5 /* XcodesTest.entitlements */, + E886ED07273D7D2F00CD81A2 /* Intents.intentdefinition */, ); path = Resources; sourceTree = ""; @@ -823,6 +826,7 @@ CABFA9C72592EEEA00380FEE /* Entry+.swift in Sources */, CAE424B4259A764700B8B246 /* AppState+Install.swift in Sources */, CAE42487259A68A300B8B246 /* XcodeListCategory.swift in Sources */, + E886ED08273D7D2F00CD81A2 /* Intents.intentdefinition in Sources */, CAA858C425A2BE4E00ACF8C0 /* Downloader.swift in Sources */, E8977EA325C11E1500835F80 /* PreferencesView.swift in Sources */, CA9FF87B2595293E00E47BAF /* DataSource.swift in Sources */, @@ -941,6 +945,7 @@ ENABLE_HARDENED_RUNTIME = NO; ENABLE_PREVIEWS = YES; INFOPLIST_FILE = Xcodes/Resources/Info.plist; + INTENTS_CODEGEN_LANGUAGE = Swift; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", @@ -1177,6 +1182,7 @@ ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; INFOPLIST_FILE = Xcodes/Resources/Info.plist; + INTENTS_CODEGEN_LANGUAGE = Swift; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", @@ -1200,6 +1206,7 @@ ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; INFOPLIST_FILE = Xcodes/Resources/Info.plist; + INTENTS_CODEGEN_LANGUAGE = Swift; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", diff --git a/Xcodes/Resources/Info.plist b/Xcodes/Resources/Info.plist index ac71cf1..b0f3d61 100644 --- a/Xcodes/Resources/Info.plist +++ b/Xcodes/Resources/Info.plist @@ -22,6 +22,12 @@ 8 CODE_SIGNING_SUBJECT_ORGANIZATIONAL_UNIT $(CODE_SIGNING_SUBJECT_ORGANIZATIONAL_UNIT) + INIntentsSupported + + DownloadXcodeVersionIntent + + LSApplicationCategoryType + public.app-category.utilities LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) NSHumanReadableCopyright @@ -32,6 +38,10 @@ NSSupportsSuddenTermination + NSUserActivityTypes + + DownloadXcodeVersionIntent + SMPrivilegedExecutables com.robotsandpencils.XcodesApp.Helper diff --git a/Xcodes/Resources/Intents.intentdefinition b/Xcodes/Resources/Intents.intentdefinition new file mode 100644 index 0000000..f9815eb --- /dev/null +++ b/Xcodes/Resources/Intents.intentdefinition @@ -0,0 +1,273 @@ + + + + + INEnums + + INIntentDefinitionModelVersion + 1.2 + INIntentDefinitionNamespace + DDibcP + INIntentDefinitionSystemVersion + 21A559 + INIntentDefinitionToolsBuildVersion + 13A1030d + INIntentDefinitionToolsVersion + 13.1 + INIntents + + + INIntentCategory + download + INIntentConfigurable + + INIntentDescription + Downloads a specific xcode version from input + INIntentDescriptionID + 7WiRvz + INIntentInput + version + INIntentKeyParameter + version + INIntentLastParameterTag + 4 + INIntentManagedParameterCombinations + + version + + INIntentParameterCombinationSupportsBackgroundExecution + + INIntentParameterCombinationTitle + Download Xcode ${version} + INIntentParameterCombinationTitleID + PjUEKy + INIntentParameterCombinationUpdatesLinked + + + + INIntentName + DownloadXcodeVersion + INIntentParameterCombinations + + version + + INIntentParameterCombinationSubtitle + Downloads a specific Xcode version + INIntentParameterCombinationSubtitleID + Jm4PtV + INIntentParameterCombinationSupportsBackgroundExecution + + INIntentParameterCombinationTitle + Download Xcode ${version} + INIntentParameterCombinationTitleID + hxK8St + + + INIntentParameters + + + INIntentParameterConfigurable + + INIntentParameterCustomDisambiguation + + INIntentParameterDisplayName + Version + INIntentParameterDisplayNameID + xX1Nlk + INIntentParameterDisplayPriority + 1 + INIntentParameterName + version + INIntentParameterObjectType + XcodeVersion + INIntentParameterObjectTypeNamespace + DDibcP + INIntentParameterPromptDialogs + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogFormatString + Xcode version + INIntentParameterPromptDialogFormatStringID + QtXNi5 + INIntentParameterPromptDialogType + Configuration + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogFormatString + What version would you like to download? + INIntentParameterPromptDialogFormatStringID + GMl6KP + INIntentParameterPromptDialogType + Primary + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogFormatString + There are ${count} options matching ‘${version}’. + INIntentParameterPromptDialogFormatStringID + fShjJB + INIntentParameterPromptDialogType + DisambiguationIntroduction + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogFormatString + Just to confirm, you wanted ‘${version}’? + INIntentParameterPromptDialogFormatStringID + oWUTBx + INIntentParameterPromptDialogType + Confirmation + + + INIntentParameterSupportsDynamicEnumeration + + INIntentParameterSupportsResolution + + INIntentParameterSupportsSearch + + INIntentParameterTag + 4 + INIntentParameterType + Object + INIntentParameterUnsupportedReasons + + + INIntentParameterUnsupportedReasonCode + invalidVersion + INIntentParameterUnsupportedReasonCustom + + INIntentParameterUnsupportedReasonFormatString + Could not find the Xcode version ${version} + INIntentParameterUnsupportedReasonFormatStringID + u1xTKA + + + + + INIntentResponse + + INIntentResponseCodes + + + INIntentResponseCodeConciseFormatString + Xcode ${versionString} is downloading. Please be patient. + INIntentResponseCodeConciseFormatStringID + TOpF4C + INIntentResponseCodeFormatString + Xcode ${versionString} is downloading. Please be patient. + INIntentResponseCodeFormatStringID + pZhmmj + INIntentResponseCodeName + success + INIntentResponseCodeSuccess + + + + INIntentResponseCodeName + failure + + + INIntentResponseLastParameterTag + 2 + INIntentResponseParameters + + + INIntentResponseParameterDisplayName + Version String + INIntentResponseParameterDisplayNameID + 8kV4Bo + INIntentResponseParameterDisplayPriority + 1 + INIntentResponseParameterName + versionString + INIntentResponseParameterTag + 2 + INIntentResponseParameterType + String + + + + INIntentTitle + Download Xcode Version + INIntentTitleID + 9PPOeK + INIntentType + Custom + INIntentVerb + Download + + + INTypes + + + INTypeDisplayName + Xcode Version + INTypeDisplayNameID + eCDGVR + INTypeLastPropertyTag + 99 + INTypeName + XcodeVersion + INTypeProperties + + + INTypePropertyDefault + + INTypePropertyDisplayPriority + 1 + INTypePropertyName + identifier + INTypePropertyTag + 1 + INTypePropertyType + String + + + INTypePropertyDefault + + INTypePropertyDisplayPriority + 2 + INTypePropertyName + displayString + INTypePropertyTag + 2 + INTypePropertyType + String + + + INTypePropertyDefault + + INTypePropertyDisplayPriority + 3 + INTypePropertyName + pronunciationHint + INTypePropertyTag + 3 + INTypePropertyType + String + + + INTypePropertyDefault + + INTypePropertyDisplayPriority + 4 + INTypePropertyName + alternativeSpeakableMatches + INTypePropertySupportsMultipleValues + + INTypePropertyTag + 4 + INTypePropertyType + SpeakableString + + + + + + diff --git a/Xcodes/Resources/Licenses.rtf b/Xcodes/Resources/Licenses.rtf index 96bf513..b8bf725 100644 --- a/Xcodes/Resources/Licenses.rtf +++ b/Xcodes/Resources/Licenses.rtf @@ -1,4 +1,4 @@ -{\rtf1\ansi\ansicpg1252\cocoartf2580 +{\rtf1\ansi\ansicpg1252\cocoartf2636 \cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fnil\fcharset0 .SFNS-Regular;} {\colortbl;\red255\green255\blue255;} {\*\expandedcolortbl;;} diff --git a/Xcodes/XcodesApp.swift b/Xcodes/XcodesApp.swift index 76f5186..0e045f8 100644 --- a/Xcodes/XcodesApp.swift +++ b/Xcodes/XcodesApp.swift @@ -1,6 +1,7 @@ import AppKit import Sparkle import SwiftUI +import Intents @main struct XcodesApp: App { @@ -120,4 +121,58 @@ class AppDelegate: NSObject, NSApplicationDelegate { // Initialize manually SUUpdater.shared() } + + func application(_ application: NSApplication, handlerFor intent: INIntent) -> Any? { + if intent is DownloadXcodeVersionIntent { + return IntentHandler() + } + return nil + } +} + +class IntentHandler: NSObject, DownloadXcodeVersionIntentHandling { + var appState: AppState = AppState() + + func provideVersionOptionsCollection(for intent: DownloadXcodeVersionIntent, searchTerm: String?, with completion: @escaping (INObjectCollection?, Error?) -> Void) { + guard let searchTerm = searchTerm else { + return + } + + let xcodes = appState.allXcodes.filter { $0.description.contains(searchTerm) } + let versions: [XcodeVersion] = xcodes.map { XcodeVersion(identifier: $0.id.appleDescription, display: $0.description)} + completion(INObjectCollection(items: versions), nil) + } + + // check the version parameter + func resolveVersion(for intent: DownloadXcodeVersionIntent, with completion: @escaping (DownloadXcodeVersionVersionResolutionResult) -> Void) { + guard let version = intent.version else { + return completion(.needsValue()) + } + + return completion(.success(with: version)) + } + + func handle(intent: DownloadXcodeVersionIntent, completion: @escaping (DownloadXcodeVersionIntentResponse) -> Void) { + // do actual downloading + + + let response = DownloadXcodeVersionIntentResponse(code: .success, userActivity: nil) + response.versionString = intent.version?.description + completion(response) + } + + + + +// func provideVersionOptionsCollection(for intent: DownloadXcodeVersionIntent, searchTerm: String?, with completion: @escaping (INObjectCollection?, Error?) -> Void) { +// guard let searchTerm = searchTerm else { +// return +// } +// +// let xcodes = appState.allXcodes.filter { $0.description.contains(searchTerm) } +// let versions: [NSString] = xcodes.map { $0.version.descriptionWithoutBuildMetadata } +// let xcodeVersions = INObjectCollection(items: xcodes) + +// } + }