# Rebreak Native (React Native + Expo) > Mobile App für iOS + Android. Migration von Nuxt+Capacitor → React Native+Expo. > Migration-Plan: [`apps/rebreak/docs/react-native-migration.md`](../rebreak/docs/react-native-migration.md) ## Status **Phase 1 — Foundation Skeleton** (2026-05-02) - [x] Verzeichnisstruktur - [x] `package.json` mit Expo SDK 53 + RN 0.76 (New Architecture) - [x] `app.config.ts` (Expo, Bundle-ID `org.rebreak.app`) - [x] Expo Router Skeleton - [x] NativeWind Setup (Tailwind für RN) - [x] Metro Config (pnpm Monorepo aware) - [x] Supabase Client + API Wrapper - [ ] `pnpm install` — vom User auszuführen - [ ] `expo prebuild` — generiert `ios/` + `android/` Bare-Projekte - [ ] Native Module Imports (NEFilter, VpnService, A11y) — Phase 5+ ## Setup ```bash # vom Monorepo-Root: pnpm install # Native-Projekte generieren (lokal, nicht committed) cd apps/rebreak-native pnpm prebuild # Run pnpm ios # iOS Simulator pnpm android # Android Emulator ``` ## Stack | Bereich | Lib | |---|---| | Framework | React Native 0.76 (New Architecture) + Expo SDK 53 | | Routing | Expo Router (file-based) | | State | Zustand | | Server State | TanStack Query (React Query) | | Styling | NativeWind 4 (Tailwind) | | Forms | React Hook Form + Valibot | | i18n | react-i18next | | Auth | @supabase/supabase-js + AsyncStorage | | Animation | react-native-reanimated, lottie-react-native | | Storage | react-native-mmkv (fast key-value) | ## Verzeichnisstruktur ``` apps/rebreak-native/ ├── app/ # Expo Router (file-based routes) │ ├── _layout.tsx # Root Stack │ ├── index.tsx # Landing (auth oder app entscheiden) │ ├── (auth)/ # Auth-Flow (signin, signup, forgot-password) │ └── (app)/ # Authenticated App (tabs) ├── components/ # Reusable UI Components ├── hooks/ # Custom React Hooks ├── stores/ # Zustand Stores ├── lib/ # Supabase Client, API Wrapper, Utils │ ├── supabase.ts │ └── api.ts ├── locales/ # de.json, en.json ├── modules/ # Custom Expo Native Modules │ ├── rebreak-ios-filter/ # NEFilter + Tunnel (Phase 5) │ ├── rebreak-android-blocker/ # VpnService + DnsFilter (Phase 6) │ └── rebreak-android-a11y/ # AccessibilityService (Phase 6) ├── plugins/ # Expo Config Plugins └── assets/ # Icons, Splashscreens, Fonts ``` ## Dev-Variant (Hot-Reload parallel zur MDM-App) Die MDM-managed Dist-App (`org.rebreak.app`) ist non-removable auf dem iPhone Air. Der Dev-Build nutzt eine separate Bundle-ID (`org.rebreak.app.dev`) und kann parallel installiert werden. ### Erstmaliges Setup (nur einmal nötig) ```bash # 1. Dev-Build starten — schlägt beim ersten Mal wegen Signing-Bundle fehl REBREAK_DEV=1 ./dev-build.sh --clean # Wenn Xcode "No profiles for 'org.rebreak.app.dev'" meldet: # a) open ios/ReBreak.xcworkspace # b) Targets → ReBreak → Signing & Capabilities # c) Team auf "84BQ7MTFYK" setzen — Xcode registriert Bundle-ID automatisch # d) Xcode schliessen, nochmal ausführen: REBREAK_DEV=1 ./dev-build.sh --clean ``` ### Täglicher Workflow ```bash # Vollbuild (nach native-code Änderungen oder erstem Mal): ./dev-build.sh # Nur Metro (wenn Dev-App schon auf iPhone, reine JS-Änderungen): ./dev-build.sh --metro-only # Nuclear clean + rebuild (nach Plugin/Pod-Änderungen): ./dev-build.sh --clean ``` ### Wichtige Unterschiede Dev vs. Dist | | Dev (`org.rebreak.app.dev`) | Dist (`org.rebreak.app`) | |---|---|---| | App-Name | ReBreak Dev | ReBreak | | Splash-Color | #1e3a5f (dunkles Blau) | #0f172a (schwarz) | | URL-Scheme | `rebreak-dev://` | `rebreak://` | | App-Group | `group.org.rebreak.app` (geteilt) | `group.org.rebreak.app` | | Hot-Reload | via Metro | nein | | MDM-managed | nein | ja (non-removable) | App-Group ist bewusst geteilt — Dev-Build kann blocklist.bin lesen und Sideload-Profile-Verhalten testen ohne MDM-Push. ### Prod-Build bleibt unverändert `deploy-adhoc.sh` und `deploy-tf.sh` setzen `REBREAK_DEV` nicht → landen automatisch auf `org.rebreak.app`. ## Wichtige Konfiguration | Datei | Zweck | |---|---| | `app.config.ts` | Expo App-Config (Bundle-ID, Permissions, Plugins) | | `metro.config.js` | Monorepo-aware Metro (Symlinks, Workspace-Folders) | | `babel.config.js` | NativeWind Preset + Reanimated Plugin | | `tailwind.config.js` | Tailwind Config — Brand-Colors aus apps/rebreak/ syncen | | `global.css` | NativeWind Tailwind-Imports | ## Native Module Strategie Bestehender Native-Code aus `apps/rebreak/ios/` + `apps/rebreak/android/` wird in Expo Native Modules gewrappt — **ohne neu zu schreiben**. ### iOS — `modules/rebreak-ios-filter/` Wrapped: - `RebreakURLFilter` (NEFilterDataProvider) → blockt bet365 etc. - `RebreakTunnel` (NEPacketTunnelProvider) → DNS-Filter ### Android — `modules/rebreak-android-blocker/` Wrapped: - `RebreakVpnService` (Kotlin) → VpnService DNS-Filter - `DnsFilter` + `HashList` + `DomainHasher` ### Android — `modules/rebreak-android-a11y/` Wrapped: - `RebreakAccessibilityService` → Detection von Gambling-Apps ## ⚠️ Wichtige Hinweise - **Schutz-Stack bleibt 1:1 erhalten** — Swift- und Kotlin-Code wandert unverändert in `modules/`. - **Backend bleibt** in `apps/rebreak/server/` — RN ruft die gleichen Endpoints. - **Alte Capacitor-App** bleibt deployed bis RN-App im Store ist. - **Kein Auto-Commit** — User entscheidet wann committet wird. ## Release-Pipeline ### Multi-Target Deploy (`deploy-app.sh`) Ein einziges Script baut und deployed alle drei Release-Targets: ```bash # Default: Alle drei Targets (MDM + TestFlight + Android) ./deploy-app.sh --bump # Nur spezifische Targets ./deploy-app.sh --mdm-only # Nur MDM (Ad-Hoc iOS) ./deploy-app.sh --tf-only # Nur TestFlight ./deploy-app.sh --android-only # Nur Android (EAS → Play-Console) # Targets selektiv überspringen ./deploy-app.sh --skip-mdm --bump # TestFlight + Android ./deploy-app.sh --skip-android # Nur iOS (MDM + TF) # Version-Bumping ./deploy-app.sh --bump # iOS buildNumber++, Android versionCode++ ./deploy-app.sh --version 0.4.0 # Explizite SemVer ./deploy-app.sh --android-version-code 15 # Override Android versionCode # Dry-Run (alles simulieren) ./deploy-app.sh --dry-run --bump ``` #### Was passiert pro Target | Target | Pipeline | Output | |---|---|---| | **MDM** | `deploy-adhoc.sh` → xcodebuild → scp upload | MDM-Push via NanoMDM (systemd-watcher) | | **TestFlight** | `deploy-tf.sh` → altool upload | ASC → Internal Testing (~5-15min) | | **Android** | EAS Cloud-Build → Play-Console | Internal-Track (~10-30min Processing) | #### Android-Vorbereitung (einmalig) Android-Submit benötigt `serviceAccountKeyPath` in `eas.json`: 1. Google-Cloud-Service-Account erstellen (Play-Console-Zugriff) 2. JSON-Key downloaden (z.B. `~/secrets/rebreak-play-service-account.json`) 3. In `eas.json` eintragen: ```json "submit": { "production": { "android": { "serviceAccountKeyPath": "~/secrets/rebreak-play-service-account.json", "track": "internal" } } } ``` 4. **NIEMALS committen** (liegt in `.gitignore`) Falls noch nicht konfiguriert → Script bricht mit klarer Fehlermeldung ab. #### Changelog Changelog-Updates erfolgen bei `--bump` automatisch für iOS (via `deploy-adhoc.sh` intern) und Android (via `deploy-app.sh`). ### Alte Scripts (weiterhin nutzbar) - `deploy-adhoc.sh` — MDM (Ad-Hoc iOS) standalone - `deploy-tf.sh` — TestFlight standalone (wiederverwendet xcarchive) - `eas-release.sh` — EAS Cloud-Build (manueller Wrapper, KEIN Version-Bumping) `deploy-app.sh` ist die empfohlene All-in-One-Lösung. ## Phasen-Tracker Siehe Migration-Plan für Details: [`apps/rebreak/docs/react-native-migration.md`](../rebreak/docs/react-native-migration.md)