Convert iOS from group to folder. Make Intents a separate group.

This commit is contained in:
Brent Simmons
2025-01-02 21:14:11 -08:00
parent 1774d75d3d
commit 811a7f52b2
4 changed files with 32 additions and 145 deletions

View File

@@ -1,143 +0,0 @@
//
// AddWebFeedIntentHandler.swift
// NetNewsWire
//
// Created by Maurice Parker on 10/18/19.
// Copyright © 2019 Ranchero Software. All rights reserved.
//
import Intents
public enum AddWebFeedIntentHandlerError: LocalizedError {
case communicationFailure
public var errorDescription: String? {
switch self {
case .communicationFailure:
return NSLocalizedString("Unable to communicate with NetNewsWire.", comment: "Communication failure")
}
}
}
public class AddWebFeedIntentHandler: NSObject, AddWebFeedIntentHandling {
override init() {
super.init()
}
public func resolveUrl(for intent: AddWebFeedIntent, with completion: @escaping (AddWebFeedUrlResolutionResult) -> Void) {
guard let url = intent.url else {
completion(.unsupported(forReason: .required))
return
}
completion(.success(with: url))
}
public func provideAccountNameOptions(for intent: AddWebFeedIntent, with completion: @escaping ([String]?, Error?) -> Void) {
guard let extensionContainers = ExtensionContainersFile.read() else {
completion(nil, AddWebFeedIntentHandlerError.communicationFailure)
return
}
let accountNames = extensionContainers.accounts.map { $0.name }
completion(accountNames, nil)
}
public func resolveAccountName(for intent: AddWebFeedIntent, with completion: @escaping (AddWebFeedAccountNameResolutionResult) -> Void) {
guard let accountName = intent.accountName else {
completion(AddWebFeedAccountNameResolutionResult.notRequired())
return
}
guard let extensionContainers = ExtensionContainersFile.read() else {
completion(.unsupported(forReason: .communication))
return
}
if extensionContainers.findAccount(forName: accountName) == nil {
completion(.unsupported(forReason: .invalid))
} else {
completion(.success(with: accountName))
}
}
public func provideFolderNameOptions(for intent: AddWebFeedIntent, with completion: @escaping ([String]?, Error?) -> Void) {
guard let extensionContainers = ExtensionContainersFile.read() else {
completion(nil, AddWebFeedIntentHandlerError.communicationFailure)
return
}
guard let accountName = intent.accountName, let account = extensionContainers.findAccount(forName: accountName) else {
completion([String](), nil)
return
}
let folderNames = account.folders.map { $0.name }
completion(folderNames, nil)
}
public func resolveFolderName(for intent: AddWebFeedIntent, with completion: @escaping (AddWebFeedFolderNameResolutionResult) -> Void) {
guard let accountName = intent.accountName, let folderName = intent.folderName else {
completion(AddWebFeedFolderNameResolutionResult.notRequired())
return
}
guard let extensionContainers = ExtensionContainersFile.read() else {
completion(.unsupported(forReason: .communication))
return
}
guard let account = extensionContainers.findAccount(forName: accountName) else {
completion(.unsupported(forReason: .invalid))
return
}
if account.findFolder(forName: folderName) == nil {
completion(.unsupported(forReason: .invalid))
} else {
completion(.success(with: folderName))
}
return
}
public func handle(intent: AddWebFeedIntent, completion: @escaping (AddWebFeedIntentResponse) -> Void) {
guard let url = intent.url, let extensionContainers = ExtensionContainersFile.read() else {
completion(AddWebFeedIntentResponse(code: .failure, userActivity: nil))
return
}
let account: ExtensionAccount? = {
if let accountName = intent.accountName {
return extensionContainers.findAccount(forName: accountName)
} else {
return extensionContainers.accounts.first
}
}()
guard let validAccount = account else {
completion(AddWebFeedIntentResponse(code: .failure, userActivity: nil))
return
}
let container: ExtensionContainer? = {
if let folderName = intent.folderName {
return validAccount.findFolder(forName: folderName)
} else {
return validAccount
}
}()
guard let validContainer = container, let containerID = validContainer.containerID else {
completion(AddWebFeedIntentResponse(code: .failure, userActivity: nil))
return
}
let request = ExtensionFeedAddRequest(name: nil, feedURL: url, destinationContainerID: containerID)
ExtensionFeedAddRequestFile.save(request)
completion(AddWebFeedIntentResponse(code: .success, userActivity: nil))
}
}

