WT1.1.3 logo change, error fixes

This commit is contained in:
bossanyit 2021-01-07 22:40:59 +01:00
parent 234a2f10e9
commit e6d0543021
119 changed files with 3581 additions and 1179 deletions

View File

@ -2,5 +2,5 @@
The WorkoutTest Mobile Application
Prototye 1.1.2f
live 1.1.3

Binary file not shown.

Before

Width:  |  Height:  |  Size: 544 B

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 B

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 721 B

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 23 KiB

1432
asset/data/menu_live.sql Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 307 KiB

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
asset/icon/icon0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 KiB

BIN
asset/icon/icon1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 375 KiB

BIN
asset/image/merleg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -11,6 +11,8 @@
"Change Language": "Change Language",
"Password too short": "Password too short (at least 6 characters)",
"Please type an email address": "Please type an email address",
"Exception: Please accept our data policy":"Please accept our data policy",
"Please accept our data protection policy. For more information please click on 'Privacy'":"Please accept our data protection policy. For more information please click on 'Privacy'",
"SignUp": "SignUp",
"Privacy": "Privacy",
"Change App Language": "Change App Language",
@ -21,11 +23,10 @@
"Settings": "Settings",
"Profile": "Profile",
"Selected Language": "Selected Language",
"gdpr_text": "",
"Please log in": "Please log in",
"Exception: Customer does not exist or the password is wrong": "The email does not exist or the password is wrong",
"Customer exists": "The email address has been registered already",
"Exception: Customer exists": "The email address has been registered already",
"There is an error: during registration:": "There is an error: during registration:",
"Please select an exercise": "Please select an exercise",
"Cardio": "Cardio",
@ -55,6 +56,9 @@
"Save": "Save",
"Delete": "Delete",
"Endurance_desc":"",
"OneRepMax_desc":"",
"Name": "Name",
"Exercise": "Exercise",
"Quantity": "Quantity",
@ -113,20 +117,26 @@
"Endomorph": "Endomorph",
"Mesomorph": "Mesomorph",
"Ectomorph_desc": "Ectomorf",
"Endomorph_desc":"Endomorf",
"Mesomorph_desc":"Mezomorf",
"Description": "Description",
"Make your first test": "Make your first test",
"finished": "finished",
"Why do you need Exercise Control?" : "Why do you need Exercise Control?",
"Why do you need Exercise Control?" : "Why do you need Test Exercise?",
"Your 1RM:":"Your 1RM:",
"Your 1RM:":"Your One-Rep-Max:",
"Your Real 1RM:":"Your Real 1RM:",
"Check":"Check",
"Control Exercise:": "Control Exercise:",
"Control Exercise:": "Test Exercise:",
"controlexercise_desc":"",
"Summary of your test":"Summary of your test",
"Test":"Test",
"1st Control": "1st Control",
"2nd Control": "2nd Control",
"3rd Control": "3rd Control",
"1st Control": "1st Test Exercise",
"2nd Control": "2nd Test Exercise",
"3rd Control": "3rd Test Exercise",
"My Development":"Development",
"My Training Plan":"Training Plan",
@ -137,6 +147,7 @@
"Save The Exercise To The Exercise Plan": "Save The Exercise To The Exercise Plan",
"The number of the serie done with":"The number of the serie done with",
"The number of the repeats of one serie":"The number of the repeats of one serie",
"reps":"reps",
"1. Chest": "1. Chest",
"2. Biceps": "2. Biceps",
@ -165,7 +176,10 @@
"Here you see you development in the last period." : "Here you see your development in the last period.",
"Sum Of Mass":"Sum Of Mass",
"Percent": "Percent",
"One Max Rep": "One Max Rep",
"One Rep Max": "One Rep Max",
"OneRepMax": "One Rep Max",
"onerepmax_desc": "",
"Detailed": "Detailed",
"Weekly": "Weekly",
"Monthly": "Monthly",
@ -179,7 +193,7 @@
"Custom Exercise Plan": "Custom Exercise Plan",
"Select manually the exercises what you would like to have in your plan. At the end don't forget to save.": "Select manually the exercises what you would like to have in your plan. At the end don't forget to save.",
"In this list you will find all your executed exercises grouped by the date.": "In this list you will find all your executed exercises grouped by the date.",
"In this list you will find all your executed exercises grouped by the date.": "In this list you can find all your completed exercises sorted by the date.",
"Persistence!": "Persistence!",
"Greetings!": "Greetings!",
@ -211,11 +225,19 @@
"I forgot the password":"I forgot the password",
"Exception: Instance of 'NotFoundException'": "Customer with the email not found. Please register or reset your password",
"Customer does not exist or the password is wrong": "Customer does not exist or the password is wrong",
"The email does not exist or the password is wrong": "Customer does not exist or the password is wrong",
"Exception: You have a previous Facebook login operation in progress":"You have a previous Facebook login operation in progress",
"Exception: Facebook login was not successful":"Facebook login was not successful",
"Exception: Facebook login cancelled":"Facebook login cancelled",
"Exception: Facebook login failed":"Facebook login failed",
"More »": "More »",
"Done": "Done",
"Height":"Height",
"Actual Height":"Actual Height",
"Actual Weight":"Actual Weight",
"Actual Height":"Height",
"Actual Weight":"Weight",
"Based on your weight and height your goal for BMI and weight:":"Based on your weight and height your goal for BMI and weight:",
"Body Mass Index":"Body Mass Index",
"Basal Metabolic Rate":"Basal Metabolic Rate",
@ -263,7 +285,11 @@
"feature is reachable after you finished":"feature is reachable after you finished",
"100% test circles":"100% test circles",
"Enjoy also this premium fetaure to show all old evaluation data of your successful exercises.":"Enjoy also this premium fetaure to show all old evaluation data of your successful exercises."
"Enjoy also this premium fetaure to show all old evaluation data of your successful exercises.":"Enjoy also this premium fetaure to show all old evaluation data of your successful exercises.",
"Please define your Exercise Plan":"Please define your Exercise Plan",
"Go to: 'Training Plan' - 'Edit My Custom Plan'":"Go to: 'Training Plan' - 'Edit My Custom Plan'",
"Jump there »":"Jump there »"
}

View File

@ -12,6 +12,8 @@
"Password too short": "A jelszó min. 6 karakterből álljon",
"Please type an email address": "Kérlek írj be egy email címet",
"SignUp": "Regisztráció",
"Exception: Please accept our data policy":"Kérlek fogadd el az adatvédelmi szabályzatunkat",
"Please accept our data protection policy. For more information please click on 'Privacy'":"Kérlek fogadd el az adatvédelmi szabályzatunkat. További információkért kattints az 'Adatkezelés' linkre.",
"Privacy": "Adatkezelés",
"Change App Language": "Nyelvválasztás",
"English": "Angol",
@ -21,13 +23,19 @@
"Settings": "Beállítások",
"Profile": "Személyes adatok",
"Selected Language": "Választott nyelv",
"gdpr_text": "",
"Please log in": "Kérlek jelentkezz be",
"Exception: Customer does not exist or the password is wrong": "A felhasználónév nem létezik vagy a jelszó rossz.",
"Customer does not exist or the password is wrong": "A felhasználó nem létezik vagy a jelszó rossz.",
"The email does not exist or the password is wrong": "A felhasználó nem létezik vagy a jelszó rossz.",
"Exception: Facebook login was not successful": "Facebook bejelentkezés sikertelen",
"Exception: You have a previous Facebook login operation in progress":"Az előző bejelentkezés még folyamatban van.",
"Exception: Facebook login cancelled":"Facebook bejelentkezés megszakítva ",
"Exception: Facebook login failed":"Facebook bejelentkezés sikertelen",
"Please select an exercise": "Válassz ki egy gyakorlatot",
"There is an error: during registration:": "Hiba lépett fel a regisztráció során:",
"Customer exists": "Ez az email cím már regisztrálva van",
"Exception: Customer exists": "Ez az email cím már regisztrálva van",
"Cardio": "Kardió",
"400m": "400m",
"300m": "300m",
@ -60,6 +68,9 @@
"Execute the": "Hajtsd végre a(z)",
"set!":"sorozatot!",
"Endurance_desc":"<p>Erőállóképességi teszt lényege, ahogy az 1RM tesztnél is, hogy a Neked megfelelő SÚLY és ISMÉTLÉS számot tudjuk javasolni. </p><p>Nagyon fontos, hogy szabályosan és a kért ismétléssel dolgozz!</p><p> Ha a célod a hosszabb távú erő fenntartása, netán sportoló vagy, akkor feltétlen teszteld az erőállóképességi modulunkat is.</p><br/><h2>Miért az erőállóképesség?</h2><p>Javítja az izmok oxigén és tápanyagellátottságát és ezáltal képes leszel egyre nagyobb súlyok egyre hosszabbtávon való megmozgatására. Például egyre több fekvőtámaszra és húzódzkodásra. </p><p>Kevésbé tömegnövelő hatású, ámbár atlétikus és nagyon erős testalkatot kölcsönöz, ha hosszútávon gyakorlod.</p>",
"OneRepMax_desc":"<p>Az egy ismétléses maximum, vagy más néven 1RM ismerete számodra fontos lehet a Neked megfelelő SÚLY és ISMÉTLÉS kiszámításában. <p>Végezd el szabályosan(!) a tesztet, hogy a Neked legmegfelelőbb súlyokat és ismétléseket tudjuk javasolni a későbbiekben.</p> <p>Ha a célod az izom, vagy az erőnövelés, akkor feltétlen csináld meg az 1RM teszteket!</p><br/><h2>Mi az 1RM?</h2><p>Az a súly, amit egyetlen egyszer lennél képes szabályosan megmozgatni. Az egyszer szabályosan végrehajtott maximális súlyú gyakorlatból származtatjuk a céloknak megfelelő súly és ismétlésszámokat.</p>",
"Name": "Név",
"Exercise": "Gyakorlat",
"Quantity": "Mennyiség",
@ -113,16 +124,18 @@
"Endomorph":"Endomorf",
"Mesomorph":"Mezomorf",
"Ectomorph_desc": "<p>A Te testtípusod, ha:</p><ul><li>alapvetően vékony testalkat vagy, mint a hosszútávfutók</li><li>hosszú végtagok, keskenyebb vállak</li><li>nehezen tudsz izomtömeget növelni</li><li>Mellkas és a derék szinte egyforma szélességű</li><li>Könnyen elveszíted a felszedett izmot</li><li>Meglehetősen alacsony a testzsírszázalék jellemez</li></ul><p>Természetesen, mint a többi testtípusnál itt sem beszélhetünk 100%-os egyezésről, de fontos a választás a személyre szabottság érdekében. Előfordul, hogy egy ectomorph zsírfelesleggel is rendelkezik. Ekkor az ízületek vékonysága és az izomzat viselkedése a döntő szempont.</p>",
"Endomorph_desc":"<p>A te testtípusod, ha úgy érzed, hogy a testalkatod az ektomorf szöges ellentéte.</p><ul><li>Ha az erős megjelenésű testalkatod ellenére kevésbé érvényesülnek vizuálisan az izmok.</li><li>Ha nehezen szabadulsz meg a fölöslegtől</li><li>Nagyon könnyen erősödsz</li><li>Széles nagy térfogatú a bordakosár</li><li>Vastag erős ízületeid vannak</li><li>Ha a csípőben vagy erősebb</li></ul><p>Itt sem beszélhetünk 100%-os egyezésről, de fontos a személyre szabottság miatt. Előfordul, hogy egy endomorf nehezen különböztethető meg a mezomorftól. Ekkor vedd figyelembe a bordakosár méretét és a derekat. Oldalról egy mezomorf laposabb mellkassal, hassal rendelkezhet az eredendően „erős” tömöttebb, netán elhízott megjelenés a döntő szempont. Minden alma és körte forma ide sorolható.</p>",
"Mesomorph_desc":"<p>A testtípusod, ha</p><ul><li>Sportos testalkat vagy, mint egy sprinter, úszó vagy tornász</li><li>Széles kulcscsontok és vállak</li><li>Szimmetrikus felépítés</li><li>Keskeny csípő és sportos keskeny derék</li><li>alapvetően vékonyabb ízületek, de erős csontok jellemeznek</li><li>izmosabbak, mint az ektomorfok</li><li>Gyorsan izmosodsz</li><li>vastagabbak a csontok és az ízületek az ekromorfhoz képest</li><li>mellkas a derékhez képest széles</li><li>erősebb vádli és alkar</li></ul><p>Természetesen, mint a többi testtípusnál itt sem beszélhetünk 100%-os egyezésről, de fontos a személyre szabottság miatt. Előfordul, hogy egy mezomorf zsírfelesleggel is rendelkezik. Ekkor a csípőcsont/mellkas arány és az izomzat viselkedése a döntő szempont.</p>",
"Description": "Leírás",
"Make your first test": "Végezd el az első tesztet",
"finished": "végrehajtva",
"Why do you need Exercise Control?": "Miért szükséges a kontrollgyakorlat?",
"Why do you need Exercise Control?": "Miért szükséges a tesztgyakorlat?",
"Your 1RM:":"Maxerőd:",
"Your Real 1RM:":"Ellenőrzött maxerő:",
"Check":"Ellenőrzés",
"1st Control Exercise:": "1. kontrollgyakorlat:",
"2nd Control Exercise:": "2. kontrollgyakorlat:",
"3rd Control Exercise:": "3. kontrollgyakorlat:",
"My Development":"Fejlődésem",
"My Training Plan":"Edzéstervem",
@ -162,7 +175,10 @@
"Here you see you development in the last period." : "Itt az izomcsoportok fejlődését látod az elmúlt időszakban. A pontos képhez három diagram közül választhatsz: 'Gyakorlat össztömeg', 'Maxerő' és 'Százalékos fejlődés', illetv választhatsz 4 különböző időszaki bontásból is: 'Részletes', 'Heti', 'Havi', 'Éves",
"Sum Of Mass":"Össztömeg",
"Percent": "Százalék",
"One Max Rep": "Maxerő",
"One Rep Max": "Maxerő",
"OneRepMax": "Maxerő",
"Detailed": "Részletes",
"Weekly": "Heti",
"Monthly": "Havi",
@ -202,11 +218,13 @@
"Are you sure to logout?": "Biztos, hogy kijelentkezel?",
"hu_with": "-mal",
"Control Exercise:": "Gyakorlat végrehajtása:",
"Control Exercise:": "Tesztgyakorlat végrehajtása:",
"controlexercise_desc":"<h2>Miért csináld meg a tesztgyakorlatokat?</h2><p>Ha a leírtak szerint és szabályos végrehajtással végzed a tesztgyakorlatokat, akkor pontos képet ad az applikáció az izomerő és erőállóképesség állapotodról, ami alapján a későbbiekben testreszabottan tudod végezni a gyakorlatokat. </p><p>Ez mit jelent? Azt, hogy meghatározzuk számodra a célod eléréséhez megfelelő súlyt és a hozzátartozó ismétlésszámot, ami a siker kulcsa. Sőt! Az appon belül az egyéni edzésterv menüben össze is állíthatod magadnak a saját edzésnapodat.</p><p>Ne feledd! A teszt csak a jelen állapotodról ad visszaigazolást. Ha folyamatosan fejlődni szeretnél 3-6 hetente érdemes visszalátogatnod az 1RM vagy Erőállóképességi tesztekbe. Hajrá!</p>",
"Test":"Teszt",
"1st Control": "1. kontrollgyakorlat",
"2nd Control": "2. kontrollgyakorlat",
"3rd Control": "3. kontrollgyakorlat",
"1st Control": "1. tesztgyakorlat",
"2nd Control": "2. tesztgyakorlat",
"3rd Control": "3. tesztgyakorlat",
"Summary of your test":"A teszt összefoglalása:",
"Are you sure to delete this exercise?": "Biztos, hogy törlöd a gyakorlatot?",
@ -251,6 +269,7 @@
"Average BPM":"Átl pulzus",
"Fatburn %":"Zsírégetés %",
"Health Data Summary":"Egészségadatok összefoglalás",
"reps":"ism.",
"Congratulation!":"Gratulálok!",
"You have achieved to first 100% test-round!":"Teljesítetted az első 100%-os tesztköröd!",
@ -264,8 +283,10 @@
"feature is reachable after you finished":"funkció elérhető számodra, miután teljesítetted",
"100% test circles":"100%-os teszt-köröd",
"Enjoy also this premium fetaure to show all old evaluation data of your successful exercises.":"Élvezd ezt a prémium funkciót is, amely megjeleníti a korábbi gyakorlatok teljes kiértékelését"
"Enjoy also this premium fetaure to show all old evaluation data of your successful exercises.":"Élvezd ezt a prémium funkciót is, amely megjeleníti a korábbi gyakorlatok teljes kiértékelését",
"Please define your Exercise Plan":"Kérlek készíts edzéstervet!",
"Go to: 'Training Plan' - 'Edit My Custom Plan'":"Menj a 'Edzéstervem' - 'Egyéni edzésterv' menübe",
"Jump there »":"Vigyél oda »"
}

