import 'dart:convert'; import 'dart:developer'; import 'package:auto_route/auto_route.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:mnemo_cards/features/packs/pack_manager.dart'; import 'package:mnemo_cards/managers/user_state_holder.dart'; import 'package:mnemo_cards/utils/string_helper.dart'; import 'package:mnemo_cards/widgets/header.dart'; import 'package:mnemo_cards/widgets/shared_pref_button.dart'; import 'package:mnemo_cards_common/mnemo_cards_common.dart'; import 'package:shimmer/shimmer.dart'; import '../admin/add_package.dart'; import '../di/locator.dart'; import '../domain/router/app_router.dart'; import '../domain/router/app_router.gr.dart'; import '../flags.dart'; import '../managers/repository/repository.dart'; import '../theme/themes.dart'; import 'package:collection/collection.dart'; class PacksMenuWidget extends StatefulWidget { final Repository repository; final PackManager packManager; final ScrollController? scrollController; const PacksMenuWidget( this.repository, this.packManager, { this.scrollController, super.key, }); @override State createState() => _PacksMenuWidgetState(); } class _PacksMenuWidgetState extends State { @override Widget build(BuildContext context) { return LayoutBuilder(builder: (context, constraints) { final cardHeight = 130.h; final theme = Theme.of(context); return StreamBuilder( stream: widget.packManager.packsPreviewStream.asyncMap((packs) async { if (packs != null) { await _precache(packs); } return packs; }), builder: (context, snapshot) { return Column( children: [ Header( 'Темы', trail: GestureDetector( onTap: () { AppRouter.openAuthOrProfile(); }, child: Image.asset( 'icons/profile.png', width: 27.w, height: 27.h, ), ), ), if (ADMIN_BUILD) Column( children: [ GestureDetector( onTap: () { locator.packManager.clearCache(); }, child: Container( alignment: Alignment.center, color: Colors.white, margin: EdgeInsets.all(8.0), child: Text('Clear cache'), height: 40.h, ), ), SharedPrefButton( enabledWidget: Text('PROD'), disabledWidget: Text('TEST'), spKey: 'env', ), ], ), Expanded( child: Padding( padding: const EdgeInsets.all(8.0), child: RefreshIndicator( onRefresh: locator.previewPackPoller.poll, child: ListView( scrollDirection: Axis.vertical, children: [ if (snapshot.data == null) ...[1, 2, 3, 4].map( (e) => _PackButton4Shimmer( constraints.maxWidth, cardHeight, ), ), if (snapshot.hasData) ...snapshot.data! .map((pack) => _PackButton4(pack, cardHeight)), ], ), ), ), ), ], ); }, ); }); } Future _precache(List packs) async { for (final pack in packs) { if (pack.imageBase64 != null) { try { final bytes = base64Decode(pack.imageBase64!); await precacheImage(MemoryImage(bytes), context); } catch (e) { log('${pack.id} cover not cached'); } } } } } class _PackButton4 extends StatelessWidget { final CardPackPreviewDto pack; final double cardHeight; const _PackButton4( this.pack, this.cardHeight, ); @override Widget build(BuildContext context) { final theme = Theme.of(context); return InkWell( onTap: () { AutoRouter.of(context).push( PageRouteInfo( CardPackPage.name, args: CardPackPageArgs(cardPackId: pack.id), ), ); }, child: Container( margin: EdgeInsets.all(4.0.h), alignment: Alignment.center, height: cardHeight, decoration: BoxDecoration( color: Colors.white, border: Border.all( color: pack.color?.asColor?.withOpacity(0.9) ?? Colors.grey.withOpacity(0.5), ), borderRadius: BorderRadius.circular(12.0), ), child: Row( mainAxisSize: MainAxisSize.max, children: [ Container( decoration: BoxDecoration( // border: Border.all( // color: pack.dto.color?.asColor?.withOpacity(0.9) ?? // Colors.grey.withOpacity(0.5), // ), // borderRadius: BorderRadius.circular(12.0), image: pack.imageBase64 == null ? null : DecorationImage( image: MemoryImage( base64Decode(pack.imageBase64!), ), ), ), margin: EdgeInsets.all(2.0.w), width: cardHeight, height: cardHeight, ), Expanded( child: Padding( padding: const EdgeInsets.all(8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ FittedBox( fit: BoxFit.scaleDown, child: Text( pack.title, style: TextStyle( fontWeight: FontWeight.w500, fontSize: 24.sp, height: 0.9, ), ), ), if (pack.subtitle != null && pack.subtitle!.isNotEmpty) FittedBox( fit: BoxFit.scaleDown, child: Text( pack.subtitle!, style: TextStyle( fontWeight: FontWeight.w300, fontSize: 16.sp, ), ), ), Spacer(), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Row( children: [ Text( pack.cards.toString(), style: TextStyle( fontWeight: FontWeight.w200, fontSize: 15.sp, ), ), Image.asset( 'icons/cards.png', width: 18.w, height: 16.h, ) ], ), ), if (pack.price != null && !pack.isAvailable) Text( pack.price!, style: TextStyle( fontWeight: FontWeight.w400, fontSize: 20.sp, ), ), ], ) ], ), ), ), ], ), ), ); } } class _PackButton4Shimmer extends StatelessWidget { final double cardHeight; final double cardWidth; const _PackButton4Shimmer( this.cardWidth, this.cardHeight, ); @override Widget build(BuildContext context) { return Shimmer.fromColors( baseColor: Colors.white, highlightColor: Colors.white, child: Container( alignment: Alignment.center, height: cardHeight, decoration: BoxDecoration( color: Colors.white, border: Border.all( color: Colors.grey.withOpacity(0.5), ), borderRadius: BorderRadius.circular(12.0), ), child: Row( mainAxisSize: MainAxisSize.max, children: [ Container( color: Colors.white, width: cardHeight, height: cardHeight, ), Expanded( child: Padding( padding: const EdgeInsets.all(8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( height: 30, width: (cardWidth - cardHeight) * 0.7, color: Colors.white, ), Container( height: 20, width: (cardWidth - cardHeight) * 0.5, color: Colors.white, ), Spacer(), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Container( height: 20, width: (cardWidth - cardHeight) * 0.1, color: Colors.white, ), Container( height: 25, width: (cardWidth - cardHeight) * 0.1, color: Colors.white, ), ], ) ], ), ), ), ], ), ), ); } } class _PackButtonShimmer extends StatelessWidget { final double cardWidth; final double cardHeight; const _PackButtonShimmer( this.cardWidth, this.cardHeight, ); @override Widget build(BuildContext context) { return Shimmer.fromColors( baseColor: Colors.white, highlightColor: Colors.grey[200]!, child: Container( width: cardWidth, height: cardHeight, child: Padding( padding: const EdgeInsets.all(12.0), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Container( alignment: Alignment.center, width: cardWidth, height: cardWidth, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12.0), )), Container( decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(8.0)), color: Colors.white, ), width: cardWidth * 0.7, height: 30, alignment: Alignment.center, ) ], ), ), ), ); } }