import 'dart:io'; import 'package:firebase_analytics/firebase_analytics.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:path_provider/path_provider.dart'; import 'app.dart'; import 'data/content_repository.dart'; import 'data/remote/content_downloader.dart'; import 'data/save_repository.dart'; import 'firebase_options.dart'; import 'services/analytics_service.dart'; import 'services/firebase_analytics_backend.dart'; import 'state/providers.dart'; /// Remote content origin. Swap per environment with /// --dart-define=CONTENT_BASE_URL=...; the default points at the production /// Firebase Hosting site (owner setup pending). const contentBaseUrl = String.fromEnvironment( 'CONTENT_BASE_URL', defaultValue: 'https://block-seasons.web.app/content', ); Future main() async { WidgetsFlutterBinding.ensureInitialized(); final saveRepository = await SaveRepository.open(); // Analytics: real GA4 traffic flows only from release builds so development // never pollutes production. If Firebase init fails (e.g. missing native // config), fall back to the console logger rather than blocking startup. AnalyticsService analytics; try { await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ); // Keep development traffic out of GA4 entirely — this also silences the // native SDK's automatic events (session_start, screen_view), not just // our custom ones, so only release builds ever reach production analytics. await FirebaseAnalytics.instance.setAnalyticsCollectionEnabled(kReleaseMode); analytics = AnalyticsService( kReleaseMode ? FirebaseAnalyticsBackend() : DebugAnalyticsBackend(), ); } catch (e) { debugPrint('Firebase init failed, analytics disabled: $e'); analytics = AnalyticsService(DebugAnalyticsBackend()); } ContentRepository contentRepository; try { final support = await getApplicationSupportDirectory(); final cacheDir = Directory('${support.path}/content'); contentRepository = ContentRepository( cacheDir: cacheDir, downloader: ContentDownloader( baseUrl: contentBaseUrl, cacheDir: cacheDir, ), ); } catch (e) { debugPrint('content cache unavailable, bundled only: $e'); contentRepository = ContentRepository(); } runApp(ProviderScope( overrides: [ saveRepositoryProvider.overrideWithValue(saveRepository), contentRepositoryProvider.overrideWithValue(contentRepository), analyticsProvider.overrideWithValue(analytics), ], child: const BlockSeasonsApp(), )); }