11 Commits

Author SHA1 Message Date
davide cd82edd8d3 chore: bump versione a 2.1.0 e aggiorna CLAUDE.md
versionCode 10300 → 10400. CLAUDE.md aggiornato con i nuovi servizi
shared (UpdateService, UrlLauncherService, update_dialog), il
MethodChannel in MainActivity.kt e il pattern di mock per widget test.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 08:55:23 +02:00
davide ab1a7c18cd docs: documenta update checker nella guida utente e nella guida in-app
Aggiunge sezione "Aggiornamenti" in docs/guida-utente.md con rimando
dalla sezione "Informazioni app". Aggiunge TipCard nella tab Pasti
della guida in-app che descrive il controllo automatico all'avvio.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 08:50:57 +02:00
davide 3da8ccc4d3 refactor: estrai showUpdateDialog e parseTagName in file dedicati
Sposta la logica del dialog in lib/shared/widgets/update_dialog.dart
per renderla importabile nei test senza duplicare il codice.
Estrae parseTagName come metodo @visibleForTesting in UpdateService
isolando il parsing JSON dalla chiamata HTTP. app.dart semplificato
di conseguenza.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 16:28:13 +02:00
davide 296a622d82 feat: aggiungi controllo aggiornamenti con dialog all'avvio
All'avvio l'app chiama l'API GitHub releases per confrontare la versione
installata con l'ultima disponibile (comparazione semantica major.minor.patch).
Se esiste una versione più recente, mostra un AlertDialog con i pulsanti
"Più tardi" e "Scarica" — quest'ultimo apre releases/latest nel browser.
Il controllo è silenzioso in caso di assenza di rete o errori, e disabilitato
su Flutter web (dart:io non disponibile).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 16:17:53 +02:00
davide 8d25f63f24 perf: riduci spazio APK e allocazioni a runtime
- Comprimi icon-only.png da 5.2 MB a 72 KB (512×512, quantizzazione 256 colori)
- Rimuovi setState() ridondante in ConverterPage.onChanged: search() chiama già notifyListeners()
- Cattura pendingItems/checkedItems in variabili locali nel build di ShoppingListPage per evitare filtraggio ripetuto a ogni paint

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 00:01:49 +02:00
davide 9fcaae9687 fix(shopping_list): genera ID univoci in ShoppingListProvider
add() usava millisecondsSinceEpoch come ID: chiamate ravvicinate nello
stesso millisecondo producevano ID identici, causando toggle e remove
incorretti su più elementi. Introdotto _idSeq come contatore progressivo,
allineato all'approccio già usato in addAll().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 23:27:04 +02:00
davide 49e7bcdbfa refactor(meal_planner): estrai logica QR in qr_codec.dart
buildQrPayload e parseMealPlanFromQr erano metodi privati non testabili.
Estratti in un modulo dedicato e importati da qr_share_sheet e qr_scan_page.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 23:26:55 +02:00
davide cebeaf889a feat: condivisione piano pasti via QR code
Porta la funzionalità QR code dalla versione Vue a Flutter.

Condividi: pulsante in fondo alla tab Pasti (attivo solo con piano
non vuoto) → bottom sheet con QR code generato da qr_flutter.
Payload: { "v": 1, "meals": { ... } }, limite 2953 byte.

Ricevi: pulsante sempre visibile → QrScanPage full-screen con
fotocamera via mobile_scanner, cornice di mira, validazione
struttura JSON e importazione via MealPlannerProvider.importPlan().

Nuovi package: qr_flutter ^4.1.0, mobile_scanner ^5.0.0

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 23:09:16 +02:00
davide 404a5f44ac feat: aggrega duplicati nella lista della spesa con quantità
Quando si genera la lista dal piano pasti, gli alimenti ripetuti in
più giorni o slot vengono aggregati in un unico elemento con contatore.
Es. zucchine lunedì + mercoledì → "zucchine (x2)".

- ShoppingItem: aggiunto campo quantity (default 1, persistito in JSON)
- ShoppingListProvider.addAll: conta le occorrenze per nome
  (case-insensitive) e crea un ShoppingItem con quantity = conteggio
- ShoppingItemTile: mostra "(xN)" colorato in primary quando quantity > 1,
  diventa muted insieme al nome quando l'elemento è completato

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 18:54:22 +02:00
davide cba83c9559 feat: aggiungi guida utente e icona launcher
Guida utente:
- Pulsante info nell'AppBar principale
- InfoBottomSheet: icona app, versione, autore, licenza, link alla guida
- GuidePage: tre tab (Pasti / Converti / Spesa) con card e step numerati,
  portata dalla DocsPanel Vue originale

AppBar globale in app.dart con titolo dinamico per tab corrente.

Icona launcher:
- flutter_launcher_icons eseguito in build.sh prima di flutter build apk
  (sia debug che release) per applicare assets/icon-only.png all'APK.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 18:38:02 +02:00
davide eb7912421c feat: riscrivi app in Flutter
Riscrittura completa da Vue 3 + Capacitor a Flutter/Dart.

Architettura feature-based (lib/features/):
- meal_planner: modello MealPlan/DayPlan, provider, pagina e widget
- converter: modello ConversionEntry, provider con ricerca, pagina
- shopping_list: modello ShoppingItem, provider con deduplicazione, pagina e widget

Core:
- Material 3 con seed color #2d6a4f
- NavigationBar + IndexedStack (preserva stato dei tab)
- Portrait lock via SystemChrome
- Persistenza con shared_preferences
- 50+ alimenti × metodi cottura in assets/data/conversions.json

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 17:41:26 +02:00