Editors now take document TipTap nodes from a shared factory. Workspace and editor helpers move out of the large panes. Store iOS no longer builds from Expo EAS.
EdgeEver iOS (Swift)
Native SwiftUI client for EdgeEver. This replaces the React Native / Expo iOS target.
App Store binaries on macOS beta: use Xcode Cloud (manual) — docs/ios-xcode-cloud.md.
Status
UI/interaction is aligned with the Android RN app (apps/mobile):
- Login / session (Keychain with UserDefaults fallback) / device id
- GRDB local mirror + bootstrap / incremental sync
- SQLite outbox (create/update, create-absorbs-update, conflict/retry)
- Workspace chrome: notebook title picker, search (250ms debounce), filter chips, list options (sort/density/batch), FAB create, long-press multi-select, swipe pin/delete
- Memo detail + create/edit autosave, share link, revisions, soft delete
- EditorBundle (WKWebView body + toolbar)
- Image pick + materialize-for-upload (K24) + protected resource blob loading
- Settings: general / account / tags / API tokens / devices / users (owner) / about
- Share Extension (text/URL → App Group → new draft)
- Locale (system/zh/en) + theme + list density
Android remains Expo / React Native in apps/mobile. Store builds for iOS use this native tree (Scripts/archive-app-store.sh), not EAS.
Motion / animations
Motion stack: SwiftUI Animation (timing / springs) + Pow (Emerge).
| Effect | Where |
|---|---|
| Jump (physics hop + squash) | First list open (whole list); create/edit return on that memo |
| Boing (elastic drop-in) | Staggered first-paint cards |
| Ping | Create button / returned memo highlight |
| Shine / Shake / Haptic | Pin success, errors, selection |
| SwiftUI scale press | Card / create / filter finger-down |
Curves & wrappers: EdgeEver/DesignSystem/Motion.swift.
Requirements
- Xcode 16+ (Xcode 27 beta OK for local dev)
- iOS 17+ deployment target
- XcodeGen to regenerate the project
brew install xcodegen
Generate & open
cd apps/ios
xcodegen generate
open EdgeEver.xcodeproj
Tests
# Unit + live API tests (live tests skip if local server is down)
xcodebuild test \
-project EdgeEver.xcodeproj \
-scheme EdgeEver \
-destination 'platform=iOS Simulator,name=iPhone 17 Pro'
Live API tests login to http://127.0.0.1:8787 using EDGE_EVER_AUTH_PASSWORD or monorepo .env.wrangler.generated.local.
Simulator auto-login (QA)
With local bun run dev running:
xcrun simctl launch booted org.edgeever.mobile \
-EdgeEverAutoLoginURL "http://127.0.0.1:8787" \
-EdgeEverAutoLoginUser admin \
-EdgeEverAutoLoginPassword "$EDGE_EVER_AUTH_PASSWORD"
Versioning
| Field | File | Notes |
|---|---|---|
MARKETING_VERSION |
Config/Version.xcconfig |
Align with monorepo release X.Y.Z on store submissions |
CURRENT_PROJECT_VERSION |
Config/Version.xcconfig |
Local floor for build numbers |
Xcode Cloud stamps CFBundleVersion from App Store Connect → Xcode Cloud → Build Number (not only this file). Before a Cloud store run, set that counter above the latest ASC build (Scripts/ensure-xcode-cloud-build-number.sh prints the recommended value).
App Store archive
Preferred: Xcode Cloud (manual only)
If the Mac runs macOS beta, local archives are rejected by App Store Connect (ITMS-90111) even with release Xcode. Day-to-day development stays local; only store / TestFlight binaries should use Xcode Cloud (25 compute hours/month with Apple Developer Program).
- Setup and workflow:
docs/ios-xcode-cloud.md - Cloud hooks:
ci_scripts/ci_post_clone.sh→ci_pre_xcodebuild.sh→ci_post_xcodebuild.sh - Workflow start condition must stay Manual so hours are not burned on every push
- Put ASC API secrets in Xcode Cloud shared environment variables so
ci_post_xcodebuild.shauto-uploads the App Store IPA
# Before Start Build (optional but recommended)
cd apps/ios
bash Scripts/ensure-xcode-cloud-build-number.sh
# If Cloud produced ARCHIVE_EXPORT but ASC has no build:
bash Scripts/upload-app-store-ipa.sh /path/to/EdgeEver-*-app-store.zip
Local archive (release macOS only)
Use the stable Xcode app (not beta) on a non-beta host OS:
cd apps/ios
DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer bash Scripts/archive-app-store.sh
bash Scripts/upload-app-store-ipa.sh build/export/EdgeEver.ipa
On a beta host the script exits unless you set EDGE_EVER_IOS_ALLOW_BETA_HOST=1 (upload will still likely fail ASC).
Signing in the Xcode project is Automatic (Cloud-friendly). Local export still uses ExportOptions.plist with App Store profiles. Then submit the exact build with:
cd apps/ios
APP_STORE_VERSION=X.Y.Z APP_STORE_BUILD_NUMBER=N \
APP_STORE_CONNECT_API_KEY_ID=... \
APP_STORE_CONNECT_API_ISSUER_ID=... \
APP_STORE_CONNECT_API_KEY_P8_BASE64=... \
fastlane ios submit_review
Regenerating the Xcode project
Edit project.yml, then:
xcodegen generate