LCOV - code coverage report
Current view: top level - lib/exercises/widget - exercise_header.dart Coverage Total Hit
Test: lcov.info Lines: 1.8 % 56 1
Test Date: 2025-05-10 20:26:13 Functions: - 0 0

            Line data    Source code
       1              : import 'package:amadeus_proto/exercises/exercises_provider.dart';
       2              : import 'package:amadeus_proto/exercises/widget/previous_button.dart';
       3              : import 'package:flutter/material.dart';
       4              : import 'package:flutter/scheduler.dart';
       5              : import 'package:flutter_svg/svg.dart';
       6              : import 'package:provider/provider.dart';
       7              : 
       8              : /// Widget that will display the header of the exercise.
       9              : ///
      10              : /// This widget is generic type [T] that must extends from
      11              : /// the [ExerciseProvider].
      12              : ///
      13              : /// This widget will display :
      14              : /// - [IconButton] to quit the exercise page.
      15              : /// - [ListView] of lives [Icon] in a row to display how many lives
      16              : ///   the user still have. We get the number of lives by its
      17              : ///   corresponding [ExerciseProvider]
      18              : 
      19              : class ExerciseHeader<T extends ExerciseProvider> extends StatefulWidget {
      20           60 :   const ExerciseHeader({super.key});
      21              : 
      22            0 :   @override
      23            0 :   State<ExerciseHeader<T>> createState() => _ExerciseHeaderState<T>();
      24              : }
      25              : 
      26              : class _ExerciseHeaderState<T extends ExerciseProvider>
      27              :     extends State<ExerciseHeader<T>> with TickerProviderStateMixin {
      28              :   final List<AnimationController> _animationControllers = [];
      29              :   final List<Animation<Offset>> _animations = [];
      30              :   final List<Animation<double>> _animationOpacities = [];
      31              : 
      32            0 :   void _triggerAnimation() {
      33            0 :     final animationController = AnimationController(
      34              :       vsync: this,
      35              :       duration: const Duration(milliseconds: 1000),
      36              :     );
      37              : 
      38            0 :     final animation = Tween<Offset>(
      39              :       begin: const Offset(0, 0),
      40              :       end: const Offset(0, 0.5),
      41            0 :     ).animate(animationController);
      42              : 
      43              :     final animationOpacity =
      44            0 :         Tween<double>(begin: 1, end: 0).animate(animationController);
      45              : 
      46            0 :     setState(() {
      47            0 :       _animationControllers.add(animationController);
      48            0 :       _animations.add(animation);
      49            0 :       _animationOpacities.add(animationOpacity);
      50              :     });
      51              : 
      52            0 :     animationController.forward().whenComplete(() {
      53            0 :       setState(() {
      54            0 :         int index = _animationControllers.indexOf(animationController);
      55            0 :         if (index != -1) {
      56            0 :           _animationControllers.removeAt(index);
      57            0 :           _animations.removeAt(index);
      58            0 :           _animationOpacities.removeAt(index);
      59              :         }
      60              :       });
      61              :     });
      62              :   }
      63              : 
      64            0 :   @override
      65              :   void dispose() {
      66            0 :     for (var controller in _animationControllers) {
      67            0 :       controller.dispose();
      68              :     }
      69            0 :     super.dispose();
      70              :   }
      71              : 
      72            0 :   @override
      73              :   Widget build(BuildContext context) {
      74            0 :     return Consumer<T>(
      75            0 :       builder: (context, provider, child) {
      76            0 :         SchedulerBinding.instance.addPostFrameCallback((_) {
      77            0 :           if (provider.correctAnswer != null && !provider.correctAnswer!) {
      78            0 :             _triggerAnimation();
      79            0 :             provider.correctAnswer = null; // Reset flag
      80              :           }
      81              :         });
      82            0 :         return Row(
      83              :           mainAxisAlignment: MainAxisAlignment.spaceBetween,
      84            0 :           children: [
      85              :             const PreviousButton(),
      86            0 :             Stack(
      87            0 :               children: [
      88            0 :                 ...List.generate(_animations.length, (index) {
      89            0 :                   return AnimatedSwitcher(
      90              :                       duration: const Duration(milliseconds: 1000),
      91            0 :                       transitionBuilder: (Widget child, _) => FadeTransition(
      92            0 :                             opacity: _animationOpacities[index],
      93            0 :                             child: SlideTransition(
      94            0 :                               position: _animations[index],
      95              :                               child: child,
      96              :                             ),
      97              :                           ),
      98            0 :                       child: Container(
      99            0 :                           key: UniqueKey(),
     100              :                           width: 65,
     101              :                           height: 40,
     102              :                           margin: const EdgeInsets.all(10),
     103            0 :                           decoration: BoxDecoration(
     104            0 :                             borderRadius: BorderRadius.circular(50),
     105              :                           ),
     106            0 :                           child: Row(
     107              :                             crossAxisAlignment: CrossAxisAlignment.center,
     108              :                             mainAxisAlignment: MainAxisAlignment.center,
     109            0 :                             children: [
     110            0 :                               SvgPicture.asset(
     111              :                                 "assets/FigmaDesign/Asset/SVG/Heart.svg",
     112              :                                 width: 25,
     113              :                                 height: 25,
     114              :                                 fit: BoxFit.fill,
     115              :                               ),
     116              :                               const SizedBox(width: 5),
     117              :                               const Text(
     118              :                                 "-1",
     119              :                                 style: TextStyle(
     120              :                                     fontSize: 16,
     121              :                                     fontWeight: FontWeight.w700,
     122              :                                     fontStyle: FontStyle.normal),
     123              :                               )
     124              :                             ],
     125              :                           )));
     126              :                   // : const SizedBox.shrink());
     127              :                 }),
     128            0 :                 Container(
     129              :                     width: 65,
     130              :                     height: 40,
     131              :                     margin: const EdgeInsets.all(10),
     132            0 :                     decoration: BoxDecoration(
     133            0 :                       borderRadius: BorderRadius.circular(50),
     134            0 :                       border: Border.all(color: const Color(0xFFDFDFDF)),
     135              :                     ),
     136            0 :                     child: Row(
     137              :                       crossAxisAlignment: CrossAxisAlignment.center,
     138              :                       mainAxisAlignment: MainAxisAlignment.center,
     139            0 :                       children: [
     140            0 :                         SvgPicture.asset(
     141              :                           "assets/FigmaDesign/Asset/SVG/Heart.svg",
     142              :                           width: 25,
     143              :                           height: 25,
     144              :                           fit: BoxFit.fill,
     145              :                         ),
     146              :                         const SizedBox(width: 5),
     147            0 :                         Text(
     148            0 :                           provider.lives.toString(),
     149              :                           style: const TextStyle(
     150              :                               fontSize: 16,
     151              :                               fontWeight: FontWeight.w700,
     152              :                               fontStyle: FontStyle.normal),
     153              :                         )
     154              :                       ],
     155              :                     )),
     156              :               ],
     157              :             ),
     158              :           ],
     159              :         );
     160              :       },
     161              :     );
     162              :   }
     163              : }
        

Generated by: LCOV version 2.3-1