stuff
12
.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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -3,8 +3,5 @@
|
|||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<application
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
||||
|
|
|
|||
|
|
@ -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" />
|
||||
</application>
|
||||
<!-- Required to query activities that can process text, see:
|
||||
https://developer.android.com/training/package-visibility and
|
||||
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
|
||||
|
||||
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.TTS_SERVICE" />
|
||||
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
||||
<data android:mimeType="text/plain"/>
|
||||
</intent>
|
||||
</queries>
|
||||
</manifest>
|
||||
|
|
|
|||
|
|
@ -2,5 +2,4 @@ package com.cinnabarflower.mnemo_cards
|
|||
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
|
||||
class MainActivity: FlutterActivity() {
|
||||
}
|
||||
class MainActivity: FlutterActivity()
|
||||
|
Before Width: | Height: | Size: 544 B |
|
Before Width: | Height: | Size: 442 B |
|
Before Width: | Height: | Size: 721 B |
|
Before Width: | Height: | Size: 1 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
org.gradle.jvmargs=-Xmx4608M
|
||||
org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
|
|
|||
|
|
@ -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
|
||||
4
android/key.properties
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
storePassword=345234
|
||||
keyPassword=345234
|
||||
keyAlias=upload
|
||||
storeFile=../../../../upload-keystore.jks
|
||||
BIN
android/pepk.jar
Normal file
|
|
@ -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"
|
||||
|
|
|
|||
BIN
cerdo_1024x512.png
Normal file
|
After Width: | Height: | Size: 169 KiB |
BIN
cerdo_512.png
Normal file
|
After Width: | Height: | Size: 178 KiB |
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -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<bool> buyPack(CardPackBuyDto dto) async {
|
||||
try {
|
||||
final pack = await getPackStoreProduct(dto);
|
||||
final result = await buyItemInStore(pack.first);
|
||||
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<List<ProductDetails>> getPackStoreProduct(CardPackBuyDto dto) async {
|
||||
Future<List<ProductDetails>> _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<bool> buyItemInStore(ProductDetails product) async {
|
||||
Future<bool> _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');
|
||||
|
|
|
|||
50
lib/features/purchase/rustore/mnemo_rustore.dart
Normal file
|
|
@ -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<bool> 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<bool> 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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<MainTabsPage> {
|
|||
|
||||
_Tabs _currentTab = _Tabs.home;
|
||||
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
print('CHANGE DEPS');
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
|
|
|||
|
|
@ -171,5 +171,3 @@ class UserManager {
|
|||
_subscription = null;
|
||||
}
|
||||
}
|
||||
|
||||
enum ExternalIdType { google, device }
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class AuthPage extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
if (ADMIN_BUILD)
|
||||
SharedPrefButton<bool>(
|
||||
MobileSharedPrefButton<bool>(
|
||||
builder: (v, _) => (v ?? false) ? Text('PROD') : Text('TEST'),
|
||||
spKey: 'env',
|
||||
setOnTap: (v) => !(v ?? false),
|
||||
|
|
|
|||
|
|
@ -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<bool>(
|
||||
child: MobileSharedPrefButton<bool>(
|
||||
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),
|
||||
|
|
|
|||
|
|
@ -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<bool>.builder(
|
||||
MobileSharedPrefButton<bool>.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<bool>.builder(
|
||||
MobileSharedPrefButton<bool>.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<bool>.builder(
|
||||
MobileSharedPrefButton<bool>.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<bool>.builder(
|
||||
MobileSharedPrefButton<bool>.builder(
|
||||
spKey: 'auto_play_sound_tests',
|
||||
builder: (enabled, _) => AbsorbPointer(
|
||||
child: SwitchTile(
|
||||
|
|
@ -108,7 +103,7 @@ class SettingsPage extends StatelessWidget {
|
|||
),
|
||||
SimpleTile.text(
|
||||
text: 'Скорость чтения',
|
||||
trail: SharedPrefButton<double>.builder(
|
||||
trail: MobileSharedPrefButton<double>.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<bool>.builder(
|
||||
MobileSharedPrefButton<bool>.builder(
|
||||
spKey: 'show_admin',
|
||||
builder: (enabled, _) => AbsorbPointer(
|
||||
child: SwitchTile(
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<CardsView>
|
|||
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),
|
||||
|
|
|
|||
|
|
@ -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<StatefulWidget> createState() => _EnterPromoCodeState();
|
||||
}
|
||||
class MobileEnterPromoCodeWidget extends StatelessWidget {
|
||||
|
||||
class _EnterPromoCodeState extends State<EnterPromoCodeWidget> {
|
||||
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();
|
||||
return EnterPromoCodeWidget(onApplyPromoCode: onApplyPromoCode);
|
||||
}
|
||||
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!),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
Future<(bool, String?)> onApplyPromoCode(String code) async {
|
||||
final result = await locator.userManager.applyPromocode(code);
|
||||
return (result.success ?? false, result.message);
|
||||
}
|
||||
|
||||
const MobileEnterPromoCodeWidget();
|
||||
}
|
||||
|
|
@ -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,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class FeedbackBuilder {
|
||||
static Widget tests(Widget child, int index, Animation<double> 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),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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<StatefulWidget> createState() => _ImageFadeState();
|
||||
}
|
||||
|
||||
class _ImageFadeState extends State<ImageFade> 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<double>(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<double> 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<double>? 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<Widget> 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<double> 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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<TextSpan> 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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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<T> extends StatefulWidget {
|
||||
class MobileSharedPrefButton<T> 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<T> setValue)? builder;
|
||||
|
||||
SharedPrefButton({
|
||||
MobileSharedPrefButton({
|
||||
this.builder,
|
||||
required this.spKey,
|
||||
this.setOnTap,
|
||||
|
|
@ -20,7 +21,7 @@ class SharedPrefButton<T> extends StatefulWidget {
|
|||
this.shouldRebuild,
|
||||
});
|
||||
|
||||
SharedPrefButton.builder({
|
||||
MobileSharedPrefButton.builder({
|
||||
this.builder,
|
||||
required this.spKey,
|
||||
this.setOnTap,
|
||||
|
|
@ -29,89 +30,12 @@ class SharedPrefButton<T> extends StatefulWidget {
|
|||
});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _SharedPrefButtonState<T>();
|
||||
}
|
||||
|
||||
class _SharedPrefButtonState<T> extends State<SharedPrefButton<T>> {
|
||||
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<T?>();
|
||||
} else if (T == int) {
|
||||
return _sp?.getInt(widget.spKey).as<T?>();
|
||||
} else if (T == num || T == double) {
|
||||
return _sp?.getDouble(widget.spKey).as<T?>();
|
||||
} else if (T == String) {
|
||||
return _sp?.getString(widget.spKey).as<T?>();
|
||||
} else if (T == Iterable<String>) {
|
||||
return _sp?.getStringList(widget.spKey).as<T?>();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<void> 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<String>) {
|
||||
_sp?.setStringList(widget.spKey, (value as Iterable<String>).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),
|
||||
Widget build(BuildContext context) => SharedPrefButton(
|
||||
sharedPreferences: globalSharedPreferences,
|
||||
spKey: spKey,
|
||||
setOnTap: setOnTap,
|
||||
onClick: onClick,
|
||||
shouldRebuild: shouldRebuild,
|
||||
builder: builder,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _setValue(T value) async {
|
||||
await setValue(value!);
|
||||
if (widget.shouldRebuild?.call(value) != false) {
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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!,
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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<double> activationAnimation,
|
||||
required Animation<double> 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<double> radiusTween = Tween<double>(
|
||||
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<double> elevationTween = Tween<double>(
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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) {},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
229
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"
|
||||
|
|
|
|||
16
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
|
||||
|
|
|
|||