import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:flutter_in_store_app_version_checker/flutter_in_store_app_version_checker.dart'; import 'package:on_field_work/helpers/services/app_logger.dart'; import 'package:on_field_work/helpers/utils/mixins/ui_mixin.dart'; import 'package:on_field_work/images.dart'; import 'package:on_field_work/helpers/widgets/wave_background.dart'; class MandatoryUpdateScreen extends StatefulWidget { final String newVersion; final InStoreAppVersionCheckerResult? updateResult; const MandatoryUpdateScreen({ super.key, required this.newVersion, this.updateResult, }); @override State createState() => _MandatoryUpdateScreenState(); } class _MandatoryUpdateScreenState extends State with SingleTickerProviderStateMixin, UIMixin { late AnimationController _controller; late Animation _logoAnimation; static const double _kMaxContentWidth = 480.0; Color get _primaryColor => contentTheme.primary; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 800), ); _logoAnimation = CurvedAnimation( parent: _controller, curve: Curves.elasticOut, ); _controller.forward(); } @override void dispose() { _controller.dispose(); super.dispose(); } Future _launchStoreUrl() async { final url = widget.updateResult?.appURL; if (url != null && url.isNotEmpty) { final uri = Uri.parse(url); try { if (await canLaunchUrl(uri)) { await launchUrl(uri, mode: LaunchMode.externalApplication); } else { logSafe("Could not launch store URL: $url"); } } catch (e, stack) { logSafe( "Error launching store URL: $url", error: e, stackTrace: stack, level: LogLevel.error, ); } } } @override Widget build(BuildContext context) { return Directionality( textDirection: TextDirection.ltr, child: Scaffold( body: Stack( children: [ RedWaveBackground(brandRed: _primaryColor), SafeArea( child: Center( child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: _kMaxContentWidth), child: SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 24), child: Column( mainAxisSize: MainAxisSize.min, children: [ const SizedBox(height: 32), ScaleTransition( scale: _logoAnimation, child: Container( width: 100, height: 100, decoration: BoxDecoration( color: Colors.white, shape: BoxShape.circle, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 20, offset: const Offset(0, 8), ), ], ), padding: const EdgeInsets.all(20), child: Image.asset(Images.logoDark), ), ), const SizedBox(height: 32), Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 5), ), ], ), padding: const EdgeInsets.all(32), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // Title Text( "Update Required", textAlign: TextAlign.center, style: Theme.of(context) .textTheme .headlineMedium ?.copyWith( fontWeight: FontWeight.bold, color: Colors.black87, ), ), const SizedBox(height: 12), // Subtitle/Message Text( "A mandatory update (version ${widget.newVersion}) is available to continue using the application. Please update now for uninterrupted access.", textAlign: TextAlign.center, style: Theme.of(context) .textTheme .bodyLarge ?.copyWith( color: Colors.black54, height: 1.4, ), ), const SizedBox(height: 32), // Prominent Action Button ElevatedButton.icon( onPressed: _launchStoreUrl, icon: const Icon( Icons.system_update_alt, color: Colors.white, ), label: Text( "UPDATE NOW", style: Theme.of(context) .textTheme .labelLarge ?.copyWith( fontWeight: FontWeight.w700, color: Colors.white, fontSize: 16, ), ), style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 18), backgroundColor: _primaryColor, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), elevation: 5, ), ), const SizedBox(height: 32), // Why Update Section Text( "Why updating is important:", textAlign: TextAlign.start, style: Theme.of(context) .textTheme .titleMedium ?.copyWith( fontWeight: FontWeight.w600, color: Colors.black87, ), ), const SizedBox(height: 12), const Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ BulletPoint( text: "Access new features and improvements"), BulletPoint( text: "Fix critical bugs and security issues"), BulletPoint( text: "Ensure smooth app performance and stability"), BulletPoint( text: "Stay compatible with latest operating system and services"), ], ), const SizedBox(height: 12), Text( "Thank you for keeping your app up to date!", textAlign: TextAlign.center, style: Theme.of(context) .textTheme .bodySmall ?.copyWith( color: Colors.black45, ), ), ], ), ), ], ), ), ), ), ), ], ), ), ); } } class BulletPoint extends StatelessWidget { final String text; final Color bulletColor; const BulletPoint({ super.key, required this.text, this.bulletColor = const Color(0xFF555555), }); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.only(bottom: 8), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.only(right: 8, top: 4), child: Icon( Icons.circle, size: 6, color: bulletColor, ), ), Expanded( child: Text( text, style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: Colors.black87, height: 1.4, ), ), ), ], ), ); } }