cards order

This commit is contained in:
Dmitry 2024-06-05 00:44:16 +03:00
parent 578eb0ec2f
commit e19be0b015
4 changed files with 152 additions and 117 deletions

View file

@ -8,6 +8,7 @@ import 'package:mnemo_cards/admin/admin_api.dart';
import 'package:mnemo_cards/di/injector.dart'; import 'package:mnemo_cards/di/injector.dart';
import 'package:mnemo_cards/managers/repository/api.dart'; import 'package:mnemo_cards/managers/repository/api.dart';
import 'package:mnemo_cards/managers/repository/dio_provider.dart'; import 'package:mnemo_cards/managers/repository/dio_provider.dart';
import 'package:mnemo_cards/utils/iterable_helper.dart';
import 'package:mnemo_cards/utils/string_helper.dart'; import 'package:mnemo_cards/utils/string_helper.dart';
import 'package:mnemo_cards/widgets/header.dart'; import 'package:mnemo_cards/widgets/header.dart';
import 'package:mnemo_cards_common/mnemo_cards_common.dart'; import 'package:mnemo_cards_common/mnemo_cards_common.dart';
@ -268,6 +269,18 @@ class AddPackage with Api {
); );
}, },
), ),
_TextParam(
'Cards order (ids)',
cardPackDto.cardsOrder?.join(','),
(v) {
final ids = v
.split(',')
.map((s) => int.tryParse(s.trim()))
.whereNotNull()
.toList();
cardPackDto = cardPackDto.copyWith(cardsOrder: ids);
},
),
], ],
), ),
), ),

View file

