Using App Shortcuts with app intents, Siri only responds to the first shortcut defined in the app shortcut below.
struct MementoShortcuts: AppShortcutsProvider {
u/AppShortcutsBuilder
static var appShortcuts: [AppShortcut] {
AppShortcut(
intent: SaveLinkIntent(),
phrases: ["Add a link to \(.applicationName)", "Add \(\.$url) to \(.applicationName)", "Make a new link in \(.applicationName)", "Create a new link in \(.applicationName) from \(\.$url)"],
shortTitle: "Add Link",
systemImageName: "link.badge.plus"
)
AppShortcut(
intent: LinkViewedIntent(),
phrases: [
"Mark a link I saved in \(.applicationName) as viewed",
"Mark \(\.$link) as viewed in \(.applicationName)",
"Set link in \(.applicationName) to viewed",
"Change status of \(\.$link) to viewed in \(.applicationName)",
],
shortTitle: "Mark Link as Viewed",
systemImageName: "book"
)
}
}
I have tried switching the order and she always uses the one that comes first. Both show up in the shortcuts app as an app shortcut, but only one shortcut is recognized by Siri even if I say the other one's phrase.
Post
Replies
Boosts
Views
Activity
When using App Intents, I can edit already existing SwiftData items, but I cannot insert new ones. Below are the two app intents I've used, both function in their entirety other than the model context insertion at the end of the second one.
struct LinkViewedIntent: AppIntent {
static var title: LocalizedStringResource = "Mark Link Viewed"
@Parameter(title: "Link")
var link: LinkEntity?
init(link: Link) {
self.link = LinkEntity(link: link)
}
init() {}
func perform() async throws -> some IntentResult & ProvidesDialog {
let entities = try await LinkEntityQuery().suggestedEntities().filter({$0.viewed == false})
guard !entities.isEmpty else {
return .result(dialog: "There are no unviewed links to mark.")
}
var enteredLink: LinkEntity
if let link = link {
enteredLink = link
} else {
enteredLink = try await $link.requestDisambiguation(
among: LinkEntityQuery().suggestedEntities(),
dialog: "Which link would you like to mark viewed?"
)
}
let context = ModelContext(ConfigureModelContainer())
let links = try? context.fetch(FetchDescriptor<Link>())
guard let link = links?.filter({ $0.id == enteredLink.id }).first else {
return .result(dialog: "An Error Occured")
}
if link.viewed == true {
return .result(dialog: "Link is already viewed")
}
link.viewed = true
try context.save()
return .result(dialog: "Okay, \(enteredLink.name ?? enteredLink.link) has been marked as viewed.")
}
static var parameterSummary: some ParameterSummary {
Summary("Mark \(\.$link) as viewed.")
}
}
struct SaveLinkIntent: AppIntent {
static var title: LocalizedStringResource = "Save Link"
@Parameter(title: "URL")
var url: URL?
func perform() async throws -> some IntentResult & ProvidesDialog {
let modelContext = ModelContext(ConfigureModelContainer())
var fullurl: URL
if let url = url {
fullurl = url
} else {
fullurl = try await $url.requestValue()
}
print(fullurl.absoluteString)
guard let link = await makeLink(address: fullurl.absoluteString) else {
return .result(dialog: "")
}
modelContext.insert(link)
return .result(dialog: "I've added \(link.metadata?.title ?? link.address) to Memento")
}
}
When in Safari, you can say something like, "Siri, text this link to mom" or "Siri, save this link to reminders" and it will do it with the currently viewed link. Shortcuts also has a "Get what's on screen" action that can be added. How do I expose the user's current context to my App Intent?