View File

@@ -1,314 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>INEnums</key>
<array/>
<key>INIntentDefinitionModelVersion</key>
<string>1.1</string>
<key>INIntentDefinitionNamespace</key>
<string>U6u7RF</string>
<key>INIntentDefinitionSystemVersion</key>
<string>19D76</string>
<key>INIntentDefinitionToolsBuildVersion</key>
<string>11B53</string>
<key>INIntentDefinitionToolsVersion</key>
<string>11.2.1</string>
<key>INIntents</key>
<array>
<dict>
<key>INIntentCategory</key>
<string>create</string>
<key>INIntentConfigurable</key>
<true/>
<key>INIntentDescription</key>
<string>Add a web feed</string>
<key>INIntentDescriptionID</key>
<string>IuAbef</string>
<key>INIntentIneligibleForSuggestions</key>
<true/>
<key>INIntentInput</key>
<string>url</string>
<key>INIntentKeyParameter</key>
<string>url</string>
<key>INIntentLastParameterTag</key>
<integer>4</integer>
<key>INIntentManagedParameterCombinations</key>
<dict>
<key>url,accountName</key>
<dict>
<key>INIntentParameterCombinationSupportsBackgroundExecution</key>
<true/>
<key>INIntentParameterCombinationTitle</key>
<string>Add ${url} to ${accountName}</string>
<key>INIntentParameterCombinationTitleID</key>
<string>kaKsEY</string>
<key>INIntentParameterCombinationUpdatesLinked</key>
<true/>
</dict>
<key>url,accountName,folderName</key>
<dict>
<key>INIntentParameterCombinationSupportsBackgroundExecution</key>
<true/>
<key>INIntentParameterCombinationTitle</key>
<string>Add ${url} to ${folderName} in ${accountName}</string>
<key>INIntentParameterCombinationTitleID</key>
<string>dkSFD2</string>
<key>INIntentParameterCombinationUpdatesLinked</key>
<true/>
</dict>
</dict>
<key>INIntentName</key>
<string>AddWebFeed</string>
<key>INIntentParameters</key>
<array>
<dict>
<key>INIntentParameterDisplayName</key>
<string>URL</string>
<key>INIntentParameterDisplayNameID</key>
<string>BCHr23</string>
<key>INIntentParameterDisplayPriority</key>
<integer>1</integer>
<key>INIntentParameterName</key>
<string>url</string>
<key>INIntentParameterPromptDialogs</key>
<array>
<dict>
<key>INIntentParameterPromptDialogCustom</key>
<true/>
<key>INIntentParameterPromptDialogFormatString</key>
<string>What is the ${url} you would like add?</string>
<key>INIntentParameterPromptDialogFormatStringID</key>
<string>jLLidQ</string>
<key>INIntentParameterPromptDialogType</key>
<string>Primary</string>
</dict>
</array>
<key>INIntentParameterSupportsResolution</key>
<true/>
<key>INIntentParameterTag</key>
<integer>2</integer>
<key>INIntentParameterType</key>
<string>URL</string>
<key>INIntentParameterUnsupportedReasons</key>
<array>
<dict>
<key>INIntentParameterUnsupportedReasonCode</key>
<string>required</string>
<key>INIntentParameterUnsupportedReasonCustom</key>
<true/>
<key>INIntentParameterUnsupportedReasonFormatString</key>
<string>You must supply a URL.</string>
<key>INIntentParameterUnsupportedReasonFormatStringID</key>
<string>4xjRes</string>
</dict>
</array>
</dict>
<dict>
<key>INIntentParameterCustomDisambiguation</key>
<true/>
<key>INIntentParameterDisplayName</key>
<string>Account Name</string>
<key>INIntentParameterDisplayNameID</key>
<string>CSrgUY</string>
<key>INIntentParameterDisplayPriority</key>
<integer>2</integer>
<key>INIntentParameterMetadata</key>
<dict>
<key>INIntentParameterMetadataCapitalization</key>
<string>Sentences</string>
</dict>
<key>INIntentParameterName</key>
<string>accountName</string>
<key>INIntentParameterPromptDialogs</key>
<array>
<dict>
<key>INIntentParameterPromptDialogCustom</key>
<true/>
<key>INIntentParameterPromptDialogType</key>
<string>Primary</string>
</dict>
<dict>
<key>INIntentParameterPromptDialogCustom</key>
<true/>
<key>INIntentParameterPromptDialogFormatString</key>
<string>There are ${count} options matching ${accountName}.</string>
<key>INIntentParameterPromptDialogFormatStringID</key>
<string>IbqUVS</string>
<key>INIntentParameterPromptDialogType</key>
<string>DisambiguationIntroduction</string>
</dict>
<dict>
<key>INIntentParameterPromptDialogFormatString</key>
<string>Which one?</string>
<key>INIntentParameterPromptDialogFormatStringID</key>
<string>fWs3li</string>
<key>INIntentParameterPromptDialogType</key>
<string>DisambiguationSelection</string>
</dict>
<dict>
<key>INIntentParameterPromptDialogCustom</key>
<true/>
<key>INIntentParameterPromptDialogFormatString</key>
<string>Just to confirm, you wanted ${accountName}?</string>
<key>INIntentParameterPromptDialogFormatStringID</key>
<string>HHiZUh</string>
<key>INIntentParameterPromptDialogType</key>
<string>Confirmation</string>
</dict>
</array>
<key>INIntentParameterSupportsDynamicEnumeration</key>
<true/>
<key>INIntentParameterSupportsResolution</key>
<true/>
<key>INIntentParameterTag</key>
<integer>3</integer>
<key>INIntentParameterType</key>
<string>String</string>
<key>INIntentParameterUnsupportedReasons</key>
<array>
<dict>
<key>INIntentParameterUnsupportedReasonCode</key>
<string>invalid</string>
<key>INIntentParameterUnsupportedReasonCustom</key>
<true/>
<key>INIntentParameterUnsupportedReasonFormatString</key>
<string>A valid Account Name is required.</string>
<key>INIntentParameterUnsupportedReasonFormatStringID</key>
<string>JGkCuS</string>
</dict>
<dict>
<key>INIntentParameterUnsupportedReasonCode</key>
<string>communication</string>
<key>INIntentParameterUnsupportedReasonCustom</key>
<true/>
<key>INIntentParameterUnsupportedReasonFormatString</key>
<string>Unable to communicate with NetNewsWire.</string>
<key>INIntentParameterUnsupportedReasonFormatStringID</key>
<string>uSfloN</string>
</dict>
</array>
</dict>
<dict>
<key>INIntentParameterCustomDisambiguation</key>
<true/>
<key>INIntentParameterDisplayName</key>
<string>Folder Name</string>
<key>INIntentParameterDisplayNameID</key>
<string>zXhMPF</string>
<key>INIntentParameterDisplayPriority</key>
<integer>3</integer>
<key>INIntentParameterMetadata</key>
<dict>
<key>INIntentParameterMetadataCapitalization</key>
<string>Sentences</string>
</dict>
<key>INIntentParameterName</key>
<string>folderName</string>
<key>INIntentParameterPromptDialogs</key>
<array>
<dict>
<key>INIntentParameterPromptDialogCustom</key>
<true/>
<key>INIntentParameterPromptDialogType</key>
<string>Primary</string>
</dict>
<dict>
<key>INIntentParameterPromptDialogCustom</key>
<true/>
<key>INIntentParameterPromptDialogFormatString</key>
<string>There are ${count} options matching ${folderName}.</string>
<key>INIntentParameterPromptDialogFormatStringID</key>
<string>5CYbGL</string>
<key>INIntentParameterPromptDialogType</key>
<string>DisambiguationIntroduction</string>
</dict>
<dict>
<key>INIntentParameterPromptDialogFormatString</key>
<string>Which one?</string>
<key>INIntentParameterPromptDialogFormatStringID</key>
<string>gEzXaM</string>
<key>INIntentParameterPromptDialogType</key>
<string>DisambiguationSelection</string>
</dict>
<dict>
<key>INIntentParameterPromptDialogCustom</key>
<true/>
<key>INIntentParameterPromptDialogFormatString</key>
<string>Just to confirm, you wanted ${folderName}?</string>
<key>INIntentParameterPromptDialogFormatStringID</key>
<string>k5GTo0</string>
<key>INIntentParameterPromptDialogType</key>
<string>Confirmation</string>
</dict>
</array>
<key>INIntentParameterRelationship</key>
<dict>
<key>INIntentParameterRelationshipParentName</key>
<string>accountName</string>
<key>INIntentParameterRelationshipPredicateName</key>
<string>HasAnyValue</string>
</dict>
<key>INIntentParameterSupportsDynamicEnumeration</key>
<true/>
<key>INIntentParameterSupportsResolution</key>
<true/>
<key>INIntentParameterTag</key>
<integer>4</integer>
<key>INIntentParameterType</key>
<string>String</string>
<key>INIntentParameterUnsupportedReasons</key>
<array>
<dict>
<key>INIntentParameterUnsupportedReasonCode</key>
<string>invalid</string>
<key>INIntentParameterUnsupportedReasonCustom</key>
<true/>
<key>INIntentParameterUnsupportedReasonFormatString</key>
<string>A valid Folder Name is required.</string>
<key>INIntentParameterUnsupportedReasonFormatStringID</key>
<string>ef5kBt</string>
</dict>
<dict>
<key>INIntentParameterUnsupportedReasonCode</key>
<string>communication</string>
<key>INIntentParameterUnsupportedReasonCustom</key>
<true/>
<key>INIntentParameterUnsupportedReasonFormatString</key>
<string>Unable to communicate with NetNewsWire.</string>
<key>INIntentParameterUnsupportedReasonFormatStringID</key>
<string>ExjqcE</string>
</dict>
</array>
</dict>
</array>
<key>INIntentResponse</key>
<dict>
<key>INIntentResponseCodes</key>
<array>
<dict>
<key>INIntentResponseCodeName</key>
<string>success</string>
<key>INIntentResponseCodeSuccess</key>
<true/>
</dict>
<dict>
<key>INIntentResponseCodeName</key>
<string>failure</string>
</dict>
</array>
</dict>
<key>INIntentTitle</key>
<string>Add Web Feed</string>
<key>INIntentTitleID</key>
<string>oV681v</string>
<key>INIntentType</key>
<string>Custom</string>
<key>INIntentVerb</key>
<string>Add</string>
</dict>
</array>
<key>INTypes</key>
<array/>
</dict>
</plist>

View File

@@ -1,30 +0,0 @@
"4xjRes" = "You must supply a URL.";
"8Dh9Yy" = "No feed was found at the specified URL.";
"BCHr23" = "URL";
"CSrgUY" = "Account Name";
"HHiZUh" = "Just to confirm, you wanted ${accountName}?";
"IbqUVS" = "There are ${count} options matching ${accountName}.";
"IuAbef" = "Add a feed";
"JGkCuS" = "An account name is required.";
"UGGPkp" = "You are already subscribed to this feed in this account.";
"dkSFD2" = "Add${url}to ${accountName}";
"drQfaI" = "No feed was found at the specified URL.";
"fWs3li" = "Which one?";
"jLLidQ" = "What is the ${url}you would like add?";
"oV681v" = "Add Feed";
"srME8b" = "You are already subscribed to this feed in this account.";