diff --git a/android/app/build.gradle b/android/app/build.gradle index 5e89197..ea075c8 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -61,12 +61,21 @@ android { storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null storePassword keystoreProperties['storePassword'] } + debug { + keyAlias keystoreProperties['keyAlias'] + keyPassword keystoreProperties['keyPassword'] + storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null + storePassword keystoreProperties['storePassword'] + } } buildTypes { release { signingConfig signingConfigs.release } + debug { + signingConfig signingConfigs.release + } } } diff --git a/build/app/outputs/flutter-apk/app-arm64-v8a-release.apk b/build/app/outputs/flutter-apk/app-arm64-v8a-release.apk index 3bb5543..6bfd70e 100644 Binary files a/build/app/outputs/flutter-apk/app-arm64-v8a-release.apk and b/build/app/outputs/flutter-apk/app-arm64-v8a-release.apk differ diff --git a/lib/domain/router/dialogs.dart b/lib/domain/router/dialogs.dart new file mode 100644 index 0000000..fd00dfd --- /dev/null +++ b/lib/domain/router/dialogs.dart @@ -0,0 +1,60 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:mnemo_cards/theme/themes.dart'; + +import '../../main.dart'; + +showErrorDialog(String message) { + return showDialog( + context: scaffoldKey.currentContext!, + builder: (context) { + return Center( + child: Material( + color: Colors.transparent, + child: Container( + margin: EdgeInsets.all(4.0.h), + padding: EdgeInsets.all(4.0.h), + height: 200.h, + width: MediaQuery.of(context).size.width * 0.8, + decoration: BoxDecoration( + color: white, + border: Border.all( + color: Colors.grey.withOpacity(0.5), + width: 1, + ), + borderRadius: BorderRadius.circular(12.0), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: Center( + child: Text( + message, + textAlign: TextAlign.center, + ), + ), + ), + GestureDetector( + onTap: Navigator.of(context).pop, + child: Container( + height: 40.h, + decoration: BoxDecoration( + color: testBlue, + border: Border.all( + color: Colors.grey.withOpacity(0.5), + width: 1, + ), + borderRadius: BorderRadius.circular(8.0), + ), + alignment: Alignment.center, + child: Text('Оки'), + ), + ) + ], + ), + ), + ), + ); + }); +} diff --git a/lib/features/packs/pack_updater.dart b/lib/features/packs/pack_updater.dart index a3f000a..aa3bd25 100644 --- a/lib/features/packs/pack_updater.dart +++ b/lib/features/packs/pack_updater.dart @@ -106,7 +106,8 @@ class PackUpdater { } } - Future updatePackAndSaveImages(String packId) async { + Future updatePackAndSaveImages(String packId, + {bool shouldUpdateHolder = false}) async { try { log('Updating with cards ${packId}', name: 'updatePackWithCards'); final s = Stopwatch()..start(); @@ -146,6 +147,12 @@ class PackUpdater { _cacheManager.savePack(packDto, images: images); print('saved pack ${s.elapsedMilliseconds} mills'); log('Pack ${packId} updated with cards'); + if (shouldUpdateHolder) { + _packHolder.setPacks([ + ..._packHolder.state?.packsWithCards ?? [], + packDto, + ]); + } return packDto; } catch (e, s) { log('Cant update pack', name: 'updatePackWithCards'); diff --git a/lib/features/purchase/rustore/mnemo_rustore.dart b/lib/features/purchase/rustore/mnemo_rustore.dart index cb53448..3e391c4 100644 --- a/lib/features/purchase/rustore/mnemo_rustore.dart +++ b/lib/features/purchase/rustore/mnemo_rustore.dart @@ -1,8 +1,14 @@ +import 'dart:developer'; + +import 'package:auto_route/auto_route.dart'; import 'package:flutter_rustore_billing/flutter_rustore_billing.dart'; +import 'package:mnemo_cards/features/analytics/analytics.dart'; import 'package:mnemo_cards/flags.dart'; +import 'package:mnemo_cards/main.dart'; import 'package:mnemo_cards_common/mnemo_cards_common.dart'; import '../../../di/locator.dart'; +import '../../../domain/router/dialogs.dart'; class RustorePurchaseService { Future init() async { @@ -26,25 +32,81 @@ class RustorePurchaseService { if (!await init()) { return false; } + if (!await RustoreBillingClient.available().then((value) { + print("available success $value"); + return true; + }, onError: (err) { + print("available err: $err"); + return false; + })) { + return false; + } final product = (await RustoreBillingClient.products([dto.rustoreId])) .products .firstOrNull; if (product == null) { return false; } - final result = await RustoreBillingClient.purchase(dto.rustoreId!, null); - if (result.successPurchase == null && result.successInvoice == null) { - return false; - } - if (result.successPurchase != null) { - final purchase = result.successPurchase!; - final success = await locator.repository.checkPayment( - purchase.productId, - purchase.subscriptionToken ?? '', - androidPaymentSystem, + try { + final result = await RustoreBillingClient.purchase(dto.rustoreId!, null); + try { + try { + // creating payment to check it later + // in case there will be an error after confirmation + await locator.repository.checkPayment( + result.successPurchase!.productId, + result.successPurchase!.subscriptionToken!, + androidPaymentSystem, + ); + } catch (e, s) { + Analytics.buyError( + dto, + PaymentSystem.rustore, + message: 'Error when creating payment', + ); + log('Error when creating payment', error: e, stackTrace: s); + showErrorDialog( + 'Технические шоколадки...\n\nПопробуйте позже или обновите приложение до последней версии'); + return false; + } + final p = await RustoreBillingClient.confirm( + result.successPurchase!.purchaseId, + ); + if (p.success) { + final r = await locator.repository.checkPayment( + result.successPurchase!.productId, + result.successPurchase!.subscriptionToken!, + androidPaymentSystem, + ); + if (r) { + return r; + } else { + Analytics.buyError( + dto, + PaymentSystem.rustore, + message: 'Error when confirming payment', + ); + showErrorDialog( + 'Технические шоколадки...\n\nДоступ откроется в течение 5 мин', + ); + } + } + } catch (e, s) { + log('Error when confirming purchase', error: e, stackTrace: s); + Analytics.crashlyticsError( + e: e, + s: s, + message: 'Error when confirming rustore purchase', + ); + } + } catch (e, s) { + log('Error when processing purchase', error: e, stackTrace: s); + Analytics.crashlyticsError( + e: e, + s: s, + message: 'Error when processing rustore purchase', ); - return success; } - return true; + return false; } } diff --git a/lib/pages/profile_page.dart b/lib/pages/profile_page.dart index 6490523..f1b00d6 100644 --- a/lib/pages/profile_page.dart +++ b/lib/pages/profile_page.dart @@ -14,6 +14,7 @@ import 'package:url_launcher/url_launcher.dart'; import '../admin/all_cards.dart'; import '../admin/all_users.dart'; import '../di/locator.dart'; +import '../domain/router/dialogs.dart'; import '../features/analytics/analytics.dart'; import '../theme/themes.dart'; import '../widgets/enter_promo_code_widget.dart'; @@ -67,9 +68,11 @@ class ProfilePage extends StatelessWidget { Expanded( child: MaterialButton( onPressed: () { - showDialog( - context: context, - builder: (c) => const AllCards()); + showErrorDialog('Технические шоколадки...\n\nПопробуйте позже или обновите приложение до последней версии'); + + // showDialog( + // context: context, + // builder: (c) => const AllCards()); }, child: Text('ALL CARDS'), ), diff --git a/lib/widgets/card_pack/buy_pack_page.dart b/lib/widgets/card_pack/buy_pack_page.dart index 5e80ec1..ce98a1b 100644 --- a/lib/widgets/card_pack/buy_pack_page.dart +++ b/lib/widgets/card_pack/buy_pack_page.dart @@ -83,7 +83,7 @@ class BuyPack extends StatelessWidget { ), _BuyButton(dto, (v) { setState(() { - loading = v; + loading = v != null; }); }), SizedBox( @@ -132,14 +132,17 @@ class _Loading extends StatelessWidget { class _BuyButton extends StatelessWidget { final CardPackBuyDto dto; - final Function(bool) callback; + final Function(String? loadingText) callback; _BuyButton(this.dto, this.callback); Future _updatePack() async { try { - callback(true); - await locator.packUpdater.updatePackAndSaveImages(dto.id); + callback('Загрузка темы...'); + await locator.packUpdater.updatePackAndSaveImages( + dto.id, + shouldUpdateHolder: true, + ); await locator.packCacheManager.loadPackFromCache(dto.id); } catch (e, s) { log( diff --git a/pubspec.yaml b/pubspec.yaml index dd0698b..8f3d81e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: mnemo_cards description: Mnemo publish_to: 'none' -version: 1.0.1+11 +version: 1.0.1+13 environment: sdk: '>=3.1.3 <4.0.0'