# VniDrop — native Apple app (iOS / iPadOS / macOS) A native SwiftUI app for Apple platforms, sharing the existing Rust transfer core (`crates/vnidrop`) through UniFFI-generated Swift bindings. The Rust crate is not modified; the Kotlin/Compose app layer is ported to Swift and mirrors the Compose UI screen-for-screen. Android and desktop JVM continue to use `shared/` + Compose. ## Layout ``` apple/ scripts/build-core.sh # builds the Rust core + generates Swift bindings + xcframework VnidropCore/ # local SwiftPM package: xcframework + generated Vnidrop.swift VniDrop/ # SwiftUI app sources App/ # entry point, object graph, root view, environment Core/ # repository, models, preferences, notifications, progress Features/Send|Receive|Approvals|Settings/ UI/Theme|Components|Navigation|Feedback|Shell/ Platform/ # pickers, QR, NFC, share/export, per-OS file services Resources/ # Localizable.xcstrings, Info.plist, entitlements, assets Tests/ # XCTest (ported progress-derivation assertions) Package.swift # builds VniDrop/ as a library for CLI build/test project.yml # XcodeGen spec for the iOS/macOS app target ``` ## Build & run Prerequisites: Xcode, Rust with the Apple targets (`aarch64-apple-ios`, `aarch64-apple-ios-sim`, `x86_64-apple-ios`, `aarch64-apple-darwin`), and `xcodegen` (`brew install xcodegen`). ```bash # 1. Build the Rust core and generate the Swift bindings + xcframework. apple/scripts/build-core.sh debug # or: release (see note below) # 2. Generate the Xcode project. cd apple && xcodegen generate # 3. Open and run, or build from the CLI: open VniDrop.xcodeproj # macOS: xcodebuild -project VniDrop.xcodeproj -scheme VniDrop -destination 'platform=macOS' build # iOS simulator: xcodebuild -project VniDrop.xcodeproj -scheme VniDrop \ -destination 'platform=iOS Simulator,name=iPhone 15' build ``` ## Command-line typecheck & tests `Package.swift` builds the same sources as a library (minus the `@main` entry), so the shared logic can be checked and unit-tested without Xcode: ```bash cd apple swift build # macOS swift test # runs Tests/ (ported progress-derivation assertions) # iOS typecheck: swift build --triple arm64-apple-ios16.0-simulator --sdk "$(xcrun --sdk iphonesimulator --show-sdk-path)" ``` ## Generated / ignored artifacts `build-core.sh` produces build outputs that are gitignored (see `apple/.gitignore`): `VnidropCore/vnidrop.xcframework/`, `VnidropCore/Sources/VnidropCore/Vnidrop.swift`, and `.build-core/`. A clean checkout must run `build-core.sh` before generating or opening the Xcode project. `VniDrop.xcodeproj` itself is generated by XcodeGen from `project.yml` and does not need to be committed. ## Build profile note The default is `debug`. The workspace `[profile.release]` uses thin LTO, which the current macOS toolchain miscompiles into corrupt host proc-macro dylibs ("mis-aligned LINKEDIT string pool"). `build-core.sh` sets `CARGO_PROFILE_DEV_STRIP=none` (matching the existing Gobley Xcode run-script) so debug builds succeed. For a release core, disable LTO for proc-macros/build scripts (e.g. add a `[profile.release.build-override] lto = false` locally) — the Rust crate itself is never changed. ## System frameworks The Rust core (iroh network stack) links `SystemConfiguration`, `Security`, and `libresolv`. These are declared in both `Package.swift` (for CLI build/test) and `project.yml` (for the app target). ## Parity & scope Screens mirror the Compose UI in `shared/`. Two deliberate simplifications: - Empty-state Lottie animations are rendered as SF Symbols (no `lottie-ios` dependency); swap in `lottie-ios` if exact-parity animation is required. - The full diagnostics/telemetry stack (`diagnostics/*`) is stubbed behind `BugReportService` / `DiagnosticsBuildConfig` and lands in a later phase; the UI hides the diagnostics toggle when not compiled in. ```