View File

@ -1,8 +1,16 @@
PODS:
- device_info (0.0.1):
- Flutter
- devicelocale (0.0.1):
- Flutter
- FBSDKCoreKit (8.2.0):
- FBSDKCoreKit/Basics (= 8.2.0)
- FBSDKCoreKit/Core (= 8.2.0)
- FBSDKCoreKit/Basics (8.2.0)
- FBSDKCoreKit/Core (8.2.0):
- FBSDKCoreKit/Basics
- FBSDKLoginKit (8.2.0):
- FBSDKLoginKit/Login (= 8.2.0)
- FBSDKLoginKit/Login (8.2.0):
- FBSDKCoreKit (~> 8.2.0)
- Firebase/Auth (6.33.0):
- Firebase/CoreOnly
- FirebaseAuth (~> 6.9.2)
@ -61,6 +69,10 @@ PODS:
- Flutter
- Flurry-iOS-SDK/FlurrySDK (11.1.1)
- Flutter (1.0.0)
- flutter_facebook_auth (1.0.0):
- FBSDKCoreKit (~> 8.2.0)
- FBSDKLoginKit (~> 8.2.0)
- Flutter
- flutter_inapp_purchase (0.0.1):
- Flutter
- flutter_keyboard_visibility (0.0.1):
@ -88,8 +100,6 @@ PODS:
- GoogleUtilities/UserDefaults (6.7.2):
- GoogleUtilities/Logger
- GTMSessionFetcher/Core (1.5.0)
- health (1.0.1):
- Flutter
- nanopb (1.30906.0):
- nanopb/decode (= 1.30906.0)
- nanopb/encode (= 1.30906.0)
@ -104,24 +114,34 @@ PODS:
- sqflite (0.0.2):
- Flutter
- FMDB (>= 2.7.5)
- video_player (0.0.1):
- Flutter
- wakelock (0.0.1):
- Flutter
- webview_flutter (0.0.1):
- Flutter
DEPENDENCIES:
- device_info (from `.symlinks/plugins/device_info/ios`)
- devicelocale (from `.symlinks/plugins/devicelocale/ios`)
- firebase_auth (from `.symlinks/plugins/firebase_auth/ios`)
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
- flurry (from `.symlinks/plugins/flurry/ios`)
- Flutter (from `Flutter`)
- flutter_facebook_auth (from `.symlinks/plugins/flutter_facebook_auth/ios`)
- flutter_inapp_purchase (from `.symlinks/plugins/flutter_inapp_purchase/ios`)
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
- health (from `.symlinks/plugins/health/ios`)
- path_provider (from `.symlinks/plugins/path_provider/ios`)
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
- video_player (from `.symlinks/plugins/video_player/ios`)
- wakelock (from `.symlinks/plugins/wakelock/ios`)
- webview_flutter (from `.symlinks/plugins/webview_flutter/ios`)
SPEC REPOS:
trunk:
- FBSDKCoreKit
- FBSDKLoginKit
- Firebase
- FirebaseAuth
- FirebaseCore
@ -139,8 +159,6 @@ SPEC REPOS:
- Protobuf
EXTERNAL SOURCES:
device_info:
:path: ".symlinks/plugins/device_info/ios"
devicelocale:
:path: ".symlinks/plugins/devicelocale/ios"
firebase_auth:
@ -153,22 +171,29 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/flurry/ios"
Flutter:
:path: Flutter
flutter_facebook_auth:
:path: ".symlinks/plugins/flutter_facebook_auth/ios"
flutter_inapp_purchase:
:path: ".symlinks/plugins/flutter_inapp_purchase/ios"
flutter_keyboard_visibility:
:path: ".symlinks/plugins/flutter_keyboard_visibility/ios"
health:
:path: ".symlinks/plugins/health/ios"
path_provider:
:path: ".symlinks/plugins/path_provider/ios"
shared_preferences:
:path: ".symlinks/plugins/shared_preferences/ios"
sqflite:
:path: ".symlinks/plugins/sqflite/ios"
video_player:
:path: ".symlinks/plugins/video_player/ios"
wakelock:
:path: ".symlinks/plugins/wakelock/ios"
webview_flutter:
:path: ".symlinks/plugins/webview_flutter/ios"
SPEC CHECKSUMS:
device_info: d7d233b645a32c40dfdc212de5cf646ca482f175
devicelocale: feebbe5e7a30adb8c4f83185de1b50ff19b44f00
FBSDKCoreKit: 4afd6ff53d8133a433dbcda44451c9498f8c6ce4
FBSDKLoginKit: 7181765f2524d7ebf82d9629066c8e6caafc99d0
Firebase: 8db6f2d1b2c5e2984efba4949a145875a8f65fe5
firebase_auth: d5159db3873478d1ac839af7b10d2f831516136a
firebase_core: 5d6a02f3d85acd5f8321c2d6d62877626a670659
@ -182,19 +207,22 @@ SPEC CHECKSUMS:
flurry: 15b01f664ab1367c62b50291541ea7f78ca85aad
Flurry-iOS-SDK: 8f3f7fce27177002f15f145eede88dc1b9ac0cd0
Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
flutter_facebook_auth: bad08a3d465e7b7ba9d8468a9dc7df3f69c136b8
flutter_inapp_purchase: 5c6a1ac3f11b11d0c8c0321c0c41c1f05805e4c8
flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
GoogleDataTransport: f56af7caa4ed338dc8e138a5d7c5973e66440833
GoogleUtilities: 7f2f5a07f888cdb145101d6042bc4422f57e70b3
GTMSessionFetcher: b3503b20a988c4e20cc189aa798fd18220133f52
health: 44840ad4328aa5586e77bef289898bfed644a81c
nanopb: 59317e09cf1f1a0af72f12af412d54edf52603fc
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
PromisesObjC: 8c196f5a328c2cba3e74624585467a557dcb482f
Protobuf: 3dac39b34a08151c6d949560efe3f86134a3f748
shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
video_player: 9cc823b1d9da7e8427ee591e8438bfbcde500e6e
wakelock: bfc7955c418d0db797614075aabbc58a39ab5107
webview_flutter: d2b4d6c66968ad042ad94cbb791f5b72b4678a96
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c

View File

