Add a native iOS markProcessed(shareId) method to the SharedImage plugin that records an explicit completion signal in App Group UserDefaults (sharedPhotoProcessedShareId) and logs "[ShareTarget] shareId=<id> marked processed". The API is exposed to TypeScript via the plugin definitions and a web no-op stub. Deliberately does not delete files or clear share metadata (cleanup is deferred to a later phase), is not yet called from application code, and does not touch Android. Documents the share-target lifecycle and plugin API in doc/share-target-ios-audit.md.
3.5 KiB
iOS Share Target Audit
Date: 2026-06-30 Platform: iOS only (Android unchanged) Status: Phase 1D complete — explicit share completion API added (not yet called)
Purpose
This document tracks the native iOS share-target lifecycle and the Capacitor API surface exposed to the web/TypeScript layer. It is updated as each phase lands.
Lifecycle Overview
- The Share Extension (
ShareViewController.swift) receives an image, writes it to the App Group container, records metadata in App GroupUserDefaults, assigns ashareId(UUID), sets thesharedPhotoReadyflag, and opens the main app viatimesafari://. - The main app reads the shared image through the
SharedImageCapacitor plugin. - The application layer processes the image, then (in a future phase) signals
explicit completion via
markProcessed(shareId).
App Group Storage Keys
Stored in UserDefaults(suiteName: "group.app.trentlarson.timesafari.share"):
| Key | Set by | Meaning |
|---|---|---|
sharedPhotoFileName |
Share Extension | Original display filename |
sharedPhotoFilePath |
Share Extension | On-disk filename in App Group container |
sharedPhotoShareId |
Share Extension | Current pending share identifier (UUID) |
sharedPhotoReady |
Share Extension | Flag indicating a share is ready |
sharedPhotoProcessedShareId |
Main app (markProcessed) |
Last shareId explicitly marked processed (Phase 1D) |
Capacitor API (SharedImage plugin)
The plugin is registered as SharedImage and is implemented in:
- Native iOS:
ios/App/App/SharedImagePlugin.swift(delegates toios/App/App/SharedImageUtility.swift) - Web stub:
src/plugins/SharedImagePlugin.web.ts - TypeScript definitions:
src/plugins/definitions.ts
getSharedImage(): Promise<SharedImageResult | null>
Returns the shared image as { base64, fileName }, or null if none exists.
Read-only: native metadata and the file are left intact after retrieval
(Phase 1C).
hasSharedImage(): Promise<{ hasImage: boolean }>
Returns whether a shared image file currently exists, without reading it.
markProcessed(options: { shareId: string }): Promise<{ success: boolean }> — Phase 1D
Explicit completion signal from the application layer for a given share.
- Input:
shareId— the identifier reported bygetSharedImage(). Must be a non-empty string; otherwise the call rejects. - Behavior (iOS): Records
shareIdin App GroupUserDefaultsundersharedPhotoProcessedShareIdand resolves with{ success: true }. - Does NOT delete files: The stored image file and share metadata are intentionally left intact. File cleanup is deferred to a later phase.
- Web: No-op; resolves with
{ success: false }. - Logging: Emits
[ShareTarget] shareId=<id> marked processedon success.
Note (Phase 1D):
markProcessedis implemented and exposed to TypeScript but is not yet called from application code. Wiring it into the processing flow is a later phase.
Native Logging Reference
Relevant [ShareTarget] log lines emitted on iOS:
[ShareTarget] shareId=<id> retrieved[ShareTarget] shareId=<id> left intact after retrieval[ShareTarget] shareId=<id> marked processed(Phase 1D)
Out of Scope
- Android: no changes. The Android plugin
(
android/app/src/main/java/app/timesafari/sharedimage/SharedImagePlugin.java) does not implementmarkProcessed. - File deletion / cleanup of processed shares.
- Calling
markProcessedfrom application code.