import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'global_data.dart'; import 'comp_16.dart'; class Comp15Screen extends StatefulWidget { const Comp15Screen({super.key}); @override State createState() => _Comp15ScreenState(); } class _Comp15ScreenState extends State { late List _puntiFirma; late bool isB; bool _isNavigating = false; @override void initState() { super.initState(); isB = GlobalData.latoCorrente == 'B'; _puntiFirma = isB ? List.from(GlobalData.puntiFirmaB) : List.from(GlobalData.puntiFirmaA); // Appena entro, ruoto in orizzontale SystemChrome.setPreferredOrientations([ DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight, ]); } // --- PUNTO CHIAVE: LA PULIZIA AUTOMATICA --- @override void dispose() { // Quando questa pagina viene distrutta (in qualsiasi modo), // FORZO immediatamente il ritorno al verticale. SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); super.dispose(); } Future _tornaIndietro() async { _salvaInMemoria(); if (mounted) Navigator.pop(context); } void _salvaInMemoria() { if (isB) { GlobalData.puntiFirmaB = List.from(_puntiFirma); } else { GlobalData.puntiFirmaA = List.from(_puntiFirma); } } Future _confermaEProsegui() async { _salvaInMemoria(); if (_puntiFirma.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("La firma è obbligatoria!"), backgroundColor: Colors.red), ); return; } setState(() => _isNavigating = true); if (mounted) { // Prima di andare alla 16, forzo GIA' il verticale qui. await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); // Piccola pausa per dare tempo all'animazione di rotazione await Future.delayed(const Duration(milliseconds: 100)); if (!mounted) return; // Navigo verso la 16. Uso pushReplacement per distruggere la 15 (e chiamare dispose) // oppure push normale, ma avendo già forzato il portrait sopra siamo sicuri. await Navigator.push( context, MaterialPageRoute(builder: (c) => const Comp16Screen()) ); // --- AGGIUNTA FONDAMENTALE --- // Aspettiamo un attimo. Se stiamo facendo "Cancella tutto", // in questo lasso di tempo la pagina verrà smontata (mounted diventerà false) // e il codice sotto NON verrà eseguito, evitando la trottola. await Future.delayed(const Duration(milliseconds: 300)); // ----------------------------- if (mounted && ModalRoute.of(context)?.isCurrent == true) { await SystemChrome.setPreferredOrientations([ DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight, ]); setState(() => _isNavigating = false); } // --------------------------- } } @override Widget build(BuildContext context) { // Ribadisco orizzontale nel build per sicurezza // SystemChrome.setPreferredOrientations([ // DeviceOrientation.landscapeLeft, // DeviceOrientation.landscapeRight, // ]); return PopScope( canPop: false, onPopInvokedWithResult: (didPop, result) async { if (!didPop) await _tornaIndietro(); }, child: Scaffold( backgroundColor: Colors.white, resizeToAvoidBottomInset: false, body: OrientationBuilder( builder: (context, orientation) { double shortestSide = MediaQuery.of(context).size.shortestSide; bool isTablet = shortestSide > 600; // Fix per iPad che potrebbe rimanere verticale if (orientation == Orientation.portrait) { return Center( child: RotatedBox( quarterTurns: 1, child: SizedBox( width: MediaQuery.of(context).size.height, height: MediaQuery.of(context).size.width, child: SafeArea(child: _buildBody(context, isTablet)), ), ), ); } return SafeArea(child: _buildBody(context, isTablet)); }, ), ), ); } Widget _buildBody(BuildContext context, bool isTablet) { Color mainCol = isB ? Colors.amber.shade700 : Colors.blue.shade900; double shortestSide = MediaQuery.of(context).size.shortestSide; double spessoreFirma = (shortestSide * 0.01).clamp(3.0, 8.0); double verticalPadding = isTablet ? MediaQuery.of(context).size.height * 0.12 : 2.0; double horizontalPadding = isTablet ? 80.0 : 5.0; return _isNavigating ? const Center(child: CircularProgressIndicator()) : Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Container( height: 50, color: mainCol, padding: const EdgeInsets.symmetric(horizontal: 10), child: Row(children: [ IconButton(icon: const Icon(Icons.arrow_back, color: Colors.white), onPressed: _tornaIndietro), Expanded(child: Text("15. Firma (${GlobalData.latoCorrente})", textAlign: TextAlign.center, style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 18))), const SizedBox(width: 48), ]), ), Expanded( child: Padding( padding: EdgeInsets.symmetric(vertical: verticalPadding, horizontal: horizontalPadding), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ if (isTablet) ...[const Text("Firma nello spazio sottostante:", style: TextStyle(fontSize: 16)), const SizedBox(height: 8)], Expanded( child: Container( width: double.infinity, decoration: BoxDecoration(border: Border.all(color: Colors.grey, width: 2), borderRadius: BorderRadius.circular(10), color: Colors.grey.shade50), child: ClipRRect( borderRadius: BorderRadius.circular(8), child: GestureDetector( onPanUpdate: (d) => setState(() => _puntiFirma.add(d.localPosition)), onPanEnd: (d) => setState(() => _puntiFirma.add(null)), child: RepaintBoundary(child: CustomPaint(painter: FirmaPainter(_puntiFirma, spessoreFirma), size: Size.infinite)), ), ), ), ), ], ), ), ), Padding( padding: EdgeInsets.fromLTRB(20, 5, 20, isTablet ? 15 : 5), child: Row(children: [ Expanded(flex: 1, child: SizedBox(height: 45, child: OutlinedButton.icon(onPressed: () => setState(() => _puntiFirma.clear()), icon: const Icon(Icons.delete, color: Colors.red), label: const Text("CANCELLA", style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold)), style: OutlinedButton.styleFrom(side: const BorderSide(color: Colors.red))))), const SizedBox(width: 20), Expanded(flex: 2, child: SizedBox(height: 45, child: ElevatedButton.icon(onPressed: _confermaEProsegui, style: ElevatedButton.styleFrom(backgroundColor: Colors.green[700], foregroundColor: Colors.white, elevation: 5), icon: const Icon(Icons.check_circle_outline), label: const Text("CONFERMA FIRMA", style: TextStyle(fontWeight: FontWeight.bold))))), ]), ), ], ); } } class FirmaPainter extends CustomPainter { final List punti; final double spessore; FirmaPainter(this.punti, this.spessore); @override void paint(Canvas canvas, Size size) { Paint p = Paint()..color = Colors.black..strokeWidth = spessore..strokeCap = StrokeCap.round..strokeJoin = StrokeJoin.round..style = PaintingStyle.stroke..isAntiAlias = true; for (int i = 0; i < punti.length - 1; i++) { if (punti[i] != null && punti[i + 1] != null) canvas.drawLine(punti[i]!, punti[i + 1]!, p); } } @override bool shouldRepaint(FirmaPainter old) => true; }