diff --git a/i18n/en.json b/i18n/en.json
index e549413..4ce1721 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -330,7 +330,7 @@
"Progressindicator for the tests":"Where do you stand achieving your tests?",
"Progressindicator_desc":"
It shows which muscle group test did your achieved already.
When do you reach the 100% test round?
If you have sucessfully tested one of the base exercises of each muscle group
",
- "Unleash Your Development Now!":"Unleash Your Development Now!",
+ "Unleash Your Development Now!":"Commit To Your Development",
"Learn about your development, enjoy AI-driven predictions of all of your skills and bodyparts.":"Learn about your development, enjoy AI-driven predictions of all of your skills and bodyparts.",
"Subscription Conditions":"Subscription Conditions",
"Payment will be charged to your account. Subscription automatically renews unless auto-renew is turned off at least 24 hours before the end of the current period":"Payment will be charged to your account. Subscription automatically renews unless auto-renew is turned off at least 24 hours before the end of the current period",
@@ -471,6 +471,13 @@
"Please take a short tour in the app":"Please take a short tour in the app",
"No Login":"No Login",
"You will skip the login.":"You will skip the login.",
- "The app functionalitity will be restricted, but please take a tour!":"The app functionalitity will be restricted, but please take a tour!"
+ "The app functionalitity will be restricted, but please take a tour!":"The app functionalitity will be restricted, but please take a tour!",
+
+ "Activating the basic tutorial":"Activating the basic tutorial",
+ "Basic Tutorial":"Basic Tutorial",
+ "Activate":"Activate",
+
+ "Try free for 3 days!":"Try it without risk for 3 days! In this period you can cancel any time without lasting your account.",
+ "View other alternatives":"View other alternatives"
}
\ No newline at end of file
diff --git a/i18n/hu.json b/i18n/hu.json
index 52f8310..409279b 100644
--- a/i18n/hu.json
+++ b/i18n/hu.json
@@ -463,5 +463,12 @@
"Please take a short tour in the app":"Kérlek tégy egy rövid túrát az applikációban",
"No Login":"Bejelentkezés kimaradt",
"You will skip the login.":"Átugrod a bejelentkezést.",
- "The app functionalitity will be restricted, but please take a tour!":"Az applikációt korlátozottan tudod így használni, de tégy egy túrát!"
+ "The app functionalitity will be restricted, but please take a tour!":"Az applikációt korlátozottan tudod így használni, de tégy egy túrát!",
+
+ "Activating the basic tutorial":"Bemutató aktiválása",
+ "Basic Tutorial":"Alap bemutató",
+ "Activate":"Aktivál",
+
+ "Try free for 3 days!":"Próbáld ki kockázat nélkül 3 napig! Ebben az időszakban bármikor lemondhatod, anélkül, hogy megterhelnénk a számládat.",
+ "View other alternatives":"Megnézek egy másik lehetőséget"
}
\ No newline at end of file
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 47f524b..8e3f912 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -18,74 +18,108 @@ PODS:
- FBSDKLoginKit/Login (= 9.1.0)
- FBSDKLoginKit/Login (9.1.0):
- FBSDKCoreKit (~> 9.1.0)
- - Firebase/Analytics (7.3.0):
+ - Firebase/Analytics (7.11.0):
- Firebase/Core
- - Firebase/Auth (7.3.0):
+ - Firebase/Auth (7.11.0):
- Firebase/CoreOnly
- - FirebaseAuth (~> 7.3.0)
- - Firebase/Core (7.3.0):
+ - FirebaseAuth (~> 7.11.0)
+ - Firebase/Core (7.11.0):
- Firebase/CoreOnly
- - FirebaseAnalytics (= 7.3.0)
- - Firebase/CoreOnly (7.3.0):
- - FirebaseCore (= 7.3.0)
- - Firebase/Messaging (7.3.0):
+ - FirebaseAnalytics (~> 7.11.0)
+ - Firebase/CoreOnly (7.11.0):
+ - FirebaseCore (= 7.11.0)
+ - Firebase/Messaging (7.11.0):
- Firebase/CoreOnly
- - FirebaseMessaging (~> 7.3.0)
- - firebase_analytics (8.0.0-dev.2):
- - Firebase/Analytics (= 7.3.0)
+ - FirebaseMessaging (~> 7.11.0)
+ - Firebase/RemoteConfig (7.11.0):
+ - Firebase/CoreOnly
+ - FirebaseRemoteConfig (~> 7.11.0)
+ - firebase_analytics (8.0.2):
+ - Firebase/Analytics (= 7.11.0)
- firebase_core
- Flutter
- - firebase_auth (1.0.3):
- - Firebase/Auth (= 7.3.0)
+ - firebase_auth (1.1.2):
+ - Firebase/Auth (= 7.11.0)
- firebase_core
- Flutter
- - firebase_core (1.0.3):
- - Firebase/CoreOnly (= 7.3.0)
+ - firebase_core (1.1.0):
+ - Firebase/CoreOnly (= 7.11.0)
- Flutter
- - firebase_messaging (9.1.1):
- - Firebase/Messaging (= 7.3.0)
+ - firebase_messaging (9.1.3):
+ - Firebase/Messaging (= 7.11.0)
- firebase_core
- Flutter
- - FirebaseAnalytics (7.3.0):
+ - firebase_remote_config (0.10.0-dev.2):
+ - Firebase/RemoteConfig (= 7.11.0)
+ - firebase_core
+ - Flutter
+ - FirebaseABTesting (7.11.0):
+ - FirebaseCore (~> 7.0)
+ - FirebaseAnalytics (7.11.0):
+ - FirebaseAnalytics/AdIdSupport (= 7.11.0)
- FirebaseCore (~> 7.0)
- FirebaseInstallations (~> 7.0)
- - GoogleAppMeasurement (= 7.3.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.0)
- GoogleUtilities/MethodSwizzler (~> 7.0)
- GoogleUtilities/Network (~> 7.0)
- "GoogleUtilities/NSData+zlib (~> 7.0)"
- - nanopb (~> 2.30906.0)
- - FirebaseAuth (7.3.0):
+ - nanopb (~> 2.30908.0)
+ - FirebaseAnalytics/AdIdSupport (7.11.0):
+ - FirebaseAnalytics/Base (= 7.11.0)
+ - FirebaseCore (~> 7.0)
+ - FirebaseInstallations (~> 7.0)
+ - GoogleAppMeasurement/AdIdSupport (= 7.11.0)
+ - GoogleUtilities/AppDelegateSwizzler (~> 7.0)
+ - GoogleUtilities/MethodSwizzler (~> 7.0)
+ - GoogleUtilities/Network (~> 7.0)
+ - "GoogleUtilities/NSData+zlib (~> 7.0)"
+ - nanopb (~> 2.30908.0)
+ - FirebaseAnalytics/Base (7.11.0):
+ - FirebaseCore (~> 7.0)
+ - FirebaseInstallations (~> 7.0)
+ - GoogleUtilities/AppDelegateSwizzler (~> 7.0)
+ - GoogleUtilities/MethodSwizzler (~> 7.0)
+ - GoogleUtilities/Network (~> 7.0)
+ - "GoogleUtilities/NSData+zlib (~> 7.0)"
+ - nanopb (~> 2.30908.0)
+ - FirebaseAuth (7.11.0):
- FirebaseCore (~> 7.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.0)
- GoogleUtilities/Environment (~> 7.0)
- GTMSessionFetcher/Core (~> 1.4)
- - FirebaseCore (7.3.0):
- - FirebaseCoreDiagnostics (~> 7.0)
+ - FirebaseCore (7.11.0):
+ - FirebaseCoreDiagnostics (~> 7.4)
- GoogleUtilities/Environment (~> 7.0)
- GoogleUtilities/Logger (~> 7.0)
- - FirebaseCoreDiagnostics (7.3.0):
- - GoogleDataTransport (~> 8.0)
+ - FirebaseCoreDiagnostics (7.11.0):
+ - GoogleDataTransport (~> 8.4)
- GoogleUtilities/Environment (~> 7.0)
- GoogleUtilities/Logger (~> 7.0)
- - nanopb (~> 2.30906.0)
- - FirebaseInstallations (7.9.0):
+ - nanopb (~> 2.30908.0)
+ - FirebaseInstallations (7.11.0):
- FirebaseCore (~> 7.0)
- GoogleUtilities/Environment (~> 7.0)
- GoogleUtilities/UserDefaults (~> 7.0)
- PromisesObjC (~> 1.2)
- - FirebaseInstanceID (7.9.0):
+ - FirebaseInstanceID (7.11.0):
- FirebaseCore (~> 7.0)
- FirebaseInstallations (~> 7.0)
- GoogleUtilities/Environment (~> 7.0)
- GoogleUtilities/UserDefaults (~> 7.0)
- - FirebaseMessaging (7.3.0):
+ - FirebaseMessaging (7.11.0):
- FirebaseCore (~> 7.0)
+ - FirebaseInstallations (~> 7.0)
- FirebaseInstanceID (~> 7.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.0)
- GoogleUtilities/Environment (~> 7.0)
- GoogleUtilities/Reachability (~> 7.0)
- GoogleUtilities/UserDefaults (~> 7.0)
+ - FirebaseRemoteConfig (7.11.0):
+ - FirebaseABTesting (~> 7.0)
+ - FirebaseCore (~> 7.0)
+ - FirebaseInstallations (~> 7.0)
+ - GoogleUtilities/Environment (~> 7.0)
+ - "GoogleUtilities/NSData+zlib (~> 7.0)"
- flurry (0.0.4):
- Flurry-iOS-SDK/FlurrySDK
- Flutter
@@ -110,36 +144,38 @@ PODS:
- google_sign_in (0.0.1):
- Flutter
- GoogleSignIn (~> 5.0)
- - GoogleAppMeasurement (7.3.0):
+ - GoogleAppMeasurement/AdIdSupport (7.11.0):
- GoogleUtilities/AppDelegateSwizzler (~> 7.0)
- GoogleUtilities/MethodSwizzler (~> 7.0)
- GoogleUtilities/Network (~> 7.0)
- "GoogleUtilities/NSData+zlib (~> 7.0)"
- - nanopb (~> 2.30906.0)
- - GoogleDataTransport (8.1.0):
- - nanopb (~> 2.30906.0)
+ - nanopb (~> 2.30908.0)
+ - GoogleDataTransport (8.4.0):
+ - GoogleUtilities/Environment (~> 7.2)
+ - nanopb (~> 2.30908.0)
+ - PromisesObjC (~> 1.2)
- GoogleSignIn (5.0.2):
- AppAuth (~> 1.2)
- GTMAppAuth (~> 1.0)
- GTMSessionFetcher/Core (~> 1.1)
- - GoogleUtilities/AppDelegateSwizzler (7.3.1):
+ - GoogleUtilities/AppDelegateSwizzler (7.4.0):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- - GoogleUtilities/Environment (7.3.1):
+ - GoogleUtilities/Environment (7.4.0):
- PromisesObjC (~> 1.2)
- - GoogleUtilities/Logger (7.3.1):
+ - GoogleUtilities/Logger (7.4.0):
- GoogleUtilities/Environment
- - GoogleUtilities/MethodSwizzler (7.3.1):
+ - GoogleUtilities/MethodSwizzler (7.4.0):
- GoogleUtilities/Logger
- - GoogleUtilities/Network (7.3.1):
+ - GoogleUtilities/Network (7.4.0):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Reachability
- - "GoogleUtilities/NSData+zlib (7.3.1)"
- - GoogleUtilities/Reachability (7.3.1):
+ - "GoogleUtilities/NSData+zlib (7.4.0)"
+ - GoogleUtilities/Reachability (7.4.0):
- GoogleUtilities/Logger
- - GoogleUtilities/UserDefaults (7.3.1):
+ - GoogleUtilities/UserDefaults (7.4.0):
- GoogleUtilities/Logger
- GTMAppAuth (1.1.0):
- AppAuth/Core (~> 1.4)
@@ -151,11 +187,11 @@ PODS:
- GTMSessionFetcher/Core (= 1.5.0)
- modal_progress_hud_nsn (0.0.1):
- Flutter
- - nanopb (2.30906.0):
- - nanopb/decode (= 2.30906.0)
- - nanopb/encode (= 2.30906.0)
- - nanopb/decode (2.30906.0)
- - nanopb/encode (2.30906.0)
+ - nanopb (2.30908.0):
+ - nanopb/decode (= 2.30908.0)
+ - nanopb/encode (= 2.30908.0)
+ - nanopb/decode (2.30908.0)
+ - nanopb/encode (2.30908.0)
- package_info (0.0.1):
- Flutter
- package_info_plus (0.4.5):
@@ -197,6 +233,7 @@ DEPENDENCIES:
- firebase_auth (from `.symlinks/plugins/firebase_auth/ios`)
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
+ - firebase_remote_config (from `.symlinks/plugins/firebase_remote_config/ios`)
- flurry (from `.symlinks/plugins/flurry/ios`)
- Flutter (from `Flutter`)
- flutter_app_badger (from `.symlinks/plugins/flutter_app_badger/ios`)
@@ -223,6 +260,7 @@ SPEC REPOS:
- FBSDKCoreKit
- FBSDKLoginKit
- Firebase
+ - FirebaseABTesting
- FirebaseAnalytics
- FirebaseAuth
- FirebaseCore
@@ -230,6 +268,7 @@ SPEC REPOS:
- FirebaseInstallations
- FirebaseInstanceID
- FirebaseMessaging
+ - FirebaseRemoteConfig
- Flurry-iOS-SDK
- FMDB
- GoogleAppMeasurement
@@ -259,6 +298,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/firebase_core/ios"
firebase_messaging:
:path: ".symlinks/plugins/firebase_messaging/ios"
+ firebase_remote_config:
+ :path: ".symlinks/plugins/firebase_remote_config/ios"
flurry:
:path: ".symlinks/plugins/flurry/ios"
Flutter:
@@ -304,18 +345,21 @@ SPEC CHECKSUMS:
devicelocale: b22617f40038496deffba44747101255cee005b0
FBSDKCoreKit: a00fe2efd780c195a5e09201bf51c56106245b40
FBSDKLoginKit: d98498c598ec09de657385a9349a1f21119b7f86
- Firebase: 26223c695fe322633274198cb19dca8cb7e54416
- firebase_analytics: 4c032e04324c47ee6dd7a28bfff831e0ac0d09b6
- firebase_auth: c2c27e1081671b02f90981e70dad54722198491f
- firebase_core: b5d81dfd4fb2d6f700e67de34d9a633ae325c4e9
- firebase_messaging: 7547c99f31466371f9cfcb733d5a1bf32a819872
- FirebaseAnalytics: 2580c2d62535ae7b644143d48941fcc239ea897a
- FirebaseAuth: c224a0cf1afa0949bd5c7bfcf154b4f5ce8ddef2
- FirebaseCore: 4d3c72622ce0e2106aaa07bb4b2935ba2c370972
- FirebaseCoreDiagnostics: d50e11039e5984d92c8a512be2395f13df747350
- FirebaseInstallations: 5e777e6640fa060405cc7632447b6c5ca5af4742
- FirebaseInstanceID: 53140c03b9f6136f890d7901399f85a4c90ab2d0
- FirebaseMessaging: 68d1bcb14880189558a8ae57167abe0b7e417232
+ Firebase: c121feb35e4126c0b355e3313fa9b487d47319fd
+ firebase_analytics: 620e8cc1705feb6b9c40b6127bea9b39e03e3970
+ firebase_auth: e7065954aa2a7c8ef1a8502fba3009bcdd8fc91a
+ firebase_core: 84dcd80ac6d29c3d1039071b7306ee99688eb9c7
+ firebase_messaging: 7aecb08eada5e5cde85b10875141706a8d18b818
+ firebase_remote_config: f855065886b7d6ccc38144c9a3cecbdc7887f33e
+ FirebaseABTesting: e66f1f80747792630d9b292966de206d5df9853b
+ FirebaseAnalytics: cd3bd84d722a24a8923918af8af8e5236f615d77
+ FirebaseAuth: 5fe4585c2ed847319f0ea68bd1d82c77e49ff9a0
+ FirebaseCore: 907447d8917a4d3eb0cce2829c5a0ad21d90b432
+ FirebaseCoreDiagnostics: 68ad972f99206cef818230f3f3179d52ccfb7f8c
+ FirebaseInstallations: a58d4f72ec5861840b84df489f2668d970df558a
+ FirebaseInstanceID: ad5135045a498d7775903efd39762d2cdfa1be27
+ FirebaseMessaging: 163435fb6db065e3b6228f1e577b10ed2cc506d2
+ FirebaseRemoteConfig: 0ea30de5fb0231df8c1bdcdf3b6c23bdc5066131
flurry: 15b01f664ab1367c62b50291541ea7f78ca85aad
Flurry-iOS-SDK: 6636d30c30f12010e7c7c71d84b443416a168efc
Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
@@ -326,14 +370,14 @@ SPEC CHECKSUMS:
flutter_uxcam: 87dd981feb200bc81a2f062edb5ca2d16dae595a
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
google_sign_in: 6bd214b9c154f881422f5fe27b66aaa7bbd580cc
- GoogleAppMeasurement: 8d3c0aeede16ab7764144b5a4ca8e1d4323841b7
- GoogleDataTransport: 116c84c4bdeb76be2a7a46de51244368f9794eab
+ GoogleAppMeasurement: fd19169c3034975cb934e865e5667bfdce59df7f
+ GoogleDataTransport: cd9db2180fcecd8da1b561aea31e3e56cf834aa7
GoogleSignIn: 7137d297ddc022a7e0aa4619c86d72c909fa7213
- GoogleUtilities: e1d9ed4e544fc32a93e00e721400cbc3f377200d
+ GoogleUtilities: 284cddc7fffc14ae1907efb6f78ab95c1fccaedc
GTMAppAuth: 197a8dabfea5d665224aa00d17f164fc2248dab9
GTMSessionFetcher: b3503b20a988c4e20cc189aa798fd18220133f52
modal_progress_hud_nsn: f6fb744cd060653d66ed8f325360ef3650eb2fde
- nanopb: 1bf24dd71191072e120b83dd02d08f3da0d65e53
+ nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 7116abd..bb311a3 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -388,7 +388,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
- CURRENT_PROJECT_VERSION = 1;
+ CURRENT_PROJECT_VERSION = 4;
DEVELOPMENT_TEAM = SFJJBDCU6Z;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -531,7 +531,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
- CURRENT_PROJECT_VERSION = 1;
+ CURRENT_PROJECT_VERSION = 4;
DEVELOPMENT_TEAM = SFJJBDCU6Z;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -566,7 +566,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
- CURRENT_PROJECT_VERSION = 1;
+ CURRENT_PROJECT_VERSION = 4;
DEVELOPMENT_TEAM = SFJJBDCU6Z;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 86c6d65..51bcb99 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -44,7 +44,7 @@
fbshareextension
LSMinimumSystemVersion
- 12.0
+ 11.0
LSRequiresIPhoneOS
NSAppTransportSecurity
diff --git a/lib/bloc/sales/sales_bloc.dart b/lib/bloc/sales/sales_bloc.dart
index acf7a07..a20ba25 100644
--- a/lib/bloc/sales/sales_bloc.dart
+++ b/lib/bloc/sales/sales_bloc.dart
@@ -6,6 +6,7 @@ import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/product.dart';
import 'package:aitrainer_app/model/product_test.dart';
import 'package:aitrainer_app/model/purchase.dart';
+import 'package:aitrainer_app/repository/description_repository.dart';
import 'package:aitrainer_app/service/logging.dart';
import 'package:aitrainer_app/service/purchase_service.dart';
import 'package:aitrainer_app/util/enums.dart';
@@ -13,6 +14,7 @@ import 'package:aitrainer_app/util/purchases.dart';
import 'package:aitrainer_app/util/track.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
+import 'package:firebase_remote_config/firebase_remote_config.dart';
import 'package:purchases_flutter/offering_wrapper.dart';
part 'sales_event.dart';
@@ -22,8 +24,29 @@ class SalesBloc extends Bloc with Logging {
List? tests = [];
List product2Display = [];
int productSet = -1;
+ final DescriptionRepository descriptionRepository = DescriptionRepository();
SalesBloc() : super(SalesInitial());
+ String? salesText;
+
+ String salesButtonText = "Workout Test Monthly
localizedPrice
cancel any time
";
+ Product? offeredProduct;
+
+ Product? getProductByName(String name) {
+ Product? product;
+ if (product2Display.isNotEmpty) {
+ product2Display.forEach((element) {
+ if (element.type == name) {
+ product = element;
+ salesButtonText = salesButtonText.replaceFirst(RegExp(r'localizedPrice'), product!.localizedPrice!);
+ print("Localized Price ${product!.localizedPrice!} - Text: $salesButtonText");
+ }
+ });
+ }
+
+ return product;
+ }
+
@override
Stream mapEventToState(
SalesEvent event,
@@ -32,9 +55,30 @@ class SalesBloc extends Bloc with Logging {
if (event is SalesLoad) {
yield SalesLoading();
log("Load Sales");
- Track().track(TrackingEvent.sales_page);
+ if (Cache().userLoggedIn == null) {
+ throw Exception("Please log in");
+ }
+
+ String descriptionName = "sales_page_text";
+ RemoteConfig? remoteConfig = Cache().remoteConfig;
+ if (remoteConfig != null) {
+ remoteConfig.fetchAndActivate();
+ Map config = remoteConfig.getAll();
+ RemoteConfigValue? value = config['sales_page_text_a'];
+ if (value != null) {
+ log("RemoteConfig sales_page_text value: ${value.asString()}");
+ if (value.asString() == "1") {
+ descriptionName = "sales_page_text_a";
+ }
+ }
+ }
await RevenueCatPurchases().getOfferings();
this.getProductSet();
+ salesText = descriptionRepository.getDescriptionByName(descriptionName);
+ log(salesText!);
+ salesButtonText = descriptionRepository.getDescriptionByName("sales_button_monthly");
+ offeredProduct = getProductByName("wt_sub_2_3");
+ Track().track(TrackingEvent.sales_page);
yield SalesReady();
} else if (event is SalesPurchase) {
if (Cache().hasPurchased) {
@@ -60,6 +104,22 @@ class SalesBloc extends Bloc with Logging {
} else {
yield SalesError(message: "No selected product");
}
+ } else if (event is SalesChangeSubscription) {
+ yield SalesLoading();
+ print("offered product .. $offeredProduct");
+ if (offeredProduct != null) {
+ if (offeredProduct!.type == "wt_sub_2_3") {
+ print("go yearly");
+ salesButtonText = descriptionRepository.getDescriptionByName("sales_button_yearly");
+ offeredProduct = getProductByName("wt_sub_2_1");
+ } else {
+ print("go monthly");
+ salesButtonText = descriptionRepository.getDescriptionByName("sales_button_monthly");
+ offeredProduct = getProductByName("wt_sub_2_3");
+ }
+ }
+
+ yield SalesReady();
}
} on Exception catch (ex) {
yield SalesError(message: ex.toString());
@@ -76,7 +136,7 @@ class SalesBloc extends Bloc with Logging {
return prod;
}
- String getLocalizedPrice(String productId) {
+ String getLocalizedPrice(String productId, Product product) {
String price = "";
Offering? offering = RevenueCatPurchases().offering;
if (offering != null) {
@@ -86,7 +146,7 @@ class SalesBloc extends Bloc with Logging {
price = package.product.priceString;
if (price.contains(r'HUF')) {
price = price.replaceAll(RegExp(r'HUF'), 'Ft');
- price = price.replaceAll(RegExp(r',00'), "");
+ price = price.replaceAll(RegExp(r'\,00'), "");
}
break;
}
@@ -94,18 +154,21 @@ class SalesBloc extends Bloc with Logging {
} else {
log(" !!! No Offering");
}
+ if (price.isEmpty) {
+ price = Platform.isAndroid ? product.priceAndroid.toString() : product.priceIos.toString();
+ }
return price;
}
void getProductSet() {
int productId = 0;
- this.tests = Cache().productTests;
+ //this.tests = Cache().productTests;
List? products = Cache().products;
if (products == null) {
return;
}
- if (tests != null && tests!.isEmpty) {
+ /* if (tests != null && tests!.isEmpty) {
var rand = math.Random.secure();
productSet = rand.nextInt(5) + 1;
} else {
@@ -118,9 +181,9 @@ class SalesBloc extends Bloc with Logging {
break;
}
}
- }
+ } */
- ProductTest productTest = ProductTest();
+ //ProductTest productTest = ProductTest();
productSet = 2;
log("ProductSet: " + productSet.toString());
@@ -130,7 +193,8 @@ class SalesBloc extends Bloc with Logging {
if (product.productSet == productSet) {
productId = product.productId;
final String platformProductId = Platform.isAndroid ? product.productIdAndroid! : product.productIdIos!;
- product.localizedPrice = getLocalizedPrice(platformProductId);
+ product.localizedPrice = getLocalizedPrice(platformProductId, product);
+ log("product with localized price: $product");
product2Display.add(product);
}
}
@@ -139,9 +203,9 @@ class SalesBloc extends Bloc with Logging {
return a.sort < b.sort ? -1 : 1;
});
- productTest.productId = productId;
- productTest.customerId = Cache().userLoggedIn!.customerId!;
- productTest.dateView = DateTime.now();
+ //productTest.productId = productId;
+ //productTest.customerId = Cache().userLoggedIn!.customerId!;
+ //productTest.dateView = DateTime.now();
//ProductTestApi().saveProductTest(productTest);
//Cache().productTests.add(productTest);
}
diff --git a/lib/bloc/sales/sales_event.dart b/lib/bloc/sales/sales_event.dart
index af62439..8f400e1 100644
--- a/lib/bloc/sales/sales_event.dart
+++ b/lib/bloc/sales/sales_event.dart
@@ -15,3 +15,7 @@ class SalesPurchase extends SalesEvent {
final int productId;
const SalesPurchase({required this.productId});
}
+
+class SalesChangeSubscription extends SalesEvent {
+ const SalesChangeSubscription();
+}
diff --git a/lib/bloc/session/session_bloc.dart b/lib/bloc/session/session_bloc.dart
index d76dee4..b2b940c 100644
--- a/lib/bloc/session/session_bloc.dart
+++ b/lib/bloc/session/session_bloc.dart
@@ -1,6 +1,7 @@
import 'dart:async';
import 'package:aitrainer_app/bloc/settings/settings_bloc.dart';
+import 'package:aitrainer_app/service/firebase_api.dart';
import 'package:aitrainer_app/util/app_language.dart';
import 'package:aitrainer_app/service/logging.dart';
import 'package:aitrainer_app/util/session.dart';
@@ -26,6 +27,7 @@ class SessionBloc extends Bloc with Logging {
// ignore: close_sinks
SettingsBloc settingsBloc = event.settingsBloc;
await session.fetchSessionAndNavigate();
+ FirebaseApi().setupRemoteConfig();
String lang = AppLanguage().appLocal.languageCode;
log("Change lang to $lang");
settingsBloc.add(SettingsChangeLanguage(language: lang));
diff --git a/lib/bloc/tutorial/tutorial_bloc.dart b/lib/bloc/tutorial/tutorial_bloc.dart
index f7bc352..9d5ec66 100644
--- a/lib/bloc/tutorial/tutorial_bloc.dart
+++ b/lib/bloc/tutorial/tutorial_bloc.dart
@@ -12,6 +12,7 @@ part 'tutorial_state.dart';
class TutorialBloc extends Bloc with Logging {
late String tutorialName;
+ final double mediaHeightBase = 390;
bool isActive = false;
bool canActivate = false;
@@ -46,6 +47,7 @@ class TutorialBloc extends Bloc with Logging {
setNextStepData(step);
isActive = true;
+ canActivate = true;
}
});
}
@@ -58,8 +60,9 @@ class TutorialBloc extends Bloc with Logging {
}
if (tutorial != null && tutorial!.steps != null) {
actualText = tutorial!.steps![step].tutorialTextTranslation;
- print("Step: $step, text: $actualText");
+
this.actualCheck = tutorial!.steps![step].checkText;
+ print("Step: $step, text: $actualCheck");
this.checks = [];
if (this.actualCheck != null) {
@@ -78,27 +81,31 @@ class TutorialBloc extends Bloc with Logging {
calculateHeight();
}
- /* else {
- this.add(TutorialFinished());
- } */
}
- bool activateTutorial() {
- if (!canActivate) {
- print("Tutorial canActivate false");
- return false;
- }
+ bool isTutorialDone() {
ActivityDone? activityDone = ActivityDone.tutorialBasic.searchByString(tutorialName);
if (activityDone == null) {
- return false;
+ return true;
}
bool? isActivityDone = Cache().activitiesDone[activityDone.toStr()];
- log("isActivityDone? $isActivityDone");
+
+ log("$tutorialName isActivityDone? $isActivityDone");
if (isActivityDone == null || isActivityDone == true) {
+ return true;
+ }
+ canActivate = true;
+ return false;
+ }
+
+ bool activateTutorial() {
+ if (isTutorialDone()) {
+ isActive = false;
+ canActivate = false;
return false;
}
- log("Running tutorial $activityDone");
+
init();
return true;
}
@@ -135,20 +142,9 @@ class TutorialBloc extends Bloc with Logging {
if (action == null) {
return step + 1;
}
- /* bool found = false;
- if (tutorial != null && tutorial!.steps != null) {
- for (var nextStep in tutorial!.steps!) {
- print("step $step parent: ${nextStep.action!.parent}");
- if (step + 1 == nextStep.step) {
- next = nextStep.step!;
- found = true;
- break;
- }
- }
- } */
step++;
next = step;
- print("Next step:! $next");
+ print("Next step:! $step");
if (step >= tutorial!.steps!.length) {
next = -1;
this.add(TutorialFinished());
@@ -172,6 +168,7 @@ class TutorialBloc extends Bloc with Logging {
menuBloc!.add(MenuCreate());
}
} else if (event is TutorialNext) {
+ print("Tutorial Next: ${event.text}");
if (tutorial != null) {
yield TutorialLoading();
@@ -195,7 +192,6 @@ class TutorialBloc extends Bloc with Logging {
yield TutorialReady();
} else if (event is TutorialStart) {
yield TutorialLoading();
- isActive = true;
canActivate = true;
step = 0;
yield TutorialReady();
diff --git a/lib/library/button_animations.dart b/lib/library/button_animations.dart
new file mode 100644
index 0000000..01e7e6f
--- /dev/null
+++ b/lib/library/button_animations.dart
@@ -0,0 +1,304 @@
+import 'package:flutter/material.dart';
+
+enum PredefinedThemes {
+ success,
+ successOutline,
+ danger,
+ dangerOutline,
+ warning,
+ warningOutline,
+ info,
+ infoOutline,
+ primary,
+ primaryOutline,
+ secondary,
+ secondaryOutline,
+ dark,
+ darkOutline,
+ light,
+}
+
+List definedColors = [
+ // success
+ {"color": Color(0xFF5CB85C), "borderColor": Colors.black, "shadowColor": Colors.black, "blurColor": Colors.black},
+ // successOutline
+ {"color": Color(0xFFFAFAFA), "borderColor": Color(0xFF5CB85C), "shadowColor": Color(0xFF5CB85C), "blurColor": Color(0xFF5CB85C)},
+ // danger
+ {"color": Color(0xFFD9534F), "borderColor": Colors.black, "shadowColor": Colors.black, "blurColor": Colors.black},
+ // dangerOutline
+ {"color": Color(0xFFFAFAFA), "borderColor": Color(0xFFD9534F), "shadowColor": Color(0xFFD9534F), "blurColor": Color(0xFFD9534F)},
+ // warning
+ {"color": Color(0xFFF0AD4E), "borderColor": Colors.black, "shadowColor": Colors.black, "blurColor": Colors.black},
+ // warningOutline
+ {"color": Color(0xFFFAFAFA), "borderColor": Color(0xFFF0AD4E), "shadowColor": Color(0xFFF0AD4E), "blurColor": Color(0xFFF0AD4E)},
+ // info
+ {"color": Color(0xFF5BC0DE), "borderColor": Colors.black, "shadowColor": Colors.black, "blurColor": Colors.black},
+ // infoOutline
+ {"color": Color(0xFFFAFAFA), "borderColor": Color(0xFF5BC0DE), "shadowColor": Color(0xFF5BC0DE), "blurColor": Color(0xFF5BC0DE)},
+ // primary
+ {"color": Color(0xFF0275D8), "borderColor": Colors.black, "shadowColor": Colors.black, "blurColor": Colors.black},
+ // primaryOutline
+ {"color": Color(0xFFFAFAFA), "borderColor": Color(0xFF0275D8), "shadowColor": Color(0xFF0275D8), "blurColor": Color(0xFF0275D8)},
+ // secondary
+ {"color": Color(0xFF6B5B95), "borderColor": Colors.black, "shadowColor": Colors.black, "blurColor": Colors.black},
+ // secondaryOutline
+ {"color": Color(0xFFFAFAFA), "borderColor": Color(0xFF6B5B95), "shadowColor": Color(0xFF6B5B95), "blurColor": Color(0xFF6B5B95)},
+ // dark
+ {"color": Color(0xFF292B2C), "borderColor": Colors.black, "shadowColor": Colors.black, "blurColor": Colors.black},
+ // darkOutline
+ {"color": Color(0xFFFAFAFA), "borderColor": Color(0xFF292B2C), "shadowColor": Color(0xFF292B2C), "blurColor": Color(0xFF292B2C)},
+ {"color": Color(0xFFF7F7F7), "borderColor": Colors.black, "shadowColor": Colors.black, "blurColor": Colors.black},
+ {"color": Color(0xFFBFBFC4), "borderColor": Colors.black, "shadowColor": Colors.black, "blurColor": Colors.black}
+];
+
+class AnimatedButton extends StatefulWidget {
+ // * @param onTap The function that is called whenever the widget is tapped
+ final GestureTapCallback onTap;
+ final Widget child;
+ // * @param type There are 16 predefined themes from which you can choose from if you dont want to customize the widget yourself
+ final PredefinedThemes type;
+ // * @param animationCurve The curve that the animation will follow
+ final Curve animationCurve;
+ // * @param enabled To check whether the button is enabbled or not
+ final bool enabled;
+ // * @param isMultiColor To check whether the button has multiple color gradient or not
+ final bool isMultiColor;
+ // * @param isOutline To check whether the button has a outline or not
+ final bool isOutline;
+ // * @param darkShadow To check whether the button has dark or light shadow
+ final bool darkShadow;
+
+ // * @param duration The time that the animation takes in milliseconds
+ final int duration;
+
+ // * @param height The height of the widget
+ final double height;
+ // * @param width The width of the widget
+ final double width;
+ // * @param blurRadius The radius of the blur effect of the widget
+ final double blurRadius;
+ // * @param borderRadius The radius of the borders of the widget
+ final double borderRadius;
+ // * @param shadowHeightBottom The height of the shadow and the animation of the widget from the bottom of the child widget
+ final double shadowHeightBottom;
+ // * @param shadowHeightLeft The height of the shadow and the animation of the widget from the left of the child widget
+ final double shadowHeightLeft;
+ // * @param borderWidth The width of the border of the widget
+ final double borderWidth;
+
+ // * @param borderColor The color of the border of the widget(if type is not null, this will not work, is Outline should be true for this to work)
+ final Color borderColor;
+ // * @param blurColor The color of the blur of the widget(if type is not null, this will not work)
+ final Color blurColor;
+ // * @param color The color of the widget(if type is not null, this will not work)
+ final Color color;
+ // * @param shadowColor The color of the shadow of the widget(if type is not null, this will not work)
+ final Color? shadowColor;
+
+ // * @param colors The list of colors for the gradient for the background of the widget(isMulticolor should be true for this to work)
+ final List? colors;
+
+ AnimatedButton({
+ Key? key,
+ required this.onTap,
+ required this.child,
+ this.enabled = true,
+ this.type = PredefinedThemes.primary,
+ this.color = Colors.blue,
+ this.height = 64,
+ this.colors,
+ this.isMultiColor = false,
+ this.darkShadow = true,
+ this.width = 200,
+ this.duration = 70,
+ this.blurRadius = 0,
+ this.borderRadius = 12,
+ this.animationCurve = Curves.easeIn,
+ this.shadowHeightBottom = 4,
+ this.shadowHeightLeft = 0,
+ this.isOutline = false,
+ this.borderColor = Colors.black,
+ this.borderWidth = 1,
+ this.blurColor = Colors.black,
+ this.shadowColor,
+ }) : assert(child != null),
+ super(key: key);
+
+ @override
+ _AnimatedButtonState createState() => _AnimatedButtonState(
+ type: this.type,
+ color: this.color,
+ blurColor: this.blurColor,
+ borderColor: this.borderColor,
+ );
+}
+
+class _AnimatedButtonState extends State {
+ late double btnPositionBottom;
+ late double btnPositionTop;
+ late double btnPositionLeft;
+ late double btnPositionRight;
+ PredefinedThemes? type;
+ Color? color;
+ Color? shadowColor;
+ Color? borderColor;
+ Color? blurColor;
+ _AnimatedButtonState({
+ this.type,
+ this.color,
+ this.shadowColor,
+ this.borderColor,
+ this.blurColor,
+ });
+
+ @override
+ void initState() {
+ super.initState();
+ // check if there is a PredefinedThemes type used in the widget
+ // if yes, over-ride all the colors of the widget
+ if (type != null) {
+ int index = type!.index;
+ setState(() {
+ color = definedColors[index]["color"];
+ shadowColor = definedColors[index]["shadowColor"];
+ blurColor = definedColors[index]["blurColor"];
+ borderColor = definedColors[index]["borderColor"];
+ });
+ } else {
+ setState(() {
+ color = widget.color;
+ shadowColor = widget.shadowColor;
+ blurColor = widget.blurColor;
+ borderColor = widget.borderColor;
+ });
+ }
+ // initialize the top widget with the defined bottom and left height
+ setState(() {
+ btnPositionBottom = widget.shadowHeightBottom;
+ btnPositionLeft = widget.shadowHeightLeft;
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ final double height = widget.height - btnPositionBottom;
+
+ return GestureDetector(
+ child: Center(
+ child: Container(
+ width: widget.width + btnPositionLeft,
+ height: height + btnPositionBottom,
+ child: Stack(
+ children: [
+ Positioned(
+ bottom: 0,
+ child: Container(
+ height: height,
+ width: widget.width,
+ decoration: BoxDecoration(
+ gradient: widget.isMultiColor
+ ? LinearGradient(
+ colors: shadow(widget.colors!, widget.darkShadow),
+ )
+ : null,
+ color: (widget.shadowColor != null)
+ ? widget.shadowColor
+ : shadow((widget.isOutline) ? [color!] : [borderColor!], widget.darkShadow),
+ borderRadius: BorderRadius.all(
+ Radius.circular(
+ widget.borderRadius,
+ ),
+ ),
+ border: widget.isOutline
+ ? Border.all(
+ color: borderColor!,
+ width: widget.borderWidth,
+ )
+ : null,
+ boxShadow: [
+ BoxShadow(
+ color: blurColor!,
+ blurRadius: widget.blurRadius,
+ offset: Offset(0.0, 0.0),
+ ),
+ ],
+ ),
+ ),
+ ),
+ AnimatedPositioned(
+ curve: widget.animationCurve,
+ duration: Duration(milliseconds: widget.duration),
+ bottom: btnPositionBottom,
+ left: btnPositionLeft,
+ child: Container(
+ height: height,
+ width: widget.width,
+ decoration: BoxDecoration(
+ gradient: widget.isMultiColor
+ ? LinearGradient(
+ colors: widget.colors!,
+ )
+ : null,
+ color: color,
+ borderRadius: BorderRadius.all(
+ Radius.circular(
+ widget.borderRadius,
+ ),
+ ),
+ border: widget.isOutline
+ ? Border.all(
+ color: borderColor!,
+ width: widget.borderWidth,
+ )
+ : null,
+ ),
+ child: Center(
+ child: widget.child,
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ onTapDown: widget.enabled ? _tapDown : null,
+ onTapUp: widget.enabled ? _tapUp : null,
+ onTapCancel: widget.enabled ? _unTap : null,
+ );
+ }
+
+ void _tapDown(_) {
+ // when the widget is pressed make both the heights, bottom and left to zero
+ setState(() {
+ btnPositionBottom = 0;
+ btnPositionLeft = 0;
+ });
+ }
+
+ // when the widget is released after being pressed, it returns to the given heights, bottom and left
+ void _tapUp(_) => _unTap();
+
+ void _unTap() {
+ setState(() {
+ btnPositionLeft = widget.shadowHeightLeft;
+
+ btnPositionBottom = widget.shadowHeightBottom;
+ });
+ widget.onTap();
+ }
+
+ // returns a list of color shades according to the params
+ // * @param colors list of colors
+ // * @param darkshadow whether to return a darker shadow or lighter shadow
+ shadow(List colors, bool darkShadow) {
+ List w = [];
+
+ colors.forEach((color) {
+ double amount = darkShadow ? 0.22 : 0.1;
+ final hsl = HSLColor.fromColor(color);
+ final hslDark = hsl.withLightness((hsl.lightness - amount).clamp(0.0, 1.0));
+ w.add(hslDark.toColor());
+ });
+ return (w.length == 1) ? w[0] : w;
+ }
+}
diff --git a/lib/model/cache.dart b/lib/model/cache.dart
index c9e7661..cfb077e 100644
--- a/lib/model/cache.dart
+++ b/lib/model/cache.dart
@@ -2,6 +2,7 @@ import 'dart:collection';
import 'dart:convert';
import 'package:aitrainer_app/model/customer.dart';
import 'package:aitrainer_app/model/customer_activity.dart';
+import 'package:aitrainer_app/model/description.dart';
import 'package:aitrainer_app/model/evaluation.dart';
import 'package:aitrainer_app/model/exercise_plan.dart';
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
@@ -25,6 +26,7 @@ import 'package:aitrainer_app/main.dart';
import 'package:aitrainer_app/util/enums.dart';
import 'package:aitrainer_app/util/env.dart';
import 'package:aitrainer_app/util/track.dart';
+import 'package:firebase_remote_config/firebase_remote_config.dart';
import 'package:flurry/flurry.dart';
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
import 'package:flutter_uxcam/flutter_uxcam.dart';
@@ -58,7 +60,14 @@ enum SharePrefsChange {
- is_logged_in
*/
-enum ActivityDone { tutorialBasic, tutorialDevelopment, isExerciseLogSeen, isMuscleDevelopmentSeen }
+enum ActivityDone {
+ tutorialBasic,
+ tutorialBasicChestPress,
+ tutorialBasicLegPress,
+ tutorialDevelopment,
+ isExerciseLogSeen,
+ isMuscleDevelopmentSeen
+}
extension ActivityDoneExt on ActivityDone {
String toStr() => this.toString().split(".").last;
@@ -131,6 +140,7 @@ class Cache with Logging {
List? _customerDevices;
List? _customerActivities;
List? _tutorials;
+ List? _descriptions;
LinkedHashMap _myExercisesPlanDetails = LinkedHashMap();
@@ -141,6 +151,8 @@ class Cache with Logging {
List? _exercisesTrainee;
ExercisePlan? _traineeExercisePlan;
+ RemoteConfig? remoteConfig;
+
LinkedHashMap _badges = LinkedHashMap();
List? deviceLanguages;
@@ -664,4 +676,10 @@ class Cache with Logging {
List? get tutorials => this._tutorials;
setTutorials(List? value) => this._tutorials = value;
+
+ RemoteConfig? getRemoteConfig() => this.remoteConfig;
+ setRemoteConfig(RemoteConfig? remoteConfig) => this.remoteConfig = remoteConfig;
+
+ List? getDescriptions() => this._descriptions;
+ setDescriptions(List? value) => this._descriptions = value;
}
diff --git a/lib/model/description.dart b/lib/model/description.dart
new file mode 100644
index 0000000..a42a6b8
--- /dev/null
+++ b/lib/model/description.dart
@@ -0,0 +1,40 @@
+import 'package:aitrainer_app/util/app_language.dart';
+import 'dart:ui';
+
+class Description {
+ late int descriptionId;
+ late String name;
+ late String description;
+ int? version;
+ DateTime? validFrom;
+ DateTime? validTo;
+
+ String? descriptionTranslation;
+
+ Description.fromJson(Map json) {
+ this.descriptionId = json['descriptionId'];
+ this.name = json['name'];
+ this.description = json['description'];
+ this.version = json['version'];
+ this.validFrom = json['validFrom'];
+ this.validTo = json['validTo'];
+
+ if (json['translations'] != null && json['translations'].length > 0) {
+ this.descriptionTranslation =
+ AppLanguage().appLocal == Locale('hu') ? json['translations'][0]['descriptionTranslation'] : json['description'];
+ }
+ }
+
+ Map toJson() => {
+ "descriptionId": this.descriptionId,
+ "name": this.name,
+ "description": this.description,
+ "version": this.version,
+ "validFrom": this.validFrom,
+ "validTo": this.validTo,
+ "descriptionTranslation": this.descriptionTranslation
+ };
+
+ @override
+ String toString() => this.toJson().toString();
+}
diff --git a/lib/model/product.dart b/lib/model/product.dart
index 3cbbfb3..0d3744e 100644
--- a/lib/model/product.dart
+++ b/lib/model/product.dart
@@ -46,6 +46,7 @@ class Product {
'productIdAndroid': this.productIdAndroid,
'priceIos': this.priceIos,
'priceAndroid': this.priceAndroid,
+ 'localizedPrice': this.localizedPrice
};
return json.toString();
}
diff --git a/lib/model/tutorial.dart b/lib/model/tutorial.dart
index 2a2204e..9136131 100644
--- a/lib/model/tutorial.dart
+++ b/lib/model/tutorial.dart
@@ -14,6 +14,19 @@ class Tutorial {
if (json['steps'] != null && json['steps'].length > 0) {
steps = json['steps'].map((step) => TutorialStep.fromJson(step)).toList();
+ if (steps != null) {
+ steps!.sort((a, b) {
+ if (a.step == null || b.step == null) {
+ return -1;
+ } else {
+ if (a.step! <= b.step!) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+ });
+ }
}
}
diff --git a/lib/model/tutorial_step.dart b/lib/model/tutorial_step.dart
index 7ec14f5..fa49b29 100644
--- a/lib/model/tutorial_step.dart
+++ b/lib/model/tutorial_step.dart
@@ -71,7 +71,6 @@ class TutorialStep {
this.condition = json['condition'];
if (this.condition != null) {
this.condition = condition!.replaceAll(r'\\', "replace");
- print("Json condition $condition");
this.action = TutorialStepAction.fromJson(jsonDecode(condition!));
}
diff --git a/lib/push_notifications.dart b/lib/push_notifications.dart
index cdf31b6..f4d7797 100644
--- a/lib/push_notifications.dart
+++ b/lib/push_notifications.dart
@@ -27,5 +27,7 @@ class PushNotificationsManager with Logging {
badge: true,
sound: true,
);
+ String? token = await FirebaseMessaging.instance.getToken();
+ print("FirebaseMessaging tokne $token");
}
}
diff --git a/lib/repository/description_repository.dart b/lib/repository/description_repository.dart
new file mode 100644
index 0000000..b00b3f8
--- /dev/null
+++ b/lib/repository/description_repository.dart
@@ -0,0 +1,23 @@
+import 'package:aitrainer_app/model/cache.dart';
+import 'package:aitrainer_app/model/description.dart';
+
+class DescriptionRepository {
+ List? descriptions;
+
+ DescriptionRepository() {
+ this.descriptions = Cache().getDescriptions();
+ }
+
+ String getDescriptionByName(String name) {
+ String descriptionText = "";
+ if (descriptions != null) {
+ this.descriptions!.forEach((element) {
+ print("Desc ${element.name} - $name");
+ if (element.name == name) {
+ descriptionText = element.descriptionTranslation != null ? element.descriptionTranslation! : element.description;
+ }
+ });
+ }
+ return descriptionText;
+ }
+}
diff --git a/lib/service/firebase_api.dart b/lib/service/firebase_api.dart
index b224a3d..36a776c 100644
--- a/lib/service/firebase_api.dart
+++ b/lib/service/firebase_api.dart
@@ -3,6 +3,7 @@ import 'package:aitrainer_app/service/logging.dart' as logging;
import 'package:apple_sign_in/apple_sign_in.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
+import 'package:firebase_remote_config/firebase_remote_config.dart';
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
@@ -28,7 +29,8 @@ class FirebaseApi with logging.Logging {
Future initializeFlutterFire() async {
try {
// Wait for Firebase to initialize and set `_initialized` state to true
- await Firebase.initializeApp();
+ FirebaseApp app = await Firebase.initializeApp();
+
this.appleSignInAvailable = await AppleSignIn.isAvailable();
} catch (e) {
// Set `_error` state to true if Firebase initialization fails
@@ -286,4 +288,23 @@ class FirebaseApi with logging.Logging {
Future resetPassword(String email) async {
await FirebaseAuth.instance.sendPasswordResetEmail(email: email);
}
+
+ Future setupRemoteConfig() async {
+ initializeFlutterFire();
+ final RemoteConfig remoteConfig = RemoteConfig.instance;
+ await remoteConfig.setConfigSettings(RemoteConfigSettings(
+ fetchTimeout: const Duration(seconds: 10),
+ minimumFetchInterval: const Duration(seconds: 1),
+ ));
+ await remoteConfig.setDefaults({
+ 'sales_page_text': '0',
+ 'sales_page_bkg': 'dark',
+ 'sales_page_offer': 'monthly',
+ });
+ RemoteConfigValue(null, ValueSource.valueStatic);
+ Cache().setRemoteConfig(remoteConfig);
+
+ Map config = remoteConfig.getAll();
+ print("RemoteConfig sales_page_text Value : ${config['sales_page_text'].asString()}");
+ }
}
diff --git a/lib/service/package_service.dart b/lib/service/package_service.dart
index d08ce1a..43bbb1f 100644
--- a/lib/service/package_service.dart
+++ b/lib/service/package_service.dart
@@ -5,6 +5,7 @@ import 'package:aitrainer_app/model/customer.dart';
import 'package:aitrainer_app/model/customer_activity.dart';
import 'package:aitrainer_app/model/customer_exercise_device.dart';
import 'package:aitrainer_app/model/customer_property.dart';
+import 'package:aitrainer_app/model/description.dart';
import 'package:aitrainer_app/model/evaluation.dart';
import 'package:aitrainer_app/model/exercise.dart';
import 'package:aitrainer_app/model/exercise_device.dart';
@@ -72,8 +73,13 @@ class PackageApi {
} else if (headRecord[0] == "Tutorial") {
final Iterable json = jsonDecode(headRecord[1]);
final List tutorials = json.map((tutorial) => Tutorial.fromJson(tutorial)).toList();
- print("Tutorial: $tutorials");
+
Cache().setTutorials(tutorials);
+ } else if (headRecord[0] == "Description") {
+ final Iterable json = jsonDecode(headRecord[1]);
+ final List? descriptions = json.map((description) => Description.fromJson(description)).toList();
+ //print("Description: $descriptions");
+ Cache().setDescriptions(descriptions);
}
});
diff --git a/lib/util/session.dart b/lib/util/session.dart
index da96042..7fbc1e1 100644
--- a/lib/util/session.dart
+++ b/lib/util/session.dart
@@ -1,5 +1,6 @@
import 'dart:io';
+import 'package:aitrainer_app/service/firebase_api.dart';
import 'package:aitrainer_app/util/app_language.dart';
import 'package:aitrainer_app/util/app_localization.dart';
import 'package:aitrainer_app/service/api.dart';
@@ -7,6 +8,8 @@ import 'package:aitrainer_app/service/logging.dart';
import 'package:aitrainer_app/service/package_service.dart';
import 'package:aitrainer_app/util/purchases.dart';
import 'package:devicelocale/devicelocale.dart';
+import 'package:firebase_core/firebase_core.dart';
+import 'package:firebase_remote_config/firebase_remote_config.dart';
import 'package:flutter/services.dart';
import 'package:flutter_app_badger/flutter_app_badger.dart';
import 'package:package_info/package_info.dart';
diff --git a/lib/util/track.dart b/lib/util/track.dart
index 969058f..3bf721a 100644
--- a/lib/util/track.dart
+++ b/lib/util/track.dart
@@ -4,11 +4,13 @@ import 'package:aitrainer_app/service/logging.dart';
import 'package:aitrainer_app/service/tracking_service.dart';
import 'package:aitrainer_app/util/enums.dart';
import 'package:aitrainer_app/model/tracking.dart' as model;
+import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:flurry/flurry.dart';
import 'package:flutter_uxcam/flutter_uxcam.dart';
class Track with Logging {
static final Track _singleton = Track._internal();
+ static FirebaseAnalytics analytics = FirebaseAnalytics();
factory Track() {
return _singleton;
@@ -22,6 +24,7 @@ class Track with Logging {
// Smartlook.setGlobalEventProperty(event.toString(), eventValue, false);
FlutterUxcam.logEventWithProperties(event.enumToString(), {"value": eventValue});
model.Tracking tracking = model.Tracking();
+ analytics.logEvent(name: event.enumToString(), parameters: {"value": eventValue});
tracking.customerId = Cache().userLoggedIn == null ? 0 : Cache().userLoggedIn!.customerId!;
tracking.event = event.enumToString();
if (eventValue.isNotEmpty) {
diff --git a/lib/view/exercise_control_page.dart b/lib/view/exercise_control_page.dart
index d4d8706..2a2d9d1 100644
--- a/lib/view/exercise_control_page.dart
+++ b/lib/view/exercise_control_page.dart
@@ -2,6 +2,7 @@ import 'dart:collection';
import 'package:aitrainer_app/bloc/exercise_control/exercise_control_bloc.dart';
import 'package:aitrainer_app/bloc/timer/timer_bloc.dart';
+import 'package:aitrainer_app/bloc/tutorial/tutorial_bloc.dart';
import 'package:aitrainer_app/library/custom_icon_icons.dart';
import 'package:aitrainer_app/util/app_language.dart';
import 'package:aitrainer_app/model/cache.dart';
@@ -267,6 +268,7 @@ class _ExerciseControlPage extends State with Trans {
String title = (step + 1).toString() + "/4 " + t("Control Exercise:");
LinkedHashMap args = LinkedHashMap();
+ final TutorialBloc tutorialBloc = BlocProvider.of(context);
List listWidgets = [
Text(
@@ -332,15 +334,20 @@ class _ExerciseControlPage extends State with Trans {
primary: Colors.white,
onSurface: Colors.blueAccent,
),
- onPressed: () => {
- exerciseBloc.add(ExerciseControlSubmit(step: step)),
- if (step == 3)
- {
- Navigator.of(context).pop(),
- args['exerciseRepository'] = exerciseBloc.exerciseRepository,
- Navigator.of(context).pushNamed('evaluationPage', arguments: args)
- }
- },
+ onPressed: () {
+ if (tutorialBloc.isActive) {
+ if (!tutorialBloc.checkAction("Save")) {
+ return;
+ }
+ }
+
+ exerciseBloc.add(ExerciseControlSubmit(step: step));
+ if (step == 3) {
+ Navigator.of(context).pop();
+ args['exerciseRepository'] = exerciseBloc.exerciseRepository;
+ Navigator.of(context).pushNamed('evaluationPage', arguments: args);
+ }
+ },
child: step == exerciseBloc.step
? Stack(
alignment: Alignment.center,
diff --git a/lib/view/sales_page.dart b/lib/view/sales_page.dart
index 65c4680..d3975a0 100644
--- a/lib/view/sales_page.dart
+++ b/lib/view/sales_page.dart
@@ -1,4 +1,5 @@
import 'package:aitrainer_app/bloc/sales/sales_bloc.dart';
+import 'package:aitrainer_app/library/button_animations.dart';
import 'package:aitrainer_app/service/logging.dart';
import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/widgets/app_bar_min.dart';
@@ -6,6 +7,8 @@ import 'package:aitrainer_app/widgets/dialog_common.dart';
import 'package:aitrainer_app/widgets/sales_button.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter_html/flutter_html.dart';
+import 'package:flutter_html/style.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
@@ -22,7 +25,6 @@ class SalesPage extends StatelessWidget with Trans, Logging {
create: (context) => SalesBloc()..add(SalesLoad()),
child: BlocConsumer(listener: (context, state) {
if (state is SalesError) {
- log("Error: " + state.message);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(backgroundColor: Colors.orange, content: Text(t(state.message), style: TextStyle(color: Colors.white))));
} else if (state is SalesSuccessful) {
@@ -57,6 +59,9 @@ class SalesPage extends StatelessWidget with Trans, Logging {
}
Widget salesWidget(SalesBloc bloc) {
+ final salesText = bloc.salesText != null ? bloc.salesText! : "";
+ final String html = salesText;
+
return Container(
decoration: BoxDecoration(
image: DecorationImage(
@@ -68,55 +73,144 @@ class SalesPage extends StatelessWidget with Trans, Logging {
child: CustomScrollView(scrollDirection: Axis.vertical, slivers: [
SliverList(
delegate: SliverChildListDelegate([
- Divider(),
- Container(
- padding: EdgeInsets.only(left: 65, right: 65),
- child: Text(t("Unleash Your Development Now!"),
+ Html(
+ data: html,
+ //Optional parameters:
+ style: {
+ "p": Style(
+ color: Colors.white,
+ fontSize: FontSize(16),
+ padding: const EdgeInsets.only(left: 20, right: 8, bottom: 4),
+ ),
+ "strong": Style(
+ color: Colors.yellow[600],
+ fontSize: FontSize(16),
+ ),
+ "h3": Style(
+ color: Colors.yellow[600],
+ fontSize: FontSize(16),
+ textAlign: TextAlign.center,
+ padding: const EdgeInsets.all(12),
+ ),
+ "li": Style(
+ color: Colors.white,
+ fontSize: FontSize(14),
+ padding: const EdgeInsets.only(left: 20, bottom: 10, right: 8),
+ //before: "*",
+ display: Display.LIST_ITEM),
+ "h2": Style(
+ color: Colors.yellow[600],
+ fontWeight: FontWeight.bold,
+ fontSize: FontSize(24),
+ textAlign: TextAlign.center,
+ //padding: const EdgeInsets.all(4),
+ ),
+ "h1": Style(
+ color: Colors.yellow[400],
+ fontWeight: FontWeight.bold,
+ fontSize: FontSize.larger,
+ alignment: Alignment.center,
+ padding: const EdgeInsets.all(4),
+ ),
+ },
+ ), // final Color bgrColor = Color(0xffb4f500);
+ //final Color bgrColorEnd = Colors.blue;
+ AnimatedButton(
+ child: Html(
+ data: bloc.salesButtonText,
+ //Optional parameters:
+ style: {
+ "p": Style(
+ color: Colors.black,
+ fontSize: FontSize(16),
+ padding: const EdgeInsets.all(4),
textAlign: TextAlign.center,
- maxLines: 4,
- softWrap: true,
- style: GoogleFonts.archivoBlack(
- fontSize: 30,
- color: Colors.white,
- shadows: [
- Shadow(
- offset: Offset(5.0, 5.0),
- blurRadius: 12.0,
- color: Colors.black54,
- ),
- Shadow(
- offset: Offset(-3.0, 3.0),
- blurRadius: 12.0,
- color: Colors.black54,
- ),
- ],
- ))),
- Divider(),
- Container(
- padding: EdgeInsets.only(left: 45, right: 45),
- child: Text(t("Learn about your development, enjoy AI-driven predictions of all of your skills and bodyparts."),
- textAlign: TextAlign.left,
- maxLines: 4,
- softWrap: true,
- style: GoogleFonts.inter(
- fontSize: 16,
- color: Colors.white,
- ))),
- SizedBox(
- height: 50,
+ textShadow: [
+ Shadow(
+ offset: Offset(2.0, 2.0),
+ blurRadius: 6.0,
+ color: Colors.black54,
+ )
+ ],
+ ),
+ "li": Style(
+ color: Colors.white,
+ fontSize: FontSize(14),
+ padding: const EdgeInsets.only(left: 10, bottom: 10),
+ before: "*",
+ ),
+ "h2": Style(
+ color: Colors.black,
+ fontWeight: FontWeight.bold,
+ fontSize: FontSize.larger,
+ textAlign: TextAlign.center,
+ textShadow: [
+ Shadow(
+ offset: Offset(2.0, 2.0),
+ blurRadius: 12.0,
+ color: Colors.black54,
+ )
+ ],
+ //padding: const EdgeInsets.all(4),
+ ),
+ "h1": Style(
+ color: Colors.yellow[600],
+ fontWeight: FontWeight.bold,
+ fontSize: FontSize.xLarge,
+ alignment: Alignment.center,
+ padding: const EdgeInsets.all(4),
+ textAlign: TextAlign.center,
+ textShadow: [
+ Shadow(
+ offset: Offset(5.0, 5.0),
+ blurRadius: 12.0,
+ color: Colors.black54,
+ )
+ ],
+ ),
+ },
+ ),
+ duration: 600,
+ darkShadow: true,
+ blurRadius: 12,
+ animationCurve: Curves.easeIn,
+ height: 120,
+ width: 320,
+ onTap: () => bloc.add(SalesPurchase(productId: bloc.offeredProduct!.productId)),
+ //color: Color(0xffb4f500),
+ isMultiColor: true,
+ colors: [
+ Colors.blue,
+ Color(0xffb4f500),
+ Color(0xffb4f500),
+ ],
),
- ])),
- SliverGrid(
- delegate: SliverChildListDelegate(getButtons(bloc)),
- gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
- crossAxisCount: 3,
- mainAxisSpacing: 10.0,
- crossAxisSpacing: 10.0,
- childAspectRatio: 0.55,
+
+ getTrialDescription(),
+ //Divider(),
+ AnimatedButton(
+ child: Html(
+ data: "" + t("View other alternatives") + "
",
+ //Optional parameters:
+ style: {
+ "p": Style(
+ color: Colors.black,
+ fontSize: FontSize(14),
+ padding: const EdgeInsets.all(4),
+ textAlign: TextAlign.center,
+ ),
+ },
+ ),
+ onTap: () => bloc.add(SalesChangeSubscription()),
+ width: 320,
+ blurRadius: 6,
+ isMultiColor: true,
+ colors: [
+ Colors.white,
+ Colors.yellow[300]!,
+ ],
),
- ),
- SliverList(
- delegate: SliverChildListDelegate([
+
SizedBox(
height: 30,
),
@@ -144,6 +238,35 @@ class SalesPage extends StatelessWidget with Trans, Logging {
]));
}
+ Widget getTrialDescription() {
+ final trialText = t("Try free for 3 days!");
+ return Container(
+ padding: EdgeInsets.only(left: 55, right: 55),
+ child: Html(
+ data: "" + trialText + "
",
+ //Optional parameters:
+ style: {
+ "p": Style(
+ color: Colors.white,
+ fontSize: FontSize(13),
+ padding: const EdgeInsets.all(4),
+ textAlign: TextAlign.center,
+ textShadow: [
+ Shadow(
+ offset: Offset(2.0, 2.0),
+ blurRadius: 6.0,
+ color: Colors.black54,
+ )
+ ],
+ ),
+ "strong": Style(
+ color: Colors.yellow[600],
+ fontSize: FontSize(13),
+ ),
+ },
+ ));
+ }
+
List getButtons(SalesBloc bloc) {
List buttons = [];
diff --git a/lib/view/settings.dart b/lib/view/settings.dart
index 7518021..0189004 100644
--- a/lib/view/settings.dart
+++ b/lib/view/settings.dart
@@ -139,7 +139,7 @@ class SettingsPage extends StatelessWidget with Trans {
final TutorialBloc tutorialBloc = BlocProvider.of(context);
return ListTile(
leading: Icon(CustomIcon.question_circle),
- subtitle: Text("Activating the basic tutorial"),
+ subtitle: Text(t("Activating the basic tutorial")),
title: ToggleSwitch(
minWidth: 120.0,
minHeight: 30.0,
@@ -151,7 +151,15 @@ class SettingsPage extends StatelessWidget with Trans {
inactiveFgColor: Colors.grey[900],
labels: [t('Basic Tutorial'), t('Activate')],
onToggle: (index) {
- settingsBloc.add(SettingsActivateTutorial(activity: ActivityDone.tutorialBasic));
+ ActivityDone activity = ActivityDone.tutorialBasic;
+ if (Cache().userLoggedIn != null) {
+ if (Cache().userLoggedIn!.sex == "m") {
+ activity = ActivityDone.tutorialBasicChestPress;
+ } else {
+ activity = ActivityDone.tutorialBasicLegPress;
+ }
+ }
+ settingsBloc.add(SettingsActivateTutorial(activity: activity));
tutorialBloc.add(TutorialStart());
},
),
diff --git a/lib/view/test_set_edit.dart b/lib/view/test_set_edit.dart
index 3801f75..91185c1 100644
--- a/lib/view/test_set_edit.dart
+++ b/lib/view/test_set_edit.dart
@@ -9,6 +9,7 @@ import 'package:aitrainer_app/model/workout_menu_tree.dart';
import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/widgets/app_bar.dart';
import 'package:aitrainer_app/widgets/dialog_common.dart';
+import 'package:aitrainer_app/widgets/dialog_html.dart';
import 'package:aitrainer_app/widgets/menu_image.dart';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/cupertino.dart';
@@ -190,12 +191,9 @@ class TestSetEdit extends StatelessWidget with Trans {
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
- return DialogCommon(
+ return DialogHTML(
title: bloc.templateNameTranslation,
- descriptions: bloc.templateDescription,
- text: "OK",
- onTap: () => {Navigator.of(context).pop()},
- onCancel: () => {Navigator.of(context).pop()},
+ htmlData: bloc.templateDescription,
);
}),
child: Icon(
diff --git a/lib/widgets/menu_page_widget.dart b/lib/widgets/menu_page_widget.dart
index 813378a..8e3899e 100644
--- a/lib/widgets/menu_page_widget.dart
+++ b/lib/widgets/menu_page_widget.dart
@@ -67,17 +67,25 @@ class _MenuPageWidgetState extends State with Trans, Logging {
}
Future runDelayedEvent() async {
- print("runDelayedEvent start");
bool isFirst = false;
await Future.delayed(Duration(milliseconds: 600), () async {
- if (tutorialBloc.isActive == false) {
- print("Activate tutorial");
- tutorialBloc.canActivate = true;
- tutorialBloc.isActive = true;
- tutorialBloc.menuBloc = menuBloc;
- tutorialBloc.add(TutorialLoad());
- tutorialBloc.init();
- isFirst = true;
+ if (Cache().userLoggedIn != null) {
+ if (Cache().userLoggedIn!.sex == "m") {
+ tutorialBloc.tutorialName = ActivityDone.tutorialBasicChestPress.toStr();
+ } else {
+ tutorialBloc.tutorialName = ActivityDone.tutorialBasicLegPress.toStr();
+ }
+ }
+ if (!tutorialBloc.isTutorialDone()) {
+ if (tutorialBloc.isActive == false && tutorialBloc.canActivate) {
+ print("Activate tutorial");
+ tutorialBloc.canActivate = true;
+ tutorialBloc.isActive = true;
+ tutorialBloc.menuBloc = menuBloc;
+ tutorialBloc.add(TutorialLoad());
+ tutorialBloc.init();
+ isFirst = true;
+ }
}
});
final bool canActivate = tutorialBloc.activateTutorial();
@@ -351,6 +359,7 @@ class _MenuPageWidgetState extends State with Trans, Logging {
void menuClick(WorkoutMenuTree workoutTree, MenuBloc menuBloc) {
if (tutorialBloc.isActive) {
final String checkText = workoutTree.nameEnglish;
+ print("Click: tutorial is active $checkText");
if (!tutorialBloc.checkAction(checkText)) {
return;
}
diff --git a/lib/widgets/sales_button.dart b/lib/widgets/sales_button.dart
index 7bf70b9..85a0199 100644
--- a/lib/widgets/sales_button.dart
+++ b/lib/widgets/sales_button.dart
@@ -66,7 +66,8 @@ class SalesButton extends StatelessWidget {
fontSize: 1,
)),
child: Container(
- child: Center(
+ child: Text(
+ "ho") /* Center(
child: Column(
children: [
Divider(
@@ -92,7 +93,8 @@ class SalesButton extends StatelessWidget {
child: Text(desc4!, maxLines: 2, style: GoogleFonts.inter(fontSize: 10, color: Colors.red[800])))
],
),
- )),
+ ) */
+ ),
)));
}
}
diff --git a/lib/widgets/tutorial_widget.dart b/lib/widgets/tutorial_widget.dart
index e0c8441..e2266ef 100644
--- a/lib/widgets/tutorial_widget.dart
+++ b/lib/widgets/tutorial_widget.dart
@@ -40,10 +40,13 @@ class TutorialWidget with Trans, Logging {
area = bloc.action!.showBubble == true
? Rect.fromLTWH(targetGlobalCenter.dx - bloc.action!.bubbleX, targetGlobalCenter.dy - bloc.action!.bubbleY,
bloc.action!.bubbleWidth.toDouble(), bloc.action!.bubbleHeight.toDouble())
+ //? Rect.fromLTWH(targetGlobalCenter.dx - 60, targetGlobalCenter.dy + 120, 420, 320)
: null;
}
final double mediaSize = MediaQuery.of(context).size.width;
+ final double mediaHeight = MediaQuery.of(context).size.width;
+ final double distortion = mediaHeight / bloc.mediaHeightBase;
double fontSize = 14;
if (mediaSize > 400) {
@@ -51,8 +54,16 @@ class TutorialWidget with Trans, Logging {
} else if (mediaSize < 375) {
fontSize = 13;
}
+
+ double calculatedTop = bloc.top! / distortion;
+ //-((1 - distortion) * 100 * (fontSize));
+ if (calculatedTop < 0) {
+ calculatedTop = 10;
+ }
+ print("Height: $mediaHeight, distortion: $distortion top: ${bloc.top!} calculated $calculatedTop");
+
tooltip = SuperTooltip(
- top: bloc.top,
+ top: calculatedTop,
left: bloc.left,
backgroundColor: Colors.black.withOpacity(0.7),
popupDirection: bloc.action == null || bloc.action!.direction == "up" ? TooltipDirection.up : TooltipDirection.down,
diff --git a/pubspec.lock b/pubspec.lock
index 5f8060c..4751a46 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -15,6 +15,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
+ animated_widgets:
+ dependency: "direct main"
+ description:
+ name: animated_widgets
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.0.6"
apple_sign_in:
dependency: "direct main"
description:
@@ -315,49 +322,49 @@ packages:
name: firebase_analytics
url: "https://pub.dartlang.org"
source: hosted
- version: "8.0.0-dev.2"
+ version: "8.0.2"
firebase_analytics_platform_interface:
dependency: transitive
description:
name: firebase_analytics_platform_interface
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.0-dev.0"
+ version: "2.0.0"
firebase_analytics_web:
dependency: transitive
description:
name: firebase_analytics_web
url: "https://pub.dartlang.org"
source: hosted
- version: "0.3.0-dev.0"
+ version: "0.3.0"
firebase_auth:
dependency: "direct main"
description:
name: firebase_auth
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.3"
+ version: "1.1.2"
firebase_auth_platform_interface:
dependency: transitive
description:
name: firebase_auth_platform_interface
url: "https://pub.dartlang.org"
source: hosted
- version: "4.0.2"
+ version: "4.2.0"
firebase_auth_web:
dependency: transitive
description:
name: firebase_auth_web
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.5"
+ version: "1.1.0"
firebase_core:
dependency: "direct main"
description:
name: firebase_core
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.3"
+ version: "1.1.0"
firebase_core_platform_interface:
dependency: transitive
description:
@@ -378,21 +385,35 @@ packages:
name: firebase_messaging
url: "https://pub.dartlang.org"
source: hosted
- version: "9.1.1"
+ version: "9.1.3"
firebase_messaging_platform_interface:
dependency: transitive
description:
name: firebase_messaging_platform_interface
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.1"
+ version: "2.1.3"
firebase_messaging_web:
dependency: transitive
description:
name: firebase_messaging_web
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.4"
+ version: "1.0.6"
+ firebase_remote_config:
+ dependency: "direct main"
+ description:
+ name: firebase_remote_config
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.10.0-dev.2"
+ firebase_remote_config_platform_interface:
+ dependency: transitive
+ description:
+ name: firebase_remote_config_platform_interface
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.3.0-dev.2"
fixnum:
dependency: transitive
description:
@@ -419,6 +440,13 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
+ flutter_app_badger:
+ dependency: "direct main"
+ description:
+ name: flutter_app_badger
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.2.0"
flutter_bloc:
dependency: "direct main"
description:
@@ -447,6 +475,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.4.1+1"
+ flutter_fadein:
+ dependency: "direct main"
+ description:
+ name: flutter_fadein
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.0.0"
flutter_html:
dependency: "direct main"
description:
@@ -506,6 +541,13 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
+ flutter_uxcam:
+ dependency: "direct main"
+ description:
+ name: flutter_uxcam
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.3.2"
flutter_web_plugins:
dependency: transitive
description: flutter
@@ -707,6 +749,48 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
+ package_info_plus:
+ dependency: transitive
+ description:
+ name: package_info_plus
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.0.0"
+ package_info_plus_linux:
+ dependency: transitive
+ description:
+ name: package_info_plus_linux
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.0.0"
+ package_info_plus_macos:
+ dependency: transitive
+ description:
+ name: package_info_plus_macos
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.0"
+ package_info_plus_platform_interface:
+ dependency: transitive
+ description:
+ name: package_info_plus_platform_interface
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.0.0"
+ package_info_plus_web:
+ dependency: transitive
+ description:
+ name: package_info_plus_web
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.0.0"
+ package_info_plus_windows:
+ dependency: transitive
+ description:
+ name: package_info_plus_windows
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.0.0"
path:
dependency: transitive
description:
@@ -876,12 +960,19 @@ packages:
source: hosted
version: "0.26.0"
sentry:
- dependency: "direct main"
+ dependency: transitive
description:
name: sentry
url: "https://pub.dartlang.org"
source: hosted
version: "5.0.0"
+ sentry_flutter:
+ dependency: "direct main"
+ description:
+ name: sentry_flutter
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "5.0.0"
shared_preferences:
dependency: "direct dev"
description:
@@ -957,13 +1048,6 @@ packages:
description: flutter
source: sdk
version: "0.0.99"
- smartlook:
- dependency: "direct main"
- description:
- name: smartlook
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.0.7"
source_gen:
dependency: transitive
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 24c2cd8..8f311e8 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -57,12 +57,14 @@ dependencies:
convex_bottom_bar: ^3.0.0
flutter_app_badger: ^1.2.0
#super_tooltip: ^1.0.1
-
- firebase_core: ^1.0.3
- firebase_analytics: ^8.0.0-dev.2
- firebase_messaging: ^9.1.1
+
+ firebase_core: ^1.1.0
+ firebase_analytics: ^8.0.2
+ firebase_messaging: ^9.1.3
flutter_local_notifications: ^5.0.0
- firebase_auth: ^1.0.3
+ firebase_auth: ^1.1.2
+ firebase_remote_config: ^0.10.0-dev.2
+
flutter_facebook_auth: ^3.3.2
google_sign_in: ^5.0.1
apple_sign_in: ^0.1.0