482 lines
16 KiB
Bash
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# dev.sh — ReBreak Native Development Tooling
#
# Konsolidiert: dev-ios.sh + dev-iphone.sh + metro.sh (alle gelöscht).
#
# SUBCOMMANDS:
# ./dev.sh default: ios --device (physisches iPhone USB + Build)
# ./dev.sh ios iOS Dev (Default: USB-Device mit Build)
# ./dev.sh android Android Dev (Gradle Build + Install + Launch)
# ./dev.sh metro Nur Metro starten
# ./dev.sh clean iOS: Nuclear clean (Pods, DerivedData, Archives)
# ./dev.sh install ios Build Release + Install auf iPhone USB
# ./dev.sh install android Build Debug APK + Install auf Android Device
#
# FLAGS (ios):
# --device Build auf physisches iPhone via USB (DEFAULT)
# --simulator Build auf iOS Simulator
# --xcode Nur Xcode öffnen (manueller Build)
# --wifi Metro mit --host lan (WiFi-Dev, KEIN Native-Build)
# --no-build KEIN Native-Rebuild → nur Metro starten
# (für schnellen UI/JS-Reload — App muss installiert sein)
#
# FLAGS (android):
# --no-build KEIN Gradle-Rebuild → nur Metro starten
# (für schnellen UI/JS-Reload — APK muss installiert sein)
# --no-launch Build+Install, aber kein Auto-Launch
# --wifi Metro mit --host lan (nur in Kombi mit --no-build)
#
# FLAGS (metro):
# --keep Cache behalten (kein --clear)
#
# FLAGS (clean):
# --build + iOS build am Ende
# --xcode + Xcode öffnen am Ende
#
# BEISPIELE:
# # Default: iPhone USB + Native-Build:
# ./dev.sh
#
# # Schneller UI-Loop (App schon installiert, nur JS-Reload):
# ./dev.sh ios --no-build
# ./dev.sh android --no-build
#
# # WiFi-Dev (Kabel ab, Metro über LAN):
# ./dev.sh ios --wifi
#
# # iOS Simulator:
# ./dev.sh ios --simulator
#
# # Nur Xcode öffnen:
# ./dev.sh ios --xcode
#
# # iOS Clean + Rebuild:
# ./dev.sh clean --build
#
# # Release-Build auf iPhone installieren:
# ./dev.sh install ios
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
IOS_DIR="$SCRIPT_DIR/ios"
ANDROID_DIR="$SCRIPT_DIR/android"
# ═══════════════════════════════════════════════════════════════════════════
# Color Output
# ═══════════════════════════════════════════════════════════════════════════
if [[ -t 1 ]]; then
BOLD=$(tput bold)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
RED=$(tput setaf 1)
BLUE=$(tput setaf 4)
RESET=$(tput sgr0)
else
BOLD="" GREEN="" YELLOW="" RED="" BLUE="" RESET=""
fi
log() { echo "${BLUE}==>${RESET} ${BOLD}$*${RESET}"; }
ok() { echo "${GREEN}${RESET} $*"; }
warn() { echo "${YELLOW}${RESET} $*" >&2; }
error() { echo "${RED}${RESET} ${BOLD}$*${RESET}" >&2; }
die() { error "$*"; exit 1; }
section() {
echo ""
echo "${BOLD}$*${RESET}"
echo "${BOLD}────────────────────────────────────────────────────────────${RESET}"
}
# ═══════════════════════════════════════════════════════════════════════════
# ENV Defaults
# ═══════════════════════════════════════════════════════════════════════════
export REBREAK_ENABLE_FAMILY_CONTROLS="${REBREAK_ENABLE_FAMILY_CONTROLS:-1}"
export EXPO_PUBLIC_ENABLE_DEBUG="${EXPO_PUBLIC_ENABLE_DEBUG:-1}"
export REBREAK_DEV="${REBREAK_DEV:-0}"
# ═══════════════════════════════════════════════════════════════════════════
# Commands
# ═══════════════════════════════════════════════════════════════════════════
cmd_ios() {
local MODE="device" # Default: physisches iPhone via USB
local WIFI=false
local BUILD=true # Default: nativen Build laufen lassen
while [[ $# -gt 0 ]]; do
case "$1" in
--device) MODE="device"; shift ;;
--simulator) MODE="simulator"; shift ;;
--xcode) MODE="xcode"; shift ;;
--wifi) WIFI=true; shift ;;
--no-build) BUILD=false; shift ;;
*) die "Unbekannter Flag für 'ios': $1" ;;
esac
done
section "iOS Dev Mode"
# ─────────────────────────────────────────────────────────────
# --no-build / WiFi: KEIN Native-Rebuild, nur Metro + Dev-Client
# → schnellster Loop für reine UI/JS-Änderungen
# → App muss schon auf dem Device/Simulator installiert sein
# ─────────────────────────────────────────────────────────────
if ! $BUILD || $WIFI; then
local HOST_FLAG=""
if $WIFI; then
HOST_FLAG="--host lan"
log "Metro: WiFi-Modus (--host lan)"
echo ""
echo "Mac LAN-IP:"
ipconfig getifaddr en0 2>/dev/null || ipconfig getifaddr en1 2>/dev/null || echo " (kein WiFi/Ethernet detected)"
echo ""
echo "Falls dev-client Metro nicht automatisch findet:"
echo " im iPhone-Launcher → 'Enter URL manually' → http://<LAN-IP>:8081"
else
log "Metro: USB/Local-Modus (kein Native-Rebuild)"
echo "App auf Device/Simulator muss schon installiert sein."
echo "Beim Öffnen connected dev-client automatisch zu Metro."
fi
echo ""
log "Killing old Metro on port 8081..."
lsof -ti:8081 2>/dev/null | xargs kill -9 2>/dev/null || true
pkill -f "expo start" 2>/dev/null || true
echo ""
exec pnpm expo start $HOST_FLAG --clear --dev-client
fi
case "$MODE" in
xcode)
log "Opening Xcode Workspace..."
osascript -e 'tell application "Xcode" to close every window whose name contains "Rebreak.xcodeproj"' 2>/dev/null || true
open -a Xcode "$IOS_DIR/ReBreak.xcworkspace"
ok "Xcode geöffnet — Cmd+R für Build & Run"
echo ""
echo " Metro: separat starten via './dev.sh metro' falls noch nicht läuft"
;;
device)
log "Building für physisches iPhone (USB)..."
echo " Für schnellen UI-Reload ohne Rebuild: './dev.sh ios --no-build'"
pnpm expo run:ios --device
;;
simulator)
log "Building für iOS Simulator..."
pnpm expo run:ios
;;
esac
}
cmd_android() {
local BUILD=true
local LAUNCH=true
local WIFI=false
while [[ $# -gt 0 ]]; do
case "$1" in
--no-build) BUILD=false; shift ;;
--no-launch) LAUNCH=false; shift ;;
--wifi) WIFI=true; shift ;;
*) die "Unbekannter Flag für 'android': $1" ;;
esac
done
section "Android Dev Mode"
# ─────────────────────────────────────────────────────────────
# --no-build: KEIN Gradle-Rebuild, nur Metro + Dev-Client
# → schnellster Loop für reine UI/JS-Änderungen
# → APK muss schon auf dem Device installiert sein
# ─────────────────────────────────────────────────────────────
if ! $BUILD; then
local HOST_FLAG=""
if $WIFI; then
HOST_FLAG="--host lan"
log "Metro: WiFi-Modus (--host lan)"
echo ""
echo "Mac LAN-IP:"
ipconfig getifaddr en0 2>/dev/null || ipconfig getifaddr en1 2>/dev/null || echo " (kein WiFi/Ethernet detected)"
else
log "Metro: USB/ADB-Modus (kein Gradle-Rebuild)"
echo "APK muss schon auf dem Device installiert sein."
fi
echo ""
log "Killing old Metro on port 8081..."
lsof -ti:8081 2>/dev/null | xargs kill -9 2>/dev/null || true
pkill -f "expo start" 2>/dev/null || true
echo ""
exec pnpm expo start $HOST_FLAG --clear --dev-client
fi
command -v adb >/dev/null 2>&1 || die "adb nicht gefunden — brew install --cask android-platform-tools"
local DEVICE_COUNT
DEVICE_COUNT=$(adb devices | grep -E '[[:space:]]device$' | grep -c '.' || true)
if [[ "$DEVICE_COUNT" -eq 0 ]]; then
warn "Kein Android-Gerät via ADB verbunden"
echo ""
adb devices
echo ""
echo "Mögliche Ursachen:"
echo " - USB nicht angeschlossen / Kabel nur Strom"
echo " - USB-Debugging auf dem Phone aus"
echo " - 'Diesem Computer vertrauen?' Dialog noch nicht bestätigt"
exit 1
fi
log "Building Debug APK..."
echo " Für schnellen UI-Reload ohne Rebuild: './dev.sh android --no-build'"
(cd "$ANDROID_DIR" && ./gradlew assembleDebug --console=plain)
local APK="$ANDROID_DIR/app/build/outputs/apk/debug/app-debug.apk"
[[ -f "$APK" ]] || die "APK nicht gefunden: $APK"
log "Installing APK..."
adb install -r -d "$APK"
if $LAUNCH; then
log "Launching App..."
adb shell monkey -p org.rebreak.app -c android.intent.category.LAUNCHER 1 >/dev/null 2>&1 || {
warn "Launch via monkey schlug fehl — App ist installiert, manuell öffnen"
}
fi
ok "Android Dev Build abgeschlossen"
}
cmd_metro() {
local CLEAR_FLAG="--clear"
while [[ $# -gt 0 ]]; do
case "$1" in
--keep) CLEAR_FLAG=""; shift ;;
*) die "Unbekannter Flag für 'metro': $1" ;;
esac
done
section "Metro Bundler"
log "Killing existing Metro on port 8081..."
lsof -iTCP:8081 -sTCP:LISTEN -n -P 2>/dev/null | awk 'NR>1 {print $2}' | sort -u | xargs kill -9 2>/dev/null || true
pkill -f "expo start" 2>/dev/null || true
pkill -f "react-native/cli/build" 2>/dev/null || true
if [[ -n "$CLEAR_FLAG" ]]; then
log "Starting Metro mit --clear (Cache reset)..."
else
log "Starting Metro (Cache behalten)..."
fi
exec npx expo start $CLEAR_FLAG
}
cmd_clean() {
local POST_ACTION=""
while [[ $# -gt 0 ]]; do
case "$1" in
--build) POST_ACTION="build"; shift ;;
--xcode) POST_ACTION="xcode"; shift ;;
*) die "Unbekannter Flag für 'clean': $1" ;;
esac
done
section "iOS Nuclear Clean"
log "rm -rf ios/Pods ios/Podfile.lock ios/build"
rm -rf "$IOS_DIR/Pods" "$IOS_DIR/Podfile.lock" "$IOS_DIR/build"
local DERIVED_DATA="$HOME/Library/Developer/Xcode/DerivedData"
if [[ -d "$DERIVED_DATA" ]]; then
log "rm -rf DerivedData/Rebreak-*"
rm -rf "$DERIVED_DATA"/Rebreak-* 2>/dev/null || true
fi
local ARCHIVES_DIR="$HOME/Library/Developer/Xcode/Archives"
if [[ -d "$ARCHIVES_DIR" ]]; then
local before_count
before_count=$(find "$ARCHIVES_DIR" -maxdepth 2 -type d -iname "*rebreak*.xcarchive" 2>/dev/null | wc -l | tr -d ' ')
log "Cleaning Xcode Archives (Rebreak, >24h) — vorher: $before_count Stk"
find "$ARCHIVES_DIR" -maxdepth 2 -type d -iname "*rebreak*.xcarchive" -mtime +1 -exec rm -rf {} + 2>/dev/null || true
find "$ARCHIVES_DIR" -maxdepth 1 -type d -empty -delete 2>/dev/null || true
fi
log "pnpm expo prebuild --clean"
pnpm expo prebuild --clean
log "cd ios && pod install"
(cd "$IOS_DIR" && pod install)
ok "Clean abgeschlossen"
case "$POST_ACTION" in
build)
echo ""
log "Building + Running..."
pnpm ios
;;
xcode)
echo ""
log "Opening Xcode..."
osascript -e 'tell application "Xcode" to close every window whose name contains "Rebreak.xcodeproj"' 2>/dev/null || true
open -a Xcode "$IOS_DIR/ReBreak.xcworkspace"
ok "Xcode geöffnet — Cmd+R für Build & Run"
;;
"")
echo ""
echo "Nächste Schritte:"
echo " ./dev.sh ios # Build & Run"
echo " ./dev.sh ios --xcode # Xcode öffnen"
;;
esac
}
cmd_install_ios() {
section "iOS Standalone Install"
local CONFIGURATION="Release"
command -v xcrun >/dev/null 2>&1 || die "Xcode Command-Line-Tools fehlen — xcode-select --install"
local XCTRACE_OUT
XCTRACE_OUT=$(xcrun xctrace list devices 2>&1)
local ONLINE
ONLINE=$(printf '%s\n' "$XCTRACE_OUT" \
| awk '/^== Devices ==/{f=1; next} /^== /{f=0} f' \
| grep -E "iPhone|iPad" || true)
if [[ -z "$ONLINE" ]]; then
error "Kein iPhone/iPad ONLINE"
echo ""
echo "Setup:"
echo " - iPhone via USB anschließen + entsperren"
echo " - 'Diesem Computer vertrauen?' am iPhone bestätigen"
echo " - Xcode öffnen, dort 'Use for Development' aktivieren"
exit 1
fi
log "Gerät online: $(printf '%s\n' "$ONLINE" | head -1)"
log "Building iOS Release bundle + installing on device..."
echo ""
echo "(Erster Release-Build dauert 5-10 min wegen Pod-Install + Bundle)"
echo ""
npx expo run:ios --device --configuration "$CONFIGURATION"
ok "App läuft jetzt standalone auf deinem iPhone"
echo "Backend: https://staging.rebreak.org"
echo "Free-Account: 7 Tage gültig, danach Skript erneut laufen lassen"
}
cmd_install_android() {
section "Android Standalone Install"
local SKIP_BUILD=false
local LAUNCH=true
while [[ $# -gt 0 ]]; do
case "$1" in
--no-build) SKIP_BUILD=true; shift ;;
--no-launch) LAUNCH=false; shift ;;
*) die "Unbekannter Flag für 'install android': $1" ;;
esac
done
command -v adb >/dev/null 2>&1 || die "adb nicht gefunden — brew install --cask android-platform-tools"
local DEVICE_COUNT
DEVICE_COUNT=$(adb devices | grep -E '[[:space:]]device$' | grep -c '.' || true)
if [[ "$DEVICE_COUNT" -eq 0 ]]; then
error "Kein Android-Gerät via ADB"
adb devices
exit 1
fi
local APK="$ANDROID_DIR/app/build/outputs/apk/debug/app-debug.apk"
if ! $SKIP_BUILD; then
log "Building debug APK..."
(cd "$ANDROID_DIR" && ./gradlew assembleDebug --console=plain)
fi
[[ -f "$APK" ]] || die "APK nicht gefunden: $APK"
log "Installing $APK..."
adb install -r -d "$APK"
if $LAUNCH; then
log "Launching App..."
adb shell monkey -p org.rebreak.app -c android.intent.category.LAUNCHER 1 >/dev/null 2>&1 || {
warn "Launch schlug fehl — App ist installiert, manuell öffnen"
}
fi
ok "Fertig"
}
# ═══════════════════════════════════════════════════════════════════════════
# Main
# ═══════════════════════════════════════════════════════════════════════════
COMMAND="${1:-ios}"
shift || true
case "$COMMAND" in
ios)
cmd_ios "$@"
;;
android)
cmd_android "$@"
;;
metro)
cmd_metro "$@"
;;
clean)
cmd_clean "$@"
;;
install)
local PLATFORM="${1:-}"
shift || true
case "$PLATFORM" in
ios) cmd_install_ios "$@" ;;
android) cmd_install_android "$@" ;;
*)
error "Unbekannte install-Platform: $PLATFORM"
echo "Verfügbar: ios, android"
exit 1
;;
esac
;;
-h|--help)
awk '/^#!/{next} /^#/{sub(/^# ?/, ""); print; next} {exit}' "$0"
exit 0
;;
*)
error "Unbekanntes Subcommand: $COMMAND"
echo ""
echo "Verfügbare Commands:"
echo " ios iOS Dev (Metro + Xcode/Simulator/Device)"
echo " android Android Dev (Metro + Gradle + Install)"
echo " metro Nur Metro starten"
echo " clean iOS Nuclear Clean"
echo " install ios Release-Build auf iPhone installieren"
echo " install android Debug-APK auf Android installieren"
echo ""
echo "Nutze --help für Details"
exit 1
;;
esac