From b313f37170620718fa91a3c5a6cd21a9a2e6e812 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sat, 2 Oct 2021 10:53:05 -0400 Subject: [PATCH] Add all the intents --- Gemini-iOS/Info.plist | 6 + Gemini-iOS/Intents.intentdefinition | 1058 ++++++++++++++++- Gemini-iOS/Intents/OpenURLIntentHandler.swift | 2 - Gemini-iOS/{ => Intents}/UserActivities.swift | 2 +- Gemini.xcodeproj/project.pbxproj | 232 +++- .../xcschemes/GeminiIntents.xcscheme | 95 ++ .../xcschemes/xcschememanagement.plist | 10 + .../GemtextToHTMLIntentHandler.swift | 30 + .../GemtextToMarkdownIntentHandler.swift | 28 + GeminiIntents/GetBodyIntentHandler.swift | 22 + GeminiIntents/GetMetaIntentHandler.swift | 22 + GeminiIntents/GetStatusIntentHandler.swift | 22 + GeminiIntents/Info.plist | 30 + GeminiIntents/IntentHandler.swift | 41 + GeminiIntents/MakeRequestIntentHandler.swift | 77 ++ 15 files changed, 1645 insertions(+), 32 deletions(-) rename Gemini-iOS/{ => Intents}/UserActivities.swift (94%) create mode 100644 Gemini.xcodeproj/xcshareddata/xcschemes/GeminiIntents.xcscheme create mode 100644 GeminiIntents/GemtextToHTMLIntentHandler.swift create mode 100644 GeminiIntents/GemtextToMarkdownIntentHandler.swift create mode 100644 GeminiIntents/GetBodyIntentHandler.swift create mode 100644 GeminiIntents/GetMetaIntentHandler.swift create mode 100644 GeminiIntents/GetStatusIntentHandler.swift create mode 100644 GeminiIntents/Info.plist create mode 100644 GeminiIntents/IntentHandler.swift create mode 100644 GeminiIntents/MakeRequestIntentHandler.swift diff --git a/Gemini-iOS/Info.plist b/Gemini-iOS/Info.plist index 24a1a82..8945ee1 100644 --- a/Gemini-iOS/Info.plist +++ b/Gemini-iOS/Info.plist @@ -42,6 +42,12 @@ NSUserActivityTypes $(PRODUCE_BUNDLE_IDENTIFIER).activity.browse + GemtextToHTMLIntent + GemtextToMarkdownIntent + GetBodyIntent + GetMetaIntent + GetStatusIntent + MakeRequestIntent OpenURLIntent UIApplicationSceneManifest diff --git a/Gemini-iOS/Intents.intentdefinition b/Gemini-iOS/Intents.intentdefinition index 318be23..f3d17e0 100644 --- a/Gemini-iOS/Intents.intentdefinition +++ b/Gemini-iOS/Intents.intentdefinition @@ -3,7 +3,181 @@ INEnums - + + + INEnumDisplayName + Response Status + INEnumDisplayNameID + 5XudQc + INEnumGeneratesHeader + + INEnumName + ResponseStatus + INEnumType + Regular + INEnumValues + + + INEnumValueDisplayName + unknown + INEnumValueDisplayNameID + MGn9ki + INEnumValueName + unknown + + + INEnumValueDisplayName + input + INEnumValueDisplayNameID + uZg9j3 + INEnumValueIndex + 10 + INEnumValueName + input + + + INEnumValueDisplayName + sensitive input + INEnumValueDisplayNameID + grLfxN + INEnumValueIndex + 11 + INEnumValueName + sensitiveInput + + + INEnumValueDisplayName + success + INEnumValueDisplayNameID + TyAqx0 + INEnumValueIndex + 20 + INEnumValueName + success + + + INEnumValueDisplayName + temporary redirect + INEnumValueDisplayNameID + D9mvCJ + INEnumValueIndex + 30 + INEnumValueName + temporaryRedirect + + + INEnumValueDisplayName + permanent redirect + INEnumValueDisplayNameID + EtneD0 + INEnumValueIndex + 31 + INEnumValueName + permanentRedirect + + + INEnumValueDisplayName + temporary failure + INEnumValueDisplayNameID + sW23DU + INEnumValueIndex + 40 + INEnumValueName + temporaryFailure + + + INEnumValueDisplayName + server unavailable + INEnumValueDisplayNameID + ulF8d2 + INEnumValueIndex + 41 + INEnumValueName + serverUnavailable + + + INEnumValueDisplayName + cgi error + INEnumValueDisplayNameID + EDJ826 + INEnumValueIndex + 42 + INEnumValueName + cgiError + + + INEnumValueDisplayName + proxy error + INEnumValueDisplayNameID + bQiy99 + INEnumValueIndex + 43 + INEnumValueName + proxyError + + + INEnumValueDisplayName + slow down + INEnumValueDisplayNameID + YrE5Xr + INEnumValueIndex + 44 + INEnumValueName + slowDown + + + INEnumValueDisplayName + permanent failure + INEnumValueDisplayNameID + KqG52J + INEnumValueIndex + 50 + INEnumValueName + permanentFailure + + + INEnumValueDisplayName + not found + INEnumValueDisplayNameID + R2IcVQ + INEnumValueIndex + 51 + INEnumValueName + notFound + + + INEnumValueDisplayName + gone + INEnumValueDisplayNameID + yfDnto + INEnumValueIndex + 52 + INEnumValueName + gone + + + INEnumValueDisplayName + proxy request refused + INEnumValueDisplayNameID + dzIhaK + INEnumValueIndex + 53 + INEnumValueName + proxyRequestRefused + + + INEnumValueDisplayName + bad request + INEnumValueDisplayNameID + B1KiSt + INEnumValueIndex + 59 + INEnumValueName + badRequest + + + + INIntentDefinitionModelVersion 1.2 INIntentDefinitionNamespace @@ -25,6 +199,8 @@ Open a Gemini link in Rocketeer. INIntentDescriptionID q39SFr + INIntentIneligibleForSuggestions + INIntentInput url INIntentLastParameterTag @@ -45,20 +221,6 @@ INIntentName OpenURL - INIntentParameterCombinations - - url - - INIntentParameterCombinationIsLinked - - INIntentParameterCombinationSupportsBackgroundExecution - - INIntentParameterCombinationTitle - Open ${url} - INIntentParameterCombinationTitleID - vxeXI3 - - INIntentParameters @@ -124,8 +286,872 @@ INIntentVerb Open + + INIntentCategory + request + INIntentConfigurable + + INIntentDescription + Request a Gemini response for a given URL in the background. + INIntentDescriptionID + Y56Y37 + INIntentIneligibleForSuggestions + + INIntentInput + url + INIntentLastParameterTag + 4 + INIntentManagedParameterCombinations + + url,followRedirects + + INIntentParameterCombinationSupportsBackgroundExecution + + INIntentParameterCombinationTitle + Request ${url} + INIntentParameterCombinationTitleID + lPo8jb + INIntentParameterCombinationUpdatesLinked + + + + INIntentName + MakeRequest + INIntentParameters + + + INIntentParameterConfigurable + + INIntentParameterDisplayName + URL + INIntentParameterDisplayNameID + 1aIUuX + INIntentParameterDisplayPriority + 1 + INIntentParameterName + url + INIntentParameterPromptDialogs + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogType + Configuration + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogFormatString + What URL would you like to request? + INIntentParameterPromptDialogFormatStringID + 5DS84Z + INIntentParameterPromptDialogType + Primary + + + INIntentParameterSupportsResolution + + INIntentParameterTag + 2 + INIntentParameterType + URL + + + INIntentParameterConfigurable + + INIntentParameterDisplayName + Follow Redirects + INIntentParameterDisplayNameID + Vovvey + INIntentParameterDisplayPriority + 2 + INIntentParameterMetadata + + INIntentParameterMetadataDefaultValue + + INIntentParameterMetadataFalseDisplayName + false + INIntentParameterMetadataFalseDisplayNameID + zn096w + INIntentParameterMetadataTrueDisplayName + true + INIntentParameterMetadataTrueDisplayNameID + pqB3Ax + + INIntentParameterName + followRedirects + INIntentParameterPromptDialogs + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogType + Configuration + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogType + Primary + + + INIntentParameterTag + 4 + INIntentParameterType + Boolean + + + INIntentResponse + + INIntentResponseCodes + + + INIntentResponseCodeName + success + INIntentResponseCodeSuccess + + + + INIntentResponseCodeName + failure + + + INIntentResponseLastParameterTag + 14 + INIntentResponseOutput + response + INIntentResponseParameters + + + INIntentResponseParameterDisplayName + Response + INIntentResponseParameterDisplayNameID + k3nbZY + INIntentResponseParameterDisplayPriority + 1 + INIntentResponseParameterName + response + INIntentResponseParameterObjectType + Response + INIntentResponseParameterObjectTypeNamespace + YzEWx7 + INIntentResponseParameterTag + 14 + INIntentResponseParameterType + Object + + + + INIntentTitle + Make Request + INIntentTitleID + xGCpJ2 + INIntentType + Custom + INIntentVerb + Request + + + INIntentCategory + download + INIntentConfigurable + + INIntentDescription + Get the body text from a Gemini response. + INIntentDescriptionID + oi57lk + INIntentIneligibleForSuggestions + + INIntentInput + response + INIntentLastParameterTag + 4 + INIntentManagedParameterCombinations + + response + + INIntentParameterCombinationSupportsBackgroundExecution + + INIntentParameterCombinationTitle + Get ${response} body + INIntentParameterCombinationTitleID + QUFiH4 + INIntentParameterCombinationUpdatesLinked + + + + INIntentName + GetBody + INIntentParameters + + + INIntentParameterConfigurable + + INIntentParameterDisplayName + Response + INIntentParameterDisplayNameID + Cv6lVy + INIntentParameterDisplayPriority + 1 + INIntentParameterName + response + INIntentParameterObjectType + Response + INIntentParameterObjectTypeNamespace + YzEWx7 + INIntentParameterPromptDialogs + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogType + Configuration + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogType + Primary + + + INIntentParameterTag + 2 + INIntentParameterType + Object + + + INIntentResponse + + INIntentResponseCodes + + + INIntentResponseCodeName + success + INIntentResponseCodeSuccess + + + + INIntentResponseCodeName + failure + + + INIntentResponseLastParameterTag + 1 + INIntentResponseOutput + text + INIntentResponseParameters + + + INIntentResponseParameterDisplayName + Text + INIntentResponseParameterDisplayNameID + 0L7xBg + INIntentResponseParameterDisplayPriority + 1 + INIntentResponseParameterName + text + INIntentResponseParameterTag + 1 + INIntentResponseParameterType + String + + + + INIntentTitle + Get Response Body + INIntentTitleID + RpJLkx + INIntentType + Custom + INIntentVerb + Get + + + INIntentCategory + generic + INIntentConfigurable + + INIntentDescription + Get the status code from a Gemini response. + INIntentDescriptionID + 5D3a4e + INIntentIneligibleForSuggestions + + INIntentInput + response + INIntentLastParameterTag + 2 + INIntentManagedParameterCombinations + + response + + INIntentParameterCombinationSupportsBackgroundExecution + + INIntentParameterCombinationTitle + Get ${response} status + INIntentParameterCombinationTitleID + e4OgxM + INIntentParameterCombinationUpdatesLinked + + + + INIntentName + GetStatus + INIntentParameters + + + INIntentParameterConfigurable + + INIntentParameterDisplayName + Response + INIntentParameterDisplayNameID + 8bo9mE + INIntentParameterDisplayPriority + 1 + INIntentParameterName + response + INIntentParameterObjectType + Response + INIntentParameterObjectTypeNamespace + YzEWx7 + INIntentParameterPromptDialogs + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogType + Configuration + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogType + Primary + + + INIntentParameterTag + 2 + INIntentParameterType + Object + + + INIntentResponse + + INIntentResponseCodes + + + INIntentResponseCodeName + success + INIntentResponseCodeSuccess + + + + INIntentResponseCodeName + failure + + + INIntentResponseLastParameterTag + 2 + INIntentResponseOutput + status + INIntentResponseParameters + + + INIntentResponseParameterDisplayName + Status + INIntentResponseParameterDisplayNameID + Qlg67m + INIntentResponseParameterDisplayPriority + 1 + INIntentResponseParameterName + status + INIntentResponseParameterTag + 2 + INIntentResponseParameterType + Integer + + + + INIntentTitle + Get Response Status + INIntentTitleID + S6c5Js + INIntentType + Custom + INIntentVerb + Do + + + INIntentCategory + generic + INIntentConfigurable + + INIntentDescription + Get the meta string from a Gemini response. + INIntentDescriptionID + Pczzvi + INIntentIneligibleForSuggestions + + INIntentInput + response + INIntentLastParameterTag + 2 + INIntentManagedParameterCombinations + + response + + INIntentParameterCombinationSupportsBackgroundExecution + + INIntentParameterCombinationTitle + Get ${response} meta + INIntentParameterCombinationTitleID + sjaZjZ + INIntentParameterCombinationUpdatesLinked + + + + INIntentName + GetMeta + INIntentParameters + + + INIntentParameterConfigurable + + INIntentParameterDisplayName + Response + INIntentParameterDisplayNameID + wGjeRv + INIntentParameterDisplayPriority + 1 + INIntentParameterName + response + INIntentParameterObjectType + Response + INIntentParameterObjectTypeNamespace + YzEWx7 + INIntentParameterPromptDialogs + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogType + Configuration + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogType + Primary + + + INIntentParameterTag + 2 + INIntentParameterType + Object + + + INIntentResponse + + INIntentResponseCodes + + + INIntentResponseCodeName + success + INIntentResponseCodeSuccess + + + + INIntentResponseCodeName + failure + + + INIntentResponseLastParameterTag + 1 + INIntentResponseOutput + meta + INIntentResponseParameters + + + INIntentResponseParameterDisplayName + Meta + INIntentResponseParameterDisplayNameID + bSYEER + INIntentResponseParameterDisplayPriority + 1 + INIntentResponseParameterName + meta + INIntentResponseParameterTag + 1 + INIntentResponseParameterType + String + + + + INIntentTitle + Get Response Meta + INIntentTitleID + GMDdff + INIntentType + Custom + INIntentVerb + Do + + + INIntentCategory + generic + INIntentConfigurable + + INIntentDescription + Converts the Gemtext of the supplied Gemini response to an HTML string. + INIntentDescriptionID + Vm3f2J + INIntentIneligibleForSuggestions + + INIntentInput + response + INIntentLastParameterTag + 2 + INIntentManagedParameterCombinations + + response + + INIntentParameterCombinationSupportsBackgroundExecution + + INIntentParameterCombinationTitle + Convert ${response} to HTML + INIntentParameterCombinationTitleID + 7GZS31 + INIntentParameterCombinationUpdatesLinked + + + + INIntentName + GemtextToHTML + INIntentParameters + + + INIntentParameterConfigurable + + INIntentParameterDisplayName + Response + INIntentParameterDisplayNameID + Z7rpmj + INIntentParameterDisplayPriority + 1 + INIntentParameterName + response + INIntentParameterObjectType + Response + INIntentParameterObjectTypeNamespace + YzEWx7 + INIntentParameterPromptDialogs + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogType + Configuration + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogType + Primary + + + INIntentParameterTag + 2 + INIntentParameterType + Object + + + INIntentResponse + + INIntentResponseCodes + + + INIntentResponseCodeName + success + INIntentResponseCodeSuccess + + + + INIntentResponseCodeName + failure + + + INIntentResponseLastParameterTag + 2 + INIntentResponseOutput + html + INIntentResponseParameters + + + INIntentResponseParameterDisplayName + HTML + INIntentResponseParameterDisplayNameID + gfCuJ6 + INIntentResponseParameterDisplayPriority + 1 + INIntentResponseParameterName + html + INIntentResponseParameterTag + 2 + INIntentResponseParameterType + File + + + + INIntentTitle + Convert Gemtext To HTML + INIntentTitleID + surT4F + INIntentType + Custom + INIntentVerb + Do + + + INIntentCategory + generic + INIntentConfigurable + + INIntentDescription + Converts the Gemtext of the supplied Gemini response to a Markdown string. + INIntentDescriptionID + ZbTDiF + INIntentIneligibleForSuggestions + + INIntentInput + response + INIntentLastParameterTag + 2 + INIntentManagedParameterCombinations + + response + + INIntentParameterCombinationSupportsBackgroundExecution + + INIntentParameterCombinationTitle + Convert ${response} to Markdown + INIntentParameterCombinationTitleID + bqC2wG + INIntentParameterCombinationUpdatesLinked + + + + INIntentName + GemtextToMarkdown + INIntentParameters + + + INIntentParameterConfigurable + + INIntentParameterDisplayName + Response + INIntentParameterDisplayNameID + KBJBgm + INIntentParameterDisplayPriority + 1 + INIntentParameterName + response + INIntentParameterObjectType + Response + INIntentParameterObjectTypeNamespace + YzEWx7 + INIntentParameterPromptDialogs + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogType + Configuration + + + INIntentParameterPromptDialogCustom + + INIntentParameterPromptDialogType + Primary + + + INIntentParameterTag + 2 + INIntentParameterType + Object + + + INIntentResponse + + INIntentResponseCodes + + + INIntentResponseCodeName + success + INIntentResponseCodeSuccess + + + + INIntentResponseCodeName + failure + + + INIntentResponseLastParameterTag + 2 + INIntentResponseOutput + markdown + INIntentResponseParameters + + + INIntentResponseParameterDisplayName + Markdown + INIntentResponseParameterDisplayNameID + 8GaKeU + INIntentResponseParameterDisplayPriority + 1 + INIntentResponseParameterName + markdown + INIntentResponseParameterTag + 2 + INIntentResponseParameterType + File + + + + INIntentTitle + Convert Gemtext To Markdown + INIntentTitleID + Fs7C6t + INIntentType + Custom + INIntentVerb + Do + INTypes - + + + INTypeDisplayName + Response + INTypeDisplayNameID + KU93pL + INTypeLastPropertyTag + 105 + INTypeName + Response + INTypeProperties + + + INTypePropertyDefault + + INTypePropertyDisplayPriority + 1 + INTypePropertyName + identifier + INTypePropertyTag + 1 + INTypePropertyType + String + + + INTypePropertyDefault + + INTypePropertyDisplayPriority + 2 + INTypePropertyName + displayString + INTypePropertyTag + 2 + INTypePropertyType + String + + + INTypePropertyDisplayName + URL + INTypePropertyDisplayNameID + k7uE8P + INTypePropertyDisplayPriority + 3 + INTypePropertyName + url + INTypePropertyTag + 105 + INTypePropertyType + URL + + + INTypePropertyDefault + + INTypePropertyDisplayPriority + 4 + INTypePropertyName + pronunciationHint + INTypePropertyTag + 3 + INTypePropertyType + String + + + INTypePropertyDefault + + INTypePropertyDisplayPriority + 5 + INTypePropertyName + alternativeSpeakableMatches + INTypePropertySupportsMultipleValues + + INTypePropertyTag + 4 + INTypePropertyType + SpeakableString + + + INTypePropertyDisplayName + Body + INTypePropertyDisplayNameID + 2po3HW + INTypePropertyDisplayPriority + 6 + INTypePropertyName + body + INTypePropertyTag + 100 + INTypePropertyType + String + + + INTypePropertyDisplayName + Status + INTypePropertyDisplayNameID + T1CQcb + INTypePropertyDisplayPriority + 7 + INTypePropertyEnumType + ResponseStatus + INTypePropertyEnumTypeNamespace + YzEWx7 + INTypePropertyName + status + INTypePropertyTag + 102 + INTypePropertyType + Integer + + + INTypePropertyDisplayName + Meta + INTypePropertyDisplayNameID + I0a3Ep + INTypePropertyDisplayPriority + 8 + INTypePropertyName + meta + INTypePropertyTag + 103 + INTypePropertyType + String + + + + diff --git a/Gemini-iOS/Intents/OpenURLIntentHandler.swift b/Gemini-iOS/Intents/OpenURLIntentHandler.swift index 7bdfe5f..f2680d8 100644 --- a/Gemini-iOS/Intents/OpenURLIntentHandler.swift +++ b/Gemini-iOS/Intents/OpenURLIntentHandler.swift @@ -6,7 +6,6 @@ // import Intents -import UIKit class OpenURLIntentHandler: NSObject, OpenURLIntentHandling { @@ -20,7 +19,6 @@ class OpenURLIntentHandler: NSObject, OpenURLIntentHandling { } func handle(intent: OpenURLIntent, completion: @escaping (OpenURLIntentResponse) -> Void) { - print("handling intent") guard let url = intent.url, url.scheme?.lowercased() == "gemini" else { completion(OpenURLIntentResponse(code: .failure, userActivity: nil)) diff --git a/Gemini-iOS/UserActivities.swift b/Gemini-iOS/Intents/UserActivities.swift similarity index 94% rename from Gemini-iOS/UserActivities.swift rename to Gemini-iOS/Intents/UserActivities.swift index 5c59e9e..017a880 100644 --- a/Gemini-iOS/UserActivities.swift +++ b/Gemini-iOS/Intents/UserActivities.swift @@ -8,7 +8,7 @@ import Foundation import BrowserCore -private let type = "\(Bundle.main.bundleIdentifier!).activity.browse" +private let type = "space.vaccor.Gemini.activity.browse" private let encoder = PropertyListEncoder() private let decoder = PropertyListDecoder() diff --git a/Gemini.xcodeproj/project.pbxproj b/Gemini.xcodeproj/project.pbxproj index 386e52a..db2e0fa 100644 --- a/Gemini.xcodeproj/project.pbxproj +++ b/Gemini.xcodeproj/project.pbxproj @@ -43,18 +43,33 @@ D664673624BD07F700B0B741 /* RenderingBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = D664673524BD07F700B0B741 /* RenderingBlock.swift */; }; D664673824BD086F00B0B741 /* RenderingBlockView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D664673724BD086F00B0B741 /* RenderingBlockView.swift */; }; D664673A24BD0B8E00B0B741 /* Fonts.swift in Sources */ = {isa = PBXBuildFile; fileRef = D664673924BD0B8E00B0B741 /* Fonts.swift */; }; - D688F586258AC738003A0A73 /* GeminiHTMLRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D688F585258AC738003A0A73 /* GeminiHTMLRenderer.swift */; }; - D688F590258AC814003A0A73 /* HTMLEntities in Frameworks */ = {isa = PBXBuildFile; productRef = D688F58F258AC814003A0A73 /* HTMLEntities */; }; D688F599258ACAAE003A0A73 /* BrowserWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D688F598258ACAAE003A0A73 /* BrowserWebViewController.swift */; }; D688F5FF258ACE6B003A0A73 /* browser.css in Resources */ = {isa = PBXBuildFile; fileRef = D688F5FE258ACE6B003A0A73 /* browser.css */; }; D688F633258B09BB003A0A73 /* TrackpadScrollGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D688F632258B09BB003A0A73 /* TrackpadScrollGestureRecognizer.swift */; }; D688F64A258C17F3003A0A73 /* SymbolCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D688F649258C17F3003A0A73 /* SymbolCache.swift */; }; D688F65A258C2256003A0A73 /* BrowserNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D688F659258C2256003A0A73 /* BrowserNavigationController.swift */; }; D688F663258C2479003A0A73 /* UIViewController+Children.swift in Sources */ = {isa = PBXBuildFile; fileRef = D688F662258C2479003A0A73 /* UIViewController+Children.swift */; }; - D68C1E002703EA13002D642B /* UserActivities.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68C1DFF2703EA13002D642B /* UserActivities.swift */; }; D68C1E1927055E09002D642B /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = D68C1E1827055E09002D642B /* Intents.intentdefinition */; }; - D68C1E1C27055EB0002D642B /* OpenURLIntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68C1E1B27055EB0002D642B /* OpenURLIntentHandler.swift */; }; D68C1E1E270605A7002D642B /* BrowserHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68C1E1D270605A7002D642B /* BrowserHelper.swift */; }; + D68C1E25270614F9002D642B /* Intents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D68C1E24270614F9002D642B /* Intents.framework */; platformFilter = maccatalyst; }; + D68C1E28270614F9002D642B /* IntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68C1E27270614F9002D642B /* IntentHandler.swift */; }; + D68C1E2C270614F9002D642B /* GeminiIntents.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = D68C1E23270614F9002D642B /* GeminiIntents.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + D68C1E312706150E002D642B /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = D68C1E1827055E09002D642B /* Intents.intentdefinition */; }; + D68C1E3227061557002D642B /* OpenURLIntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68C1E1B27055EB0002D642B /* OpenURLIntentHandler.swift */; }; + D68C1E3327061568002D642B /* UserActivities.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68C1DFF2703EA13002D642B /* UserActivities.swift */; }; + D68C1E34270615D3002D642B /* OpenURLIntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68C1E1B27055EB0002D642B /* OpenURLIntentHandler.swift */; }; + D68C1E35270615D3002D642B /* UserActivities.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68C1DFF2703EA13002D642B /* UserActivities.swift */; }; + D68C1E372706215A002D642B /* MakeRequestIntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68C1E362706215A002D642B /* MakeRequestIntentHandler.swift */; }; + D68C1E392707A1E5002D642B /* GetBodyIntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68C1E382707A1E5002D642B /* GetBodyIntentHandler.swift */; }; + D68C1E3B2707BF25002D642B /* GetStatusIntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68C1E3A2707BF25002D642B /* GetStatusIntentHandler.swift */; }; + D68C1E3D2707C002002D642B /* GetMetaIntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68C1E3C2707C002002D642B /* GetMetaIntentHandler.swift */; }; + D68C1E3F2707C3B2002D642B /* GemtextToHTMLIntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68C1E3E2707C3B2002D642B /* GemtextToHTMLIntentHandler.swift */; }; + D68C1E412707CB03002D642B /* GemtextToMarkdownIntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68C1E402707CB03002D642B /* GemtextToMarkdownIntentHandler.swift */; }; + D68C1E482708A958002D642B /* GeminiMarkdownRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68C1E422707CB69002D642B /* GeminiMarkdownRenderer.swift */; }; + D68C1E492708A958002D642B /* GeminiHTMLRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D688F585258AC738003A0A73 /* GeminiHTMLRenderer.swift */; }; + D68C1E4A2708A95D002D642B /* GeminiMarkdownRendererTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68C1E462707D109002D642B /* GeminiMarkdownRendererTests.swift */; }; + D68C1E4B2708A95D002D642B /* GeminiHTMLRendererTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68C1E442707CCDB002D642B /* GeminiHTMLRendererTests.swift */; }; + D68C1E4D2708A981002D642B /* HTMLEntities in Frameworks */ = {isa = PBXBuildFile; productRef = D68C1E4C2708A981002D642B /* HTMLEntities */; }; D691A64E25217C6F00348C4B /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = D691A64D25217C6F00348C4B /* Preferences.swift */; }; D691A66725217FD800348C4B /* PreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D691A66625217FD800348C4B /* PreferencesView.swift */; }; D69F00AC24BE9DD300E37622 /* GeminiDataTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69F00AB24BE9DD300E37622 /* GeminiDataTask.swift */; }; @@ -211,6 +226,13 @@ remoteGlobalIDString = D62664A724BBF26A00DF9B88; remoteInfo = GeminiFormat; }; + D68C1E2A270614F9002D642B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D626645324BBF1C200DF9B88 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D68C1E22270614F9002D642B; + remoteInfo = GeminiIntents; + }; D6E152DA24C0007200FDF9D3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D626645324BBF1C200DF9B88 /* Project object */; @@ -259,6 +281,17 @@ name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; + D68C1E30270614F9002D642B /* Embed App Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + D68C1E2C270614F9002D642B /* GeminiIntents.appex in Embed App Extensions */, + ); + name = "Embed App Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; D6E152C224BFFE2500FDF9D3 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -329,6 +362,19 @@ D68C1E1827055E09002D642B /* Intents.intentdefinition */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; path = Intents.intentdefinition; sourceTree = ""; }; D68C1E1B27055EB0002D642B /* OpenURLIntentHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenURLIntentHandler.swift; sourceTree = ""; }; D68C1E1D270605A7002D642B /* BrowserHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserHelper.swift; sourceTree = ""; }; + D68C1E23270614F9002D642B /* GeminiIntents.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = GeminiIntents.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + D68C1E24270614F9002D642B /* Intents.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Intents.framework; path = System/Library/Frameworks/Intents.framework; sourceTree = SDKROOT; }; + D68C1E27270614F9002D642B /* IntentHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntentHandler.swift; sourceTree = ""; }; + D68C1E29270614F9002D642B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D68C1E362706215A002D642B /* MakeRequestIntentHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MakeRequestIntentHandler.swift; sourceTree = ""; }; + D68C1E382707A1E5002D642B /* GetBodyIntentHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetBodyIntentHandler.swift; sourceTree = ""; }; + D68C1E3A2707BF25002D642B /* GetStatusIntentHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetStatusIntentHandler.swift; sourceTree = ""; }; + D68C1E3C2707C002002D642B /* GetMetaIntentHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetMetaIntentHandler.swift; sourceTree = ""; }; + D68C1E3E2707C3B2002D642B /* GemtextToHTMLIntentHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GemtextToHTMLIntentHandler.swift; sourceTree = ""; }; + D68C1E402707CB03002D642B /* GemtextToMarkdownIntentHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GemtextToMarkdownIntentHandler.swift; sourceTree = ""; }; + D68C1E422707CB69002D642B /* GeminiMarkdownRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeminiMarkdownRenderer.swift; sourceTree = ""; }; + D68C1E442707CCDB002D642B /* GeminiHTMLRendererTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeminiHTMLRendererTests.swift; sourceTree = ""; }; + D68C1E462707D109002D642B /* GeminiMarkdownRendererTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeminiMarkdownRendererTests.swift; sourceTree = ""; }; D691A64D25217C6F00348C4B /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = ""; }; D691A66625217FD800348C4B /* PreferencesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesView.swift; sourceTree = ""; }; D69F00AB24BE9DD300E37622 /* GeminiDataTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeminiDataTask.swift; sourceTree = ""; }; @@ -390,6 +436,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + D68C1E4D2708A981002D642B /* HTMLEntities in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -405,7 +452,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - D688F590258AC814003A0A73 /* HTMLEntities in Frameworks */, D62664F024BC0D7700DF9B88 /* GeminiFormat.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -418,6 +464,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + D68C1E20270614F9002D642B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D68C1E25270614F9002D642B /* Intents.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; D6E1529F24BFFDF500FDF9D3 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -452,6 +506,7 @@ children = ( D626645D24BBF1C200DF9B88 /* Gemini */, D6E152A324BFFDF500FDF9D3 /* Gemini-iOS */, + D68C1E26270614F9002D642B /* GeminiIntents */, D6E152D124C0007200FDF9D3 /* BrowserCore */, D6E152DE24C0007200FDF9D3 /* BrowserCoreTests */, D626647824BBF22E00DF9B88 /* GeminiProtocol */, @@ -478,6 +533,7 @@ D6E152A224BFFDF500FDF9D3 /* Gemini-iOS.app */, D6E152D024C0007200FDF9D3 /* BrowserCore.framework */, D6E152D824C0007200FDF9D3 /* BrowserCoreTests.xctest */, + D68C1E23270614F9002D642B /* GeminiIntents.appex */, ); name = Products; sourceTree = ""; @@ -539,6 +595,8 @@ D62664C724BBF2C600DF9B88 /* Document.swift */, D62664C524BBF27300DF9B88 /* GeminiParser.swift */, D6BC9AC4258F01F6008652BC /* TableOfContents.swift */, + D688F585258AC738003A0A73 /* GeminiHTMLRenderer.swift */, + D68C1E422707CB69002D642B /* GeminiMarkdownRenderer.swift */, ); path = GeminiFormat; sourceTree = ""; @@ -549,6 +607,8 @@ D62664F924BC12BC00DF9B88 /* DocumentTests.swift */, D62664B724BBF26A00DF9B88 /* GeminiParserTests.swift */, D6BC9ACD258F07BC008652BC /* TableOfContentsTests.swift */, + D68C1E442707CCDB002D642B /* GeminiHTMLRendererTests.swift */, + D68C1E462707D109002D642B /* GeminiMarkdownRendererTests.swift */, D62664B924BBF26A00DF9B88 /* Info.plist */, ); path = GeminiFormatTests; @@ -565,7 +625,6 @@ D62664EB24BC0B4D00DF9B88 /* DocumentView.swift */, D664673724BD086F00B0B741 /* RenderingBlockView.swift */, D6DA5782252396030048B65A /* View+Extensions.swift */, - D688F585258AC738003A0A73 /* GeminiHTMLRenderer.swift */, ); path = GeminiRenderer; sourceTree = ""; @@ -582,6 +641,7 @@ D62664EF24BC0D7700DF9B88 /* Frameworks */ = { isa = PBXGroup; children = ( + D68C1E24270614F9002D642B /* Intents.framework */, ); name = Frameworks; sourceTree = ""; @@ -605,11 +665,27 @@ D68C1E1A27055EA0002D642B /* Intents */ = { isa = PBXGroup; children = ( + D68C1DFF2703EA13002D642B /* UserActivities.swift */, D68C1E1B27055EB0002D642B /* OpenURLIntentHandler.swift */, ); path = Intents; sourceTree = ""; }; + D68C1E26270614F9002D642B /* GeminiIntents */ = { + isa = PBXGroup; + children = ( + D68C1E27270614F9002D642B /* IntentHandler.swift */, + D68C1E362706215A002D642B /* MakeRequestIntentHandler.swift */, + D68C1E382707A1E5002D642B /* GetBodyIntentHandler.swift */, + D68C1E3A2707BF25002D642B /* GetStatusIntentHandler.swift */, + D68C1E3C2707C002002D642B /* GetMetaIntentHandler.swift */, + D68C1E3E2707C3B2002D642B /* GemtextToHTMLIntentHandler.swift */, + D68C1E402707CB03002D642B /* GemtextToMarkdownIntentHandler.swift */, + D68C1E29270614F9002D642B /* Info.plist */, + ); + path = GeminiIntents; + sourceTree = ""; + }; D6E152A324BFFDF500FDF9D3 /* Gemini-iOS */ = { isa = PBXGroup; children = ( @@ -628,7 +704,6 @@ D653F40C26799F2F004E32B1 /* HomepagePrefView.swift */, D653F40A267996FF004E32B1 /* ActivityItemSource.swift */, D653F40E2679A0AB004E32B1 /* SetHomepageActivity.swift */, - D68C1DFF2703EA13002D642B /* UserActivities.swift */, D68C1E1A27055EA0002D642B /* Intents */, D688F618258AD231003A0A73 /* Resources */, D6376A6E26DDAF57005AD89C /* Vendor */, @@ -781,6 +856,9 @@ dependencies = ( ); name = GeminiFormat; + packageProductDependencies = ( + D68C1E4C2708A981002D642B /* HTMLEntities */, + ); productName = GeminiFormat; productReference = D62664A824BBF26A00DF9B88 /* GeminiFormat.framework */; productType = "com.apple.product-type.framework"; @@ -821,7 +899,6 @@ ); name = GeminiRenderer; packageProductDependencies = ( - D688F58F258AC814003A0A73 /* HTMLEntities */, ); productName = GeminiRenderer; productReference = D62664CE24BC081B00DF9B88 /* GeminiRenderer.framework */; @@ -846,6 +923,23 @@ productReference = D62664D624BC081B00DF9B88 /* GeminiRendererTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; + D68C1E22270614F9002D642B /* GeminiIntents */ = { + isa = PBXNativeTarget; + buildConfigurationList = D68C1E2D270614F9002D642B /* Build configuration list for PBXNativeTarget "GeminiIntents" */; + buildPhases = ( + D68C1E1F270614F9002D642B /* Sources */, + D68C1E20270614F9002D642B /* Frameworks */, + D68C1E21270614F9002D642B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = GeminiIntents; + productName = GeminiIntents; + productReference = D68C1E23270614F9002D642B /* GeminiIntents.appex */; + productType = "com.apple.product-type.app-extension"; + }; D6E152A124BFFDF500FDF9D3 /* Gemini-iOS */ = { isa = PBXNativeTarget; buildConfigurationList = D6E152B324BFFDF600FDF9D3 /* Build configuration list for PBXNativeTarget "Gemini-iOS" */; @@ -854,6 +948,7 @@ D6E1529F24BFFDF500FDF9D3 /* Frameworks */, D6E152A024BFFDF500FDF9D3 /* Resources */, D6E152C224BFFE2500FDF9D3 /* Embed Frameworks */, + D68C1E30270614F9002D642B /* Embed App Extensions */, ); buildRules = ( ); @@ -862,6 +957,7 @@ D68543FC2522DEF5004C4AE0 /* PBXTargetDependency */, D68543FA2522DEF3004C4AE0 /* PBXTargetDependency */, D68543F82522DEF0004C4AE0 /* PBXTargetDependency */, + D68C1E2B270614F9002D642B /* PBXTargetDependency */, ); name = "Gemini-iOS"; productName = "Gemini-iOS"; @@ -914,7 +1010,7 @@ D626645324BBF1C200DF9B88 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1200; + LastSwiftUpdateCheck = 1300; LastUpgradeCheck = 1220; TargetAttributes = { D626645A24BBF1C200DF9B88 = { @@ -944,6 +1040,9 @@ CreatedOnToolsVersion = 12.0; TestTargetID = D626645A24BBF1C200DF9B88; }; + D68C1E22270614F9002D642B = { + CreatedOnToolsVersion = 13.0; + }; D6E152A124BFFDF500FDF9D3 = { CreatedOnToolsVersion = 12.0; }; @@ -982,6 +1081,7 @@ D62664D524BC081B00DF9B88 /* GeminiRendererTests */, D6E152CF24C0007200FDF9D3 /* BrowserCore */, D6E152D724C0007200FDF9D3 /* BrowserCoreTests */, + D68C1E22270614F9002D642B /* GeminiIntents */, ); }; /* End PBXProject section */ @@ -1040,6 +1140,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + D68C1E21270614F9002D642B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; D6E152A024BFFDF500FDF9D3 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -1106,6 +1213,8 @@ files = ( D62664C824BBF2C600DF9B88 /* Document.swift in Sources */, D62664C624BBF27300DF9B88 /* GeminiParser.swift in Sources */, + D68C1E492708A958002D642B /* GeminiHTMLRenderer.swift in Sources */, + D68C1E482708A958002D642B /* GeminiMarkdownRenderer.swift in Sources */, D6BC9AC5258F01F6008652BC /* TableOfContents.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1116,7 +1225,9 @@ files = ( D62664FA24BC12BC00DF9B88 /* DocumentTests.swift in Sources */, D6BC9ACE258F07BC008652BC /* TableOfContentsTests.swift in Sources */, + D68C1E4A2708A95D002D642B /* GeminiMarkdownRendererTests.swift in Sources */, D62664B824BBF26A00DF9B88 /* GeminiParserTests.swift in Sources */, + D68C1E4B2708A95D002D642B /* GeminiHTMLRendererTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1129,7 +1240,6 @@ D62664EE24BC0BCE00DF9B88 /* MaybeLazyVStack.swift in Sources */, D62664EC24BC0B4D00DF9B88 /* DocumentView.swift in Sources */, D6DA5783252396030048B65A /* View+Extensions.swift in Sources */, - D688F586258AC738003A0A73 /* GeminiHTMLRenderer.swift in Sources */, D664673824BD086F00B0B741 /* RenderingBlockView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1142,6 +1252,23 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + D68C1E1F270614F9002D642B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D68C1E3227061557002D642B /* OpenURLIntentHandler.swift in Sources */, + D68C1E3B2707BF25002D642B /* GetStatusIntentHandler.swift in Sources */, + D68C1E312706150E002D642B /* Intents.intentdefinition in Sources */, + D68C1E392707A1E5002D642B /* GetBodyIntentHandler.swift in Sources */, + D68C1E3D2707C002002D642B /* GetMetaIntentHandler.swift in Sources */, + D68C1E3F2707C3B2002D642B /* GemtextToHTMLIntentHandler.swift in Sources */, + D68C1E28270614F9002D642B /* IntentHandler.swift in Sources */, + D68C1E412707CB03002D642B /* GemtextToMarkdownIntentHandler.swift in Sources */, + D68C1E372706215A002D642B /* MakeRequestIntentHandler.swift in Sources */, + D68C1E3327061568002D642B /* UserActivities.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; D6E1529E24BFFDF500FDF9D3 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -1151,7 +1278,9 @@ D688F633258B09BB003A0A73 /* TrackpadScrollGestureRecognizer.swift in Sources */, D6E152A524BFFDF500FDF9D3 /* AppDelegate.swift in Sources */, D6E152A724BFFDF500FDF9D3 /* SceneDelegate.swift in Sources */, + D68C1E35270615D3002D642B /* UserActivities.swift in Sources */, D6376A7026DDAF65005AD89C /* URIFixup.swift in Sources */, + D68C1E34270615D3002D642B /* OpenURLIntentHandler.swift in Sources */, D653F40B267996FF004E32B1 /* ActivityItemSource.swift in Sources */, D6BC9AB3258E8E13008652BC /* ToolbarView.swift in Sources */, D688F64A258C17F3003A0A73 /* SymbolCache.swift in Sources */, @@ -1161,10 +1290,8 @@ D68C1E1927055E09002D642B /* Intents.intentdefinition in Sources */, D688F663258C2479003A0A73 /* UIViewController+Children.swift in Sources */, D653F40D26799F2F004E32B1 /* HomepagePrefView.swift in Sources */, - D68C1E1C27055EB0002D642B /* OpenURLIntentHandler.swift in Sources */, D691A64E25217C6F00348C4B /* Preferences.swift in Sources */, D6BC9ABC258E9862008652BC /* NavigationBarView.swift in Sources */, - D68C1E002703EA13002D642B /* UserActivities.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1274,6 +1401,11 @@ target = D62664A724BBF26A00DF9B88 /* GeminiFormat */; targetProxy = D685442F2522E10F004C4AE0 /* PBXContainerItemProxy */; }; + D68C1E2B270614F9002D642B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D68C1E22270614F9002D642B /* GeminiIntents */; + targetProxy = D68C1E2A270614F9002D642B /* PBXContainerItemProxy */; + }; D6E152DB24C0007200FDF9D3 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = D6E152CF24C0007200FDF9D3 /* BrowserCore */; @@ -1473,6 +1605,7 @@ D626648F24BBF22E00DF9B88 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; @@ -1506,6 +1639,7 @@ D626649024BBF22E00DF9B88 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; @@ -1578,6 +1712,7 @@ D62664C024BBF26A00DF9B88 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; @@ -1611,6 +1746,7 @@ D62664C124BBF26A00DF9B88 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; @@ -1683,6 +1819,7 @@ D62664E624BC081B00DF9B88 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; @@ -1716,6 +1853,7 @@ D62664E724BC081B00DF9B88 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; @@ -1785,6 +1923,63 @@ }; name = Release; }; + D68C1E2E270614F9002D642B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 10; + DEVELOPMENT_TEAM = V4WK9KR9U2; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = GeminiIntents/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = GeminiIntents; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 13.5; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 2021.1; + PRODUCT_BUNDLE_IDENTIFIER = space.vaccor.Gemini.GeminiIntents; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + D68C1E2F270614F9002D642B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 10; + DEVELOPMENT_TEAM = V4WK9KR9U2; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = GeminiIntents/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = GeminiIntents; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 13.5; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 2021.1; + PRODUCT_BUNDLE_IDENTIFIER = space.vaccor.Gemini.GeminiIntents; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; D6E152B424BFFDF600FDF9D3 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1841,6 +2036,7 @@ D6E152E824C0007200FDF9D3 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; @@ -1872,6 +2068,7 @@ D6E152E924C0007200FDF9D3 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; @@ -2015,6 +2212,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + D68C1E2D270614F9002D642B /* Build configuration list for PBXNativeTarget "GeminiIntents" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D68C1E2E270614F9002D642B /* Debug */, + D68C1E2F270614F9002D642B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; D6E152B324BFFDF600FDF9D3 /* Build configuration list for PBXNativeTarget "Gemini-iOS" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -2056,7 +2262,7 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ - D688F58F258AC814003A0A73 /* HTMLEntities */ = { + D68C1E4C2708A981002D642B /* HTMLEntities */ = { isa = XCSwiftPackageProductDependency; package = D688F58E258AC814003A0A73 /* XCRemoteSwiftPackageReference "swift-html-entities" */; productName = HTMLEntities; diff --git a/Gemini.xcodeproj/xcshareddata/xcschemes/GeminiIntents.xcscheme b/Gemini.xcodeproj/xcshareddata/xcschemes/GeminiIntents.xcscheme new file mode 100644 index 0000000..4c37a9d --- /dev/null +++ b/Gemini.xcodeproj/xcshareddata/xcschemes/GeminiIntents.xcscheme @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gemini.xcodeproj/xcuserdata/shadowfacts.xcuserdatad/xcschemes/xcschememanagement.plist b/Gemini.xcodeproj/xcuserdata/shadowfacts.xcuserdatad/xcschemes/xcschememanagement.plist index b8da17f..7d5c47b 100644 --- a/Gemini.xcodeproj/xcuserdata/shadowfacts.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Gemini.xcodeproj/xcuserdata/shadowfacts.xcuserdatad/xcschemes/xcschememanagement.plist @@ -24,6 +24,11 @@ orderHint 0 + GeminiIntents.xcscheme_^#shared#^_ + + orderHint + 6 + GeminiProtocol.xcscheme_^#shared#^_ orderHint @@ -62,6 +67,11 @@ primary + D68C1E22270614F9002D642B + + primary + + D6E152A124BFFDF500FDF9D3 primary diff --git a/GeminiIntents/GemtextToHTMLIntentHandler.swift b/GeminiIntents/GemtextToHTMLIntentHandler.swift new file mode 100644 index 0000000..6604ed0 --- /dev/null +++ b/GeminiIntents/GemtextToHTMLIntentHandler.swift @@ -0,0 +1,30 @@ +// +// GemtextToHTMLIntentHandler.swift +// GeminiIntents +// +// Created by Shadowfacts on 10/1/21. +// + +import Intents +import GeminiFormat + +class GemtextToHTMLIntentHandler: NSObject, GemtextToHTMLIntentHandling { + + func handle(intent: GemtextToHTMLIntent, completion: @escaping (GemtextToHTMLIntentResponse) -> Void) { + guard let response = intent.response, + let text = response.body, + let url = response.url else { + completion(GemtextToHTMLIntentResponse(code: .failure, userActivity: nil)) + return + } + let doc = GeminiParser.parse(text: text, baseURL: url) + let renderer = GeminiHTMLRenderer() + renderer.addLinkClass = false + renderer.addHeadingLineIDs = false + let html = renderer.renderDocumentToHTML(doc) + let intentResp = GemtextToHTMLIntentResponse(code: .success, userActivity: nil) + intentResp.html = INFile(data: html.data(using: .utf8)!, filename: "converted_gemtext.html", typeIdentifier: "public.html") + completion(intentResp) + } + +} diff --git a/GeminiIntents/GemtextToMarkdownIntentHandler.swift b/GeminiIntents/GemtextToMarkdownIntentHandler.swift new file mode 100644 index 0000000..be65ef7 --- /dev/null +++ b/GeminiIntents/GemtextToMarkdownIntentHandler.swift @@ -0,0 +1,28 @@ +// +// GemtextToMarkdownIntentHandler.swift +// GeminiIntents +// +// Created by Shadowfacts on 10/1/21. +// + +import Intents +import GeminiFormat + +class GemtextToMarkdownIntentHandler: NSObject, GemtextToMarkdownIntentHandling { + + func handle(intent: GemtextToMarkdownIntent, completion: @escaping (GemtextToMarkdownIntentResponse) -> Void) { + guard let response = intent.response, + let text = response.body, + let url = response.url else { + completion(GemtextToMarkdownIntentResponse(code: .failure, userActivity: nil)) + return + } + let doc = GeminiParser.parse(text: text, baseURL: url) + let renderer = GeminiMarkdownRenderer() + let html = renderer.renderDocumentToMarkdown(doc) + let intentResp = GemtextToMarkdownIntentResponse(code: .success, userActivity: nil) + intentResp.markdown = INFile(data: html.data(using: .utf8)!, filename: "converted_gemtext.md", typeIdentifier: "net.daringfireball.markdown") + completion(intentResp) + } + +} diff --git a/GeminiIntents/GetBodyIntentHandler.swift b/GeminiIntents/GetBodyIntentHandler.swift new file mode 100644 index 0000000..8760e5a --- /dev/null +++ b/GeminiIntents/GetBodyIntentHandler.swift @@ -0,0 +1,22 @@ +// +// GetBodyIntenHandler.swift +// GeminiIntents +// +// Created by Shadowfacts on 10/1/21. +// + +import Intents + +class GetBodyIntentHandler: NSObject, GetBodyIntentHandling { + + func handle(intent: GetBodyIntent, completion: @escaping (GetBodyIntentResponse) -> Void) { + guard let response = intent.response else { + completion(GetBodyIntentResponse(code: .failure, userActivity: nil)) + return + } + let intentResp = GetBodyIntentResponse(code: .success, userActivity: nil) + intentResp.text = response.body + completion(intentResp) + } + +} diff --git a/GeminiIntents/GetMetaIntentHandler.swift b/GeminiIntents/GetMetaIntentHandler.swift new file mode 100644 index 0000000..e8afffa --- /dev/null +++ b/GeminiIntents/GetMetaIntentHandler.swift @@ -0,0 +1,22 @@ +// +// GetMetaIntentHandler.swift +// GeminiIntents +// +// Created by Shadowfacts on 10/1/21. +// + +import Intents + +class GetMetaIntentHandler: NSObject, GetMetaIntentHandling { + + func handle(intent: GetMetaIntent, completion: @escaping (GetMetaIntentResponse) -> Void) { + guard let response = intent.response else { + completion(GetMetaIntentResponse(code: .failure, userActivity: nil)) + return + } + let intentResp = GetMetaIntentResponse(code: .success, userActivity: nil) + intentResp.meta = response.meta + completion(intentResp) + } + +} diff --git a/GeminiIntents/GetStatusIntentHandler.swift b/GeminiIntents/GetStatusIntentHandler.swift new file mode 100644 index 0000000..aa8bc58 --- /dev/null +++ b/GeminiIntents/GetStatusIntentHandler.swift @@ -0,0 +1,22 @@ +// +// GetStatusIntentHandler.swift +// GeminiIntents +// +// Created by Shadowfacts on 10/1/21. +// + +import Intents + +class GetStatusIntentHandler: NSObject, GetStatusIntentHandling { + + func handle(intent: GetStatusIntent, completion: @escaping (GetStatusIntentResponse) -> Void) { + guard let response = intent.response else { + completion(GetStatusIntentResponse(code: .failure, userActivity: nil)) + return + } + let intentResp = GetStatusIntentResponse(code: .success, userActivity: nil) + intentResp.status = response.status.rawValue as NSNumber + completion(intentResp) + } + +} diff --git a/GeminiIntents/Info.plist b/GeminiIntents/Info.plist new file mode 100644 index 0000000..612c31b --- /dev/null +++ b/GeminiIntents/Info.plist @@ -0,0 +1,30 @@ + + + + + NSExtension + + NSExtensionAttributes + + IntentsRestrictedWhileLocked + + IntentsRestrictedWhileProtectedDataUnavailable + + IntentsSupported + + GemtextToHTMLIntent + GemtextToMarkdownIntent + GetBodyIntent + GetMetaIntent + GetStatusIntent + MakeRequestIntent + OpenURLIntent + + + NSExtensionPointIdentifier + com.apple.intents-service + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).IntentHandler + + + diff --git a/GeminiIntents/IntentHandler.swift b/GeminiIntents/IntentHandler.swift new file mode 100644 index 0000000..7fec199 --- /dev/null +++ b/GeminiIntents/IntentHandler.swift @@ -0,0 +1,41 @@ +// +// IntentHandler.swift +// GeminiIntents +// +// Created by Shadowfacts on 9/30/21. +// + +import Intents + +class IntentHandler: INExtension { + + override func handler(for intent: INIntent) -> Any? { + switch intent { + // we also need to support extension-based handling because in-app handling isn't support Void) { + guard let url = intent.url, + url.scheme?.lowercased() == "gemini" else { + completion(.unsupported()) + return + } + completion(.success(with: url)) + } + + func handle(intent: MakeRequestIntent, completion: @escaping (MakeRequestIntentResponse) -> Void) { + guard let url = intent.url else { + completion(MakeRequestIntentResponse(code: .failure, userActivity: nil)) + return + } + makeRequest(for: url, followRedirects: intent.followRedirects?.boolValue ?? true, completion: completion) + } + + private func makeRequest(for url: URL, followRedirects: Bool, completion: @escaping (MakeRequestIntentResponse) -> Void) { + guard let request = try? GeminiRequest(url: url) else { + completion(MakeRequestIntentResponse(code: .failure, userActivity: nil)) + return + } + + // foo(bar(baz)) + // a + + task = GeminiDataTask(request: request) { [unowned self] (result) in + switch result { + case let .success(response): + if response.status.isRedirect && followRedirects { + if let newURL = URL(string: response.meta, relativeTo: url) { + self.makeRequest(for: newURL, followRedirects: followRedirects, completion: completion) + } else { + completion(MakeRequestIntentResponse(code: .failure, userActivity: nil)) + } + } else { + let intentResp = MakeRequestIntentResponse(code: .success, userActivity: nil) + let displayStr = "\(response.status), \(BrowserHelper.urlForDisplay(url)), '\(response.meta)'" + intentResp.response = Response(identifier: url.absoluteString, display: displayStr) + intentResp.response!.url = url + intentResp.response!.body = response.bodyText + intentResp.response!.status = ResponseStatus(rawValue: response.status.rawValue)! + intentResp.response!.meta = response.meta +// intentResp.status = ResponseStatus(rawValue: response.status.rawValue)! +// intentResp.status = NSNumber(integerLiteral: response.status.rawValue) +// intentResp.statusCategory = ResponseStatusCategory(rawValue: response.status.rawValue / 10)! +// intentResp.meta = response.meta +// intentResp.mimeType = response.mimeType +// intentResp.body = response.bodyText + completion(intentResp) + } + + case .failure(_): + completion(MakeRequestIntentResponse(code: .failure, userActivity: nil)) + } + } + if #available(iOS 15.0, *) { + task!.attribution = .user + } + task!.resume() + } +}