import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../l10n/app_localizations.dart'; import '../viewmodels/product_list_view_model.dart'; /// Movie-style end credits, opened by tapping the version number in settings. class CreditsView extends StatefulWidget { final String appVersion; const CreditsView({super.key, required this.appVersion}); @override State createState() => _CreditsViewState(); } class _CreditsViewState extends State with SingleTickerProviderStateMixin { late final AnimationController _controller = AnimationController( vsync: this, duration: const Duration(seconds: 25), )..forward(); @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context); final products = context.select>( (viewModel) => [ for (final product in viewModel.products) if (product.active) product.name, ], ); const titleStyle = TextStyle( color: Colors.white, fontSize: 34, fontWeight: FontWeight.w900, letterSpacing: 4, ); const headingStyle = TextStyle( color: Colors.white54, fontSize: 14, fontWeight: FontWeight.w600, letterSpacing: 3, ); const nameStyle = TextStyle( color: Colors.white, fontSize: 22, fontWeight: FontWeight.w700, ); final credits = Column( mainAxisSize: MainAxisSize.min, children: [ const Text('KOOLTAP', style: titleStyle), const SizedBox(height: 8), Text(l10n.version(widget.appVersion), style: headingStyle), const SizedBox(height: 64), Text(l10n.creditsDirectedBy.toUpperCase(), style: headingStyle), const SizedBox(height: 8), const Text('Bram Verhulst 👑', style: nameStyle), const SizedBox(height: 48), Text(l10n.creditsStarring.toUpperCase(), style: headingStyle), const SizedBox(height: 8), for (final name in products) Padding( padding: const EdgeInsets.symmetric(vertical: 6), child: Text(name, style: nameStyle, textAlign: TextAlign.center), ), const SizedBox(height: 48), Text(l10n.creditsSpecialThanks.toUpperCase(), style: headingStyle), const SizedBox(height: 8), Text(l10n.creditsEveryoneAtTheBar, style: nameStyle), const SizedBox(height: 96), Text( l10n.creditsDrinkResponsibly, style: headingStyle, textAlign: TextAlign.center, ), ], ); return Scaffold( backgroundColor: Colors.black, body: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () => Navigator.of(context).pop(), child: SafeArea( child: LayoutBuilder( builder: (context, constraints) { return ClipRect( child: AnimatedBuilder( animation: _controller, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 24), child: credits, ), builder: (context, child) { // Rolls from just below the screen to fully above it. return OverflowBox( alignment: Alignment.topCenter, maxHeight: double.infinity, child: FractionalTranslation( translation: Offset(0, -_controller.value), child: Transform.translate( offset: Offset( 0, constraints.maxHeight * (1 - _controller.value), ), child: child, ), ), ); }, ), ); }, ), ), ), ); } }