# Scambio di ricette: backup, condivisione, impostazioni

Data: 2026-09-16. Deciso con Paolo dopo la prima giornata dell'app sull'iPhone
vero, dove export e import erano due icone nella home e l'import ignorava un
backup se le ricette erano state cancellate.

## Il problema

Export e import oggi sono un gesto solo, senza intenzione: si esporta tutto,
si importa quello che c'è e si scopre dopo cosa è entrato. Ma chi esporta lo
fa per due motivi diversi, e i due motivi vogliono due posti e due
comportamenti:

- **fare una copia** del proprio ricettario, intero o di una categoria, per
  tenerla o per passarla a un altro telefono proprio;
- **mandare una ricetta a un amico** che ha l'app, come si manda una foto.

E chi riceve un file deve poterlo aprire toccandolo, senza sapere cos'è un
archivio zip.

## Decisioni

### Un formato, un'estensione: `.quantobasta`

Il file è lo stesso archivio di oggi, `ricettario.json` più la cartella
`foto/`, con l'estensione `.quantobasta`. Un solo formato per il backup e per
la ricetta singola: cambia solo cosa c'è dentro. Un solo tipo di file da
registrare sui due sistemi, un solo percorso di lettura.

Il nome del file dice il contenuto, così si riconosce nella cartella Download:

| Cosa | Nome |
|---|---|
| tutto il ricettario | `Ricettario 2026-09-16.quantobasta` |
| una categoria | `Primi.quantobasta` |
| una ricetta | `Farinata.quantobasta` |

I caratteri che un file system non accetta (`/ \ : * ? " < > |`) diventano
spazi. I vecchi `.zip` e i JSON nudi continuano a entrare dal tasto «Importa»
delle impostazioni: il contenuto si riconosce dai primi byte, come oggi.

### Chi esporta, e da dove

**Impostazioni → Esporta…** apre un foglio con «Tutte le ricette» e, sotto,
l'elenco delle categorie. Scelta una voce, l'app scrive il file e lo passa al
foglio di condivisione del sistema, come oggi. Le categorie viaggiano: è una
copia, deve tornare com'era.

**Nella ricetta, dal menù «···»**, due voci:

- **Condividi ricetta**: il file, con la ricetta scritta **senza categoria** e
  senza l'elenco delle categorie. Chi la riceve la trova fra quelle «senza
  categoria» e decide lui dove metterla: la sua «Antipasti» non è la mia, e
  l'app non deve creargliela.
- **Copia come testo**: la ricetta in chiaro negli appunti (titolo, porzioni,
  ingredienti uno per riga con quantità e unità nel formato della lingua,
  procedimento). Un cenno «Copiata» e basta. Serve per chi non ha l'app, e per
  incollarla dove si vuole.

La regola su cosa contiene il file sta in chi lo scrive, non in chi lo legge:
l'import applica quello che trova.

### Chi importa: due porte, una schermata

1. **Il sistema apre l'app** perché l'utente ha toccato un `.quantobasta` in
   WhatsApp, Mail, File.
2. **Impostazioni → Importa…** e si sceglie il file a mano.

In tutti e due i casi l'app legge il file **senza scrivere niente** e mostra
l'**anteprima**:

```
Importa

Farinata                 nuova · con foto
Pasta al pomodoro        aggiorna la tua
Ciambella                già aggiornata

Categorie
Antipasti                nuova
Primi                    già aggiornata

[Annulla]        [Importa 2 ricette e 1 categoria]
```

Il segno accanto a ogni riga è il risultato del confronto con quello che c'è
sul telefono: lo stesso confronto che poi decide l'import, calcolato una volta.
Il tasto dice quante cose entrano davvero; se non entra niente dice «Niente da
importare» ed è spento. Un file rotto, o di un'altra app, non arriva
all'anteprima: avviso e basta, come oggi.

Dopo l'import, l'esito in una riga, come oggi, e la schermata principale si
rilegge.

### Impostazioni

Si entra dall'**ingranaggio** nell'intestazione della home, che prende il posto
delle due icone di export e import: quelle spariscono dalla home. È un segno
nuovo del set (`ingranaggio`), disegnato come gli altri.

La pagina, dall'alto:

- **Aspetto**
  - Tema: come il telefono / chiaro / scuro
  - Lingua: come il telefono / Italiano / English
- **Ricette**
  - Esporta…
  - Importa…
- **Informazioni**
  - Informativa sulla privacy (apre il browser all'indirizzo pubblico)
  - in fondo, in piccolo: «Quanto Basta 1.0.0 (1)», letti dal pacchetto

Tema e lingua cambiano subito, senza riavviare, e si salvano nella tabella
`impostazioni` che c'è già (chiavi `tema` e `lingua`; assenti = come il
telefono). Nessuna migrazione.

### Il tipo di file sui due sistemi

