Add the ability to specify folder in Add Feed shortcut

This commit is contained in:
Maurice Parker 2019-10-20 18:49:17 -05:00
parent b1668d6a62
commit af16731ecd
4 changed files with 172 additions and 11 deletions

View File

@ -455,6 +455,10 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
return ensureFolder(with: folderName)
}
public func findFolder(withDisplayName displayName: String) -> Folder? {
return folders?.first(where: { $0.nameForDisplay == displayName })
}
func newFeed(with opmlFeedSpecifier: RSOPMLFeedSpecifier) -> Feed {
let feedURL = opmlFeedSpecifier.feedURL
let metadata = feedMetadata(feedURL: feedURL, feedID: feedURL)

View File

@ -58,6 +58,10 @@ public final class AccountManager: UnreadCountProvider {
return sortByName(activeAccounts)
}
public func findActiveAccount(forDisplayName displayName: String) -> Account? {
return AccountManager.shared.activeAccounts.first(where: { $0.nameForDisplay == displayName })
}
public var refreshInProgress: Bool {
for account in activeAccounts {
if account.refreshInProgress {

View File

@ -10,7 +10,7 @@ import Intents
import Account
public class AddFeedIntentHandler: NSObject, AddFeedIntentHandling {
override init() {
super.init()
DispatchQueue.main.sync {
@ -35,25 +35,85 @@ public class AddFeedIntentHandler: NSObject, AddFeedIntentHandling {
public func resolveAccountName(for intent: AddFeedIntent, with completion: @escaping (AddFeedAccountNameResolutionResult) -> Void) {
guard let accountName = intent.accountName else {
completion(.unsupported(forReason: .required))
completion(AddFeedAccountNameResolutionResult.notRequired())
return
}
DispatchQueue.main.async {
if AccountManager.shared.findActiveAccount(forDisplayName: accountName) == nil {
completion(.unsupported(forReason: .invalid))
} else {
completion(.success(with: accountName))
}
}
}
public func provideFolderNameOptions(for intent: AddFeedIntent, with completion: @escaping ([String]?, Error?) -> Void) {
DispatchQueue.main.async {
guard let accountName = intent.accountName, let account = AccountManager.shared.findActiveAccount(forDisplayName: accountName) else {
completion([String](), nil)
return
}
let folderNames = account.folders?.map { $0.nameForDisplay }
completion(folderNames, nil)
}
}
public func resolveFolderName(for intent: AddFeedIntent, with completion: @escaping (AddFeedFolderNameResolutionResult) -> Void) {
guard let accountName = intent.accountName, let folderName = intent.folderName else {
completion(AddFeedFolderNameResolutionResult.notRequired())
return
}
DispatchQueue.main.async {
guard let account = AccountManager.shared.findActiveAccount(forDisplayName: accountName) else {
completion(.unsupported(forReason: .invalid))
return
}
if account.findFolder(withDisplayName: folderName) == nil {
completion(.unsupported(forReason: .invalid))
} else {
completion(.success(with: folderName))
}
return
}
completion(.success(with: accountName))
}
public func handle(intent: AddFeedIntent, completion: @escaping (AddFeedIntentResponse) -> Void) {
guard let url = intent.url, let accountName = intent.accountName else {
guard let url = intent.url else {
completion(AddFeedIntentResponse(code: .failure, userActivity: nil))
return
}
DispatchQueue.main.async {
guard let account = AccountManager.shared.activeAccounts.first(where: { $0.nameForDisplay == accountName }) else {
let account: Account? = {
if let accountName = intent.accountName {
return AccountManager.shared.findActiveAccount(forDisplayName: accountName)
} else {
return AccountManager.shared.sortedActiveAccounts.first
}
}()
guard let validAccount = account else {
completion(AddFeedIntentResponse(code: .failure, userActivity: nil))
return
}
account.createFeed(url: url.absoluteString, name: nil, container: account) { result in
let container: Container? = {
if let folderName = intent.folderName {
return validAccount.findFolder(withDisplayName: folderName)
} else {
return validAccount
}
}()
guard let validContainer = container else {
completion(AddFeedIntentResponse(code: .failure, userActivity: nil))
return
}
validAccount.createFeed(url: url.absoluteString, name: nil, container: validContainer) { result in
switch result {
case .success:
completion(AddFeedIntentResponse(code: .success, userActivity: nil))

View File

@ -32,7 +32,7 @@
<key>INIntentKeyParameter</key>
<string>url</string>
<key>INIntentLastParameterTag</key>
<integer>3</integer>
<integer>4</integer>
<key>INIntentManagedParameterCombinations</key>
<dict>
<key>url,accountName</key>
@ -40,7 +40,18 @@
<key>INIntentParameterCombinationSupportsBackgroundExecution</key>
<true/>
<key>INIntentParameterCombinationTitle</key>
<string>Add${url}to ${accountName}</string>
<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>
@ -66,7 +77,7 @@
<key>INIntentParameterPromptDialogCustom</key>
<true/>
<key>INIntentParameterPromptDialogFormatString</key>
<string>What is the ${url}you would like add?</string>
<string>What is the ${url} you would like add?</string>
<key>INIntentParameterPromptDialogFormatStringID</key>
<string>jLLidQ</string>
<key>INIntentParameterPromptDialogType</key>
@ -158,16 +169,98 @@
<array>
<dict>
<key>INIntentParameterUnsupportedReasonCode</key>
<string>required</string>
<string>invalid</string>
<key>INIntentParameterUnsupportedReasonCustom</key>
<true/>
<key>INIntentParameterUnsupportedReasonFormatString</key>
<string>An account name is required.</string>
<string>A valid Account Name is required.</string>
<key>INIntentParameterUnsupportedReasonFormatStringID</key>
<string>JGkCuS</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>
</array>
</dict>
</array>
<key>INIntentResponse</key>
<dict>