didvan-app/lib/views/splash/splash.dart

292 lines
10 KiB
Dart

// 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<Splash> createState() => _SplashState();
}
class _SplashState extends State<Splash> with TickerProviderStateMixin {
bool _errorOccured = false;
late ThemeProvider themeProvider;
late UserProvider userProvider;
late MediaProvider mediaProvider;
late AnimationController _pulseController;
late Animation<double> _pulseAnimation;
@override
void initState() {
super.initState();
_pulseController = AnimationController(
duration: const Duration(milliseconds: 1500),
vsync: this,
);
_pulseAnimation = Tween<double>(
begin: 1.0,
end: 1.1,
).animate(CurvedAnimation(
parent: _pulseController,
curve: Curves.easeInOut,
));
_pulseController.repeat(reverse: true);
themeProvider = context.read<ThemeProvider>();
userProvider = context.read<UserProvider>();
mediaProvider = context.read<MediaProvider>();
_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<SystemUiOverlayStyle>(
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<double>(
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<void> _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;
});
}
}
}