Files
edgeever/apps/ios
Dariusz Koryto 80dadb3194 feat(i18n): add Polish as an in-app locale (#473)
* feat(editor): add setting to turn off spellcheck underlines

Add a device-local "Underline spelling mistakes" switch to the editing
preferences. The rich-text editor and the mobile plain-text editor now
set spellcheck from this preference and update live when it changes.
Defaults to enabled, so existing behavior is unchanged.

Refs #468

* feat(i18n): add Polish as an in-app locale

Add Polish (pl) across clients, mirroring how Japanese was added:

- Shared: full pl catalog, locale matching for pl/pl-*, Polish memo
  templates and factory AI prompts, mobile editor strings, and Polish as
  an AI translation target and selection-translate chip.
- Web: "Polski" in the language picker; the catalog is lazy-loaded in its
  own i18n-pl chunk and kept out of the PWA precache like ja.
- Android: pl locale option, mobile-only strings, web-clip labels.
  Messages that only had an English branch now use English for every
  non-Chinese locale, so Japanese no longer falls back to Chinese there.
- iOS: .polish UI language (pl-PL), pl argument for every t() call,
  pl in CFBundleLocalizations and Localizable.xcstrings.
- Companion: accepts locale "pl" and detects Polish requests.
- Browser extension: _locales/pl messages.
- Marketing site: /pl/ pages, hreflang, sitemap, language switcher.
- Google Play listing copy for pl-PL (manual publish only).

* fix(ios): show the note editor in Polish and Japanese

The iOS editor received every interface language except English as
Chinese, so with Polish or Japanese selected its toolbar and image
gallery controls were labeled in Chinese. Pass Polish and Japanese
through to the embedded editor, label its toolbar and the shared image
gallery controls in both languages, and rebuild the checked-in
EditorBundle. The Android editor uses the same gallery labels.

Also translate the last iOS strings that had no Polish text: the
follow-system language label, note created/updated times and the
current-device marker.

Refs #473

* fix(companion): recognize Polish typed without diacritics

Requests in Latin letters without Polish diacritics were always treated
as English, so with a Polish interface "Napisz plan na jutro" got an
English reply. With a Polish interface, such text is now told apart by
common English and Polish words; when it is still unclear, the recent
conversation and then the interface language decide. Other interface
languages keep treating Latin text as English.

Refs #473

* chore(ios): regenerate the Xcode project for Polish

Run xcodegen so the shipped Info.plist lists Polish in
CFBundleLocalizations and the project knows the pl region. The
hand-written AiDirectStream.swift entries are replaced by the IDs
xcodegen generates. MARKETING_VERSION and CURRENT_PROJECT_VERSION stay
in the project file because the release script and Xcode Cloud update
them there.

Refs #473

* i18n(pl): translate the sidebar shortcut, desktop menus and video scope

Add Polish for features that reached main while this branch was open:
the show/hide sidebar shortcut label, the desktop application and
editing context menus, and the new "ai:generate" MCP scope. The desktop
menus switch to Polish for pl and pl-* locales; other locales are
unchanged.

Refs #473
2026-10-06 16:18:38 +08:00
..
2026-10-05 12:01:32 +08:00

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 — docs/ios-xcode-cloud.md. Formal Releases start Cloud through store-delivery.

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

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). Formal Releases start Cloud through store-delivery; keep the Cloud workflow start condition Manual so git pushes do not consume hours.

  • 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.sh auto-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