diff --git a/android/.gitignore b/android/.gitignore index bc2100d..b37a358 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -4,4 +4,5 @@ gradle-wrapper.jar /gradlew /gradlew.bat /local.properties +key.properties GeneratedPluginRegistrant.java diff --git a/asset/image/man_sizes.png b/asset/image/man_sizes.png index dea4786..5e0397e 100644 Binary files a/asset/image/man_sizes.png and b/asset/image/man_sizes.png differ diff --git a/asset/image/woman_sizes.png b/asset/image/woman_sizes.png index 4c43331..1ffeb46 100644 Binary files a/asset/image/woman_sizes.png and b/asset/image/woman_sizes.png differ diff --git a/asset/menu/2.1.4.squats.jpg b/asset/menu/2.1.4.squats.jpg new file mode 100644 index 0000000..8a24cdd Binary files /dev/null and b/asset/menu/2.1.4.squats.jpg differ diff --git a/asset/menu/bent_over_rows.jpg b/asset/menu/bent_over_rows.jpg new file mode 100644 index 0000000..bc9397e Binary files /dev/null and b/asset/menu/bent_over_rows.jpg differ diff --git a/asset/menu/close_grip_bench_press.jpg b/asset/menu/close_grip_bench_press.jpg new file mode 100644 index 0000000..dbae95c Binary files /dev/null and b/asset/menu/close_grip_bench_press.jpg differ diff --git a/asset/menu/hyperextension_floor.jpg b/asset/menu/hyperextension_floor.jpg new file mode 100644 index 0000000..94ff75f Binary files /dev/null and b/asset/menu/hyperextension_floor.jpg differ diff --git a/asset/menu/pulldown_machine.jpg b/asset/menu/pulldown_machine.jpg new file mode 100644 index 0000000..c05eb39 Binary files /dev/null and b/asset/menu/pulldown_machine.jpg differ diff --git a/asset/menu/row_machine.jpg b/asset/menu/row_machine.jpg new file mode 100644 index 0000000..a0376c3 Binary files /dev/null and b/asset/menu/row_machine.jpg differ diff --git a/asset/wine-glass.mp3 b/asset/wine-glass.mp3 new file mode 100644 index 0000000..13c3273 Binary files /dev/null and b/asset/wine-glass.mp3 differ diff --git a/i18n/en.json b/i18n/en.json index 107ddcc..78d4c92 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -361,33 +361,36 @@ "Body Type Analyser":"Body Type Analyser", "How likely is it true about you?":"How likely is it true about you?", - "Very unlikely":"Very unlikely", + "Very unlikely":"Not True", "Maybe":"Maybe", - "Very likely":"Very likely", + "Very likely":"True", "« Back":"« Back", - "1. Basicly I am skinny and bonny":"1. Basicly I am skinny and bonny", - "2. question":"2. question", - "3. question":"3. question", - "4. question":"4. question", - "5. question":"5. question", - "6. question":"6. question", - "7. question":"7. question", - "8. question":"8. question", - "9. question":"9. question", - "10. question":"10. question", - "11. question":"11. question", - "12. question":"12. question", - "13. question":"13. question", - "14. question":"14. question", - "15. question":"15. question", - "16. question":"16. question", - "17. question":"17. question", - "18. question":"18. question", - "19. question":"19. question", - "20. question":"20. question", - "21. question":"21. question", - "22. question":"22. question", + "1. Basicly I am skinny and bonny":"1. I have basically a thin and bony physique", + "2. question":"2. Long limbs and narrow shoulders are typical of me", + "3. question":"3. It is difficult for me to build muscle", + "4. question":"4. My chest and waist are nearly the same width", + "5. question":"5. ’Chopstick’ was my nickname in the kindergarten", + "6. question":"6. I easily lose the muscle I built up", + "7. question":"7. To my knowledge, my body fat percentage is low", + "8. question":"8. Basically, I have a sporty and athletic physique", + "9. question":"9. I have a wide collarbone and shoulders", + "10. question":"10. My hips are narrow and my waist is sporty", + "11. question":"11. I get muscular quickly", + "12. question":"12. My chest is wider than my waist", + "13. question":"13. I could be the statue of David", + "14. question":"14. I have a strong calf and forearm", + "15. question":"15. I have a wide rib cage", + "16. question":"16. I have thick and wide joints", + "17. question":"17. My bones are strong", + "18. question":"18. My body is muscular but a little fatter", + "19. question":"19. My hips are wider than my chest", + "20. question":"20. Tun’ could be my nickname too", + "21. question":"21. I lose weight hard and gain weight more easily", + "22. question":"22. I have a strong and chunky physique", "Your Bodytype result":"Your Bodytype result", - "Change the weight to":"Change the weight to" + "Change the weight to":"Change the weight to", + + "Search Exercises...":"Search Exercises...", + "No exercise found":"No exercise found" } \ No newline at end of file diff --git a/i18n/hu.json b/i18n/hu.json index 149b0d2..1aa1001 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -361,7 +361,7 @@ "Maybe":"Talán", "Very likely":"Biztosan", "« Back":"« Vissza", - "1. Basicly I am skinny and bonny":"1. Alapvetően vékony csontos testalkat vagyok", + "1. Basicly I am skinny and bonny":"1. Alapvetően vékony, csontos testalkat vagyok", "2. question":"2. Hosszú végtagok, keskeny vállak jellemzőek rám", "3. question":"3. Nehezen tudok izmot növelni", "4. question":"4. Mellkasom, derekam közel egyforma szélességű", @@ -374,16 +374,19 @@ "11. question":"11. Gyorsan izmosodok", "12. question":"12. Szélesebb a mellkasom a derekamnál", "13. question":"13. Akár lehetnék én a Dávid szobor", - "14. question":"14. Erős vádli és alkar", + "14. question":"14. Erős vádli és alkar jellemez", "15. question":"15. Széles bordakosaram van", - "16. question":"16. Vastag széles ízületeim vannak", + "16. question":"16. Vastag, széles ízületeim vannak", "17. question":"17. Erős a csontozatom", "18. question":"18. Zsírosabb, de izmos vagyok", "19. question":"19. Szélesebb a csípőm a mellkasomnál", "20. question":"20. Hordó is lehetne a becenevem", "21. question":"21. Nehezen fogyok, könnyebben hízok", - "22. question":"22. Erős vaskos testalkat vagyok", + "22. question":"22. Erős, vaskos testalkat vagyok", "Your Bodytype result":"Testtípus eredményed", - "Change the weight to":"Súly változtatása" + "Change the weight to":"Súly változtatása", + + "Search Exercises...":"Gyakorlat keresése...", + "No exercise found":"Nincs ilyen gyakorlat" } \ No newline at end of file diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 1bc6c3d..0920532 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -6,6 +6,8 @@ PODS: - AppAuth/ExternalUserAgent (1.4.0) - apple_sign_in (0.0.1): - Flutter + - audioplayer (0.0.1): + - Flutter - devicelocale (0.0.1): - Flutter - FBSDKCoreKit (9.0.0): @@ -181,6 +183,7 @@ PODS: DEPENDENCIES: - apple_sign_in (from `.symlinks/plugins/apple_sign_in/ios`) + - audioplayer (from `.symlinks/plugins/audioplayer/ios`) - devicelocale (from `.symlinks/plugins/devicelocale/ios`) - firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`) - firebase_auth (from `.symlinks/plugins/firebase_auth/ios`) @@ -232,6 +235,8 @@ SPEC REPOS: EXTERNAL SOURCES: apple_sign_in: :path: ".symlinks/plugins/apple_sign_in/ios" + audioplayer: + :path: ".symlinks/plugins/audioplayer/ios" devicelocale: :path: ".symlinks/plugins/devicelocale/ios" firebase_analytics: @@ -274,6 +279,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: AppAuth: 31bcec809a638d7bd2f86ea8a52bd45f6e81e7c7 apple_sign_in: 7716c7ddfa195aeab7dec0dc374ef4ff45d1adb4 + audioplayer: 0584f31a697e4b0bbad405ae7903d7a93585e784 devicelocale: feebbe5e7a30adb8c4f83185de1b50ff19b44f00 FBSDKCoreKit: ac6cc500b8e104bb9a4dd20b1527b5d199123c2e FBSDKLoginKit: e9b6542fdee322333502ab497f628b011dce7d78 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index dbacf6c..91c705e 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -388,7 +388,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 2; DEVELOPMENT_TEAM = SFJJBDCU6Z; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -405,7 +405,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - MARKETING_VERSION = 1.1.6; + MARKETING_VERSION = 1.1.7; PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -531,7 +531,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 2; DEVELOPMENT_TEAM = SFJJBDCU6Z; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -548,7 +548,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - MARKETING_VERSION = 1.1.6; + MARKETING_VERSION = 1.1.7; PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -566,7 +566,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 2; DEVELOPMENT_TEAM = SFJJBDCU6Z; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -583,7 +583,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - MARKETING_VERSION = 1.1.6; + MARKETING_VERSION = 1.1.7; PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index d6084d5..c1bb7ff 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -47,8 +47,14 @@ 10.0 LSRequiresIPhoneOS + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + UIBackgroundModes + audio fetch remote-notification diff --git a/lib/bloc/development_by_muscle/development_by_muscle_bloc.dart b/lib/bloc/development_by_muscle/development_by_muscle_bloc.dart index cf14bd7..94f8cd7 100644 --- a/lib/bloc/development_by_muscle/development_by_muscle_bloc.dart +++ b/lib/bloc/development_by_muscle/development_by_muscle_bloc.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'dart:collection'; -import 'package:aitrainer_app/localization/app_language.dart'; +import 'package:aitrainer_app/util/app_language.dart'; import 'package:aitrainer_app/model/exercise.dart'; import 'package:aitrainer_app/model/workout_menu_tree.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; diff --git a/lib/bloc/development_sizes/development_sizes_bloc.dart b/lib/bloc/development_sizes/development_sizes_bloc.dart new file mode 100644 index 0000000..88cc1b7 --- /dev/null +++ b/lib/bloc/development_sizes/development_sizes_bloc.dart @@ -0,0 +1,32 @@ +import 'dart:async'; + +import 'package:aitrainer_app/model/cache.dart'; +import 'package:aitrainer_app/repository/customer_repository.dart'; +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; + +part 'development_sizes_event.dart'; +part 'development_sizes_state.dart'; + +class DevelopmentSizesBloc extends Bloc { + final CustomerRepository customerRepository; + DevelopmentSizesBloc({this.customerRepository}) : super(DevelopmentSizesInitial()) { + isMan = Cache().userLoggedIn.sex == "m"; + } + + bool isMan; + + @override + Stream mapEventToState( + DevelopmentSizesEvent event, + ) async* { + try { + if (state is DevelopmentSizesLoad) { + yield DevelopmentSizesLoading(); + yield DevelopmentSizesReady(); + } + } on Exception catch (e) { + yield DevelopmentSizesError(message: e.toString()); + } + } +} diff --git a/lib/bloc/development_sizes/development_sizes_event.dart b/lib/bloc/development_sizes/development_sizes_event.dart new file mode 100644 index 0000000..3468e59 --- /dev/null +++ b/lib/bloc/development_sizes/development_sizes_event.dart @@ -0,0 +1,12 @@ +part of 'development_sizes_bloc.dart'; + +abstract class DevelopmentSizesEvent extends Equatable { + const DevelopmentSizesEvent(); + + @override + List get props => []; +} + +class DevelopmentSizesLoad extends DevelopmentSizesEvent { + const DevelopmentSizesLoad(); +} diff --git a/lib/bloc/development_sizes/development_sizes_state.dart b/lib/bloc/development_sizes/development_sizes_state.dart new file mode 100644 index 0000000..a91b6a4 --- /dev/null +++ b/lib/bloc/development_sizes/development_sizes_state.dart @@ -0,0 +1,28 @@ +part of 'development_sizes_bloc.dart'; + +abstract class DevelopmentSizesState extends Equatable { + const DevelopmentSizesState(); + + @override + List get props => []; +} + +class DevelopmentSizesInitial extends DevelopmentSizesState { + const DevelopmentSizesInitial(); +} + +class DevelopmentSizesLoading extends DevelopmentSizesState { + const DevelopmentSizesLoading(); +} + +class DevelopmentSizesReady extends DevelopmentSizesState { + const DevelopmentSizesReady(); +} + +class DevelopmentSizesError extends DevelopmentSizesState { + final String message; + const DevelopmentSizesError({this.message}); + + @override + List get props => [this.message]; +} diff --git a/lib/bloc/exercise_control/exercise_control_bloc.dart b/lib/bloc/exercise_control/exercise_control_bloc.dart index 55a6241..127af32 100644 --- a/lib/bloc/exercise_control/exercise_control_bloc.dart +++ b/lib/bloc/exercise_control/exercise_control_bloc.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'package:aitrainer_app/bloc/timer/timer_bloc.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; @@ -9,6 +10,7 @@ part 'exercise_control_event.dart'; part 'exercise_control_state.dart'; class ExerciseControlBloc extends Bloc { + final TimerBloc timerBloc; final ExerciseRepository exerciseRepository; final bool readonly; final double percentToCalculate; @@ -25,7 +27,8 @@ class ExerciseControlBloc extends Bloc 100 ? (repeatOconner + repeatWendler) / 2 : repeatWendler; } } diff --git a/lib/bloc/exercise_new/exercise_new_bloc.dart b/lib/bloc/exercise_new/exercise_new_bloc.dart index c3355a5..64a8cb8 100644 --- a/lib/bloc/exercise_new/exercise_new_bloc.dart +++ b/lib/bloc/exercise_new/exercise_new_bloc.dart @@ -44,14 +44,12 @@ class ExerciseNewBloc extends Bloc with Logg String fitnessLevel; bool changedWeight = false; bool changedSizes = false; - final List womanSizes = List(); - final List manSizes = List(); final double baseWidth = 312; final double baseHeight = 675.2; double mediaWidth = 0; double mediaHeight = 0; - bool isMan = true; + String exerciseTask = ""; final StopWatchTimer stopWatchTimer = StopWatchTimer( @@ -73,7 +71,7 @@ class ExerciseNewBloc extends Bloc with Logg height = customerRepository.customer.getProperty("Height"); birthYear = customerRepository.customer.birthYear; fitnessLevel = customerRepository.customer.fitnessLevel; - this.isMan = (customerRepository.customer.sex == "m"); + } if (exerciseType.unit == "second") { stopWatchTimer.rawTime.listen((value) => {timerValue = value, this.setQuantity((value / 1000).toDouble())}); @@ -109,196 +107,6 @@ class ExerciseNewBloc extends Bloc with Logg exerciseRepository.setQuantity(quantity); } - void setMediaDimensions(double width, double height) { - this.mediaHeight = height; - this.mediaWidth = width; - this.addSizes(customerRepository.sex); - } - - void addSizes(String sex) { - List properties = Cache().getProperties(); - if (properties == null) { - return; - } - final double distortionWidth = mediaWidth / baseWidth; - final double distortionHeight = mediaHeight / baseHeight; - if (isMan) { - properties.forEach((element) { - if (element.propertyName == "Shoulder") { - element.top = (122 * distortionHeight).toInt(); - element.left = (130 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Shoulder"); - manSizes.add(element); - } else if (element.propertyName == "Neck") { - element.top = (68 * distortionHeight).toInt(); - element.left = (130 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Neck"); - manSizes.add(element); - } else if (element.propertyName == "Biceps") { - element.top = (178 * distortionHeight).toInt(); - element.left = (208 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Biceps"); - manSizes.add(element); - } else if (element.propertyName == "Chest") { - element.top = (154 * distortionHeight).toInt(); - element.left = (130 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Chest"); - manSizes.add(element); - } else if (element.propertyName == "Belly") { - element.top = (244 * distortionHeight).toInt(); - element.left = (130 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Belly"); - manSizes.add(element); - } else if (element.propertyName == "Hip") { - element.top = (308 * distortionHeight).toInt(); - element.left = (130 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Hip"); - manSizes.add(element); - } else if (element.propertyName == "Thigh Top") { - element.top = (332 * distortionHeight).toInt(); - element.left = (165 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Thigh Top"); - manSizes.add(element); - } else if (element.propertyName == "Thigh Middle") { - element.top = (382 * distortionHeight).toInt(); - element.left = (100 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Thigh Middle"); - manSizes.add(element); - } else if (element.propertyName == "Knee") { - element.top = (464 * distortionHeight).toInt(); - element.left = (97 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Knee"); - manSizes.add(element); - } else if (element.propertyName == "Calf") { - element.top = (520 * distortionHeight).toInt(); - element.left = (97 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Calf"); - manSizes.add(element); - } else if (element.propertyName == "Ankle") { - element.top = (620 * distortionHeight).toInt(); - element.left = (150 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Ankle"); - manSizes.add(element); - } else if (element.propertyName == "Weight") { - element.top = (402 * distortionHeight).toInt(); - element.left = (240 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Weight"); - manSizes.add(element); - } - }); - } else { - properties.forEach((element) { - if (element.propertyName == "Shoulder") { - element.top = (122 * distortionHeight).toInt(); - element.left = (151 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Shoulder"); - manSizes.add(element); - } else if (element.propertyName == "Neck") { - element.top = (78 * distortionHeight).toInt(); - element.left = (151 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Neck"); - manSizes.add(element); - } else if (element.propertyName == "Biceps") { - element.top = (178 * distortionHeight).toInt(); - element.left = (212 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Biceps"); - manSizes.add(element); - } else if (element.propertyName == "Chest") { - element.top = (154 * distortionHeight).toInt(); - element.left = (151 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Chest"); - manSizes.add(element); - } else if (element.propertyName == "Belly") { - element.top = (230 * distortionHeight).toInt(); - element.left = (151 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Belly"); - manSizes.add(element); - } else if (element.propertyName == "Hip") { - element.top = (294 * distortionHeight).toInt(); - element.left = (151 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Hip"); - manSizes.add(element); - } else if (element.propertyName == "Thigh Top") { - element.top = (335 * distortionHeight).toInt(); - element.left = (185 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Thigh Top"); - manSizes.add(element); - } else if (element.propertyName == "Thigh Middle") { - element.top = (377 * distortionHeight).toInt(); - element.left = (125 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Thigh Middle"); - manSizes.add(element); - } else if (element.propertyName == "Knee") { - element.top = (468 * distortionHeight).toInt(); - element.left = (129 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Knee"); - manSizes.add(element); - } else if (element.propertyName == "Calf") { - element.top = (525 * distortionHeight).toInt(); - element.left = (129 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Calf"); - manSizes.add(element); - } else if (element.propertyName == "Ankle") { - element.top = (620 * distortionHeight).toInt(); - element.left = (162 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Ankle"); - manSizes.add(element); - } else if (element.propertyName == "Weight") { - element.top = (402 * distortionHeight).toInt(); - element.left = (240 * distortionWidth).toInt(); - element.value = customerRepository.customer.getProperty("Weight"); - manSizes.add(element); - } - }); - } - } - - 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 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 sizes; - if (customerRepository.sex == "Man") { - sizes = this.manSizes; - } else { - sizes = this.womanSizes; - } - - sizes.forEach((element) { - if (element.propertyName == propertyName) { - element.value = value; - } - }); - } - @override Stream mapEventToState(ExerciseNewEvent event) async* { try { @@ -358,7 +166,7 @@ class ExerciseNewBloc extends Bloc with Logg } else if (event is ExerciseNewSizeChange) { yield ExerciseNewLoading(); this.changedSizes = true; - this.updateSizes(event.propertyName, event.value); + this.customerRepository.updateSizes(event.propertyName, event.value); customerRepository.setCustomerProperty(event.propertyName, event.value); yield ExerciseNewReady(); } else if (event is ExerciseNewSubmit) { diff --git a/lib/bloc/session/session_bloc.dart b/lib/bloc/session/session_bloc.dart index dee7093..e13d6e9 100644 --- a/lib/bloc/session/session_bloc.dart +++ b/lib/bloc/session/session_bloc.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:aitrainer_app/bloc/settings/settings_bloc.dart'; -import 'package:aitrainer_app/localization/app_language.dart'; +import 'package:aitrainer_app/util/app_language.dart'; import 'package:aitrainer_app/service/logging.dart'; import 'package:aitrainer_app/util/session.dart'; import 'package:bloc/bloc.dart'; diff --git a/lib/bloc/settings/settings_bloc.dart b/lib/bloc/settings/settings_bloc.dart index abc9aab..25553b2 100644 --- a/lib/bloc/settings/settings_bloc.dart +++ b/lib/bloc/settings/settings_bloc.dart @@ -1,7 +1,7 @@ import 'dart:async'; -import 'package:aitrainer_app/localization/app_language.dart'; -import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/util/app_language.dart'; +import 'package:aitrainer_app/util/app_localization.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/service/logging.dart'; import 'package:aitrainer_app/util/enums.dart'; diff --git a/lib/bloc/timer/timer_bloc.dart b/lib/bloc/timer/timer_bloc.dart new file mode 100644 index 0000000..1abb16f --- /dev/null +++ b/lib/bloc/timer/timer_bloc.dart @@ -0,0 +1,106 @@ +import 'dart:async'; + +import 'package:audioplayer/audioplayer.dart'; +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; + +part 'timer_event.dart'; +part 'timer_state.dart'; + +class Ticker { + Stream tick({int ticks}) { + return Stream.periodic(Duration(seconds: 1), (x) => compute(ticks, x)).take(ticks); + } + + int compute(int ticks, int x) { + //print("tcik: " + (ticks - x - 1).toString()); + return ticks - x - 1; + } +} + +class TimerBloc extends Bloc { + final Ticker _ticker = Ticker(); + int _duration = 0; + + final AudioPlayer audioPlayer = AudioPlayer(); + int minutes = 0; + int seconds = 0; + + StreamSubscription _tickerSubscription; + + TimerBloc() : super(TimerReady(300)); + + @override + void onTransition(Transition transition) { + super.onTransition(transition); + //print(transition); + } + + @override + Stream mapEventToState( + TimerEvent event, + ) async* { + if (event is TimerStart) { + yield* _mapStartToState(event); + } else if (event is TimerPause) { + yield* _mapPauseToState(event); + } else if (event is TimerResume) { + yield* _mapResumeToState(event); + } else if (event is TimerReset) { + yield* _mapResetToState(event); + } else if (event is TimerTick) { + yield* _mapTickToState(event); + } else if (event is TimerEnd) { + print("$event"); + _tickerSubscription?.cancel(); + yield TimerFinished(state.duration); + } + } + + @override + Future close() { + _tickerSubscription?.cancel(); + return super.close(); + } + + Stream _mapStartToState(TimerStart start) async* { + //print("$start"); + yield TimerRunning(start.duration); + _tickerSubscription?.cancel(); + _tickerSubscription = _ticker.tick(ticks: start.duration).listen( + (localDuration) { + //print("local: $localDuration"); + add(TimerTick(duration: localDuration)); + }, + ); + } + + Stream _mapPauseToState(TimerPause pause) async* { + if (state is TimerRunning) { + _tickerSubscription?.pause(); + yield TimerPaused(state.duration); + } + } + + Stream _mapResumeToState(TimerResume pause) async* { + if (state is TimerPaused) { + _tickerSubscription?.resume(); + yield TimerRunning(state.duration); + } + } + + Stream _mapResetToState(TimerReset reset) async* { + this._duration = 0; + yield TimerReady(_duration); + } + + Stream _mapTickToState(TimerTick tick) async* { + //print("tick $tick"); + yield TickStart(tick.duration); + yield tick.duration >= 0 ? TimerRunning(tick.duration) : TimerFinished(tick.duration); + } + + Future _play() async { + await audioPlayer.play('asset/wine-glass.mp3', isLocal: true); + } +} diff --git a/lib/bloc/timer/timer_event.dart b/lib/bloc/timer/timer_event.dart new file mode 100644 index 0000000..0d935a1 --- /dev/null +++ b/lib/bloc/timer/timer_event.dart @@ -0,0 +1,41 @@ +part of 'timer_bloc.dart'; + +abstract class TimerEvent extends Equatable { + const TimerEvent(); + + @override + List get props => []; +} + +class TimerStart extends TimerEvent { + final int duration; + const TimerStart({this.duration}); + + @override + String toString() => "TimerStart { duration: $duration }"; +} + +class TimerEnd extends TimerEvent { + final int duration; + const TimerEnd({this.duration}); +} + +class TimerTick extends TimerEvent { + final int duration; + const TimerTick({this.duration}); + + @override + String toString() => "Tick { duration: $duration }"; +} + +class TimerPause extends TimerEvent { + const TimerPause(); +} + +class TimerResume extends TimerEvent { + const TimerResume(); +} + +class TimerReset extends TimerEvent { + const TimerReset(); +} diff --git a/lib/bloc/timer/timer_state.dart b/lib/bloc/timer/timer_state.dart new file mode 100644 index 0000000..0c69778 --- /dev/null +++ b/lib/bloc/timer/timer_state.dart @@ -0,0 +1,49 @@ +part of 'timer_bloc.dart'; + +abstract class TimerState extends Equatable { + final int duration; + + TimerState(this.duration, [List props = const []]); + + @override + List get props => []; +} + +class TickStart extends TimerState { + TickStart(int duration) : super(duration); + @override + String toString() => 'Start { duration: $duration }'; +} + +class TimerRunning extends TimerState { + TimerRunning(int duration) : super(duration); + + @override + String toString() => 'Running { duration: $duration }'; +} + +class TimerReady extends TimerState { + TimerReady(int duration) : super(duration); + + @override + String toString() => 'Ready { duration: $duration }'; +} + +class TimerPaused extends TimerState { + TimerPaused(int duration) : super(duration); + + @override + String toString() => 'Paused { duration: $duration }'; +} + +class TimerFinished extends TimerState { + TimerFinished(int duration) : super(duration); + + @override + String toString() => 'Finished { duration: $duration }'; +} + +class TimerError extends TimerState { + final String message; + TimerError(int duration, {this.message}) : super(duration); +} diff --git a/lib/library/clock.dart b/lib/library/clock.dart new file mode 100644 index 0000000..bb455ff --- /dev/null +++ b/lib/library/clock.dart @@ -0,0 +1,161 @@ +import 'package:aitrainer_app/bloc/timer/timer_bloc.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'dart:math'; +import 'package:google_fonts/google_fonts.dart'; + +final temperatureColors = [ + const Color(0xFFB50DE2), // -20 Celsius , friggin cold + const Color(0xFFAE0DE2), + const Color(0xFF980DE2), + const Color(0xFF8E0DE2), + const Color(0xFF810DE2), + const Color(0xFF7B0DE2), + const Color(0xFF670DE2), + const Color(0xFF570DE2), + const Color(0xFF4A0DE2), + const Color(0xFF410DE2), + const Color(0xFF1D0DE2), + const Color(0xFF0D4AE2), + const Color(0xFF0D57E2), + const Color(0xFF0D74E2), + const Color(0xFF0DB8E2), + const Color(0xFF0DD8E2), + const Color(0xFF0DE2BB), + const Color(0xFF0DE2A1), + const Color(0xFF0DE284), + const Color(0xFF0DE25E), + const Color(0xFF0DE244), + const Color(0xFF84E20D), + const Color(0xFFC2E20D), + const Color(0xFFE2DF0D), + const Color(0xFFE2A10D), + const Color(0xFFE2740D), + const Color(0xFFE2510D), + const Color(0xFFE22D0D), + const Color(0xFFE2100D), + const Color(0xFFE20D17), // 40 Celsius, rather be dead +]; + +// ignore: must_be_immutable +class Clock extends StatelessWidget { + final TimerBloc bloc; + final List colors = temperatureColors; + + Clock({this.bloc}); + + // ignore: close_sinks + + final Paint paintSeconds = Paint() + ..strokeCap = StrokeCap.butt + ..style = PaintingStyle.stroke + ..strokeWidth = 4 + ..isAntiAlias = true; + + final Paint paintMinutes = Paint() + ..strokeCap = StrokeCap.butt + ..style = PaintingStyle.stroke + ..strokeWidth = 4 + ..isAntiAlias = true; + + final Paint paintHours = Paint() + ..strokeCap = StrokeCap.butt + ..style = PaintingStyle.stroke + ..strokeWidth = 4 + ..isAntiAlias = true; + + @override + Widget build(BuildContext context) { + return BlocBuilder(builder: (context, state) { + if (state is TimerRunning) { + return getLayout(bloc.state); + } else { + return Offstage(); + } + }); + } + + Widget getLayout(TimerState state) { + int duration = 300 - state.duration; + int seconds = (duration % 60).floor(); + int minutes = ((duration / 60) % 60).floor(); + String secondStr = seconds.toString().padLeft(2, '0'); + String time = minutes == 0 ? "$secondStr" : "$minutes:$secondStr"; + return LayoutBuilder(builder: (context, constraints) { + return Stack( + alignment: Alignment.center, + fit: StackFit.expand, + children: [ + Positioned( + top: 37, + left: (45 - time.length / 2 * 9).toDouble(), //seconds < 10 ? 37 : 30, + child: Text( + "$time", + style: GoogleFonts.kosugi(color: colors[(seconds ~/ 2)], fontSize: 16), + )), + CustomPaint(painter: ArcPainter(minutes, paintMinutes, 5, constraints.maxHeight * 0.40, 0.15, colors)), + CustomPaint(painter: ArcPainter(seconds, paintSeconds, 60, constraints.maxHeight * 0.34, 0.2, colors)), + ], + ); + }); + } +} + +class ArcPainter extends CustomPainter { + int _progress; + Paint _paint; + int _units; + double _gap; + + List _gradient; + + Offset center; + double _radius; + + Paint paintMarkerEmpty; + + ArcPainter( + this._progress, + this._paint, + this._units, + this._radius, + this._gap, + this._gradient, + ) { + this.paintMarkerEmpty = Paint() + ..strokeCap = StrokeCap.butt + ..style = PaintingStyle.stroke + ..strokeWidth = this._paint.strokeWidth + ..isAntiAlias = true; + } + + @override + void paint(Canvas canvas, Size size) { + center = Offset(size.width / 2, size.height / 2); + var rect = Rect.fromCircle(center: center, radius: this._radius); + + final gradient2 = new SweepGradient( + startAngle: -pi / 2, + endAngle: (-pi / 2) + (pi * 2), + tileMode: TileMode.repeated, + colors: this._gradient, + ); + + this._paint.shader = gradient2.createShader(rect); + + this.paintMarkerEmpty.color = this._gradient[0].withOpacity(0.2); + + for (var i = 0; i < this._units; i++) { + final double unit = 2 * pi / this._units; + double start = unit * i; + double to = (((2 * pi) / this._units) + unit); + + canvas.drawArc(rect, (-pi / 2 + start), to * 2 * this._gap, false, i < this._progress ? this._paint : this.paintMarkerEmpty); + } + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) { + return true; + } +} diff --git a/lib/main.dart b/lib/main.dart index 1b22712..ca7c048 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -26,6 +26,7 @@ import 'package:aitrainer_app/view/menu_page.dart'; import 'package:aitrainer_app/view/mydevelopment_body_page.dart'; import 'package:aitrainer_app/view/mydevelopment_muscle_page.dart'; import 'package:aitrainer_app/view/mydevelopment_page.dart'; +import 'package:aitrainer_app/view/mydevelopment_sizes_page.dart'; import 'package:aitrainer_app/view/myexcercise_plan_page.dart'; import 'package:aitrainer_app/view/registration.dart'; import 'package:aitrainer_app/view/reset_password.dart'; @@ -40,7 +41,7 @@ import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; -import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/util/app_localization.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:sentry/sentry.dart'; import 'bloc/account/account_bloc.dart'; @@ -51,6 +52,7 @@ import 'bloc/exercise_plan/exercise_plan_bloc.dart'; import 'bloc/menu/menu_bloc.dart'; import 'bloc/session/session_bloc.dart'; import 'bloc/settings/settings_bloc.dart'; +import 'bloc/timer/timer_bloc.dart'; const dsn = 'https://5fac40cbfcfb4c15aa80c7a8638d7310@o418565.ingest.sentry.io/5322520'; @@ -145,6 +147,9 @@ Future main() async { BlocProvider( create: (BuildContext context) => BodyDevelopmentBloc(workoutTreeRepository: menuTreeRepository), ), + BlocProvider( + create: (BuildContext context) => TimerBloc(), + ), ], child: WorkoutTestApp(), )); @@ -218,6 +223,7 @@ class WorkoutTestApp extends StatelessWidget { 'exerciseExecuteAddPage': (context) => ExerciseExecutePlanAddPage(), 'mydevelopmentMusclePage': (context) => MyDevelopmentMusclePage(), 'mydevelopmentBodyPage': (context) => MyDevelopmentBodyPage(), + 'mydevelopmentSizesPage': (context) => SizesDevelopmentPage(), 'evaluationPage': (context) => EvaluationPage(), 'salesPage': (context) => SalesPage(), }, diff --git a/lib/model/cache.dart b/lib/model/cache.dart index 977896a..1e68b38 100644 --- a/lib/model/cache.dart +++ b/lib/model/cache.dart @@ -62,6 +62,7 @@ class Cache with Logging { static final String serverKey = 'live'; static final String hardwareKey = 'hardware'; static final String loginTypeKey = 'login_type'; + static final String timerDisplayKey = 'timer_display'; static String baseUrl = 'http://aitrainer.info:8888/api/'; static final String mediaUrl = 'https://aitrainer.info:4343/media/'; @@ -421,7 +422,7 @@ class Cache with Logging { int _ecto = customerRepository.getCustomerPropertyValue(PropertyEnum.Ectomorph.toStr()).toInt(); int _mezo = customerRepository.getCustomerPropertyValue(PropertyEnum.Mesomorph.toStr()).toInt(); int _endo = customerRepository.getCustomerPropertyValue(PropertyEnum.Endomorph.toStr()).toInt(); - print("endo " + _endo.toString() + " mezo " + _mezo.toString()); + //print("endo " + _endo.toString() + " mezo " + _mezo.toString()); if (this.userLoggedIn != null) { if (this.userLoggedIn.birthYear == null || this.userLoggedIn.birthYear == 0) { setBadge("personalData", true); diff --git a/lib/model/workout_menu_tree.dart b/lib/model/workout_menu_tree.dart index 3a0258e..f65c7c1 100644 --- a/lib/model/workout_menu_tree.dart +++ b/lib/model/workout_menu_tree.dart @@ -38,9 +38,26 @@ class WorkoutMenuTree { bool executed = false; String exerciseDetail; String nameEnglish; + String parentName; + String parentNameEnglish; - WorkoutMenuTree(this.id, this.parent, this.name, this.imageName, this.color, this.fontSize, this.child, this.exerciseTypeId, - this.exerciseType, this.base, this.is1RM, this.isEndurance, this.isRunning, this.nameEnglish); + WorkoutMenuTree( + this.id, + this.parent, + this.name, + this.imageName, + this.color, + this.fontSize, + this.child, + this.exerciseTypeId, + this.exerciseType, + this.base, + this.is1RM, + this.isEndurance, + this.isRunning, + this.nameEnglish, + this.parentName, + this.parentNameEnglish); Map toJson() { return { diff --git a/lib/repository/customer_repository.dart b/lib/repository/customer_repository.dart index 35745b3..5444a80 100644 --- a/lib/repository/customer_repository.dart +++ b/lib/repository/customer_repository.dart @@ -11,6 +11,7 @@ import 'package:aitrainer_app/service/customer_service.dart'; import 'package:aitrainer_app/service/logging.dart'; import 'package:aitrainer_app/service/product_test_service.dart'; import 'package:aitrainer_app/service/purchase_service.dart'; +import 'package:aitrainer_app/util/enums.dart'; import 'package:aitrainer_app/util/not_found_exception.dart'; class GenderItem { @@ -25,6 +26,14 @@ class CustomerRepository with Logging { List _trainees; List _allProperties; final PropertyRepository propertyRepository = PropertyRepository(); + final List womanSizes = List(); + final List manSizes = List(); + + final double baseWidth = 312; + final double baseHeight = 675.2; + double mediaWidth = 0; + double mediaHeight = 0; + bool isMan = true; //List customerList = List(); bool visibleDetails = false; @@ -32,10 +41,10 @@ class CustomerRepository with Logging { CustomerRepository({this.customer}) { customer = Customer(); - genders = [ - GenderItem("m", "Man"), - GenderItem("w", "Woman"), - ]; + + if (Cache().userLoggedIn != null) { + isMan = (Cache().userLoggedIn.sex == "m"); + } } String getGenderByName(String name) { @@ -297,4 +306,194 @@ class CustomerRepository with Logging { Future addProductTest(ProductTest productTest) async { await ProductTestApi().saveProductTest(productTest); } + + void setMediaDimensions(double width, double height) { + this.mediaHeight = height; + this.mediaWidth = width; + this.addSizes(this.sex); + } + + void addSizes(String sex) { + List properties = Cache().getProperties(); + if (properties == null) { + return; + } + final double distortionWidth = mediaWidth / baseWidth; + final double distortionHeight = mediaHeight / baseHeight; + if (isMan) { + properties.forEach((element) { + if (element.propertyName == "Shoulder") { + element.top = (122 * distortionHeight).toInt(); + element.left = (130 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Shoulder"); + manSizes.add(element); + } else if (element.propertyName == "Neck") { + element.top = (68 * distortionHeight).toInt(); + element.left = (130 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Neck"); + manSizes.add(element); + } else if (element.propertyName == "Biceps") { + element.top = (178 * distortionHeight).toInt(); + element.left = (208 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Biceps"); + manSizes.add(element); + } else if (element.propertyName == "Chest") { + element.top = (154 * distortionHeight).toInt(); + element.left = (130 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Chest"); + manSizes.add(element); + } else if (element.propertyName == "Belly") { + element.top = (244 * distortionHeight).toInt(); + element.left = (130 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Belly"); + manSizes.add(element); + } else if (element.propertyName == "Hip") { + element.top = (308 * distortionHeight).toInt(); + element.left = (130 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Hip"); + manSizes.add(element); + } else if (element.propertyName == "Thigh Top") { + element.top = (332 * distortionHeight).toInt(); + element.left = (165 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Thigh Top"); + manSizes.add(element); + } else if (element.propertyName == "Thigh Middle") { + element.top = (382 * distortionHeight).toInt(); + element.left = (100 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Thigh Middle"); + manSizes.add(element); + } else if (element.propertyName == "Knee") { + element.top = (464 * distortionHeight).toInt(); + element.left = (97 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Knee"); + manSizes.add(element); + } else if (element.propertyName == "Calf") { + element.top = (520 * distortionHeight).toInt(); + element.left = (97 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Calf"); + manSizes.add(element); + } else if (element.propertyName == "Ankle") { + element.top = (620 * distortionHeight).toInt(); + element.left = (150 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Ankle"); + manSizes.add(element); + } else if (element.propertyName == "Weight") { + element.top = (402 * distortionHeight).toInt(); + element.left = (240 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Weight"); + manSizes.add(element); + } + }); + } else { + properties.forEach((element) { + if (element.propertyName == "Shoulder") { + element.top = (122 * distortionHeight).toInt(); + element.left = (151 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Shoulder"); + manSizes.add(element); + } else if (element.propertyName == "Neck") { + element.top = (78 * distortionHeight).toInt(); + element.left = (151 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Neck"); + manSizes.add(element); + } else if (element.propertyName == "Biceps") { + element.top = (178 * distortionHeight).toInt(); + element.left = (212 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Biceps"); + manSizes.add(element); + } else if (element.propertyName == "Chest") { + element.top = (154 * distortionHeight).toInt(); + element.left = (151 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Chest"); + manSizes.add(element); + } else if (element.propertyName == "Belly") { + element.top = (230 * distortionHeight).toInt(); + element.left = (151 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Belly"); + manSizes.add(element); + } else if (element.propertyName == "Hip") { + element.top = (294 * distortionHeight).toInt(); + element.left = (151 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Hip"); + manSizes.add(element); + } else if (element.propertyName == "Thigh Top") { + element.top = (335 * distortionHeight).toInt(); + element.left = (185 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Thigh Top"); + manSizes.add(element); + } else if (element.propertyName == "Thigh Middle") { + element.top = (377 * distortionHeight).toInt(); + element.left = (125 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Thigh Middle"); + manSizes.add(element); + } else if (element.propertyName == "Knee") { + element.top = (468 * distortionHeight).toInt(); + element.left = (129 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Knee"); + manSizes.add(element); + } else if (element.propertyName == "Calf") { + element.top = (525 * distortionHeight).toInt(); + element.left = (129 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Calf"); + manSizes.add(element); + } else if (element.propertyName == "Ankle") { + element.top = (620 * distortionHeight).toInt(); + element.left = (162 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Ankle"); + manSizes.add(element); + } else if (element.propertyName == "Weight") { + element.top = (402 * distortionHeight).toInt(); + element.left = (240 * distortionWidth).toInt(); + element.value = this.customer.getProperty("Weight"); + manSizes.add(element); + } + }); + } + } + + int getWeightCoordinate(isMan, {isTop = false, isLeft = false}) { + int value = 0; + this.manSizes.forEach((element) { + if (element.propertyName == SizesEnum.Weight.toStr()) { + if (isTop == true) { + value = element.top; + } else if (isLeft == true) { + value = element.left; + } + } + }); + return value; + } + + Property getPropertyByName(String propertyName) { + Property property; + List sizes; + if (this.sex == "m") { + 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 sizes; + if (this.sex == "m") { + sizes = this.manSizes; + } else { + sizes = this.womanSizes; + } + + sizes.forEach((element) { + if (element.propertyName == propertyName) { + element.value = value; + } + }); + } } diff --git a/lib/repository/exercise_repository.dart b/lib/repository/exercise_repository.dart index a7affed..1afc4e0 100644 --- a/lib/repository/exercise_repository.dart +++ b/lib/repository/exercise_repository.dart @@ -1,6 +1,6 @@ import 'dart:collection'; -import 'package:aitrainer_app/localization/app_language.dart'; +import 'package:aitrainer_app/util/app_language.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/customer.dart'; import 'package:aitrainer_app/model/exercise.dart'; diff --git a/lib/repository/workout_tree_repository.dart b/lib/repository/workout_tree_repository.dart index 22e9684..eb9f439 100644 --- a/lib/repository/workout_tree_repository.dart +++ b/lib/repository/workout_tree_repository.dart @@ -1,5 +1,5 @@ import 'dart:collection'; -import 'package:aitrainer_app/localization/app_language.dart'; +import 'package:aitrainer_app/util/app_language.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/exercise_ability.dart'; import 'package:aitrainer_app/model/exercise_tree.dart'; @@ -35,6 +35,7 @@ class WorkoutTreeRepository with Logging { SplayTreeMap sortedTree = SplayTreeMap>(); bool isEnglish; WorkoutType workoutType; + final List menuAsExercise = List(); final Map _antagonist = { Antagonist.chest: Antagonist.chestNr, @@ -85,23 +86,24 @@ class WorkoutTreeRepository with Logging { if (isRunning == false && treeItem.parentId != 0) { isRunning = isParentRunning(treeItem.parentId); } - + WorkoutMenuTree parent = getParentItem(treeItem.parentId); WorkoutMenuTree menuItem = WorkoutMenuTree( - treeItem.treeId, - treeItem.parentId, - treeName, - treeItem.imageUrl, - Colors.white, - 30, - false, - 0, - null, - false, - is1RM, - isEndurance, - isRunning, - treeItem.name, - ); + treeItem.treeId, + treeItem.parentId, + treeName, + treeItem.imageUrl, + Colors.white, + 30, + false, + 0, + null, + false, + is1RM, + isEndurance, + isRunning, + treeItem.name, + parent != null ? parent.name : "", + parent != null ? parent.nameEnglish : ""); menuItem = this.setWorkoutTypes(menuItem, treeItem); this.tree[treeItem.name + "_" + treeItem.parentId.toString()] = menuItem; //log("WorkoutMenuTree item " + menuItem.toJson().toString()); @@ -113,6 +115,7 @@ class WorkoutTreeRepository with Logging { exerciseType.active == true) { String exerciseTypeName = isEnglish ? exerciseType.name : exerciseType.nameTranslation; //String assetImage = await _buildImage(exerciseType.imageUrl); //'asset/menu/' + exerciseType.imageUrl.substring(7); + if (exerciseType.parents.isNotEmpty) { exerciseType.parents.forEach((parentId) { bool is1RM = this.isParent1RM(parentId); @@ -121,6 +124,7 @@ class WorkoutTreeRepository with Logging { if (isEndurance) exerciseType.setAbility(ExerciseAbility.endurance); bool isRunning = this.isParentRunning(parentId); if (isRunning) exerciseType.setAbility(ExerciseAbility.running); + WorkoutMenuTree parent = getParentItem(parentId); WorkoutMenuTree menuItem = WorkoutMenuTree( exerciseType.exerciseTypeId, parentId, @@ -135,8 +139,11 @@ class WorkoutTreeRepository with Logging { is1RM, isEndurance, isRunning, - exerciseType.name); + exerciseType.name, + parent != null ? parent.name : "", + parent != null ? parent.nameEnglish : ""); this.tree[exerciseType.name] = menuItem; + menuAsExercise.add(menuItem); //log("WorkoutMenuTree item " + menuItem.toJson().toString()); /* log("ExerciseType in Menu item " + exerciseType.toJson().toString() + @@ -156,6 +163,7 @@ class WorkoutTreeRepository with Logging { Cache().setWorkoutMenuTree(tree); ExerciseRepository exerciseRepository = ExerciseRepository(); exerciseRepository.getBaseExerciseFinishedPercent(); + menuAsExercise.sort((a, b) => a.name.compareTo(b.name)); } WorkoutMenuTree setWorkoutTypes(WorkoutMenuTree menu, ExerciseTree treeItem) { diff --git a/lib/localization/app_language.dart b/lib/util/app_language.dart similarity index 100% rename from lib/localization/app_language.dart rename to lib/util/app_language.dart diff --git a/lib/localization/app_localization.dart b/lib/util/app_localization.dart similarity index 100% rename from lib/localization/app_localization.dart rename to lib/util/app_localization.dart diff --git a/lib/util/common.dart b/lib/util/common.dart index 1d72988..1add7a9 100644 --- a/lib/util/common.dart +++ b/lib/util/common.dart @@ -1,6 +1,6 @@ import 'dart:convert'; -import 'package:aitrainer_app/localization/app_language.dart'; +import 'package:aitrainer_app/util/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'; diff --git a/lib/util/enums.dart b/lib/util/enums.dart index 779ac2b..6c122d2 100644 --- a/lib/util/enums.dart +++ b/lib/util/enums.dart @@ -36,7 +36,7 @@ enum TrackingEvent { my_special_plan, my_suggested_plan, prediction, - + search, exercise_device, customer_change, settings_lang, @@ -62,3 +62,11 @@ extension PropertyExt on PropertyEnum { bool equalsTo(PropertyEnum event) => this.toString() == event.toString(); bool equalsStringTo(String event) => this.toString() == event; } + +enum SizesEnum { Weight, Height, Shoulder, Neck, Biceps, Chest, Belly, Hip, ThighTop, ThighMiddle, Knee, Calf, Ankle, Underarm, Lowerarm } + +extension SizesExt on SizesEnum { + String toStr() => this.toString().split(".").last; + bool equalsTo(SizesEnum event) => this.toString() == event.toString(); + bool equalsStringTo(String event) => this.toString() == event; +} diff --git a/lib/util/platform_purchase.dart b/lib/util/platform_purchase.dart deleted file mode 100644 index a183e98..0000000 --- a/lib/util/platform_purchase.dart +++ /dev/null @@ -1,231 +0,0 @@ -/* -import 'package:aitrainer_app/model/cache.dart'; -import 'package:aitrainer_app/model/product.dart'; -import 'package:aitrainer_app/service/logging.dart'; -import 'package:in_app_purchase/in_app_purchase.dart'; - -class PlatformPurchaseApi with Logging { - static final PlatformPurchaseApi _singleton = PlatformPurchaseApi._internal(); - - bool _kAutoConsume = true; - final String _kConsumableId = 'consumable'; - final InAppPurchaseConnection _connection = InAppPurchaseConnection.instance; - bool _isAvailable = false; - List _products = []; - List _purchases = []; - List _notFoundIds = []; - List _consumables = []; - bool _purchasePending = false; - String _queryProductError; - - StreamSubscription> _subscription; - - final List _productList = List(); - - List getProductList() => _productList; - - factory PlatformPurchaseApi() { - return _singleton; - } - - PlatformPurchaseApi._internal(); - - Future close() async { - _subscription.cancel(); - } - - Future initStoreInfo() async { - final bool isAvailable = await _connection.isAvailable(); - if (!isAvailable) { - _isAvailable = isAvailable; - _products = []; - _purchases = []; - _notFoundIds = []; - _consumables = []; - _purchasePending = false; - log("Payment processor not available"); - return; - } - - getSubscriptions(); - ProductDetailsResponse productDetailResponse = await _connection.queryProductDetails(_productList.toSet()); - log("ProductDetailsResponse " + productDetailResponse.toString()); - if (productDetailResponse.error != null) { - _queryProductError = productDetailResponse.error.message; - _isAvailable = isAvailable; - _products = productDetailResponse.productDetails; - _purchases = []; - _notFoundIds = productDetailResponse.notFoundIDs; - _consumables = []; - _purchasePending = false; - log("Payment processor not available"); - return; - } - - if (productDetailResponse.productDetails.isEmpty) { - _queryProductError = null; - _isAvailable = isAvailable; - _products = productDetailResponse.productDetails; - _purchases = []; - _notFoundIds = productDetailResponse.notFoundIDs; - _consumables = []; - _purchasePending = false; - - return; - } - - _products = productDetailResponse.productDetails; - _products.forEach((element) { - ProductDetails product = element as ProductDetails; - log("Product " + product.id + " " + product.price + " " + product.skuDetail.toString()); - }); - - final QueryPurchaseDetailsResponse purchaseResponse = await _connection.queryPastPurchases(); - if (purchaseResponse.error != null) { - // handle query past purchase error.. - } - - final List verifiedPurchases = []; - for (PurchaseDetails purchase in purchaseResponse.pastPurchases) { - if (await _verifyPurchase(purchase)) { - verifiedPurchases.add(purchase); - } - } - - //TODO List consumables = await ConsumableStore.load(); - _isAvailable = isAvailable; - _products = productDetailResponse.productDetails; - _purchases = verifiedPurchases; - _notFoundIds = productDetailResponse.notFoundIDs; - //_consumables = consumables; - _purchasePending = false; - } - - // Platform messages are asynchronous, so we initialize in an async method. - Future initPurchasePlatform() async { - if (_productList.length > 0) { - return; - } - log(' --- InappPurchase connection: $_connection'); - log(" --- Init PurchasePlatform"); - await this.initStoreInfo(); - - Stream purchaseUpdated = InAppPurchaseConnection.instance.purchaseUpdatedStream; - _subscription = purchaseUpdated.listen((purchaseDetailsList) { - _listenToPurchaseUpdated(purchaseDetailsList); - }, onDone: () { - _subscription.cancel(); - }, onError: (error) { - // handle error here. - log("Error listen purchase updated " + error.toString()); - }); - } - - void deliverProduct(PurchaseDetails purchaseDetails) async { - log("DeliverProduct"); - // IMPORTANT!! Always verify a purchase purchase details before delivering the product. - if (purchaseDetails.productID == _kConsumableId) { - //TODO - //await ConsumableStore.save(purchaseDetails.purchaseID); - //List consumables = await ConsumableStore.load(); - - _purchasePending = false; - //_consumables = consumables; - } else { - _purchases.add(purchaseDetails); - _purchasePending = false; - } - } - - Future _verifyPurchase(PurchaseDetails purchaseDetails) { - log("verifyPurchase"); - // IMPORTANT!! Always verify a purchase before delivering the product. - // For the purpose of an example, we directly return true. - log("Verifying Purchase" + purchaseDetails.toString()); - return Future.value(true); - } - - void _handleInvalidPurchase(PurchaseDetails purchaseDetails) { - // handle invalid purchase here if _verifyPurchase` failed. - log("Invalid Purchase" + purchaseDetails.toString()); - } - - void _listenToPurchaseUpdated(List purchaseDetailsList) { - purchaseDetailsList.forEach((PurchaseDetails purchaseDetails) async { - if (purchaseDetails.status == PurchaseStatus.pending) { - //showPendingUI(); - log("Purchase pending"); - } else { - if (purchaseDetails.status == PurchaseStatus.error) { - //handleError(purchaseDetails.error); - } else if (purchaseDetails.status == PurchaseStatus.purchased) { - bool valid = await _verifyPurchase(purchaseDetails); - if (valid) { - deliverProduct(purchaseDetails); - } else { - _handleInvalidPurchase(purchaseDetails); - return; - } - } - if (Platform.isAndroid) { - if (!_kAutoConsume && purchaseDetails.productID == _kConsumableId) { - await InAppPurchaseConnection.instance.consumePurchase(purchaseDetails); - } - } - if (purchaseDetails.pendingCompletePurchase) { - await InAppPurchaseConnection.instance.completePurchase(purchaseDetails); - } - } - }); - } - - void getSubscriptions() { - Cache().products.forEach((element) { - Product product = element as Product; - if (Platform.isAndroid) { - if (product.productIdAndroid != null && product.productIdAndroid.isNotEmpty) { - _productList.add(product.productIdAndroid); - } - } else { - if (product.productIdIos != null && product.productIdIos.isNotEmpty) { - _productList.add(product.productIdIos); - } - } - }); - - _productList.forEach((element) { - print(element); - }); - } - - void purchase(Product product) { - if (product == null) { - throw Exception("No product to purchase"); - } - String productId = Platform.isAndroid ? product.productIdAndroid : product.productIdIos; - ProductDetails productDetails; - _products.forEach((element) { - if (element.id == productId) { - productDetails = element; - log("product to purchase: " + - productDetails.id + - " title " + - productDetails.title + - " price " + - productDetails.price + - " period " + - productDetails.skuDetail.subscriptionPeriod); - } - }); - - final PurchaseParam purchaseParam = PurchaseParam(productDetails: productDetails); -/* if (_isConsumable(productDetails)) { - InAppPurchaseConnection.instance.buyConsumable(purchaseParam: purchaseParam); - } else { */ - InAppPurchaseConnection.instance.buyNonConsumable(purchaseParam: purchaseParam); - //} -// From here the purchase flow will be handled by the underlying storefront. -// Updates will be delivered to the `InAppPurchaseConnection.instance.purchaseUpdatedStream`. - } -} - */ diff --git a/lib/util/purchases.dart b/lib/util/purchases.dart index 458bdc6..7dcf71d 100644 --- a/lib/util/purchases.dart +++ b/lib/util/purchases.dart @@ -34,7 +34,8 @@ class RevenueCatPurchases with Logging { Future restore() async { if (appUserId != null) { try { - PurchaserInfo purchaserInfo = await Purchases.restoreTransactions(); + //PurchaserInfo purchaserInfo = await Purchases.restoreTransactions(); + PurchaserInfo purchaserInfo = await Purchases.getPurchaserInfo(); if (purchaserInfo != null && purchaserInfo.entitlements.all["wt_subscription"] != null && purchaserInfo.entitlements.all["wt_subscription"].isActive) { diff --git a/lib/util/session.dart b/lib/util/session.dart index 6f8cb87..ca5c3d9 100644 --- a/lib/util/session.dart +++ b/lib/util/session.dart @@ -1,15 +1,11 @@ import 'dart:io'; -import 'package:aitrainer_app/localization/app_language.dart'; -import 'package:aitrainer_app/localization/app_localization.dart'; -import 'package:aitrainer_app/main.dart'; +import 'package:aitrainer_app/util/app_language.dart'; +import 'package:aitrainer_app/util/app_localization.dart'; import 'package:aitrainer_app/service/api.dart'; import 'package:aitrainer_app/service/logging.dart'; import 'package:aitrainer_app/service/package_service.dart'; -import 'package:aitrainer_app/service/product_service.dart'; -import 'package:aitrainer_app/service/property_service.dart'; import 'package:aitrainer_app/util/purchases.dart'; -import 'package:aitrainer_app/util/track.dart'; import 'package:devicelocale/devicelocale.dart'; import 'package:flutter/services.dart'; import 'package:package_info/package_info.dart'; diff --git a/lib/util/trans.dart b/lib/util/trans.dart index c2313ed..0ccb9f3 100644 --- a/lib/util/trans.dart +++ b/lib/util/trans.dart @@ -1,4 +1,4 @@ -import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/util/app_localization.dart'; import 'package:flutter/cupertino.dart'; mixin Trans { diff --git a/lib/view/account.dart b/lib/view/account.dart index 1430a53..a1d2241 100644 --- a/lib/view/account.dart +++ b/lib/view/account.dart @@ -2,12 +2,10 @@ import 'dart:collection'; import 'package:aitrainer_app/bloc/account/account_bloc.dart'; import 'package:aitrainer_app/library/custom_icon_icons.dart'; -import 'package:aitrainer_app/localization/app_language.dart'; +import 'package:aitrainer_app/util/app_language.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/customer.dart'; -import 'package:aitrainer_app/repository/customer_repository.dart'; import 'package:aitrainer_app/util/common.dart'; -import 'package:aitrainer_app/util/enums.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/widgets/app_bar_min.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/lib/view/custom_exercise_page.dart b/lib/view/custom_exercise_page.dart index 1d6e4fa..6d8fb31 100644 --- a/lib/view/custom_exercise_page.dart +++ b/lib/view/custom_exercise_page.dart @@ -1,7 +1,7 @@ import 'dart:collection'; import 'package:aitrainer_app/bloc/custom_exercise_form_bloc.dart'; -import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/util/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'; diff --git a/lib/view/customer_bodytype_animation.dart b/lib/view/customer_bodytype_animation.dart index 1ace66c..b9afbae 100644 --- a/lib/view/customer_bodytype_animation.dart +++ b/lib/view/customer_bodytype_animation.dart @@ -2,7 +2,7 @@ import 'dart:collection'; import 'dart:ui'; import 'package:aitrainer_app/bloc/body_type/bodytype_bloc.dart'; -import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/util/app_localization.dart'; import 'package:aitrainer_app/repository/customer_repository.dart'; import 'package:aitrainer_app/util/enums.dart'; import 'package:aitrainer_app/util/trans.dart'; @@ -44,7 +44,7 @@ class _CustomerBodyTypeAnimationPageState extends State with TickerProviderStateMixin { } void buildAnimation() { - _controller = AnimationController(duration: const Duration(milliseconds: 1000), vsync: this); - _animation = CurvedAnimation(parent: _controller, curve: Curves.slowMiddle); + _controller = AnimationController(duration: const Duration(milliseconds: 2000), vsync: this); + _animation = CurvedAnimation(parent: _controller, curve: Curves.fastOutSlowIn); _controller.forward(); } diff --git a/lib/view/customer_bodytype_page.dart b/lib/view/customer_bodytype_page.dart deleted file mode 100644 index c169416..0000000 --- a/lib/view/customer_bodytype_page.dart +++ /dev/null @@ -1,220 +0,0 @@ -import 'dart:collection'; - -import 'package:aitrainer_app/bloc/customer_change/customer_change_bloc.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/app_bar_progress.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'; - -// ignore: must_be_immutable -class CustomerBodyTypePage extends StatefulWidget { - _CustomerBodyTypePageState _state; - - _CustomerBodyTypePageState createState() { - _state = _CustomerBodyTypePageState(); - return _state; - } -} - -class BodyTypeItem { - static String endomorph = "endomorph"; - static String ectomorph = "ectomorph"; - static String mesomorph = "mesomorph"; -} - -class _CustomerBodyTypePageState extends State with Trans { - String selected; - bool fulldata = false; - @override - Widget build(BuildContext context) { - CustomerRepository customerRepository; - dynamic args = ModalRoute.of(context).settings.arguments; - if (args is HashMap && args['personal_data'] != null) { - fulldata = args['personal_data']; - customerRepository = args['bloc']; - } else { - customerRepository = ModalRoute.of(context).settings.arguments; - } - final double cWidth = MediaQuery.of(context).size.width * 0.75; - setContext(context); - - return Scaffold( - appBar: fulldata - ? AppBarMin( - back: true, - ) - : AppBarProgress(min: 76, max: 100), - body: Container( - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage('asset/image/WT_light_background.jpg'), - fit: BoxFit.cover, - alignment: Alignment.center, - ), - ), - child: BlocProvider( - create: (context) => CustomerChangeBloc(customerRepository: customerRepository), - child: Builder(builder: (context) { - // ignore: close_sinks - CustomerChangeBloc changeBloc = BlocProvider.of(context); - - return Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Divider(), - Wrap( - //runAlignment: WrapAlignment.center, - alignment: WrapAlignment.center, - children: [ - Text( - t("Your Body Type"), - textAlign: TextAlign.center, - style: TextStyle(color: Colors.orange, fontSize: 42, fontFamily: 'Arial', fontWeight: FontWeight.w900), - ) - ]), - Divider(), - 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), - ), - 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), - ), - 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, - textColor: Colors.white, - child: Text(fulldata ? t("Save") : t("Next")), - onPressed: () => { - changeBloc.add(CustomerSave()), - Navigator.of(context).pop(), - if (fulldata == false) {Navigator.of(context).pushNamed("customerWelcomePage", arguments: customerRepository)} - }, - ) - ], - ); - })), - )); - } - - dynamic getShape(CustomerRepository customerRepository, String fitnessLevel) { - String selected = customerRepository.bodyType; - dynamic returnCode = (selected == fitnessLevel) - ? RoundedRectangleBorder( - side: BorderSide(width: 4, color: Colors.orange), - ) - : RoundedRectangleBorder( - side: BorderSide(width: 1, color: Colors.blue), - ); - //return - return returnCode; - } -} diff --git a/lib/view/customer_exercise_device.dart b/lib/view/customer_exercise_device.dart index 3652a75..27c3003 100644 --- a/lib/view/customer_exercise_device.dart +++ b/lib/view/customer_exercise_device.dart @@ -1,5 +1,5 @@ import 'package:aitrainer_app/bloc/customer_exercise_device/customer_exercise_device_bloc.dart'; -import 'package:aitrainer_app/localization/app_language.dart'; +import 'package:aitrainer_app/util/app_language.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/exercise_device.dart'; import 'package:aitrainer_app/repository/customer_exercise_device_repository.dart'; diff --git a/lib/view/customer_fitness_page.dart b/lib/view/customer_fitness_page.dart index f30e3ed..0629b15 100644 --- a/lib/view/customer_fitness_page.dart +++ b/lib/view/customer_fitness_page.dart @@ -1,7 +1,7 @@ import 'dart:collection'; import 'package:aitrainer_app/bloc/customer_change/customer_change_bloc.dart'; -import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/util/app_localization.dart'; import 'package:aitrainer_app/repository/customer_repository.dart'; import 'package:aitrainer_app/model/fitness_state.dart'; import 'package:aitrainer_app/util/trans.dart'; diff --git a/lib/view/customer_goal_page.dart b/lib/view/customer_goal_page.dart index 6873a63..d7a5693 100644 --- a/lib/view/customer_goal_page.dart +++ b/lib/view/customer_goal_page.dart @@ -1,7 +1,7 @@ import 'dart:collection'; import 'package:aitrainer_app/bloc/customer_change/customer_change_bloc.dart'; -import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/util/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'; diff --git a/lib/view/customer_welcome_page.dart b/lib/view/customer_welcome_page.dart index de6751b..e4386e6 100644 --- a/lib/view/customer_welcome_page.dart +++ b/lib/view/customer_welcome_page.dart @@ -1,4 +1,4 @@ -import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/util/app_localization.dart'; import 'package:aitrainer_app/widgets/app_bar_min.dart'; import 'package:flutter/material.dart'; diff --git a/lib/view/evaluation.dart b/lib/view/evaluation.dart index e06ec85..c587b08 100644 --- a/lib/view/evaluation.dart +++ b/lib/view/evaluation.dart @@ -2,7 +2,7 @@ import 'dart:collection'; import 'dart:ui'; import 'package:aitrainer_app/bloc/result/result_bloc.dart'; -import 'package:aitrainer_app/localization/app_language.dart'; +import 'package:aitrainer_app/util/app_language.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/exercise.dart'; import 'package:aitrainer_app/model/exercise_ability.dart'; diff --git a/lib/view/exercise_control_page.dart b/lib/view/exercise_control_page.dart index 1e7baaa..1eb134d 100644 --- a/lib/view/exercise_control_page.dart +++ b/lib/view/exercise_control_page.dart @@ -1,15 +1,16 @@ import 'dart:collection'; import 'package:aitrainer_app/bloc/exercise_control/exercise_control_bloc.dart'; +import 'package:aitrainer_app/bloc/timer/timer_bloc.dart'; import 'package:aitrainer_app/library/custom_icon_icons.dart'; -import 'package:aitrainer_app/localization/app_language.dart'; +import 'package:aitrainer_app/util/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/timer_widget.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -38,9 +39,12 @@ class _ExerciseControlPage extends State with Trans { final double percent = arguments['percent']; final bool readonly = arguments['readonly']; setContext(context); + // ignore: close_sinks + TimerBloc timerBloc = BlocProvider.of(context); return BlocProvider( - create: (context) => ExerciseControlBloc(exerciseRepository: exerciseRepository, percentToCalculate: percent, readonly: readonly) + create: (context) => ExerciseControlBloc( + exerciseRepository: exerciseRepository, percentToCalculate: percent, readonly: readonly, timerBloc: timerBloc) ..add(ExerciseControlLoad()), child: BlocConsumer(listener: (context, state) { if (state is ExerciseControlError) { @@ -53,7 +57,7 @@ class _ExerciseControlPage extends State with Trans { _controller.animateTo(exerciseBloc.scrollOffset, duration: Duration(milliseconds: 300), curve: Curves.easeIn); } return ModalProgressHUD( - child: getControlForm(exerciseBloc), + child: getControlForm(exerciseBloc, timerBloc), inAsyncCall: state is ExerciseControlLoading, opacity: 0.5, color: Colors.black54, @@ -62,7 +66,7 @@ class _ExerciseControlPage extends State with Trans { })); } - Form getControlForm(ExerciseControlBloc exerciseBloc) { + Form getControlForm(ExerciseControlBloc exerciseBloc, TimerBloc timerBloc) { this.offset = exerciseBloc.scrollOffset; String exerciseName = AppLanguage().appLocal == Locale("en") ? exerciseBloc.exerciseRepository.exerciseType.name @@ -84,120 +88,63 @@ class _ExerciseControlPage extends State with Trans { alignment: Alignment.topCenter, ), ), - child: Container( - padding: const EdgeInsets.only(top: 10, left: 25, right: 25), - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - controller: _controller, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - exerciseName, - style: GoogleFonts.archivoBlack( - fontWeight: FontWeight.bold, - fontSize: 24, - color: Colors.white, - shadows: [ - 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, - ), - ], - ), - overflow: TextOverflow.fade, - textAlign: TextAlign.center, - maxLines: 2, - softWrap: true, - ), - Divider( - color: Colors.transparent, - ), - Divider( - color: Colors.transparent, - ), - Divider( - color: Colors.transparent, - ), - Divider( - color: Colors.transparent, - ), - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text(t("Your 1RM:"), - style: GoogleFonts.inter( - color: Colors.yellow[300], - fontSize: 18, - shadows: [ - 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, - shadows: [ - 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, - ), - ], - ), + child: Stack(children: [ + Container( + padding: const EdgeInsets.only(top: 10, left: 25, right: 25), + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + controller: _controller, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + exerciseName, + style: GoogleFonts.archivoBlack( + fontWeight: FontWeight.bold, + fontSize: 24, + color: Colors.white, + shadows: [ + 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("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?"), + overflow: TextOverflow.fade, + textAlign: TextAlign.center, + maxLines: 2, + softWrap: true, + ), + Divider( + color: Colors.transparent, + ), + Divider( + color: Colors.transparent, + ), + Divider( + color: Colors.transparent, + ), + Divider( + color: Colors.transparent, + ), + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text(t("Your 1RM:"), style: GoogleFonts.inter( color: Colors.yellow[300], fontSize: 18, shadows: [ Shadow( - offset: Offset(2.0, 2.0), - blurRadius: 6.0, + offset: Offset(-2.0, -2.0), + blurRadius: 12.0, color: Colors.black54, ), Shadow( @@ -206,29 +153,91 @@ class _ExerciseControlPage extends State with Trans { 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])) + )), + Text( + " " + + exerciseBloc.initialRM.toStringAsFixed(0) + + " " + + exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit, + style: GoogleFonts.inter( + color: Colors.yellow[300], + fontSize: 18, + fontWeight: FontWeight.bold, + shadows: [ + 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( + 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), + Divider(), + numberPickForm(exerciseBloc, 3), ]), - Divider(), - numberPickForm(exerciseBloc, 1), - Divider(), - numberPickForm(exerciseBloc, 2), - Divider(), - numberPickForm(exerciseBloc, 3), - ]), - ))), + )), + TimerWidget( + bloc: timerBloc, + ), + ])), //bottomNavigationBar: BottomNavigator(bottomNavIndex: 1), ), ); diff --git a/lib/view/exercise_execute_plan_add_page.dart b/lib/view/exercise_execute_plan_add_page.dart index 2dc888d..3b3b37f 100644 --- a/lib/view/exercise_execute_plan_add_page.dart +++ b/lib/view/exercise_execute_plan_add_page.dart @@ -3,7 +3,7 @@ import 'dart:collection'; import 'package:aitrainer_app/bloc/exercise_execute_plan/exercise_execute_plan_bloc.dart'; import 'package:aitrainer_app/bloc/exercise_execute_plan_add/exercise_execute_plan_add_bloc.dart'; import 'package:aitrainer_app/library/custom_icon_icons.dart'; -import 'package:aitrainer_app/localization/app_language.dart'; +import 'package:aitrainer_app/util/app_language.dart'; import 'package:aitrainer_app/model/workout_menu_tree.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/util/trans.dart'; diff --git a/lib/view/exercise_log_page.dart b/lib/view/exercise_log_page.dart index da17d0f..bcb370f 100644 --- a/lib/view/exercise_log_page.dart +++ b/lib/view/exercise_log_page.dart @@ -7,7 +7,7 @@ import 'package:aitrainer_app/widgets/dialog_premium.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:intl/intl.dart'; -import 'package:aitrainer_app/localization/app_language.dart'; +import 'package:aitrainer_app/util/app_language.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/exercise.dart'; import 'package:aitrainer_app/model/exercise_type.dart'; diff --git a/lib/view/exercise_new_page.dart b/lib/view/exercise_new_page.dart index d2d2d3e..d9d4bce 100644 --- a/lib/view/exercise_new_page.dart +++ b/lib/view/exercise_new_page.dart @@ -3,7 +3,7 @@ import 'dart:collection'; import 'package:aitrainer_app/bloc/exercise_new/exercise_new_bloc.dart'; import 'package:aitrainer_app/bloc/menu/menu_bloc.dart'; import 'package:aitrainer_app/library/custom_icon_icons.dart'; -import 'package:aitrainer_app/localization/app_language.dart'; +import 'package:aitrainer_app/util/app_language.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/exercise_ability.dart'; import 'package:aitrainer_app/model/exercise_type.dart'; diff --git a/lib/view/exercise_plan_custom_detail_add_page.dart b/lib/view/exercise_plan_custom_detail_add_page.dart index e94f1b1..d9349dc 100644 --- a/lib/view/exercise_plan_custom_detail_add_page.dart +++ b/lib/view/exercise_plan_custom_detail_add_page.dart @@ -2,7 +2,7 @@ import 'dart:collection'; import 'package:aitrainer_app/bloc/exercise_plan/exercise_plan_bloc.dart'; import 'package:aitrainer_app/bloc/exercise_plan_custom_add/exercise_plan_custom_add_bloc.dart'; -import 'package:aitrainer_app/localization/app_language.dart'; +import 'package:aitrainer_app/util/app_language.dart'; import 'package:aitrainer_app/model/workout_menu_tree.dart'; import 'package:aitrainer_app/repository/exercise_plan_repository.dart'; import 'package:aitrainer_app/util/trans.dart'; diff --git a/lib/view/exercise_type_description.dart b/lib/view/exercise_type_description.dart index a07b76e..4f2d9f1 100644 --- a/lib/view/exercise_type_description.dart +++ b/lib/view/exercise_type_description.dart @@ -1,4 +1,4 @@ -import 'package:aitrainer_app/localization/app_language.dart'; +import 'package:aitrainer_app/util/app_language.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/widgets/app_bar_min.dart'; import 'package:flutter/cupertino.dart'; diff --git a/lib/view/login.dart b/lib/view/login.dart index bcaf4e8..7692cfd 100644 --- a/lib/view/login.dart +++ b/lib/view/login.dart @@ -2,7 +2,6 @@ import 'dart:io'; 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/trans.dart'; import 'package:aitrainer_app/widgets/app_bar_min.dart'; @@ -183,17 +182,17 @@ class LoginPage extends StatelessWidget with Trans { ), Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ InkWell( - child: Text(AppLocalizations.of(context).translate('SignUpLink')), + child: Text(t('SignUpLink')), onTap: () => Navigator.of(context).pushNamed('registration'), ), Spacer(flex: 2), InkWell( - child: Text(AppLocalizations.of(context).translate('I forgot the password')), + child: Text(t('I forgot the password')), onTap: () => Navigator.of(context).pushNamed('resetPassword'), ), Spacer(flex: 2), InkWell( - child: Text(AppLocalizations.of(context).translate('Privacy')), + child: Text(t('Privacy')), onTap: () => { showDialog( context: context, diff --git a/lib/view/mydevelopment_muscle_page.dart b/lib/view/mydevelopment_muscle_page.dart index e7aae14..2a4f08d 100644 --- a/lib/view/mydevelopment_muscle_page.dart +++ b/lib/view/mydevelopment_muscle_page.dart @@ -83,15 +83,12 @@ class _MyDevelopmentMuscleState extends State with Comm ), backgroundColor: Colors.orange, )); - } else if (state is DevelopmentByMuscleLoadingState) { - //LoadingDialog.show(context); } }, builder: (context, state) { if (state is DevelopmentByMuscleStateInitial) { return Container(); } else { - //LoadingDialog.hide(context); return TreeView( startExpanded: false, children: _getTreeChildren(bloc.workoutTreeRepository.sortedTree, bloc), diff --git a/lib/view/mydevelopment_page.dart b/lib/view/mydevelopment_page.dart index c1ad145..7a4bc05 100644 --- a/lib/view/mydevelopment_page.dart +++ b/lib/view/mydevelopment_page.dart @@ -77,6 +77,25 @@ class _MyDevelopmentPage extends State with Trans { }, isLocked: true, ), + /* ImageButton( + width: imageWidth, + textAlignment: Alignment.topLeft, + text: t("My Sizes Development"), + style: GoogleFonts.robotoMono( + textStyle: TextStyle( + fontSize: 14, color: Colors.white, fontWeight: FontWeight.bold, backgroundColor: Colors.black54.withOpacity(0.4)), + ), + image: "asset/image/testemfejl400x400.jpg", + left: 5, + onTap: () => { + if (Cache().userLoggedIn != null) + { + args['customerId'] = Cache().userLoggedIn.customerId, + Navigator.of(context).pushNamed('mydevelopmentSizesPage', arguments: args) + } + }, + isLocked: true, + ), */ ImageButton( width: imageWidth, textAlignment: Alignment.topLeft, diff --git a/lib/view/mydevelopment_sizes_page.dart b/lib/view/mydevelopment_sizes_page.dart new file mode 100644 index 0000000..e8f5e8b --- /dev/null +++ b/lib/view/mydevelopment_sizes_page.dart @@ -0,0 +1,196 @@ +import 'package:aitrainer_app/bloc/development_sizes/development_sizes_bloc.dart'; +import 'package:aitrainer_app/model/property.dart'; +import 'package:aitrainer_app/repository/customer_repository.dart'; +import 'package:aitrainer_app/util/trans.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.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 '../widgets/app_bar.dart'; +import '../widgets/input_dialog_widget.dart'; + +class SizesDevelopmentPage extends StatefulWidget { + const SizesDevelopmentPage(); + + @override + _SizeState createState() => _SizeState(); +} + +class _SizeState extends State with Trans { + @override + Widget build(BuildContext context) { + setContext(context); + return BlocProvider( + create: (context) => DevelopmentSizesBloc(customerRepository: CustomerRepository())..add(DevelopmentSizesLoad()), + child: BlocConsumer(listener: (context, state) { + if (state is DevelopmentSizesError) { + Scaffold.of(context) + .showSnackBar(SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white)))); + } + }, builder: (context, state) { + final bloc = BlocProvider.of(context); + return ModalProgressHUD( + child: getForm(bloc), + inAsyncCall: state is DevelopmentSizesLoad, + opacity: 0.5, + color: Colors.black54, + progressIndicator: CircularProgressIndicator(), + ); + }), + ); + } + + Widget getForm(DevelopmentSizesBloc bloc) { + return Form( + child: Scaffold( + resizeToAvoidBottomInset: true, + appBar: AppBarNav(depth: 1), + body: Container( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height, + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage('asset/image/WT_black_background.jpg'), + fit: BoxFit.fill, + alignment: Alignment.center, + ), + ), + child: SafeArea( + child: Container( + padding: EdgeInsets.only(top: 10), + child: Column(crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ + Stack( + alignment: Alignment.center, + children: getSizeFigure(bloc), + ) + ]))), + ))); + } + + List getSizeFigure(DevelopmentSizesBloc bloc) { + double mediaWidth = MediaQuery.of(context).size.width * .8; + double mediaHeight = MediaQuery.of(context).size.height * .8; + + bloc.customerRepository.setMediaDimensions(mediaWidth, mediaHeight); + List list = List(); + + list.add( + bloc.isMan + ? Image.asset( + "asset/image/man_sizes.png", + height: mediaHeight, + width: mediaWidth, + ) + : Image.asset( + "asset/image/woman_sizes.png", + height: mediaHeight, + width: mediaWidth, + ), + ); + list.add(Positioned( + top: bloc.customerRepository.getWeightCoordinate(bloc.isMan, isTop: true).toDouble(), + left: bloc.customerRepository.getWeightCoordinate(bloc.isMan, isTop: false, isLeft: true).toDouble() - 45, + child: GestureDetector( + //onTap: () => onPressed(bloc.customerRepository.getPropertyByName("Weight")), + child: Image.asset( + "asset/image/merleg.png", + height: 120, + width: 120, + color: Colors.blue, + )), + )); + + list.addAll(getSizeElements(bloc)); + list.add( + Positioned( + top: mediaHeight * .07, + left: bloc.isMan ? mediaWidth * .62 : mediaWidth * .65, + child: Stack( + alignment: Alignment.topLeft, + children: [ + SizedBox(height: 80, width: 100), + Text(t("Your Size Diagrams"), + maxLines: 2, + style: GoogleFonts.archivoBlack( + shadows: [ + Shadow( + offset: Offset(5.0, 5.0), + blurRadius: 3.0, + color: Colors.black54, + ), + ], + fontSize: 20, + color: Colors.orange[500], + )), + ], + )), + ); + + return list; + } + + List getSizeElements(DevelopmentSizesBloc bloc) { + List list = List(); + + bloc.customerRepository.manSizes.forEach((element) { + list.add( + Positioned( + top: element.top.toDouble(), + left: element.left.toDouble(), + child: element.value != 0 + ? Container( + width: 20, + height: 20, + decoration: BoxDecoration( + color: bloc.isMan ? Colors.green[800] : Color(0xFFEA776C), + borderRadius: BorderRadius.all( + Radius.circular(20), + ), + ), + padding: EdgeInsets.zero, + child: IconButton( + icon: Icon(Icons.trending_up, color: Colors.green), + padding: EdgeInsets.zero, + color: Colors.red[800], + splashColor: Colors.amber, + onPressed: () => onPressed(element), + )) + : Container( + width: 23, + height: 23, + padding: EdgeInsets.zero, + decoration: BoxDecoration( + color: bloc.isMan ? Colors.white10 : Color(0xFFEA776C), + borderRadius: BorderRadius.all( + Radius.circular(23), + ), + ), + child: IconButton( + icon: Icon(Icons.trending_up, color: Colors.red), + padding: EdgeInsets.zero, + color: Colors.red[800], + splashColor: Colors.amber, + onPressed: () => onPressed(element), + ))), + ); + }); + + return list; + } + + void onPressed(Property element) { + print(element.propertyName); + showDialog( + context: context, + builder: (context) => InputDialog( + title: t("Size Of Your"), + subtitle: element.propertyNameTranslation, + initialValue: element.value, + onChanged: (value) { + //widget.exerciseBloc.add(ExerciseNewSizeChange(propertyName: element.propertyName, value: value)); + }, + )); + } +} diff --git a/lib/view/registration.dart b/lib/view/registration.dart index 44f4266..aba2cb8 100644 --- a/lib/view/registration.dart +++ b/lib/view/registration.dart @@ -2,7 +2,6 @@ import 'dart:io'; 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/trans.dart'; import 'package:aitrainer_app/widgets/app_bar_min.dart'; @@ -208,12 +207,12 @@ class RegistrationPage extends StatelessWidget with Trans { ), Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ InkWell( - child: Text(AppLocalizations.of(context).translate('Login')), + child: Text(t('Login')), onTap: () => Navigator.of(context).pushNamed('login'), ), Spacer(flex: 2), InkWell( - child: Text(AppLocalizations.of(context).translate('Privacy')), + child: Text(t('Privacy')), onTap: () => { showDialog( context: context, diff --git a/lib/view/reset_password.dart b/lib/view/reset_password.dart index a9ca47a..c9044a5 100644 --- a/lib/view/reset_password.dart +++ b/lib/view/reset_password.dart @@ -1,5 +1,4 @@ import 'package:aitrainer_app/bloc/reset_password_bloc.dart'; -import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/repository/user_repository.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/widgets/app_bar_min.dart'; @@ -77,8 +76,7 @@ class ResetPasswordPage extends StatelessWidget with Trans { mainAxisAlignment: MainAxisAlignment.start, children: [ new InkWell( - child: new Text(AppLocalizations.of(context).translate('I forgot the password'), - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 24)), + child: new Text(t('I forgot the password'), style: TextStyle(fontWeight: FontWeight.bold, fontSize: 24)), ), ], ), @@ -119,7 +117,7 @@ class ResetPasswordPage extends StatelessWidget with Trans { ), Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ new InkWell( - child: new Text(AppLocalizations.of(context).translate('Login')), + child: new Text(t('Login')), onTap: () => Navigator.of(context).pushNamed('login'), ), Spacer(flex: 1), diff --git a/lib/view/settings.dart b/lib/view/settings.dart index c8a8f5d..fdb382d 100644 --- a/lib/view/settings.dart +++ b/lib/view/settings.dart @@ -1,7 +1,7 @@ import 'package:aitrainer_app/bloc/menu/menu_bloc.dart'; import 'package:aitrainer_app/bloc/settings/settings_bloc.dart'; import 'package:aitrainer_app/library/custom_icon_icons.dart'; -import 'package:aitrainer_app/localization/app_language.dart'; +import 'package:aitrainer_app/util/app_language.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/util/common.dart'; import 'package:aitrainer_app/util/trans.dart'; diff --git a/lib/widgets/app_bar.dart b/lib/widgets/app_bar.dart index bf01e90..5968f48 100644 --- a/lib/widgets/app_bar.dart +++ b/lib/widgets/app_bar.dart @@ -1,7 +1,8 @@ import 'dart:async'; import 'package:aitrainer_app/bloc/menu/menu_bloc.dart'; -import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/bloc/timer/timer_bloc.dart'; +import 'package:aitrainer_app/util/app_localization.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/util/common.dart'; @@ -69,6 +70,8 @@ class _AppBarNav extends State with SingleTickerProviderStateMixin, C @override Widget build(BuildContext context) { menuBloc = BlocProvider.of(context); + // ignore: close_sinks + final TimerBloc timerBloc = BlocProvider.of(context); return AppBar( backgroundColor: Colors.black, @@ -91,6 +94,7 @@ class _AppBarNav extends State with SingleTickerProviderStateMixin, C leading: IconButton( icon: Icon(Icons.arrow_back, color: Colors.white), onPressed: () => { + timerBloc.add(TimerEnd()), if (widget.isMenu != null) { if (menuBloc.workoutItem != null) diff --git a/lib/widgets/app_bar_min.dart b/lib/widgets/app_bar_min.dart index 3b04f97..3eaeee9 100644 --- a/lib/widgets/app_bar_min.dart +++ b/lib/widgets/app_bar_min.dart @@ -1,7 +1,9 @@ +import 'package:aitrainer_app/bloc/timer/timer_bloc.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/util/common.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:google_fonts/google_fonts.dart'; // ignore: must_be_immutable @@ -24,6 +26,8 @@ class _AppBarNav extends State with Common { @override Widget build(BuildContext context) { + // ignore: close_sinks + final TimerBloc timerBloc = BlocProvider.of(context); return AppBar( backgroundColor: Colors.black, title: Row( @@ -44,6 +48,7 @@ class _AppBarNav extends State with Common { leading: IconButton( icon: Icon(Icons.arrow_back, color: widget.back ? Colors.white : Colors.black), onPressed: () => { + timerBloc.add(TimerEnd()), if (widget.back) {Navigator.of(context).pop()} }, )); diff --git a/lib/widgets/app_bar_progress.dart b/lib/widgets/app_bar_progress.dart index 792f8f1..423804d 100644 --- a/lib/widgets/app_bar_progress.dart +++ b/lib/widgets/app_bar_progress.dart @@ -1,6 +1,8 @@ +import 'package:aitrainer_app/bloc/timer/timer_bloc.dart'; import 'package:aitrainer_app/util/common.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:liquid_progress_indicator/liquid_progress_indicator.dart'; class AppBarProgress extends StatefulWidget implements PreferredSizeWidget { @@ -23,14 +25,12 @@ class _AppBarNav extends State with SingleTickerProviderStateMix _animationController = AnimationController( lowerBound: (widget.min).toDouble(), upperBound: (widget.max).toDouble(), - //upperBound: (widget.value / 100).toDouble(), vsync: this, duration: Duration(seconds: 3), ); _animationController.addListener(() => setState(() {})); _animationController.forward(); - //Future.delayed(Duration(seconds: 3)).then((value) => _animationController.repeat()); super.initState(); } @@ -42,12 +42,15 @@ class _AppBarNav extends State with SingleTickerProviderStateMix @override Widget build(BuildContext context) { + // ignore: close_sinks + final TimerBloc timerBloc = BlocProvider.of(context); + return AppBar( backgroundColor: Colors.black, title: getAnimatedWidget(), leading: IconButton( icon: Icon(Icons.arrow_back, color: Colors.white), - onPressed: () => {Navigator.of(context).pop()}, + onPressed: () => {timerBloc.add(TimerEnd()), Navigator.of(context).pop()}, )); } diff --git a/lib/widgets/bmi_widget.dart b/lib/widgets/bmi_widget.dart index 343e651..f31db27 100644 --- a/lib/widgets/bmi_widget.dart +++ b/lib/widgets/bmi_widget.dart @@ -1,5 +1,5 @@ import 'package:aitrainer_app/bloc/exercise_new/exercise_new_bloc.dart'; -import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/util/app_localization.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:animated_widgets/widgets/rotation_animated.dart'; import 'package:flutter/cupertino.dart'; @@ -73,7 +73,7 @@ class _BMIState extends State with Trans { double mediaWidth = MediaQuery.of(context).size.width * .8; double mediaHeight = MediaQuery.of(context).size.height * .8; //print("w " + mediaWidth.toString() + "h " + mediaHeight.toString()); - widget.exerciseBloc.setMediaDimensions(mediaWidth, mediaHeight); + widget.exerciseBloc.customerRepository.setMediaDimensions(mediaWidth, mediaHeight); widget.exerciseBloc.getBMI(); return Form( child: Scaffold( diff --git a/lib/widgets/bmr_widget.dart b/lib/widgets/bmr_widget.dart index 9e2640d..5ecb64e 100644 --- a/lib/widgets/bmr_widget.dart +++ b/lib/widgets/bmr_widget.dart @@ -1,5 +1,5 @@ import 'package:aitrainer_app/bloc/exercise_new/exercise_new_bloc.dart'; -import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/util/app_localization.dart'; import 'package:aitrainer_app/model/fitness_state.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:flutter/cupertino.dart'; diff --git a/lib/widgets/bottom_nav.dart b/lib/widgets/bottom_nav.dart index 279aca6..9321fb0 100644 --- a/lib/widgets/bottom_nav.dart +++ b/lib/widgets/bottom_nav.dart @@ -1,4 +1,4 @@ -import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/util/app_localization.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/service/logging.dart'; import 'package:aitrainer_app/util/common.dart'; @@ -94,7 +94,12 @@ class _NawDrawerWidget extends State with Trans, Logging { backgroundColor: bgrColor, icon: Icon(Icons.settings, color: inactive), activeIcon: Icon(Icons.settings, color: active), - title: Text(t("Settings"), style: TextStyle(fontSize: 12))) + title: Text(t("Settings"), style: TextStyle(fontSize: 12))), + /* BottomNavigationBarItem( + backgroundColor: bgrColor, + icon: Icon(Icons.multiple_stop, color: inactive), + activeIcon: Icon(Icons.multiple_stop, color: active), + title: Text(t("Multi test"), style: TextStyle(fontSize: 12))) */ ], onTap: (index) { setState(() { diff --git a/lib/widgets/menu_page_widget.dart b/lib/widgets/menu_page_widget.dart index 4365124..45dcddf 100644 --- a/lib/widgets/menu_page_widget.dart +++ b/lib/widgets/menu_page_widget.dart @@ -3,8 +3,11 @@ import 'dart:ui'; import 'package:aitrainer_app/bloc/menu/menu_bloc.dart'; import 'package:aitrainer_app/library/custom_icon_icons.dart'; -import 'package:aitrainer_app/localization/app_language.dart'; -import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/util/enums.dart'; +import 'package:aitrainer_app/util/track.dart'; +import 'package:aitrainer_app/widgets/menu_search_bar.dart'; +import 'package:aitrainer_app/util/app_language.dart'; +import 'package:aitrainer_app/util/app_localization.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/workout_menu_tree.dart'; import 'package:aitrainer_app/service/logging.dart'; @@ -233,86 +236,50 @@ class _MenuPageWidgetState extends State with Trans, Logging { return sliverList; } - SliverList getInfoWidget(BuildContext context, MenuBloc menuBloc) { - List widgets = List(); + SliverAppBar getInfoWidget(BuildContext context, MenuBloc menuBloc) { + menuBloc.setContext(context); + menuBloc.setMenuInfo(); - if (context != null) { - menuBloc.setContext(context); - menuBloc.setMenuInfo(); - widgets.add(SizedBox( - height: 10, - )); - - widgets.add( - GestureDetector( - onTap: () => { - showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext context) { - return DialogCommon( - title: menuBloc.infoTitle, - descriptions: menuBloc.infoText, - description2: menuBloc.infoText2, - description3: menuBloc.infoText3, - text: "OK", - onTap: () => {Navigator.of(context).pop()}, - onCancel: () => {Navigator.of(context).pop()}, - ); - }) - }, - child: Align( - alignment: Alignment.center, - child: SizedBox( - height: 35, - child: AnimatedSwitcher( - duration: Duration(milliseconds: 800), - transitionBuilder: (Widget child, Animation animation) { - return ScaleTransition(child: child, scale: animation); - }, - child: isFirst && !wait - ? Icon( - CustomIcon.question_circle, - color: Colors.yellow[300], - size: 40, - ) - : Offstage())))), - ); - } - SliverList sliverList = SliverList(delegate: SliverChildListDelegate(widgets)); - return sliverList; - } - - SliverGrid getInfoWidget2(BuildContext context, MenuBloc menuBloc) { - final List _columnChildren = List(); - if (context != null) { - menuBloc.setContext(context); - menuBloc.setMenuInfo(); - - Widget info = MenuInfoWidget( - title: menuBloc.infoTitle, - titleSize: 18, - titleWeight: FontWeight.bold, - titleColor: Colors.orangeAccent, - text: menuBloc.infoText, - textSize: 13, - textColor: Colors.yellowAccent, - text2: menuBloc.infoText2, - text3: menuBloc.infoText3, - link: menuBloc.infoLink, - bloc: menuBloc, - ); - _columnChildren.add(info); - } - SliverGrid sliverList = SliverGrid( - delegate: SliverChildListDelegate(_columnChildren), - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 1, - mainAxisSpacing: 5.0, - crossAxisSpacing: 5.0, - childAspectRatio: 2, - )); - return sliverList; + SliverAppBar sliverAppBar = SliverAppBar( + backgroundColor: Colors.transparent, + title: Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ + SizedBox( + width: 10, + ), + GestureDetector( + onTap: () => { + showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return DialogCommon( + title: menuBloc.infoTitle, + descriptions: menuBloc.infoText, + description2: menuBloc.infoText2, + description3: menuBloc.infoText3, + text: "OK", + onTap: () => {Navigator.of(context).pop()}, + onCancel: () => {Navigator.of(context).pop()}, + ); + }) + }, + child: Icon( + CustomIcon.question_circle, + color: Colors.orange[400], + size: 40, + )), + MenuSearchBar( + listItems: menuBloc.menuTreeRepository.menuAsExercise, + onFind: (value) => { + Track().track(TrackingEvent.search, eventValue: value.exerciseType.name), + Navigator.of(context).pushNamed('exerciseNewPage', arguments: value.exerciseType) + }, + ), + SizedBox( + width: 10, + ), + ])); + return sliverAppBar; } void menuClick(WorkoutMenuTree workoutTree, MenuBloc menuBloc, BuildContext context) { diff --git a/lib/widgets/menu_search_bar.dart b/lib/widgets/menu_search_bar.dart new file mode 100644 index 0000000..a5e9205 --- /dev/null +++ b/lib/widgets/menu_search_bar.dart @@ -0,0 +1,277 @@ +import 'dart:async'; + +import 'package:aitrainer_app/model/workout_menu_tree.dart'; +import 'package:aitrainer_app/util/trans.dart'; +import 'package:dropdown_search/dropdown_search.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; + +class SearchBarStream { + static final SearchBarStream _singleton = SearchBarStream._internal(); + final StreamController streamController = StreamController.broadcast(); + bool searching = false; + + Stream get stream => streamController.stream; + StreamController getStreamController() => streamController; + + factory SearchBarStream() => _singleton; + + SearchBarStream._internal(); + + void dispose() { + streamController.close(); + } +} + +class MenuSearchBar extends StatelessWidget { + final List listItems; + final Function(WorkoutMenuTree) onFind; + + const MenuSearchBar({@required this.listItems, this.onFind}); + + @override + Widget build(BuildContext context) { + return AnimatedSearch( + listItems: listItems, + onFind: onFind, + ); + } +} + +class AnimatedSearch extends StatefulWidget { + final List listItems; + final Function(WorkoutMenuTree) onFind; + + AnimatedSearch({this.listItems, this.onFind}); + @override + _AnimatedSearch createState() => _AnimatedSearch(); +} + +class _AnimatedSearch extends State { + bool isSearching = false; + final Stream stream = SearchBarStream().stream; + var subscription; + + @override + void initState() { + super.initState(); + } + + @override + void didChangeDependencies() { + subscription = stream.listen((value) { + setState(() { + isSearching = SearchBarStream().searching; + }); + }); + super.didChangeDependencies(); + } + + @override + void dispose() { + subscription.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.only(top: 0), + child: Stack( + alignment: Alignment.center, + children: [ + AnimateExpansion( + animate: !isSearching, + axisAlignment: 1.0, + child: IconButton( + onPressed: () => { + setState(() { + isSearching = !isSearching; + SearchBarStream().searching = isSearching; + SearchBarStream().getStreamController().add(true); + }) + }, + icon: Icon( + Icons.search, + color: Color(0xffb4f500), + size: 40, + ), + )), + AnimateExpansion( + animate: isSearching, + axisAlignment: -1.0, + child: Search( + listItems: widget.listItems, + onFind: widget.onFind, + ), + ), + ], + )); + } +} + +// ignore: must_be_immutable +class Search extends StatelessWidget with Trans { + final List listItems; + final Function(WorkoutMenuTree) onFind; + + Search({this.listItems, this.onFind}); + + @override + Widget build(BuildContext context) { + setContext(context); + return SizedBox( + width: MediaQuery.of(context).size.width * .6, + child: DropdownSearch( + onPopupDismissed: () => {SearchBarStream().searching = false, SearchBarStream().getStreamController().add(false)}, + showAsSuffixIcons: false, + showSearchBox: true, + mode: Mode.DIALOG, + showSelectedItem: false, + items: listItems, + onChanged: (value) => onFind(value), + dropdownSearchDecoration: InputDecoration( + contentPadding: EdgeInsets.only(left: 15, top: 0, bottom: 5), + labelStyle: GoogleFonts.inter(fontSize: 12, color: Colors.yellow[50]), + fillColor: Colors.black38, + filled: true, + border: OutlineInputBorder( + gapPadding: 8.0, + borderRadius: BorderRadius.circular(12.0), + borderSide: BorderSide(color: Colors.white12, width: 0.4), + ), + ), + searchBoxController: TextEditingController(), + searchBoxDecoration: InputDecoration( + contentPadding: EdgeInsets.only(left: 15, top: 5, bottom: 5), + labelText: t("Search Exercises..."), + labelStyle: GoogleFonts.inter(fontSize: 14, color: Colors.grey[400]), + fillColor: Colors.white24, + filled: true, + border: OutlineInputBorder( + gapPadding: 8.0, + borderRadius: BorderRadius.circular(12.0), + borderSide: BorderSide(color: Colors.white12, width: 0.4), + ), + ), + popupBackgroundColor: Colors.grey[700], + popupItemBuilder: (context, item, isSelected) { + return Container( + margin: EdgeInsets.all(3), + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage('asset/image/WT_black_G_background.jpg'), + fit: BoxFit.cover, + ), + ), + child: ListTile( + selected: isSelected, + title: Text( + item.name, + style: GoogleFonts.inter(color: Colors.yellow[300], fontSize: 16), + ), + subtitle: Text( + item.parentName, + maxLines: 1, + style: GoogleFonts.inter(color: Colors.grey[400]), + ), + leading: ClipRRect( + borderRadius: BorderRadius.circular(8.0), + child: Image.asset(item.imageName), + ), + ), + ); + }, + emptyBuilder: (context, searchEntry) => Center( + child: Text( + t("No exercise found"), + textAlign: TextAlign.center, + style: GoogleFonts.inter(color: Colors.yellow[200], fontSize: 16), + )), + dropdownBuilder: (context, WorkoutMenuTree item, itemDesignation) => Container( + child: ListView(scrollDirection: Axis.vertical, shrinkWrap: true, children: [ + (item == null) + ? Container( + height: 15, + padding: EdgeInsets.all(0), + child: Text( + t("Search Exercises..."), + style: GoogleFonts.inter(color: Colors.grey[400], fontSize: 14), + ), + ) + : Container( + height: 15, + padding: EdgeInsets.all(0), + child: Text( + item.name, + maxLines: 3, + style: GoogleFonts.inter(color: Colors.yellow[400], fontSize: 14), + ), + ), + ]))), + ); + } +} + +class AnimateExpansion extends StatefulWidget { + final Widget child; + final bool animate; + final double axisAlignment; + AnimateExpansion({ + this.animate = false, + this.axisAlignment, + this.child, + }); + + @override + _AnimateExpansionState createState() => _AnimateExpansionState(); +} + +class _AnimateExpansionState extends State with SingleTickerProviderStateMixin { + AnimationController _animationController; + Animation _animation; + + void prepareAnimations() { + _animationController = AnimationController( + vsync: this, + duration: Duration(milliseconds: 350), + ); + _animation = CurvedAnimation( + parent: _animationController, + curve: Curves.easeInCubic, + reverseCurve: Curves.easeOutCubic, + ); + } + + void _toggle() { + if (widget.animate) { + _animationController.forward(); + } else { + _animationController.reverse(); + } + } + + @override + void initState() { + super.initState(); + prepareAnimations(); + _toggle(); + } + + @override + void didUpdateWidget(AnimateExpansion oldWidget) { + super.didUpdateWidget(oldWidget); + _toggle(); + } + + @override + Widget build(BuildContext context) { + return SizeTransition(axis: Axis.horizontal, axisAlignment: -1.0, sizeFactor: _animation, child: widget.child); + } + + @override + void dispose() { + _animationController.dispose(); + super.dispose(); + } +} diff --git a/lib/widgets/size_widget.dart b/lib/widgets/size_widget.dart index 1828149..72d49be 100644 --- a/lib/widgets/size_widget.dart +++ b/lib/widgets/size_widget.dart @@ -53,7 +53,7 @@ class _SizeState extends State with Trans { double mediaWidth = MediaQuery.of(context).size.width * .8; double mediaHeight = MediaQuery.of(context).size.height * .8; //print("w " + mediaWidth.toString() + "h " + mediaHeight.toString()); - widget.exerciseBloc.setMediaDimensions(mediaWidth, mediaHeight); + widget.exerciseBloc.customerRepository.setMediaDimensions(mediaWidth, mediaHeight); List list = List(); list.add(GestureDetector( onTap: () => {print("Save"), widget.exerciseBloc.add(ExerciseNewSaveWeight())}, @@ -63,7 +63,7 @@ class _SizeState extends State with Trans { ))); list.add( - widget.exerciseBloc.isMan + widget.exerciseBloc.customerRepository.isMan ? Image.asset( "asset/image/man_sizes.png", height: mediaHeight, @@ -76,10 +76,13 @@ class _SizeState extends State with Trans { ), ); list.add(Positioned( - top: widget.exerciseBloc.getWeightCoordinate(widget.exerciseBloc.isMan, isTop: true).toDouble(), - left: widget.exerciseBloc.getWeightCoordinate(widget.exerciseBloc.isMan, isTop: false, isLeft: true).toDouble() - 45, + top: widget.exerciseBloc.customerRepository.getWeightCoordinate(widget.exerciseBloc.customerRepository.isMan, isTop: true).toDouble(), + left: widget.exerciseBloc.customerRepository + .getWeightCoordinate(widget.exerciseBloc.customerRepository.isMan, isTop: false, isLeft: true) + .toDouble() - + 45, child: GestureDetector( - onTap: () => onPressed(widget.exerciseBloc.getPropertyByName("Weight")), + onTap: () => onPressed(widget.exerciseBloc.customerRepository.getPropertyByName("Weight")), child: Image.asset( "asset/image/merleg.png", height: 120, @@ -92,7 +95,7 @@ class _SizeState extends State with Trans { list.add( Positioned( top: mediaHeight * .07, - left: widget.exerciseBloc.isMan ? mediaWidth * .62 : mediaWidth * .65, + left: widget.exerciseBloc.customerRepository.isMan ? mediaWidth * .62 : mediaWidth * .65, child: Stack( alignment: Alignment.topLeft, children: [ @@ -129,7 +132,7 @@ class _SizeState extends State with Trans { List getSizeElements() { List list = List(); - widget.exerciseBloc.manSizes.forEach((element) { + widget.exerciseBloc.customerRepository.manSizes.forEach((element) { list.add( Positioned( top: element.top.toDouble(), @@ -139,7 +142,7 @@ class _SizeState extends State with Trans { width: 20, height: 20, decoration: BoxDecoration( - color: widget.exerciseBloc.isMan ? Colors.green[800] : Color(0xFFEA776C), + color: widget.exerciseBloc.customerRepository.isMan ? Colors.green[800] : Color(0xFFEA776C), borderRadius: BorderRadius.all( Radius.circular(20), ), @@ -156,7 +159,7 @@ class _SizeState extends State with Trans { height: 20, padding: EdgeInsets.zero, decoration: BoxDecoration( - color: widget.exerciseBloc.isMan ? Color(0xFF369fb9) : Color(0xFFEA776C), + color: widget.exerciseBloc.customerRepository.isMan ? Color(0xFF369fb9) : Color(0xFFEA776C), borderRadius: BorderRadius.all( Radius.circular(20), ), diff --git a/lib/widgets/timer_widget.dart b/lib/widgets/timer_widget.dart new file mode 100644 index 0000000..b5ee59b --- /dev/null +++ b/lib/widgets/timer_widget.dart @@ -0,0 +1,34 @@ +import 'package:aitrainer_app/bloc/timer/timer_bloc.dart'; +import 'package:aitrainer_app/library/clock.dart'; +import 'package:flutter/material.dart'; + +class TimerWidget extends StatelessWidget { + final TimerBloc bloc; + const TimerWidget({this.bloc}); + + @override + Widget build(BuildContext context) { + return Positioned( + left: MediaQuery.of(context).size.width - 95, + top: 28, + child: Stack(alignment: AlignmentDirectional.topEnd, children: [ + digitalClock(), + ])); + } + + Widget digitalClock() { + return ClipRRect( + borderRadius: BorderRadius.circular(45.0), + child: Container( + width: 90, + height: 90, + color: Colors.transparent, + child: Overlay(initialEntries: [ + OverlayEntry( + opaque: true, + builder: (BuildContext context) { + return Container(color: Colors.transparent, child: Clock(bloc: bloc)); + }) + ]))); + } +} diff --git a/pubspec.lock b/pubspec.lock index 9e72d93..05e872f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -50,6 +50,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.5.0-nullsafety.1" + audioplayer: + dependency: "direct main" + description: + name: audioplayer + url: "https://pub.dartlang.org" + source: hosted + version: "0.8.1" badges: dependency: "direct main" description: @@ -259,7 +266,7 @@ packages: name: dropdown_search url: "https://pub.dartlang.org" source: hosted - version: "0.4.8" + version: "0.4.9" equatable: dependency: "direct main" description: @@ -397,7 +404,7 @@ packages: name: flutter_bloc url: "https://pub.dartlang.org" source: hosted - version: "6.1.1" + version: "6.1.2" flutter_facebook_auth: dependency: "direct main" description: @@ -1005,7 +1012,7 @@ packages: name: sqflite url: "https://pub.dartlang.org" source: hosted - version: "1.3.2+2" + version: "1.3.2+3" sqflite_common: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 816ae1c..50a5940 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.1.6+55 +version: 1.1.7+56 environment: sdk: ">=2.7.0 <3.0.0" @@ -28,7 +28,7 @@ dependencies: google_fonts: ^1.1.1 devicelocale: ^0.3.3 sentry: ^4.0.3 - flutter_bloc: ^6.1.1 + flutter_bloc: ^6.1.2 equatable: ^1.2.5 #freezed: ^0.12.2 flutter_form_bloc: ^0.19.0 @@ -40,7 +40,6 @@ dependencies: infinite_listview: ^1.0.1+1 toggle_switch: ^0.1.8 keyboard_actions: ^3.3.1+1 - dropdown_search: ^0.4.8 badges: ^1.1.4 #health: ^3.0.0 stop_watch_timer: ^0.6.0+1 @@ -53,6 +52,8 @@ dependencies: network_image_to_byte: ^0.0.1 package_info: ^0.4.3+4 liquid_progress_indicator: ^0.3.2 + dropdown_search: ^0.4.9 + audioplayer: ^0.8.1 firebase_core: ^0.5.0 @@ -71,7 +72,7 @@ dependencies: animated_widgets: ^1.0.6 mockito: ^4.1.3 - sqflite: ^1.3.2+2 + sqflite: ^1.3.2+3 flutter_secure_storage: ^3.3.5 flutter_localizations: @@ -212,6 +213,7 @@ flutter: - asset/menu/1.2.anaerob.jpg - asset/menu/2.strength.jpg - asset/menu/2.1.endurance.jpg + - asset/menu/2.1.4.squats.jpg - asset/menu/2.1.6.core.jpg - asset/menu/2.1.1.1RM.jpg - asset/menu/2.2.1.1.chest.jpg @@ -234,6 +236,7 @@ flutter: - asset/menu/bent_arm_barbell_pullovers.jpg - asset/menu/bent_knee_situps.jpg - asset/menu/bent_over_lateral_raises_with_dumbbells.jpg + - asset/menu/bent_over_rows.jpg - asset/menu/biceps_machine.jpg - asset/menu/bmi.jpg - asset/menu/bmr.jpg @@ -244,14 +247,18 @@ flutter: - asset/menu/chest_press_machine.jpg - asset/menu/chest_press.jpg - asset/menu/chins.jpg + - asset/menu/close_grip_bench_press.jpg - asset/menu/close_grip_front_lat_pulldown.jpg - asset/menu/close_grip_pull_ups.jpg + - asset/menu/close_reverse_grip_lat_pulldown.jpg - asset/menu/concentration.jpg - asset/menu/cooper.jpg - asset/menu/crisscross.jpg - asset/menu/cross_bench_dumbbell_pullover.jpg - asset/menu/deadlift.jpg + - asset/menu/decline_bench_press.jpg - asset/menu/decline_dumbbell_bench_press.jpg + - asset/menu/decline_flyes.jpg - asset/menu/decline_cable_flyes.jpg - asset/menu/donkey_calf_raises.jpg - asset/menu/dumbbell_alternate_bicep_curl.jpg @@ -266,6 +273,7 @@ flutter: - asset/menu/hanging_leg_raises.jpg - asset/menu/head-on-bench_dumbbell_rear_delt_raise.jpg - asset/menu/hyperextension.jpg + - asset/menu/hyperextension_floor.jpg - asset/menu/incline_cable_flyes.jpg - asset/menu/incline_curl_with_dumbbels.jpg - asset/menu/incline_dumbbell_press.jpg @@ -292,10 +300,13 @@ flutter: - asset/menu/peck_deck_flyes.jpg - asset/menu/plank.jpg - asset/menu/pull_up.jpg + - asset/menu/pulldown_machine.jpg - asset/menu/pullups.jpg - asset/menu/pushups.jpg + - asset/menu/pushups_dip.jpg - asset/menu/reverse_crunches.jpg - asset/menu/roman_chair_situps.jpg + - asset/menu/row_machine.jpg - asset/menu/russian_twist.jpg - asset/menu/seated_bar_twist.jpg - asset/menu/seated_dumbbell_curl.jpg @@ -307,7 +318,7 @@ flutter: - asset/menu/single_arm_bent_over_cable_reverse_fly.jpg - asset/menu/single_arm_t-bar_rows.jpg - asset/menu/single_hand_lateral_raises.jpg - - asset/menu/single_hand_lying_triceps_Extension.jpg + - asset/menu/single_hand_lying_triceps_extension.jpg - asset/menu/sitting_knee_ups.jpg - asset/menu/sitting_machine_calf_raises.jpg - asset/menu/situps.jpg @@ -340,6 +351,7 @@ flutter: - asset/menu/weighted_bench_dip.jpg - asset/menu/wide_grip_behind_the_neck_pull_ups.jpg - asset/menu/wide_grip_front_lat_pulldown.jpg + - asset/wine-glass.mp3 - i18n/en.json diff --git a/test/widget_test.db.dart b/test/widget_test.db.dart index 383d8d8..7c39e0d 100644 --- a/test/widget_test.db.dart +++ b/test/widget_test.db.dart @@ -8,7 +8,7 @@ //import 'package:aitrainer_app/bloc/login_form_bloc.dart'; import 'package:aitrainer_app/helper/database.dart'; import 'package:aitrainer_app/library_keys.dart'; -import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/util/app_localization.dart'; import 'package:aitrainer_app/model/user.dart'; import 'package:aitrainer_app/repository/user_repository.dart'; import 'package:aitrainer_app/util/common.dart'; diff --git a/test/widget_test.login.dart b/test/widget_test.login.dart index 18b0607..042322b 100644 --- a/test/widget_test.login.dart +++ b/test/widget_test.login.dart @@ -9,7 +9,7 @@ import 'package:aitrainer_app/bloc/login/login_bloc.dart'; import 'package:aitrainer_app/helper/database.dart'; import 'package:aitrainer_app/library_keys.dart'; -import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/util/app_localization.dart'; import 'package:aitrainer_app/model/user.dart'; import 'package:aitrainer_app/repository/user_repository.dart'; import 'package:aitrainer_app/util/common.dart';