@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 51;
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
@ -15,7 +15,6 @@
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
BB69292B2521AF45001FBA4C /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BB69292A2521AF45001FBA4C /* Launch Screen.storyboard */; };
BB81345024BB4BE10078D9A4 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB81344F24BB4BE10078D9A4 /* GoogleService-Info.plist */; };
BBDBEBB825862170006762F6 /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BBDBEBB725862170006762F6 /* HealthKit.framework */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@ -49,7 +48,6 @@
BB43773E2540715900D74BFA /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
BB69292A2521AF45001FBA4C /* Launch Screen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = "<group>"; };
BB81344F24BB4BE10078D9A4 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
BBDBEBB725862170006762F6 /* HealthKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = HealthKit.framework; path = System/Library/Frameworks/HealthKit.framework; sourceTree = SDKROOT; };
D5EDDC52125075FB9E21AD35 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
F39E6E227EB942E5663A6086 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -60,7 +58,6 @@
buildActionMask = 2147483647;
files = (
42B6B159AF35AFB6DE777DFB /* Pods_Runner.framework in Frameworks */,
BBDBEBB825862170006762F6 /* HealthKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -80,7 +77,6 @@
3ADC50290ED054951FAC1F56 /* Frameworks */ = {
isa = PBXGroup;
children = (
BBDBEBB725862170006762F6 /* HealthKit.framework */,
09BD889296C5C90D989820C8 /* Pods_Runner.framework */,
);
name = Frameworks;
@ -182,7 +178,7 @@
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 10.0";
compatibilityVersion = "Xcode 12.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
@ -366,7 +362,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 42;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = SFJJBDCU6Z;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@ -383,7 +379,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 1.1.0;
MARKETING_VERSION = 1.1.3;
PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@ -509,7 +505,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 42;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = SFJJBDCU6Z;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@ -526,7 +522,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 1.1.0;
MARKETING_VERSION = 1.1.3;
PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@ -544,7 +540,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 42;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = SFJJBDCU6Z;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@ -561,7 +557,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 1.1.0;
MARKETING_VERSION = 1.1.3;
PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 307 KiB

After

Width:  |  Height:  |  Size: 422 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 973 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because one or more lines are too long

View File

@ -46,10 +46,6 @@
<string>10.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSHealthShareUsageDescription</key>
<string>We will sync your data with the Apple Health app to give you better insights</string>
<key>NSHealthUpdateUsageDescription</key>
<string>We will sync your data with the Apple Health app to give you better insights</string>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>

View File

@ -4,11 +4,5 @@
<dict>
<key>aps-environment</key>
<string>development</string>
<key>com.apple.developer.healthkit</key>
<true/>
<key>com.apple.developer.healthkit.access</key>
<array>
<string>health-records</string>
</array>
</dict>
</plist>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 358 KiB

After

Width:  |  Height:  |  Size: 422 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 KiB

After

Width:  |  Height:  |  Size: 221 KiB

View File

@ -4,6 +4,7 @@ import 'package:flutter_form_bloc/flutter_form_bloc.dart';
class CustomExerciseFormBloc extends FormBloc<String, String> {
final ExerciseRepository exerciseRepository;
bool loading = false;
final quantityField = TextFieldBloc(
validators: [
FieldBlocValidators.required,
@ -66,10 +67,12 @@ class CustomExerciseFormBloc extends FormBloc<String, String> {
@override
void onSubmitting() async {
try {
loading = true;
emitLoading(progress: 30);
// Emit either Loaded or Error
emitSuccess(canSubmitAgain: false);
loading = false;
} on Exception catch (ex) {
emitFailure(failureResponse: ex.toString());
}

View File

@ -2,26 +2,30 @@ import 'dart:async';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/repository/customer_repository.dart';
import 'package:aitrainer_app/util/common.dart';
import 'package:aitrainer_app/util/trans.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:meta/meta.dart';
part 'customer_change_event.dart';
part 'customer_change_state.dart';
class CustomerChangeBloc extends Bloc<CustomerChangeEvent, CustomerChangeState> {
class CustomerChangeBloc extends Bloc<CustomerChangeEvent, CustomerChangeState> with Trans {
final CustomerRepository customerRepository;
final BuildContext context;
bool visiblePassword = false;
int year = 1990;
double weight = 60;
double height = 170;
CustomerChangeBloc({this.customerRepository}) : super(CustomerChangeInitial()) {
CustomerChangeBloc({this.customerRepository, this.context}) : super(CustomerChangeInitial()) {
year = this.customerRepository.customer.birthYear;
if (year == 0) {
year = 1990;
}
weight = this.customerRepository.getWeight();
height = this.customerRepository.getHeight();
weight = this.customerRepository.getWeight() == 0 ? 60 : this.customerRepository.getWeight();
height = this.customerRepository.getHeight() == 0 ? 170 : this.customerRepository.getHeight();
}
@override
@ -98,21 +102,24 @@ class CustomerChangeBloc extends Bloc<CustomerChangeEvent, CustomerChangeState>
}
String emailValidation(String email) {
bool emailValid = RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+").hasMatch(email);
return emailValid ? null : "Please type an email address";
String message = Common.emailValidation(email);
if (message != null) {
message = t(message);
}
return message;
}
String passwordValidation(String value) {
if (value == null || value.length == 0) {
return null;
String message = Common.passwordValidation(value);
if (message != null) {
message = t(message);
}
bool valid = 8 < value.length;
return valid ? null : "Password too short";
return message;
}
String nameValidation(String value) {
if (value == null || value.length == 0) {
return "Name too short";
return t("Name too short");
}
return null;
}

View File

@ -13,7 +13,6 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
final bool readonly;
final double percentToCalculate;
int step = 1;
final List<double> repeats = List();
double initialRM;
double unitQuantity;
@ -27,17 +26,13 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
@override
ExerciseControlBloc({this.exerciseRepository, this.readonly, this.percentToCalculate}) : super(ExerciseControlInitial()) {
firstUnitQuantity = exerciseRepository.exercise.unitQuantity;
firstQuantity = exerciseRepository.exercise.quantity;
repeats.add(firstUnitQuantity);
repeats.add(firstQuantity);
initialRM = this.calculate1RM(percent75: false);
unitQuantity = this.calculate1RM(percent75: true).roundToDouble();
quantity = percentToCalculate == 0.75 ? 12 : 30;
origQuantity = quantity;
exerciseRepository.setUnitQuantity(unitQuantity);
exerciseRepository.setQuantity(quantity);
}
@override
@ -48,31 +43,24 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
step = 1;
yield ExerciseControlReady();
} else if (event is ExerciseControlQuantityChange) {
yield ExerciseControlLoading();
//yield ExerciseControlLoading();
if (event.step == step) {
exerciseRepository.setQuantity(event.quantity);
quantity = event.quantity;
}
yield ExerciseControlReady();
//yield ExerciseControlReady();
} else if (event is ExerciseControlSubmit) {
yield ExerciseControlLoading();
if (event.step == step) {
step++;
scrollOffset = step * 200.0;
/* print("step " +
step.toString() +
" quantity " +
quantity.toString() +
" origQuantity: " +
origQuantity.toString() +
" scrollOffset: " +
scrollOffset.toString()); */
repeats.add(quantity);
scrollOffset = step * 400.0;
quantity = origQuantity;
exerciseRepository.end = DateTime.now();
await exerciseRepository.addExercise();
exerciseRepository.setQuantity(quantity);
exerciseRepository.exercise.exerciseId = null;
}
yield ExerciseControlReady();
}

View File

@ -15,6 +15,7 @@ class ExerciseExecutePlanBloc extends Bloc<ExerciseExecutePlanEvent, ExerciseExe
final WorkoutTreeRepository menuTreeRepository;
final ExercisePlanRepository exercisePlanRepository = ExercisePlanRepository();
int customerId;
int selectedNumber = 0;
@override
ExerciseExecutePlanBloc({this.menuTreeRepository}) : super(ExerciseByPlanStateInitial());
@ -32,6 +33,7 @@ class ExerciseExecutePlanBloc extends Bloc<ExerciseExecutePlanEvent, ExerciseExe
if (exercisePlanRepository.getExercisePlanDetailSize() > 0) {
if (exercisePlanRepository.getExercisePlanDetailByExerciseId(workoutTree.exerciseTypeId) != null) {
workoutTree.selected = true;
this.selectedNumber++;
}
}
});

View File

@ -55,6 +55,7 @@ class ExerciseExecutePlanAddBloc extends Bloc<ExerciseExecutePlanAddEvent, Exerc
try {
if (event is ExerciseExecutePlanAddLoad) {
yield ExerciseExecutePlanAddLoading();
Flurry.logEvent("ExecuteExercisePlanOpen");
yield ExerciseExecutePlanAddReady();
} else if (event is ExerciseExecutePlanAddChangeQuantity) {
yield ExerciseExecutePlanAddLoading();
@ -72,7 +73,7 @@ class ExerciseExecutePlanAddBloc extends Bloc<ExerciseExecutePlanAddEvent, Exerc
exerciseRepository.exercise.unit = workoutTree.exerciseType.unit;
workoutTree.executed = true;
await exerciseRepository.addExercise();
Flurry.logEvent("ExecuteExercisePlan");
Flurry.logEvent("ExecuteExercisePlanSave");
step++;
scrollOffset = step * 200.0;
planBloc.add(ExerciseByPlanLoad());

View File

@ -3,6 +3,7 @@ import 'package:aitrainer_app/model/exercise.dart';
import 'package:aitrainer_app/repository/exercise_repository.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flurry/flurry.dart';
import 'package:meta/meta.dart';
part 'exercise_log_event.dart';
@ -14,17 +15,22 @@ class ExerciseLogBloc extends Bloc<ExerciseLogEvent, ExerciseLogState> {
@override
ExerciseLogBloc({this.exerciseRepository}) : super(ExerciseLogInitial());
@override
Stream<ExerciseLogState> mapEventToState(ExerciseLogEvent event) async* {
try {
if (event is ExerciseLogLoad) {
yield ExerciseLogLoading();
Flurry.logEvent("exerciseLog");
yield ExerciseLogReady();
} else if ( event is ExerciseLogDelete ) {
} else if (event is ExerciseLogDelete) {
yield ExerciseLogLoading();
exerciseRepository.exerciseList.remove(event.exercise);
await exerciseRepository.deleteExercise(event.exercise);
Flurry.logEvent("exerciseDelete");
yield ExerciseLogReady();
} else if (event is ExerciseResult) {
yield ExerciseLogLoading();
Flurry.logEvent("exerciseResult");
yield ExerciseLogReady();
}
} on Exception catch (e) {

View File

@ -18,5 +18,8 @@ class ExerciseLogDelete extends ExerciseLogEvent {
@override
List<Object> get props => [exercise];
}
class ExerciseResult extends ExerciseLogEvent {
const ExerciseResult();
}

View File

@ -1,11 +1,13 @@
import 'dart:async';
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/exercise_ability.dart';
import 'package:aitrainer_app/model/property.dart';
import 'package:aitrainer_app/model/exercise_type.dart';
import 'package:aitrainer_app/model/fitness_state.dart';
import 'package:aitrainer_app/repository/customer_repository.dart';
import 'package:aitrainer_app/repository/exercise_repository.dart';
import 'package:aitrainer_app/service/logging.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flurry/flurry.dart';
@ -18,7 +20,7 @@ import 'package:stop_watch_timer/stop_watch_timer.dart';
part 'exercise_new_event.dart';
part 'exercise_new_state.dart';
class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> {
class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> with Logging {
final ExerciseRepository exerciseRepository;
final CustomerRepository customerRepository;
final MenuBloc menuBloc;
@ -45,6 +47,7 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> {
double mediaWidth = 0;
double mediaHeight = 0;
bool isMan = true;
String exerciseTask = "";
final StopWatchTimer stopWatchTimer = StopWatchTimer(
isLapHours: false,
@ -54,8 +57,8 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> {
@override
ExerciseNewBloc({this.exerciseRepository, this.menuBloc, this.customerRepository, ExerciseType exerciseType})
: super(ExerciseNewInitial()) {
exerciseRepository.exerciseType = exerciseType;
exerciseRepository.setUnit(exerciseType.unit);
exerciseRepository.setQuantity(quantity);
exerciseRepository.setUnitQuantity(unitQuantity);
exerciseRepository.exercise.exercisePlanDetailId = 0;
exerciseRepository.start = DateTime.now();
@ -66,7 +69,38 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> {
fitnessLevel = customerRepository.customer.fitnessLevel;
this.isMan = (customerRepository.customer.sex == "m");
}
stopWatchTimer.rawTime.listen((value) => timerValue = value);
if (exerciseType.unit == "second") {
stopWatchTimer.rawTime.listen((value) => {timerValue = value, this.setQuantity((value / 1000).toDouble())});
}
this.setExerciseTask(init: true);
}
String setExerciseTask({bool init = false}) {
if (this.exerciseRepository.exerciseType == null) {
print("WTF, exerciseType is null");
return "";
}
if (this.exerciseRepository.exerciseType.unit != "second") {
if (menuBloc.ability.toString() == ExerciseAbility.oneRepMax.toString()) {
this.exerciseTask = "Please take a relative bigger weight and repeat 12-20 times";
if (init) {
this.setQuantity(12);
}
} else if (this.exerciseRepository.exerciseType.isEndurance() &&
menuBloc.ability.toString() == ExerciseAbility.endurance.toString() &&
exerciseRepository.exerciseType.unitQuantity == "1") {
this.exerciseTask = "Please take a medium weight and repeat 20-30 times";
if (init) {
this.setQuantity(20);
}
}
}
return this.exerciseTask;
}
void setQuantity(double quantity) {
this.quantity = quantity;
exerciseRepository.setQuantity(quantity);
}
void setMediaDimensions(double width, double height) {
@ -213,6 +247,37 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> {
}
}
int getWeightCoordinate(isMan, {isTop = false, isLeft = false}) {
int value = 0;
this.manSizes.forEach((element) {
if (element.propertyName == "Weight") {
if (isTop == true) {
value = element.top;
} else if (isLeft == true) {
value = element.left;
}
}
});
return value;
}
Property getPropertyByName(String propertyName) {
Property property;
List<Property> sizes;
if (customerRepository.sex == "Man") {
sizes = this.manSizes;
} else {
sizes = this.womanSizes;
}
sizes.forEach((element) {
if (element.propertyName == propertyName) {
property = element;
}
});
return property;
}
void updateSizes(String propertyName, double value) {
List<Property> sizes;
if (customerRepository.sex == "Man") {
@ -236,8 +301,8 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> {
yield ExerciseNewReady();
} else if (event is ExerciseNewQuantityChange) {
yield ExerciseNewLoading();
exerciseRepository.setQuantity(event.quantity);
quantity = event.quantity;
log("Event quantity " + event.quantity.toStringAsFixed(0));
this.setQuantity(event.quantity);
yield ExerciseNewReady();
} else if (event is ExerciseNewQuantityUnitChange) {
yield ExerciseNewLoading();
@ -288,6 +353,7 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> {
menuBloc.add(MenuTreeDown(parent: 0));
Cache().initBadges();
Flurry.logEvent("newExercise");
Flurry.logEvent("newExercise " + exerciseRepository.exerciseType.name);
yield ExerciseNewReady();
} else if (event is ExerciseNewBMIAnimate) {
yield ExerciseNewLoading();
@ -342,19 +408,32 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> {
getBMI();
}
final double distortionWidth = mediaWidth / baseWidth;
final double distortionHeight = mediaHeight / baseHeight;
final double distortionHeight = distortionWidth - 0.02; //mediaHeight / baseHeight;
/* log("Width: " +
mediaWidth.toStringAsFixed(0) +
" Height: " +
mediaHeight.toStringAsFixed(0) +
" BaseW: " +
baseWidth.toStringAsFixed(0) +
" BaseH: " +
baseHeight.toStringAsFixed(0) +
" DistW: " +
distortionWidth.toStringAsFixed(2) +
" DistH: " +
distortionHeight.toStringAsFixed(2)); */
this.bmiAngle = (bmi * 90 / 25) - 90;
if (bmi < 18.5) {
goalBMI = 19;
this.bmiTop = 99 * distortionHeight;
this.bmiLeft = 77 * distortionWidth;
bmiAngle = -62;
} else if (bmi < 25 && 18.5 < bmi) {
goalBMI = 27;
} else if (bmi > 18.5 && bmi < 25) {
goalBMI = this.bmi;
this.bmiTop = 48 * distortionHeight;
this.bmiLeft = 130 * distortionWidth;
bmiAngle = -23;
} else if (bmi < 30 && 24.9 < bmi) {
} else if (bmi < 30 && bmi > 24.9) {
goalBMI = 24;
this.bmiTop = 40.0 * distortionHeight;
this.bmiLeft = 184.0 * distortionWidth;
@ -376,9 +455,4 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> {
return goalBMI;
}
@override
void dispose() async {
await stopWatchTimer.dispose();
}
}

View File

@ -7,6 +7,7 @@ import 'package:aitrainer_app/repository/workout_tree_repository.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flurry/flurry.dart';
import 'package:flurry/flurry.dart';
import 'package:meta/meta.dart';
part 'exercise_plan_event.dart';
@ -48,6 +49,7 @@ class ExercisePlanBloc extends Bloc<ExercisePlanEvent, ExercisePlanState> {
try {
if (event is ExercisePlanLoad) {
yield ExercisePlanLoading();
Flurry.logEvent("exercisePlan");
await this.getData();
yield ExercisePlanReady();
}

View File

@ -0,0 +1,108 @@
import 'dart:async';
import 'package:aitrainer_app/bloc/account/account_bloc.dart';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/repository/customer_repository.dart';
import 'package:aitrainer_app/repository/user_repository.dart';
import 'package:aitrainer_app/util/common.dart';
import 'package:aitrainer_app/util/trans.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flurry/flurry.dart';
import 'package:flutter/material.dart';
part 'login_event.dart';
part 'login_state.dart';
class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
final AccountBloc accountBloc;
final UserRepository userRepository;
final CustomerRepository customerRepository = CustomerRepository();
final BuildContext context;
final bool isRegistration;
bool dataPolicyAllowed = false;
LoginBloc({this.accountBloc, this.userRepository, this.context, this.isRegistration}) : super(LoginInitial());
@override
Stream<LoginState> mapEventToState(
LoginEvent event,
) async* {
try {
if (event is LoginEmailChange) {
yield LoginLoading();
final String email = event.email;
userRepository.setEmail(email);
yield LoginReady();
} else if (event is LoginPasswordChange) {
yield LoginLoading();
final String password = event.password;
userRepository.setPassword(password);
yield LoginReady();
} else if (event is LoginSubmit) {
yield LoginLoading();
await userRepository.getUser();
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn));
Flurry.logEvent("Login");
yield LoginSuccess();
} else if (event is LoginFB) {
yield LoginLoading();
await userRepository.getUserByFB();
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn));
Flurry.logEvent("Login");
Flurry.logEvent("LoginFB");
yield LoginSuccess();
} else if (event is RegistrationSubmit) {
yield LoginLoading();
if (!this.dataPolicyAllowed) {
yield LoginError();
throw Exception("Please accept our data policy");
}
await userRepository.addUser();
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn));
await saveCustomer();
Flurry.logEvent("Registration");
yield LoginSuccess();
} else if (event is RegistrationFB) {
yield LoginLoading();
if (!this.dataPolicyAllowed) {
yield LoginError();
throw Exception("Please accept our data policy");
}
await userRepository.addUserFB();
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn));
await saveCustomer();
Flurry.logEvent("RegistrationFB");
Flurry.logEvent("Registration");
yield LoginSuccess();
} else if (event is DataProtectionClicked) {
this.dataPolicyAllowed = event.marked;
yield LoginReady();
}
} on Exception catch (e) {
yield LoginError(message: e.toString());
}
}
Future<void> saveCustomer() async {
customerRepository.customer = Cache().userLoggedIn;
customerRepository.customer.dataPolicyAllowed = 1;
await customerRepository.saveCustomer();
}
String emailValidation(String email) {
String message = Common.emailValidation(email);
if (message != null) {
message = t(message);
}
return message;
}
String passwordValidation(String value) {
String message = Common.passwordValidation(value);
if (message != null) {
message = t(message);
}
return message;
}
}

View File

@ -0,0 +1,49 @@
part of 'login_bloc.dart';
abstract class LoginEvent extends Equatable {
const LoginEvent();
@override
List<Object> get props => [];
}
class LoginEmailChange extends LoginEvent {
final String email;
const LoginEmailChange({this.email});
@override
List<Object> get props => [email];
}
class LoginPasswordChange extends LoginEvent {
final String password;
const LoginPasswordChange({this.password});
@override
List<Object> get props => [password];
}
class LoginPasswordChangeObscure extends LoginEvent {
const LoginPasswordChangeObscure();
}
class LoginSubmit extends LoginEvent {
const LoginSubmit();
}
class LoginFB extends LoginEvent {
const LoginFB();
}
class DataProtectionClicked extends LoginEvent {
final bool marked;
const DataProtectionClicked({this.marked});
}
class RegistrationSubmit extends LoginEvent {
const RegistrationSubmit();
}
class RegistrationFB extends LoginEvent {
const RegistrationFB();
}

View File

@ -0,0 +1,36 @@
part of 'login_bloc.dart';
abstract class LoginState extends Equatable {
const LoginState();
@override
List<Object> get props => [];
}
class LoginInitial extends LoginState {
const LoginInitial();
}
class LoginLoading extends LoginState {
const LoginLoading();
}
class LoginReady extends LoginState {
const LoginReady();
}
class LoginSuccess extends LoginState {
const LoginSuccess();
}
class LoginError extends LoginState {
final String message;
const LoginError({this.message});
@override
List<Object> get props => [message];
}
class DataPolicyError extends LoginState {
const DataPolicyError();
}

View File

@ -1,65 +0,0 @@
import 'package:aitrainer_app/bloc/account/account_bloc.dart';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/repository/exercise_repository.dart';
import 'package:aitrainer_app/repository/user_repository.dart';
import 'package:aitrainer_app/service/exercise_tree_service.dart';
import 'package:aitrainer_app/service/exercisetype_service.dart';
import 'package:aitrainer_app/service/property_service.dart';
import 'package:aitrainer_app/util/common.dart';
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
class LoginFormBloc extends FormBloc<String, String> with Common {
final AccountBloc accountBloc;
final UserRepository userRepository;
final emailField = TextFieldBloc(
validators: [
FieldBlocValidators.required,
],
);
final passwordField = TextFieldBloc(validators: [
FieldBlocValidators.required,
]);
LoginFormBloc({this.userRepository, this.accountBloc}) {
addFieldBlocs(fieldBlocs: [emailField, passwordField]);
emailField.onValueChanges(onData: (previous, current) async* {
userRepository.setEmail(current.value);
});
passwordField.onValueChanges(onData: (previous, current) async* {
userRepository.setPassword(current.value);
});
}
@override
void onSubmitting() async {
try {
emitLoading(progress: 30);
if (!validateEmail(userRepository)) {
emailField.addFieldError(EMAIL_ERROR, isPermanent: true);
emitFailure(failureResponse: EMAIL_ERROR);
} else if (!validatePassword(userRepository)) {
passwordField.addFieldError(PASSWORD_ERROR, isPermanent: true);
emitFailure(failureResponse: PASSWORD_ERROR);
} else {
// Emit either Loaded or Error
await PropertyApi().getProperties();
await userRepository.getUser();
await ExerciseTypeApi().getExerciseTypes();
await ExerciseTreeApi().getExerciseTree();
if (Cache().userLoggedIn != null && Cache().userLoggedIn.customerId > 0) {
ExerciseRepository exerciseRepository = ExerciseRepository();
await exerciseRepository.getExercisesByCustomer(Cache().userLoggedIn.customerId);
}
emitSuccess(canSubmitAgain: false);
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn));
Cache().initBadges();
}
} on Exception catch (ex) {
emitFailure(failureResponse: ex.toString());
}
}
}

View File

@ -1,53 +0,0 @@
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/repository/user_repository.dart';
import 'package:aitrainer_app/util/common.dart';
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
import 'account/account_bloc.dart';
class RegistrationFormBloc extends FormBloc<String, String> with Common {
final AccountBloc accountBloc;
final emailField = TextFieldBloc(
validators: [
FieldBlocValidators.required,
],
);
final passwordField = TextFieldBloc(validators: [
FieldBlocValidators.required,
]);
final UserRepository userRepository;
RegistrationFormBloc({this.userRepository, this.accountBloc}) {
addFieldBlocs(fieldBlocs: [emailField, passwordField]);
emailField.onValueChanges(onData: (previous, current) async* {
userRepository.setEmail(current.value);
});
passwordField.onValueChanges(onData: (previous, current) async* {
userRepository.setPassword(current.value);
});
}
@override
void onSubmitting() async {
try {
emitLoading(progress: 30);
if (!validateEmail(userRepository)) {
emailField.addFieldError(EMAIL_ERROR, isPermanent: true);
emitFailure(failureResponse: EMAIL_ERROR);
} else if (!validatePassword(userRepository)) {
passwordField.addFieldError(PASSWORD_ERROR, isPermanent: true);
emitFailure(failureResponse: PASSWORD_ERROR);
} else {
// Emit either Loaded or Error
await userRepository.addUser();
emitSuccess(canSubmitAgain: false);
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn));
Cache().initBadges();
}
} on Exception catch (ex) {
emitFailure(failureResponse: ex.toString());
}
}
}

View File

@ -1,10 +1,10 @@
import 'package:aitrainer_app/repository/user_repository.dart';
import 'package:aitrainer_app/util/common.dart';
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
class ResetPasswordFormBloc extends FormBloc<String, String> with Common {
final UserRepository userRepository;
bool loading = false;
final emailField = TextFieldBloc(
validators: [
@ -13,9 +13,7 @@ class ResetPasswordFormBloc extends FormBloc<String, String> with Common {
);
ResetPasswordFormBloc({this.userRepository}) {
addFieldBlocs(fieldBlocs: [
emailField
]);
addFieldBlocs(fieldBlocs: [emailField]);
emailField.onValueChanges(onData: (previous, current) async* {
userRepository.setEmail(current.value);
@ -26,7 +24,8 @@ class ResetPasswordFormBloc extends FormBloc<String, String> with Common {
void onSubmitting() async {
try {
emitLoading(progress: 30);
if ( ! validateEmail(userRepository)) {
loading = true;
if (!validateEmail(userRepository)) {
emailField.addFieldError(EMAIL_ERROR, isPermanent: true);
emitFailure(failureResponse: EMAIL_ERROR);
@ -35,9 +34,9 @@ class ResetPasswordFormBloc extends FormBloc<String, String> with Common {
await userRepository.resetPassword();
emitSuccess(canSubmitAgain: false);
}
loading = false;
} on Exception catch (ex) {
emitFailure(failureResponse: ex.toString());
}
}
@ -45,5 +44,4 @@ class ResetPasswordFormBloc extends FormBloc<String, String> with Common {
emailField.close();
return super.close();
}
}
}

View File

@ -5,21 +5,24 @@ import 'package:aitrainer_app/model/result.dart';
import 'package:aitrainer_app/repository/exercise_repository.dart';
import 'package:aitrainer_app/repository/exercise_result_repository.dart';
import 'package:aitrainer_app/service/logging.dart';
import 'package:aitrainer_app/util/trans.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
import 'package:health/health.dart';
//import 'package:health/health.dart';
part 'result_event.dart';
part 'result_state.dart';
class ResultBloc extends Bloc<ResultEvent, ResultState> with Logging {
class ResultBloc extends Bloc<ResultEvent, ResultState> with Logging, Trans {
final ExerciseResultRepository resultRepository;
final ExerciseRepository exerciseRepository;
List<HealthDataPoint> _healthDataList = List();
final BuildContext context;
//List<HealthDataPoint> _healthDataList = List();
DateTime startTime;
DateTime endTime;
final HealthFactory health = HealthFactory();
/* final HealthFactory health = HealthFactory();
final List<HealthDataType> types = [
HealthDataType.ACTIVE_ENERGY_BURNED,
HealthDataType.WATER,
@ -30,9 +33,9 @@ class ResultBloc extends Bloc<ResultEvent, ResultState> with Logging {
HealthDataType.HIGH_HEART_RATE_EVENT,
HealthDataType.LOW_HEART_RATE_EVENT,
HealthDataType.RESTING_HEART_RATE
];
]; */
ResultBloc({this.resultRepository, this.exerciseRepository}) : super(ResultInitial()) {
ResultBloc({this.resultRepository, this.exerciseRepository, this.context}) : super(ResultInitial()) {
this.startTime = exerciseRepository.start;
this.endTime = exerciseRepository.end;
}
@ -45,7 +48,7 @@ class ResultBloc extends Bloc<ResultEvent, ResultState> with Logging {
if (event is ResultLoad) {
yield ResultLoading();
await _fetchHealthData();
//await _fetchHealthData();
_matchExerciseData();
await resultRepository.saveExerciseResults();
yield ResultReady();
@ -62,16 +65,16 @@ class ResultBloc extends Bloc<ResultEvent, ResultState> with Logging {
element.exerciseId = exerciseRepository.actualExerciseList[0].exerciseId;
switch (element.item) {
case ResultItem.bpm_avg:
element.data = _gethHealthDataPointValueAvg(HealthDataType.HEART_RATE);
//element.data = _gethHealthDataPointValueAvg(HealthDataType.HEART_RATE);
break;
case ResultItem.bpm_min:
element.data = element.data = _gethHealthDataPointValueMin(HealthDataType.HEART_RATE);
//element.data = element.data = _gethHealthDataPointValueMin(HealthDataType.HEART_RATE);
break;
case ResultItem.bpm_max:
element.data = element.data = _gethHealthDataPointValueMax(HealthDataType.HEART_RATE);
//element.data = element.data = _gethHealthDataPointValueMax(HealthDataType.HEART_RATE);
break;
case ResultItem.calorie:
element.data = _gethHealthDataPointValueSum(HealthDataType.ACTIVE_ENERGY_BURNED);
//element.data = _gethHealthDataPointValueSum(HealthDataType.ACTIVE_ENERGY_BURNED);
break;
case ResultItem.development_percent_bodypart:
// TODO: Handle this case.
@ -82,7 +85,7 @@ class ResultBloc extends Bloc<ResultEvent, ResultState> with Logging {
}
break;
case ResultItem.fatburn_percent:
DateTime today = DateTime.now();
/* DateTime today = DateTime.now();
int age = today.year - Cache().userLoggedIn.birthYear;
double minBpm = (200 - age) * 0.6;
double maxBpm = (200 - age) * 0.7;
@ -100,7 +103,7 @@ class ResultBloc extends Bloc<ResultEvent, ResultState> with Logging {
element.data = (burnCounter / counter * 100);
} else {
element.data = 0;
}
} */
break;
case ResultItem.speed_max:
// TODO: Handle this case.
@ -108,14 +111,14 @@ class ResultBloc extends Bloc<ResultEvent, ResultState> with Logging {
case ResultItem.reps_volume:
if (exerciseRepository.exerciseType.unit == "repeat") {
double value = 0;
exerciseRepository.actualExerciseList.forEach((element) {
value += element.quantity;
exerciseRepository.actualExerciseList.forEach((actual) {
value += actual.quantity;
});
element.data = value;
}
break;
case ResultItem.steps:
element.data = _gethHealthDataPointValueSum(HealthDataType.STEPS);
element.data = 0; //_gethHealthDataPointValueSum(HealthDataType.STEPS);
break;
/* case ResultItem.time:
final Duration duration = this.endTime.difference(this.startTime);
@ -124,8 +127,8 @@ class ResultBloc extends Bloc<ResultEvent, ResultState> with Logging {
case ResultItem.weight_volume:
if (exerciseRepository.exerciseType.unitQuantityUnit == "kilogram") {
double value = 0;
exerciseRepository.actualExerciseList.forEach((element) {
value += element.quantity * element.unitQuantity;
exerciseRepository.actualExerciseList.forEach((actual) {
value += actual.quantity * actual.unitQuantity;
});
element.data = value;
}
@ -134,15 +137,31 @@ class ResultBloc extends Bloc<ResultEvent, ResultState> with Logging {
});
}
String _printDuration(Duration duration) {
String printDuration(Duration duration, {isText = false, isDecimal = false}) {
String twoDigits(int n) => n.toString().padLeft(2, "0");
String twoDigitMinutes = twoDigits(duration.inMinutes);
String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60));
String twoDigitMilliSeconds = duration.inMilliseconds.remainder(1000).toString();
return "$twoDigitMinutes:$twoDigitSeconds:$twoDigitMilliSeconds" + '"';
if (isText) {
if (isDecimal) {
return "$twoDigitMinutes" + t("min") + "$twoDigitSeconds" + t("sec") + ":$twoDigitMilliSeconds" + '"';
} else {
return "$twoDigitMinutes" + t("min") + "$twoDigitSeconds" + t("sec");
}
} else {
return "$twoDigitMinutes:$twoDigitSeconds:$twoDigitMilliSeconds" + '"';
}
}
double _gethHealthDataPointValueAvg(HealthDataType dataType) {
String printTime(double duration) {
String twoDigits(int n) => n.toString().padLeft(1, "0");
String twoDigitMinutes = twoDigits((duration ~/ 60).toInt());
String twoDigitSeconds = (duration % 60).toStringAsFixed(0);
return "$twoDigitMinutes " + t("minutes") + " $twoDigitSeconds";
}
/* double _gethHealthDataPointValueAvg(HealthDataType dataType) {
double value = 0;
double counter = 0;
_healthDataList.forEach((dataPoint) {
@ -193,9 +212,9 @@ class ResultBloc extends Bloc<ResultEvent, ResultState> with Logging {
min = 0;
}
return min;
}
} */
Future<void> _fetchHealthData() async {
/* Future<void> _fetchHealthData() async {
if (health == null) {
return;
}
@ -209,7 +228,7 @@ class ResultBloc extends Bloc<ResultEvent, ResultState> with Logging {
log("Caught exception in getHealthDataFromTypes: $e");
throw Exception(e);
}
}
} */
double calculate1RM({double percent}) {
if (exerciseRepository.exercise == null) {

View File

@ -8,6 +8,7 @@ import 'package:aitrainer_app/service/logging.dart';
import 'package:aitrainer_app/service/product_test_service.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flurry/flurry.dart';
part 'sales_event.dart';
part 'sales_state.dart';
@ -25,11 +26,13 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
try {
if (event is SalesLoad) {
yield SalesLoading();
Flurry.logEvent("SalesPageOpen");
this.getProductSet();
yield SalesReady();
} else if (event is SalesPurchase) {
final int productId = event.productId;
trace("Requesting purchase for" + productId.toString());
Flurry.logEvent("PurchaseRequest");
//PlatformPurchaseApi().requestPurchase(null);
}
} on Exception catch (ex) {

View File

@ -7,6 +7,7 @@ import 'package:aitrainer_app/util/platform_purchase.dart';
import 'package:aitrainer_app/util/session.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flurry/flurry.dart';
part 'session_event.dart';
part 'session_state.dart';
@ -31,6 +32,7 @@ class SessionBloc extends Bloc<SessionEvent, SessionState> with Logging {
String lang = AppLanguage().appLocal.languageCode;
log("Change lang to $lang");
settingsBloc.add(SettingsChangeLanguage(language: lang));
Flurry.logEvent("Enter");
yield SessionReady();
}
} on Exception catch (ex) {

View File

@ -7,7 +7,7 @@ import 'package:aitrainer_app/service/logging.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/cupertino.dart';
import 'package:health/health.dart';
//import 'package:health/health.dart';
import 'package:meta/meta.dart';
part 'settings_event.dart';
@ -50,17 +50,19 @@ class SettingsBloc extends Bloc<SettingsEvent, SettingsState> with Logging {
bool selectedHardwareBefore = await Cache().selectedHardwareBefore();
log("selectedBefore " + selectedHardwareBefore.toString());
if (!selectedHardwareBefore) {
await _accessHealthData();
}
final bool hasHardware = event.hasHardware;
await Cache().setHardware(hasHardware);
if (hasHardware == true) {
await _accessHealthData();
}
Cache().initBadges();
yield SettingsReady(_locale);
}
}
Future<void> _accessHealthData() async {
final List<HealthDataType> types = [
/* final List<HealthDataType> types = [
HealthDataType.ACTIVE_ENERGY_BURNED,
HealthDataType.WATER,
HealthDataType.STEPS,
@ -71,10 +73,10 @@ class SettingsBloc extends Bloc<SettingsEvent, SettingsState> with Logging {
HealthDataType.LOW_HEART_RATE_EVENT,
HealthDataType.RESTING_HEART_RATE
];
final HealthFactory health = HealthFactory();
final HealthFactory health = HealthFactory(); */
DateTime now = DateTime.now();
List<HealthDataPoint> _healthDataList = await health.getHealthDataFromTypes(now.subtract(Duration(minutes: 5)), now, types);
log(_healthDataList.toString());
//List<HealthDataPoint> _healthDataList = await health.getHealthDataFromTypes(now.subtract(Duration(minutes: 5)), now, types);
//log(_healthDataList.toString());
}
Future<void> _changeLang(String lang) async {
@ -94,6 +96,7 @@ class SettingsBloc extends Bloc<SettingsEvent, SettingsState> with Logging {
this.language = lang;
AppLanguage().changeLanguage(_locale);
await loadLang();
await Cache().initBadges();
}
Future<void> loadLang() async {

View File

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:aitrainer_app/service/logging.dart';
import 'package:flutter/cupertino.dart';
import 'package:shared_preferences/shared_preferences.dart';
@ -34,8 +36,14 @@ class AppLanguage with Logging {
getLocale(SharedPreferences prefs) {
String langCode = prefs.getString('language_code');
if (langCode == null) {
_appLocale = Locale('en');
langCode = "en";
final String localName = Platform.localeName;
if (localName.endsWith("HU")) {
_appLocale = Locale('hu');
langCode = "hu";
} else {
_appLocale = Locale('en');
langCode = "en";
}
}
_appLocale = Locale(langCode);
log(" ---- Get lang: " + _appLocale.toString() + " lang code $langCode");

View File

@ -1,5 +1,4 @@
import 'dart:async';
import 'package:aitrainer_app/bloc/sales/sales_bloc.dart';
import 'package:aitrainer_app/push_notifications.dart';
import 'package:aitrainer_app/repository/customer_repository.dart';
import 'package:aitrainer_app/repository/workout_tree_repository.dart';
@ -21,7 +20,6 @@ import 'package:aitrainer_app/view/exercise_log_page.dart';
import 'package:aitrainer_app/view/exercise_plan_custom_page.dart';
import 'package:aitrainer_app/view/exercise_plan_custom_detail_add_page.dart';
import 'package:aitrainer_app/view/exercise_type_description.dart';
import 'package:aitrainer_app/view/gdpr.dart';
import 'package:aitrainer_app/view/login.dart';
import 'package:aitrainer_app/view/exercise_new_page.dart';
import 'package:aitrainer_app/view/menu_page.dart';
@ -209,7 +207,6 @@ class WorkoutTestApp extends StatelessWidget {
'login': (context) => LoginPage(),
'resetPassword': (context) => ResetPasswordPage(),
'registration': (context) => RegistrationPage(),
'gdpr': (context) => Gdpr(),
'menu_page': (context) => MenuPage(),
'account': (context) => AccountPage(),
'settings': (context) => SettingsPage(),

View File

@ -17,9 +17,11 @@ import 'package:aitrainer_app/service/customer_service.dart';
import 'package:aitrainer_app/service/exercise_device_service.dart';
import 'package:aitrainer_app/service/exercise_tree_service.dart';
import 'package:aitrainer_app/service/exercisetype_service.dart';
import 'package:aitrainer_app/service/firebase_api.dart';
import 'package:aitrainer_app/service/logging.dart';
import 'package:aitrainer_app/util/env.dart';
import 'package:flurry/flurry.dart';
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:aitrainer_app/model/exercise_type.dart';
@ -68,8 +70,11 @@ class Cache with Logging {
static final String password = 'andio2009';
String authToken = "";
AccessToken accessTokenFacebook;
Customer userLoggedIn;
String firebaseUid;
String facebookUid;
bool hasPurchased = false;
bool firstLoad = true;
@ -196,7 +201,8 @@ class Cache with Logging {
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
userLoggedIn = customer;
await setPreferences(prefs, SharePrefsChange.registration, customer.customerId, Cache().firebaseUid);
final String uid = Cache().firebaseUid == null ? Cache().facebookUid : Cache().firebaseUid;
await setPreferences(prefs, SharePrefsChange.registration, customer.customerId, uid);
}
afterLogin(Customer customer) async {
@ -211,7 +217,15 @@ class Cache with Logging {
await setPreferences(prefs, SharePrefsChange.login, userLoggedIn.customerId, Cache().firebaseUid);
}
afterFacebookLogin() async {
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
await setPreferences(prefs, SharePrefsChange.login, userLoggedIn.customerId, Cache().facebookUid);
}
logout() async {
if (this.accessTokenFacebook != null) {
await FirebaseApi().logOutFacebook();
}
userLoggedIn = null;
firebaseUid = null;
authToken = "";
@ -249,7 +263,7 @@ class Cache with Logging {
sharedPreferences.setString(Cache.firebaseUidKey, null);
sharedPreferences.setString(authTokenKey, "");
}
initBadges();
await initBadges();
}
void setExerciseTypes(List<ExerciseType> exerciseTypes) {
@ -374,7 +388,7 @@ class Cache with Logging {
}
}
void initBadges() {
Future<void> initBadges() async {
CustomerRepository customerRepository = CustomerRepository();
_badges = LinkedHashMap();
customerRepository.setCustomer(userLoggedIn);
@ -422,7 +436,7 @@ class Cache with Logging {
Future<void> initCustomer(int customerId) async {
log(" *** initCustomer");
await CustomerApi().getCustomer(customerId);
Cache().startPage = "home";
Flurry.setUserId(customerId.toString());
final customerDevices = await CustomerExerciseDeviceApi().getDevices(customerId);
Cache().setCustomerDevices(customerDevices);
@ -438,5 +452,12 @@ class Cache with Logging {
await customerRepository.getProductTests();
this.hasPurchased = this._purchases.isNotEmpty;
Cache().startPage = "home";
}
AccessToken get getAccessTokenFacebook => accessTokenFacebook;
set setAccessTokenFacebook(AccessToken accessTokenFacebook) => this.accessTokenFacebook = accessTokenFacebook;
String get getFacebookUid => facebookUid;
set setFacebookUid(String facebookUid) => this.facebookUid = facebookUid;
}

View File

@ -129,14 +129,14 @@ class CustomerRepository with Logging {
}
double getWeight() {
return getCustomerProperty("Weight");
return getCustomerPropertyValue("Weight");
}
double getHeight() {
return getCustomerProperty("Height");
return getCustomerPropertyValue("Height");
}
double getCustomerProperty(String propertyName) {
double getCustomerPropertyValue(String propertyName) {
if (this.customer.properties[propertyName] == null) {
return 0.0;
} else {
@ -144,6 +144,10 @@ class CustomerRepository with Logging {
}
}
CustomerProperty getCustomerProperty(String propertyName) {
return this.customer.properties[propertyName];
}
setBirthYear(int birthYear) {
this.customer.birthYear = birthYear;
}

View File

@ -80,17 +80,32 @@ class ExerciseRepository {
if (exerciseType.unitQuantity != "1") {
modelExercise.unitQuantity = null;
}
this.actualExerciseList.add(modelExercise);
int index = this.actualExerciseList.length - 1;
Exercise copy = modelExercise.copy();
this.actualExerciseList.add(copy);
//final int index = this.actualExerciseList.length - 1;
//print("$index. actual exercise " + this.actualExerciseList[index].toJson().toString());
Exercise savedExercise = await ExerciseApi().addExercise(modelExercise);
this.actualExerciseList[index].exerciseId = savedExercise.exerciseId;
//this.actualExerciseList[index].exerciseId = savedExercise.exerciseId;
if (customer.customerId == Cache().userLoggedIn.customerId) {
Cache().addExercise(savedExercise);
} else if (Cache().getTrainee() != null && customer.customerId == Cache().getTrainee().customerId) {
Cache().addExerciseTrainee(savedExercise);
}
/* this.actualExerciseList.forEach((element) {
print("$index. actual: " + element.toJson().toString());
}); */
this.createNew();
this.exerciseType = exerciseType;
this.setUnit(exerciseType.unit);
exercise.exerciseTypeId = this.exerciseType.exerciseTypeId;
this.setQuantity(quantity);
this.setUnitQuantity(modelExercise.unitQuantity);
this.exercise.exercisePlanDetailId = 0;
this.start = DateTime.now();
}
Future<void> deleteExercise(Exercise exercise) async {
@ -274,7 +289,8 @@ class ExerciseRepository {
}
String delimiter = "";
if (prevCount > 0) delimiter = ", ";
summary += delimiter + exercise.quantity.toStringAsFixed(0);
double quantity = exercise.quantity == null ? 0 : exercise.quantity;
summary += delimiter + quantity.toStringAsFixed(0);
ExerciseType exerciseType = Cache().getExercise(exercise.exerciseTypeId);
if (exerciseType.unitQuantity == "1") {
summary += "x" + exercise.unitQuantity.toStringAsFixed(0);
@ -286,6 +302,5 @@ class ExerciseRepository {
prevExercise = exercise;
prevCount++;
}
;
}
}

View File

@ -42,15 +42,17 @@ class ExerciseResultRepository {
List<ResultExt> getResults() => this._results;
Future<void> saveExerciseResults() async {
this._results.forEach((result) async {
ExerciseResult exerciseResult = ExerciseResult();
exerciseResult.customerId = Cache().userLoggedIn.customerId;
exerciseResult.exerciseId = result.exerciseId;
exerciseResult.dateFrom = result.dateFrom;
exerciseResult.dateTo = result.dateTo;
exerciseResult.resultType = result.itemString;
exerciseResult.value = result.data;
await ExerciseResultApi().saveExerciseResult(exerciseResult);
});
if (this._results != null) {
this._results.forEach((result) async {
ExerciseResult exerciseResult = ExerciseResult();
exerciseResult.customerId = Cache().userLoggedIn.customerId;
exerciseResult.exerciseId = result.exerciseId;
exerciseResult.dateFrom = result.dateFrom;
exerciseResult.dateTo = result.dateTo;
exerciseResult.resultType = result.itemString;
exerciseResult.value = result.data;
//await ExerciseResultApi().saveExerciseResult(exerciseResult);
});
}
}
}

View File

@ -36,13 +36,33 @@ class UserRepository {
}
}
Future<void> addUserFB() async {
final User modelUser = this.user;
Map<String, dynamic> userData = await FirebaseApi().signInWithFacebook();
if (userData != null) {
modelUser.email = userData['email'];
modelUser.password = "1234567";
modelUser.firebaseUid = Cache().facebookUid;
await CustomerApi().addUser(modelUser);
}
}
Future<void> getUserByFB() async {
final User modelUser = this.user;
Map<String, dynamic> userData = await FirebaseApi().signInWithFacebook();
modelUser.email = userData['email'];
await CustomerApi().getUserByEmail(modelUser.email);
await Cache().afterFacebookLogin();
}
Future<void> getUser() async {
final User modelUser = this.user;
String rc = await FirebaseApi().signInEmail(modelUser.email, modelUser.password);
if (rc == FirebaseApi.SIGN_IN_OK) {
await CustomerApi().getUserByEmail(modelUser.email);
Cache().afterFirebaseLogin();
await Cache().afterFirebaseLogin();
} else {
print("Exception: user not found or password is wrong");
throw Exception("Customer does not exist or the password is wrong");

View File

@ -47,7 +47,7 @@ class CustomerApi with Logging {
throw new Exception(jsonDecode(responseBody)['error']);
} else {
customer = Customer.fromJson(jsonDecode(responseBody));
Cache().afterRegistration(customer);
await Cache().afterRegistration(customer);
}
} on FormatException {
throw new Exception(responseBody);

View File

@ -2,7 +2,7 @@ import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/service/logging.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
//import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
class FirebaseApi with Logging {
static FirebaseApi _instance;
@ -75,16 +75,41 @@ class FirebaseApi with Logging {
return rc;
}
/*Future<UserCredential> signInWithFacebook() async {
// Trigger the sign-in flow
final LoginResult result = await FacebookAuth.instance.login();
Future<Map<String, dynamic>> signInWithFacebook() async {
Map<String, dynamic> userData;
try {
// by default the login method has the next permissions ['email','public_profile']
AccessToken accessToken = await FacebookAuth.instance.login();
if (accessToken != null) {
log(accessToken.toJson().toString());
Cache().accessTokenFacebook = accessToken;
// get the user data
userData = await FacebookAuth.instance.getUserData();
Cache().facebookUid = userData['id'];
log(userData.toString());
} else {
throw Exception("Facebook login was not successful");
}
} on FacebookAuthException catch (e) {
switch (e.errorCode) {
case FacebookAuthErrorCode.OPERATION_IN_PROGRESS:
throw Exception("You have a previous Facebook login operation in progress");
break;
case FacebookAuthErrorCode.CANCELLED:
throw Exception("Facebook login cancelled");
break;
case FacebookAuthErrorCode.FAILED:
throw Exception("Facebook login failed");
break;
}
}
return userData;
}
// Create a credential from the access token
final FacebookAuthCredential facebookAuthCredential = FacebookAuthProvider.credential(result.accessToken.token);
// Once signed in, return the UserCredential
return await FirebaseAuth.instance.signInWithCredential(facebookAuthCredential);
}*/
Future<void> logOutFacebook() async {
await FacebookAuth.instance.logOut();
Cache().accessTokenFacebook = null;
}
Future<void> signOut() async {
await FirebaseAuth.instance.signOut();

View File

@ -4,8 +4,9 @@ import 'package:aitrainer_app/localization/app_language.dart';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/exercise_type.dart';
import 'package:aitrainer_app/repository/user_repository.dart';
import 'package:aitrainer_app/util/env.dart';
import 'package:badges/badges.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
class DateRate {
@ -96,4 +97,37 @@ mixin Common {
}
return datePart;
}
static String emailValidation(String email) {
bool emailValid = RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+").hasMatch(email);
return emailValid ? null : "Please type an email address";
}
static String passwordValidation(String value) {
if (value == null || value.length == 0) {
return null;
}
bool valid = 8 < value.length;
return valid ? null : "Password too short";
}
static Widget badgedIcon(Color color, IconData icon, String badgeKey) {
bool show = Cache().getBadges()[badgeKey] != null;
int counter = Cache().getBadges()[badgeKey] != null ? Cache().getBadges()[badgeKey] : 0;
return Badge(
position: BadgePosition.topEnd(top: -10, end: -10),
animationDuration: Duration(milliseconds: 500),
animationType: BadgeAnimationType.slide,
badgeColor: Colors.red,
showBadge: show,
badgeContent: Text(
counter.toString(),
style: TextStyle(color: Colors.white),
),
child: Icon(
icon,
color: color,
),
);
}
}

View File

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:aitrainer_app/localization/app_language.dart';
import 'package:aitrainer_app/localization/app_localization.dart';
import 'package:aitrainer_app/service/api.dart';
@ -17,7 +19,7 @@ class Session with Logging {
fetchSessionAndNavigate() async {
log(" -- Session: await prefs..");
_sharedPreferences = await _prefs;
print("Platform: " + Platform.localeName);
if (Cache().firstLoad) {
log(" -- Session: fetch locale..");
await AppLanguage().getLocale(_sharedPreferences);

View File

@ -2,6 +2,7 @@ import 'package:aitrainer_app/bloc/account/account_bloc.dart';
import 'package:aitrainer_app/localization/app_language.dart';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/customer.dart';
import 'package:aitrainer_app/util/common.dart';
import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/widgets/app_bar_min.dart';
import 'package:badges/badges.dart';
@ -58,7 +59,7 @@ class AccountPage extends StatelessWidget with Trans {
ListView accountWidget(BuildContext context, String customerName, AccountBloc accountBloc) {
return ListView(padding: EdgeInsets.only(top: 35), children: <Widget>[
ListTile(
leading: badgedIcon(Colors.grey, Icons.perm_identity, "personalData"), //Icon(Icons.perm_identity),
leading: Common.badgedIcon(Colors.grey, Icons.perm_identity, "personalData"), //Icon(Icons.perm_identity),
subtitle: Text(t("Profile")),
title: FlatButton(
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
@ -84,7 +85,7 @@ class AccountPage extends StatelessWidget with Trans {
ListTile devices(BuildContext context, AccountBloc accountBloc) {
ListTile element = ListTile();
element = ListTile(
leading: badgedIcon(Colors.grey, Icons.device_hub, "customerDevice"),
leading: Common.badgedIcon(Colors.grey, Icons.device_hub, "customerDevice"),
title: FlatButton(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -226,24 +227,4 @@ class AccountPage extends StatelessWidget with Trans {
],
));
}
Widget badgedIcon(Color color, IconData icon, String badgeKey) {
bool show = Cache().getBadges()[badgeKey] != null;
int counter = Cache().getBadges()[badgeKey] != null ? Cache().getBadges()[badgeKey] : 0;
return Badge(
position: BadgePosition.topEnd(top: -10, end: -10),
animationDuration: Duration(milliseconds: 500),
animationType: BadgeAnimationType.slide,
badgeColor: Colors.red,
showBadge: show,
badgeContent: Text(
counter.toString(),
style: TextStyle(color: Colors.white),
),
child: Icon(
icon,
color: color,
),
);
}
}

View File

@ -5,12 +5,12 @@ import 'package:aitrainer_app/localization/app_localization.dart';
import 'package:aitrainer_app/model/exercise_type.dart';
import 'package:aitrainer_app/repository/exercise_repository.dart';
import 'package:aitrainer_app/service/logging.dart';
import 'package:aitrainer_app/widgets/splash.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
import 'package:modal_progress_hud/modal_progress_hud.dart';
class CustomExercisePage extends StatefulWidget {
_CustomExerciseNewPageState createState() => _CustomExerciseNewPageState();
@ -50,17 +50,15 @@ class _CustomExerciseNewPageState extends State<CustomExercisePage> with Logging
),
),
body: FormBlocListener<CustomExerciseFormBloc, String, String>(
onSubmitting: (context, state) {
/* onSubmitting: (context, state) {
LoadingDialog.show(context);
},
onSuccess: (context, state) {
LoadingDialog.hide(context);
},
onFailure: (context, state) {
LoadingDialog.hide(context);
Scaffold.of(context).showSnackBar(SnackBar(
backgroundColor: Colors.orange, content: Text(state.failureResponse, style: TextStyle(color: Colors.white))));
},
}, */
onSuccess: (context, state) {},
onFailure: (context, state) {
Scaffold.of(context).showSnackBar(SnackBar(
backgroundColor: Colors.orange, content: Text(state.failureResponse, style: TextStyle(color: Colors.white))));
},
child: ModalProgressHUD(
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
@ -86,7 +84,13 @@ class _CustomExerciseNewPageState extends State<CustomExercisePage> with Logging
]),
),
gridCalculation(exerciseBloc)
]))));
])),
inAsyncCall: exerciseBloc.loading == true,
opacity: 0.5,
color: Colors.black54,
progressIndicator: CircularProgressIndicator(),
),
));
}));
}

View File

@ -1,6 +1,10 @@
import 'package:aitrainer_app/bloc/customer_change/customer_change_bloc.dart';
import 'package:aitrainer_app/localization/app_localization.dart';
import 'package:aitrainer_app/repository/customer_repository.dart';
import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/widgets/app_bar_min.dart';
import 'package:aitrainer_app/widgets/dialog_html.dart';
import 'package:badges/badges.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@ -20,27 +24,16 @@ class BodyTypeItem {
static String mesomorph = "mesomorph";
}
class _CustomerBodyTypePageState extends State<CustomerBodyTypePage> {
class _CustomerBodyTypePageState extends State<CustomerBodyTypePage> with Trans {
String selected;
@override
Widget build(BuildContext context) {
final CustomerRepository customerRepository = ModalRoute.of(context).settings.arguments;
final double cWidth = MediaQuery.of(context).size.width * 0.75;
setContext(context);
return Scaffold(
appBar: AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Image.asset(
'asset/image/WT_long_logo.png',
fit: BoxFit.cover,
height: 65.0,
),
],
),
backgroundColor: Colors.transparent,
),
appBar: AppBarMin(),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
@ -64,78 +57,123 @@ class _CustomerBodyTypePageState extends State<CustomerBodyTypePage> {
alignment: WrapAlignment.center,
children: [
Text(
AppLocalizations.of(context).translate("Your Body Type"),
t("Your Body Type"),
textAlign: TextAlign.center,
style: TextStyle(color: Colors.orange, fontSize: 42, fontFamily: 'Arial', fontWeight: FontWeight.w900),
)
]),
Divider(),
FlatButton(
child: Container(
width: cWidth,
child: Column(
children: [
Text(AppLocalizations.of(context).translate("Endomorph"),
textWidthBasis: TextWidthBasis.longestLine,
style: TextStyle(color: Colors.blue, fontSize: 32, fontFamily: 'Arial', fontWeight: FontWeight.w900)),
],
)),
padding: EdgeInsets.all(10.0),
shape: getShape(customerRepository, BodyTypeItem.endomorph),
onPressed: () => {
setState(() {
selected = BodyTypeItem.endomorph;
changeBloc.add(CustomerBodyTypeChange(bodyType: selected));
}),
}),
Divider(),
FlatButton(
child: Container(
width: cWidth,
child: Column(
children: [
InkWell(
child: Text(
AppLocalizations.of(context).translate("Ectomorph"),
style: TextStyle(color: Colors.blue, fontSize: 32, fontFamily: 'Arial', fontWeight: FontWeight.w900),
),
highlightColor: Colors.white,
),
],
),
Badge(
badgeColor: customerRepository.bodyType == BodyTypeItem.ectomorph ? Colors.orange[200] : Colors.blue[50],
badgeContent: GestureDetector(
onTap: () => {
showDialog(
context: context,
builder: (BuildContext context) {
return DialogHTML(
title: t("Ectomorph"),
htmlData: t("Ectomorph_desc"),
);
})
},
child: Icon(Icons.info_outline_rounded),
),
padding: EdgeInsets.all(10.0),
shape: getShape(customerRepository, BodyTypeItem.ectomorph),
onPressed: () => {
setState(() {
selected = BodyTypeItem.ectomorph;
changeBloc.add(CustomerBodyTypeChange(bodyType: selected));
}),
}),
Divider(),
FlatButton(
child: Container(
width: cWidth,
child: Column(
children: [
InkWell(
child: Text(
AppLocalizations.of(context).translate("Mesomorph"),
style: TextStyle(color: Colors.blue, fontSize: 32, fontFamily: 'Arial', fontWeight: FontWeight.w900),
),
highlightColor: Colors.white,
child: FlatButton(
child: Container(
width: cWidth,
child: Column(
children: [
InkWell(
child: Text(
t("Ectomorph"),
style: TextStyle(color: Colors.blue, fontSize: 32, fontFamily: 'Arial', fontWeight: FontWeight.w900),
),
highlightColor: Colors.white,
),
],
),
],
),
),
padding: EdgeInsets.all(10.0),
shape: getShape(customerRepository, BodyTypeItem.ectomorph),
onPressed: () => {
setState(() {
selected = BodyTypeItem.ectomorph;
changeBloc.add(CustomerBodyTypeChange(bodyType: selected));
}),
})),
Divider(),
Badge(
badgeColor: customerRepository.bodyType == BodyTypeItem.endomorph ? Colors.orange : Colors.blue[50],
badgeContent: GestureDetector(
onTap: () => {
showDialog(
context: context,
builder: (BuildContext context) {
return DialogHTML(
title: t("Endomorph"),
htmlData: t("Endomorph_desc"),
);
})
},
child: Icon(Icons.info_outline_rounded)),
child: FlatButton(
child: Container(
width: cWidth,
child: Column(
children: [
Text(t("Endomorph"),
textWidthBasis: TextWidthBasis.longestLine,
style:
TextStyle(color: Colors.blue, fontSize: 32, fontFamily: 'Arial', fontWeight: FontWeight.w900)),
],
)),
padding: EdgeInsets.all(10.0),
shape: getShape(customerRepository, BodyTypeItem.endomorph),
onPressed: () => {
setState(() {
selected = BodyTypeItem.endomorph;
changeBloc.add(CustomerBodyTypeChange(bodyType: selected));
}),
})),
Divider(),
Badge(
badgeColor: customerRepository.bodyType == BodyTypeItem.mesomorph ? Colors.orange[200] : Colors.blue[50],
badgeContent: GestureDetector(
onTap: () => {
showDialog(
context: context,
builder: (BuildContext context) {
return DialogHTML(
title: t("Mesomorph"),
htmlData: t("Mesomorph_desc"),
);
})
},
child: Icon(Icons.info_outline_rounded),
),
padding: EdgeInsets.all(10.0),
shape: getShape(customerRepository, BodyTypeItem.mesomorph),
onPressed: () => {
setState(() {
selected = BodyTypeItem.mesomorph;
changeBloc.add(CustomerBodyTypeChange(bodyType: selected));
}),
}),
child: FlatButton(
child: Container(
width: cWidth,
child: Column(
children: [
InkWell(
child: Text(
t("Mesomorph"),
style: TextStyle(color: Colors.blue, fontSize: 32, fontFamily: 'Arial', fontWeight: FontWeight.w900),
),
highlightColor: Colors.white,
),
],
),
),
padding: EdgeInsets.all(10.0),
shape: getShape(customerRepository, BodyTypeItem.mesomorph),
onPressed: () => {
setState(() {
selected = BodyTypeItem.mesomorph;
changeBloc.add(CustomerBodyTypeChange(bodyType: selected));
}),
})),
Divider(),
RaisedButton(
color: Colors.orange,

View File

@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:modal_progress_hud/modal_progress_hud.dart';
import 'package:toggle_switch/toggle_switch.dart';
@ -23,7 +24,7 @@ class CustomerModifyPage extends StatelessWidget with Trans {
final accountBloc = BlocProvider.of<AccountBloc>(context);
return BlocProvider(
create: (context) => CustomerChangeBloc(customerRepository: accountBloc.customerRepository)..add(CustomerLoad()),
create: (context) => CustomerChangeBloc(customerRepository: accountBloc.customerRepository, context: context)..add(CustomerLoad()),
child: Builder(builder: (context) {
// ignore: close_sinks
final customerBloc = BlocProvider.of<CustomerChangeBloc>(context);
@ -43,18 +44,26 @@ class CustomerModifyPage extends StatelessWidget with Trans {
),
child: BlocConsumer<CustomerChangeBloc, CustomerChangeState>(
listener: (context, state) {
if (state is CustomerChangeLoading) {
//LoadingDialog();
} else if (state is CustomerSaveError) {
//LoadingDialog.hide(context);
Scaffold.of(context).showSnackBar(
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
if (state is CustomerSaveError) {
String message = t(state.message);
if (message == null) {
message = "";
} else {
Scaffold.of(context).showSnackBar(
SnackBar(backgroundColor: Colors.orange, content: Text(message, style: TextStyle(color: Colors.white))));
}
} else if (state is CustomerSaveSuccess) {
Navigator.of(context).pushNamed("customerGoalPage", arguments: customerBloc.customerRepository);
}
},
builder: (context, state) {
return loadForm(customerBloc);
return ModalProgressHUD(
child: loadForm(customerBloc),
inAsyncCall: state is CustomerChangeLoading,
opacity: 0.5,
color: Colors.black54,
progressIndicator: CircularProgressIndicator(),
);
},
)));
}));

View File

@ -58,9 +58,10 @@ class EvaluationPage extends StatelessWidget with Trans {
),
),
child: BlocProvider(
create: (context) =>
ResultBloc(resultRepository: ExerciseResultRepository(resultType: resultType), exerciseRepository: exerciseRepository)
..add(ResultLoad()),
create: (context) => ResultBloc(
resultRepository: ExerciseResultRepository(resultType: resultType),
exerciseRepository: exerciseRepository,
context: context), //..add(ResultLoad())
child: BlocConsumer<ResultBloc, ResultState>(listener: (context, state) {
if (state is ResultError) {
Scaffold.of(context).showSnackBar(
@ -163,8 +164,8 @@ class EvaluationPage extends StatelessWidget with Trans {
getSuggestionTitle(resultBloc),
getSuggestion(resultBloc),
emptySliver(),
getResultTitle(resultBloc),
getResults(resultBloc),
//getResultTitle(resultBloc),
//getResults(resultBloc),
]));
}
@ -239,9 +240,9 @@ class EvaluationPage extends StatelessWidget with Trans {
return SliverList(
delegate: SliverChildListDelegate(
[
getSuggestionWidget(resultBloc, "Hypertrophy", "asset/image/pict_hypertrophy.png", "3x10-12", 0.9, "2"),
getSuggestionWidget(resultBloc, "Hypertrophy", "asset/image/pict_hypertrophy.png", "3x10-12", 0.75, "2"),
Divider(color: Colors.transparent),
getSuggestionWidget(resultBloc, "Gain Strength", "asset/image/pict_weight_volumen_tonna.png", "3x10-12", 0.75, "3-5"),
getSuggestionWidget(resultBloc, "Gain Strength", "asset/image/pict_weight_volumen_tonna.png", "3x4-8", 0.95, "3-5"),
Divider(color: Colors.transparent),
getSuggestionWidget(resultBloc, "Endurance", "asset/image/pict_reps_volumen_db.png", "4x25-35", 0.50, "3"),
],
@ -381,11 +382,20 @@ class EvaluationPage extends StatelessWidget with Trans {
Widget getSummary(ResultBloc bloc) {
int index = 0;
List<Text> resultList = List();
bloc.exerciseRepository.actualExerciseList.forEach((exercise) {
/* for (int i = 0; i < bloc.exerciseRepository.actualExerciseList.length; i++) {
print("Q " +
bloc.exerciseRepository.actualExerciseList[i].quantity.toString() +
" Qu: " +
bloc.exerciseRepository.actualExerciseList[i].unitQuantity.toString());
} */
bloc.exerciseRepository.actualExerciseList.forEach((actual) {
final String unit = t(bloc.exerciseRepository.exerciseType.unit);
String exerciseElement = "";
final String exerciseRepeats = exercise.quantity.toStringAsFixed(0);
final String exerciseUnitQuantity = exercise.unitQuantity != null ? "x" + exercise.unitQuantity.toStringAsFixed(0) : "";
String exerciseRepeats = actual.quantity.toStringAsFixed(0);
if (bloc.exerciseRepository.exerciseType.unit == "second") {
exerciseRepeats = bloc.printTime(actual.quantity);
}
final String exerciseUnitQuantity = actual.unitQuantity != null ? "x" + actual.unitQuantity.toStringAsFixed(0) : "";
if (index == 0) {
exerciseElement = t("Test") + ": ";
} else if (index == 1) {
@ -477,7 +487,7 @@ class EvaluationPage extends StatelessWidget with Trans {
Image.asset(
element.getImage(),
height: 80,
color: Colors.black54,
color: Colors.black.withOpacity(0.8),
),
])
: Image.asset(
@ -489,11 +499,11 @@ class EvaluationPage extends StatelessWidget with Trans {
),
Text(
element.data.toStringAsFixed(0),
style: GoogleFonts.archivoBlack(fontSize: 28, color: blur ? Colors.white30 : Colors.white),
style: GoogleFonts.archivoBlack(fontSize: 28, color: blur ? Colors.white12 : Colors.white),
),
Text(
t(element.getDescription()),
style: GoogleFonts.archivoBlack(fontSize: 14, color: blur ? Colors.white30 : Colors.white),
style: GoogleFonts.archivoBlack(fontSize: 14, color: blur ? Colors.white12 : Colors.white),
textAlign: TextAlign.left,
),
],

View File

@ -1,25 +1,36 @@
import 'dart:collection';
import 'package:aitrainer_app/bloc/exercise_control/exercise_control_bloc.dart';
import 'package:aitrainer_app/library/custom_icon_icons.dart';
import 'package:aitrainer_app/localization/app_language.dart';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/repository/exercise_repository.dart';
import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/widgets/app_bar.dart';
import 'package:aitrainer_app/widgets/bottom_nav.dart';
import 'package:aitrainer_app/widgets/dialog_html.dart';
import 'package:aitrainer_app/widgets/number_picker.dart';
import 'package:aitrainer_app/widgets/splash.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:modal_progress_hud/modal_progress_hud.dart';
class ExerciseControlPage extends StatefulWidget {
_ExerciseControlPage createState() => _ExerciseControlPage();
}
class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
final ScrollController _controller = ScrollController();
double offset = 0;
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
LinkedHashMap arguments = ModalRoute.of(context).settings.arguments;
@ -35,22 +46,24 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
if (state is ExerciseControlError) {
Scaffold.of(context).showSnackBar(
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
} else if (state is ExerciseControlLoading) {
return LoadingDialog();
}
}, builder: (context, state) {
final exerciseBloc = BlocProvider.of<ExerciseControlBloc>(context);
if (state is ExerciseControlLoading) {
return LoadingDialog();
} else if (state is ExerciseControlReady) {
return getControlForm(exerciseBloc);
} else {
return getControlForm(exerciseBloc);
if (state is ExerciseControlReady) {
_controller.animateTo(exerciseBloc.scrollOffset, duration: Duration(milliseconds: 300), curve: Curves.easeIn);
}
return ModalProgressHUD(
child: getControlForm(exerciseBloc),
inAsyncCall: state is ExerciseControlLoading,
opacity: 0.5,
color: Colors.black54,
progressIndicator: CircularProgressIndicator(),
);
}));
}
Form getControlForm(ExerciseControlBloc exerciseBloc) {
this.offset = exerciseBloc.scrollOffset;
String exerciseName = AppLanguage().appLocal == Locale("en")
? exerciseBloc.exerciseRepository.exerciseType.name
: exerciseBloc.exerciseRepository.exerciseType.nameTranslation;
@ -75,9 +88,7 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
padding: const EdgeInsets.only(top: 10, left: 25, right: 25),
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
controller: ScrollController(
initialScrollOffset: exerciseBloc.scrollOffset,
),
controller: _controller,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.start,
@ -86,7 +97,7 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
exerciseName,
style: GoogleFonts.archivoBlack(
fontWeight: FontWeight.bold,
fontSize: 20,
fontSize: 24,
color: Colors.white,
shadows: <Shadow>[
Shadow(
@ -115,27 +126,9 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
Divider(
color: Colors.transparent,
),
/* FlatButton(
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Icon(
Icons.info,
color: Colors.yellow[50],
),
Flexible(
child: Text(t("Why do you need Exercise Control?"),
style: TextStyle(color: Colors.yellow[50], fontWeight: FontWeight.normal, fontSize: 14)),
),
Icon(
Icons.arrow_forward_ios,
color: Colors.yellow[50],
),
]),
textColor: Colors.blueAccent,
Divider(
color: Colors.transparent,
onPressed: () => {
//Navigator.of(context).pushNamed('exerciseTypeDescription', arguments: exerciseBloc.exerciseRepository),
},
), */
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
@ -143,17 +136,92 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
style: GoogleFonts.inter(
color: Colors.yellow[300],
fontSize: 18,
shadows: <Shadow>[
Shadow(
offset: Offset(-2.0, -2.0),
blurRadius: 12.0,
color: Colors.black54,
),
Shadow(
offset: Offset(-3.0, 3.0),
blurRadius: 12.0,
color: Colors.black54,
),
],
)),
Text(
" " +
exerciseBloc.initialRM.toStringAsFixed(0) +
" " +
exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit,
style: GoogleFonts.inter(color: Colors.yellow[300], fontSize: 18, fontWeight: FontWeight.bold),
style: GoogleFonts.inter(
color: Colors.yellow[300],
fontSize: 18,
fontWeight: FontWeight.bold,
shadows: <Shadow>[
Shadow(
offset: Offset(-2.0, -2.0),
blurRadius: 6.0,
color: Colors.black54,
),
Shadow(
offset: Offset(-3.0, 3.0),
blurRadius: 6.0,
color: Colors.black54,
),
],
),
),
SizedBox(width: 10),
GestureDetector(
onTap: () => {
showDialog(
context: context,
builder: (BuildContext context) {
return DialogHTML(
title: t("OneRepMax"),
htmlData: t("OneRepMax_desc"),
);
})
},
child: Icon(CustomIcon.question, color: Colors.yellow[300]))
],
),
Divider(),
Row(mainAxisAlignment: MainAxisAlignment.start, children: [
Flexible(
child: Text(t("Why do you need Exercise Control?"),
style: GoogleFonts.inter(
color: Colors.yellow[300],
fontSize: 18,
shadows: <Shadow>[
Shadow(
offset: Offset(2.0, 2.0),
blurRadius: 6.0,
color: Colors.black54,
),
Shadow(
offset: Offset(-3.0, 3.0),
blurRadius: 12.0,
color: Colors.black54,
),
],
))),
SizedBox(width: 10),
GestureDetector(
onTap: () => {
showDialog(
context: context,
builder: (BuildContext context) {
return DialogHTML(
title: t("Control Exercise:"),
htmlData: t("controlexercise_desc"),
);
})
},
child: Icon(CustomIcon.question, color: Colors.yellow[300]))
]),
Divider(),
numberPickForm(exerciseBloc, 1),
Divider(),
numberPickForm(exerciseBloc, 2),
@ -166,6 +234,24 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
);
}
List<Widget> getButton(int step, ExerciseControlBloc exerciseBloc) {
List<Widget> widgets = List();
if (step < exerciseBloc.step) {
widgets.add(Icon(
CustomIcon.check_circle,
color: Color(0xffb4f500),
size: 36,
));
} else {
widgets.add(Icon(
CustomIcon.question,
color: Colors.grey[700],
size: 36,
));
}
return widgets;
}
Widget numberPickForm(ExerciseControlBloc exerciseBloc, int step) {
String strTimes = step == 2 ? exerciseBloc.origQuantity.toStringAsFixed(0) : "max.";
String textInstruction = "";
@ -211,7 +297,6 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
exerciseBloc.add(ExerciseControlSubmit(step: step)),
if (step == 3)
{
//confirmationDialog(exerciseBloc)
Navigator.of(context).pop(),
args['exerciseRepository'] = exerciseBloc.exerciseRepository,
Navigator.of(context).pushNamed('evaluationPage', arguments: args)
@ -228,7 +313,10 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
),
],
)
: Container()),
: Stack(
alignment: Alignment.center,
children: getButton(step, exerciseBloc),
)),
],
),
];
@ -238,46 +326,4 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
children: listWidgets,
);
}
void confirmationDialog(ExerciseControlBloc bloc) {
String unit = t(bloc.exerciseRepository.exerciseType.unit);
LinkedHashMap args = LinkedHashMap();
showCupertinoDialog(
useRootNavigator: true,
context: context,
//barrierDismissible: false,
builder: (_) => CupertinoAlertDialog(
title: Text(t("Summary of your test")),
content: Column(children: [
Text(
t("Test") + ": " + bloc.repeats[1].toStringAsFixed(0) + "x" + bloc.repeats[0].toStringAsFixed(0) + " " + unit,
style: (TextStyle(color: Colors.blue)),
),
Divider(),
Text(
t("1st Control") + ": " + bloc.repeats[2].toStringAsFixed(0) + "x" + bloc.unitQuantity.toStringAsFixed(0) + " " + unit,
style: (TextStyle(color: Colors.blue)),
),
Text(
t("2nd Control") + ": " + bloc.repeats[3].toStringAsFixed(0) + "x" + bloc.unitQuantity.toStringAsFixed(0) + " " + unit,
style: (TextStyle(color: Colors.blue)),
),
Text(
t("3rd Control") + ": " + bloc.repeats[4].toStringAsFixed(0) + "x" + bloc.unitQuantity.toStringAsFixed(0) + " " + unit,
style: (TextStyle(color: Colors.blue)),
),
]),
actions: [
FlatButton(
child: Text(t("OK")),
onPressed: () => {
Navigator.of(context).pop(),
args['exerciseRepository'] = bloc.exerciseRepository,
Navigator.of(context).pushNamed('evaluationPage', arguments: args)
},
)
],
));
}
}

View File

@ -127,15 +127,43 @@ class _ExerciseExecutePage extends State<ExerciseExecutePage> with Trans {
exerciseTypes.add(explanation);
bloc.menuTreeRepository.sortedTree.forEach((name, list) {
if (bloc.selectedNumber == 0) {
exerciseTypes.add(Container(
margin: const EdgeInsets.only(left: 4.0),
child: TreeViewChild(
startExpanded: true,
parent: TreeviewParentWidget(text: name),
children: _getChildList(list, bloc),
)));
});
child: Center(
child: Text(
t("Please define your Exercise Plan"),
style: GoogleFonts.inter(color: Colors.white),
))));
exerciseTypes.add(Container(
child: Center(
child: Text(
t("Go to: 'Training Plan' - 'Edit My Custom Plan'"),
style: GoogleFonts.inter(color: Colors.white),
))));
exerciseTypes.add(Container(
child: Center(
child: InkWell(
onTap: () {
final LinkedHashMap args = LinkedHashMap();
args['customerId'] = Cache().userLoggedIn.customerId;
Navigator.of(context).pop();
Navigator.of(context).pushNamed('exercisePlanCustomPage', arguments: args);
},
child: Text(
t("Jump there »"),
style: GoogleFonts.inter(color: Colors.blue[200], decorationStyle: TextDecorationStyle.solid),
)))));
} else {
bloc.menuTreeRepository.sortedTree.forEach((name, list) {
exerciseTypes.add(Container(
margin: const EdgeInsets.only(left: 4.0),
child: TreeViewChild(
startExpanded: true,
parent: TreeviewParentWidget(text: name),
children: _getChildList(list, bloc),
)));
});
}
return exerciseTypes;
}

View File

@ -7,12 +7,12 @@ import 'package:aitrainer_app/model/workout_menu_tree.dart';
import 'package:aitrainer_app/repository/exercise_repository.dart';
import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/widgets/app_bar.dart';
import 'package:aitrainer_app/widgets/splash.dart';
import 'package:aitrainer_app/library/numberpicker.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
import 'package:modal_progress_hud/modal_progress_hud.dart';
class ExerciseExecutePlanAddPage extends StatefulWidget {
_ExerciseExecuteAddPage createState() => _ExerciseExecuteAddPage();
@ -40,19 +40,18 @@ class _ExerciseExecuteAddPage extends State<ExerciseExecutePlanAddPage> with Tra
if (state is ExerciseExecutePlanAddError) {
Scaffold.of(context).showSnackBar(
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
} else if (state is ExerciseExecutePlanAddLoading) {
return LoadingDialog();
}
}, builder: (context, state) {
// ignore: close_sinks
final exerciseBloc = BlocProvider.of<ExerciseExecutePlanAddBloc>(context);
if (state is ExerciseExecutePlanAddLoading) {
return LoadingDialog();
} else if (state is ExerciseExecutePlanAddReady) {
return getControlForm(exerciseBloc);
} else {
return getControlForm(exerciseBloc);
}
return ModalProgressHUD(
child: getControlForm(exerciseBloc),
inAsyncCall: state is ExerciseExecutePlanAddLoading,
opacity: 0.5,
color: Colors.black54,
progressIndicator: CircularProgressIndicator(),
);
}));
}

View File

@ -4,7 +4,6 @@ import 'package:aitrainer_app/library/custom_icon_icons.dart';
import 'package:aitrainer_app/widgets/app_bar.dart';
import 'package:aitrainer_app/widgets/bottom_nav.dart';
import 'package:aitrainer_app/widgets/dialog_premium.dart';
import 'package:aitrainer_app/widgets/splash.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:intl/intl.dart';
@ -18,6 +17,7 @@ import 'package:aitrainer_app/util/common.dart';
import 'package:aitrainer_app/util/trans.dart';
import 'package:flutter/material.dart';
import 'package:aitrainer_app/widgets/treeview_parent_widget.dart';
import 'package:modal_progress_hud/modal_progress_hud.dart';
class ExerciseLogPage extends StatefulWidget {
@override
@ -28,31 +28,25 @@ class _ExerciseLogPage extends State<ExerciseLogPage> with Trans, Common {
@override
Widget build(BuildContext context) {
LinkedHashMap arguments = ModalRoute.of(context).settings.arguments;
//final ExerciseRepository exerciseRepository = arguments['exerciseRepository'];
final int customerId = arguments['customerId'];
setContext(context);
return BlocProvider(
create: (context) => ExerciseLogBloc(exerciseRepository: ExerciseRepository())..add(ExerciseLogLoad()),
child: BlocConsumer<ExerciseLogBloc, ExerciseLogState>(listener: (context, state) {
if (state is ExerciseLogLoading) {
return LoadingDialog();
} else if (state is ExerciseLogError) {
//LoadingDialog.hide(context);
if (state is ExerciseLogError) {
Scaffold.of(context).showSnackBar(
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
}
}, builder: (context, state) {
final exerciseBloc = BlocProvider.of<ExerciseLogBloc>(context);
if (state is ExerciseLogReady) {
//LoadingDialog.hide(context);
return getExerciseLog(customerId, exerciseBloc);
} else if (state is ExerciseLogLoading) {
return LoadingDialog();
} else {
//LoadingDialog.hide(context);
return getExerciseLog(customerId, exerciseBloc);
}
return ModalProgressHUD(
child: getExerciseLog(customerId, exerciseBloc),
inAsyncCall: state is ExerciseLogLoading,
opacity: 0.5,
color: Colors.black54,
progressIndicator: CircularProgressIndicator(),
);
}));
}

View File

@ -23,6 +23,7 @@ import 'package:flutter_form_bloc/flutter_form_bloc.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:keyboard_actions/keyboard_actions.dart';
import 'package:stop_watch_timer/stop_watch_timer.dart';
import 'package:wakelock/wakelock.dart';
class ExerciseNewPage extends StatefulWidget {
_ExerciseNewPageState createState() => _ExerciseNewPageState();
@ -94,9 +95,7 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
child: BlocConsumer<ExerciseNewBloc, ExerciseNewState>(
listener: (context, state) {
if (state is ExerciseNewLoading) {
//LoadingDialog.show(context);
} else if (state is ExerciseNewError) {
//LoadingDialog.hide(context);
Scaffold.of(context).showSnackBar(
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
}
@ -136,20 +135,7 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
return SizeWidget(exerciseBloc: exerciseBloc);
}
bool isSecond = false;
String exerciseTask = "";
if (exerciseBloc.exerciseRepository.exerciseType.unit != "second") {
if (exerciseBloc.exerciseRepository.exerciseType.is1RM() && menuBloc.ability.toString() == ExerciseAbility.oneRepMax.toString()) {
exerciseTask = "Please take a relative bigger weight and repeat 12-20 times";
exerciseBloc.quantity = 12;
} else if (exerciseBloc.exerciseRepository.exerciseType.isEndurance() &&
menuBloc.ability.toString() == ExerciseAbility.endurance.toString()) {
exerciseTask = "Please take a medium weight and repeat 20-30 times";
exerciseBloc.quantity = 20;
}
} else {
isSecond = true;
}
final String exerciseTask = exerciseBloc.setExerciseTask();
return Form(
child: Scaffold(
@ -205,7 +191,7 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
Text(
exerciseDescription,
style: GoogleFonts.inter(fontSize: 12, color: Colors.yellow[300]),
maxLines: 8,
maxLines: 4,
overflow: TextOverflow.fade,
softWrap: true,
),
@ -338,6 +324,7 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
//shape: const StadiumBorder(),
onPressed: () async {
bloc.stopWatchTimer.onExecute.add(StopWatchExecute.start);
Wakelock.enable(); // prevent sleep the phone
},
icon: Icon(CustomIcon.play_1),
iconSize: 40,
@ -352,6 +339,7 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
//shape: const StadiumBorder(),
onPressed: () async {
bloc.stopWatchTimer.onExecute.add(StopWatchExecute.stop);
Wakelock.disable();
},
icon: Icon(CustomIcon.stop),
),
@ -378,7 +366,7 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
Divider(),
Text("Or type the time manually:", style: GoogleFonts.inter(color: Colors.white)),
TimePickerWidget(
onChange: (value) => {bloc.add(ExerciseNewQuantityChange(quantity: value))},
onChange: (value) => {print("timer"), bloc.add(ExerciseNewQuantityChange(quantity: value))},
)
]);
}
@ -410,6 +398,7 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
void confirmationDialog(ExerciseNewBloc bloc, MenuBloc menuBloc) {
LinkedHashMap args = LinkedHashMap();
print("quantity: " + bloc.quantity.toString());
if (bloc.exerciseRepository.exercise.quantity == null) {
return;
}

View File

@ -1,26 +0,0 @@
import 'package:aitrainer_app/localization/app_localization.dart';
import 'package:aitrainer_app/widgets/app_bar_min.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class Gdpr extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBarMin(
back: true,
),
body: Container(
padding: const EdgeInsets.only(left: 15, right: 15),
child: ListView(
children: <Widget>[
InkWell(
child: Text(
AppLocalizations.of(context).translate('gdpr_text'),
),
customBorder: Border.all(color: Colors.orange, width: 1),
),
],
)));
}
}

View File

@ -1,67 +1,53 @@
import 'package:aitrainer_app/bloc/login_form_bloc.dart';
import 'package:aitrainer_app/bloc/account/account_bloc.dart';
import 'package:aitrainer_app/bloc/login/login_bloc.dart';
import 'package:aitrainer_app/localization/app_localization.dart';
import 'package:aitrainer_app/repository/user_repository.dart';
import 'package:aitrainer_app/util/common.dart';
import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/widgets/app_bar_min.dart';
import 'package:aitrainer_app/widgets/splash.dart';
import 'package:aitrainer_app/widgets/dialog_long.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:modal_progress_hud/modal_progress_hud.dart';
import '../library_keys.dart';
class LoginPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return LoginWidget();
}
}
class LoginWidget extends StatefulWidget {
LoginWidget();
@override
State<StatefulWidget> createState() => _LoginWidget();
}
class _LoginWidget extends State<LoginWidget> with Common, Trans {
// ignore: must_be_immutable
class LoginPage extends StatelessWidget with Trans {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
final accountBloc = BlocProvider.of<AccountBloc>(context);
setContext(context);
return BlocProvider(
create: (context) => LoginFormBloc(userRepository: UserRepository(), accountBloc: accountBloc),
child: Builder(builder: (context) {
final loginBloc = BlocProvider.of<LoginFormBloc>(context);
return Scaffold(
//key: _scaffoldKey,
appBar: AppBarMin(),
body: FormBlocListener<LoginFormBloc, String, String>(
onSubmitting: (context, state) {
LoadingDialog.show(context);
},
onSuccess: (context, state) {
LoadingDialog.hide(context);
Navigator.of(context).pushNamed('home');
},
onFailure: (context, state) {
LoadingDialog.hide(context);
Scaffold.of(context).showSnackBar(SnackBar(
backgroundColor: Colors.orange, content: Text(t(state.failureResponse), style: TextStyle(color: Colors.white))));
},
onLoaded: (context, state) {},
child: loadForm(loginBloc, accountBloc)),
);
}));
return Scaffold(
appBar: AppBarMin(),
body: BlocProvider(
create: (context) =>
LoginBloc(userRepository: UserRepository(), accountBloc: accountBloc, context: context, isRegistration: false),
child: BlocConsumer<LoginBloc, LoginState>(listener: (context, state) {
if (state is LoginError) {
Scaffold.of(context).showSnackBar(
SnackBar(backgroundColor: Colors.orange, content: Text(t(state.message), style: TextStyle(color: Colors.white))));
} else if (state is LoginSuccess) {
Navigator.of(context).pushNamed('home');
}
}, builder: (context, state) {
final loginBloc = BlocProvider.of<LoginBloc>(context);
return ModalProgressHUD(
child: loadForm(loginBloc, accountBloc),
inAsyncCall: state is LoginLoading,
opacity: 0.5,
color: Colors.black54,
progressIndicator: CircularProgressIndicator(),
);
})));
}
Widget loadForm(LoginFormBloc loginBloc, AccountBloc accountBloc) {
Widget loadForm(LoginBloc loginBloc, AccountBloc accountBloc) {
return SafeArea(
top: false,
bottom: false,
@ -78,25 +64,20 @@ class _LoginWidget extends State<LoginWidget> with Common, Trans {
);
}
Widget buildLoginForm(LoginFormBloc formBloc, AccountBloc accountBloc) {
Widget buildLoginForm(LoginBloc loginBloc, AccountBloc accountBloc) {
return Form(
key: _scaffoldKey,
child: Container(
padding: const EdgeInsets.only(left: 15, right: 50),
child: ListView(shrinkWrap: false, padding: EdgeInsets.only(top: 150.0), children: <Widget>[
Divider(color: Colors.transparent),
/* FlatButton(
child: new Image.asset(
'asset/image/login_fb.png',
width: cWidth * .85,
),
onPressed: () => {
//_fbLogin(),
FirebaseApi().signInWithFacebook(),
print("Login with FB"),
},
),
Text(AppLocalizations.of(context).translate("OR")),*/
child: ListView(shrinkWrap: false, padding: EdgeInsets.only(top: 100.0), children: <Widget>[
FlatButton(
child: new Image.asset(
'asset/image/login_fb.png',
width: MediaQuery.of(context).size.width * .85,
),
onPressed: () => {loginBloc.add(LoginFB())},
),
Text(AppLocalizations.of(context).translate("OR")),
Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.start,
@ -107,28 +88,61 @@ class _LoginWidget extends State<LoginWidget> with Common, Trans {
),
],
),
Divider(),
TextFieldBlocBuilder(
Divider(
color: Colors.transparent,
),
TextFormField(
key: LibraryKeys.loginEmailField,
textFieldBloc: formBloc.emailField,
decoration: InputDecoration(
fillColor: Colors.white,
contentPadding: EdgeInsets.only(left: 15, top: 15, bottom: 15),
labelText: t('Email'),
fillColor: Colors.white24,
filled: true,
labelText: 'Email',
border: OutlineInputBorder(
gapPadding: 4.0,
borderRadius: BorderRadius.circular(12.0),
borderSide: BorderSide(color: Colors.green[50], width: 0.4),
),
),
initialValue: loginBloc.userRepository.user.email,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (val) {
return t(loginBloc.emailValidation(val));
},
onChanged: (value) => loginBloc.add(LoginEmailChange(email: value)),
keyboardType: TextInputType.emailAddress,
style: new TextStyle(fontSize: 16, color: Colors.indigo),
),
Divider(
color: Colors.transparent,
),
TextFieldBlocBuilder(
TextFormField(
key: LibraryKeys.loginPasswordField,
textFieldBloc: formBloc.passwordField,
obscureText: true,
decoration: InputDecoration(
fillColor: Colors.white,
labelStyle: TextStyle(fontSize: 14),
contentPadding: EdgeInsets.only(left: 15, top: 15, bottom: 15),
suffixIcon: IconButton(
onPressed: () => {loginBloc.add(LoginPasswordChangeObscure())},
icon: Icon(Icons.remove_red_eye),
),
labelText: t('Password'),
fillColor: Colors.white24,
filled: true,
labelText: 'Password',
border: OutlineInputBorder(
gapPadding: 1.0,
borderRadius: BorderRadius.circular(12.0),
borderSide: BorderSide(color: Colors.green[50], width: 0.4),
),
),
suffixButton: SuffixButton.obscureText,
initialValue: loginBloc.userRepository.user.password,
autovalidateMode: AutovalidateMode.always,
validator: (val) {
return t(loginBloc.passwordValidation(val));
},
onChanged: (value) => loginBloc.add(LoginPasswordChange(password: value)),
keyboardType: TextInputType.visiblePassword,
style: new TextStyle(fontSize: 16, color: Colors.indigo),
),
Divider(
color: Colors.transparent,
@ -147,7 +161,7 @@ class _LoginWidget extends State<LoginWidget> with Common, Trans {
],
),
//Image.asset('asset/icon/gomb_zold_b-1.png', width: 100, height: 100),
onPressed: () => {formBloc.add(SubmitFormBloc())}),
onPressed: () => {loginBloc.add(LoginSubmit())}),
]),
Divider(
color: Colors.transparent,
@ -164,9 +178,14 @@ class _LoginWidget extends State<LoginWidget> with Common, Trans {
),
Spacer(flex: 2),
InkWell(
child: Text(AppLocalizations.of(context).translate('Privacy')),
onTap: () => Navigator.of(context).pushNamed('gdpr'),
),
child: Text(AppLocalizations.of(context).translate('Privacy')),
onTap: () => {
showDialog(
context: context,
builder: (BuildContext context) {
return DialogGDPR();
})
}),
]),
])),
);

Some files were not shown because too many files have changed in this diff Show More