// ignore_for_file: deprecated_member_use, avoid_print import 'package:didvan/config/design_config.dart'; import 'package:didvan/constants/assets.dart'; import 'package:didvan/main.dart'; import 'package:didvan/providers/media.dart'; import 'package:didvan/providers/server_data.dart'; import 'package:didvan/providers/theme.dart'; import 'package:didvan/providers/user.dart'; import 'package:didvan/routes/routes.dart'; import 'package:didvan/services/app_initalizer.dart'; import 'package:didvan/services/network/request.dart'; import 'package:didvan/services/storage/storage.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:provider/provider.dart'; import 'package:universal_html/html.dart' as html; class Splash extends StatefulWidget { const Splash({Key? key}) : super(key: key); @override State createState() => _SplashState(); } class _SplashState extends State with TickerProviderStateMixin { bool _errorOccured = false; late ThemeProvider themeProvider; late UserProvider userProvider; late MediaProvider mediaProvider; late AnimationController _pulseController; late Animation _pulseAnimation; @override void initState() { super.initState(); _pulseController = AnimationController( duration: const Duration(milliseconds: 1500), vsync: this, ); _pulseAnimation = Tween( begin: 1.0, end: 1.1, ).animate(CurvedAnimation( parent: _pulseController, curve: Curves.easeInOut, )); _pulseController.repeat(reverse: true); themeProvider = context.read(); userProvider = context.read(); mediaProvider = context.read(); _initialize(themeProvider, userProvider, mediaProvider); } @override void dispose() { _pulseController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; final isDark = Theme.of(context).brightness == Brightness.dark; return AnnotatedRegion( value: DesignConfig.systemUiOverlayStyle.copyWith( systemNavigationBarColor: colorScheme.background, statusBarColor: Colors.transparent, statusBarIconBrightness: isDark ? Brightness.light : Brightness.dark, ), child: Scaffold( backgroundColor: colorScheme.background, body: SafeArea( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Spacer(flex: 2), TweenAnimationBuilder( duration: const Duration(milliseconds: 800), tween: Tween(begin: 0.0, end: 1.0), builder: (context, value, child) { return Opacity( opacity: value, child: AnimatedBuilder( animation: _pulseAnimation, builder: (context, child) { return Transform.scale( scale: _pulseAnimation.value, child: SvgPicture.asset( Assets.horizontalLogoWithText, height: 80, ), ); }, ), ); }, ), const SizedBox(height: 60), if (!_errorOccured) ...[ SizedBox( width: 60, height: 60, child: Image.asset( Assets.loadingAnimation, fit: BoxFit.contain, ), ), const SizedBox(height: 24), AnimatedBuilder( animation: _pulseController, builder: (context, child) { return Opacity( opacity: 0.4 + (0.4 * _pulseController.value), child: Text( 'در حال بارگذاری...', style: TextStyle( fontSize: 14, color: colorScheme.onBackground.withOpacity(0.6), fontWeight: FontWeight.w400, ), ), ); }, ), ] else ...[ Container( width: 56, height: 56, decoration: BoxDecoration( color: colorScheme.error.withOpacity(0.1), shape: BoxShape.circle, ), child: Icon( Icons.wifi_off_rounded, size: 24, color: colorScheme.error, ), ), const SizedBox(height: 16), Text( 'مشکل در اتصال', style: TextStyle( fontSize: 16, color: colorScheme.onBackground, fontWeight: FontWeight.w500, ), ), const SizedBox(height: 8), Text( 'لطفاً اتصال اینترنت خود را بررسی کنید', style: TextStyle( fontSize: 13, color: colorScheme.onBackground.withOpacity(0.6), ), ), const SizedBox(height: 24), ElevatedButton( onPressed: () { setState(() { _errorOccured = false; }); _initialize(themeProvider, userProvider, mediaProvider); }, style: ElevatedButton.styleFrom( backgroundColor: colorScheme.primary, foregroundColor: Colors.white, elevation: 0, padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: const Text( 'تلاش مجدد', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, ), ), ), ], const Spacer(flex: 3), ], ), ), ), ), ); } Future _initialize(ThemeProvider themeProvider, UserProvider userProvider, MediaProvider mediaProvider) async { try { print("checking if is in browser"); if (kIsWeb) { print("detected browser"); html.window.onBeforeUnload.listen((event) { StorageService.webStorage .removeWhere((key, value) => key == 'image-cache'); }); } final settingsData = await AppInitializer.initilizeSettings(); themeProvider.themeMode = settingsData.themeMode; themeProvider.fontFamily = settingsData.fontFamily; themeProvider.fontScale = settingsData.fontScale; await AppInitializer.setupServices(navigatorKey.currentContext!); final String? hasSeenOnboarding = await StorageService.getValue(key: 'hasSeenOnboarding'); if (hasSeenOnboarding == null || hasSeenOnboarding != 'true') { await navigatorKey.currentState!.pushReplacementNamed(Routes.onboarding); return; } final String? token = await userProvider.setAndGetToken(); print("detected token as $token"); if (token != null) { RequestService.token = token; if (!kIsWeb) { await mediaProvider.getDownloadsList(); } // اگر اینجا خطای سرور رخ دهد (به خاطر تغییر در user.dart)، کد به بلوک catch می‌رود final result = await userProvider.getUserInfo(); if (!result) { // این بخش فقط زمانی اجرا می‌شود که سرور پاسخ ۴۰۱ (نامعتبر بودن توکن) داده باشد print("no results were returned for user info"); try { StorageService.delete(key: 'token'); } catch (e) { print("error in case of no user info result: $e"); } navigatorKey.currentState!.pushNamedAndRemoveUntil( Routes.splash, (_) => false, ); return; } print("got results for user info: $result"); await ServerDataProvider.getData(); } print("token route is $token"); String extractedPath = initialURI?.path.toString() == '/' ? Routes.home : initialURI?.path.toString() ?? Routes.home; final String destinationRoute = token == null ? Routes.authenticaion : extractedPath; dynamic routeArguments = token == null ? {'isResetPassword': false} : {'showDialogs': false}; if (destinationRoute == Routes.home) { print("destination route was home and init uri is $initialURI"); initialURI = null; } if(destinationRoute == Routes.authenticaion){ print("destination route is auth route"); routeArguments = false; } print("destination route: $destinationRoute, route args: $routeArguments"); await navigatorKey.currentState!.pushReplacementNamed( destinationRoute, arguments: routeArguments, ); } catch (e) { // اگر خطای سرور رخ دهد، اینجا گرفته می‌شود و دکمه تلاش مجدد نشان داده می‌شود setState(() { _errorOccured = true; }); } } }