diff --git a/ios/App/App/SharedImagePlugin.swift b/ios/App/App/SharedImagePlugin.swift index a18c4b27..06abe82c 100644 --- a/ios/App/App/SharedImagePlugin.swift +++ b/ios/App/App/SharedImagePlugin.swift @@ -24,7 +24,8 @@ public class SharedImagePlugin: CAPPlugin, CAPBridgedPlugin { public var pluginMethods: [CAPPluginMethod] { return [ CAPPluginMethod(#selector(getSharedImage(_:)), returnType: .promise), - CAPPluginMethod(#selector(hasSharedImage(_:)), returnType: .promise) + CAPPluginMethod(#selector(hasSharedImage(_:)), returnType: .promise), + CAPPluginMethod(#selector(getShareExtensionDiagnostics(_:)), returnType: .promise) ] } @@ -62,5 +63,12 @@ public class SharedImagePlugin: CAPPlugin, CAPBridgedPlugin { "hasImage": hasImage ]) } + + /** + * Diagnostic snapshot of Share Extension startup and pending share state + */ + @objc public func getShareExtensionDiagnostics(_ call: CAPPluginCall) { + call.resolve(SharedImageUtility.getShareExtensionDiagnostics()) + } } diff --git a/ios/App/App/SharedImageUtility.swift b/ios/App/App/SharedImageUtility.swift index 42be0aeb..59f08339 100644 --- a/ios/App/App/SharedImageUtility.swift +++ b/ios/App/App/SharedImageUtility.swift @@ -14,6 +14,7 @@ public class SharedImageUtility { private static let sharedPhotoFileNameKey = "sharedPhotoFileName" private static let sharedPhotoFilePathKey = "sharedPhotoFilePath" private static let sharedPhotoShareIdKey = "sharedPhotoShareId" + private static let shareExtensionLastStartKey = "shareExtensionLastStart" private static let sharedPhotoReadyKey = "sharedPhotoReady" /// Get the App Group container URL for accessing shared files @@ -96,7 +97,42 @@ public class SharedImageUtility { let fileURL = containerURL.appendingPathComponent(filePath) return FileManager.default.fileExists(atPath: fileURL.path) } - + + /** + * Diagnostic snapshot of Share Extension startup and pending share state + * Read-only: does not modify App Group storage + */ + static func getShareExtensionDiagnostics() -> [String: Any] { + guard let userDefaults = UserDefaults(suiteName: appGroupIdentifier) else { + return [ + "shareExtensionLastStart": NSNull(), + "sharedPhotoShareId": NSNull(), + "sharedPhotoFilePath": NSNull(), + "fileExists": false + ] + } + + let shareExtensionLastStart = userDefaults.string(forKey: shareExtensionLastStartKey) + let shareId = userDefaults.string(forKey: sharedPhotoShareIdKey) + let filePath = userDefaults.string(forKey: sharedPhotoFilePathKey) + let fileExists: Bool + if let filePath = filePath, let containerURL = appGroupContainerURL { + let fileURL = containerURL.appendingPathComponent(filePath) + fileExists = FileManager.default.fileExists(atPath: fileURL.path) + } else { + fileExists = false + } + + print("[ShareTarget] getShareExtensionDiagnostics shareExtensionLastStart=\(shareExtensionLastStart ?? "nil") sharedPhotoShareId=\(shareId ?? "nil") sharedPhotoFilePath=\(filePath ?? "nil") fileExists=\(fileExists)") + + return [ + "shareExtensionLastStart": shareExtensionLastStart ?? NSNull(), + "sharedPhotoShareId": shareId ?? NSNull(), + "sharedPhotoFilePath": filePath ?? NSNull(), + "fileExists": fileExists + ] + } + /** * Check if shared photo ready flag is set * This flag is set by the Share Extension when image is ready diff --git a/ios/App/TimeSafariShareExtension/ShareViewController.swift b/ios/App/TimeSafariShareExtension/ShareViewController.swift index f37f3adf..a8cdb460 100644 --- a/ios/App/TimeSafariShareExtension/ShareViewController.swift +++ b/ios/App/TimeSafariShareExtension/ShareViewController.swift @@ -14,6 +14,7 @@ class ShareViewController: UIViewController { private let sharedPhotoFileNameKey = "sharedPhotoFileName" private let sharedPhotoFilePathKey = "sharedPhotoFilePath" private let sharedPhotoShareIdKey = "sharedPhotoShareId" + private let shareExtensionLastStartKey = "shareExtensionLastStart" private let sharedImageFileName = "shared-image" /// Get the App Group container URL for storing shared files @@ -22,6 +23,13 @@ class ShareViewController: UIViewController { } override func viewDidLoad() { + if let userDefaults = UserDefaults(suiteName: appGroupIdentifier) { + let timestamp = ISO8601DateFormatter().string(from: Date()) + userDefaults.set(timestamp, forKey: shareExtensionLastStartKey) + userDefaults.synchronize() + print("[ShareTarget] shareExtensionLastStart=\(timestamp)") + } + print("[ShareTarget] viewDidLoad started") super.viewDidLoad() diff --git a/src/plugins/SharedImagePlugin.web.ts b/src/plugins/SharedImagePlugin.web.ts index d609be16..71f021f6 100644 --- a/src/plugins/SharedImagePlugin.web.ts +++ b/src/plugins/SharedImagePlugin.web.ts @@ -4,7 +4,11 @@ */ import { WebPlugin } from "@capacitor/core"; -import type { SharedImagePlugin, SharedImageResult } from "./definitions"; +import type { + SharedImagePlugin, + SharedImageResult, + ShareExtensionDiagnostics, +} from "./definitions"; export class SharedImagePluginWeb extends WebPlugin @@ -18,4 +22,13 @@ export class SharedImagePluginWeb async hasSharedImage(): Promise<{ hasImage: boolean }> { return { hasImage: false }; } + + async getShareExtensionDiagnostics(): Promise { + return { + shareExtensionLastStart: null, + sharedPhotoShareId: null, + sharedPhotoFilePath: null, + fileExists: false, + }; + } } diff --git a/src/plugins/definitions.ts b/src/plugins/definitions.ts index f67a443c..1dd11255 100644 --- a/src/plugins/definitions.ts +++ b/src/plugins/definitions.ts @@ -7,6 +7,13 @@ export interface SharedImageResult { fileName: string; } +export interface ShareExtensionDiagnostics { + shareExtensionLastStart: string | null; + sharedPhotoShareId: string | null; + sharedPhotoFilePath: string | null; + fileExists: boolean; +} + export interface SharedImagePlugin { /** * Get shared image data from native layer @@ -20,4 +27,9 @@ export interface SharedImagePlugin { * Useful for quick checks before calling getSharedImage() */ hasSharedImage(): Promise<{ hasImage: boolean }>; + + /** + * Diagnostic snapshot of Share Extension startup and pending share state (iOS) + */ + getShareExtensionDiagnostics(): Promise; }