import 'dart:async'; import 'dart:io'; import 'package:app_links/app_links.dart'; import 'package:bot_toast/bot_toast.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_downloader/flutter_downloader.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:get/get.dart'; import 'package:home_widget/home_widget.dart'; import 'package:provider/provider.dart'; import 'package:provider/single_child_widget.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:didvan/config/theme_data.dart'; import 'package:didvan/firebase_options.dart'; import 'package:didvan/models/requests/news.dart'; import 'package:didvan/models/requests/radar.dart'; import 'package:didvan/routes/route_generator.dart'; import 'package:didvan/routes/routes.dart'; import 'package:didvan/services/app_home_widget/home_widget_repository.dart'; import 'package:didvan/services/media/media.dart'; import 'package:didvan/services/network/request.dart'; import 'package:didvan/services/notification/firebase_api.dart'; import 'package:didvan/services/notification/notification_service.dart'; import 'package:didvan/utils/my_custom_scroll_behavior.dart'; import 'package:didvan/providers/media.dart'; import 'package:didvan/providers/theme.dart'; import 'package:didvan/providers/user.dart'; import 'package:didvan/views/ai/ai_chat_state.dart'; import 'package:didvan/views/ai/ai_state.dart'; import 'package:didvan/views/ai/bot_assistants_state.dart'; import 'package:didvan/views/ai/history_ai_chat_state.dart'; import 'package:didvan/views/podcasts/podcasts_state.dart'; import 'package:didvan/views/podcasts/studio_details/studio_details_state.dart'; final GlobalKey navigatorKey = GlobalKey(); Uri? initialURI; @pragma('vm:entry-point') Future _backgroundCallbackHomeWidget(Uri? uri) async { if (uri != null) { await HomeWidget.saveWidgetData("uri", uri.host); } } void main() async { runZonedGuarded( () async { WidgetsFlutterBinding.ensureInitialized(); try { if (!kIsWeb) { HomeWidget.registerBackgroundCallback(_backgroundCallbackHomeWidget); HomeWidget.registerInteractivityCallback( _backgroundCallbackHomeWidget); await NotificationService.initializeNotification(); if (Platform.isAndroid) { try { await FlutterDownloader.initialize(debug: true, ignoreSsl: true); } catch (e) { e.printError(); } } } await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform); await FirebaseApi().initNotification(); } catch (e) { debugPrint("Initialization Error: $e"); } await SentryFlutter.init( (options) { options.dsn = 'https://a4cfcaa7d67471240d295c25c968d91d@o4508585857384448.ingest.de.sentry.io/4508585886548048'; options.tracesSampleRate = 1.0; options.profilesSampleRate = 1.0; }, appRunner: () => runApp(const Didvan()), ); }, (error, stack) { Sentry.captureException(error, stackTrace: stack); }, ); } class Didvan extends StatefulWidget { const Didvan({Key? key}) : super(key: key); @override State createState() => _DidvanState(); } class _DidvanState extends State with WidgetsBindingObserver { late final AppLinks _appLinks; StreamSubscription? _linkSubscription; final List _applicationProviders = [ ChangeNotifierProvider(create: (_) => PodcastsState()), ChangeNotifierProvider(create: (_) => MediaProvider()), ChangeNotifierProvider(create: (_) => UserProvider()), ChangeNotifierProvider(create: (_) => ThemeProvider()), ChangeNotifierProvider( create: (_) => StudioDetailsState()), ChangeNotifierProvider( create: (_) => HistoryAiChatState()), ChangeNotifierProvider(create: (_) => AiState()), ChangeNotifierProvider(create: (_) => AiChatState()), ChangeNotifierProvider( create: (_) => BotAssistantsState()), ]; @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); _initDeepLinks(); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); _linkSubscription?.cancel(); if (MediaService.currentPodcast != null) { MediaService.audioPlayer.dispose(); } super.dispose(); } Future _initDeepLinks() async { _appLinks = AppLinks(); initialURI = await _appLinks.getInitialLink(); _linkSubscription = _appLinks.uriLinkStream.listen((uri) { _navigateTo(uri); }); } void _navigateTo(Uri uri) { if (!mounted) return; final Map params = uri.queryParameters; final String? token = params['token']; if (token != null) { debugPrint("DeepLink Token Received: $token"); RequestService.token = token; } final String path = uri.path; if (path.startsWith('/news/')) { final String idStr = path.split('/news/').last; final int? id = int.tryParse(idStr); if (id != null) { navigatorKey.currentState?.pushNamed( Routes.newsDetails, arguments: {'id': id, 'args': const NewsRequestArgs(page: 0)}, ); } } else if (path.startsWith('/radar/')) { final String idStr = path.split('/radar/').last; final int? id = int.tryParse(idStr); if (id != null) { navigatorKey.currentState?.pushNamed( Routes.radarDetails, arguments: {'id': id, 'args': const RadarRequestArgs(page: 0)}, ); } } } @override void didChangeAppLifecycleState(AppLifecycleState state) async { if (!kIsWeb && state == AppLifecycleState.resumed) { final route = await HomeWidget.getWidgetData("cRoute", defaultValue: ''); if (route.toString() != Routes.splash) { await HomeWidgetRepository.decideWhereToGo(); if (HomeWidgetRepository.data != null) { await HomeWidgetRepository.decideWhereToGoNotif(); } } } } @override Widget build(BuildContext context) { return MultiProvider( providers: _applicationProviders, child: Consumer( builder: (context, themeProvider, child) { final lightTheme = LightThemeConfig.themeData.copyWith( bottomSheetTheme: const BottomSheetThemeData( surfaceTintColor: Colors.transparent, backgroundColor: Colors.transparent, ), textTheme: LightThemeConfig.themeData.textTheme.apply( fontFamily: themeProvider.fontFamily, ), ); final darkTheme = DarkThemeConfig.themeData.copyWith( bottomSheetTheme: const BottomSheetThemeData( surfaceTintColor: Colors.transparent, backgroundColor: Colors.transparent, ), textTheme: DarkThemeConfig.themeData.textTheme.apply( fontFamily: themeProvider.fontFamily, ), ); return Container( color: Theme.of(context).colorScheme.surface, child: SafeArea( child: MaterialApp( scrollBehavior: MyCustomScrollBehavior(), navigatorKey: navigatorKey, debugShowCheckedModeBanner: false, title: 'Didvan', theme: lightTheme, darkTheme: darkTheme, color: lightTheme.primaryColor, themeMode: themeProvider.themeMode, onGenerateRoute: (settings) => RouteGenerator.generateRoute(settings), builder: BotToastInit(), navigatorObservers: [BotToastNavigatorObserver()], initialRoute: "/", localizationsDelegates: const [ GlobalCupertinoLocalizations.delegate, GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, ], supportedLocales: const [ Locale("fa", "IR"), ], locale: const Locale("fa", "IR"), ), ), ); }, ), ); } }