Tutto in `app.json`, niente codice nativo scritto a mano: il prebuild genera.

- **iOS**: in `ios.infoPlist`, `UTExportedTypeDeclarations` dichiara il tipo
  `it.duebytes.quantobasta.ricettario` (conforme a `public.data` e
  `com.pkware.zip-archive`, estensione `quantobasta`), e `CFBundleDocumentTypes`
  associa l'app a quel tipo con `LSHandlerRank = Owner`.
- **Android**: in `android.intentFilters`, un filtro `VIEW` su
  `content://` e `file://` con `pathPattern .*\\.quantobasta`, più uno sul
  MIME `application/zip` con lo stesso pattern, perché i gestori file Android
  dichiarano volentieri i tipi a caso.

Quando il sistema apre l'app col file, arriva un URL: lo raccoglie
`expo-linking` (`getInitialURL` all'avvio, `addEventListener('url')` se l'app
è già aperta). Il SceneDelegate aggiunto il 2026-09-16 inoltra già gli URL a
React Native, sia a freddo sia a caldo. Su iOS l'URL è `file://` in una
cartella temporanea: si copia subito nella cartella dell'app, perché il sistema
la può togliere. Su Android è `content://`: `expo-file-system` lo legge.

**Expo Go non può registrare tipi di file**: questa parte si collauda solo con
l'app compilata sull'iPhone, e su Android quando ci sarà un telefono.

## Dentro il codice

Le decisioni stanno nei moduli puri; le schermate leggono e mostrano.

- `src/io/piano.ts` (nuovo, puro): `pianoImport(file, localiRicette,
  localiCategorie, adesso)` restituisce il piano: per ogni ricetta e categoria
  del file, `nuova | aggiorna | ferma` con il motivo, e i totali. Usa la stessa
  `vinceIlFile` di `importa.ts`, che si sposta qui. `importa.ts` esegue un
  piano invece di decidere riga per riga: anteprima ed esecuzione non possono
  dire due cose diverse. I test attuali dell'import restano verdi e se ne
  aggiungono per il piano.
- `src/io/esporta.ts`: `esporta(db, selezione)` dove la selezione è `tutto |
  {categoriaId} | {ricettaId}`. Con `ricettaId` la ricetta esce con
  `categoriaId: null` e `categorie: []`. Il nome del file lo dà una funzione
  pura `nomeFile(selezione, nomi, adesso)`.
- `src/domain/testo.ts` (nuovo, puro): `ricettaInTesto(ricetta, voc)`, il
  contrario del parser: quello che scrive deve rientrare da `leggiBlocco` con le
  stesse quantità. Un test lo garantisce nei due versi.
- `src/ui/scambio.ts`: le righe dell'anteprima e l'etichetta del tasto, da un
  piano; i testi passano da `i18n` come oggi.
- `src/ui/schermate/Impostazioni.tsx`, `Anteprima.tsx` (nuove);
  `Categorie.tsx` perde `BarraIo` e prende l'ingranaggio; `Dosatore.tsx`
  guadagna le due voci nel menù. `BarraIo.tsx` si smonta: export e import
  vivono in Impostazioni.
- `src/ui/logica-impostazioni.ts` (nuovo, puro): lettura e scrittura di tema e
  lingua, e la scelta effettiva («come il telefono» → quello del sistema).
  `App.tsx` oggi fissa la lingua all'avvio con `useMemo`: diventa uno stato che
  la pagina impostazioni cambia.
- `src/ui/segni.ts` e `scripts/genera-segni.py`: il segno `ingranaggio`.
- `app.json`: le dichiarazioni del tipo di file.

## Casi al margine

- File aperto dal sistema mentre l'app è già su un'altra schermata: si apre
  l'anteprima sopra, e «Annulla» torna dov'era.
- File aperto dal sistema con l'app chiusa: l'anteprima è la prima schermata
  dopo l'avvio.
- Due file aperti di seguito: il secondo sostituisce il primo, senza
  chiedere.
- Ricetta condivisa che l'amico ha già (stesso id, per esempio l'avevo già
  mandata): l'anteprima dice «aggiorna la tua» o «già aggiornata» con la stessa
  regola del backup. Non è un caso speciale.
- Un backup vecchio importato sopra ricette cancellate le riporta indietro:
  deciso il 2026-09-16, `vinceIlFile`.
- Il tema scelto a mano vale anche se il telefono cambia il suo; «come il
  telefono» lo segue.

## Fuori da questa spec

- Ripristino della copia di sicurezza fatta prima dell'import (esiste su disco,
  non ha un tasto). Si aggiunge se qualcuno la chiede.
- Condivisione con testo e file insieme nello stesso foglio: scartata, su
  WhatsApp fa due messaggi.
- Sync fra dispositivi (pezzo B): questa spec non la avvicina né la allontana,
  il formato del file resta quello.
