Adds the reverse direction: share FROM Photos/Files/Safari INTO a Biz Connect conversation. An app can only appear in the iOS share sheet as an app-extension target, so this is real native work, not a web change. Pieces: - mobile/ios-share/ShareViewController.swift: a UI-less Share Extension. It stages the shared items into the App Group container and opens bizconnect://share. It deliberately does NOT reimplement the chat picker — that lives in the app, which already has the chat list, search and upload progress. Appends to the manifest (never overwrites), so sharing twice before opening the app loses nothing. - mobile/scripts/add-share-extension.rb: injects the extension target into the Capacitor-generated Xcode project on every CI build (Codemagic checks out fresh), using the xcodeproj gem that ships with CocoaPods. Embeds it, sets the bundle id <app>.share, and MERGES the App Group into the app's entitlements rather than clobbering them (push's aps-environment must survive). Idempotent. - mobile/plugins/share-inbox: getPending()/clear() to read that manifest — the App Group container isn't one of Filesystem's known directories, so it needs a bridge. - home.html: on bizconnect://share (and every resume, and cold-launch), read the inbox and show a "Send to…" picker over the chat list; chosen files run the SAME upload + /api/messages send as an in-app attachment. Reuses convertFileSrc to read the staged bytes with no base64 marshalling. - ios-patch.sh registers the bizconnect URL scheme; codemagic.yaml fetches a profile for the .share bundle id too. One-time manual gate (CI cannot toggle App capabilities): the App Group group.com.bizgaze.connect must be created and enabled on both App IDs in the Apple portal — documented in mobile/IOS_SETUP.md. Without it the two processes can't see each other's files and sharing silently no-ops; everything else still works. Validated cross-file: pod-name/jsName/method wiring for all three plugins, App Group id identical in all 4 files, URL scheme consistent across extension/plist/web, entitlement-merge preserves push. Needs a new iOS build (new targets + plugins). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
7.4 KiB
Biz Connect — iOS App Store setup (Codemagic, no Mac needed)
The iOS app is a Capacitor shell that loads the live Connect web UI (https://remote.bizgaze.com).
Building/signing/uploading happens on Codemagic's macOS cloud — you never need a Mac.
Bundle id: com.bizgaze.connect · CI config: codemagic.yaml (repo root).
Step 0 — Register the App ID (Identifiers → + → App IDs → App)
On the Register an App ID page, only three fields matter — leave everything else default:
- Platform: leave as-is (the default
iOS, iPadOS, macOS…combined App ID is fine). - Description:
Biz Connect(label only; no@ & * "). - Bundle ID: keep Explicit →
com.bizgaze.connect. - Capabilities: tick Push Notifications only. Leave all others unchecked. (Camera/mic are NOT here — they're Info.plist runtime strings, added by the build pipeline.)
- Continue → Register. (The App ID Prefix shown is your Team ID — note it for Step 5's APNs.)
Step 1 — App Store Connect: create the app record
- appstoreconnect.apple.com → Apps → + → New App.
- Platform iOS, Name Biz Connect, primary language, Bundle ID =
com.bizgaze.connect(the App ID you registered in Step 0 now appears in the dropdown). - SKU: anything unique (e.g.
bizconnect-ios). Create.
Step 2 — App Store Connect API key (for Codemagic to sign + upload)
- App Store Connect → Users and Access → Integrations → App Store Connect API → +.
- Access App Manager. Generate. Note the Issuer ID (top of the page) and the key's Key ID,
and download the
.p8(you can only download it once).
Step 3 — Codemagic: connect + add the key
- codemagic.io → sign in with the git provider → add this repository.
- Teams → Integrations → App Store Connect → Connect, upload the
.p8, paste the Issuer ID and Key ID. Name it exactlyBizGaze App Store Connect(thecodemagic.yamlreferences that name). - Codemagic detects
codemagic.yaml. That's all the signing setup — automatic signing creates the distribution certificate + provisioning profile from this key on the first build.
Step 4 — Run the build
- Codemagic → the app → Start new build → workflow "Biz Connect iOS → TestFlight".
- ~10–15 min. On success the build appears in App Store Connect → TestFlight.
- Add yourself under TestFlight → Internal Testing to install via the TestFlight app on your iPhone.
Step 5 — Push notifications (APNs) — do this once, then tell me
So the app gets calls/messages while it's closed:
- developer.apple.com → Keys → + → enable Apple Push Notifications service (APNs) → download the
.p8. Note its Key ID and your Team ID (top-right of the developer portal). - Send me: the
.p8contents, the Key ID, and the Team ID. I set these in the server.env(server-side only, like the LiveKit/Giphy keys):The APNs sender is already built into the server — it's a no-op until these are set.APNS_KEY=<contents of the .p8> APNS_KEY_ID=<key id> APNS_TEAM_ID=<team id> APNS_BUNDLE_ID=com.bizgaze.connect APNS_PRODUCTION=1
Step 6 — Public App Store submission (when you're ready to leave TestFlight)
In App Store Connect, fill the listing: screenshots (6.7" + 6.1" iPhone), description, keywords,
support URL, and a Privacy Policy URL (required). Complete the App Privacy questionnaire (we
collect account info + usage for chat/calls). Then submit for review (or flip submit_to_app_store in
codemagic.yaml).
App Review note (Guideline 4.2 — "Minimum Functionality")
Apple scrutinises apps that look like "just a website". Ours passes because it ships real native capabilities — push notifications, camera/microphone for calls, photo sharing. Make sure push (Step 5) is live before the public submission, and in the reviewer notes mention the native video/voice calling + push notifications. Do not advertise "share your screen" as an iOS feature in the store listing yet — see the follow-up below (you can still view a screen someone else shares).
Known iOS limitations & follow-ups (phase 2 — after TestFlight)
1. Sharing YOUR iOS screen into a meeting → needs a ReplayKit Broadcast Upload Extension
- Why: the app's screen share uses the web
getDisplayMediaAPI, which iOS WebViews and Safari do not support. Apple only allows capturing the device screen via ReplayKit. - What works today on iOS: viewing a screen another participant shares (it's just incoming video), chat, voice/video calls, camera, photo sharing.
- What's needed to broadcast the iOS screen: a native Broadcast Upload Extension target that captures frames via ReplayKit and feeds them into the LiveKit/WebRTC session, plus the App Groups capability (to pass data between the app and the extension). This is native Swift work — NOT part of the Capacitor wrapper — so it's tracked as a separate task, done after the app is on TestFlight.
- Store impact: don't claim iOS screen-sharing in the listing until this ships, or a reviewer may test it and it will fail.
2. Native mobile audio routing (speaker / earpiece / Bluetooth) — needs a Capacitor audio plugin
- Mobile web can't switch the audio output route (
setSinkIdis unimplemented on iOS/Android), so the in-meeting speaker/earpiece/Bluetooth control is web-only where it works and hidden where it doesn't. - True routing on iOS needs a small native plugin driving
AVAudioSession. Phase-2 native task.
Share Extension ("Biz Connect" in the iOS share sheet) — one-time Apple portal setup
The app now has a Share Extension target (com.bizgaze.connect.share) so users can share a photo /
video / file FROM the Photos or Files app INTO a Biz Connect conversation. The Codemagic build injects the
target and fetches a profile for it automatically, but two things can ONLY be done once, by hand, in the
Apple Developer portal — CI cannot toggle App capabilities:
- Create the App Group (developer.apple.com → Identifiers → App Groups → +):
identifier
group.com.bizgaze.connect. - Enable the App Groups capability on BOTH App IDs and assign them to that group:
com.bizgaze.connect(the app)com.bizgaze.connect.share(the extension — create this App ID if the first build hasn't yet;fetch-signing-files --createwill register it, then edit it to add App Groups) After enabling the capability, the provisioning profiles must be regenerated — the next Codemagic build does that viafetch-signing-files, so just re-run it once the capability is on.
If the App Group isn't set up, the app and the extension can't see each other's files: sharing will appear to do nothing (the extension stages the file, but the app finds an empty inbox). Everything else — download to the Files folder, the Photos "Connect" album, Manage storage — works without it.
Also enabled by this change (main app Info.plist, done automatically by ios-patch.sh):
UIFileSharingEnabled+LSSupportsOpeningDocumentsInPlace→ the Biz Connect folder in Files.CFBundleURLTypesschemebizconnect→ lets the extension bounce back into the app after staging.