diff --git a/ios/App/App/AppDelegate.swift b/ios/App/App/AppDelegate.swift
index 10fc3faf49..11d2176cfc 100644
--- a/ios/App/App/AppDelegate.swift
+++ b/ios/App/App/AppDelegate.swift
@@ -6,12 +6,56 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
- func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
- // Override point for customization after application launch.
-
+ // Cold start
+ func application(_ application: UIApplication,
+ didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
+ if let shortcutItem = launchOptions?[.shortcutItem] as? UIApplicationShortcutItem {
+ // Delay a tick so Capacitor bridge is ready
+ DispatchQueue.main.async {
+ _ = self.handleShortcutItem(shortcutItem)
+ }
+ }
return true
}
+ // Warm start (app already running/in background)
+ func application(_ application: UIApplication,
+ performActionFor shortcutItem: UIApplicationShortcutItem,
+ completionHandler: @escaping (Bool) -> Void) {
+ let handled = handleShortcutItem(shortcutItem)
+ completionHandler(handled)
+ }
+
+ // Shared handler
+ private func handleShortcutItem(_ shortcutItem: UIApplicationShortcutItem) -> Bool {
+ var urlString: String?
+
+ switch shortcutItem.type {
+ case "logseq.voice":
+ urlString = "logseq://go/audio"
+ case "logseq.quickadd":
+ urlString = "logseq://go/quick-add"
+ default:
+ break
+ }
+
+ if let urlString {
+ print("Quick action URL:", urlString)
+ if let url = URL(string: urlString) {
+ UIApplication.shared.open(url, options: [:]) { success in
+ if success {
+ print("Opened \(url)")
+ } else {
+ print("Failed to open \(url)")
+ }
+ }
+ }
+ return true
+ }
+
+ return false
+ }
+
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
diff --git a/ios/App/App/Info.plist b/ios/App/App/Info.plist
index 6c7e67c2ea..55931b5605 100644
--- a/ios/App/App/Info.plist
+++ b/ios/App/App/Info.plist
@@ -120,5 +120,25 @@
ITSAppUsesNonExemptEncryption
+ UIApplicationShortcutItems
+
+
+ UIApplicationShortcutItemType
+ logseq.voice
+ UIApplicationShortcutItemTitle
+ Voice
+ UIApplicationShortcutItemIconSymbolName
+ waveform
+
+
+ UIApplicationShortcutItemType
+ logseq.quickadd
+ UIApplicationShortcutItemTitle
+ Quick Add
+ UIApplicationShortcutItemIconSymbolName
+ plus
+
+
+
diff --git a/src/main/mobile/deeplink.cljs b/src/main/mobile/deeplink.cljs
index 5e04f9cdcd..824c9efd00 100644
--- a/src/main/mobile/deeplink.cljs
+++ b/src/main/mobile/deeplink.cljs
@@ -30,9 +30,9 @@
(map :url))
repo-names (map #(get-graph-name-fn %) repos)]
(cond
- (= pathname "/audio")
+ (and (= hostname "go") (= pathname "/audio"))
(state/pub-event! [:mobile/start-audio-record])
- (= pathname "/quick-add")
+ (and (= hostname "go") (= pathname "/quick-add"))
(state/pub-event! [:dialog/mobile-quick-add])
(= hostname "graph")
(let [graph-name (some-> pathname