cards order
This commit is contained in:
parent
578eb0ec2f
commit
e19be0b015
4 changed files with 152 additions and 117 deletions
|
|
@ -8,6 +8,7 @@ import 'package:mnemo_cards/admin/admin_api.dart';
|
|||
import 'package:mnemo_cards/di/injector.dart';
|
||||
import 'package:mnemo_cards/managers/repository/api.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/widgets/header.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);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import 'dart:io';
|
|||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:dio/dio.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/managers/repository/http_repository.dart';
|
||||
import 'package:mnemo_cards_common/mnemo_cards_common.dart';
|
||||
|
|
@ -118,10 +119,18 @@ class UserManager {
|
|||
await _createUser(token!, ExternalIdType.google, name);
|
||||
}
|
||||
}))
|
||||
..add(Stream.periodic(Duration(seconds: 10)).listen((_) async {
|
||||
..add(userStateHolder.asNullableStream.listen((user) async {
|
||||
try {
|
||||
if (userStateHolder.user == null) {
|
||||
if (user == null) {
|
||||
await _updateUser();
|
||||
} else {
|
||||
try {
|
||||
await locator.previewPackPoller.poll();
|
||||
await locator.packManager.clearCache();
|
||||
await locator.packUpdater.updateAvailablePacks();
|
||||
} catch (err) {
|
||||
log(err.toString());
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
|
|
|
|||
|
|
@ -1,22 +1,15 @@
|
|||
import 'dart:async';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:collection/collection.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/widgets.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_common/mnemo_cards_common.dart';
|
||||
import 'package:yandex_mobileads/mobile_ads.dart';
|
||||
import '../../domain/router/app_router.gr.dart';
|
||||
import '../../features/analytics/analytics.dart';
|
||||
import '../../features/yandex_ads/yandex_ads.dart';
|
||||
import '../game_card_widget.dart';
|
||||
|
||||
import '../../di/locator.dart';
|
||||
import '../../theme/themes.dart';
|
||||
|
|
@ -40,119 +33,139 @@ class AvailablePack extends StatelessWidget {
|
|||
Analytics.availablePackOpened(cardPack);
|
||||
return Column(
|
||||
children: [
|
||||
CardPackHeader.fromDto(cardPack),
|
||||
CardPackHeader(
|
||||
cardPack.title,
|
||||
cardPack.subtitle,
|
||||
Colors.transparent,
|
||||
),
|
||||
Expanded(
|
||||
child: ListView(
|
||||
controller: _mainScrollController,
|
||||
children: [
|
||||
StatefulBuilder(builder: (context, setState) {
|
||||
return Column(
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: cardPack.color?.asColor?.withOpacity(0.1),
|
||||
child: RefreshIndicator(
|
||||
onRefresh: () =>
|
||||
locator.packUpdater.updatePackAndSaveImages(cardPack.id),
|
||||
backgroundColor: Colors.white,
|
||||
color: cardPack.color?.asColor ?? Colors.black,
|
||||
child: ListView(
|
||||
physics: BouncingScrollPhysics(
|
||||
decelerationRate: ScrollDecelerationRate.fast,
|
||||
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,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: CardsView(_cardsViewController, cardPack),
|
||||
),
|
||||
Container(
|
||||
height: 1,
|
||||
color: cardPack.color?.asColor ??
|
||||
Colors.grey.withOpacity(0.5),
|
||||
),
|
||||
SizedBox(
|
||||
height: 10.h,
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 10.w,
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: cardPack.color?.asColor?.withOpacity(0.1),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: CardsView(_cardsViewController, cardPack),
|
||||
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
StreamBuilder(
|
||||
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,
|
||||
);
|
||||
}
|
||||
},
|
||||
Container(
|
||||
height: 1,
|
||||
color: cardPack.color?.asColor ??
|
||||
Colors.grey.withOpacity(0.5),
|
||||
),
|
||||
SizedBox(
|
||||
height: 10.h,
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 10.w,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
StreamBuilder(
|
||||
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', () {}),
|
||||
StreamBuilder(
|
||||
stream: _cardsViewController.asStream,
|
||||
builder: (context, snapshot) {
|
||||
return _Button(
|
||||
(snapshot.data?.favorite ?? false)
|
||||
? 'heart_fill.png'
|
||||
: 'heart.png', () {
|
||||
if (snapshot.hasData) {
|
||||
_cardsViewController.setFavorite(
|
||||
!snapshot.requireData.favorite,
|
||||
);
|
||||
}
|
||||
});
|
||||
}),
|
||||
],
|
||||
);
|
||||
}),
|
||||
// _Button('chat.png', () {}),
|
||||
StreamBuilder(
|
||||
stream: _cardsViewController.asStream,
|
||||
builder: (context, snapshot) {
|
||||
return _Button(
|
||||
(snapshot.data?.favorite ?? false)
|
||||
? 'heart_fill.png'
|
||||
: 'heart.png', () {
|
||||
if (snapshot.hasData) {
|
||||
_cardsViewController.setFavorite(
|
||||
!snapshot.requireData.favorite,
|
||||
);
|
||||
}
|
||||
});
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
_AdTile(),
|
||||
_TestsSection(cardPack.id.toString()),
|
||||
// _TestButton(
|
||||
// title: 'Быстрый тест',
|
||||
// subtitle: 'Лучший результат: 99 / 100',
|
||||
// time: '3',
|
||||
// timeSubtitle: 'мин',
|
||||
// onTap: () {},
|
||||
// ),
|
||||
// _TestButton(
|
||||
// title: 'Полный тест',
|
||||
// subtitle: 'Лучший результат: 99 / 100',
|
||||
// time: '10',
|
||||
// timeSubtitle: 'мин',
|
||||
// onTap: () {},
|
||||
// ),
|
||||
],
|
||||
],
|
||||
);
|
||||
}),
|
||||
_AdTile(),
|
||||
_TestsSection(cardPack.id.toString()),
|
||||
// _TestButton(
|
||||
// title: 'Быстрый тест',
|
||||
// subtitle: 'Лучший результат: 99 / 100',
|
||||
// time: '3',
|
||||
// timeSubtitle: 'мин',
|
||||
// onTap: () {},
|
||||
// ),
|
||||
// _TestButton(
|
||||
// title: 'Полный тест',
|
||||
// subtitle: 'Лучший результат: 99 / 100',
|
||||
// time: '10',
|
||||
// timeSubtitle: 'мин',
|
||||
// onTap: () {},
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Hero(
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ class GameCardDecoration extends StatelessWidget {
|
|||
margin: EdgeInsets.only(
|
||||
left: 10.0 * alpha,
|
||||
right: 10.0 * alpha,
|
||||
bottom: 10.0 * alpha,
|
||||
bottom: 2.0 * alpha,
|
||||
top: 0.0 * alpha,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
|
|
|
|||
Loading…
Reference in a new issue