Files
crowd-funder-for-time-pwa/doc/ios-share-implementation-status.md
Jose Olarte III ae49c0e907 feat(ios): implement native share target for images
Implement iOS Share Extension to enable native image sharing from Photos
and other apps directly into TimeSafari. Users can now share images from
the iOS share sheet, which will open in SharedPhotoView for use as gifts
or profile pictures.

iOS Native Implementation:
- Add TimeSafariShareExtension target with ShareViewController
- Configure App Groups for data sharing between extension and main app
- Implement ShareViewController to process shared images and convert to base64
- Store shared image data in App Group UserDefaults
- Add ShareImageBridge utility to read shared data from App Group
- Update AppDelegate to handle shared-photo deep link and bridge data to JS

JavaScript Integration:
- Add checkAndStoreNativeSharedImage() in main.capacitor.ts to read shared
  images from native layer via temporary file bridge
- Convert base64 data to data URL format for compatibility with base64ToBlob
- Integrate with existing SharedPhotoView component
- Add "shared-photo" to deep link validation schema

Build System:
- Integrate Xcode 26 / CocoaPods compatibility workaround into build-ios.sh
- Add run_pod_install_with_workaround() for explicit pod install
- Add run_cap_sync_with_workaround() for Capacitor sync (which runs pod
  install internally)
- Automatically detect project format version 70 and apply workaround
- Remove standalone pod-install-workaround.sh script

Code Cleanup:
- Remove verbose debug logs from ShareViewController, AppDelegate, and
  main.capacitor.ts
- Retain essential logger calls for production debugging

Documentation:
- Add ios-share-extension-setup.md with manual Xcode setup instructions
- Add ios-share-extension-git-commit-guide.md for version control best practices
- Add ios-share-implementation-status.md tracking implementation progress
- Add native-share-target-implementation.md with overall architecture
- Add xcode-26-cocoapods-workaround.md documenting the compatibility issue

The implementation uses a temporary file bridge (AppDelegate writes to Documents
directory, JS reads via Capacitor Filesystem plugin) as a workaround for
Capacitor plugin auto-discovery issues. This can be improved in the future by
properly registering ShareImagePlugin in Capacitor's plugin registry.
2025-11-24 20:46:58 +08:00

3.4 KiB

iOS Share Extension Implementation Status

Date: 2025-01-27
Status: In Progress - Native Code Complete, Bridge Pending

Completed

Share Extension Files Created:

  • ios/App/TimeSafariShareExtension/ShareViewController.swift - Handles image sharing
  • ios/App/TimeSafariShareExtension/Info.plist - Extension configuration

Native Bridge Created:

  • ios/App/App/ShareImageBridge.swift - Native method to read from App Group

JavaScript Integration Started:

  • src/services/nativeShareHandler.ts - Service to handle native shared images
  • src/main.capacitor.ts - Updated to check for native shared images on deep link

Documentation:

  • doc/native-share-target-implementation.md - Complete implementation guide
  • doc/ios-share-extension-setup.md - Xcode setup instructions

Pending

⚠️ Xcode Configuration (Manual Steps Required):

  1. Create Share Extension target in Xcode
  2. Configure App Groups for both main app and extension
  3. Add ShareImageBridge.swift to App target
  4. Build and test

⚠️ JavaScript-Native Bridge: The current implementation has a placeholder for calling the native ShareImageBridge.getSharedImageData() method from JavaScript. This needs to be completed using one of:

Option A: Minimal Capacitor Plugin (Recommended for Option 1)

  • Create a small plugin that exposes the method
  • Clean and maintainable
  • Follows Capacitor patterns

Option B: Direct Bridge Call

  • Use Capacitor's executePlugin or similar mechanism
  • Requires understanding Capacitor's internal bridge
  • Less maintainable

Option C: AppDelegate Integration

  • Have AppDelegate check on launch and expose via a different mechanism
  • Workaround approach
  • Less clean but functional

Next Steps

  1. Complete Xcode Setup:

    • Follow doc/ios-share-extension-setup.md
    • Create Share Extension target
    • Configure App Groups
    • Build and verify extension appears in share sheet
  2. Implement JavaScript-Native Bridge:

    • Choose one of the options above
    • Complete the checkAndStoreNativeSharedImage() function in main.capacitor.ts
    • Test end-to-end flow
  3. Testing:

    • Share image from Photos app
    • Verify Share Extension appears
    • Verify app opens and displays shared image
    • Test "Record Gift" and "Save as Profile" flows

Current Flow

  1. User shares image → Share Extension receives
  2. Share Extension converts to base64
  3. Share Extension stores in App Group UserDefaults
  4. Share Extension opens app with timesafari://shared-photo?fileName=...
  5. ⚠️ App receives deep link (handled)
  6. ⚠️ App checks App Group UserDefaults (bridge needed)
  7. ⚠️ App stores in temp database (pending bridge)
  8. SharedPhotoView reads from temp database (already works)

Code Locations

  • Share Extension: ios/App/TimeSafariShareExtension/
  • Native Bridge: ios/App/App/ShareImageBridge.swift
  • JavaScript Handler: src/services/nativeShareHandler.ts
  • Deep Link Integration: src/main.capacitor.ts
  • View Component: src/views/SharedPhotoView.vue (already complete)

Notes

  • The Share Extension code is complete and ready to use
  • The main missing piece is the JavaScript-to-native bridge
  • Once the bridge is complete, the entire flow should work end-to-end
  • The existing SharedPhotoView.vue doesn't need changes - it already handles images from temp storage