@ -6,6 +6,7 @@ import 'dart:io';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:google_sign_in/google_sign_in.dart'; import 'package:google_sign_in/google_sign_in.dart';
import 'package:mnemo_cards/di/locator.dart';
import 'package:mnemo_cards/main.dart'; import 'package:mnemo_cards/main.dart';
import 'package:mnemo_cards/managers/repository/http_repository.dart'; import 'package:mnemo_cards/managers/repository/http_repository.dart';
import 'package:mnemo_cards_common/mnemo_cards_common.dart'; import 'package:mnemo_cards_common/mnemo_cards_common.dart';
@ -118,10 +119,18 @@ class UserManager {
await _createUser(token!, ExternalIdType.google, name); await _createUser(token!, ExternalIdType.google, name);
} }
})) }))
..add(Stream.periodic(Duration(seconds: 10)).listen((_) async { ..add(userStateHolder.asNullableStream.listen((user) async {
try { try {
if (userStateHolder.user == null) { if (user == null) {
await _updateUser(); await _updateUser();
} else {
try {
await locator.previewPackPoller.poll();
await locator.packManager.clearCache();
await locator.packUpdater.updateAvailablePacks();
} catch (err) {
log(err.toString());
}
} }
} catch (e) { } catch (e) {
log(e.toString()); log(e.toString());

View file

@ -1,22 +1,15 @@
import 'dart:async';
import 'dart:math'; import 'dart:math';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:flutter/animation.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:mnemo_cards/features/packs/images_holder.dart';
import 'package:mnemo_cards/main.dart';
import 'package:mnemo_cards/widgets/fade_in_widget.dart'; import 'package:mnemo_cards/widgets/fade_in_widget.dart';
import 'package:mnemo_cards_common/mnemo_cards_common.dart'; import 'package:mnemo_cards_common/mnemo_cards_common.dart';
import 'package:yandex_mobileads/mobile_ads.dart'; import 'package:yandex_mobileads/mobile_ads.dart';
import '../../domain/router/app_router.gr.dart'; import '../../domain/router/app_router.gr.dart';
import '../../features/analytics/analytics.dart'; import '../../features/analytics/analytics.dart';
import '../../features/yandex_ads/yandex_ads.dart'; import '../../features/yandex_ads/yandex_ads.dart';
import '../game_card_widget.dart';
import '../../di/locator.dart'; import '../../di/locator.dart';
import '../../theme/themes.dart'; import '../../theme/themes.dart';
@ -40,119 +33,139 @@ class AvailablePack extends StatelessWidget {
Analytics.availablePackOpened(cardPack); Analytics.availablePackOpened(cardPack);
return Column( return Column(
children: [ children: [
CardPackHeader.fromDto(cardPack), CardPackHeader(
cardPack.title,
cardPack.subtitle,
Colors.transparent,
),
Expanded( Expanded(
child: ListView( child: RefreshIndicator(
controller: _mainScrollController, onRefresh: () =>
children: [ locator.packUpdater.updatePackAndSaveImages(cardPack.id),
StatefulBuilder(builder: (context, setState) { backgroundColor: Colors.white,
return Column( color: cardPack.color?.asColor ?? Colors.black,
children: [ child: ListView(
Container( physics: BouncingScrollPhysics(
decoration: BoxDecoration( decelerationRate: ScrollDecelerationRate.fast,
color: cardPack.color?.asColor?.withOpacity(0.1), parent: AlwaysScrollableScrollPhysics()),
controller: _mainScrollController,
children: [
StatefulBuilder(builder: (context, setState) {
return Column(
children: [
Container(
height: 1,
color: cardPack.color?.asColor ??
Colors.grey.withOpacity(0.5),
), ),
alignment: Alignment.center, Container(
clipBehavior: Clip.antiAlias, decoration: BoxDecoration(
child: CardsView(_cardsViewController, cardPack), color: cardPack.color?.asColor?.withOpacity(0.1),
), ),
Container( alignment: Alignment.center,
height: 1, clipBehavior: Clip.antiAlias,
color: cardPack.color?.asColor ?? child: CardsView(_cardsViewController, cardPack),
Colors.grey.withOpacity(0.5),
),
SizedBox(
height: 10.h,
),
Padding(
padding: EdgeInsets.symmetric(
horizontal: 10.w,
), ),
child: Row( Container(
mainAxisAlignment: MainAxisAlignment.spaceBetween, height: 1,
children: [ color: cardPack.color?.asColor ??
StreamBuilder( Colors.grey.withOpacity(0.5),
stream: _cardsViewController.asStream, ),
builder: (context, snapshot) { SizedBox(
return AnimatedRotation( height: 10.h,
duration: Duration(milliseconds: 300), ),
turns: (snapshot.data?.expanded ?? false) Padding(
? 0.5 padding: EdgeInsets.symmetric(
: 0.0, horizontal: 10.w,
child: _Button( ),
'down.png', child: Row(
() async { mainAxisAlignment: MainAxisAlignment.spaceBetween,
if (snapshot.hasData) { children: [
_cardsViewController.setExpanded( StreamBuilder(
!snapshot.requireData.expanded, stream: _cardsViewController.asStream,
); builder: (context, snapshot) {
} return AnimatedRotation(
}, duration: Duration(milliseconds: 300),
turns: (snapshot.data?.expanded ?? false)
? 0.5
: 0.0,
child: _Button(
'down.png',
() async {
if (snapshot.hasData) {
_cardsViewController.setExpanded(
!snapshot.requireData.expanded,
);
}
},
),
);
}),
_Button('shuffle.png', () async {
final cards =
_cardsViewController.state.packCards;
if (cards.isEmpty) return;
final index = (_cardsViewController.offsetCards +
Random().nextInt(
(cards.length / 2).ceil(),
) +
3) %
cards.length;
await _cardsViewController.animateTo(index);
AutoRouter.of(context).push(
PageRouteInfo(
CardGamePage.name,
args: CardGamePageArgs(
cards: cards,
color: cardPack.color?.asColor,
startCardId: cards[index].id,
infinite: true,
shuffle: true,
// id: cardPack.dto.id.toString(),
), ),
);
}),
_Button('shuffle.png', () async {
final cards = _cardsViewController.state.packCards;
if (cards.isEmpty) return;
final index = (_cardsViewController.offsetCards +
Random().nextInt(
(cards.length / 2).ceil(),
) +
3) %
cards.length;
await _cardsViewController.animateTo(index);
AutoRouter.of(context).push(
PageRouteInfo(
CardGamePage.name,
args: CardGamePageArgs(
cards: cards,
color: cardPack.color?.asColor,
startCardId: cards[index].id,
infinite: true,
shuffle: true,
// id: cardPack.dto.id.toString(),
), ),
), );
); }),
}), // _Button('chat.png', () {}),
// _Button('chat.png', () {}), StreamBuilder(
StreamBuilder( stream: _cardsViewController.asStream,
stream: _cardsViewController.asStream, builder: (context, snapshot) {
builder: (context, snapshot) { return _Button(
return _Button( (snapshot.data?.favorite ?? false)
(snapshot.data?.favorite ?? false) ? 'heart_fill.png'
? 'heart_fill.png' : 'heart.png', () {
: 'heart.png', () { if (snapshot.hasData) {
if (snapshot.hasData) { _cardsViewController.setFavorite(
_cardsViewController.setFavorite( !snapshot.requireData.favorite,
!snapshot.requireData.favorite, );
); }
} });
}); }),
}), ],
], ),
), ),
), ],
], );
); }),
}), _AdTile(),
_AdTile(), _TestsSection(cardPack.id.toString()),
_TestsSection(cardPack.id.toString()), // _TestButton(
// _TestButton( // title: 'Быстрый тест',
// title: 'Быстрый тест', // subtitle: 'Лучший результат: 99 / 100',
// subtitle: 'Лучший результат: 99 / 100', // time: '3',
// time: '3', // timeSubtitle: 'мин',
// timeSubtitle: 'мин', // onTap: () {},
// onTap: () {}, // ),
// ), // _TestButton(
// _TestButton( // title: 'Полный тест',
// title: 'Полный тест', // subtitle: 'Лучший результат: 99 / 100',
// subtitle: 'Лучший результат: 99 / 100', // time: '10',
// time: '10', // timeSubtitle: 'мин',
// timeSubtitle: 'мин', // onTap: () {},
// onTap: () {}, // ),
// ), ],
], ),
), ),
), ),
Hero( Hero(

View file

@ -61,7 +61,7 @@ class GameCardDecoration extends StatelessWidget {
margin: EdgeInsets.only( margin: EdgeInsets.only(
left: 10.0 * alpha, left: 10.0 * alpha,
right: 10.0 * alpha, right: 10.0 * alpha,
bottom: 10.0 * alpha, bottom: 2.0 * alpha,
top: 0.0 * alpha, top: 0.0 * alpha,
), ),
decoration: BoxDecoration( decoration: BoxDecoration(