import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '../utils/app_lock_service.dart'; import '../utils/app_theme.dart'; class AppLockOverlay extends StatefulWidget { const AppLockOverlay({ super.key, required this.child, }); final Widget child; @override State createState() => _AppLockOverlayState(); } class _AppLockOverlayState extends State with WidgetsBindingObserver { bool _shouldRelockOnResume = false; @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); super.dispose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { final service = AppLockService.instance; if (!service.isEnabled) return; if (state == AppLifecycleState.inactive || state == AppLifecycleState.paused || state == AppLifecycleState.hidden) { _shouldRelockOnResume = true; return; } if (state == AppLifecycleState.resumed && _shouldRelockOnResume) { _shouldRelockOnResume = false; service.lock(); } } @override Widget build(BuildContext context) { return AnimatedBuilder( animation: AppLockService.instance, builder: (context, _) { final service = AppLockService.instance; return Stack( fit: StackFit.expand, children: [ widget.child, if (service.initialized && service.isLocked) const Positioned.fill(child: _AppLockBarrier()), ], ); }, ); } } class _AppLockBarrier extends StatelessWidget { const _AppLockBarrier(); @override Widget build(BuildContext context) { return PopScope( canPop: false, child: Material( color: AppTheme.darkBg.withValues(alpha: 0.96), child: Stack( fit: StackFit.expand, children: [ Positioned.fill( child: CustomPaint( painter: _LockBackgroundPainter(), ), ), const SafeArea( child: Center( child: Padding( padding: EdgeInsets.all(20), child: _AppLockCard(), ), ), ), ], ), ), ); } } class _AppLockCard extends StatefulWidget { const _AppLockCard(); @override State<_AppLockCard> createState() => _AppLockCardState(); } class _AppLockCardState extends State<_AppLockCard> { final TextEditingController _controller = TextEditingController(); bool _isVerifying = false; String? _errorText; @override void dispose() { _controller.dispose(); super.dispose(); } Future _unlock() async { if (_isVerifying) return; FocusScope.of(context).unfocus(); final passcode = _controller.text.trim(); if (passcode.isEmpty) { setState(() => _errorText = 'رمز برنامه را وارد کنید.'); return; } setState(() { _isVerifying = true; _errorText = null; }); final isValid = await AppLockService.instance.verifyPasscode(passcode); if (!mounted) return; setState(() { _isVerifying = false; _errorText = isValid ? null : 'رمز واردشده درست نیست.'; }); if (isValid) { _controller.clear(); } } @override Widget build(BuildContext context) { final theme = Theme.of(context); return ConstrainedBox( constraints: const BoxConstraints(maxWidth: 420), child: AppTheme.glassWrapper( radius: 28, sigma: 14, child: Padding( padding: const EdgeInsets.fromLTRB(24, 28, 24, 24), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( width: 76, height: 76, decoration: BoxDecoration( shape: BoxShape.circle, gradient: LinearGradient( colors: [ theme.primaryColor.withValues(alpha: 0.95), AppTheme.accentCyan.withValues(alpha: 0.95), ], ), boxShadow: [ BoxShadow( color: theme.primaryColor.withValues(alpha: 0.28), blurRadius: 20, spreadRadius: 1, ), ], ), child: const Icon( Icons.lock_rounded, size: 38, color: Colors.white, ), ), const SizedBox(height: 18), const Text( 'قفل برنامه فعال است', style: TextStyle( fontSize: 22, fontWeight: FontWeight.bold, color: Colors.white, ), textAlign: TextAlign.center, ), const SizedBox(height: 10), const Text( 'برای ورود به صبا، رمز برنامه را وارد کنید.', style: TextStyle( fontSize: 14, height: 1.6, color: Colors.white70, ), textAlign: TextAlign.center, ), const SizedBox(height: 24), TextField( controller: _controller, autofocus: true, keyboardType: TextInputType.number, textInputAction: TextInputAction.done, obscureText: true, obscuringCharacter: '•', inputFormatters: [ FilteringTextInputFormatter.digitsOnly, LengthLimitingTextInputFormatter(8), ], onSubmitted: (_) => _unlock(), decoration: InputDecoration( labelText: 'رمز برنامه', hintText: '۴ تا ۸ رقم', errorText: _errorText, filled: true, fillColor: Colors.white.withValues(alpha: 0.06), border: OutlineInputBorder( borderRadius: BorderRadius.circular(16), ), ), ), const SizedBox(height: 18), SizedBox( width: double.infinity, child: ElevatedButton.icon( onPressed: _isVerifying ? null : _unlock, style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 15), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), ), icon: _isVerifying ? const SizedBox( width: 18, height: 18, child: CircularProgressIndicator(strokeWidth: 2), ) : const Icon(Icons.lock_open_rounded), label: Text(_isVerifying ? 'در حال بررسی...' : 'ورود به برنامه'), ), ), ], ), ), ), ); } } class _LockBackgroundPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { final purplePaint = Paint() ..shader = RadialGradient( colors: [ AppTheme.accentPurple.withValues(alpha: 0.22), AppTheme.accentPurple.withValues(alpha: 0), ], ).createShader( Rect.fromCircle( center: Offset(size.width * 0.18, size.height * 0.2), radius: size.width * 0.55, ), ); final cyanPaint = Paint() ..shader = RadialGradient( colors: [ AppTheme.accentCyan.withValues(alpha: 0.14), AppTheme.accentCyan.withValues(alpha: 0), ], ).createShader( Rect.fromCircle( center: Offset(size.width * 0.82, size.height * 0.78), radius: size.width * 0.6, ), ); canvas.drawCircle( Offset(size.width * 0.18, size.height * 0.2), size.width * 0.55, purplePaint, ); canvas.drawCircle( Offset(size.width * 0.82, size.height * 0.78), size.width * 0.6, cyanPaint, ); } @override bool shouldRepaint(covariant CustomPainter oldDelegate) => false; }