import 'dart:async'; import 'dart:math'; import 'package:flutter/material.dart'; /// Simple binary rain animation with a label for the update check splash. class UpdateCheckingScreen extends StatefulWidget { const UpdateCheckingScreen({super.key}); @override State createState() => _UpdateCheckingScreenState(); } class _UpdateCheckingScreenState extends State { static const int cols = 20; final List<_Drop> _drops = []; Timer? _timer; final Random _rng = Random(); @override void initState() { super.initState(); _timer = Timer.periodic(const Duration(milliseconds: 50), (_) { _tick(); }); } void _tick() { setState(() { if (_rng.nextDouble() < 0.3 || _drops.isEmpty) { _drops.add( _Drop( col: _rng.nextInt(cols), y: 0.0, speed: _rng.nextDouble() * 4 + 2, ), ); } _drops.removeWhere((d) => d.y > MediaQuery.of(context).size.height); for (final d in _drops) { d.y += d.speed; } }); } @override void dispose() { _timer?.cancel(); super.dispose(); } @override Widget build(BuildContext context) { final cs = Theme.of(context).colorScheme; return Scaffold( backgroundColor: cs.surface, body: SafeArea( child: Column( children: [ const SizedBox(height: 40), Hero( tag: 'tasq-logo', child: Image.asset('assets/tasq_ico.png', height: 80, width: 80), ), const SizedBox(height: 24), Expanded( child: CustomPaint( size: Size.infinite, painter: _BinaryRainPainter(_drops, cols, cs.primary), ), ), const SizedBox(height: 24), Text( 'Checking for updates...', style: Theme.of(context).textTheme.titleMedium?.copyWith( color: cs.onSurface.withAlpha((0.75 * 255).round()), ), ), const SizedBox(height: 40), ], ), ), ); } } class _Drop { int col; double y; double speed; _Drop({required this.col, required this.y, required this.speed}); } class _BinaryRainPainter extends CustomPainter { static const double fontSize = 16; final List<_Drop> drops; final int cols; final Color textColor; _BinaryRainPainter(this.drops, this.cols, this.textColor); @override void paint(Canvas canvas, Size size) { // paint variable not needed when drawing text final textStyle = TextStyle( color: textColor, fontSize: fontSize, fontFeatures: const [FontFeature.tabularFigures()], ); final cellW = size.width / cols; for (final d in drops) { final text = (Random().nextBool() ? '1' : '0'); final tp = TextPainter( text: TextSpan(text: text, style: textStyle), textAlign: TextAlign.center, textDirection: TextDirection.ltr, )..layout(); final x = d.col * cellW + (cellW - tp.width) / 2; final y = d.y; tp.paint(canvas, Offset(x, y)); } } @override bool shouldRepaint(covariant _BinaryRainPainter old) => true; }