import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flux/features/attachments/data/attachments_repository.dart'; import 'package:flux/features/auth/bloc/auth_cubit.dart'; import 'package:flux/features/operations/data/operations_repository.dart'; import 'package:flux/l10n/app_localizations.dart'; import 'package:get_it/get_it.dart'; import 'package:go_router/go_router.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; import 'package:flux/core/blocs/session/session_cubit.dart'; import 'package:flux/core/data/core_repository.dart'; import 'package:flux/core/routes/app_router.dart'; import 'package:flux/core/theme/theme.dart'; import 'package:flux/core/theme/bloc/theme_bloc.dart'; import 'package:flux/features/customers/blocs/customers_cubit.dart'; import 'package:flux/features/customers/data/customer_repository.dart'; import 'package:flux/features/master_data/products/blocs/product_cubit.dart'; import 'package:flux/features/master_data/products/data/product_repository.dart'; import 'package:flux/features/master_data/providers/blocs/provider_cubit.dart'; import 'package:flux/features/master_data/providers/data/provider_repository.dart'; import 'package:flux/features/master_data/staff/blocs/staff_cubit.dart'; import 'package:flux/features/master_data/staff/data/staff_repository.dart'; import 'package:flux/features/master_data/store/bloc/store_cubit.dart'; import 'package:flux/features/master_data/store/data/store_repository.dart'; import 'package:flux/features/operations/blocs/operations_cubit.dart'; import 'package:flux/features/settings/settings.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await dotenv.load(fileName: ".env"); // Inizializza le dipendenze PRIMA di lanciare l'app await setupLocator(); runApp( MultiBlocProvider( providers: [ BlocProvider(create: (context) => AuthCubit()), BlocProvider( create: (context) => ThemeBloc()..add(LoadThemeEvent()), ), // Il Vigile Urbano viene inizializzato! BlocProvider(create: (_) => GetIt.I()), // Cubit delle feature BlocProvider(create: (_) => StoreCubit()), BlocProvider(create: (_) => CustomersCubit()), BlocProvider(create: (_) => ProductsCubit()), BlocProvider(create: (_) => StaffCubit()), BlocProvider(create: (_) => OperationsCubit()), BlocProvider(create: (_) => ProvidersCubit()), ], child: const FluxApp(), ), ); } Future setupLocator() async { final GetIt getIt = GetIt.instance; getIt.registerSingleton( await SharedPreferences.getInstance(), ); await Supabase.initialize( url: dotenv.env['SUPABASE_URL'] ?? '', anonKey: dotenv.env['SUPABASE_ANON_KEY'] ?? '', ); //await Supabase.instance.client.auth.signOut(); getIt.registerSingleton(Supabase.instance.client); // Settings getIt.registerLazySingleton(() => AppSettings()); // Repositories getIt.registerLazySingleton( () => CoreRepository(), ); // <-- NUOVO getIt.registerLazySingleton(() => StoreRepository()); getIt.registerLazySingleton(() => CustomerRepository()); getIt.registerLazySingleton(() => ProductRepository()); getIt.registerLazySingleton(() => StaffRepository()); getIt.registerLazySingleton( () => OperationsRepository(), ); getIt.registerLazySingleton(() => ProviderRepository()); getIt.registerLazySingleton( () => AttachmentsRepository(), ); // NOTA: CompanyRepository l'ho tolto perché la logica della Company // ora è gestita dal CoreRepository durante l'Onboarding. // Se ti serve per altro, rimettilo pure! // Inizializziamo il SessionCubit (che prende CoreRepository e SharedPreferences) // Usiamo registerSingleton così viene creato subito e inizia ad ascoltare Supabase Auth. getIt.registerSingleton( SessionCubit(getIt(), getIt()), ); } class FluxApp extends StatefulWidget { const FluxApp({super.key}); @override State createState() => _FluxAppState(); } class _FluxAppState extends State { late final GoRouter _router; @override void initState() { super.initState(); // Creiamo il router passandogli il Cubit per i redirect _router = AppRouter.createRouter(context.read()); GetIt.I.get().setIsMobileDevice(isMobileDevice(context)); } bool isMobileDevice(BuildContext context) { if (kIsWeb) { return false; // Il web non lo consideriamo "mobile nativo" per i deep link } return Platform.isAndroid || Platform.isIOS; } @override Widget build(BuildContext context) { // Il BlocConsumer unisce Listener e Builder in un colpo solo! return BlocConsumer( // --- PARTE LISTENER (Il colpo di clacson in background) --- listenWhen: (previous, current) => previous.status != SessionStatus.authenticated && current.status == SessionStatus.authenticated, listener: (context, state) { // BAM! L'utente è dentro. Pre-carichiamo i Cubit leggeri. context.read().loadStores(); context.read().loadAllStaff(); context.read().loadProviders(); }, // --- PARTE BUILDER (La UI che viene disegnata a schermo) --- builder: (context, sessionState) { if (sessionState.status == SessionStatus.initial) { return _buildLoadingScreen(); } return BlocBuilder( builder: (context, themeState) { return MaterialApp.router( title: 'FLUX Gestionale', debugShowCheckedModeBanner: false, theme: fluxLightTheme, darkTheme: fluxDarkTheme, themeMode: themeState.currentTheme.themeMode, routerConfig: _router, localizationsDelegates: AppLocalizations.localizationsDelegates, supportedLocales: AppLocalizations.supportedLocales, locale: const Locale('it'), ); }, ); }, ); } Widget _buildLoadingScreen() { return MaterialApp( debugShowCheckedModeBanner: false, home: Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.bolt, size: 64, color: Colors.blue), const SizedBox(height: 24), const CircularProgressIndicator(), const SizedBox(height: 16), const Text( "Inizializzazione sessione...", style: TextStyle( fontWeight: FontWeight.bold, color: Colors.grey, ), ), ], ), ), ), ); } }