WIP: iOS Share Target Reliability #235

Draft
jose wants to merge 31 commits from fix/ios-share-target-reliability into master
5 changed files with 80 additions and 3 deletions
Showing only changes of commit 498a4926bf - Show all commits

View File

@@ -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())
}
}

View File

@@ -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

View File

@@ -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()

View File

@@ -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<ShareExtensionDiagnostics> {
return {
shareExtensionLastStart: null,
sharedPhotoShareId: null,
sharedPhotoFilePath: null,
fileExists: false,
};
}
}

View File

@@ -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<ShareExtensionDiagnostics>;
}