import 'dart:math'; import 'package:auto_route/auto_route.dart'; import 'package:dio/dio.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:mnemo_cards/features/packs/images_holder.dart'; import 'package:mnemo_cards/flags.dart'; import 'package:mnemo_cards/utils/color_helper.dart'; import 'package:mnemo_cards/utils/string_helper.dart'; import 'package:mnemo_cards_common/mnemo_cards_common.dart'; import 'package:rxdart/rxdart.dart'; import '../../admin/add_card.dart'; import '../../di/locator.dart'; import '../../domain/router/app_router.dart'; import '../../features/card_flipper/flip_card_controllers.dart'; import '../../features/card_swiper/src/allowed_swipe_direction.dart'; import '../../features/card_swiper/src/card_swiper.dart'; import '../../features/card_swiper/src/card_swiper_controller.dart'; import '../../main.dart'; import '../game_card_widget.dart'; class CardGameMainWidget extends StatelessWidget { final CardPackDto cardPack; final int? startCardId; final CardSwiperController cardSwiperController; final FlipCardController flipCardController; final int length; const CardGameMainWidget( this.cardPack, this.startCardId, this.cardSwiperController, this.flipCardController, this.length, ); @override Widget build(BuildContext context) { final numberOfCardsDisplayed = min(2, cardPack.cards.length); final initialScale = 0.9; int lastThreshold = 0; List cards = cardPack.cards; if (startCardId != null) { final startCardIndex = cards.indexWhere( (card) => card.id == startCardId, ); if (startCardIndex >= 0) { cards = [ ...cards.sublist(startCardIndex), ...cards.sublist(0, startCardIndex), ]; } } else { cards = cards.toList()..shuffle(); } GameCardDto? activeCard() => cardSwiperController.currentIndex >= 0 ? cards[cardSwiperController.currentIndex % cards.length] : null; return PopScope( canPop: false, onPopInvoked: (v) { if (!v) { appRouter.popForced(activeCard()?.id); } }, child: Material( type: MaterialType.transparency, child: LayoutBuilder(builder: (context, constraints) { final cardWidth = constraints.maxWidth; final cardHeight = cardWidth; bool enabled = true; return StatefulBuilder(builder: (context, setState) { return Stack( children: [ _EndWidget(cardSwiperController, flipCardController, () { setState(() { enabled = false; }); AutoRouter.of(context).maybePop(); }), if (enabled) Hero( tag: activeCard()?.id ?? 'empty', child: StreamBuilder( stream: cardSwiperController.asStream .map((index) => /*cards[index].isAd*/ false) .pairwise() .asyncMap((pair) async { if (pair.first) { await Future.delayed(Duration(seconds: 5)); return false; } return pair.last; }).timeout(Duration(seconds: 5), onTimeout: (_) => false), builder: (context, snapshot) { return AbsorbPointer( absorbing: snapshot.data ?? false, child: CardSwiper( controller: cardSwiperController, padding: const EdgeInsets.symmetric( vertical: 0.0, horizontal: 0.0, ), cardsCount: length, numberOfCardsDisplayed: numberOfCardsDisplayed, allowedSwipeDirection: AllowedSwipeDirection.symmetric( horizontal: true, ), scale: initialScale, backCardOffset: Offset(0, cardHeight * 0.1 / 2), isLoop: false, cardBuilder: ( context, cardIndex, percentThresholdX, percentThresholdY, scale, ) { final index = cardIndex % cards.length; final isFirstCard = (cardSwiperController.currentIndex == cardIndex); if (cardSwiperController.currentIndex == index) { lastThreshold = percentThresholdX; } print('${cards[index].translation} $scale'); final cardWidget = Center( child: GameCardWidget( cards[index], cards[index].id.memoryImage, flipCardController, flipCardController.state // || cards[index].isAd , isFirstCard, isFirstCard ? cardPack.color?.asColor : cardPack.color?.asColor?.darken( (scale - 1) / (initialScale - 1) * 0.075, ), ), ); return cardWidget; }, ), ); }), ), ], ); }); }), ), ); } } class _EndWidget extends StatelessWidget { final CardSwiperController cardSwiperController; final FlipCardController flipCardController; final VoidCallback callback; _EndWidget( this.cardSwiperController, this.flipCardController, this.callback, ); @override Widget build(BuildContext context) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('Ok: ${cardSwiperController.swipedLeftIds.length}'), Text('Repeat: ${cardSwiperController.swipedRightIds.length}'), MaterialButton( onPressed: () { cardSwiperController.restart(); }, child: Text('restart'), ), MaterialButton( onPressed: () { callback(); }, child: Text('to pack'), ), ], ), ); } }