WT 1.1.14+2 sales page update
This commit is contained in:
parent
c901b07bf8
commit
3137bc2330
11
i18n/en.json
11
i18n/en.json
@ -330,7 +330,7 @@
|
||||
"Progressindicator for the tests":"Where do you stand achieving your tests?",
|
||||
"Progressindicator_desc":"<p>It shows which muscle group test did your achieved already.</p><h2>When do you reach the 100% test round?</h2><br/><p>If you have sucessfully tested one of the <strong>base</strong> exercises of each muscle group</p>",
|
||||
|
||||
"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"
|
||||
|
||||
}
|
@ -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"
|
||||
}
|
168
ios/Podfile.lock
168
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
|
||||
|
@ -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 = (
|
||||
|
@ -44,7 +44,7 @@
|
||||
<string>fbshareextension</string>
|
||||
</array>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>12.0</string>
|
||||
<string>11.0</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
|
@ -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<SalesEvent, SalesState> with Logging {
|
||||
List<ProductTest>? tests = [];
|
||||
List<Product> product2Display = [];
|
||||
int productSet = -1;
|
||||
final DescriptionRepository descriptionRepository = DescriptionRepository();
|
||||
SalesBloc() : super(SalesInitial());
|
||||
|
||||
String? salesText;
|
||||
|
||||
String salesButtonText = "<h1>Workout Test Monthly</h1><p>localizedPrice</p><p><small>cancel any time</small></p>";
|
||||
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<SalesState> mapEventToState(
|
||||
SalesEvent event,
|
||||
@ -32,9 +55,30 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> 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<SalesEvent, SalesState> 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<SalesEvent, SalesState> 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<SalesEvent, SalesState> 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<SalesEvent, SalesState> 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<Product>? 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<SalesEvent, SalesState> with Logging {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
ProductTest productTest = ProductTest();
|
||||
//ProductTest productTest = ProductTest();
|
||||
|
||||
productSet = 2;
|
||||
log("ProductSet: " + productSet.toString());
|
||||
@ -130,7 +193,8 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> 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<SalesEvent, SalesState> 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);
|
||||
}
|
||||
|
@ -15,3 +15,7 @@ class SalesPurchase extends SalesEvent {
|
||||
final int productId;
|
||||
const SalesPurchase({required this.productId});
|
||||
}
|
||||
|
||||
class SalesChangeSubscription extends SalesEvent {
|
||||
const SalesChangeSubscription();
|
||||
}
|
||||
|
@ -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<SessionEvent, SessionState> 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));
|
||||
|
@ -12,6 +12,7 @@ part 'tutorial_state.dart';
|
||||
|
||||
class TutorialBloc extends Bloc<TutorialEvent, TutorialState> with Logging {
|
||||
late String tutorialName;
|
||||
final double mediaHeightBase = 390;
|
||||
bool isActive = false;
|
||||
bool canActivate = false;
|
||||
|
||||
@ -46,6 +47,7 @@ class TutorialBloc extends Bloc<TutorialEvent, TutorialState> with Logging {
|
||||
|
||||
setNextStepData(step);
|
||||
isActive = true;
|
||||
canActivate = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -58,8 +60,9 @@ class TutorialBloc extends Bloc<TutorialEvent, TutorialState> 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<TutorialEvent, TutorialState> 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<TutorialEvent, TutorialState> 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<TutorialEvent, TutorialState> 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<TutorialEvent, TutorialState> with Logging {
|
||||
yield TutorialReady();
|
||||
} else if (event is TutorialStart) {
|
||||
yield TutorialLoading();
|
||||
isActive = true;
|
||||
canActivate = true;
|
||||
step = 0;
|
||||
yield TutorialReady();
|
||||
|
304
lib/library/button_animations.dart
Normal file
304
lib/library/button_animations.dart
Normal file
@ -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<Color>? 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<AnimatedButton> {
|
||||
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: <Widget>[
|
||||
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>[
|
||||
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<Color> colors, bool darkShadow) {
|
||||
List<Color> 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;
|
||||
}
|
||||
}
|
@ -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<CustomerExerciseDevice>? _customerDevices;
|
||||
List<CustomerActivity>? _customerActivities;
|
||||
List<Tutorial>? _tutorials;
|
||||
List<Description>? _descriptions;
|
||||
|
||||
LinkedHashMap<int, ExercisePlanDetail> _myExercisesPlanDetails = LinkedHashMap<int, ExercisePlanDetail>();
|
||||
|
||||
@ -141,6 +151,8 @@ class Cache with Logging {
|
||||
List<Exercise>? _exercisesTrainee;
|
||||
ExercisePlan? _traineeExercisePlan;
|
||||
|
||||
RemoteConfig? remoteConfig;
|
||||
|
||||
LinkedHashMap<String, int> _badges = LinkedHashMap();
|
||||
|
||||
List? deviceLanguages;
|
||||
@ -664,4 +676,10 @@ class Cache with Logging {
|
||||
|
||||
List<Tutorial>? get tutorials => this._tutorials;
|
||||
setTutorials(List<Tutorial>? value) => this._tutorials = value;
|
||||
|
||||
RemoteConfig? getRemoteConfig() => this.remoteConfig;
|
||||
setRemoteConfig(RemoteConfig? remoteConfig) => this.remoteConfig = remoteConfig;
|
||||
|
||||
List<Description>? getDescriptions() => this._descriptions;
|
||||
setDescriptions(List<Description>? value) => this._descriptions = value;
|
||||
}
|
||||
|
40
lib/model/description.dart
Normal file
40
lib/model/description.dart
Normal file
@ -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<String, dynamic> 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();
|
||||
}
|
@ -46,6 +46,7 @@ class Product {
|
||||
'productIdAndroid': this.productIdAndroid,
|
||||
'priceIos': this.priceIos,
|
||||
'priceAndroid': this.priceAndroid,
|
||||
'localizedPrice': this.localizedPrice
|
||||
};
|
||||
return json.toString();
|
||||
}
|
||||
|
@ -14,6 +14,19 @@ class Tutorial {
|
||||
|
||||
if (json['steps'] != null && json['steps'].length > 0) {
|
||||
steps = json['steps'].map<TutorialStep>((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;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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!));
|
||||
}
|
||||
|
||||
|
@ -27,5 +27,7 @@ class PushNotificationsManager with Logging {
|
||||
badge: true,
|
||||
sound: true,
|
||||
);
|
||||
String? token = await FirebaseMessaging.instance.getToken();
|
||||
print("FirebaseMessaging tokne $token");
|
||||
}
|
||||
}
|
||||
|
23
lib/repository/description_repository.dart
Normal file
23
lib/repository/description_repository.dart
Normal file
@ -0,0 +1,23 @@
|
||||
import 'package:aitrainer_app/model/cache.dart';
|
||||
import 'package:aitrainer_app/model/description.dart';
|
||||
|
||||
class DescriptionRepository {
|
||||
List<Description>? 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;
|
||||
}
|
||||
}
|
@ -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<void> 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<void> resetPassword(String email) async {
|
||||
await FirebaseAuth.instance.sendPasswordResetEmail(email: email);
|
||||
}
|
||||
|
||||
Future<void> 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(<String, dynamic>{
|
||||
'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()}");
|
||||
}
|
||||
}
|
||||
|
@ -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<Tutorial> 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<Description>? descriptions = json.map((description) => Description.fromJson(description)).toList();
|
||||
//print("Description: $descriptions");
|
||||
Cache().setDescriptions(descriptions);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -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';
|
||||
|
@ -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) {
|
||||
|
@ -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<ExerciseControlPage> with Trans {
|
||||
|
||||
String title = (step + 1).toString() + "/4 " + t("Control Exercise:");
|
||||
LinkedHashMap args = LinkedHashMap();
|
||||
final TutorialBloc tutorialBloc = BlocProvider.of<TutorialBloc>(context);
|
||||
|
||||
List<Widget> listWidgets = [
|
||||
Text(
|
||||
@ -332,15 +334,20 @@ class _ExerciseControlPage extends State<ExerciseControlPage> 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,
|
||||
|
@ -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<SalesBloc, SalesState>(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>[
|
||||
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: "<p>" + t("View other alternatives") + "</p>",
|
||||
//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: "<p>" + trialText + "</p>",
|
||||
//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<Widget> getButtons(SalesBloc bloc) {
|
||||
List<Widget> buttons = [];
|
||||
|
||||
|
@ -139,7 +139,7 @@ class SettingsPage extends StatelessWidget with Trans {
|
||||
final TutorialBloc tutorialBloc = BlocProvider.of<TutorialBloc>(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());
|
||||
},
|
||||
),
|
||||
|
@ -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(
|
||||
|
@ -67,17 +67,25 @@ class _MenuPageWidgetState extends State<MenuPageWidget> 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<MenuPageWidget> 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;
|
||||
}
|
||||
|
@ -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])))
|
||||
],
|
||||
),
|
||||
)),
|
||||
) */
|
||||
),
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
120
pubspec.lock
120
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:
|
||||
|
12
pubspec.yaml
12
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
|
||||
|
Loading…
Reference in New Issue
Block a user