250 lines
8.4 KiB
Dart
250 lines
8.4 KiB
Dart
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<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
|
Uri? initialURI;
|
|
|
|
@pragma('vm:entry-point')
|
|
Future<void> _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<Didvan> createState() => _DidvanState();
|
|
}
|
|
|
|
class _DidvanState extends State<Didvan> with WidgetsBindingObserver {
|
|
late final AppLinks _appLinks;
|
|
StreamSubscription<Uri>? _linkSubscription;
|
|
|
|
final List<SingleChildWidget> _applicationProviders = [
|
|
ChangeNotifierProvider<PodcastsState>(create: (_) => PodcastsState()),
|
|
ChangeNotifierProvider<MediaProvider>(create: (_) => MediaProvider()),
|
|
ChangeNotifierProvider<UserProvider>(create: (_) => UserProvider()),
|
|
ChangeNotifierProvider<ThemeProvider>(create: (_) => ThemeProvider()),
|
|
ChangeNotifierProvider<StudioDetailsState>(
|
|
create: (_) => StudioDetailsState()),
|
|
ChangeNotifierProvider<HistoryAiChatState>(
|
|
create: (_) => HistoryAiChatState()),
|
|
ChangeNotifierProvider<AiState>(create: (_) => AiState()),
|
|
ChangeNotifierProvider<AiChatState>(create: (_) => AiChatState()),
|
|
ChangeNotifierProvider<BotAssistantsState>(
|
|
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<void> _initDeepLinks() async {
|
|
_appLinks = AppLinks();
|
|
initialURI = await _appLinks.getInitialLink();
|
|
_linkSubscription = _appLinks.uriLinkStream.listen((uri) {
|
|
_navigateTo(uri);
|
|
});
|
|
}
|
|
|
|
void _navigateTo(Uri uri) {
|
|
if (!mounted) return;
|
|
|
|
final Map<String, String> 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<ThemeProvider>(
|
|
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"),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
}
|