LCOV - code coverage report
Current view: top level - lib/pages/home/widgets/streak widgets - streak_card.dart Coverage Total Hit
Test: lcov.info Lines: 0.0 % 76 0
Test Date: 2025-05-10 20:26:13 Functions: - 0 0

            Line data    Source code
       1              : import 'dart:math';
       2              : 
       3              : import 'package:amadeus_proto/api/models/profile.dart';
       4              : import 'package:amadeus_proto/pages/home/widgets/streak%20widgets/streak_calendar_preview.dart';
       5              : import 'package:amadeus_proto/pages/home/widgets/streak%20widgets/streak_preview.dart';
       6              : import 'package:flutter/material.dart';
       7              : import 'package:localization/localization.dart';
       8              : 
       9              : class StreakCard extends StatefulWidget {
      10            0 :   const StreakCard({super.key, this.height = 250, required this.user});
      11              : 
      12              :   final double height;
      13              :   final Profile user;
      14              : 
      15            0 :   @override
      16            0 :   State<StreakCard> createState() => _StreakCardState();
      17              : }
      18              : 
      19              : class _StreakCardState extends State<StreakCard>
      20              :     with SingleTickerProviderStateMixin {
      21              :   late Animation<double> animation;
      22              :   late AnimationController controller;
      23              : 
      24            0 :   @override
      25              :   void initState() {
      26            0 :     super.initState();
      27            0 :     controller =
      28            0 :         AnimationController(duration: const Duration(seconds: 5), vsync: this)
      29            0 :           ..addStatusListener((status) {
      30            0 :             if (status == AnimationStatus.completed) {
      31            0 :               controller.reset();
      32            0 :               controller.forward();
      33              :             }
      34              :           });
      35            0 :     animation = Tween<double>(begin: -0.8, end: 2.8).animate(controller);
      36            0 :     controller.forward();
      37              :   }
      38              : 
      39            0 :   @override
      40              :   void dispose() {
      41            0 :     controller.dispose();
      42            0 :     super.dispose();
      43              :   }
      44              : 
      45            0 :   @override
      46              :   Widget build(BuildContext context) {
      47            0 :     return Card(
      48            0 :       color: Theme.of(context).primaryColor,
      49            0 :       shape: RoundedRectangleBorder(
      50            0 :         borderRadius: BorderRadius.circular(24),
      51              :       ),
      52            0 :       child: ClipRRect(
      53            0 :         borderRadius: BorderRadius.circular(24),
      54            0 :         child: AnimatedDottedBackgroud(
      55            0 :           animation: animation,
      56            0 :           height: widget.height,
      57            0 :           child: SizedBox(
      58            0 :             height: widget.height,
      59            0 :             child: Column(
      60            0 :               children: [
      61            0 :                 Padding(
      62              :                   padding: const EdgeInsets.only(top: 8.0),
      63            0 :                   child: SizedBox(
      64            0 :                     height: widget.height / 2.2,
      65            0 :                     child: StreakPreview(
      66            0 :                       user: widget.user,
      67              :                     ),
      68              :                   ),
      69              :                 ),
      70            0 :                 Text(
      71            0 :                   "streak.message".i18n([widget.user.streakDays.length.toString()]),
      72              :                   style: const TextStyle(
      73              :                     color: Colors.white,
      74              :                     fontSize: 17,
      75              :                   ),
      76              :                 ),
      77            0 :                 Text(
      78            0 :                   "calendar.status".i18n(),
      79              :                   style: const TextStyle(
      80              :                     color: Colors.white,
      81              :                     fontSize: 11,
      82              :                   ),
      83              :                 ),
      84            0 :                 Expanded(
      85            0 :                   child: StreakCalendarPreview(
      86            0 :                     user: widget.user,
      87              :                   ),
      88              :                 )
      89              :               ],
      90              :             ),
      91              :           ),
      92              :         ),
      93              :       ),
      94              :     );
      95              :   }
      96              : }
      97              : 
      98              : class AnimatedDottedBackgroud extends AnimatedWidget {
      99            0 :   const AnimatedDottedBackgroud(
     100              :       {super.key,
     101              :       required this.height,
     102              :       this.curve = Curves.linear,
     103              :       required Animation<double> animation,
     104              :       this.child})
     105            0 :       : super(listenable: animation);
     106              : 
     107              :   final double height;
     108              :   final Curve curve;
     109              :   final Widget? child;
     110              : 
     111            0 :   @override
     112              :   Widget build(BuildContext context) {
     113            0 :     final animation = listenable as Animation<double>;
     114            0 :     return CustomPaint(
     115            0 :         painter: _DottedFadeOutPatternPainter(
     116              :           baseOpacity: 0.7,
     117            0 :           animationProgress: animation.value,
     118              :           color: Colors.white,
     119              :           radius: 2,
     120              :           spacing: 15,
     121              :         ),
     122            0 :         child: child);
     123              :   }
     124              : }
     125              : 
     126              : class _DottedFadeOutPatternPainter extends CustomPainter {
     127            0 :   _DottedFadeOutPatternPainter(
     128              :       {required this.animationProgress,
     129              :       this.color,
     130              :       this.style,
     131              :       this.radius,
     132              :       this.spacing,
     133              :       required this.baseOpacity});
     134              : 
     135              :   final Color? color;
     136              :   final PaintingStyle? style;
     137              :   final double? radius;
     138              :   final double? spacing;
     139              :   final double animationProgress;
     140              :   final double baseOpacity;
     141              : 
     142            0 :   @override
     143              :   void paint(Canvas canvas, Size size) {
     144            0 :     assert(0 <= baseOpacity && baseOpacity <= 1);
     145            0 :     final Paint paint = Paint()
     146            0 :       ..color = color ?? Colors.blue
     147            0 :       ..style = style ?? PaintingStyle.fill;
     148              : 
     149              :     Offset fadePoint1 =
     150            0 :         Offset(0, size.height - (animationProgress * size.height));
     151              :     Offset fadePoint2 =
     152            0 :         Offset(0 + (animationProgress * size.width), size.height);
     153              : 
     154            0 :     double spacing = this.spacing ?? 20.0;
     155            0 :     for (double x = 0; x < size.width + spacing; x += spacing) {
     156            0 :       for (double y = size.height; y > 0 - spacing; y -= spacing) {
     157            0 :         Offset currentPoint = Offset(x, y);
     158            0 :         double numerator = (currentPoint.dx - fadePoint1.dx) *
     159            0 :                 (fadePoint2.dx - fadePoint1.dx) +
     160            0 :             (currentPoint.dy - fadePoint1.dy) * (fadePoint2.dy - fadePoint1.dy);
     161            0 :         num denominator = pow(fadePoint2.dx - fadePoint1.dx, 2) +
     162            0 :             pow(fadePoint2.dy - fadePoint1.dy, 2);
     163              :         double k = 0;
     164            0 :         if (denominator != 0) {
     165            0 :           k = numerator / denominator;
     166              :         }
     167              : 
     168            0 :         Offset p = Offset(fadePoint1.dx + k * (fadePoint2.dx - fadePoint1.dx),
     169            0 :             fadePoint1.dy + k * (fadePoint2.dy - fadePoint1.dy));
     170              : 
     171            0 :         double distance = (p - currentPoint).distance / size.shortestSide;
     172            0 :         double opacity = max(baseOpacity - distance, 0);
     173            0 :         paint.color = paint.color.withOpacity(opacity);
     174            0 :         canvas.drawCircle(Offset(x, y), radius ?? 5.0, paint);
     175              :       }
     176              :     }
     177              :   }
     178              : 
     179            0 :   @override
     180              :   bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
     181              : }
        

Generated by: LCOV version 2.3-1