99 lines
3.2 KiB
Dart
99 lines
3.2 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:firebase_core/firebase_core.dart';
|
|
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'core/theme/theme.dart';
|
|
import 'firebase_options.dart';
|
|
import 'providers/org_modules_provider.dart';
|
|
import 'routes/app_router.dart';
|
|
import 'services/auth_service.dart';
|
|
import 'services/crash_reporting.dart';
|
|
import 'services/org_date.dart';
|
|
|
|
void main() async {
|
|
runZonedGuarded<Future<void>>(
|
|
() async {
|
|
WidgetsFlutterBinding.ensureInitialized();
|
|
|
|
// Firebase + Crashlytics. Android only. iOS has no GoogleService-Info.plist
|
|
// yet, so skip init there to avoid a startup crash.
|
|
if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
|
|
await Firebase.initializeApp(
|
|
options: DefaultFirebaseOptions.currentPlatform,
|
|
);
|
|
// Off in debug to avoid spamming the Crashlytics console with dev noise.
|
|
await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(
|
|
!kDebugMode,
|
|
);
|
|
FlutterError.onError =
|
|
FirebaseCrashlytics.instance.recordFlutterFatalError;
|
|
PlatformDispatcher.instance.onError = (error, stack) {
|
|
FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
|
|
return true;
|
|
};
|
|
}
|
|
|
|
// The IANA database behind every "today" default (`orgToday`).
|
|
loadTimeZones();
|
|
await AuthService().initialize();
|
|
// Tag any already-signed-in session so the first uncaught error has a user.
|
|
await CrashReporting.applyFromAuth(AuthService());
|
|
|
|
SystemChrome.setSystemUIOverlayStyle(
|
|
const SystemUiOverlayStyle(
|
|
statusBarColor: Colors.transparent,
|
|
statusBarIconBrightness: Brightness.dark,
|
|
systemNavigationBarColor: AppColors.surface,
|
|
systemNavigationBarIconBrightness: Brightness.dark,
|
|
),
|
|
);
|
|
|
|
SystemChrome.setPreferredOrientations([
|
|
DeviceOrientation.portraitUp,
|
|
DeviceOrientation.portraitDown,
|
|
]);
|
|
|
|
runApp(const ProviderScope(child: BottleCRMApp()));
|
|
},
|
|
(error, stack) {
|
|
// Catch-all for anything that escaped the zone, e.g. errors from
|
|
// microtasks scheduled before PlatformDispatcher.onError was wired.
|
|
if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
|
|
FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
|
|
}
|
|
},
|
|
);
|
|
}
|
|
|
|
/// BottleCRM - Main Application Widget
|
|
class BottleCRMApp extends ConsumerWidget {
|
|
const BottleCRMApp({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final router = ref.watch(appRouterProvider);
|
|
ref.watch(moduleOffListenerProvider);
|
|
|
|
return MaterialApp.router(
|
|
title: 'BottleCRM',
|
|
debugShowCheckedModeBanner: false,
|
|
|
|
// Theme
|
|
theme: AppTheme.light,
|
|
darkTheme: AppTheme.dark,
|
|
themeMode: ThemeMode.light,
|
|
|
|
// Router
|
|
routerConfig: router,
|
|
|
|
// Scroll behavior for smooth scrolling
|
|
scrollBehavior: const MaterialScrollBehavior().copyWith(
|
|
physics: const BouncingScrollPhysics(),
|
|
),
|
|
);
|
|
}
|
|
}
|