41b0180b44
flutterfire configure registered the iOS/Android apps under project block-seasons and generated firebase_options.dart + native config. main() now initializes Firebase and routes analytics through FirebaseAnalyticsBackend in release builds (console logger in debug, so dev traffic never pollutes GA4). Firebase init is guarded — failure falls back to the debug logger rather than blocking startup. firebase.json keeps the existing Hosting config and gains the FlutterFire platform section. Client config files are committed (they ship in the binary; Firebase security is enforced by rules, not config secrecy). flutter analyze clean, all 161 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
71 lines
2.3 KiB
Dart
71 lines
2.3 KiB
Dart
import 'dart:io';
|
|
|
|
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<void> 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,
|
|
);
|
|
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(),
|
|
));
|
|
}
|