// =========================================================================== // FILE: lib/main.dart // =========================================================================== import 'dart:io' show Platform; import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart'; import 'package:provider/provider.dart'; import 'core/theme_manager.dart'; import 'logic/game_controller.dart'; import 'ui/home/home_screen.dart'; import 'services/storage_service.dart'; import 'services/audio_service.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'firebase_options.dart'; import 'package:firebase_app_check/firebase_app_check.dart'; // --- NUOVI IMPORT PER GLI AGGIORNAMENTI --- import 'package:upgrader/upgrader.dart'; import 'package:in_app_update/in_app_update.dart'; // --- IMPORT PER IL SUPPORTO MULTILINGUA --- import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:tetraq/l10n/app_localizations.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ); await FirebaseAppCheck.instance.activate( androidProvider: kDebugMode ? AndroidProvider.debug : AndroidProvider.playIntegrity, appleProvider: kDebugMode ? AppleProvider.debug : AppleProvider.deviceCheck, ); try { await FirebaseAuth.instance.signInAnonymously(); } catch (e) { debugPrint("Errore Auth: $e"); } await StorageService.instance.init(); await AudioService.instance.init(); runApp( MultiProvider( providers: [ ChangeNotifierProvider(create: (_) => ThemeManager()), ChangeNotifierProvider(create: (_) => GameController()), ], child: const TetraQApp(), ), ); } class TetraQApp extends StatelessWidget { const TetraQApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'TetraQ', debugShowCheckedModeBanner: false, theme: ThemeData( fontFamily: 'Roboto', useMaterial3: true, ), // --- BIVIO DELLE LINGUE ATTIVATO! --- // Flutter si occuperà di caricare automaticamente tutte le lingue // che hai generato tramite lo script. localizationsDelegates: AppLocalizations.localizationsDelegates, supportedLocales: AppLocalizations.supportedLocales, // ------------------------------------ // Avvolgiamo la HomeScreen nel nostro nuovo gestore di aggiornamenti! home: const UpdateWrapper(child: HomeScreen()), ); } } // =========================================================================== // WIDGET WRAPPER PER LA GESTIONE DEGLI AGGIORNAMENTI IBRIDI (iOS/Android) // =========================================================================== class UpdateWrapper extends StatefulWidget { final Widget child; const UpdateWrapper({super.key, required this.child}); @override State createState() => _UpdateWrapperState(); } class _UpdateWrapperState extends State { @override void initState() { super.initState(); // Controlla gli aggiornamenti in background solo se siamo su Android if (!kIsWeb && Platform.isAndroid) { _checkForAndroidUpdate(); } } Future _checkForAndroidUpdate() async { try { final info = await InAppUpdate.checkForUpdate(); if (info.updateAvailability == UpdateAvailability.updateAvailable) { // Se possibile, fai scaricare l'aggiornamento in background mentre l'utente gioca if (info.flexibleUpdateAllowed) { await InAppUpdate.startFlexibleUpdate(); await InAppUpdate.completeFlexibleUpdate(); // Chiede il riavvio rapido dell'app } // Se l'aggiornamento è impostato come critico dalla console di Google Play else if (info.immediateUpdateAllowed) { await InAppUpdate.performImmediateUpdate(); } } } catch (e) { debugPrint("Errore in_app_update Android: $e"); } } @override Widget build(BuildContext context) { // Su iOS e macOS usiamo "upgrader" che si occupa di mostrare il pop-up nativo if (!kIsWeb && (Platform.isIOS || Platform.isMacOS)) { return UpgradeAlert( upgrader: Upgrader( debugDisplayAlways: true, // <--- AGGIUNGI QUESTA RIGA PER IL TEST dialogStyle: Platform.isIOS ? UpgradeDialogStyle.cupertino : UpgradeDialogStyle.material, showIgnore: false, // Togliamo il tasto "Ignora per sempre" showLater: true, // Lasciamo il tasto "Ricordamelo più tardi" ), child: widget.child, ); } // Su Android restituiamo la UI normale (l'aggiornamento è gestito nel background da initState) return widget.child; } }