anydrop/docs/ios-setup.md
ordinarthur 9674b19590
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m14s
feat(ios): Capacitor shell + Share Extension scaffold
Phase 4 (mobile) kickoff. Ships the native iOS wrapper that lets users
share photos/videos from the iOS Share Sheet into AnyDrop — the one
thing the PWA alone cannot do on iOS because Apple still ignores the
Web Share Target API.

Architecture:
- web/ios/ — Capacitor-generated Xcode project pointing the WKWebView
  at https://anydrop.arthurbarre.fr (real web app; only native code
  is the share-in path, so no "thin wrapper" App Store concern).
- AnyDropShare (Share Extension target) — stashes selected items into
  an App Group shared container then opens anydrop://share.
- SharedInboxPlugin (custom Capacitor plugin) — drains that container
  from JS after the URL fires, returning base64 blobs.
- web/src/lib/nativeShare.ts — bridge that rehydrates File objects and
  routes them into the existing /share page flow (same one Android uses).

Xcode-side target registration + signing isn't scriptable; runbook is
in docs/ios-setup.md.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-20 15:59:51 +02:00

65 lines
3.5 KiB
Markdown

# iOS app setup — Xcode steps
The Capacitor shell + Share Extension code are committed. Xcode can't auto-register a new target from disk, so one-time Xcode work is needed before the first build.
## 1. Open the workspace
```bash
cd web
pnpm exec cap sync ios
pnpm exec cap open ios
```
`cap sync` copies the latest web build into `ios/App/App/public` and refreshes config. `cap open` launches Xcode on `ios/App/App.xcworkspace`.
## 2. Configure signing on the App target
- Click the `App` project → `App` target → **Signing & Capabilities**.
- Team: your Apple Developer team.
- Bundle identifier: `fr.arthurbarre.anydrop`.
- Add capability: **App Groups** → create `group.fr.arthurbarre.anydrop`.
- Set the entitlements file to `App/App.entitlements` (already committed).
## 3. Add the Share Extension target
- File → New → Target → iOS → **Share Extension**.
- Product name: `AnyDropShare`.
- Language: Swift.
- Bundle identifier: `fr.arthurbarre.anydrop.Share`.
- **Delete the auto-generated files** Xcode just created (ShareViewController.swift, MainInterface.storyboard, Info.plist).
- In the Project navigator, right-click the `AnyDropShare` group → **Add Files to "App"…** → select the files already in `ios/App/AnyDropShare/`:
- `ShareViewController.swift`
- `Info.plist`
- `AnyDropShare.entitlements`
- With `AnyDropShare` target selected → Build Settings → search `Info.plist File` → set to `AnyDropShare/Info.plist`.
- Build Settings → `Code Signing Entitlements` → set to `AnyDropShare/AnyDropShare.entitlements`.
- **Signing & Capabilities** on the extension target:
- Same team.
- **Add capability → App Groups** → check `group.fr.arthurbarre.anydrop` (same as main app).
- Also remove `MainInterface.storyboard` reference in the extension's Info.plist if Xcode re-added one — we use `ShareViewController` programmatically (`NSExtensionPrincipalClass`), no storyboard.
## 4. Build + run
- Plug in an iPhone (Simulator also works but AirDrop/Messages targets aren't there).
- Select the `App` scheme → pick your device → ⌘R.
- First launch, iOS may ask to trust the developer certificate (Settings → General → VPN & Device Management).
## 5. Test the share flow
1. Open Photos, select one or more images/videos, tap Share.
2. Tap **AnyDrop** in the app row (scroll if needed — you can drag it to the front via "Edit Actions").
3. Extension runs → writes files to the App Group → opens `anydrop://share`.
4. Main app catches the URL → Capacitor fires `appUrlOpen` → JS drains the inbox → `/share` page shows the selected peer list → pick a device → P2P send.
## 6. Ship updates
- **Web changes** (anything under `web/src`): the app loads from `https://anydrop.arthurbarre.fr`, so redeploying the web is enough. No App Store review needed.
- **Native changes** (Swift, Info.plist, entitlements, Capacitor config): rebuild + re-archive + TestFlight or direct install.
## Known gotchas
- **Custom URL scheme requires a real app install.** Testing in Safari or the PWA will not fire `appUrlOpen`.
- **App Group must match exactly** on both targets (`group.fr.arthurbarre.anydrop`). If they diverge, the extension writes and the app reads different directories.
- **Camera/photo permission** prompt appears the first time the extension is used; the copy is in `App/Info.plist` (`NSPhotoLibraryUsageDescription`).
- **Cookies / sessions** in Capacitor's WKWebView are **not** shared with Safari. Users will need to sign in inside the app once.