Add doc/share-target-ios-launch-flow-audit.md documenting the iOS
Share Extension launch path from openMainApp("timesafari://") through
the native AppDelegate, Capacitor bridge, and JS bootstrap to
/shared-photo navigation.
Covers cold- vs warm-start execution order, the single appUrlOpen
listener and its call graph, all shared-image detection mechanisms
(startup timer, appStateChange, applicationDidBecomeActive,
sharedPhotoReady flag, SharedPhotoReady notification), native launch-URL
handling, and a timing analysis of the race conditions.
Key findings: cold-start shares rely on the T+1000ms startup timer
reading the App Group payload (not appUrlOpen, which registers at
T+2000ms after the launch URL is delivered); warm-start shares are
driven by appUrlOpen/appStateChange; the launch URL event and the
SharedPhotoReady notification can be lost before JS is ready, but the
durable App Group payload is not. Audit only; no code changes.
Surface the complete Share Extension execution trace during app startup
so the cold-start share path can be inspected even when Xcode truncates
console output.
In checkForSharedImageAndNavigate(), after the existing diagnostics
call, retrieve SharedImage.getShareExtensionTrace() and:
- log the full untruncated trace between TRACE FULL START/END markers
- show the full trace in a user-visible alert (iOS only)
- log TRACE LENGTH and the first 500 characters
Share-target behavior is unchanged and the trace work is gated to iOS,
so Android is unaffected. All additions are marked with
"TEMPORARY SHARE TARGET DIAGNOSTICS".
Add a lightweight, temporary trace logger to diagnose where the iOS
Share Extension stops executing during a failed cold-start share.
- ShareViewController: add appendTrace() helper that writes ISO8601-
prefixed lines to share-extension-trace.log in the App Group
container, ignoring failures (diagnostics only)
- Add trace entries across the share flow: viewDidLoad,
processAndOpenApp, processSharedImage, image attachment/load,
storeImageData, setSharedPhotoReadyFlag, openMainApp, completeRequest
- SharedImageUtility: add getShareExtensionTrace() (read-only) and
clearShareExtensionTrace() (deletes the trace file)
- SharedImagePlugin: expose getShareExtensionTrace() and
clearShareExtensionTrace() to JS
- definitions.ts / SharedImagePlugin.web.ts: add ShareExtensionTrace
type, method signatures, and web stubs
Share behavior is unchanged and Android is untouched. All additions are
marked with "TEMPORARY SHARE TARGET DIAGNOSTICS".
Extend ShareExtensionDiagnostics with pendingShareExists across
SharedImageUtility, definitions, and the web stub, and log cold-start
state (pending share + current route) in the iOS startup share check.
Document App/extension entitlements, bundle IDs, teams, and signing,
flagging a code-vs-entitlement App Group ID mismatch (code uses
group.app.timesafari.share while entitlements grant
group.app.trentlarson.timesafari.share) that breaks shared storage.
Document that TimeSafariShareExtension is a code-based extension with
ShareViewController as NSExtensionPrincipalClass, confirm viewDidLoad
executes on launch, and note no blocking Info.plist/storyboard mismatches.
Write shareExtensionLastStart on ShareViewController.viewDidLoad and
expose getShareExtensionDiagnostics() through SharedImagePlugin with
shareId, file path, and fileExists for debugging failed share flows.
Log start/end, shareId, attachment counts, UTType, byte counts, filenames,
and every early return across viewDidLoad through completeRequest to trace
how far a share progresses when debugging failures.
Log shareId, sharedPhotoFilePath, metadataExists, and fileExists at the
start of getSharedImageData() and hasSharedImage() to debug pending
App Group shares without changing retrieval behavior.
Stop deleting App Group metadata and image files in getSharedImageData()
so retrieval is read-only while preserving the existing plugin API shape.
Document removed deletion paths in the iOS share target audit.
Store shared images as <shareId>.<ext> in the App Group container while
keeping the original filename in metadata, preventing on-disk collisions
without changing retrieval, deletion, or JS consumer behavior.
Generate a UUID per incoming share in the Share Extension, persist it
as sharedPhotoShareId in App Group metadata, and add [ShareTarget] logs
for receive/store/retrieve events without changing retrieval or deletion.
Document the Share Extension → App Group → main app flow, including
read/write/delete points, startup detection hooks, timing behavior,
and race conditions to support share-target reliability work.
Replace the floating circular plus FAB with a full-width bottom bar that
matches the inline Thank button. Wrap the quick-action section in a styled
container and raise the scroll threshold to 120px.
Gitignored AppIcon.appiconset and Splash.imageset are absent after clone,
which made `capacitor-assets generate --ios` fail (missing paths and
Contents.json). Add ensure_ios_capacitor_asset_directories in common.sh
to mkdir and seed minimal Contents.json when needed; call it from
build-ios.sh before asset generation and from the build:native npm script.
Document the behavior in ios/.gitignore.
Restructure the quick start with Web, Android, and iOS subheadings; put
each npm command in its own code block; fold the test-page step into the
Web section. Document Android (build:android:test:run + ADB, link to
BUILDING.md) and iOS (build:ios:studio + Xcode prerequisites).
Use generic/platform=iOS Simulator instead of a fixed device name so CLI builds
do not fail when that simulator is not installed (e.g. newer Xcode runtimes).
Pass -quiet to xcodebuild and enable SWIFT_SUPPRESS_WARNINGS plus
GCC_WARN_INHIBIT_ALL_WARNINGS for scripted builds and IPA archive/export so
terminal output stays smaller; full diagnostics remain available in Xcode.