mnemo_cards/lib/widgets/card_game/card_game_main.dart

202 lines
7.3 KiB
Dart
Raw Normal View History

2024-05-22 20:48:44 +00:00
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<GameCardDto> 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<bool>(
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'),
),
],
),
);
}
}