diff --git a/.metadata b/.metadata index 52213b5..8973d6c 100644 --- a/.metadata +++ b/.metadata @@ -4,7 +4,7 @@ # This file should be version controlled and should not be manually edited. version: - revision: "6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e" + revision: "761747bfc538b5af34aa0d3fac380f1bc331ec49" channel: "stable" project_type: app @@ -13,11 +13,11 @@ project_type: app migration: platforms: - platform: root - create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e - base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e - - platform: macos - create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e - base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e + create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49 + base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49 + - platform: android + create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49 + base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49 # User provided section diff --git a/android/app/build.gradle b/android/app/build.gradle index b4cc5a6..5e89197 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -2,27 +2,29 @@ plugins { id "com.android.application" // START: FlutterFire Configuration id 'com.google.gms.google-services' + id 'com.google.firebase.crashlytics' // END: FlutterFire Configuration id "kotlin-android" + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. id "dev.flutter.flutter-gradle-plugin" } def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') +def localPropertiesFile = rootProject.file("local.properties") if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> + localPropertiesFile.withReader("UTF-8") { reader -> localProperties.load(reader) } } -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +def flutterVersionCode = localProperties.getProperty("flutter.versionCode") if (flutterVersionCode == null) { - flutterVersionCode = '1' + flutterVersionCode = "1" } -def flutterVersionName = localProperties.getProperty('flutter.versionName') +def flutterVersionName = localProperties.getProperty("flutter.versionName") if (flutterVersionName == null) { - flutterVersionName = '1.0' + flutterVersionName = "1.0" } def keystoreProperties = new Properties() @@ -31,34 +33,25 @@ if (keystorePropertiesFile.exists()) { keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) } - android { - namespace "com.cinnabarflower.mnemo_cards" - compileSdkVersion flutter.compileSdkVersion - ndkVersion flutter.ndkVersion + namespace = "com.cinnabarflower.mnemo_cards" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = '1.8' - } - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 } defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.cinnabarflower.mnemo_cards" + applicationId = "com.cinnabarflower.mnemo_cards" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. - minSdkVersion 25 - targetSdkVersion flutter.targetSdkVersion - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName + minSdk = 25 + targetSdk = flutter.targetSdkVersion + versionCode = flutterVersionCode.toInteger() + versionName = flutterVersionName } signingConfigs { @@ -69,6 +62,7 @@ android { storePassword keystoreProperties['storePassword'] } } + buildTypes { release { signingConfig signingConfigs.release @@ -77,7 +71,5 @@ android { } flutter { - source '../..' + source = "../.." } - -dependencies {} diff --git a/android/app/google-services.json b/android/app/google-services.json index fa36c93..1b69ccc 100644 --- a/android/app/google-services.json +++ b/android/app/google-services.json @@ -21,6 +21,14 @@ "certificate_hash": "6df4f259b9c53ac01472c17df69e8c91494f3947" } }, + { + "client_id": "701767851968-5e6v0b5humhj0iu22t21nb9dtgt4tjus.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.cinnabarflower.mnemo_cards", + "certificate_hash": "49bb5b6863c9e6d8db43e7eb4d54796a300d87fe" + } + }, { "client_id": "701767851968-vqvjgf1u79jg924inm25bfuv4dg41t2u.apps.googleusercontent.com", "client_type": 1, diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml index e9ee25c..399f698 100644 --- a/android/app/src/debug/AndroidManifest.xml +++ b/android/app/src/debug/AndroidManifest.xml @@ -3,8 +3,5 @@ the Flutter tool needs it to communicate with the running application to allow setting breakpoints, to provide hot reload, etc. --> - diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 6abf7e0..705b276 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -12,6 +12,7 @@ android:name=".MainActivity" android:exported="true" android:launchMode="singleTop" + android:taskAffinity="" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" @@ -35,9 +36,15 @@ android:name="flutterEmbedding" android:value="2" /> + - + + diff --git a/android/app/src/main/kotlin/com/example/mnemo_cards/MainActivity.kt b/android/app/src/main/kotlin/com/cinnabarflower/mnemo_cards/MainActivity.kt similarity index 68% rename from android/app/src/main/kotlin/com/example/mnemo_cards/MainActivity.kt rename to android/app/src/main/kotlin/com/cinnabarflower/mnemo_cards/MainActivity.kt index d2b73e8..840a9e0 100644 --- a/android/app/src/main/kotlin/com/example/mnemo_cards/MainActivity.kt +++ b/android/app/src/main/kotlin/com/cinnabarflower/mnemo_cards/MainActivity.kt @@ -2,5 +2,4 @@ package com.cinnabarflower.mnemo_cards import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity() { -} +class MainActivity: FlutterActivity() diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index db77bb4..0000000 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 17987b7..0000000 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 09d4391..0000000 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index d5f1c8d..0000000 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 4d6372e..0000000 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/android/build.gradle b/android/build.gradle index 1a07f32..d2ffbff 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,20 +1,3 @@ -buildscript { - ext.kotlin_version = '1.8.20' - repositories { - google() - mavenCentral() - } - - dependencies { - classpath 'com.android.tools.build:gradle:7.3.0' - // START: FlutterFire Configuration - classpath 'com.google.gms:google-services:4.3.14' - classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1' - // END: FlutterFire Configuration - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - allprojects { repositories { google() @@ -22,12 +5,12 @@ allprojects { } } -rootProject.buildDir = '../build' +rootProject.buildDir = "../build" subprojects { project.buildDir = "${rootProject.buildDir}/${project.name}" } subprojects { - project.evaluationDependsOn(':app') + project.evaluationDependsOn(":app") } tasks.register("clean", Delete) { diff --git a/android/gradle.properties b/android/gradle.properties index 0961483..3b5b324 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,3 +1,3 @@ -org.gradle.jvmargs=-Xmx4608M +org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError android.useAndroidX=true android.enableJetifier=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index e1ca574..0000000 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip diff --git a/android/key.properties b/android/key.properties new file mode 100644 index 0000000..1dde9f9 --- /dev/null +++ b/android/key.properties @@ -0,0 +1,4 @@ +storePassword=345234 +keyPassword=345234 +keyAlias=upload +storeFile=../../../../upload-keystore.jks \ No newline at end of file diff --git a/android/pepk.jar b/android/pepk.jar new file mode 100644 index 0000000..5ffdd4c Binary files /dev/null and b/android/pepk.jar differ diff --git a/android/settings.gradle b/android/settings.gradle index 8ad364a..40f6db1 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -5,18 +5,14 @@ pluginManagement { def flutterSdkPath = properties.getProperty("flutter.sdk") assert flutterSdkPath != null, "flutter.sdk not set in local.properties" return flutterSdkPath - } - settings.ext.flutterSdkPath = flutterSdkPath() + }() - includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - plugins { - id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "7.3.0" apply false - // START: FlutterFire Configuration - id "com.google.gms.google-services" version "4.3.15" apply false - // END: FlutterFire Configuration - id "org.jetbrains.kotlin.android" version "1.7.10" apply false + repositories { + google() + mavenCentral() + gradlePluginPortal() } // For yoo kassa @@ -33,6 +29,14 @@ pluginManagement { } } -include ":app" +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "7.3.0" apply false + // START: FlutterFire Configuration + id "com.google.gms.google-services" version "4.3.15" apply false + id "com.google.firebase.crashlytics" version "2.8.1" apply false + // END: FlutterFire Configuration + id "org.jetbrains.kotlin.android" version "1.9.10" apply false +} -apply from: "${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle/app_plugin_loader.gradle" +include ":app" 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 c66e39f..3bb5543 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/cerdo_1024x512.png b/cerdo_1024x512.png new file mode 100644 index 0000000..d7f024a Binary files /dev/null and b/cerdo_1024x512.png differ diff --git a/cerdo_512.png b/cerdo_512.png new file mode 100644 index 0000000..12a16b8 Binary files /dev/null and b/cerdo_512.png differ diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index e087fd2..d32bea4 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -203,6 +203,7 @@ 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 10510DEBDDA8DED725BA2250 /* [CP] Copy Pods Resources */, EAA1E3F7E6B26606E42D1048 /* [CP] Embed Pods Frameworks */, + CDC7B89EEA6C1D8D4DC3C75E /* FlutterFire: "flutterfire upload-crashlytics-symbols" */, ); buildRules = ( ); @@ -345,6 +346,24 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + CDC7B89EEA6C1D8D4DC3C75E /* FlutterFire: "flutterfire upload-crashlytics-symbols" */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "FlutterFire: \"flutterfire upload-crashlytics-symbols\""; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\n#!/bin/bash\nPATH=${PATH}:$FLUTTER_ROOT/bin:$HOME/.pub-cache/bin\nflutterfire upload-crashlytics-symbols --upload-symbols-script-path=$PODS_ROOT/FirebaseCrashlytics/upload-symbols --platform=ios --apple-project-path=${SRCROOT} --env-platform-name=${PLATFORM_NAME} --env-configuration=${CONFIGURATION} --env-project-dir=${PROJECT_DIR} --env-built-products-dir=${BUILT_PRODUCTS_DIR} --env-dwarf-dsym-folder-path=${DWARF_DSYM_FOLDER_PATH} --env-dwarf-dsym-file-name=${DWARF_DSYM_FILE_NAME} --env-infoplist-path=${INFOPLIST_PATH} --default-config=default\n"; + }; EAA1E3F7E6B26606E42D1048 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; diff --git a/lib/admin/add_card.dart b/lib/admin/add_card.dart index 796d459..e77d0e9 100644 --- a/lib/admin/add_card.dart +++ b/lib/admin/add_card.dart @@ -5,11 +5,10 @@ import 'package:flutter/material.dart'; import 'package:file_picker/file_picker.dart'; import 'package:mnemo_cards/admin/admin_api.dart'; -import 'package:mnemo_cards/widgets/header.dart'; import 'package:mnemo_cards_common/mnemo_cards_common.dart'; +import 'package:mnemo_cards_frontend_common/mnemo_cards_frontend_common.dart'; import '../main.dart'; -import '../widgets/image_fade.dart'; class EditCard { GameCardDto gameCardDto; diff --git a/lib/admin/add_package.dart b/lib/admin/add_package.dart index 971f7eb..29ee311 100644 --- a/lib/admin/add_package.dart +++ b/lib/admin/add_package.dart @@ -5,13 +5,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_colorpicker/flutter_colorpicker.dart'; import 'package:mnemo_cards/admin/admin_api.dart'; import 'package:mnemo_cards/managers/repository/api.dart'; -import 'package:mnemo_cards/widgets/header.dart'; import 'package:mnemo_cards_common/mnemo_cards_common.dart'; import 'package:file_picker/file_picker.dart'; +import 'package:mnemo_cards_frontend_common/mnemo_cards_frontend_common.dart'; import '../utils/string_helper.dart'; import '../main.dart'; -import '../widgets/image_fade.dart'; class AddPackage with Api { EditCardPackDto cardPackDto; @@ -132,6 +131,13 @@ class AddPackage with Api { cardPackDto = cardPackDto.copyWith.googlePlayId(v); }, ), + _TextParam( + 'Rustore id', + cardPackDto.rustoreId, + (v) { + cardPackDto = cardPackDto.copyWith.rustoreId(v); + }, + ), _TextParam( 'Appstore id', cardPackDto.appStoreId, diff --git a/lib/admin/add_user.dart b/lib/admin/add_user.dart index 4e12247..4a75003 100644 --- a/lib/admin/add_user.dart +++ b/lib/admin/add_user.dart @@ -4,8 +4,8 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:mnemo_cards/admin/admin_api.dart'; -import 'package:mnemo_cards/widgets/header.dart'; import 'package:mnemo_cards_common/mnemo_cards_common.dart'; +import 'package:mnemo_cards_frontend_common/mnemo_cards_frontend_common.dart'; import '../main.dart'; diff --git a/lib/admin/all_cards.dart b/lib/admin/all_cards.dart index efb6599..ceabd80 100644 --- a/lib/admin/all_cards.dart +++ b/lib/admin/all_cards.dart @@ -9,8 +9,8 @@ import 'package:mnemo_cards/admin/admin_api.dart'; import 'package:mnemo_cards/di/injector.dart'; import 'package:mnemo_cards/managers/repository/dio_provider.dart'; import 'package:mnemo_cards/theme/themes.dart'; -import 'package:mnemo_cards/widgets/header.dart'; import 'package:mnemo_cards_common/mnemo_cards_common.dart'; +import 'package:mnemo_cards_frontend_common/mnemo_cards_frontend_common.dart'; import '../main.dart'; import 'add_package.dart'; diff --git a/lib/admin/all_users.dart b/lib/admin/all_users.dart index f2d1a3d..bd58c30 100644 --- a/lib/admin/all_users.dart +++ b/lib/admin/all_users.dart @@ -6,8 +6,8 @@ import 'package:mnemo_cards/admin/admin_api.dart'; import 'package:mnemo_cards/di/injector.dart'; import 'package:mnemo_cards/di/locator.dart'; import 'package:mnemo_cards/managers/repository/dio_provider.dart'; -import 'package:mnemo_cards/widgets/header.dart'; import 'package:mnemo_cards_common/mnemo_cards_common.dart'; +import 'package:mnemo_cards_frontend_common/mnemo_cards_frontend_common.dart'; import '../main.dart'; diff --git a/lib/features/purchase/in_app_purchase.dart b/lib/features/purchase/in_app_purchase.dart index 5ef11ad..a5d4757 100644 --- a/lib/features/purchase/in_app_purchase.dart +++ b/lib/features/purchase/in_app_purchase.dart @@ -3,13 +3,16 @@ import 'dart:developer'; import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:flutter_rustore_billing/pigeons/rustore.dart'; import 'package:in_app_purchase/in_app_purchase.dart'; import 'package:mnemo_cards_common/mnemo_cards_common.dart'; import 'package:webview_flutter/webview_flutter.dart'; import '../../di/injector.dart'; import '../../di/locator.dart'; +import '../../flags.dart'; import '../../main.dart'; import '../analytics/analytics.dart'; +import 'rustore/mnemo_rustore.dart'; enum StoreItemType { ads, @@ -26,14 +29,18 @@ class InAppPurchaseService { Future buyPack(CardPackBuyDto dto) async { try { - final pack = await getPackStoreProduct(dto); - final result = await buyItemInStore(pack.first); - return result; + if (RUSTORE_BUILD) { + return RustorePurchaseService().buyPack(dto); + } else { + final pack = await _getPackStoreProduct(dto); + final result = await _buyItemInStore(pack.first); + return result; + } } catch (e, s) { log('err', error: e, stackTrace: s); Analytics.buyError( dto, - PaymentSystem.google, + androidPaymentSystem, data: { 'e': e.toString(), 's': s.toString(), @@ -92,12 +99,12 @@ class InAppPurchaseService { }); } - Future> getPackStoreProduct(CardPackBuyDto dto) async { + Future> _getPackStoreProduct(CardPackBuyDto dto) async { final bool isAvailable = await _inAppPurchase.isAvailable(); if (!isAvailable) { Analytics.buyError( dto, - PaymentSystem.google, + androidPaymentSystem, message: 'in app purchase not available', ); return []; @@ -109,7 +116,7 @@ class InAppPurchaseService { if (ids.isEmpty) { Analytics.buyError( dto, - PaymentSystem.google, + androidPaymentSystem, message: 'product id not set', ); return []; @@ -122,7 +129,7 @@ class InAppPurchaseService { productDetailResponse.productDetails.isEmpty) { Analytics.buyError( dto, - PaymentSystem.google, + androidPaymentSystem, data: { 'msg': 'cant get product details ${productDetailResponse.error}', 'not_found': productDetailResponse.notFoundIDs.join(','), @@ -134,7 +141,7 @@ class InAppPurchaseService { return productDetailResponse.productDetails; } - Future buyItemInStore(ProductDetails product) async { + Future _buyItemInStore(ProductDetails product) async { final PurchaseParam purchaseParam = PurchaseParam(productDetails: product); return InAppPurchase.instance .buyNonConsumable(purchaseParam: purchaseParam); @@ -152,7 +159,7 @@ class PurchaseDetailsStreamSubscription { try { Analytics.buyEvent( null, - PaymentSystem.google, + androidPaymentSystem, message: 'onPurchased', data: { 'status': purchaseDetails.status.name, @@ -163,12 +170,12 @@ class PurchaseDetailsStreamSubscription { final result = await locator.repository.checkPayment( purchaseDetails.productID, purchaseDetails.verificationData.serverVerificationData, - PaymentSystem.google, + androidPaymentSystem, ); if (result) { Analytics.buyComplete( null, - PaymentSystem.google, + androidPaymentSystem, message: purchaseDetails.productID, ); log('Purchased'); diff --git a/lib/features/purchase/rustore/mnemo_rustore.dart b/lib/features/purchase/rustore/mnemo_rustore.dart new file mode 100644 index 0000000..cb53448 --- /dev/null +++ b/lib/features/purchase/rustore/mnemo_rustore.dart @@ -0,0 +1,50 @@ +import 'package:flutter_rustore_billing/flutter_rustore_billing.dart'; +import 'package:mnemo_cards/flags.dart'; +import 'package:mnemo_cards_common/mnemo_cards_common.dart'; + +import '../../../di/locator.dart'; + +class RustorePurchaseService { + Future init() async { + return RustoreBillingClient.initialize( + "2063563896", + "mnemocards://iamback", + true, + ).then((value) { + print("initialize success: $value"); + return true; + }, onError: (err) { + print("initialize err: $err"); + return false; + }); + } + + Future buyPack(CardPackBuyDto dto) async { + if (dto.rustoreId == null) { + return false; + } + if (!await init()) { + 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, + ); + return success; + } + return true; + } +} diff --git a/lib/features/tests/test_complete_widget.dart b/lib/features/tests/test_complete_widget.dart index c20395a..5516c99 100644 --- a/lib/features/tests/test_complete_widget.dart +++ b/lib/features/tests/test_complete_widget.dart @@ -4,11 +4,10 @@ import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:mnemo_cards/utils/color_helper.dart'; +import 'package:mnemo_cards_frontend_common/mnemo_cards_frontend_common.dart'; import 'package:rxdart/rxdart.dart'; import '../../di/locator.dart'; -import '../../widgets/big_back_button.dart'; -import '../../widgets/horizontal_progress.dart'; import 'question_states/test_question_state.dart'; class TestCompleteWidget extends StatelessWidget { diff --git a/lib/flags.dart b/lib/flags.dart index 2686372..c089c6d 100644 --- a/lib/flags.dart +++ b/lib/flags.dart @@ -1,6 +1,11 @@ import 'package:mnemo_cards/main.dart'; +import 'package:mnemo_cards_common/mnemo_cards_common.dart'; +import 'package:mnemo_cards_frontend_common/mnemo_cards_frontend_common.dart'; -const ADMIN_BUILD = false; +const ADMIN_BUILD = CommonPrefs.ADMIN_BUILD; +const RUSTORE_BUILD = CommonPrefs.RUSTORE_BUILD; + +final androidPaymentSystem = CommonPrefs.androidPaymentSystem; bool get SHOW_ADMIN => - ADMIN_BUILD && (globalSharedPreferences.getBool('show_admin') ?? false); + ADMIN_BUILD && (globalSharedPreferences.getBool('show_admin') ?? true); diff --git a/lib/main.dart b/lib/main.dart index abbd107..5a120cf 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -151,7 +151,17 @@ class MyApp extends StatelessWidget with WidgetsBindingObserver { theme: theme2, darkTheme: darkTheme2, themeMode: themeMode, - routerConfig: appRouter.config(), + routerConfig: appRouter.config( + deepLinkBuilder: (link) { + // if(link.path.contains('/ru/reset-password')) { + // return const DeepLink( + // [ResetPassRoute()] + // ); + // } else { + return DeepLink.defaultPath; + } + // } + ), scaffoldMessengerKey: scaffoldMessengerKey, debugShowCheckedModeBanner: false, ); @@ -199,6 +209,13 @@ class _MainTabsPageState extends State { _Tabs _currentTab = _Tabs.home; + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + print('CHANGE DEPS'); + } + @override void initState() { super.initState(); diff --git a/lib/managers/user_manager.dart b/lib/managers/user_manager.dart index 5010275..fcff973 100644 --- a/lib/managers/user_manager.dart +++ b/lib/managers/user_manager.dart @@ -171,5 +171,3 @@ class UserManager { _subscription = null; } } - -enum ExternalIdType { google, device } diff --git a/lib/pages/auth_page.dart b/lib/pages/auth_page.dart index 869df59..63e2b65 100644 --- a/lib/pages/auth_page.dart +++ b/lib/pages/auth_page.dart @@ -39,7 +39,7 @@ class AuthPage extends StatelessWidget { ), ), if (ADMIN_BUILD) - SharedPrefButton( + MobileSharedPrefButton( builder: (v, _) => (v ?? false) ? Text('PROD') : Text('TEST'), spKey: 'env', setOnTap: (v) => !(v ?? false), diff --git a/lib/pages/profile_page.dart b/lib/pages/profile_page.dart index 29c6f01..6490523 100644 --- a/lib/pages/profile_page.dart +++ b/lib/pages/profile_page.dart @@ -7,7 +7,7 @@ import 'package:mnemo_cards/domain/router/app_router.dart'; import 'package:mnemo_cards/domain/router/app_router.gr.dart'; import 'package:mnemo_cards/flags.dart'; import 'package:mnemo_cards/main.dart'; -import 'package:mnemo_cards/widgets/header.dart'; +import 'package:mnemo_cards_frontend_common/mnemo_cards_frontend_common.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -16,11 +16,8 @@ import '../admin/all_users.dart'; import '../di/locator.dart'; import '../features/analytics/analytics.dart'; import '../theme/themes.dart'; -import '../widgets/big_back_button.dart'; import '../widgets/enter_promo_code_widget.dart'; import '../widgets/shared_pref_button.dart'; -import '../widgets/simple_tile.dart'; -import '../widgets/user_statistics.dart'; @RoutePage() class ProfilePage extends StatelessWidget { @@ -106,7 +103,7 @@ class ProfilePage extends StatelessWidget { ), ), Expanded( - child: SharedPrefButton( + child: MobileSharedPrefButton( builder: (v, _) => (v ?? false) ? Text('PROD') : Text('TEST'), spKey: 'env', @@ -140,7 +137,7 @@ class ProfilePage extends StatelessWidget { height: 5, color: borderGray.withOpacity(0.2), ), - const EnterPromoCodeWidget(), + const MobileEnterPromoCodeWidget(), Divider( height: 5, color: borderGray.withOpacity(0.2), diff --git a/lib/pages/settgins_page.dart b/lib/pages/settgins_page.dart index 4576abe..c7bb224 100644 --- a/lib/pages/settgins_page.dart +++ b/lib/pages/settgins_page.dart @@ -4,19 +4,14 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:mnemo_cards/flags.dart'; -import 'package:mnemo_cards/widgets/header.dart'; +import 'package:mnemo_cards_frontend_common/mnemo_cards_frontend_common.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:url_launcher/url_launcher.dart'; import '../di/locator.dart'; import '../features/analytics/analytics.dart'; import '../theme/themes.dart'; -import '../widgets/big_back_button.dart'; import '../widgets/shared_pref_button.dart'; -import '../widgets/simple_tile.dart'; -import '../widgets/slider.dart'; -import '../widgets/switch_tile.dart'; -import '../widgets/text_button.dart'; @RoutePage() class SettingsPage extends StatelessWidget { @@ -45,7 +40,7 @@ class SettingsPage extends StatelessWidget { height: 1, color: borderGray.withOpacity(0.2), ), - SharedPrefButton.builder( + MobileSharedPrefButton.builder( spKey: 'dark_theme', builder: (enabled, _) => AbsorbPointer( child: SwitchTile( @@ -64,7 +59,7 @@ class SettingsPage extends StatelessWidget { height: 1, color: borderGray.withOpacity(0.2), ), - SharedPrefButton.builder( + MobileSharedPrefButton.builder( spKey: 'sound_on', builder: (enabled, _) => AbsorbPointer( child: SwitchTile( @@ -78,7 +73,7 @@ class SettingsPage extends StatelessWidget { height: 1, color: borderGray.withOpacity(0.2), ), - SharedPrefButton.builder( + MobileSharedPrefButton.builder( spKey: 'auto_play_sound_view', builder: (enabled, _) => AbsorbPointer( child: SwitchTile( @@ -92,7 +87,7 @@ class SettingsPage extends StatelessWidget { height: 1, color: borderGray.withOpacity(0.2), ), - SharedPrefButton.builder( + MobileSharedPrefButton.builder( spKey: 'auto_play_sound_tests', builder: (enabled, _) => AbsorbPointer( child: SwitchTile( @@ -108,7 +103,7 @@ class SettingsPage extends StatelessWidget { ), SimpleTile.text( text: 'Скорость чтения', - trail: SharedPrefButton.builder( + trail: MobileSharedPrefButton.builder( spKey: 'sound_speed', builder: (v, s) => MnemoSlider( onChanged: (value) => s(value), @@ -122,7 +117,7 @@ class SettingsPage extends StatelessWidget { color: borderGray.withOpacity(0.2), ), if (ADMIN_BUILD) - SharedPrefButton.builder( + MobileSharedPrefButton.builder( spKey: 'show_admin', builder: (enabled, _) => AbsorbPointer( child: SwitchTile( diff --git a/lib/widgets/big_back_button.dart b/lib/widgets/big_back_button.dart deleted file mode 100644 index 5717be0..0000000 --- a/lib/widgets/big_back_button.dart +++ /dev/null @@ -1,37 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:mnemo_cards/main.dart'; - -import '../theme/themes.dart'; - -class BigBackButton extends StatelessWidget { - @override - Widget build(BuildContext context) { - return Padding( - padding: EdgeInsets.symmetric(horizontal: 10.0.w, vertical: 10.0.h), - child: InkWell( - onTap: appRouter.maybePop, - child: Container( - height: 90.h, - alignment: Alignment.center, - decoration: BoxDecoration( - color: Theme.of(context).scaffoldBackgroundColor, - border: Border.all(color: borderGray), - borderRadius: BorderRadius.circular(16.0), - ), - padding: EdgeInsets.all(10.0.w), - child: Text( - 'Назад', - style: TextStyle( - fontSize: 25.sp, - fontWeight: FontWeight.w700, - height: 0.85, - ), - ), - ), - ), - ); - } - - const BigBackButton(); -} diff --git a/lib/widgets/card_game/card_game_header.dart b/lib/widgets/card_game/card_game_header.dart index f69284f..cade818 100644 --- a/lib/widgets/card_game/card_game_header.dart +++ b/lib/widgets/card_game/card_game_header.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:mnemo_cards_common/mnemo_cards_common.dart'; +import 'package:mnemo_cards_frontend_common/mnemo_cards_frontend_common.dart'; import '../../features/card_swiper/src/card_swiper_controller.dart'; -import '../header.dart'; class CardGameHeader extends StatelessWidget { final CardSwiperController controller; diff --git a/lib/widgets/card_pack/available_pack.dart b/lib/widgets/card_pack/available_pack.dart index 31dbb88..5cabed0 100644 --- a/lib/widgets/card_pack/available_pack.dart +++ b/lib/widgets/card_pack/available_pack.dart @@ -5,8 +5,8 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.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:mnemo_cards_frontend_common/mnemo_cards_frontend_common.dart'; import 'package:yandex_mobileads/mobile_ads.dart'; import '../../domain/router/app_router.gr.dart'; import '../../features/analytics/analytics.dart'; @@ -14,7 +14,6 @@ import '../../features/yandex_ads/yandex_ads.dart'; import '../../di/locator.dart'; import '../../theme/themes.dart'; -import '../horizontal_progress.dart'; import 'card_pack_header.dart'; import 'package:mnemo_cards/utils/string_helper.dart'; diff --git a/lib/widgets/card_pack/buy_pack_page.dart b/lib/widgets/card_pack/buy_pack_page.dart index 3a6c569..5e80ec1 100644 --- a/lib/widgets/card_pack/buy_pack_page.dart +++ b/lib/widgets/card_pack/buy_pack_page.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'dart:developer'; +import 'package:mnemo_cards/flags.dart'; import 'package:mnemo_cards/utils/string_helper.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -164,7 +165,7 @@ class _BuyButton extends StatelessWidget { InkWell( onTap: () async { if (locator.userManager.hasUser) { - Analytics.buyPackPressed(dto, PaymentSystem.google); + Analytics.buyPackPressed(dto, androidPaymentSystem); final result = await locator.purchaseService.buyPack(dto); if (result) { _updatePack(); diff --git a/lib/widgets/card_pack/card_pack_header.dart b/lib/widgets/card_pack/card_pack_header.dart index a718006..31960f2 100644 --- a/lib/widgets/card_pack/card_pack_header.dart +++ b/lib/widgets/card_pack/card_pack_header.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:mnemo_cards_common/mnemo_cards_common.dart'; import 'package:mnemo_cards/utils/string_helper.dart'; -import '../header.dart'; +import 'package:mnemo_cards_frontend_common/mnemo_cards_frontend_common.dart'; class CardPackHeader extends StatelessWidget { final String? title; diff --git a/lib/widgets/card_pack/cards_view.dart b/lib/widgets/card_pack/cards_view.dart index 351687d..3db00a0 100644 --- a/lib/widgets/card_pack/cards_view.dart +++ b/lib/widgets/card_pack/cards_view.dart @@ -1,17 +1,17 @@ - import 'package:auto_route/auto_route.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_common/mnemo_cards_common.dart'; +import 'package:mnemo_cards_frontend_common/mnemo_cards_frontend_common.dart' + as frontend; import 'package:reorderables/reorderables.dart'; import 'package:rxdart/rxdart.dart'; import '../../utils/string_helper.dart'; import '../../domain/router/app_router.gr.dart'; import '../../main.dart'; -import '../feedback_builder.dart'; import '../game_card_widget.dart'; import 'cards_view_controller.dart'; @@ -157,7 +157,8 @@ class _CardsViewState extends State onReorder: (int from, int to) { controller.onOrderChanged(from, to); }, - buildDraggableFeedback: FeedbackBuilder.simple, + buildDraggableFeedback: + frontend.FeedbackBuilder.simple, padding: EdgeInsets.symmetric( horizontal: (cardWidth - imageWidth - 1), vertical: (cardWidth - imageWidth - 1), diff --git a/lib/widgets/enter_promo_code_widget.dart b/lib/widgets/enter_promo_code_widget.dart index b74474a..3be13fc 100644 --- a/lib/widgets/enter_promo_code_widget.dart +++ b/lib/widgets/enter_promo_code_widget.dart @@ -1,88 +1,21 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:mnemo_cards/di/locator.dart'; -import 'package:mnemo_cards/theme/themes.dart'; -import 'package:mnemo_cards/widgets/simple_tile.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:mnemo_cards_frontend_common/mnemo_cards_frontend_common.dart'; -class EnterPromoCodeWidget extends StatefulWidget { - const EnterPromoCodeWidget(); +import '../di/locator.dart'; - @override - State createState() => _EnterPromoCodeState(); -} +class MobileEnterPromoCodeWidget extends StatelessWidget { -class _EnterPromoCodeState extends State { - final TextEditingController controller = TextEditingController(); - String? message; @override Widget build(BuildContext context) { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - SimpleTile( - title: Row( - children: [ - Text('Промокод'), - SizedBox( - width: 16.w, - ), - Expanded( - child: TextField( - // cursorHeight: 17.h, - controller: controller, - textAlignVertical: TextAlignVertical.center, - style: TextStyle(fontSize: 17.sp), - decoration: InputDecoration( - contentPadding: EdgeInsets.all(8.0), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - ), - ), - SizedBox( - width: 8.w, - ), - ], - ), - trail: GestureDetector( - onTap: () async { - final result = await locator.userManager.applyPromocode( - controller.text, - ); - if (result.success == true) { - controller.clear(); - } - setState(() { - message = result.message; - }); - FocusScope.of(context).unfocus(); - }, - child: AspectRatio( - aspectRatio: 1.0, - child: Container( - alignment: Alignment.center, - decoration: BoxDecoration( - color: progressBlue, - borderRadius: BorderRadius.circular(12.0), - ), - child: Image.asset( - 'icons/gift.png', - width: 17.w, - color: Theme.of(context).colorScheme.primary, - ), - ), - ), - ), - ), - if (message != null && message!.isNotEmpty) - Padding( - padding: const EdgeInsets.symmetric(vertical: 4.0), - child: Text(message!), - ), - ], - ); + return EnterPromoCodeWidget(onApplyPromoCode: onApplyPromoCode); } -} + + Future<(bool, String?)> onApplyPromoCode(String code) async { + final result = await locator.userManager.applyPromocode(code); + return (result.success ?? false, result.message); + } + + const MobileEnterPromoCodeWidget(); +} \ No newline at end of file diff --git a/lib/widgets/fade_in_widget.dart b/lib/widgets/fade_in_widget.dart deleted file mode 100644 index febd710..0000000 --- a/lib/widgets/fade_in_widget.dart +++ /dev/null @@ -1,30 +0,0 @@ -import 'package:flutter/cupertino.dart'; - -class FadeInWidget extends StatelessWidget { - final Widget child; - final Duration? delay; - final Future? future; - final Duration animationDuration; - - FadeInWidget({ - required this.child, - this.delay = const Duration(milliseconds: 200), - this.future, - this.animationDuration = const Duration(milliseconds: 200), - super.key, - }) : assert(future != null || delay != null); - - @override - Widget build(BuildContext context) { - return FutureBuilder( - future: future ?? Future.delayed(delay!), - builder: (context, s) { - return AnimatedOpacity( - duration: animationDuration, - opacity: s.connectionState == ConnectionState.done ? 1.0 : 0.0, - child: child, - ); - }, - ); - } -} diff --git a/lib/widgets/feedback_builder.dart b/lib/widgets/feedback_builder.dart deleted file mode 100644 index 83cbe5d..0000000 --- a/lib/widgets/feedback_builder.dart +++ /dev/null @@ -1,31 +0,0 @@ -import 'package:flutter/material.dart'; - -class FeedbackBuilder { - static Widget tests(Widget child, int index, Animation animation) => - Transform( - transform: new Matrix4.rotationZ(0), - child: Material( - child: child, - elevation: 1.0, - color: Colors.transparent, - borderRadius: BorderRadius.circular(16.0), - ), - ); - - static Widget simple( - BuildContext context, - BoxConstraints constraints, - Widget child, - ) { - return Transform( - transform: new Matrix4.rotationZ(0.05), - // alignment: FractionalOffset.topLeft, - child: Material( - child: child, - elevation: 6.0, - color: Colors.transparent, - borderRadius: BorderRadius.circular(12.0), - ), - ); - } -} diff --git a/lib/widgets/game_card_widget.dart b/lib/widgets/game_card_widget.dart index 8659793..c725568 100644 --- a/lib/widgets/game_card_widget.dart +++ b/lib/widgets/game_card_widget.dart @@ -7,14 +7,13 @@ import 'package:mnemo_cards/features/yandex_ads/yandex_ads.dart'; import 'package:mnemo_cards/managers/audio_player.dart'; import 'package:mnemo_cards/utils/color_helper.dart'; import 'package:mnemo_cards_common/mnemo_cards_common.dart'; +import 'package:mnemo_cards_frontend_common/mnemo_cards_frontend_common.dart'; import 'package:yandex_mobileads/mobile_ads.dart'; import '../features/card_flipper/flip_card.dart'; import '../features/card_flipper/flip_card_controllers.dart'; import '../features/card_flipper/flip_side.dart'; import '../theme/themes.dart'; -import 'image_fade.dart'; -import 'mnemo_text.dart'; class GameCardWidget extends StatefulWidget { static const borderRadius = 32.0; diff --git a/lib/widgets/header.dart b/lib/widgets/header.dart deleted file mode 100644 index 5da05c0..0000000 --- a/lib/widgets/header.dart +++ /dev/null @@ -1,117 +0,0 @@ -import 'dart:math'; - -import 'package:auto_route/auto_route.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; - -class Header extends StatelessWidget { - final String? title; - final String? subtitle; - - final bool hasPopButton; - final String? popText; - final Widget? trail; - final Color? color; - - Header( - this.title, { - this.subtitle, - this.hasPopButton = false, - this.popText, - this.trail, - this.color, - }); - - @override - Widget build(BuildContext context) { - final topPadding = 74.h - - MediaQuery.of(context).padding.top - - (hasPopButton ? 30.0.h : 0.0); - return Container( - color: color, - alignment: Alignment.centerLeft, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - height: max( - topPadding / 2, - 0, - ), - ), - if (hasPopButton) - Padding( - padding: EdgeInsets.only(left: 10.0.w), - child: TapRegion( - onTapInside: AutoRouter.of(context).maybePop, - behavior: HitTestBehavior.opaque, - child: SizedBox( - height: 30.h, - child: Row( - children: [ - Image.asset( - 'icons/back.png', - color: - Theme.of(context).buttonTheme.colorScheme!.primary, - width: 17, - height: 23.h, - ), - if (popText != null) - Padding( - padding: const EdgeInsets.only(left: 4.0), - child: Text( - popText!, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w700, - ), - ), - ), - ], - ), - ), - ), - ), - SizedBox( - height: max( - topPadding / 2, - 0, - ), - ), - Container( - padding: EdgeInsets.only(left: 20.0.w, right: 24.w), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - if (title != null) - Text( - title!, - style: TextStyle( - fontSize: 36.sp, - fontWeight: FontWeight.w700, - height: 0.85, - ), - textAlign: TextAlign.start, - ), - if (trail != null) trail!, - ], - ), - ), - if (subtitle != null) - Container( - padding: EdgeInsets.only(top: 4.0.h, left: 22.0.w, bottom: 4.0.h), - alignment: Alignment.centerLeft, - child: Text( - subtitle!, - style: TextStyle( - fontSize: 20.sp, - fontWeight: FontWeight.w300, - height: 0.85, - ), - ), - ), - ], - ), - ); - } -} diff --git a/lib/widgets/horizontal_progress.dart b/lib/widgets/horizontal_progress.dart deleted file mode 100644 index 5cdaa91..0000000 --- a/lib/widgets/horizontal_progress.dart +++ /dev/null @@ -1,44 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; - -import '../theme/themes.dart'; - -class HorizontalProgressWidget extends StatelessWidget { - final int value; - final int length; - final Color color; - final Color? borderColor; - final double? height; - - HorizontalProgressWidget( - this.value, - this.length, - this.color, { - this.borderColor, - this.height, - }); - - @override - Widget build(BuildContext context) { - return Container( - height: height ?? 16.h, - clipBehavior: Clip.hardEdge, - decoration: BoxDecoration( - color: white, - border: borderColor != null ? Border.all(color: borderColor!) : null, - borderRadius: BorderRadius.circular(16.h), - ), - child: AnimatedFractionallySizedBox( - alignment: Alignment.centerLeft, - widthFactor: length == 0 ? 0 : value.toDouble() / length, - duration: Duration(milliseconds: 600), - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(16.h), - color: color, - ), - ), - ), - ); - } -} diff --git a/lib/widgets/image_fade.dart b/lib/widgets/image_fade.dart deleted file mode 100644 index fe21d68..0000000 --- a/lib/widgets/image_fade.dart +++ /dev/null @@ -1,356 +0,0 @@ -import 'package:flutter/widgets.dart'; -import 'dart:ui' as ui; - -/// Signature used by [ImageFade.errorBuilder] to build the widget that will be displayed -/// if an error occurs while loading an image. -typedef ImageFadeErrorBuilder = Widget Function( - BuildContext context, - Object exception, -); - -/// Signature used by [ImageFade.loadingBuilder] to build the widget that will be displayed -/// while an image is loading. `progress` returns a value between 0 and 1 indicating load progress. -typedef ImageFadeLoadingBuilder = Widget Function( - BuildContext context, - double progress, - ImageChunkEvent? chunkEvent, -); - -/// A widget that displays a [placeholder] widget while a specified [image] loads, -/// then cross-fades to the loaded image. Can optionally display loading progress -/// and errors. -/// -/// If [image] is subsequently changed, it will cross-fade to the new image once it -/// finishes loading. -/// -/// Setting [image] to null will cross-fade back to the [placeholder]. -/// -/// ```dart -/// ImageFade( -/// placeholder: Image.asset('assets/myPlaceholder.png'), -/// image: NetworkImage('https://backend.example.com/image.png'), -/// ) -/// ``` -class ImageFade extends StatefulWidget { - /// Creates a widget that displays a [placeholder] widget while a specified [image] loads, - /// then cross-fades to the loaded image. - const - ImageFade({ - Key? key, - this.placeholder, - this.image, - this.curve = Curves.linear, - this.duration = const Duration(milliseconds: 300), - this.syncDuration, - this.width, - this.height, - this.scale = 1, - this.fit = BoxFit.scaleDown, - this.alignment = Alignment.center, - this.repeat = ImageRepeat.noRepeat, - this.matchTextDirection = false, - this.excludeFromSemantics = false, - this.semanticLabel, - this.loadingBuilder, - this.errorBuilder, - }) : super(key: key); - - /// Widget layered behind the loaded images. Displayed when [image] is null or is loading initially. - final Widget? placeholder; - - /// The image to display. Subsequently changing the image will fade the new image over the previous one. - final ImageProvider? image; - - /// The curve of the fade-in animation. - final Curve curve; - - /// The duration of the fade-in animation. - final Duration duration; - - /// An optional duration for fading in a synchronously loaded image (ex. from memory), error, or placeholder. - /// For example, you could set this to `Duration.zero` to immediately display images that are already loaded. - /// If omitted, [duration] will be used. - final Duration? syncDuration; - - /// The width to display at. See [Image.width] for more information. - final double? width; - - /// The height to display at. See [Image.height] for more information. - final double? height; - - /// The scale factor for drawing this image at its intended size. See [RawImage.scale] for more information. - final double scale; - - /// How to draw the image within its bounds. Defaults to [BoxFit.scaleDown]. See [Image.fit] for more information. - final BoxFit fit; - - /// How to align the image within its bounds. See [Image.alignment] for more information. - final Alignment alignment; - - /// How to paint any portions of the layout bounds not covered by the image. See [Image.repeat] for more information. - final ImageRepeat repeat; - - /// Whether to paint the image in the direction of the [TextDirection]. See [Image.matchTextDirection] for more information. - final bool matchTextDirection; - - /// Whether to exclude this image from semantics. See [Image.excludeFromSemantics] for more information. - final bool excludeFromSemantics; - - /// A Semantic description of the image. See [Image.semanticLabel] for more information. - final String? semanticLabel; - - /// A builder that specifies the widget to display while an image is loading. - /// See [ImageFadeLoadingBuilder] for more information. - final ImageFadeLoadingBuilder? loadingBuilder; - - /// A builder that specifies the widget to display if an error occurs while an image is loading. - /// This will be faded in over previous content, so you may want to set an opaque background on it. - final ImageFadeErrorBuilder? errorBuilder; - - @override - State createState() => _ImageFadeState(); -} - -class _ImageFadeState extends State with TickerProviderStateMixin { - _ImageResolver? _resolver; - Widget? _front; - Widget? _back; - - late final AnimationController _controller; - Widget? _fadeFront; - Widget? _fadeBack; - - bool? _sync; // could use onImage synchronousCall, but this is more forgiving - bool _shouldBuildFront = false; - - @override - void initState() { - _controller = AnimationController(vsync: this); - super.initState(); - } - - @override - void didChangeDependencies() { - super.didChangeDependencies(); - // Can't call this in initState because createLocalImageConfiguration throws errors: - _update(context); - } - - @override - void didUpdateWidget(ImageFade old) { - // not called on init - super.didUpdateWidget(old); - _update(context, old); - } - - void _update(BuildContext context, [ImageFade? old]) { - final ImageProvider? image = widget.image; - final ImageProvider? oldImage = old?.image; - if (image == oldImage) return; - - _back = null; - _shouldBuildFront = false; - - if (_resolver != null) { - // move previous loaded image to back & cancel any active loads. - if (_resolver!.complete) _back = _fadeBack = _front; - _resolver!.dispose(); - } - - // load the new image: - _front = _sync = null; - _resolver = image == null - ? null - : _ImageResolver( - image, - context, - onError: _handleComplete, - onComplete: _handleComplete, - width: widget.width, - height: widget.height, - ); - - // start transition to placeholder if there's no new image: - if (_back != null && _resolver == null) _buildTransition(); - } - - void _handleComplete(_ImageResolver resolver) { - if (_sync == null) _sync = true; - // defer building the front content until build so we have an active context. - setState(() => _shouldBuildFront = true); - } - - void _buildFront(BuildContext context) { - _shouldBuildFront = false; - _ImageResolver resolver = _resolver!; - _front = resolver.error - ? widget.errorBuilder?.call(context, resolver.exception!) - : _getImage(resolver.image); - _buildTransition(); - } - - void _buildTransition() { - final bool out = _front == null; // no new image - - // use the "fast" duration if sync load, error, or placeholder: - bool fast = (_sync != false || _resolver?.error == true || out); - Duration duration = (fast ? widget.syncDuration : null) ?? widget.duration; - - // Fade in for duration, out for 1/2 as long: - _controller.duration = duration * (out ? 1 : 3 / 2); - - _fadeFront = _buildFade( - child: _front, - opacity: CurvedAnimation( - parent: _controller, - curve: Interval(0.0, 2 / 3, curve: widget.curve), - ), - ); - - _fadeBack = _buildFade( - child: _back, - opacity: Tween(begin: 1.0, end: 0).animate( - CurvedAnimation( - parent: _controller, - curve: Interval(out ? 0.0 : 2 / 3, 1.0), - ), - ), - ); - - if (_front != null || _back != null) _controller.forward(from: 0); - } - - Widget? _buildFade({Widget? child, required Animation opacity}) { - if (child == null) return null; - // if the child is a loaded image, we can fade its opacity directly for better performance: - return (child is RawImage) - ? _getImage(child.image, opacity: opacity) - : FadeTransition(child: child, opacity: opacity); - } - - RawImage _getImage(ui.Image? image, {Animation? opacity}) { - return RawImage( - image: image, - width: widget.width, - height: widget.height, - scale: widget.scale, - fit: widget.fit, - alignment: widget.alignment, - repeat: widget.repeat, - matchTextDirection: widget.matchTextDirection, - opacity: opacity, - ); - } - - @override - Widget build(BuildContext context) { - if (_sync == null) _sync = false; - if (_shouldBuildFront) _buildFront(context); - Widget? front = _fadeFront, back = _fadeBack; - - bool inLoad = _resolver != null && !_resolver!.complete; - if (inLoad && widget.loadingBuilder != null) { - _ImageResolver resolver = _resolver!; - front = AnimatedBuilder( - animation: resolver.notifier, - builder: (_, __) => widget.loadingBuilder!( - context, - resolver.notifier.value, - resolver.chunkEvent, - ), - ); - } - - List kids = []; - if (widget.placeholder != null) kids.add(widget.placeholder!); - if (back != null) kids.add(back); - if (front != null) kids.add(front); - - Widget content = Container( - width: widget.width, - height: widget.height, - child: kids.isEmpty - ? null - : Stack(fit: StackFit.passthrough, children: kids), - ); - - if (widget.excludeFromSemantics) return content; - - String? label = widget.semanticLabel; - return Semantics( - container: label != null, - image: true, - label: label ?? "", - child: content, - ); - } - - @override - void dispose() { - _resolver?.dispose(); - _controller.dispose(); - super.dispose(); - } -} - -// Simplifies working with image loading events and states. -class _ImageResolver { - _ImageResolver( - ImageProvider provider, - BuildContext context, { - required this.onComplete, - required this.onError, - double? width, - double? height, - }) { - Size? size = width != null && height != null ? Size(width, height) : null; - ImageConfiguration config = - createLocalImageConfiguration(context, size: size); - _listener = ImageStreamListener(_handleComplete, - onChunk: _handleProgress, onError: _handleError); - _stream = provider.resolve(config); - _stream.addListener(_listener); // Called sync if already completed. - notifier = ValueNotifier(0); - } - - Object? exception; - ImageChunkEvent? chunkEvent; - late final ValueNotifier notifier; - - final Function(_ImageResolver resolver) onComplete; - final Function(_ImageResolver resolver) onError; - - late final ImageStream _stream; - late final ImageStreamListener _listener; - ImageInfo? _imageInfo; - bool _complete = false; - - ui.Image? get image => _imageInfo?.image; - - bool get complete => _complete; - - bool get error => exception != null; - - void _handleComplete(ImageInfo imageInfo, bool sync) { - _imageInfo = imageInfo; - _complete = true; - onComplete(this); - } - - void _handleProgress(ImageChunkEvent event) { - chunkEvent = event; - notifier.value = event.expectedTotalBytes != null - ? event.cumulativeBytesLoaded / event.expectedTotalBytes! - : 0.0; - } - - void _handleError(Object exc, StackTrace? _) { - exception = exc; - _complete = true; - onError(this); - } - - void dispose() { - _stream.removeListener(_listener); - } -} diff --git a/lib/widgets/mnemo_text.dart b/lib/widgets/mnemo_text.dart deleted file mode 100644 index ca6326e..0000000 --- a/lib/widgets/mnemo_text.dart +++ /dev/null @@ -1,83 +0,0 @@ -import 'package:auto_size_text/auto_size_text.dart'; -import 'package:flutter/material.dart'; -import 'package:mnemo_cards/utils/string_helper.dart'; - -class MnemoText extends StatelessWidget { - final String? mnemo; - final TextStyle? textStyle; - final TextAlign? textAlign; - final Color? color; - final AutoSizeGroup? group; - final int? maxLines; - final bool? softWrap; - - const MnemoText( - this.mnemo, { - this.textStyle, - this.textAlign, - this.color, - this.group, - this.maxLines, - this.softWrap, - super.key, - }); - - @override - Widget build(BuildContext context) { - if (mnemo == null) return SizedBox.shrink(); - final matches = RegExp(r'\{(.*?)\}').allMatches(mnemo!); - Color? color = this.color; - color ??= Colors.red; - - List spans = []; - - RegExpMatch? lastMatch; - - for (final match in matches) { - var mnemoText = matches.isEmpty - ? '' - : mnemo! - .substring(match.start, match.end) - .replaceAll(RegExp(r'[\}\{]'), ''); - if (mnemoText.startsWith('#')) { - // #123456mnemo - color = mnemoText.substring(0, 7).asColor; - mnemoText = mnemoText.substring(7); - } - spans.addAll([ - if (lastMatch == null) - TextSpan(text: mnemo!.substring(0, match.start), style: textStyle) - else - TextSpan( - text: mnemo!.substring(lastMatch.end, match.start), - style: textStyle), - TextSpan( - text: mnemoText, - style: textStyle?.copyWith(color: color) ?? TextStyle(color: color), - ), - ]); - lastMatch = match; - } - - if (lastMatch == null) { - spans.add( - TextSpan(text: mnemo, style: textStyle), - ); - } else { - spans.add(TextSpan( - text: mnemo!.substring(lastMatch.end), - style: textStyle, - )); - } - - return AutoSizeText.rich( - maxLines: maxLines, - softWrap: softWrap, - TextSpan( - children: spans, - ), - textAlign: textAlign ?? TextAlign.center, - group: group, - ); - } -} diff --git a/lib/widgets/packs_menu_widget.dart b/lib/widgets/packs_menu_widget.dart index d2b155a..d5bdb0e 100644 --- a/lib/widgets/packs_menu_widget.dart +++ b/lib/widgets/packs_menu_widget.dart @@ -7,8 +7,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:mnemo_cards/features/packs/pack_manager.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'; +import 'package:mnemo_cards_frontend_common/mnemo_cards_frontend_common.dart'; import '../di/locator.dart'; import '../domain/router/app_router.dart'; diff --git a/lib/widgets/shared_pref_button.dart b/lib/widgets/shared_pref_button.dart index d4a8f4e..1e0ff86 100644 --- a/lib/widgets/shared_pref_button.dart +++ b/lib/widgets/shared_pref_button.dart @@ -3,16 +3,17 @@ import 'dart:async'; import 'package:flutter/cupertino.dart'; import 'package:mnemo_cards/main.dart'; import 'package:mnemo_cards_common/mnemo_cards_common.dart'; +import 'package:mnemo_cards_frontend_common/mnemo_cards_frontend_common.dart'; import 'package:shared_preferences/shared_preferences.dart'; -class SharedPrefButton extends StatefulWidget { +class MobileSharedPrefButton extends StatelessWidget { final Function(T)? onClick; final String spKey; final T Function(T? current)? setOnTap; final bool Function(T? current)? shouldRebuild; final Widget Function(T? value, ValueSetter setValue)? builder; - SharedPrefButton({ + MobileSharedPrefButton({ this.builder, required this.spKey, this.setOnTap, @@ -20,7 +21,7 @@ class SharedPrefButton extends StatefulWidget { this.shouldRebuild, }); - SharedPrefButton.builder({ + MobileSharedPrefButton.builder({ this.builder, required this.spKey, this.setOnTap, @@ -29,89 +30,12 @@ class SharedPrefButton extends StatefulWidget { }); @override - State createState() => _SharedPrefButtonState(); -} - -class _SharedPrefButtonState extends State> { - SharedPreferences? _sp; - T? value; - - StreamSubscription? _streamSubscription; - - @override - void dispose() { - _streamSubscription?.cancel(); - _streamSubscription = null; - super.dispose(); - } - - @override - void initState() { - super.initState(); - _sp = globalSharedPreferences; - value = valueFromSp; - _streamSubscription = - Stream.periodic(const Duration(milliseconds: 500), (_) => valueFromSp) - .distinct() - .listen((v) { - if (value != v) { - value = v; - if (mounted && widget.shouldRebuild?.call(value) != false) { - setState(() {}); - } - } - }); - } - - T? get valueFromSp { - if (T == bool) { - return (_sp?.getBool(widget.spKey) ?? false).as(); - } else if (T == int) { - return _sp?.getInt(widget.spKey).as(); - } else if (T == num || T == double) { - return _sp?.getDouble(widget.spKey).as(); - } else if (T == String) { - return _sp?.getString(widget.spKey).as(); - } else if (T == Iterable) { - return _sp?.getStringList(widget.spKey).as(); - } - return null; - } - - Future setValue(T value) async { - if (T == bool) { - _sp?.setBool(widget.spKey, value as bool); - } else if (T == int) { - _sp?.setInt(widget.spKey, value as int); - } else if (T == num || T == double) { - _sp?.setDouble(widget.spKey, value as double); - } else if (T == String) { - _sp?.setString(widget.spKey, value as String); - } else if (T == Iterable) { - _sp?.setStringList(widget.spKey, (value as Iterable).toList()); - } - } - - @override - Widget build(BuildContext context) { - return GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: widget.setOnTap != null - ? () async { - value = widget.setOnTap!.call(value); - if (value != null) { - _setValue(value!); - } - } - : null, - child: widget.builder?.call(value, _setValue), - ); - } - - Future _setValue(T value) async { - await setValue(value!); - if (widget.shouldRebuild?.call(value) != false) { - setState(() {}); - } - } + Widget build(BuildContext context) => SharedPrefButton( + sharedPreferences: globalSharedPreferences, + spKey: spKey, + setOnTap: setOnTap, + onClick: onClick, + shouldRebuild: shouldRebuild, + builder: builder, + ); } diff --git a/lib/widgets/simple_tile.dart b/lib/widgets/simple_tile.dart deleted file mode 100644 index db8d3ec..0000000 --- a/lib/widgets/simple_tile.dart +++ /dev/null @@ -1,39 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; - -class SimpleTile extends StatelessWidget { - final Widget? trail; - final Widget title; - final VoidCallback? onTap; - - SimpleTile({ - required this.title, - this.trail, - this.onTap, - }); - - SimpleTile.text({ - required String text, - this.trail, - this.onTap, - }) : title = Text(text); - - @override - Widget build(BuildContext context) { - return GestureDetector( - onTap: onTap, - child: Container( - height: 50.h, - padding: EdgeInsets.symmetric(vertical: 4.h), - alignment: Alignment.centerLeft, - child: Row( - children: [ - Expanded(child: title), - if (trail != null) trail!, - ], - ), - ), - ); - } -} diff --git a/lib/widgets/slider.dart b/lib/widgets/slider.dart deleted file mode 100644 index 0ed3d20..0000000 --- a/lib/widgets/slider.dart +++ /dev/null @@ -1,208 +0,0 @@ -import 'dart:math'; - -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:mnemo_cards/theme/themes.dart'; - -class MnemoSlider extends StatelessWidget { - final double value; - final void Function(double)? onChanged; - final double min; - final double max; - - MnemoSlider({ - required this.value, - this.onChanged, - this.min = 0.2, - this.max = 2.0, - super.key, - }); - - @override - Widget build(BuildContext context) { - var v = this.value; - return Container( - decoration: BoxDecoration( - border: Border.all(color: borderGray), - borderRadius: BorderRadius.circular(12.0), - ), - padding: EdgeInsets.symmetric(vertical: 3, horizontal: 2.0), - child: SliderTheme( - data: SliderTheme.of(context).copyWith( - activeTrackColor: Theme.of(context).scaffoldBackgroundColor, - inactiveTrackColor: Theme.of(context).scaffoldBackgroundColor, - thumbColor: progressBlue, - thumbShape: _RectSliderThumbShape( - enabledThumbRadius: 19.0, - borderRadius: Radius.circular(10), - textBuilder: (v) { - final value = ((v * (max - min) + min) * 10).toInt(); - if (value % 10 == 0) { - return '${(value / 10).toStringAsFixed(0)}x'; - } else { - return (value / 10).toStringAsFixed(1); - } - }, - ), - trackShape: RoundedRectSliderTrackShape(), - trackHeight: 1.h, - overlayColor: Colors.transparent, - overlappingShapeStrokeColor: Colors.transparent, - overlayShape: RoundSliderOverlayShape(overlayRadius: 2.0), - ), - child: StatefulBuilder(builder: (context, setState) { - return Slider( - min: min, - max: max, - value: v, - onChanged: (updated) { - setState(() { - v = updated; - }); - onChanged?.call((updated * 100).toInt() / 100.0); - }, - ); - }), - ), - ); - } -} - -class _RectSliderThumbShape extends SliderComponentShape { - /// Create a slider thumb that draws a Rect. - const _RectSliderThumbShape({ - this.enabledThumbRadius = 10.0, - this.disabledThumbRadius, - this.elevation = 1.0, - this.pressedElevation = 6.0, - this.borderRadius, - this.textBuilder, - }); - - final String Function(double v)? textBuilder; - - /// The preferred radius of the round thumb shape when the slider is enabled. - /// - /// If it is not provided, then the Material Design default of 10 is used. - final double enabledThumbRadius; - - /// The preferred radius of the round thumb shape when the slider is disabled. - /// - /// If no disabledRadius is provided, then it is equal to the - /// [enabledThumbRadius] - final double? disabledThumbRadius; - final Radius? borderRadius; - - double get _disabledThumbRadius => disabledThumbRadius ?? enabledThumbRadius; - - /// The resting elevation adds shadow to the unpressed thumb. - /// - /// The default is 1. - /// - /// Use 0 for no shadow. The higher the value, the larger the shadow. For - /// example, a value of 12 will create a very large shadow. - /// - final double elevation; - - /// The pressed elevation adds shadow to the pressed thumb. - /// - /// The default is 6. - /// - /// Use 0 for no shadow. The higher the value, the larger the shadow. For - /// example, a value of 12 will create a very large shadow. - final double pressedElevation; - - @override - Size getPreferredSize(bool isEnabled, bool isDiscrete) { - return Size.fromRadius( - isEnabled == true ? enabledThumbRadius : _disabledThumbRadius); - } - - @override - void paint( - PaintingContext context, - Offset center, { - required Animation activationAnimation, - required Animation enableAnimation, - required bool isDiscrete, - required TextPainter labelPainter, - required RenderBox parentBox, - required SliderThemeData sliderTheme, - required TextDirection textDirection, - required double value, - required double textScaleFactor, - required Size sizeWithOverflow, - }) { - final Canvas canvas = context.canvas; - final Tween radiusTween = Tween( - begin: _disabledThumbRadius, - end: enabledThumbRadius, - ); - final ColorTween colorTween = ColorTween( - begin: sliderTheme.disabledThumbColor, - end: sliderTheme.thumbColor, - ); - - final Color color = colorTween.evaluate(enableAnimation)!; - final double radius = radiusTween.evaluate(enableAnimation); - - final Tween elevationTween = Tween( - begin: elevation, - end: pressedElevation, - ); - - final double evaluatedElevation = - elevationTween.evaluate(activationAnimation); - final Path path = Path() - ..addArc( - Rect.fromCenter( - center: center, width: 2 * radius, height: 2 * radius), - 0, - pi * 2); - - bool paintShadows = false; - assert(() { - if (debugDisableShadows) { - paintShadows = false; - } - return true; - }()); - - if (paintShadows) { - canvas.drawShadow(path, Colors.black, evaluatedElevation, true); - } - - final TextPainter textPainter = - TextPainter(textDirection: TextDirection.rtl); - textPainter.text = TextSpan( - text: textBuilder?.call(value) ?? '', - style: TextStyle( - fontSize: radius, - color: Colors.black, - )); - textPainter.layout(); - - final Offset textCenter = Offset(center.dx - (textPainter.width / 2), - center.dy - (textPainter.height / 2)); - - // Use drawRect instead of drawCircle - canvas.drawRRect( - RRect.fromRectAndRadius( - Rect.fromCircle(center: center, radius: radius), - borderRadius ?? Radius.zero, - ), - Paint()..color = borderGray, - ); - // Use drawRect instead of drawCircle - canvas.drawRRect( - RRect.fromRectAndRadius( - Rect.fromCircle(center: center, radius: radius - 1), - borderRadius ?? Radius.zero, - ), - Paint()..color = color, - ); - - textPainter.paint(canvas, textCenter); - } -} diff --git a/lib/widgets/switch_button.dart b/lib/widgets/switch_button.dart deleted file mode 100644 index 1fd353c..0000000 --- a/lib/widgets/switch_button.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:mnemo_cards/theme/themes.dart'; - -class SwitchButton extends StatelessWidget { - final bool value; - final void Function(bool)? onChanged; - - SwitchButton({ - required this.value, - required this.onChanged, - }); - - @override - Widget build(BuildContext context) { - return Switch( - value: value, - onChanged: onChanged, - activeColor: progressBlue, - activeTrackColor: Theme.of(context).scaffoldBackgroundColor, - inactiveTrackColor: Theme.of(context).scaffoldBackgroundColor, - trackOutlineColor: WidgetStatePropertyAll(borderGray), - inactiveThumbColor: borderGray, - ); - } -} diff --git a/lib/widgets/switch_tile.dart b/lib/widgets/switch_tile.dart deleted file mode 100644 index 5735ee8..0000000 --- a/lib/widgets/switch_tile.dart +++ /dev/null @@ -1,28 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:mnemo_cards/widgets/switch_button.dart'; - -class SwitchTile extends StatelessWidget { - final bool value; - final void Function(bool)? onChanged; - final String text; - - SwitchTile({ - required this.text, - required this.value, - this.onChanged, - }); - - @override - Widget build(BuildContext context) { - return Row( - children: [ - Expanded(child: Text(text, overflow: TextOverflow.ellipsis,)), - SwitchButton( - value: value, - onChanged: onChanged ?? (v) {}, - ), - ], - ); - } -} diff --git a/lib/widgets/text_button.dart b/lib/widgets/text_button.dart deleted file mode 100644 index b10cade..0000000 --- a/lib/widgets/text_button.dart +++ /dev/null @@ -1,28 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; - -class LinkButton extends StatelessWidget { - final VoidCallback? onPressed; - final String text; - - LinkButton(this.text, this.onPressed); - - @override - Widget build(BuildContext context) { - return GestureDetector( - onTap: onPressed, - child: Padding( - padding: EdgeInsets.only(top: 2.0.h, bottom: 2.0.h), - child: Text( - text, - style: TextStyle( - fontWeight: FontWeight.w700, - fontSize: 16, - decoration: TextDecoration.underline, - ), - ), - ), - ); - } -} diff --git a/lib/widgets/user_statistics.dart b/lib/widgets/user_statistics.dart deleted file mode 100644 index 65e855d..0000000 --- a/lib/widgets/user_statistics.dart +++ /dev/null @@ -1,105 +0,0 @@ -import 'package:auto_size_text/auto_size_text.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:mnemo_cards_common/mnemo_cards_common.dart'; - -import '../theme/themes.dart'; -import 'horizontal_progress.dart'; - -class UserStatistics extends StatelessWidget { - final UserDataDto? userDataDto; - - UserStatistics(this.userDataDto); - - @override - Widget build(BuildContext context) { - final words = userDataDto?.allWordsStatistics?.words ?? []; - words.sort( - (p, n) => (n.correct / n.total).compareTo(p.correct / p.total), - ); - final learnedWords = words - .where((w) => w.correct > 10 && w.correct / w.total > 0.9) - .map((e) => e.word) - .toSet(); - final learnedWordsLength = learnedWords.length; - final lastDigit = learnedWordsLength % 10; - final String? totalWordsText; - if (learnedWordsLength == 0) { - totalWordsText = 'Словарик'; - } else if (lastDigit == 0 || lastDigit >= 5) { - totalWordsText = 'Ты уже знаешь $learnedWordsLength слов!'; - } else if (lastDigit == 1) { - totalWordsText = 'Ты уже знаешь $learnedWordsLength слово!'; - } else { - totalWordsText = 'Ты уже знаешь $learnedWordsLength слова!'; - } - - return Column( - children: [ - Padding( - padding: EdgeInsets.only(bottom: 8.0.h, top: 8.0.h), - child: Row( - children: [ - Text( - totalWordsText, - style: TextStyle( - fontSize: 18, - ), - maxLines: 1, - ), - ], - ), - ), - Expanded( - child: Container( - decoration: BoxDecoration( - border: Border.all(color: borderGray), - borderRadius: BorderRadius.circular(12), - ), - padding: EdgeInsets.symmetric(horizontal: 8.0.w), - child: words.isEmpty - ? Center( - child: AutoSizeText('Тут будут все пройденные слова'), - ) - : ListView.builder( - itemCount: words.length, - shrinkWrap: true, - itemBuilder: (context, index) { - final word = words[index]; - return Padding( - padding: EdgeInsets.symmetric(vertical: 2.0.h), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - '${word.word}', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w700, - ), - ), - Flexible( - child: SizedBox( - width: MediaQuery.of(context).size.width / 2.5, - child: HorizontalProgressWidget( - (word.correct * 100).floor(), - (word.total * 100).floor(), - learnedWords.contains(word.word) - ? golden - : progressBlue, - borderColor: borderGray, - height: 20.h, - ), - ), - ), - ], - ), - ); - }, - ), - ), - ), - ], - ); - } -} diff --git a/pubspec.lock b/pubspec.lock index e9dc48e..00a1925 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -37,10 +37,10 @@ packages: dependency: "direct main" description: name: archive - sha256: ecf4273855368121b1caed0d10d4513c7241dfc813f7d3c8933b36622ae9b265 + sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d url: "https://pub.dev" source: hosted - version: "3.5.1" + version: "3.6.1" args: dependency: transitive description: @@ -61,18 +61,18 @@ packages: dependency: "direct main" description: name: auto_route - sha256: "6cad3f408863ffff2b5757967c802b18415dac4acb1b40c5cdd45d0a26e5080f" + sha256: a9001a90539ca3effc168f7e1029a5885c7326b9032c09ac895e303c1d137704 url: "https://pub.dev" source: hosted - version: "8.1.3" + version: "8.3.0" auto_route_generator: dependency: "direct dev" description: name: auto_route_generator - sha256: ba28133d3a3bf0a66772bcc98dade5843753cd9f1a8fb4802b842895515b67d3 + sha256: a21d7a936c917488653c972f62d884d8adcf8c5d37acc7cd24da33cf784546c0 url: "https://pub.dev" source: hosted - version: "8.0.0" + version: "8.1.0" auto_size_text: dependency: "direct main" description: @@ -109,10 +109,10 @@ packages: dependency: transitive description: name: build_daemon - sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" + sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" url: "https://pub.dev" source: hosted - version: "4.0.1" + version: "4.0.2" build_resolvers: dependency: transitive description: @@ -125,18 +125,18 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22" + sha256: "644dc98a0f179b872f612d3eb627924b578897c629788e858157fa5e704ca0c7" url: "https://pub.dev" source: hosted - version: "2.4.9" + version: "2.4.11" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799" + sha256: e3c79f69a64bdfcd8a776a3c28db4eb6e3fb5356d013ae5eb2e52007706d5dbe url: "https://pub.dev" source: hosted - version: "7.3.0" + version: "7.3.1" built_collection: dependency: transitive description: @@ -189,26 +189,26 @@ packages: dependency: "direct main" description: name: cloud_firestore - sha256: e461ea9ab23959102a780efcbccfe33c2ac46269928bc57093bbc0b526afc801 + sha256: a0f161b92610e078b4962d7e6ebeb66dc9cce0ada3514aeee442f68165d78185 url: "https://pub.dev" source: hosted - version: "4.17.3" + version: "4.17.5" cloud_firestore_platform_interface: dependency: transitive description: name: cloud_firestore_platform_interface - sha256: "2e0b8db9a759ffc71086019f1bd27237e5e888ab1e99c507067ff8616acdfa24" + sha256: "6a55b319f8d33c307396b9104512e8130a61904528ab7bd8b5402678fca54b81" url: "https://pub.dev" source: hosted - version: "6.2.3" + version: "6.2.5" cloud_firestore_web: dependency: transitive description: name: cloud_firestore_web - sha256: "37b6974bef5b0a7ecd31037ffb7d7bfe6bb9d2ac6c064fbea395411ef0a64d55" + sha256: "89dfa1304d3da48b3039abbb2865e3d30896ef858e569a16804a99f4362283a9" url: "https://pub.dev" source: hosted - version: "3.12.3" + version: "3.12.5" code_builder: dependency: transitive description: @@ -309,10 +309,18 @@ packages: dependency: "direct main" description: name: dio - sha256: "11e40df547d418cc0c4900a9318b26304e665da6fa4755399a9ff9efd09034b5" + sha256: e17f6b3097b8c51b72c74c9f071a605c47bcc8893839bd66732457a5ebe73714 url: "https://pub.dev" source: hosted - version: "5.4.3+1" + version: "5.5.0+1" + dio_web_adapter: + dependency: transitive + description: + name: dio_web_adapter + sha256: "36c5b2d79eb17cdae41e974b7a8284fec631651d2a6f39a8a2ff22327e90aeac" + url: "https://pub.dev" + source: hosted + version: "1.0.1" dot_navigation_bar: dependency: "direct main" description: @@ -357,10 +365,10 @@ packages: dependency: "direct main" description: name: file_picker - sha256: "29c90806ac5f5fb896547720b73b17ee9aed9bba540dc5d91fe29f8c5745b10a" + sha256: "824f5b9f389bfc4dddac3dea76cd70c51092d9dff0b2ece7ef4f53db8547d258" url: "https://pub.dev" source: hosted - version: "8.0.3" + version: "8.0.6" firebase_analytics: dependency: "direct main" description: @@ -397,18 +405,18 @@ packages: dependency: transitive description: name: firebase_core_platform_interface - sha256: c437ae5d17e6b5cc7981cf6fd458a5db4d12979905f9aafd1fea930428a9fe63 + sha256: "1003a5a03a61fc9a22ef49f37cbcb9e46c86313a7b2e7029b9390cf8c6fc32cb" url: "https://pub.dev" source: hosted - version: "5.0.0" + version: "5.1.0" firebase_core_web: dependency: transitive description: name: firebase_core_web - sha256: "43d9e951ac52b87ae9cc38ecdcca1e8fa7b52a1dd26a96085ba41ce5108db8e9" + sha256: "23509cb3cddfb3c910c143279ac3f07f06d3120f7d835e4a5d4b42558e978712" url: "https://pub.dev" source: hosted - version: "2.17.0" + version: "2.17.3" firebase_crashlytics: dependency: "direct main" description: @@ -466,34 +474,42 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 + sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c" url: "https://pub.dev" source: hosted - version: "2.0.3" + version: "4.0.0" flutter_native_splash: dependency: "direct dev" description: name: flutter_native_splash - sha256: edf39bcf4d74aca1eb2c1e43c3e445fd9f494013df7f0da752fefe72020eedc0 + sha256: aa06fec78de2190f3db4319dd60fdc8d12b2626e93ef9828633928c2dcaea840 url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.1" flutter_plugin_android_lifecycle: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "8cf40eebf5dec866a6d1956ad7b4f7016e6c0cc69847ab946833b7d43743809f" + sha256: c6b0b4c05c458e1c01ad9bcc14041dd7b1f6783d487be4386f793f47a8a4d03e url: "https://pub.dev" source: hosted - version: "2.0.19" + version: "2.0.20" + flutter_rustore_billing: + dependency: "direct main" + description: + name: flutter_rustore_billing + sha256: "95905fec5ab46f7d0e798469c847423aa4dac07461a6111892be3f34c48a5b75" + url: "https://pub.dev" + source: hosted + version: "6.0.1" flutter_screenutil: dependency: "direct main" description: name: flutter_screenutil - sha256: "8cf100b8e4973dc570b6415a2090b0bfaa8756ad333db46939efc3e774ee100d" + sha256: "8239210dd68bee6b0577aa4a090890342d04a136ce1c81f98ee513fc0ce891de" url: "https://pub.dev" source: hosted - version: "5.9.0" + version: "5.9.3" flutter_secure_storage: dependency: "direct main" description: @@ -572,10 +588,10 @@ packages: dependency: "direct main" description: name: freezed_annotation - sha256: c3fd9336eb55a38cc1bbd79ab17573113a8deccd0ecbbf926cca3c62803b5c2d + sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2 url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.4" frontend_server_client: dependency: transitive description: @@ -600,6 +616,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" + go_router: + dependency: transitive + description: + name: go_router + sha256: b465e99ce64ba75e61c8c0ce3d87b66d8ac07f0b35d0a7e0263fcfc10f99e836 + url: "https://pub.dev" + source: hosted + version: "13.2.5" google_identity_services_web: dependency: transitive description: @@ -620,10 +644,10 @@ packages: dependency: transitive description: name: google_sign_in_android - sha256: "7647893c65e6720973f0e579051c8f84b877b486614d9f70a404259c41a4632e" + sha256: d30fb34b659679ea74397e9748b4ab5d720720d57dcc79538f1b3c4a68654cb3 url: "https://pub.dev" source: hosted - version: "6.1.23" + version: "6.1.27" google_sign_in_ios: dependency: transitive description: @@ -644,18 +668,18 @@ packages: dependency: transitive description: name: google_sign_in_web - sha256: fc0f14ed45ea616a6cfb4d1c7534c2221b7092cc4f29a709f0c3053cc3e821bd + sha256: d606264c7a1a526a3aa79d938b85a601d8589731a478bd4a3dcbdeb14a572228 url: "https://pub.dev" source: hosted - version: "0.12.4" + version: "0.12.4+1" graphs: dependency: transitive description: name: graphs - sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" html: dependency: transitive description: @@ -668,12 +692,12 @@ packages: dependency: transitive description: name: http - sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" + sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" http_certificate_pinning: - dependency: "direct main" + dependency: transitive description: name: http_certificate_pinning sha256: "12b4848113d50c570af93e94bed64004caba14dde87719310d1e4556686c0afa" @@ -700,10 +724,10 @@ packages: dependency: transitive description: name: image - sha256: "4c68bfd5ae83e700b5204c1e74451e7bf3cf750e6843c6e158289cf56bda018e" + sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8" url: "https://pub.dev" source: hosted - version: "4.1.7" + version: "4.2.0" in_app_purchase: dependency: "direct main" description: @@ -716,10 +740,10 @@ packages: dependency: transitive description: name: in_app_purchase_android - sha256: "25b4bc74d4d990c18a889ea9486cb9029285955f38ca81ff335c8936edf9e66d" + sha256: f3f3ded26d08d13383b8c9952d1cf1422f0a3440b04d27f9838adee86f2ce899 url: "https://pub.dev" source: hosted - version: "0.3.5" + version: "0.3.6+2" in_app_purchase_platform_interface: dependency: transitive description: @@ -732,18 +756,18 @@ packages: dependency: transitive description: name: in_app_purchase_storekit - sha256: c13e4fee493dff3e956ebd24f80656f5ddbf876a8d12817d6fbe52d90e7c2068 + sha256: "187f12ba8030993d117d11d1a16d3607734140d572ce1ede088bfcec960b65df" url: "https://pub.dev" source: hosted - version: "0.3.15" + version: "0.3.17+1" injectable: dependency: transitive description: name: injectable - sha256: fb722c86cf8233008e4db41c696a6145721f45dc8aeba91103e3128c3d63c9c6 + sha256: "3c8355a29d11ff28c0311bed754649761f345ef7a13ff66a714380954af51226" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.2" injectable_generator: dependency: "direct dev" description: @@ -764,10 +788,10 @@ packages: dependency: "direct main" description: name: jailbreak_root_detection - sha256: "03c7bb8ba1c12ea2b75400b152e89ae8cf50abf0c88777a5e564af4a04aeebf2" + sha256: "7dd3418d1784892dbcb6cc25df53679aa7717a2d007b34f59d570ae2ec6edfa6" url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.4" js: dependency: transitive description: @@ -820,10 +844,10 @@ packages: dependency: transitive description: name: lints - sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" + sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "4.0.0" logging: dependency: transitive description: @@ -871,6 +895,13 @@ packages: relative: true source: path version: "0.0.1" + mnemo_cards_frontend_common: + dependency: "direct main" + description: + path: "../mnemo_cards_frontend_common" + relative: true + source: path + version: "0.0.1" nested: dependency: transitive description: @@ -883,10 +914,10 @@ packages: dependency: "direct main" description: name: no_screenshot - sha256: c8621208e3e01e5b9c6d8f4611241465436618ffd3da8340bd533f8241a33fc5 + sha256: "8415601932f84d103edda5378cacd0e10c8d8ca40de4dd8ad0496d1eee71107a" url: "https://pub.dev" source: hosted - version: "0.0.1+6" + version: "0.0.1+7" package_config: dependency: transitive description: @@ -931,10 +962,10 @@ packages: dependency: transitive description: name: path_provider_android - sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d + sha256: "30c5aa827a6ae95ce2853cdc5fe3971daaac00f6f081c419c013f7f57bff2f5e" url: "https://pub.dev" source: hosted - version: "2.2.4" + version: "2.2.7" path_provider_foundation: dependency: transitive description: @@ -963,10 +994,10 @@ packages: dependency: transitive description: name: path_provider_windows - sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.3.0" petitparser: dependency: transitive description: @@ -979,10 +1010,10 @@ packages: dependency: transitive description: name: platform - sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" + sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" url: "https://pub.dev" source: hosted - version: "3.1.4" + version: "3.1.5" plugin_platform_interface: dependency: transitive description: @@ -1019,10 +1050,10 @@ packages: dependency: transitive description: name: pubspec_parse - sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367 + sha256: c799b721d79eb6ee6fa56f00c04b472dcd44a30d258fac2174a6ec57302678f8 url: "https://pub.dev" source: hosted - version: "1.2.3" + version: "1.3.0" recase: dependency: transitive description: @@ -1051,10 +1082,10 @@ packages: dependency: "direct main" description: name: rxdart - sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" + sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" url: "https://pub.dev" source: hosted - version: "0.27.7" + version: "0.28.0" shared_preferences: dependency: "direct main" description: @@ -1067,10 +1098,10 @@ packages: dependency: transitive description: name: shared_preferences_android - sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2" + sha256: "93d0ec9dd902d85f326068e6a899487d1f65ffcd5798721a95330b26c8131577" url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.3" shared_preferences_foundation: dependency: transitive description: @@ -1091,10 +1122,10 @@ packages: dependency: transitive description: name: shared_preferences_platform_interface - sha256: "22e2ecac9419b4246d7c22bfbbda589e3acf5c0351137d87dd2939d984d37c3b" + sha256: "034650b71e73629ca08a0bd789fd1d83cc63c2d1e405946f7cef7bc37432f93a" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.0" shared_preferences_web: dependency: transitive description: @@ -1123,10 +1154,10 @@ packages: dependency: transitive description: name: shelf_web_socket - sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" + sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "2.0.0" shimmer: dependency: "direct main" description: @@ -1248,26 +1279,26 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "6ce1e04375be4eed30548f10a315826fd933c1e493206eab82eed01f438c8d2e" + sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3" url: "https://pub.dev" source: hosted - version: "6.2.6" + version: "6.3.0" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "360a6ed2027f18b73c8d98e159dda67a61b7f2e0f6ec26e86c3ada33b0621775" + sha256: "95d8027db36a0e52caf55680f91e33ea6aa12a3ce608c90b06f4e429a21067ac" url: "https://pub.dev" source: hosted - version: "6.3.1" + version: "6.3.5" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "7068716403343f6ba4969b4173cbf3b84fc768042124bc2c011e5d782b24fe89" + sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.3.1" url_launcher_linux: dependency: transitive description: @@ -1348,30 +1379,38 @@ packages: url: "https://pub.dev" source: hosted version: "0.5.1" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83" + url: "https://pub.dev" + source: hosted + version: "0.1.6" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: "58c6666b342a38816b2e7e50ed0f1e261959630becd4c879c4f26bfa14aa5a42" + sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f" url: "https://pub.dev" source: hosted - version: "2.4.5" + version: "3.0.1" webview_flutter: dependency: "direct main" description: name: webview_flutter - sha256: "25e1b6e839e8cbfbd708abc6f85ed09d1727e24e08e08c6b8590d7c65c9a8932" + sha256: "6869c8786d179f929144b4a1f86e09ac0eddfe475984951ea6c634774c16b522" url: "https://pub.dev" source: hosted - version: "4.7.0" + version: "4.8.0" webview_flutter_android: dependency: transitive description: name: webview_flutter_android - sha256: dad3313c9ead95517bb1cae5e1c9d20ba83729d5a59e5e83c0a2d66203f27f91 + sha256: f42447ca49523f11d8f70abea55ea211b3cafe172dd7a0e7ac007bb35dd356dc url: "https://pub.dev" source: hosted - version: "3.16.1" + version: "3.16.4" webview_flutter_platform_interface: dependency: transitive description: @@ -1384,18 +1423,18 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: f12f8d8a99784b863e8b85e4a9a5e3cf1839d6803d2c0c3e0533a8f3c5a992a7 + sha256: "9c62cc46fa4f2d41e10ab81014c1de470a6c6f26051a2de32111b2ee55287feb" url: "https://pub.dev" source: hosted - version: "3.13.0" + version: "3.14.0" win32: dependency: transitive description: name: win32 - sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb" + sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4 url: "https://pub.dev" source: hosted - version: "5.5.0" + version: "5.5.1" win32_registry: dependency: transitive description: @@ -1432,10 +1471,10 @@ packages: dependency: "direct main" description: name: yandex_mobileads - sha256: "3c98919a96edb1c30f6407df1f599cf6ca24eb8e45e88477117d71ff3ee73147" + sha256: "836d886d1eab1e42dee819415e0d5320bb3003632b879a470a2190ec0b940e36" url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "7.1.0" yookassa_client: dependency: "direct main" description: @@ -1445,5 +1484,5 @@ packages: source: hosted version: "1.0.2" sdks: - dart: ">=3.3.0 <4.0.0" - flutter: ">=3.19.0" + dart: ">=3.4.0 <4.0.0" + flutter: ">=3.22.0" diff --git a/pubspec.yaml b/pubspec.yaml index ac5d75e..dd0698b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: mnemo_cards description: Mnemo publish_to: 'none' -version: 1.0.1 +version: 1.0.1+11 environment: sdk: '>=3.1.3 <4.0.0' @@ -14,6 +14,11 @@ dependencies: mnemo_cards_common: path: ../mnemo_cards_common + mnemo_cards_frontend_common: + path: ../mnemo_cards_frontend_common + + + get_it: shared_preferences: ^2.2.3 flutter_secure_storage: ^9.2.2 @@ -37,7 +42,7 @@ dependencies: google_sign_in: device_info_plus: ^9.1.2 package_info_plus: ^8.0.0 - yandex_mobileads: ^6.1.0 + yandex_mobileads: ^7.1.0 firebase_crashlytics: ^3.5.7 firebase_analytics: ^10.10.7 in_app_purchase: ^3.2.0 @@ -56,11 +61,10 @@ dependencies: no_screenshot: ^0.0.1+6 file_picker: - http_certificate_pinning: ^2.1.3 url_launcher: ^6.2.6 -# requests_inspector: ^4.0.3 - +# RUSTORE + flutter_rustore_billing: ^6.0.1 collection: any freezed_annotation: any @@ -71,7 +75,7 @@ dev_dependencies: auto_route_generator: build_runner: injectable_generator: - flutter_lints: ^2.0.0 + flutter_lints: ^4.0.0 flutter_launcher_icons: ^0.13.1 flutter_native_splash: ^2.4.0