WT 1.1.14+2 sales page update

This commit is contained in:
bossanyit 2021-05-05 21:01:03 +02:00
parent c901b07bf8
commit 3137bc2330
30 changed files with 1008 additions and 207 deletions

View File

@ -330,7 +330,7 @@
"Progressindicator for the tests":"Where do you stand achieving your tests?", "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>", "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.", "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", "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", "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", "Please take a short tour in the app":"Please take a short tour in the app",
"No Login":"No Login", "No Login":"No Login",
"You will skip the login.":"You will skip the 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"
} }

View File

@ -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", "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", "No Login":"Bejelentkezés kimaradt",
"You will skip the login.":"Átugrod a bejelentkezést.", "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"
} }

View File

@ -18,74 +18,108 @@ PODS:
- FBSDKLoginKit/Login (= 9.1.0) - FBSDKLoginKit/Login (= 9.1.0)
- FBSDKLoginKit/Login (9.1.0): - FBSDKLoginKit/Login (9.1.0):
- FBSDKCoreKit (~> 9.1.0) - FBSDKCoreKit (~> 9.1.0)
- Firebase/Analytics (7.3.0): - Firebase/Analytics (7.11.0):
- Firebase/Core - Firebase/Core
- Firebase/Auth (7.3.0): - Firebase/Auth (7.11.0):
- Firebase/CoreOnly - Firebase/CoreOnly
- FirebaseAuth (~> 7.3.0) - FirebaseAuth (~> 7.11.0)
- Firebase/Core (7.3.0): - Firebase/Core (7.11.0):
- Firebase/CoreOnly - Firebase/CoreOnly
- FirebaseAnalytics (= 7.3.0) - FirebaseAnalytics (~> 7.11.0)
- Firebase/CoreOnly (7.3.0): - Firebase/CoreOnly (7.11.0):
- FirebaseCore (= 7.3.0) - FirebaseCore (= 7.11.0)
- Firebase/Messaging (7.3.0): - Firebase/Messaging (7.11.0):
- Firebase/CoreOnly - Firebase/CoreOnly
- FirebaseMessaging (~> 7.3.0) - FirebaseMessaging (~> 7.11.0)
- firebase_analytics (8.0.0-dev.2): - Firebase/RemoteConfig (7.11.0):
- Firebase/Analytics (= 7.3.0) - Firebase/CoreOnly
- FirebaseRemoteConfig (~> 7.11.0)
- firebase_analytics (8.0.2):
- Firebase/Analytics (= 7.11.0)
- firebase_core - firebase_core
- Flutter - Flutter
- firebase_auth (1.0.3): - firebase_auth (1.1.2):
- Firebase/Auth (= 7.3.0) - Firebase/Auth (= 7.11.0)
- firebase_core - firebase_core
- Flutter - Flutter
- firebase_core (1.0.3): - firebase_core (1.1.0):
- Firebase/CoreOnly (= 7.3.0) - Firebase/CoreOnly (= 7.11.0)
- Flutter - Flutter
- firebase_messaging (9.1.1): - firebase_messaging (9.1.3):
- Firebase/Messaging (= 7.3.0) - Firebase/Messaging (= 7.11.0)
- firebase_core - firebase_core
- Flutter - 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) - FirebaseCore (~> 7.0)
- FirebaseInstallations (~> 7.0) - FirebaseInstallations (~> 7.0)
- GoogleAppMeasurement (= 7.3.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.0) - GoogleUtilities/AppDelegateSwizzler (~> 7.0)
- GoogleUtilities/MethodSwizzler (~> 7.0) - GoogleUtilities/MethodSwizzler (~> 7.0)
- GoogleUtilities/Network (~> 7.0) - GoogleUtilities/Network (~> 7.0)
- "GoogleUtilities/NSData+zlib (~> 7.0)" - "GoogleUtilities/NSData+zlib (~> 7.0)"
- nanopb (~> 2.30906.0) - nanopb (~> 2.30908.0)
- FirebaseAuth (7.3.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) - FirebaseCore (~> 7.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.0) - GoogleUtilities/AppDelegateSwizzler (~> 7.0)
- GoogleUtilities/Environment (~> 7.0) - GoogleUtilities/Environment (~> 7.0)
- GTMSessionFetcher/Core (~> 1.4) - GTMSessionFetcher/Core (~> 1.4)
- FirebaseCore (7.3.0): - FirebaseCore (7.11.0):
- FirebaseCoreDiagnostics (~> 7.0) - FirebaseCoreDiagnostics (~> 7.4)
- GoogleUtilities/Environment (~> 7.0) - GoogleUtilities/Environment (~> 7.0)
- GoogleUtilities/Logger (~> 7.0) - GoogleUtilities/Logger (~> 7.0)
- FirebaseCoreDiagnostics (7.3.0): - FirebaseCoreDiagnostics (7.11.0):
- GoogleDataTransport (~> 8.0) - GoogleDataTransport (~> 8.4)
- GoogleUtilities/Environment (~> 7.0) - GoogleUtilities/Environment (~> 7.0)
- GoogleUtilities/Logger (~> 7.0) - GoogleUtilities/Logger (~> 7.0)
- nanopb (~> 2.30906.0) - nanopb (~> 2.30908.0)
- FirebaseInstallations (7.9.0): - FirebaseInstallations (7.11.0):
- FirebaseCore (~> 7.0) - FirebaseCore (~> 7.0)
- GoogleUtilities/Environment (~> 7.0) - GoogleUtilities/Environment (~> 7.0)
- GoogleUtilities/UserDefaults (~> 7.0) - GoogleUtilities/UserDefaults (~> 7.0)
- PromisesObjC (~> 1.2) - PromisesObjC (~> 1.2)
- FirebaseInstanceID (7.9.0): - FirebaseInstanceID (7.11.0):
- FirebaseCore (~> 7.0) - FirebaseCore (~> 7.0)
- FirebaseInstallations (~> 7.0) - FirebaseInstallations (~> 7.0)
- GoogleUtilities/Environment (~> 7.0) - GoogleUtilities/Environment (~> 7.0)
- GoogleUtilities/UserDefaults (~> 7.0) - GoogleUtilities/UserDefaults (~> 7.0)
- FirebaseMessaging (7.3.0): - FirebaseMessaging (7.11.0):
- FirebaseCore (~> 7.0) - FirebaseCore (~> 7.0)
- FirebaseInstallations (~> 7.0)
- FirebaseInstanceID (~> 7.0) - FirebaseInstanceID (~> 7.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.0) - GoogleUtilities/AppDelegateSwizzler (~> 7.0)
- GoogleUtilities/Environment (~> 7.0) - GoogleUtilities/Environment (~> 7.0)
- GoogleUtilities/Reachability (~> 7.0) - GoogleUtilities/Reachability (~> 7.0)
- GoogleUtilities/UserDefaults (~> 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 (0.0.4):
- Flurry-iOS-SDK/FlurrySDK - Flurry-iOS-SDK/FlurrySDK
- Flutter - Flutter
@ -110,36 +144,38 @@ PODS:
- google_sign_in (0.0.1): - google_sign_in (0.0.1):
- Flutter - Flutter
- GoogleSignIn (~> 5.0) - GoogleSignIn (~> 5.0)
- GoogleAppMeasurement (7.3.0): - GoogleAppMeasurement/AdIdSupport (7.11.0):
- GoogleUtilities/AppDelegateSwizzler (~> 7.0) - GoogleUtilities/AppDelegateSwizzler (~> 7.0)
- GoogleUtilities/MethodSwizzler (~> 7.0) - GoogleUtilities/MethodSwizzler (~> 7.0)
- GoogleUtilities/Network (~> 7.0) - GoogleUtilities/Network (~> 7.0)
- "GoogleUtilities/NSData+zlib (~> 7.0)" - "GoogleUtilities/NSData+zlib (~> 7.0)"
- nanopb (~> 2.30906.0) - nanopb (~> 2.30908.0)
- GoogleDataTransport (8.1.0): - GoogleDataTransport (8.4.0):
- nanopb (~> 2.30906.0) - GoogleUtilities/Environment (~> 7.2)
- nanopb (~> 2.30908.0)
- PromisesObjC (~> 1.2)
- GoogleSignIn (5.0.2): - GoogleSignIn (5.0.2):
- AppAuth (~> 1.2) - AppAuth (~> 1.2)
- GTMAppAuth (~> 1.0) - GTMAppAuth (~> 1.0)
- GTMSessionFetcher/Core (~> 1.1) - GTMSessionFetcher/Core (~> 1.1)
- GoogleUtilities/AppDelegateSwizzler (7.3.1): - GoogleUtilities/AppDelegateSwizzler (7.4.0):
- GoogleUtilities/Environment - GoogleUtilities/Environment
- GoogleUtilities/Logger - GoogleUtilities/Logger
- GoogleUtilities/Network - GoogleUtilities/Network
- GoogleUtilities/Environment (7.3.1): - GoogleUtilities/Environment (7.4.0):
- PromisesObjC (~> 1.2) - PromisesObjC (~> 1.2)
- GoogleUtilities/Logger (7.3.1): - GoogleUtilities/Logger (7.4.0):
- GoogleUtilities/Environment - GoogleUtilities/Environment
- GoogleUtilities/MethodSwizzler (7.3.1): - GoogleUtilities/MethodSwizzler (7.4.0):
- GoogleUtilities/Logger - GoogleUtilities/Logger
- GoogleUtilities/Network (7.3.1): - GoogleUtilities/Network (7.4.0):
- GoogleUtilities/Logger - GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib" - "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Reachability - GoogleUtilities/Reachability
- "GoogleUtilities/NSData+zlib (7.3.1)" - "GoogleUtilities/NSData+zlib (7.4.0)"
- GoogleUtilities/Reachability (7.3.1): - GoogleUtilities/Reachability (7.4.0):
- GoogleUtilities/Logger - GoogleUtilities/Logger
- GoogleUtilities/UserDefaults (7.3.1): - GoogleUtilities/UserDefaults (7.4.0):
- GoogleUtilities/Logger - GoogleUtilities/Logger
- GTMAppAuth (1.1.0): - GTMAppAuth (1.1.0):
- AppAuth/Core (~> 1.4) - AppAuth/Core (~> 1.4)
@ -151,11 +187,11 @@ PODS:
- GTMSessionFetcher/Core (= 1.5.0) - GTMSessionFetcher/Core (= 1.5.0)
- modal_progress_hud_nsn (0.0.1): - modal_progress_hud_nsn (0.0.1):
- Flutter - Flutter
- nanopb (2.30906.0): - nanopb (2.30908.0):
- nanopb/decode (= 2.30906.0) - nanopb/decode (= 2.30908.0)
- nanopb/encode (= 2.30906.0) - nanopb/encode (= 2.30908.0)
- nanopb/decode (2.30906.0) - nanopb/decode (2.30908.0)
- nanopb/encode (2.30906.0) - nanopb/encode (2.30908.0)
- package_info (0.0.1): - package_info (0.0.1):
- Flutter - Flutter
- package_info_plus (0.4.5): - package_info_plus (0.4.5):
@ -197,6 +233,7 @@ DEPENDENCIES:
- firebase_auth (from `.symlinks/plugins/firebase_auth/ios`) - firebase_auth (from `.symlinks/plugins/firebase_auth/ios`)
- firebase_core (from `.symlinks/plugins/firebase_core/ios`) - firebase_core (from `.symlinks/plugins/firebase_core/ios`)
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/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`) - flurry (from `.symlinks/plugins/flurry/ios`)
- Flutter (from `Flutter`) - Flutter (from `Flutter`)
- flutter_app_badger (from `.symlinks/plugins/flutter_app_badger/ios`) - flutter_app_badger (from `.symlinks/plugins/flutter_app_badger/ios`)
@ -223,6 +260,7 @@ SPEC REPOS:
- FBSDKCoreKit - FBSDKCoreKit
- FBSDKLoginKit - FBSDKLoginKit
- Firebase - Firebase
- FirebaseABTesting
- FirebaseAnalytics - FirebaseAnalytics
- FirebaseAuth - FirebaseAuth
- FirebaseCore - FirebaseCore
@ -230,6 +268,7 @@ SPEC REPOS:
- FirebaseInstallations - FirebaseInstallations
- FirebaseInstanceID - FirebaseInstanceID
- FirebaseMessaging - FirebaseMessaging
- FirebaseRemoteConfig
- Flurry-iOS-SDK - Flurry-iOS-SDK
- FMDB - FMDB
- GoogleAppMeasurement - GoogleAppMeasurement
@ -259,6 +298,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/firebase_core/ios" :path: ".symlinks/plugins/firebase_core/ios"
firebase_messaging: firebase_messaging:
:path: ".symlinks/plugins/firebase_messaging/ios" :path: ".symlinks/plugins/firebase_messaging/ios"
firebase_remote_config:
:path: ".symlinks/plugins/firebase_remote_config/ios"
flurry: flurry:
:path: ".symlinks/plugins/flurry/ios" :path: ".symlinks/plugins/flurry/ios"
Flutter: Flutter:
@ -304,18 +345,21 @@ SPEC CHECKSUMS:
devicelocale: b22617f40038496deffba44747101255cee005b0 devicelocale: b22617f40038496deffba44747101255cee005b0
FBSDKCoreKit: a00fe2efd780c195a5e09201bf51c56106245b40 FBSDKCoreKit: a00fe2efd780c195a5e09201bf51c56106245b40
FBSDKLoginKit: d98498c598ec09de657385a9349a1f21119b7f86 FBSDKLoginKit: d98498c598ec09de657385a9349a1f21119b7f86
Firebase: 26223c695fe322633274198cb19dca8cb7e54416 Firebase: c121feb35e4126c0b355e3313fa9b487d47319fd
firebase_analytics: 4c032e04324c47ee6dd7a28bfff831e0ac0d09b6 firebase_analytics: 620e8cc1705feb6b9c40b6127bea9b39e03e3970
firebase_auth: c2c27e1081671b02f90981e70dad54722198491f firebase_auth: e7065954aa2a7c8ef1a8502fba3009bcdd8fc91a
firebase_core: b5d81dfd4fb2d6f700e67de34d9a633ae325c4e9 firebase_core: 84dcd80ac6d29c3d1039071b7306ee99688eb9c7
firebase_messaging: 7547c99f31466371f9cfcb733d5a1bf32a819872 firebase_messaging: 7aecb08eada5e5cde85b10875141706a8d18b818
FirebaseAnalytics: 2580c2d62535ae7b644143d48941fcc239ea897a firebase_remote_config: f855065886b7d6ccc38144c9a3cecbdc7887f33e
FirebaseAuth: c224a0cf1afa0949bd5c7bfcf154b4f5ce8ddef2 FirebaseABTesting: e66f1f80747792630d9b292966de206d5df9853b
FirebaseCore: 4d3c72622ce0e2106aaa07bb4b2935ba2c370972 FirebaseAnalytics: cd3bd84d722a24a8923918af8af8e5236f615d77
FirebaseCoreDiagnostics: d50e11039e5984d92c8a512be2395f13df747350 FirebaseAuth: 5fe4585c2ed847319f0ea68bd1d82c77e49ff9a0
FirebaseInstallations: 5e777e6640fa060405cc7632447b6c5ca5af4742 FirebaseCore: 907447d8917a4d3eb0cce2829c5a0ad21d90b432
FirebaseInstanceID: 53140c03b9f6136f890d7901399f85a4c90ab2d0 FirebaseCoreDiagnostics: 68ad972f99206cef818230f3f3179d52ccfb7f8c
FirebaseMessaging: 68d1bcb14880189558a8ae57167abe0b7e417232 FirebaseInstallations: a58d4f72ec5861840b84df489f2668d970df558a
FirebaseInstanceID: ad5135045a498d7775903efd39762d2cdfa1be27
FirebaseMessaging: 163435fb6db065e3b6228f1e577b10ed2cc506d2
FirebaseRemoteConfig: 0ea30de5fb0231df8c1bdcdf3b6c23bdc5066131
flurry: 15b01f664ab1367c62b50291541ea7f78ca85aad flurry: 15b01f664ab1367c62b50291541ea7f78ca85aad
Flurry-iOS-SDK: 6636d30c30f12010e7c7c71d84b443416a168efc Flurry-iOS-SDK: 6636d30c30f12010e7c7c71d84b443416a168efc
Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
@ -326,14 +370,14 @@ SPEC CHECKSUMS:
flutter_uxcam: 87dd981feb200bc81a2f062edb5ca2d16dae595a flutter_uxcam: 87dd981feb200bc81a2f062edb5ca2d16dae595a
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
google_sign_in: 6bd214b9c154f881422f5fe27b66aaa7bbd580cc google_sign_in: 6bd214b9c154f881422f5fe27b66aaa7bbd580cc
GoogleAppMeasurement: 8d3c0aeede16ab7764144b5a4ca8e1d4323841b7 GoogleAppMeasurement: fd19169c3034975cb934e865e5667bfdce59df7f
GoogleDataTransport: 116c84c4bdeb76be2a7a46de51244368f9794eab GoogleDataTransport: cd9db2180fcecd8da1b561aea31e3e56cf834aa7
GoogleSignIn: 7137d297ddc022a7e0aa4619c86d72c909fa7213 GoogleSignIn: 7137d297ddc022a7e0aa4619c86d72c909fa7213
GoogleUtilities: e1d9ed4e544fc32a93e00e721400cbc3f377200d GoogleUtilities: 284cddc7fffc14ae1907efb6f78ab95c1fccaedc
GTMAppAuth: 197a8dabfea5d665224aa00d17f164fc2248dab9 GTMAppAuth: 197a8dabfea5d665224aa00d17f164fc2248dab9
GTMSessionFetcher: b3503b20a988c4e20cc189aa798fd18220133f52 GTMSessionFetcher: b3503b20a988c4e20cc189aa798fd18220133f52
modal_progress_hud_nsn: f6fb744cd060653d66ed8f325360ef3650eb2fde modal_progress_hud_nsn: f6fb744cd060653d66ed8f325360ef3650eb2fde
nanopb: 1bf24dd71191072e120b83dd02d08f3da0d65e53 nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62 package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c

View File

@ -388,7 +388,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 4;
DEVELOPMENT_TEAM = SFJJBDCU6Z; DEVELOPMENT_TEAM = SFJJBDCU6Z;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
@ -531,7 +531,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 4;
DEVELOPMENT_TEAM = SFJJBDCU6Z; DEVELOPMENT_TEAM = SFJJBDCU6Z;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
@ -566,7 +566,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 4;
DEVELOPMENT_TEAM = SFJJBDCU6Z; DEVELOPMENT_TEAM = SFJJBDCU6Z;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (

View File

@ -44,7 +44,7 @@
<string>fbshareextension</string> <string>fbshareextension</string>
</array> </array>
<key>LSMinimumSystemVersion</key> <key>LSMinimumSystemVersion</key>
<string>12.0</string> <string>11.0</string>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>NSAppTransportSecurity</key> <key>NSAppTransportSecurity</key>

View File

@ -6,6 +6,7 @@ import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/product.dart'; import 'package:aitrainer_app/model/product.dart';
import 'package:aitrainer_app/model/product_test.dart'; import 'package:aitrainer_app/model/product_test.dart';
import 'package:aitrainer_app/model/purchase.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/logging.dart';
import 'package:aitrainer_app/service/purchase_service.dart'; import 'package:aitrainer_app/service/purchase_service.dart';
import 'package:aitrainer_app/util/enums.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:aitrainer_app/util/track.dart';
import 'package:bloc/bloc.dart'; import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:firebase_remote_config/firebase_remote_config.dart';
import 'package:purchases_flutter/offering_wrapper.dart'; import 'package:purchases_flutter/offering_wrapper.dart';
part 'sales_event.dart'; part 'sales_event.dart';
@ -22,8 +24,29 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
List<ProductTest>? tests = []; List<ProductTest>? tests = [];
List<Product> product2Display = []; List<Product> product2Display = [];
int productSet = -1; int productSet = -1;
final DescriptionRepository descriptionRepository = DescriptionRepository();
SalesBloc() : super(SalesInitial()); 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 @override
Stream<SalesState> mapEventToState( Stream<SalesState> mapEventToState(
SalesEvent event, SalesEvent event,
@ -32,9 +55,30 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
if (event is SalesLoad) { if (event is SalesLoad) {
yield SalesLoading(); yield SalesLoading();
log("Load Sales"); 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(); await RevenueCatPurchases().getOfferings();
this.getProductSet(); 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(); yield SalesReady();
} else if (event is SalesPurchase) { } else if (event is SalesPurchase) {
if (Cache().hasPurchased) { if (Cache().hasPurchased) {
@ -60,6 +104,22 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
} else { } else {
yield SalesError(message: "No selected product"); 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) { } on Exception catch (ex) {
yield SalesError(message: ex.toString()); yield SalesError(message: ex.toString());
@ -76,7 +136,7 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
return prod; return prod;
} }
String getLocalizedPrice(String productId) { String getLocalizedPrice(String productId, Product product) {
String price = ""; String price = "";
Offering? offering = RevenueCatPurchases().offering; Offering? offering = RevenueCatPurchases().offering;
if (offering != null) { if (offering != null) {
@ -86,7 +146,7 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
price = package.product.priceString; price = package.product.priceString;
if (price.contains(r'HUF')) { if (price.contains(r'HUF')) {
price = price.replaceAll(RegExp(r'HUF'), 'Ft'); price = price.replaceAll(RegExp(r'HUF'), 'Ft');
price = price.replaceAll(RegExp(r',00'), ""); price = price.replaceAll(RegExp(r'\,00'), "");
} }
break; break;
} }
@ -94,18 +154,21 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
} else { } else {
log(" !!! No Offering"); log(" !!! No Offering");
} }
if (price.isEmpty) {
price = Platform.isAndroid ? product.priceAndroid.toString() : product.priceIos.toString();
}
return price; return price;
} }
void getProductSet() { void getProductSet() {
int productId = 0; int productId = 0;
this.tests = Cache().productTests; //this.tests = Cache().productTests;
List<Product>? products = Cache().products; List<Product>? products = Cache().products;
if (products == null) { if (products == null) {
return; return;
} }
if (tests != null && tests!.isEmpty) { /* if (tests != null && tests!.isEmpty) {
var rand = math.Random.secure(); var rand = math.Random.secure();
productSet = rand.nextInt(5) + 1; productSet = rand.nextInt(5) + 1;
} else { } else {
@ -118,9 +181,9 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
break; break;
} }
} }
} } */
ProductTest productTest = ProductTest(); //ProductTest productTest = ProductTest();
productSet = 2; productSet = 2;
log("ProductSet: " + productSet.toString()); log("ProductSet: " + productSet.toString());
@ -130,7 +193,8 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
if (product.productSet == productSet) { if (product.productSet == productSet) {
productId = product.productId; productId = product.productId;
final String platformProductId = Platform.isAndroid ? product.productIdAndroid! : product.productIdIos!; 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); product2Display.add(product);
} }
} }
@ -139,9 +203,9 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
return a.sort < b.sort ? -1 : 1; return a.sort < b.sort ? -1 : 1;
}); });
productTest.productId = productId; //productTest.productId = productId;
productTest.customerId = Cache().userLoggedIn!.customerId!; //productTest.customerId = Cache().userLoggedIn!.customerId!;
productTest.dateView = DateTime.now(); //productTest.dateView = DateTime.now();
//ProductTestApi().saveProductTest(productTest); //ProductTestApi().saveProductTest(productTest);
//Cache().productTests.add(productTest); //Cache().productTests.add(productTest);
} }

View File

@ -15,3 +15,7 @@ class SalesPurchase extends SalesEvent {
final int productId; final int productId;
const SalesPurchase({required this.productId}); const SalesPurchase({required this.productId});
} }
class SalesChangeSubscription extends SalesEvent {
const SalesChangeSubscription();
}

View File

@ -1,6 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'package:aitrainer_app/bloc/settings/settings_bloc.dart'; 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/util/app_language.dart';
import 'package:aitrainer_app/service/logging.dart'; import 'package:aitrainer_app/service/logging.dart';
import 'package:aitrainer_app/util/session.dart'; import 'package:aitrainer_app/util/session.dart';
@ -26,6 +27,7 @@ class SessionBloc extends Bloc<SessionEvent, SessionState> with Logging {
// ignore: close_sinks // ignore: close_sinks
SettingsBloc settingsBloc = event.settingsBloc; SettingsBloc settingsBloc = event.settingsBloc;
await session.fetchSessionAndNavigate(); await session.fetchSessionAndNavigate();
FirebaseApi().setupRemoteConfig();
String lang = AppLanguage().appLocal.languageCode; String lang = AppLanguage().appLocal.languageCode;
log("Change lang to $lang"); log("Change lang to $lang");
settingsBloc.add(SettingsChangeLanguage(language: lang)); settingsBloc.add(SettingsChangeLanguage(language: lang));

View File

@ -12,6 +12,7 @@ part 'tutorial_state.dart';
class TutorialBloc extends Bloc<TutorialEvent, TutorialState> with Logging { class TutorialBloc extends Bloc<TutorialEvent, TutorialState> with Logging {
late String tutorialName; late String tutorialName;
final double mediaHeightBase = 390;
bool isActive = false; bool isActive = false;
bool canActivate = false; bool canActivate = false;
@ -46,6 +47,7 @@ class TutorialBloc extends Bloc<TutorialEvent, TutorialState> with Logging {
setNextStepData(step); setNextStepData(step);
isActive = true; isActive = true;
canActivate = true;
} }
}); });
} }
@ -58,8 +60,9 @@ class TutorialBloc extends Bloc<TutorialEvent, TutorialState> with Logging {
} }
if (tutorial != null && tutorial!.steps != null) { if (tutorial != null && tutorial!.steps != null) {
actualText = tutorial!.steps![step].tutorialTextTranslation; actualText = tutorial!.steps![step].tutorialTextTranslation;
print("Step: $step, text: $actualText");
this.actualCheck = tutorial!.steps![step].checkText; this.actualCheck = tutorial!.steps![step].checkText;
print("Step: $step, text: $actualCheck");
this.checks = []; this.checks = [];
if (this.actualCheck != null) { if (this.actualCheck != null) {
@ -78,27 +81,31 @@ class TutorialBloc extends Bloc<TutorialEvent, TutorialState> with Logging {
calculateHeight(); calculateHeight();
} }
/* else {
this.add(TutorialFinished());
} */
} }
bool activateTutorial() { bool isTutorialDone() {
if (!canActivate) {
print("Tutorial canActivate false");
return false;
}
ActivityDone? activityDone = ActivityDone.tutorialBasic.searchByString(tutorialName); ActivityDone? activityDone = ActivityDone.tutorialBasic.searchByString(tutorialName);
if (activityDone == null) { if (activityDone == null) {
return false; return true;
} }
bool? isActivityDone = Cache().activitiesDone[activityDone.toStr()]; bool? isActivityDone = Cache().activitiesDone[activityDone.toStr()];
log("isActivityDone? $isActivityDone");
log("$tutorialName isActivityDone? $isActivityDone");
if (isActivityDone == null || isActivityDone == true) { if (isActivityDone == null || isActivityDone == true) {
return true;
}
canActivate = true;
return false; return false;
} }
log("Running tutorial $activityDone");
bool activateTutorial() {
if (isTutorialDone()) {
isActive = false;
canActivate = false;
return false;
}
init(); init();
return true; return true;
} }
@ -135,20 +142,9 @@ class TutorialBloc extends Bloc<TutorialEvent, TutorialState> with Logging {
if (action == null) { if (action == null) {
return step + 1; 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++; step++;
next = step; next = step;
print("Next step:! $next"); print("Next step:! $step");
if (step >= tutorial!.steps!.length) { if (step >= tutorial!.steps!.length) {
next = -1; next = -1;
this.add(TutorialFinished()); this.add(TutorialFinished());
@ -172,6 +168,7 @@ class TutorialBloc extends Bloc<TutorialEvent, TutorialState> with Logging {
menuBloc!.add(MenuCreate()); menuBloc!.add(MenuCreate());
} }
} else if (event is TutorialNext) { } else if (event is TutorialNext) {
print("Tutorial Next: ${event.text}");
if (tutorial != null) { if (tutorial != null) {
yield TutorialLoading(); yield TutorialLoading();
@ -195,7 +192,6 @@ class TutorialBloc extends Bloc<TutorialEvent, TutorialState> with Logging {
yield TutorialReady(); yield TutorialReady();
} else if (event is TutorialStart) { } else if (event is TutorialStart) {
yield TutorialLoading(); yield TutorialLoading();
isActive = true;
canActivate = true; canActivate = true;
step = 0; step = 0;
yield TutorialReady(); yield TutorialReady();

View 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;
}
}

View File

@ -2,6 +2,7 @@ import 'dart:collection';
import 'dart:convert'; import 'dart:convert';
import 'package:aitrainer_app/model/customer.dart'; import 'package:aitrainer_app/model/customer.dart';
import 'package:aitrainer_app/model/customer_activity.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/evaluation.dart';
import 'package:aitrainer_app/model/exercise_plan.dart'; import 'package:aitrainer_app/model/exercise_plan.dart';
import 'package:aitrainer_app/model/exercise_plan_detail.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/enums.dart';
import 'package:aitrainer_app/util/env.dart'; import 'package:aitrainer_app/util/env.dart';
import 'package:aitrainer_app/util/track.dart'; import 'package:aitrainer_app/util/track.dart';
import 'package:firebase_remote_config/firebase_remote_config.dart';
import 'package:flurry/flurry.dart'; import 'package:flurry/flurry.dart';
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart'; import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
import 'package:flutter_uxcam/flutter_uxcam.dart'; import 'package:flutter_uxcam/flutter_uxcam.dart';
@ -58,7 +60,14 @@ enum SharePrefsChange {
- is_logged_in - is_logged_in
*/ */
enum ActivityDone { tutorialBasic, tutorialDevelopment, isExerciseLogSeen, isMuscleDevelopmentSeen } enum ActivityDone {
tutorialBasic,
tutorialBasicChestPress,
tutorialBasicLegPress,
tutorialDevelopment,
isExerciseLogSeen,
isMuscleDevelopmentSeen
}
extension ActivityDoneExt on ActivityDone { extension ActivityDoneExt on ActivityDone {
String toStr() => this.toString().split(".").last; String toStr() => this.toString().split(".").last;
@ -131,6 +140,7 @@ class Cache with Logging {
List<CustomerExerciseDevice>? _customerDevices; List<CustomerExerciseDevice>? _customerDevices;
List<CustomerActivity>? _customerActivities; List<CustomerActivity>? _customerActivities;
List<Tutorial>? _tutorials; List<Tutorial>? _tutorials;
List<Description>? _descriptions;
LinkedHashMap<int, ExercisePlanDetail> _myExercisesPlanDetails = LinkedHashMap<int, ExercisePlanDetail>(); LinkedHashMap<int, ExercisePlanDetail> _myExercisesPlanDetails = LinkedHashMap<int, ExercisePlanDetail>();
@ -141,6 +151,8 @@ class Cache with Logging {
List<Exercise>? _exercisesTrainee; List<Exercise>? _exercisesTrainee;
ExercisePlan? _traineeExercisePlan; ExercisePlan? _traineeExercisePlan;
RemoteConfig? remoteConfig;
LinkedHashMap<String, int> _badges = LinkedHashMap(); LinkedHashMap<String, int> _badges = LinkedHashMap();
List? deviceLanguages; List? deviceLanguages;
@ -664,4 +676,10 @@ class Cache with Logging {
List<Tutorial>? get tutorials => this._tutorials; List<Tutorial>? get tutorials => this._tutorials;
setTutorials(List<Tutorial>? value) => this._tutorials = value; 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;
} }

View 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();
}

View File

@ -46,6 +46,7 @@ class Product {
'productIdAndroid': this.productIdAndroid, 'productIdAndroid': this.productIdAndroid,
'priceIos': this.priceIos, 'priceIos': this.priceIos,
'priceAndroid': this.priceAndroid, 'priceAndroid': this.priceAndroid,
'localizedPrice': this.localizedPrice
}; };
return json.toString(); return json.toString();
} }

View File

@ -14,6 +14,19 @@ class Tutorial {
if (json['steps'] != null && json['steps'].length > 0) { if (json['steps'] != null && json['steps'].length > 0) {
steps = json['steps'].map<TutorialStep>((step) => TutorialStep.fromJson(step)).toList(); 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;
}
}
});
}
} }
} }

View File

@ -71,7 +71,6 @@ class TutorialStep {
this.condition = json['condition']; this.condition = json['condition'];
if (this.condition != null) { if (this.condition != null) {
this.condition = condition!.replaceAll(r'\\', "replace"); this.condition = condition!.replaceAll(r'\\', "replace");
print("Json condition $condition");
this.action = TutorialStepAction.fromJson(jsonDecode(condition!)); this.action = TutorialStepAction.fromJson(jsonDecode(condition!));
} }

View File

@ -27,5 +27,7 @@ class PushNotificationsManager with Logging {
badge: true, badge: true,
sound: true, sound: true,
); );
String? token = await FirebaseMessaging.instance.getToken();
print("FirebaseMessaging tokne $token");
} }
} }

View 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;
}
}

View File

@ -3,6 +3,7 @@ import 'package:aitrainer_app/service/logging.dart' as logging;
import 'package:apple_sign_in/apple_sign_in.dart'; import 'package:apple_sign_in/apple_sign_in.dart';
import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.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:flutter_facebook_auth/flutter_facebook_auth.dart';
import 'package:google_sign_in/google_sign_in.dart'; import 'package:google_sign_in/google_sign_in.dart';
@ -28,7 +29,8 @@ class FirebaseApi with logging.Logging {
Future<void> initializeFlutterFire() async { Future<void> initializeFlutterFire() async {
try { try {
// Wait for Firebase to initialize and set `_initialized` state to true // Wait for Firebase to initialize and set `_initialized` state to true
await Firebase.initializeApp(); FirebaseApp app = await Firebase.initializeApp();
this.appleSignInAvailable = await AppleSignIn.isAvailable(); this.appleSignInAvailable = await AppleSignIn.isAvailable();
} catch (e) { } catch (e) {
// Set `_error` state to true if Firebase initialization fails // Set `_error` state to true if Firebase initialization fails
@ -286,4 +288,23 @@ class FirebaseApi with logging.Logging {
Future<void> resetPassword(String email) async { Future<void> resetPassword(String email) async {
await FirebaseAuth.instance.sendPasswordResetEmail(email: email); 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()}");
}
} }

View File

@ -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_activity.dart';
import 'package:aitrainer_app/model/customer_exercise_device.dart'; import 'package:aitrainer_app/model/customer_exercise_device.dart';
import 'package:aitrainer_app/model/customer_property.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/evaluation.dart';
import 'package:aitrainer_app/model/exercise.dart'; import 'package:aitrainer_app/model/exercise.dart';
import 'package:aitrainer_app/model/exercise_device.dart'; import 'package:aitrainer_app/model/exercise_device.dart';
@ -72,8 +73,13 @@ class PackageApi {
} else if (headRecord[0] == "Tutorial") { } else if (headRecord[0] == "Tutorial") {
final Iterable json = jsonDecode(headRecord[1]); final Iterable json = jsonDecode(headRecord[1]);
final List<Tutorial> tutorials = json.map((tutorial) => Tutorial.fromJson(tutorial)).toList(); final List<Tutorial> tutorials = json.map((tutorial) => Tutorial.fromJson(tutorial)).toList();
print("Tutorial: $tutorials");
Cache().setTutorials(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);
} }
}); });

View File

@ -1,5 +1,6 @@
import 'dart:io'; 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_language.dart';
import 'package:aitrainer_app/util/app_localization.dart'; import 'package:aitrainer_app/util/app_localization.dart';
import 'package:aitrainer_app/service/api.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/service/package_service.dart';
import 'package:aitrainer_app/util/purchases.dart'; import 'package:aitrainer_app/util/purchases.dart';
import 'package:devicelocale/devicelocale.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/services.dart';
import 'package:flutter_app_badger/flutter_app_badger.dart'; import 'package:flutter_app_badger/flutter_app_badger.dart';
import 'package:package_info/package_info.dart'; import 'package:package_info/package_info.dart';

View File

@ -4,11 +4,13 @@ import 'package:aitrainer_app/service/logging.dart';
import 'package:aitrainer_app/service/tracking_service.dart'; import 'package:aitrainer_app/service/tracking_service.dart';
import 'package:aitrainer_app/util/enums.dart'; import 'package:aitrainer_app/util/enums.dart';
import 'package:aitrainer_app/model/tracking.dart' as model; import 'package:aitrainer_app/model/tracking.dart' as model;
import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:flurry/flurry.dart'; import 'package:flurry/flurry.dart';
import 'package:flutter_uxcam/flutter_uxcam.dart'; import 'package:flutter_uxcam/flutter_uxcam.dart';
class Track with Logging { class Track with Logging {
static final Track _singleton = Track._internal(); static final Track _singleton = Track._internal();
static FirebaseAnalytics analytics = FirebaseAnalytics();
factory Track() { factory Track() {
return _singleton; return _singleton;
@ -22,6 +24,7 @@ class Track with Logging {
// Smartlook.setGlobalEventProperty(event.toString(), eventValue, false); // Smartlook.setGlobalEventProperty(event.toString(), eventValue, false);
FlutterUxcam.logEventWithProperties(event.enumToString(), {"value": eventValue}); FlutterUxcam.logEventWithProperties(event.enumToString(), {"value": eventValue});
model.Tracking tracking = model.Tracking(); model.Tracking tracking = model.Tracking();
analytics.logEvent(name: event.enumToString(), parameters: {"value": eventValue});
tracking.customerId = Cache().userLoggedIn == null ? 0 : Cache().userLoggedIn!.customerId!; tracking.customerId = Cache().userLoggedIn == null ? 0 : Cache().userLoggedIn!.customerId!;
tracking.event = event.enumToString(); tracking.event = event.enumToString();
if (eventValue.isNotEmpty) { if (eventValue.isNotEmpty) {

View File

@ -2,6 +2,7 @@ import 'dart:collection';
import 'package:aitrainer_app/bloc/exercise_control/exercise_control_bloc.dart'; 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/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/library/custom_icon_icons.dart';
import 'package:aitrainer_app/util/app_language.dart'; import 'package:aitrainer_app/util/app_language.dart';
import 'package:aitrainer_app/model/cache.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:"); String title = (step + 1).toString() + "/4 " + t("Control Exercise:");
LinkedHashMap args = LinkedHashMap(); LinkedHashMap args = LinkedHashMap();
final TutorialBloc tutorialBloc = BlocProvider.of<TutorialBloc>(context);
List<Widget> listWidgets = [ List<Widget> listWidgets = [
Text( Text(
@ -332,13 +334,18 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
primary: Colors.white, primary: Colors.white,
onSurface: Colors.blueAccent, onSurface: Colors.blueAccent,
), ),
onPressed: () => { onPressed: () {
exerciseBloc.add(ExerciseControlSubmit(step: step)), if (tutorialBloc.isActive) {
if (step == 3) if (!tutorialBloc.checkAction("Save")) {
{ return;
Navigator.of(context).pop(), }
args['exerciseRepository'] = exerciseBloc.exerciseRepository, }
Navigator.of(context).pushNamed('evaluationPage', arguments: args)
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 child: step == exerciseBloc.step

View File

@ -1,4 +1,5 @@
import 'package:aitrainer_app/bloc/sales/sales_bloc.dart'; 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/service/logging.dart';
import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/widgets/app_bar_min.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:aitrainer_app/widgets/sales_button.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.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:google_fonts/google_fonts.dart';
import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.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()), create: (context) => SalesBloc()..add(SalesLoad()),
child: BlocConsumer<SalesBloc, SalesState>(listener: (context, state) { child: BlocConsumer<SalesBloc, SalesState>(listener: (context, state) {
if (state is SalesError) { if (state is SalesError) {
log("Error: " + state.message);
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar(backgroundColor: Colors.orange, content: Text(t(state.message), style: TextStyle(color: Colors.white)))); SnackBar(backgroundColor: Colors.orange, content: Text(t(state.message), style: TextStyle(color: Colors.white))));
} else if (state is SalesSuccessful) { } else if (state is SalesSuccessful) {
@ -57,6 +59,9 @@ class SalesPage extends StatelessWidget with Trans, Logging {
} }
Widget salesWidget(SalesBloc bloc) { Widget salesWidget(SalesBloc bloc) {
final salesText = bloc.salesText != null ? bloc.salesText! : "";
final String html = salesText;
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
image: DecorationImage( image: DecorationImage(
@ -68,55 +73,144 @@ class SalesPage extends StatelessWidget with Trans, Logging {
child: CustomScrollView(scrollDirection: Axis.vertical, slivers: [ child: CustomScrollView(scrollDirection: Axis.vertical, slivers: [
SliverList( SliverList(
delegate: SliverChildListDelegate([ delegate: SliverChildListDelegate([
Divider(), Html(
Container( data: html,
padding: EdgeInsets.only(left: 65, right: 65), //Optional parameters:
child: Text(t("Unleash Your Development Now!"), style: {
textAlign: TextAlign.center, "p": Style(
maxLines: 4,
softWrap: true,
style: GoogleFonts.archivoBlack(
fontSize: 30,
color: Colors.white, color: Colors.white,
shadows: <Shadow>[ 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,
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( Shadow(
offset: Offset(5.0, 5.0), offset: Offset(5.0, 5.0),
blurRadius: 12.0, blurRadius: 12.0,
color: Colors.black54, 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,
), ),
])), },
SliverGrid(
delegate: SliverChildListDelegate(getButtons(bloc)),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
childAspectRatio: 0.55,
), ),
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),
],
), ),
SliverList(
delegate: SliverChildListDelegate([ 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]!,
],
),
SizedBox( SizedBox(
height: 30, 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> getButtons(SalesBloc bloc) {
List<Widget> buttons = []; List<Widget> buttons = [];

View File

@ -139,7 +139,7 @@ class SettingsPage extends StatelessWidget with Trans {
final TutorialBloc tutorialBloc = BlocProvider.of<TutorialBloc>(context); final TutorialBloc tutorialBloc = BlocProvider.of<TutorialBloc>(context);
return ListTile( return ListTile(
leading: Icon(CustomIcon.question_circle), leading: Icon(CustomIcon.question_circle),
subtitle: Text("Activating the basic tutorial"), subtitle: Text(t("Activating the basic tutorial")),
title: ToggleSwitch( title: ToggleSwitch(
minWidth: 120.0, minWidth: 120.0,
minHeight: 30.0, minHeight: 30.0,
@ -151,7 +151,15 @@ class SettingsPage extends StatelessWidget with Trans {
inactiveFgColor: Colors.grey[900], inactiveFgColor: Colors.grey[900],
labels: [t('Basic Tutorial'), t('Activate')], labels: [t('Basic Tutorial'), t('Activate')],
onToggle: (index) { 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()); tutorialBloc.add(TutorialStart());
}, },
), ),

View File

@ -9,6 +9,7 @@ import 'package:aitrainer_app/model/workout_menu_tree.dart';
import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/widgets/app_bar.dart'; import 'package:aitrainer_app/widgets/app_bar.dart';
import 'package:aitrainer_app/widgets/dialog_common.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:aitrainer_app/widgets/menu_image.dart';
import 'package:carousel_slider/carousel_slider.dart'; import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
@ -190,12 +191,9 @@ class TestSetEdit extends StatelessWidget with Trans {
context: context, context: context,
barrierDismissible: false, barrierDismissible: false,
builder: (BuildContext context) { builder: (BuildContext context) {
return DialogCommon( return DialogHTML(
title: bloc.templateNameTranslation, title: bloc.templateNameTranslation,
descriptions: bloc.templateDescription, htmlData: bloc.templateDescription,
text: "OK",
onTap: () => {Navigator.of(context).pop()},
onCancel: () => {Navigator.of(context).pop()},
); );
}), }),
child: Icon( child: Icon(

View File

@ -67,10 +67,17 @@ class _MenuPageWidgetState extends State<MenuPageWidget> with Trans, Logging {
} }
Future runDelayedEvent() async { Future runDelayedEvent() async {
print("runDelayedEvent start");
bool isFirst = false; bool isFirst = false;
await Future.delayed(Duration(milliseconds: 600), () async { await Future.delayed(Duration(milliseconds: 600), () async {
if (tutorialBloc.isActive == false) { 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"); print("Activate tutorial");
tutorialBloc.canActivate = true; tutorialBloc.canActivate = true;
tutorialBloc.isActive = true; tutorialBloc.isActive = true;
@ -79,6 +86,7 @@ class _MenuPageWidgetState extends State<MenuPageWidget> with Trans, Logging {
tutorialBloc.init(); tutorialBloc.init();
isFirst = true; isFirst = true;
} }
}
}); });
final bool canActivate = tutorialBloc.activateTutorial(); final bool canActivate = tutorialBloc.activateTutorial();
if (canActivate) { if (canActivate) {
@ -351,6 +359,7 @@ class _MenuPageWidgetState extends State<MenuPageWidget> with Trans, Logging {
void menuClick(WorkoutMenuTree workoutTree, MenuBloc menuBloc) { void menuClick(WorkoutMenuTree workoutTree, MenuBloc menuBloc) {
if (tutorialBloc.isActive) { if (tutorialBloc.isActive) {
final String checkText = workoutTree.nameEnglish; final String checkText = workoutTree.nameEnglish;
print("Click: tutorial is active $checkText");
if (!tutorialBloc.checkAction(checkText)) { if (!tutorialBloc.checkAction(checkText)) {
return; return;
} }

View File

@ -66,7 +66,8 @@ class SalesButton extends StatelessWidget {
fontSize: 1, fontSize: 1,
)), )),
child: Container( child: Container(
child: Center( child: Text(
"ho") /* Center(
child: Column( child: Column(
children: [ children: [
Divider( Divider(
@ -92,7 +93,8 @@ class SalesButton extends StatelessWidget {
child: Text(desc4!, maxLines: 2, style: GoogleFonts.inter(fontSize: 10, color: Colors.red[800]))) child: Text(desc4!, maxLines: 2, style: GoogleFonts.inter(fontSize: 10, color: Colors.red[800])))
], ],
), ),
)), ) */
),
))); )));
} }
} }

View File

@ -40,10 +40,13 @@ class TutorialWidget with Trans, Logging {
area = bloc.action!.showBubble == true area = bloc.action!.showBubble == true
? Rect.fromLTWH(targetGlobalCenter.dx - bloc.action!.bubbleX, targetGlobalCenter.dy - bloc.action!.bubbleY, ? Rect.fromLTWH(targetGlobalCenter.dx - bloc.action!.bubbleX, targetGlobalCenter.dy - bloc.action!.bubbleY,
bloc.action!.bubbleWidth.toDouble(), bloc.action!.bubbleHeight.toDouble()) bloc.action!.bubbleWidth.toDouble(), bloc.action!.bubbleHeight.toDouble())
//? Rect.fromLTWH(targetGlobalCenter.dx - 60, targetGlobalCenter.dy + 120, 420, 320)
: null; : null;
} }
final double mediaSize = MediaQuery.of(context).size.width; 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; double fontSize = 14;
if (mediaSize > 400) { if (mediaSize > 400) {
@ -51,8 +54,16 @@ class TutorialWidget with Trans, Logging {
} else if (mediaSize < 375) { } else if (mediaSize < 375) {
fontSize = 13; 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( tooltip = SuperTooltip(
top: bloc.top, top: calculatedTop,
left: bloc.left, left: bloc.left,
backgroundColor: Colors.black.withOpacity(0.7), backgroundColor: Colors.black.withOpacity(0.7),
popupDirection: bloc.action == null || bloc.action!.direction == "up" ? TooltipDirection.up : TooltipDirection.down, popupDirection: bloc.action == null || bloc.action!.direction == "up" ? TooltipDirection.up : TooltipDirection.down,

View File

@ -15,6 +15,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.0" 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: apple_sign_in:
dependency: "direct main" dependency: "direct main"
description: description:
@ -315,49 +322,49 @@ packages:
name: firebase_analytics name: firebase_analytics
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "8.0.0-dev.2" version: "8.0.2"
firebase_analytics_platform_interface: firebase_analytics_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: firebase_analytics_platform_interface name: firebase_analytics_platform_interface
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.0-dev.0" version: "2.0.0"
firebase_analytics_web: firebase_analytics_web:
dependency: transitive dependency: transitive
description: description:
name: firebase_analytics_web name: firebase_analytics_web
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.3.0-dev.0" version: "0.3.0"
firebase_auth: firebase_auth:
dependency: "direct main" dependency: "direct main"
description: description:
name: firebase_auth name: firebase_auth
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.3" version: "1.1.2"
firebase_auth_platform_interface: firebase_auth_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: firebase_auth_platform_interface name: firebase_auth_platform_interface
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.0.2" version: "4.2.0"
firebase_auth_web: firebase_auth_web:
dependency: transitive dependency: transitive
description: description:
name: firebase_auth_web name: firebase_auth_web
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.5" version: "1.1.0"
firebase_core: firebase_core:
dependency: "direct main" dependency: "direct main"
description: description:
name: firebase_core name: firebase_core
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.3" version: "1.1.0"
firebase_core_platform_interface: firebase_core_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -378,21 +385,35 @@ packages:
name: firebase_messaging name: firebase_messaging
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "9.1.1" version: "9.1.3"
firebase_messaging_platform_interface: firebase_messaging_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: firebase_messaging_platform_interface name: firebase_messaging_platform_interface
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.1" version: "2.1.3"
firebase_messaging_web: firebase_messaging_web:
dependency: transitive dependency: transitive
description: description:
name: firebase_messaging_web name: firebase_messaging_web
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted 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: fixnum:
dependency: transitive dependency: transitive
description: description:
@ -419,6 +440,13 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" 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: flutter_bloc:
dependency: "direct main" dependency: "direct main"
description: description:
@ -447,6 +475,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.4.1+1" 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: flutter_html:
dependency: "direct main" dependency: "direct main"
description: description:
@ -506,6 +541,13 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" 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: flutter_web_plugins:
dependency: transitive dependency: transitive
description: flutter description: flutter
@ -707,6 +749,48 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.0" 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: path:
dependency: transitive dependency: transitive
description: description:
@ -876,12 +960,19 @@ packages:
source: hosted source: hosted
version: "0.26.0" version: "0.26.0"
sentry: sentry:
dependency: "direct main" dependency: transitive
description: description:
name: sentry name: sentry
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "5.0.0" 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: shared_preferences:
dependency: "direct dev" dependency: "direct dev"
description: description:
@ -957,13 +1048,6 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.99" version: "0.0.99"
smartlook:
dependency: "direct main"
description:
name: smartlook
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.7"
source_gen: source_gen:
dependency: transitive dependency: transitive
description: description:

View File

@ -58,11 +58,13 @@ dependencies:
flutter_app_badger: ^1.2.0 flutter_app_badger: ^1.2.0
#super_tooltip: ^1.0.1 #super_tooltip: ^1.0.1
firebase_core: ^1.0.3 firebase_core: ^1.1.0
firebase_analytics: ^8.0.0-dev.2 firebase_analytics: ^8.0.2
firebase_messaging: ^9.1.1 firebase_messaging: ^9.1.3
flutter_local_notifications: ^5.0.0 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 flutter_facebook_auth: ^3.3.2
google_sign_in: ^5.0.1 google_sign_in: ^5.0.1
apple_sign_in: ^0.1.0 apple_sign_in: ^0.1.0