# Le app native, iOS e Android

Dal 31/08/2026 la stessa PWA gira dentro due app native, costruite con
**Capacitor 8**. Non c'è una seconda base di codice: `capacitor.config.json`
ha `webDir: "pwa"`, quindi le app servono gli stessi identici file che stanno
su Vercel.

- Nome: **Faraway Score**, quello autorizzato da Catch Up il 31/08/2026
  (vedi `docs/catchup/autorizzazione-catchup-31-08-2026.md`).
- Identificativo: `it.duebytes.farawayscore`.

## La regola che conta: non si compila dal NAS

Il progetto vive su una condivisione SMB (`//admin@NASALBERTI.local/web`).
**Xcode, Gradle e la CLI di Vercel da lì non funzionano.** Non danno un errore
chiaro: escono con "disk I/O error" sul database di build, "Bad file
descriptor" leggendo i sorgenti, "EBADF" mentre scrivono. Sono tutti lo stesso
problema, cioè il file locking che su SMB non c'è.

Quindi c'è un **clone locale** in `~/dev/faraway-score`, ed è lì che si
compila e si pubblica. Il progetto sul NAS resta la copia di riferimento.

Come vanno avanti e indietro le modifiche:

```bash
# modifiche fatte sul NAS (di solito: la PWA) → al clone
cd ~/dev/faraway-score && git pull && npx cap sync

# modifiche fatte nel clone (di solito: icone, roba di Xcode) → al NAS
cd "/Users/paolo/Server/Siti Web/_private/ - App/Faraway" && git pull locale main
```

Il remoto `locale` punta alla cartella `~/dev/faraway-score`, è già
configurato.

## Compilare e provare

```bash
cd ~/dev/faraway-score
npx cap copy                       # copia pwa/ dentro i due progetti
```

**iOS.** Con Xcode 27 `npx cap run ios` compila ma non trova il simulatore:
si compila con `xcodebuild` e si installa con `xcrun simctl install` / `launch`.
**Il simulatore non ha la fotocamera**: il riconoscimento si prova su un iPhone
vero, o con la beta di TestFlight. Per lo store, dentro `ios/App`:

```bash
xcodebuild -project App.xcodeproj -scheme App -configuration Release \
  -destination "generic/platform=iOS" -archivePath build/FarawayScore.xcarchive \
  archive -allowProvisioningUpdates
xcodebuild -exportArchive -archivePath build/FarawayScore.xcarchive \
  -exportOptionsPlist ExportOptions.plist -exportPath build/export \
  -allowProvisioningUpdates           # carica anche su App Store Connect
```

Ogni caricamento vuole un `CURRENT_PROJECT_VERSION` nuovo. Se l'export dice
«No Accounts with App Store Connect Access», Paolo rinnova l'accesso in Xcode
(Settings → Accounts) e si rilancia solo l'export.

**Android.** Serve il **JDK 21** (col 17 Capacitor 8 non compila):

```bash
export JAVA_HOME=~/Library/Java/JavaVirtualMachines/jdk-21.0.12.1+1/Contents/Home
export ANDROID_HOME=/opt/homebrew/share/android-commandlinetools
cd android && ./gradlew bundleRelease   # app/build/outputs/bundle/release/app-release.aab
keytool -printcert -jarfile app/build/outputs/bundle/release/app-release.aab
```

La firma usa la chiave di caricamento in `_private/ - App/Faraway - firma
Android/`, trovata tramite le proprietà `FW_UPLOAD_*` in
`~/.gradle/gradle.properties`. Ogni release vuole un `versionCode` nuovo.
Emulatore: AVD `FarawayScore`, avviato su una porta propria (`-port 5580`)
perché altre sessioni usano i loro.

## Cose già sistemate, da non rifare

- **I caratteri stanno dentro l'app** (`pwa/fonts/`). Nell'app nativa la pagina
  è servita da `capacitor://localhost` e il foglio di Google Fonts non
  arrivava: i titoli finivano su `cursive`. Un carattere nuovo va messo lì,
  mai con un `@import` remoto.
- **Il riquadro "Installa l'app" è nascosto** dentro l'app nativa:
  `giaInstallata()` in `app.js` controlla anche `window.Capacitor`.
- **Fotocamera dichiarata**: `NSCameraUsageDescription` in Info.plist e
  `android.permission.CAMERA` nel manifest.
- **Solo verticale**: su iPad con `UIRequiresFullScreen`; su Android, oltre a
  `screenOrientation`, la property `PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY`,
  perché Android 16 con targetSdk 36 ignora l'orientamento su tablet e
  pieghevoli. Dal targetSdk 37 non varrà più. L'app iOS è dichiarata **solo
  iPhone** (`TARGETED_DEVICE_FAMILY = 1`): con l'iPad Apple vuole le schermate
  da 13" e un design per tablet che non c'è ancora.
- **Indietro**: ogni schermata ha una voce nella cronologia (`go()` in
  `app.js`). Su iOS lo swipe dal bordo lo abilita `FarawayViewController` in
  `SceneDelegate.swift`, su Android il tasto indietro lo gestisce
  `MainActivity.java`.
- **Icone e schermata d'avvio**: le genera `build-icone.py` dalla F di Catch Up.
  **Mai `@capacitor/assets`**: riscrive le icone Android e le rovina.
- **Splash**: plugin `@capacitor/splash-screen` con `launchAutoHide: false`,
  chiusa da `app.js` dopo il primo disegno; su Android 12+ la disegna il
  sistema con `windowSplashScreenBackground` e `windowSplashScreenAnimatedIcon`.
- `gradlew` su SMB perde il permesso di esecuzione: in git è `100755`.

## Da fare

- L'icona a 1024 è l'ingrandimento del file da 461 pixel mandato da Matthieu:
  va chiesto l'originale.
- Design per tablet e iPhone pieghevole, poi rimettere l'iPad.
