feat(ios): add Share Extension startup diagnostic marker and API
Write shareExtensionLastStart on ShareViewController.viewDidLoad and expose getShareExtensionDiagnostics() through SharedImagePlugin with shareId, file path, and fileExists for debugging failed share flows.
This commit is contained in:
@@ -24,7 +24,8 @@ public class SharedImagePlugin: CAPPlugin, CAPBridgedPlugin {
|
|||||||
public var pluginMethods: [CAPPluginMethod] {
|
public var pluginMethods: [CAPPluginMethod] {
|
||||||
return [
|
return [
|
||||||
CAPPluginMethod(#selector(getSharedImage(_:)), returnType: .promise),
|
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
|
"hasImage": hasImage
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Diagnostic snapshot of Share Extension startup and pending share state
|
||||||
|
*/
|
||||||
|
@objc public func getShareExtensionDiagnostics(_ call: CAPPluginCall) {
|
||||||
|
call.resolve(SharedImageUtility.getShareExtensionDiagnostics())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ public class SharedImageUtility {
|
|||||||
private static let sharedPhotoFileNameKey = "sharedPhotoFileName"
|
private static let sharedPhotoFileNameKey = "sharedPhotoFileName"
|
||||||
private static let sharedPhotoFilePathKey = "sharedPhotoFilePath"
|
private static let sharedPhotoFilePathKey = "sharedPhotoFilePath"
|
||||||
private static let sharedPhotoShareIdKey = "sharedPhotoShareId"
|
private static let sharedPhotoShareIdKey = "sharedPhotoShareId"
|
||||||
|
private static let shareExtensionLastStartKey = "shareExtensionLastStart"
|
||||||
private static let sharedPhotoReadyKey = "sharedPhotoReady"
|
private static let sharedPhotoReadyKey = "sharedPhotoReady"
|
||||||
|
|
||||||
/// Get the App Group container URL for accessing shared files
|
/// Get the App Group container URL for accessing shared files
|
||||||
@@ -96,7 +97,42 @@ public class SharedImageUtility {
|
|||||||
let fileURL = containerURL.appendingPathComponent(filePath)
|
let fileURL = containerURL.appendingPathComponent(filePath)
|
||||||
return FileManager.default.fileExists(atPath: fileURL.path)
|
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
|
* Check if shared photo ready flag is set
|
||||||
* This flag is set by the Share Extension when image is ready
|
* This flag is set by the Share Extension when image is ready
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ class ShareViewController: UIViewController {
|
|||||||
private let sharedPhotoFileNameKey = "sharedPhotoFileName"
|
private let sharedPhotoFileNameKey = "sharedPhotoFileName"
|
||||||
private let sharedPhotoFilePathKey = "sharedPhotoFilePath"
|
private let sharedPhotoFilePathKey = "sharedPhotoFilePath"
|
||||||
private let sharedPhotoShareIdKey = "sharedPhotoShareId"
|
private let sharedPhotoShareIdKey = "sharedPhotoShareId"
|
||||||
|
private let shareExtensionLastStartKey = "shareExtensionLastStart"
|
||||||
private let sharedImageFileName = "shared-image"
|
private let sharedImageFileName = "shared-image"
|
||||||
|
|
||||||
/// Get the App Group container URL for storing shared files
|
/// Get the App Group container URL for storing shared files
|
||||||
@@ -22,6 +23,13 @@ class ShareViewController: UIViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override func viewDidLoad() {
|
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")
|
print("[ShareTarget] viewDidLoad started")
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { WebPlugin } from "@capacitor/core";
|
import { WebPlugin } from "@capacitor/core";
|
||||||
import type { SharedImagePlugin, SharedImageResult } from "./definitions";
|
import type {
|
||||||
|
SharedImagePlugin,
|
||||||
|
SharedImageResult,
|
||||||
|
ShareExtensionDiagnostics,
|
||||||
|
} from "./definitions";
|
||||||
|
|
||||||
export class SharedImagePluginWeb
|
export class SharedImagePluginWeb
|
||||||
extends WebPlugin
|
extends WebPlugin
|
||||||
@@ -18,4 +22,13 @@ export class SharedImagePluginWeb
|
|||||||
async hasSharedImage(): Promise<{ hasImage: boolean }> {
|
async hasSharedImage(): Promise<{ hasImage: boolean }> {
|
||||||
return { hasImage: false };
|
return { hasImage: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getShareExtensionDiagnostics(): Promise<ShareExtensionDiagnostics> {
|
||||||
|
return {
|
||||||
|
shareExtensionLastStart: null,
|
||||||
|
sharedPhotoShareId: null,
|
||||||
|
sharedPhotoFilePath: null,
|
||||||
|
fileExists: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,13 @@ export interface SharedImageResult {
|
|||||||
fileName: string;
|
fileName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ShareExtensionDiagnostics {
|
||||||
|
shareExtensionLastStart: string | null;
|
||||||
|
sharedPhotoShareId: string | null;
|
||||||
|
sharedPhotoFilePath: string | null;
|
||||||
|
fileExists: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface SharedImagePlugin {
|
export interface SharedImagePlugin {
|
||||||
/**
|
/**
|
||||||
* Get shared image data from native layer
|
* Get shared image data from native layer
|
||||||
@@ -20,4 +27,9 @@ export interface SharedImagePlugin {
|
|||||||
* Useful for quick checks before calling getSharedImage()
|
* Useful for quick checks before calling getSharedImage()
|
||||||
*/
|
*/
|
||||||
hasSharedImage(): Promise<{ hasImage: boolean }>;
|
hasSharedImage(): Promise<{ hasImage: boolean }>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Diagnostic snapshot of Share Extension startup and pending share state (iOS)
|
||||||
|
*/
|
||||||
|
getShareExtensionDiagnostics(): Promise<ShareExtensionDiagnostics>;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user