WT 1.1.7+2 SearchBar, Timer for ExerciseControl
1
android/.gitignore
vendored
@ -4,4 +4,5 @@ gradle-wrapper.jar
|
|||||||
/gradlew
|
/gradlew
|
||||||
/gradlew.bat
|
/gradlew.bat
|
||||||
/local.properties
|
/local.properties
|
||||||
|
key.properties
|
||||||
GeneratedPluginRegistrant.java
|
GeneratedPluginRegistrant.java
|
||||||
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 54 KiB |
BIN
asset/menu/2.1.4.squats.jpg
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
asset/menu/bent_over_rows.jpg
Normal file
After Width: | Height: | Size: 75 KiB |
BIN
asset/menu/close_grip_bench_press.jpg
Normal file
After Width: | Height: | Size: 138 KiB |
BIN
asset/menu/hyperextension_floor.jpg
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
asset/menu/pulldown_machine.jpg
Normal file
After Width: | Height: | Size: 113 KiB |
BIN
asset/menu/row_machine.jpg
Normal file
After Width: | Height: | Size: 92 KiB |
BIN
asset/wine-glass.mp3
Normal file
53
i18n/en.json
@ -361,33 +361,36 @@
|
|||||||
|
|
||||||
"Body Type Analyser":"Body Type Analyser",
|
"Body Type Analyser":"Body Type Analyser",
|
||||||
"How likely is it true about you?":"How likely is it true about you?",
|
"How likely is it true about you?":"How likely is it true about you?",
|
||||||
"Very unlikely":"Very unlikely",
|
"Very unlikely":"Not True",
|
||||||
"Maybe":"Maybe",
|
"Maybe":"Maybe",
|
||||||
"Very likely":"Very likely",
|
"Very likely":"True",
|
||||||
"« Back":"« Back",
|
"« Back":"« Back",
|
||||||
"1. Basicly I am skinny and bonny":"1. Basicly I am skinny and bonny",
|
"1. Basicly I am skinny and bonny":"1. I have basically a thin and bony physique",
|
||||||
"2. question":"2. question",
|
"2. question":"2. Long limbs and narrow shoulders are typical of me",
|
||||||
"3. question":"3. question",
|
"3. question":"3. It is difficult for me to build muscle",
|
||||||
"4. question":"4. question",
|
"4. question":"4. My chest and waist are nearly the same width",
|
||||||
"5. question":"5. question",
|
"5. question":"5. ’Chopstick’ was my nickname in the kindergarten",
|
||||||
"6. question":"6. question",
|
"6. question":"6. I easily lose the muscle I built up",
|
||||||
"7. question":"7. question",
|
"7. question":"7. To my knowledge, my body fat percentage is low",
|
||||||
"8. question":"8. question",
|
"8. question":"8. Basically, I have a sporty and athletic physique",
|
||||||
"9. question":"9. question",
|
"9. question":"9. I have a wide collarbone and shoulders",
|
||||||
"10. question":"10. question",
|
"10. question":"10. My hips are narrow and my waist is sporty",
|
||||||
"11. question":"11. question",
|
"11. question":"11. I get muscular quickly",
|
||||||
"12. question":"12. question",
|
"12. question":"12. My chest is wider than my waist",
|
||||||
"13. question":"13. question",
|
"13. question":"13. I could be the statue of David",
|
||||||
"14. question":"14. question",
|
"14. question":"14. I have a strong calf and forearm",
|
||||||
"15. question":"15. question",
|
"15. question":"15. I have a wide rib cage",
|
||||||
"16. question":"16. question",
|
"16. question":"16. I have thick and wide joints",
|
||||||
"17. question":"17. question",
|
"17. question":"17. My bones are strong",
|
||||||
"18. question":"18. question",
|
"18. question":"18. My body is muscular but a little fatter",
|
||||||
"19. question":"19. question",
|
"19. question":"19. My hips are wider than my chest",
|
||||||
"20. question":"20. question",
|
"20. question":"20. Tun’ could be my nickname too",
|
||||||
"21. question":"21. question",
|
"21. question":"21. I lose weight hard and gain weight more easily",
|
||||||
"22. question":"22. question",
|
"22. question":"22. I have a strong and chunky physique",
|
||||||
"Your Bodytype result":"Your Bodytype result",
|
"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"
|
||||||
|
|
||||||
}
|
}
|
13
i18n/hu.json
@ -361,7 +361,7 @@
|
|||||||
"Maybe":"Talán",
|
"Maybe":"Talán",
|
||||||
"Very likely":"Biztosan",
|
"Very likely":"Biztosan",
|
||||||
"« Back":"« Vissza",
|
"« 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",
|
"2. question":"2. Hosszú végtagok, keskeny vállak jellemzőek rám",
|
||||||
"3. question":"3. Nehezen tudok izmot növelni",
|
"3. question":"3. Nehezen tudok izmot növelni",
|
||||||
"4. question":"4. Mellkasom, derekam közel egyforma szélességű",
|
"4. question":"4. Mellkasom, derekam közel egyforma szélességű",
|
||||||
@ -374,16 +374,19 @@
|
|||||||
"11. question":"11. Gyorsan izmosodok",
|
"11. question":"11. Gyorsan izmosodok",
|
||||||
"12. question":"12. Szélesebb a mellkasom a derekamnál",
|
"12. question":"12. Szélesebb a mellkasom a derekamnál",
|
||||||
"13. question":"13. Akár lehetnék én a Dávid szobor",
|
"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",
|
"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",
|
"17. question":"17. Erős a csontozatom",
|
||||||
"18. question":"18. Zsírosabb, de izmos vagyok",
|
"18. question":"18. Zsírosabb, de izmos vagyok",
|
||||||
"19. question":"19. Szélesebb a csípőm a mellkasomnál",
|
"19. question":"19. Szélesebb a csípőm a mellkasomnál",
|
||||||
"20. question":"20. Hordó is lehetne a becenevem",
|
"20. question":"20. Hordó is lehetne a becenevem",
|
||||||
"21. question":"21. Nehezen fogyok, könnyebben hízok",
|
"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",
|
"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"
|
||||||
|
|
||||||
}
|
}
|
@ -6,6 +6,8 @@ PODS:
|
|||||||
- AppAuth/ExternalUserAgent (1.4.0)
|
- AppAuth/ExternalUserAgent (1.4.0)
|
||||||
- apple_sign_in (0.0.1):
|
- apple_sign_in (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- audioplayer (0.0.1):
|
||||||
|
- Flutter
|
||||||
- devicelocale (0.0.1):
|
- devicelocale (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FBSDKCoreKit (9.0.0):
|
- FBSDKCoreKit (9.0.0):
|
||||||
@ -181,6 +183,7 @@ PODS:
|
|||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- apple_sign_in (from `.symlinks/plugins/apple_sign_in/ios`)
|
- apple_sign_in (from `.symlinks/plugins/apple_sign_in/ios`)
|
||||||
|
- audioplayer (from `.symlinks/plugins/audioplayer/ios`)
|
||||||
- devicelocale (from `.symlinks/plugins/devicelocale/ios`)
|
- devicelocale (from `.symlinks/plugins/devicelocale/ios`)
|
||||||
- firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`)
|
- firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`)
|
||||||
- firebase_auth (from `.symlinks/plugins/firebase_auth/ios`)
|
- firebase_auth (from `.symlinks/plugins/firebase_auth/ios`)
|
||||||
@ -232,6 +235,8 @@ SPEC REPOS:
|
|||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
apple_sign_in:
|
apple_sign_in:
|
||||||
:path: ".symlinks/plugins/apple_sign_in/ios"
|
:path: ".symlinks/plugins/apple_sign_in/ios"
|
||||||
|
audioplayer:
|
||||||
|
:path: ".symlinks/plugins/audioplayer/ios"
|
||||||
devicelocale:
|
devicelocale:
|
||||||
:path: ".symlinks/plugins/devicelocale/ios"
|
:path: ".symlinks/plugins/devicelocale/ios"
|
||||||
firebase_analytics:
|
firebase_analytics:
|
||||||
@ -274,6 +279,7 @@ EXTERNAL SOURCES:
|
|||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
AppAuth: 31bcec809a638d7bd2f86ea8a52bd45f6e81e7c7
|
AppAuth: 31bcec809a638d7bd2f86ea8a52bd45f6e81e7c7
|
||||||
apple_sign_in: 7716c7ddfa195aeab7dec0dc374ef4ff45d1adb4
|
apple_sign_in: 7716c7ddfa195aeab7dec0dc374ef4ff45d1adb4
|
||||||
|
audioplayer: 0584f31a697e4b0bbad405ae7903d7a93585e784
|
||||||
devicelocale: feebbe5e7a30adb8c4f83185de1b50ff19b44f00
|
devicelocale: feebbe5e7a30adb8c4f83185de1b50ff19b44f00
|
||||||
FBSDKCoreKit: ac6cc500b8e104bb9a4dd20b1527b5d199123c2e
|
FBSDKCoreKit: ac6cc500b8e104bb9a4dd20b1527b5d199123c2e
|
||||||
FBSDKLoginKit: e9b6542fdee322333502ab497f628b011dce7d78
|
FBSDKLoginKit: e9b6542fdee322333502ab497f628b011dce7d78
|
||||||
|
@ -388,7 +388,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 3;
|
CURRENT_PROJECT_VERSION = 2;
|
||||||
DEVELOPMENT_TEAM = SFJJBDCU6Z;
|
DEVELOPMENT_TEAM = SFJJBDCU6Z;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
@ -405,7 +405,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"$(PROJECT_DIR)/Flutter",
|
"$(PROJECT_DIR)/Flutter",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.1.6;
|
MARKETING_VERSION = 1.1.7;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app;
|
PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
@ -531,7 +531,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 3;
|
CURRENT_PROJECT_VERSION = 2;
|
||||||
DEVELOPMENT_TEAM = SFJJBDCU6Z;
|
DEVELOPMENT_TEAM = SFJJBDCU6Z;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
@ -548,7 +548,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"$(PROJECT_DIR)/Flutter",
|
"$(PROJECT_DIR)/Flutter",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.1.6;
|
MARKETING_VERSION = 1.1.7;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app;
|
PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
@ -566,7 +566,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 3;
|
CURRENT_PROJECT_VERSION = 2;
|
||||||
DEVELOPMENT_TEAM = SFJJBDCU6Z;
|
DEVELOPMENT_TEAM = SFJJBDCU6Z;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
@ -583,7 +583,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"$(PROJECT_DIR)/Flutter",
|
"$(PROJECT_DIR)/Flutter",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.1.6;
|
MARKETING_VERSION = 1.1.7;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app;
|
PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
|
@ -47,8 +47,14 @@
|
|||||||
<string>10.0</string>
|
<string>10.0</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>NSAppTransportSecurity</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSAllowsArbitraryLoads</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
<key>UIBackgroundModes</key>
|
<key>UIBackgroundModes</key>
|
||||||
<array>
|
<array>
|
||||||
|
<string>audio</string>
|
||||||
<string>fetch</string>
|
<string>fetch</string>
|
||||||
<string>remote-notification</string>
|
<string>remote-notification</string>
|
||||||
</array>
|
</array>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:collection';
|
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/exercise.dart';
|
||||||
import 'package:aitrainer_app/model/workout_menu_tree.dart';
|
import 'package:aitrainer_app/model/workout_menu_tree.dart';
|
||||||
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||||
|
32
lib/bloc/development_sizes/development_sizes_bloc.dart
Normal file
@ -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<DevelopmentSizesEvent, DevelopmentSizesState> {
|
||||||
|
final CustomerRepository customerRepository;
|
||||||
|
DevelopmentSizesBloc({this.customerRepository}) : super(DevelopmentSizesInitial()) {
|
||||||
|
isMan = Cache().userLoggedIn.sex == "m";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isMan;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<DevelopmentSizesState> mapEventToState(
|
||||||
|
DevelopmentSizesEvent event,
|
||||||
|
) async* {
|
||||||
|
try {
|
||||||
|
if (state is DevelopmentSizesLoad) {
|
||||||
|
yield DevelopmentSizesLoading();
|
||||||
|
yield DevelopmentSizesReady();
|
||||||
|
}
|
||||||
|
} on Exception catch (e) {
|
||||||
|
yield DevelopmentSizesError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
lib/bloc/development_sizes/development_sizes_event.dart
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
part of 'development_sizes_bloc.dart';
|
||||||
|
|
||||||
|
abstract class DevelopmentSizesEvent extends Equatable {
|
||||||
|
const DevelopmentSizesEvent();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class DevelopmentSizesLoad extends DevelopmentSizesEvent {
|
||||||
|
const DevelopmentSizesLoad();
|
||||||
|
}
|
28
lib/bloc/development_sizes/development_sizes_state.dart
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
part of 'development_sizes_bloc.dart';
|
||||||
|
|
||||||
|
abstract class DevelopmentSizesState extends Equatable {
|
||||||
|
const DevelopmentSizesState();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> 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<Object> get props => [this.message];
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'package:aitrainer_app/bloc/timer/timer_bloc.dart';
|
||||||
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
@ -9,6 +10,7 @@ part 'exercise_control_event.dart';
|
|||||||
part 'exercise_control_state.dart';
|
part 'exercise_control_state.dart';
|
||||||
|
|
||||||
class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlState> {
|
class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlState> {
|
||||||
|
final TimerBloc timerBloc;
|
||||||
final ExerciseRepository exerciseRepository;
|
final ExerciseRepository exerciseRepository;
|
||||||
final bool readonly;
|
final bool readonly;
|
||||||
final double percentToCalculate;
|
final double percentToCalculate;
|
||||||
@ -25,7 +27,8 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
|
|||||||
double scrollOffset = 0;
|
double scrollOffset = 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ExerciseControlBloc({this.exerciseRepository, this.readonly, this.percentToCalculate}) : super(ExerciseControlInitial()) {
|
ExerciseControlBloc({this.exerciseRepository, this.readonly, this.percentToCalculate, @required this.timerBloc})
|
||||||
|
: super(ExerciseControlInitial()) {
|
||||||
initialRM = this.calculate1RM(percent75: false);
|
initialRM = this.calculate1RM(percent75: false);
|
||||||
unitQuantity = this.calculate1RM(percent75: true).roundToDouble();
|
unitQuantity = this.calculate1RM(percent75: true).roundToDouble();
|
||||||
quantity = percentToCalculate == 0.75 ? 12 : 30;
|
quantity = percentToCalculate == 0.75 ? 12 : 30;
|
||||||
@ -34,6 +37,7 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
|
|||||||
exerciseRepository.setUnitQuantity(unitQuantity);
|
exerciseRepository.setUnitQuantity(unitQuantity);
|
||||||
exerciseRepository.setQuantity(quantity);
|
exerciseRepository.setQuantity(quantity);
|
||||||
print("init quantity: " + quantity.toString());
|
print("init quantity: " + quantity.toString());
|
||||||
|
timerBloc.add(TimerStart(duration: 300));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -78,6 +82,7 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
|
|||||||
|
|
||||||
exerciseRepository.setQuantity(quantity);
|
exerciseRepository.setQuantity(quantity);
|
||||||
exerciseRepository.exercise.exerciseId = null;
|
exerciseRepository.exercise.exerciseId = null;
|
||||||
|
step <= 3 ? timerBloc.add(TimerStart(duration: 300)) : timerBloc.add(TimerEnd());
|
||||||
}
|
}
|
||||||
yield ExerciseControlReady();
|
yield ExerciseControlReady();
|
||||||
}
|
}
|
||||||
@ -109,12 +114,7 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
|
|||||||
final double weight = exerciseRepository.exercise.unitQuantity;
|
final double weight = exerciseRepository.exercise.unitQuantity;
|
||||||
final double repeatWendler = (rmWendler - weight) / 0.0333 / weight;
|
final double repeatWendler = (rmWendler - weight) / 0.0333 / weight;
|
||||||
final double repeatOconner = (rmOconner / weight - 1) * 40;
|
final double repeatOconner = (rmOconner / weight - 1) * 40;
|
||||||
print("Weight: " +
|
print("Weight: $weight repeatWendler: $repeatWendler repeat Oconner: $repeatOconner");
|
||||||
weight.toString() +
|
return unitQuantity > 100 ? (repeatOconner + repeatWendler) / 2 : repeatWendler;
|
||||||
" repeatWendler: " +
|
|
||||||
repeatWendler.toStringAsFixed(0) +
|
|
||||||
" repeat Oconner: " +
|
|
||||||
repeatOconner.toStringAsFixed(0));
|
|
||||||
return repeatWendler;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,14 +44,12 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> with Logg
|
|||||||
String fitnessLevel;
|
String fitnessLevel;
|
||||||
bool changedWeight = false;
|
bool changedWeight = false;
|
||||||
bool changedSizes = false;
|
bool changedSizes = false;
|
||||||
final List<Property> womanSizes = List();
|
|
||||||
final List<Property> manSizes = List();
|
|
||||||
|
|
||||||
final double baseWidth = 312;
|
final double baseWidth = 312;
|
||||||
final double baseHeight = 675.2;
|
final double baseHeight = 675.2;
|
||||||
double mediaWidth = 0;
|
double mediaWidth = 0;
|
||||||
double mediaHeight = 0;
|
double mediaHeight = 0;
|
||||||
bool isMan = true;
|
|
||||||
String exerciseTask = "";
|
String exerciseTask = "";
|
||||||
|
|
||||||
final StopWatchTimer stopWatchTimer = StopWatchTimer(
|
final StopWatchTimer stopWatchTimer = StopWatchTimer(
|
||||||
@ -73,7 +71,7 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> with Logg
|
|||||||
height = customerRepository.customer.getProperty("Height");
|
height = customerRepository.customer.getProperty("Height");
|
||||||
birthYear = customerRepository.customer.birthYear;
|
birthYear = customerRepository.customer.birthYear;
|
||||||
fitnessLevel = customerRepository.customer.fitnessLevel;
|
fitnessLevel = customerRepository.customer.fitnessLevel;
|
||||||
this.isMan = (customerRepository.customer.sex == "m");
|
|
||||||
}
|
}
|
||||||
if (exerciseType.unit == "second") {
|
if (exerciseType.unit == "second") {
|
||||||
stopWatchTimer.rawTime.listen((value) => {timerValue = value, this.setQuantity((value / 1000).toDouble())});
|
stopWatchTimer.rawTime.listen((value) => {timerValue = value, this.setQuantity((value / 1000).toDouble())});
|
||||||
@ -109,196 +107,6 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> with Logg
|
|||||||
exerciseRepository.setQuantity(quantity);
|
exerciseRepository.setQuantity(quantity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMediaDimensions(double width, double height) {
|
|
||||||
this.mediaHeight = height;
|
|
||||||
this.mediaWidth = width;
|
|
||||||
this.addSizes(customerRepository.sex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addSizes(String sex) {
|
|
||||||
List<Property> 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<Property> sizes;
|
|
||||||
if (customerRepository.sex == "Man") {
|
|
||||||
sizes = this.manSizes;
|
|
||||||
} else {
|
|
||||||
sizes = this.womanSizes;
|
|
||||||
}
|
|
||||||
|
|
||||||
sizes.forEach((element) {
|
|
||||||
if (element.propertyName == propertyName) {
|
|
||||||
property = element;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return property;
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateSizes(String propertyName, double value) {
|
|
||||||
List<Property> sizes;
|
|
||||||
if (customerRepository.sex == "Man") {
|
|
||||||
sizes = this.manSizes;
|
|
||||||
} else {
|
|
||||||
sizes = this.womanSizes;
|
|
||||||
}
|
|
||||||
|
|
||||||
sizes.forEach((element) {
|
|
||||||
if (element.propertyName == propertyName) {
|
|
||||||
element.value = value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Stream<ExerciseNewState> mapEventToState(ExerciseNewEvent event) async* {
|
Stream<ExerciseNewState> mapEventToState(ExerciseNewEvent event) async* {
|
||||||
try {
|
try {
|
||||||
@ -358,7 +166,7 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> with Logg
|
|||||||
} else if (event is ExerciseNewSizeChange) {
|
} else if (event is ExerciseNewSizeChange) {
|
||||||
yield ExerciseNewLoading();
|
yield ExerciseNewLoading();
|
||||||
this.changedSizes = true;
|
this.changedSizes = true;
|
||||||
this.updateSizes(event.propertyName, event.value);
|
this.customerRepository.updateSizes(event.propertyName, event.value);
|
||||||
customerRepository.setCustomerProperty(event.propertyName, event.value);
|
customerRepository.setCustomerProperty(event.propertyName, event.value);
|
||||||
yield ExerciseNewReady();
|
yield ExerciseNewReady();
|
||||||
} else if (event is ExerciseNewSubmit) {
|
} else if (event is ExerciseNewSubmit) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:aitrainer_app/bloc/settings/settings_bloc.dart';
|
import 'package:aitrainer_app/bloc/settings/settings_bloc.dart';
|
||||||
import 'package:aitrainer_app/localization/app_language.dart';
|
import 'package:aitrainer_app/util/app_language.dart';
|
||||||
import 'package:aitrainer_app/service/logging.dart';
|
import 'package:aitrainer_app/service/logging.dart';
|
||||||
import 'package:aitrainer_app/util/session.dart';
|
import 'package:aitrainer_app/util/session.dart';
|
||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:aitrainer_app/localization/app_language.dart';
|
import 'package:aitrainer_app/util/app_language.dart';
|
||||||
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/model/cache.dart';
|
||||||
import 'package:aitrainer_app/service/logging.dart';
|
import 'package:aitrainer_app/service/logging.dart';
|
||||||
import 'package:aitrainer_app/util/enums.dart';
|
import 'package:aitrainer_app/util/enums.dart';
|
||||||
|
106
lib/bloc/timer/timer_bloc.dart
Normal file
@ -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<int> 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<TimerEvent, TimerState> {
|
||||||
|
final Ticker _ticker = Ticker();
|
||||||
|
int _duration = 0;
|
||||||
|
|
||||||
|
final AudioPlayer audioPlayer = AudioPlayer();
|
||||||
|
int minutes = 0;
|
||||||
|
int seconds = 0;
|
||||||
|
|
||||||
|
StreamSubscription<int> _tickerSubscription;
|
||||||
|
|
||||||
|
TimerBloc() : super(TimerReady(300));
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onTransition(Transition<TimerEvent, TimerState> transition) {
|
||||||
|
super.onTransition(transition);
|
||||||
|
//print(transition);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<TimerState> 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<void> close() {
|
||||||
|
_tickerSubscription?.cancel();
|
||||||
|
return super.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<TimerState> _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<TimerState> _mapPauseToState(TimerPause pause) async* {
|
||||||
|
if (state is TimerRunning) {
|
||||||
|
_tickerSubscription?.pause();
|
||||||
|
yield TimerPaused(state.duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<TimerState> _mapResumeToState(TimerResume pause) async* {
|
||||||
|
if (state is TimerPaused) {
|
||||||
|
_tickerSubscription?.resume();
|
||||||
|
yield TimerRunning(state.duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<TimerState> _mapResetToState(TimerReset reset) async* {
|
||||||
|
this._duration = 0;
|
||||||
|
yield TimerReady(_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<TimerState> _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);
|
||||||
|
}
|
||||||
|
}
|
41
lib/bloc/timer/timer_event.dart
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
part of 'timer_bloc.dart';
|
||||||
|
|
||||||
|
abstract class TimerEvent extends Equatable {
|
||||||
|
const TimerEvent();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> 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();
|
||||||
|
}
|
49
lib/bloc/timer/timer_state.dart
Normal file
@ -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<Object> 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);
|
||||||
|
}
|
161
lib/library/clock.dart
Normal file
@ -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<Color> 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<TimerBloc, TimerState>(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: <Widget>[
|
||||||
|
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<Color> _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;
|
||||||
|
}
|
||||||
|
}
|
@ -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_body_page.dart';
|
||||||
import 'package:aitrainer_app/view/mydevelopment_muscle_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_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/myexcercise_plan_page.dart';
|
||||||
import 'package:aitrainer_app/view/registration.dart';
|
import 'package:aitrainer_app/view/registration.dart';
|
||||||
import 'package:aitrainer_app/view/reset_password.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/widgets.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_localizations/flutter_localizations.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:google_fonts/google_fonts.dart';
|
||||||
import 'package:sentry/sentry.dart';
|
import 'package:sentry/sentry.dart';
|
||||||
import 'bloc/account/account_bloc.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/menu/menu_bloc.dart';
|
||||||
import 'bloc/session/session_bloc.dart';
|
import 'bloc/session/session_bloc.dart';
|
||||||
import 'bloc/settings/settings_bloc.dart';
|
import 'bloc/settings/settings_bloc.dart';
|
||||||
|
import 'bloc/timer/timer_bloc.dart';
|
||||||
|
|
||||||
const dsn = 'https://5fac40cbfcfb4c15aa80c7a8638d7310@o418565.ingest.sentry.io/5322520';
|
const dsn = 'https://5fac40cbfcfb4c15aa80c7a8638d7310@o418565.ingest.sentry.io/5322520';
|
||||||
|
|
||||||
@ -145,6 +147,9 @@ Future<Null> main() async {
|
|||||||
BlocProvider<BodyDevelopmentBloc>(
|
BlocProvider<BodyDevelopmentBloc>(
|
||||||
create: (BuildContext context) => BodyDevelopmentBloc(workoutTreeRepository: menuTreeRepository),
|
create: (BuildContext context) => BodyDevelopmentBloc(workoutTreeRepository: menuTreeRepository),
|
||||||
),
|
),
|
||||||
|
BlocProvider<TimerBloc>(
|
||||||
|
create: (BuildContext context) => TimerBloc(),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
child: WorkoutTestApp(),
|
child: WorkoutTestApp(),
|
||||||
));
|
));
|
||||||
@ -218,6 +223,7 @@ class WorkoutTestApp extends StatelessWidget {
|
|||||||
'exerciseExecuteAddPage': (context) => ExerciseExecutePlanAddPage(),
|
'exerciseExecuteAddPage': (context) => ExerciseExecutePlanAddPage(),
|
||||||
'mydevelopmentMusclePage': (context) => MyDevelopmentMusclePage(),
|
'mydevelopmentMusclePage': (context) => MyDevelopmentMusclePage(),
|
||||||
'mydevelopmentBodyPage': (context) => MyDevelopmentBodyPage(),
|
'mydevelopmentBodyPage': (context) => MyDevelopmentBodyPage(),
|
||||||
|
'mydevelopmentSizesPage': (context) => SizesDevelopmentPage(),
|
||||||
'evaluationPage': (context) => EvaluationPage(),
|
'evaluationPage': (context) => EvaluationPage(),
|
||||||
'salesPage': (context) => SalesPage(),
|
'salesPage': (context) => SalesPage(),
|
||||||
},
|
},
|
||||||
|
@ -62,6 +62,7 @@ class Cache with Logging {
|
|||||||
static final String serverKey = 'live';
|
static final String serverKey = 'live';
|
||||||
static final String hardwareKey = 'hardware';
|
static final String hardwareKey = 'hardware';
|
||||||
static final String loginTypeKey = 'login_type';
|
static final String loginTypeKey = 'login_type';
|
||||||
|
static final String timerDisplayKey = 'timer_display';
|
||||||
|
|
||||||
static String baseUrl = 'http://aitrainer.info:8888/api/';
|
static String baseUrl = 'http://aitrainer.info:8888/api/';
|
||||||
static final String mediaUrl = 'https://aitrainer.info:4343/media/';
|
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 _ecto = customerRepository.getCustomerPropertyValue(PropertyEnum.Ectomorph.toStr()).toInt();
|
||||||
int _mezo = customerRepository.getCustomerPropertyValue(PropertyEnum.Mesomorph.toStr()).toInt();
|
int _mezo = customerRepository.getCustomerPropertyValue(PropertyEnum.Mesomorph.toStr()).toInt();
|
||||||
int _endo = customerRepository.getCustomerPropertyValue(PropertyEnum.Endomorph.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 != null) {
|
||||||
if (this.userLoggedIn.birthYear == null || this.userLoggedIn.birthYear == 0) {
|
if (this.userLoggedIn.birthYear == null || this.userLoggedIn.birthYear == 0) {
|
||||||
setBadge("personalData", true);
|
setBadge("personalData", true);
|
||||||
|
@ -38,9 +38,26 @@ class WorkoutMenuTree {
|
|||||||
bool executed = false;
|
bool executed = false;
|
||||||
String exerciseDetail;
|
String exerciseDetail;
|
||||||
String nameEnglish;
|
String nameEnglish;
|
||||||
|
String parentName;
|
||||||
|
String parentNameEnglish;
|
||||||
|
|
||||||
WorkoutMenuTree(this.id, this.parent, this.name, this.imageName, this.color, this.fontSize, this.child, this.exerciseTypeId,
|
WorkoutMenuTree(
|
||||||
this.exerciseType, this.base, this.is1RM, this.isEndurance, this.isRunning, this.nameEnglish);
|
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<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
return {
|
return {
|
||||||
|
@ -11,6 +11,7 @@ import 'package:aitrainer_app/service/customer_service.dart';
|
|||||||
import 'package:aitrainer_app/service/logging.dart';
|
import 'package:aitrainer_app/service/logging.dart';
|
||||||
import 'package:aitrainer_app/service/product_test_service.dart';
|
import 'package:aitrainer_app/service/product_test_service.dart';
|
||||||
import 'package:aitrainer_app/service/purchase_service.dart';
|
import 'package:aitrainer_app/service/purchase_service.dart';
|
||||||
|
import 'package:aitrainer_app/util/enums.dart';
|
||||||
import 'package:aitrainer_app/util/not_found_exception.dart';
|
import 'package:aitrainer_app/util/not_found_exception.dart';
|
||||||
|
|
||||||
class GenderItem {
|
class GenderItem {
|
||||||
@ -25,6 +26,14 @@ class CustomerRepository with Logging {
|
|||||||
List<Customer> _trainees;
|
List<Customer> _trainees;
|
||||||
List<CustomerProperty> _allProperties;
|
List<CustomerProperty> _allProperties;
|
||||||
final PropertyRepository propertyRepository = PropertyRepository();
|
final PropertyRepository propertyRepository = PropertyRepository();
|
||||||
|
final List<Property> womanSizes = List();
|
||||||
|
final List<Property> manSizes = List();
|
||||||
|
|
||||||
|
final double baseWidth = 312;
|
||||||
|
final double baseHeight = 675.2;
|
||||||
|
double mediaWidth = 0;
|
||||||
|
double mediaHeight = 0;
|
||||||
|
bool isMan = true;
|
||||||
|
|
||||||
//List<CustomerRepository> customerList = List<CustomerRepository>();
|
//List<CustomerRepository> customerList = List<CustomerRepository>();
|
||||||
bool visibleDetails = false;
|
bool visibleDetails = false;
|
||||||
@ -32,10 +41,10 @@ class CustomerRepository with Logging {
|
|||||||
|
|
||||||
CustomerRepository({this.customer}) {
|
CustomerRepository({this.customer}) {
|
||||||
customer = Customer();
|
customer = Customer();
|
||||||
genders = [
|
|
||||||
GenderItem("m", "Man"),
|
if (Cache().userLoggedIn != null) {
|
||||||
GenderItem("w", "Woman"),
|
isMan = (Cache().userLoggedIn.sex == "m");
|
||||||
];
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String getGenderByName(String name) {
|
String getGenderByName(String name) {
|
||||||
@ -297,4 +306,194 @@ class CustomerRepository with Logging {
|
|||||||
Future<void> addProductTest(ProductTest productTest) async {
|
Future<void> addProductTest(ProductTest productTest) async {
|
||||||
await ProductTestApi().saveProductTest(productTest);
|
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<Property> 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<Property> 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<Property> sizes;
|
||||||
|
if (this.sex == "m") {
|
||||||
|
sizes = this.manSizes;
|
||||||
|
} else {
|
||||||
|
sizes = this.womanSizes;
|
||||||
|
}
|
||||||
|
|
||||||
|
sizes.forEach((element) {
|
||||||
|
if (element.propertyName == propertyName) {
|
||||||
|
element.value = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import 'dart:collection';
|
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/cache.dart';
|
||||||
import 'package:aitrainer_app/model/customer.dart';
|
import 'package:aitrainer_app/model/customer.dart';
|
||||||
import 'package:aitrainer_app/model/exercise.dart';
|
import 'package:aitrainer_app/model/exercise.dart';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import 'dart:collection';
|
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/cache.dart';
|
||||||
import 'package:aitrainer_app/model/exercise_ability.dart';
|
import 'package:aitrainer_app/model/exercise_ability.dart';
|
||||||
import 'package:aitrainer_app/model/exercise_tree.dart';
|
import 'package:aitrainer_app/model/exercise_tree.dart';
|
||||||
@ -35,6 +35,7 @@ class WorkoutTreeRepository with Logging {
|
|||||||
SplayTreeMap sortedTree = SplayTreeMap<String, List<WorkoutMenuTree>>();
|
SplayTreeMap sortedTree = SplayTreeMap<String, List<WorkoutMenuTree>>();
|
||||||
bool isEnglish;
|
bool isEnglish;
|
||||||
WorkoutType workoutType;
|
WorkoutType workoutType;
|
||||||
|
final List<WorkoutMenuTree> menuAsExercise = List();
|
||||||
|
|
||||||
final Map<String, int> _antagonist = {
|
final Map<String, int> _antagonist = {
|
||||||
Antagonist.chest: Antagonist.chestNr,
|
Antagonist.chest: Antagonist.chestNr,
|
||||||
@ -85,23 +86,24 @@ class WorkoutTreeRepository with Logging {
|
|||||||
if (isRunning == false && treeItem.parentId != 0) {
|
if (isRunning == false && treeItem.parentId != 0) {
|
||||||
isRunning = isParentRunning(treeItem.parentId);
|
isRunning = isParentRunning(treeItem.parentId);
|
||||||
}
|
}
|
||||||
|
WorkoutMenuTree parent = getParentItem(treeItem.parentId);
|
||||||
WorkoutMenuTree menuItem = WorkoutMenuTree(
|
WorkoutMenuTree menuItem = WorkoutMenuTree(
|
||||||
treeItem.treeId,
|
treeItem.treeId,
|
||||||
treeItem.parentId,
|
treeItem.parentId,
|
||||||
treeName,
|
treeName,
|
||||||
treeItem.imageUrl,
|
treeItem.imageUrl,
|
||||||
Colors.white,
|
Colors.white,
|
||||||
30,
|
30,
|
||||||
false,
|
false,
|
||||||
0,
|
0,
|
||||||
null,
|
null,
|
||||||
false,
|
false,
|
||||||
is1RM,
|
is1RM,
|
||||||
isEndurance,
|
isEndurance,
|
||||||
isRunning,
|
isRunning,
|
||||||
treeItem.name,
|
treeItem.name,
|
||||||
);
|
parent != null ? parent.name : "",
|
||||||
|
parent != null ? parent.nameEnglish : "");
|
||||||
menuItem = this.setWorkoutTypes(menuItem, treeItem);
|
menuItem = this.setWorkoutTypes(menuItem, treeItem);
|
||||||
this.tree[treeItem.name + "_" + treeItem.parentId.toString()] = menuItem;
|
this.tree[treeItem.name + "_" + treeItem.parentId.toString()] = menuItem;
|
||||||
//log("WorkoutMenuTree item " + menuItem.toJson().toString());
|
//log("WorkoutMenuTree item " + menuItem.toJson().toString());
|
||||||
@ -113,6 +115,7 @@ class WorkoutTreeRepository with Logging {
|
|||||||
exerciseType.active == true) {
|
exerciseType.active == true) {
|
||||||
String exerciseTypeName = isEnglish ? exerciseType.name : exerciseType.nameTranslation;
|
String exerciseTypeName = isEnglish ? exerciseType.name : exerciseType.nameTranslation;
|
||||||
//String assetImage = await _buildImage(exerciseType.imageUrl); //'asset/menu/' + exerciseType.imageUrl.substring(7);
|
//String assetImage = await _buildImage(exerciseType.imageUrl); //'asset/menu/' + exerciseType.imageUrl.substring(7);
|
||||||
|
|
||||||
if (exerciseType.parents.isNotEmpty) {
|
if (exerciseType.parents.isNotEmpty) {
|
||||||
exerciseType.parents.forEach((parentId) {
|
exerciseType.parents.forEach((parentId) {
|
||||||
bool is1RM = this.isParent1RM(parentId);
|
bool is1RM = this.isParent1RM(parentId);
|
||||||
@ -121,6 +124,7 @@ class WorkoutTreeRepository with Logging {
|
|||||||
if (isEndurance) exerciseType.setAbility(ExerciseAbility.endurance);
|
if (isEndurance) exerciseType.setAbility(ExerciseAbility.endurance);
|
||||||
bool isRunning = this.isParentRunning(parentId);
|
bool isRunning = this.isParentRunning(parentId);
|
||||||
if (isRunning) exerciseType.setAbility(ExerciseAbility.running);
|
if (isRunning) exerciseType.setAbility(ExerciseAbility.running);
|
||||||
|
WorkoutMenuTree parent = getParentItem(parentId);
|
||||||
WorkoutMenuTree menuItem = WorkoutMenuTree(
|
WorkoutMenuTree menuItem = WorkoutMenuTree(
|
||||||
exerciseType.exerciseTypeId,
|
exerciseType.exerciseTypeId,
|
||||||
parentId,
|
parentId,
|
||||||
@ -135,8 +139,11 @@ class WorkoutTreeRepository with Logging {
|
|||||||
is1RM,
|
is1RM,
|
||||||
isEndurance,
|
isEndurance,
|
||||||
isRunning,
|
isRunning,
|
||||||
exerciseType.name);
|
exerciseType.name,
|
||||||
|
parent != null ? parent.name : "",
|
||||||
|
parent != null ? parent.nameEnglish : "");
|
||||||
this.tree[exerciseType.name] = menuItem;
|
this.tree[exerciseType.name] = menuItem;
|
||||||
|
menuAsExercise.add(menuItem);
|
||||||
//log("WorkoutMenuTree item " + menuItem.toJson().toString());
|
//log("WorkoutMenuTree item " + menuItem.toJson().toString());
|
||||||
/* log("ExerciseType in Menu item " +
|
/* log("ExerciseType in Menu item " +
|
||||||
exerciseType.toJson().toString() +
|
exerciseType.toJson().toString() +
|
||||||
@ -156,6 +163,7 @@ class WorkoutTreeRepository with Logging {
|
|||||||
Cache().setWorkoutMenuTree(tree);
|
Cache().setWorkoutMenuTree(tree);
|
||||||
ExerciseRepository exerciseRepository = ExerciseRepository();
|
ExerciseRepository exerciseRepository = ExerciseRepository();
|
||||||
exerciseRepository.getBaseExerciseFinishedPercent();
|
exerciseRepository.getBaseExerciseFinishedPercent();
|
||||||
|
menuAsExercise.sort((a, b) => a.name.compareTo(b.name));
|
||||||
}
|
}
|
||||||
|
|
||||||
WorkoutMenuTree setWorkoutTypes(WorkoutMenuTree menu, ExerciseTree treeItem) {
|
WorkoutMenuTree setWorkoutTypes(WorkoutMenuTree menu, ExerciseTree treeItem) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import 'dart:convert';
|
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/cache.dart';
|
||||||
import 'package:aitrainer_app/model/exercise_type.dart';
|
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||||
import 'package:aitrainer_app/repository/user_repository.dart';
|
import 'package:aitrainer_app/repository/user_repository.dart';
|
||||||
|
@ -36,7 +36,7 @@ enum TrackingEvent {
|
|||||||
my_special_plan,
|
my_special_plan,
|
||||||
my_suggested_plan,
|
my_suggested_plan,
|
||||||
prediction,
|
prediction,
|
||||||
|
search,
|
||||||
exercise_device,
|
exercise_device,
|
||||||
customer_change,
|
customer_change,
|
||||||
settings_lang,
|
settings_lang,
|
||||||
@ -62,3 +62,11 @@ extension PropertyExt on PropertyEnum {
|
|||||||
bool equalsTo(PropertyEnum event) => this.toString() == event.toString();
|
bool equalsTo(PropertyEnum event) => this.toString() == event.toString();
|
||||||
bool equalsStringTo(String event) => this.toString() == event;
|
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;
|
||||||
|
}
|
||||||
|
@ -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<ProductDetails> _products = [];
|
|
||||||
List<PurchaseDetails> _purchases = [];
|
|
||||||
List<String> _notFoundIds = [];
|
|
||||||
List<String> _consumables = [];
|
|
||||||
bool _purchasePending = false;
|
|
||||||
String _queryProductError;
|
|
||||||
|
|
||||||
StreamSubscription<List<PurchaseDetails>> _subscription;
|
|
||||||
|
|
||||||
final List<String> _productList = List();
|
|
||||||
|
|
||||||
List getProductList() => _productList;
|
|
||||||
|
|
||||||
factory PlatformPurchaseApi() {
|
|
||||||
return _singleton;
|
|
||||||
}
|
|
||||||
|
|
||||||
PlatformPurchaseApi._internal();
|
|
||||||
|
|
||||||
Future<void> close() async {
|
|
||||||
_subscription.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> 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<PurchaseDetails> verifiedPurchases = [];
|
|
||||||
for (PurchaseDetails purchase in purchaseResponse.pastPurchases) {
|
|
||||||
if (await _verifyPurchase(purchase)) {
|
|
||||||
verifiedPurchases.add(purchase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO List<String> 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<void> 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<String> consumables = await ConsumableStore.load();
|
|
||||||
|
|
||||||
_purchasePending = false;
|
|
||||||
//_consumables = consumables;
|
|
||||||
} else {
|
|
||||||
_purchases.add(purchaseDetails);
|
|
||||||
_purchasePending = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<bool> _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<bool>.value(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _handleInvalidPurchase(PurchaseDetails purchaseDetails) {
|
|
||||||
// handle invalid purchase here if _verifyPurchase` failed.
|
|
||||||
log("Invalid Purchase" + purchaseDetails.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
void _listenToPurchaseUpdated(List<PurchaseDetails> 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`.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
@ -34,7 +34,8 @@ class RevenueCatPurchases with Logging {
|
|||||||
Future<void> restore() async {
|
Future<void> restore() async {
|
||||||
if (appUserId != null) {
|
if (appUserId != null) {
|
||||||
try {
|
try {
|
||||||
PurchaserInfo purchaserInfo = await Purchases.restoreTransactions();
|
//PurchaserInfo purchaserInfo = await Purchases.restoreTransactions();
|
||||||
|
PurchaserInfo purchaserInfo = await Purchases.getPurchaserInfo();
|
||||||
if (purchaserInfo != null &&
|
if (purchaserInfo != null &&
|
||||||
purchaserInfo.entitlements.all["wt_subscription"] != null &&
|
purchaserInfo.entitlements.all["wt_subscription"] != null &&
|
||||||
purchaserInfo.entitlements.all["wt_subscription"].isActive) {
|
purchaserInfo.entitlements.all["wt_subscription"].isActive) {
|
||||||
|
@ -1,15 +1,11 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:aitrainer_app/localization/app_language.dart';
|
import 'package:aitrainer_app/util/app_language.dart';
|
||||||
import 'package:aitrainer_app/localization/app_localization.dart';
|
import 'package:aitrainer_app/util/app_localization.dart';
|
||||||
import 'package:aitrainer_app/main.dart';
|
|
||||||
import 'package:aitrainer_app/service/api.dart';
|
import 'package:aitrainer_app/service/api.dart';
|
||||||
import 'package:aitrainer_app/service/logging.dart';
|
import 'package:aitrainer_app/service/logging.dart';
|
||||||
import 'package:aitrainer_app/service/package_service.dart';
|
import 'package:aitrainer_app/service/package_service.dart';
|
||||||
import 'package:aitrainer_app/service/product_service.dart';
|
|
||||||
import 'package:aitrainer_app/service/property_service.dart';
|
|
||||||
import 'package:aitrainer_app/util/purchases.dart';
|
import 'package:aitrainer_app/util/purchases.dart';
|
||||||
import 'package:aitrainer_app/util/track.dart';
|
|
||||||
import 'package:devicelocale/devicelocale.dart';
|
import 'package:devicelocale/devicelocale.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:package_info/package_info.dart';
|
import 'package:package_info/package_info.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';
|
import 'package:flutter/cupertino.dart';
|
||||||
|
|
||||||
mixin Trans {
|
mixin Trans {
|
||||||
|
@ -2,12 +2,10 @@ import 'dart:collection';
|
|||||||
|
|
||||||
import 'package:aitrainer_app/bloc/account/account_bloc.dart';
|
import 'package:aitrainer_app/bloc/account/account_bloc.dart';
|
||||||
import 'package:aitrainer_app/library/custom_icon_icons.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/cache.dart';
|
||||||
import 'package:aitrainer_app/model/customer.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/common.dart';
|
||||||
import 'package:aitrainer_app/util/enums.dart';
|
|
||||||
import 'package:aitrainer_app/util/trans.dart';
|
import 'package:aitrainer_app/util/trans.dart';
|
||||||
import 'package:aitrainer_app/widgets/app_bar_min.dart';
|
import 'package:aitrainer_app/widgets/app_bar_min.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
import 'package:aitrainer_app/bloc/custom_exercise_form_bloc.dart';
|
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/model/exercise_type.dart';
|
||||||
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||||
import 'package:aitrainer_app/service/logging.dart';
|
import 'package:aitrainer_app/service/logging.dart';
|
||||||
|
@ -2,7 +2,7 @@ import 'dart:collection';
|
|||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:aitrainer_app/bloc/body_type/bodytype_bloc.dart';
|
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/repository/customer_repository.dart';
|
||||||
import 'package:aitrainer_app/util/enums.dart';
|
import 'package:aitrainer_app/util/enums.dart';
|
||||||
import 'package:aitrainer_app/util/trans.dart';
|
import 'package:aitrainer_app/util/trans.dart';
|
||||||
@ -44,7 +44,7 @@ class _CustomerBodyTypeAnimationPageState extends State<CustomerBodyTypeAnimatio
|
|||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
image: DecorationImage(
|
image: DecorationImage(
|
||||||
image: AssetImage('asset/image/WT_black_G_background.jpg'),
|
image: AssetImage('asset/image/WT_plainblack_background.jpg'),
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
alignment: Alignment.topCenter,
|
alignment: Alignment.topCenter,
|
||||||
),
|
),
|
||||||
@ -445,8 +445,8 @@ class _QuestionState extends State<Question> with TickerProviderStateMixin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void buildAnimation() {
|
void buildAnimation() {
|
||||||
_controller = AnimationController(duration: const Duration(milliseconds: 1000), vsync: this);
|
_controller = AnimationController(duration: const Duration(milliseconds: 2000), vsync: this);
|
||||||
_animation = CurvedAnimation(parent: _controller, curve: Curves.slowMiddle);
|
_animation = CurvedAnimation(parent: _controller, curve: Curves.fastOutSlowIn);
|
||||||
|
|
||||||
_controller.forward();
|
_controller.forward();
|
||||||
}
|
}
|
||||||
|
@ -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<CustomerBodyTypePage> 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<CustomerChangeBloc>(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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
import 'package:aitrainer_app/bloc/customer_exercise_device/customer_exercise_device_bloc.dart';
|
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/cache.dart';
|
||||||
import 'package:aitrainer_app/model/exercise_device.dart';
|
import 'package:aitrainer_app/model/exercise_device.dart';
|
||||||
import 'package:aitrainer_app/repository/customer_exercise_device_repository.dart';
|
import 'package:aitrainer_app/repository/customer_exercise_device_repository.dart';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
import 'package:aitrainer_app/bloc/customer_change/customer_change_bloc.dart';
|
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/repository/customer_repository.dart';
|
||||||
import 'package:aitrainer_app/model/fitness_state.dart';
|
import 'package:aitrainer_app/model/fitness_state.dart';
|
||||||
import 'package:aitrainer_app/util/trans.dart';
|
import 'package:aitrainer_app/util/trans.dart';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
import 'package:aitrainer_app/bloc/customer_change/customer_change_bloc.dart';
|
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/repository/customer_repository.dart';
|
||||||
import 'package:aitrainer_app/util/trans.dart';
|
import 'package:aitrainer_app/util/trans.dart';
|
||||||
import 'package:aitrainer_app/widgets/app_bar_min.dart';
|
import 'package:aitrainer_app/widgets/app_bar_min.dart';
|
||||||
|
@ -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:aitrainer_app/widgets/app_bar_min.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import 'dart:collection';
|
|||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:aitrainer_app/bloc/result/result_bloc.dart';
|
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/cache.dart';
|
||||||
import 'package:aitrainer_app/model/exercise.dart';
|
import 'package:aitrainer_app/model/exercise.dart';
|
||||||
import 'package:aitrainer_app/model/exercise_ability.dart';
|
import 'package:aitrainer_app/model/exercise_ability.dart';
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
import 'package:aitrainer_app/bloc/exercise_control/exercise_control_bloc.dart';
|
import 'package:aitrainer_app/bloc/exercise_control/exercise_control_bloc.dart';
|
||||||
|
import 'package:aitrainer_app/bloc/timer/timer_bloc.dart';
|
||||||
import 'package:aitrainer_app/library/custom_icon_icons.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/cache.dart';
|
||||||
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||||
import 'package:aitrainer_app/util/trans.dart';
|
import 'package:aitrainer_app/util/trans.dart';
|
||||||
import 'package:aitrainer_app/widgets/app_bar.dart';
|
import 'package:aitrainer_app/widgets/app_bar.dart';
|
||||||
import 'package:aitrainer_app/widgets/bottom_nav.dart';
|
|
||||||
import 'package:aitrainer_app/widgets/dialog_html.dart';
|
import 'package:aitrainer_app/widgets/dialog_html.dart';
|
||||||
import 'package:aitrainer_app/widgets/number_picker.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_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -38,9 +39,12 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
|||||||
final double percent = arguments['percent'];
|
final double percent = arguments['percent'];
|
||||||
final bool readonly = arguments['readonly'];
|
final bool readonly = arguments['readonly'];
|
||||||
setContext(context);
|
setContext(context);
|
||||||
|
// ignore: close_sinks
|
||||||
|
TimerBloc timerBloc = BlocProvider.of<TimerBloc>(context);
|
||||||
|
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => ExerciseControlBloc(exerciseRepository: exerciseRepository, percentToCalculate: percent, readonly: readonly)
|
create: (context) => ExerciseControlBloc(
|
||||||
|
exerciseRepository: exerciseRepository, percentToCalculate: percent, readonly: readonly, timerBloc: timerBloc)
|
||||||
..add(ExerciseControlLoad()),
|
..add(ExerciseControlLoad()),
|
||||||
child: BlocConsumer<ExerciseControlBloc, ExerciseControlState>(listener: (context, state) {
|
child: BlocConsumer<ExerciseControlBloc, ExerciseControlState>(listener: (context, state) {
|
||||||
if (state is ExerciseControlError) {
|
if (state is ExerciseControlError) {
|
||||||
@ -53,7 +57,7 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
|||||||
_controller.animateTo(exerciseBloc.scrollOffset, duration: Duration(milliseconds: 300), curve: Curves.easeIn);
|
_controller.animateTo(exerciseBloc.scrollOffset, duration: Duration(milliseconds: 300), curve: Curves.easeIn);
|
||||||
}
|
}
|
||||||
return ModalProgressHUD(
|
return ModalProgressHUD(
|
||||||
child: getControlForm(exerciseBloc),
|
child: getControlForm(exerciseBloc, timerBloc),
|
||||||
inAsyncCall: state is ExerciseControlLoading,
|
inAsyncCall: state is ExerciseControlLoading,
|
||||||
opacity: 0.5,
|
opacity: 0.5,
|
||||||
color: Colors.black54,
|
color: Colors.black54,
|
||||||
@ -62,7 +66,7 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
Form getControlForm(ExerciseControlBloc exerciseBloc) {
|
Form getControlForm(ExerciseControlBloc exerciseBloc, TimerBloc timerBloc) {
|
||||||
this.offset = exerciseBloc.scrollOffset;
|
this.offset = exerciseBloc.scrollOffset;
|
||||||
String exerciseName = AppLanguage().appLocal == Locale("en")
|
String exerciseName = AppLanguage().appLocal == Locale("en")
|
||||||
? exerciseBloc.exerciseRepository.exerciseType.name
|
? exerciseBloc.exerciseRepository.exerciseType.name
|
||||||
@ -84,120 +88,63 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
|||||||
alignment: Alignment.topCenter,
|
alignment: Alignment.topCenter,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Container(
|
child: Stack(children: [
|
||||||
padding: const EdgeInsets.only(top: 10, left: 25, right: 25),
|
Container(
|
||||||
child: SingleChildScrollView(
|
padding: const EdgeInsets.only(top: 10, left: 25, right: 25),
|
||||||
scrollDirection: Axis.vertical,
|
child: SingleChildScrollView(
|
||||||
controller: _controller,
|
scrollDirection: Axis.vertical,
|
||||||
child: Column(
|
controller: _controller,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: <Widget>[
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
Text(
|
children: <Widget>[
|
||||||
exerciseName,
|
Text(
|
||||||
style: GoogleFonts.archivoBlack(
|
exerciseName,
|
||||||
fontWeight: FontWeight.bold,
|
style: GoogleFonts.archivoBlack(
|
||||||
fontSize: 24,
|
fontWeight: FontWeight.bold,
|
||||||
color: Colors.white,
|
fontSize: 24,
|
||||||
shadows: <Shadow>[
|
color: Colors.white,
|
||||||
Shadow(
|
shadows: <Shadow>[
|
||||||
offset: Offset(2.0, 2.0),
|
Shadow(
|
||||||
blurRadius: 6.0,
|
offset: Offset(2.0, 2.0),
|
||||||
color: Colors.black54,
|
blurRadius: 6.0,
|
||||||
),
|
color: Colors.black54,
|
||||||
Shadow(
|
),
|
||||||
offset: Offset(-3.0, 3.0),
|
Shadow(
|
||||||
blurRadius: 12.0,
|
offset: Offset(-3.0, 3.0),
|
||||||
color: Colors.black54,
|
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>[
|
|
||||||
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>[
|
|
||||||
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),
|
overflow: TextOverflow.fade,
|
||||||
GestureDetector(
|
textAlign: TextAlign.center,
|
||||||
onTap: () => {
|
maxLines: 2,
|
||||||
showDialog(
|
softWrap: true,
|
||||||
context: context,
|
),
|
||||||
builder: (BuildContext context) {
|
Divider(
|
||||||
return DialogHTML(
|
color: Colors.transparent,
|
||||||
title: t("OneRepMax"),
|
),
|
||||||
htmlData: t("OneRepMax_desc"),
|
Divider(
|
||||||
);
|
color: Colors.transparent,
|
||||||
})
|
),
|
||||||
},
|
Divider(
|
||||||
child: Icon(CustomIcon.question, color: Colors.yellow[300]))
|
color: Colors.transparent,
|
||||||
],
|
),
|
||||||
),
|
Divider(
|
||||||
Divider(),
|
color: Colors.transparent,
|
||||||
Row(mainAxisAlignment: MainAxisAlignment.start, children: [
|
),
|
||||||
Flexible(
|
Row(
|
||||||
child: Text(t("Why do you need Exercise Control?"),
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(t("Your 1RM:"),
|
||||||
style: GoogleFonts.inter(
|
style: GoogleFonts.inter(
|
||||||
color: Colors.yellow[300],
|
color: Colors.yellow[300],
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
shadows: <Shadow>[
|
shadows: <Shadow>[
|
||||||
Shadow(
|
Shadow(
|
||||||
offset: Offset(2.0, 2.0),
|
offset: Offset(-2.0, -2.0),
|
||||||
blurRadius: 6.0,
|
blurRadius: 12.0,
|
||||||
color: Colors.black54,
|
color: Colors.black54,
|
||||||
),
|
),
|
||||||
Shadow(
|
Shadow(
|
||||||
@ -206,29 +153,91 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
|||||||
color: Colors.black54,
|
color: Colors.black54,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
))),
|
)),
|
||||||
SizedBox(width: 10),
|
Text(
|
||||||
GestureDetector(
|
" " +
|
||||||
onTap: () => {
|
exerciseBloc.initialRM.toStringAsFixed(0) +
|
||||||
showDialog(
|
" " +
|
||||||
context: context,
|
exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit,
|
||||||
builder: (BuildContext context) {
|
style: GoogleFonts.inter(
|
||||||
return DialogHTML(
|
color: Colors.yellow[300],
|
||||||
title: t("Control Exercise:"),
|
fontSize: 18,
|
||||||
htmlData: t("controlexercise_desc"),
|
fontWeight: FontWeight.bold,
|
||||||
);
|
shadows: <Shadow>[
|
||||||
})
|
Shadow(
|
||||||
},
|
offset: Offset(-2.0, -2.0),
|
||||||
child: Icon(CustomIcon.question, color: Colors.yellow[300]))
|
blurRadius: 6.0,
|
||||||
|
color: Colors.black54,
|
||||||
|
),
|
||||||
|
Shadow(
|
||||||
|
offset: Offset(-3.0, 3.0),
|
||||||
|
blurRadius: 6.0,
|
||||||
|
color: Colors.black54,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 10),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () => {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return DialogHTML(
|
||||||
|
title: t("OneRepMax"),
|
||||||
|
htmlData: t("OneRepMax_desc"),
|
||||||
|
);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
child: Icon(CustomIcon.question, color: Colors.yellow[300]))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Divider(),
|
||||||
|
Row(mainAxisAlignment: MainAxisAlignment.start, children: [
|
||||||
|
Flexible(
|
||||||
|
child: Text(t("Why do you need Exercise Control?"),
|
||||||
|
style: GoogleFonts.inter(
|
||||||
|
color: Colors.yellow[300],
|
||||||
|
fontSize: 18,
|
||||||
|
shadows: <Shadow>[
|
||||||
|
Shadow(
|
||||||
|
offset: Offset(2.0, 2.0),
|
||||||
|
blurRadius: 6.0,
|
||||||
|
color: Colors.black54,
|
||||||
|
),
|
||||||
|
Shadow(
|
||||||
|
offset: Offset(-3.0, 3.0),
|
||||||
|
blurRadius: 12.0,
|
||||||
|
color: Colors.black54,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
))),
|
||||||
|
SizedBox(width: 10),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () => {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return DialogHTML(
|
||||||
|
title: t("Control Exercise:"),
|
||||||
|
htmlData: t("controlexercise_desc"),
|
||||||
|
);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
child: Icon(CustomIcon.question, color: Colors.yellow[300]))
|
||||||
|
]),
|
||||||
|
Divider(),
|
||||||
|
numberPickForm(exerciseBloc, 1),
|
||||||
|
Divider(),
|
||||||
|
numberPickForm(exerciseBloc, 2),
|
||||||
|
Divider(),
|
||||||
|
numberPickForm(exerciseBloc, 3),
|
||||||
]),
|
]),
|
||||||
Divider(),
|
)),
|
||||||
numberPickForm(exerciseBloc, 1),
|
TimerWidget(
|
||||||
Divider(),
|
bloc: timerBloc,
|
||||||
numberPickForm(exerciseBloc, 2),
|
),
|
||||||
Divider(),
|
])),
|
||||||
numberPickForm(exerciseBloc, 3),
|
|
||||||
]),
|
|
||||||
))),
|
|
||||||
//bottomNavigationBar: BottomNavigator(bottomNavIndex: 1),
|
//bottomNavigationBar: BottomNavigator(bottomNavIndex: 1),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -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/exercise_execute_plan_bloc.dart';
|
||||||
import 'package:aitrainer_app/bloc/exercise_execute_plan_add/exercise_execute_plan_add_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/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/model/workout_menu_tree.dart';
|
||||||
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||||
import 'package:aitrainer_app/util/trans.dart';
|
import 'package:aitrainer_app/util/trans.dart';
|
||||||
|
@ -7,7 +7,7 @@ import 'package:aitrainer_app/widgets/dialog_premium.dart';
|
|||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:intl/intl.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/cache.dart';
|
||||||
import 'package:aitrainer_app/model/exercise.dart';
|
import 'package:aitrainer_app/model/exercise.dart';
|
||||||
import 'package:aitrainer_app/model/exercise_type.dart';
|
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||||
|
@ -3,7 +3,7 @@ import 'dart:collection';
|
|||||||
import 'package:aitrainer_app/bloc/exercise_new/exercise_new_bloc.dart';
|
import 'package:aitrainer_app/bloc/exercise_new/exercise_new_bloc.dart';
|
||||||
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
|
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
|
||||||
import 'package:aitrainer_app/library/custom_icon_icons.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/cache.dart';
|
||||||
import 'package:aitrainer_app/model/exercise_ability.dart';
|
import 'package:aitrainer_app/model/exercise_ability.dart';
|
||||||
import 'package:aitrainer_app/model/exercise_type.dart';
|
import 'package:aitrainer_app/model/exercise_type.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/exercise_plan_bloc.dart';
|
||||||
import 'package:aitrainer_app/bloc/exercise_plan_custom_add/exercise_plan_custom_add_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/model/workout_menu_tree.dart';
|
||||||
import 'package:aitrainer_app/repository/exercise_plan_repository.dart';
|
import 'package:aitrainer_app/repository/exercise_plan_repository.dart';
|
||||||
import 'package:aitrainer_app/util/trans.dart';
|
import 'package:aitrainer_app/util/trans.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/repository/exercise_repository.dart';
|
||||||
import 'package:aitrainer_app/widgets/app_bar_min.dart';
|
import 'package:aitrainer_app/widgets/app_bar_min.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
|
@ -2,7 +2,6 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:aitrainer_app/bloc/account/account_bloc.dart';
|
import 'package:aitrainer_app/bloc/account/account_bloc.dart';
|
||||||
import 'package:aitrainer_app/bloc/login/login_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/repository/user_repository.dart';
|
||||||
import 'package:aitrainer_app/util/trans.dart';
|
import 'package:aitrainer_app/util/trans.dart';
|
||||||
import 'package:aitrainer_app/widgets/app_bar_min.dart';
|
import 'package:aitrainer_app/widgets/app_bar_min.dart';
|
||||||
@ -183,17 +182,17 @@ class LoginPage extends StatelessWidget with Trans {
|
|||||||
),
|
),
|
||||||
Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: <Widget>[
|
Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: <Widget>[
|
||||||
InkWell(
|
InkWell(
|
||||||
child: Text(AppLocalizations.of(context).translate('SignUpLink')),
|
child: Text(t('SignUpLink')),
|
||||||
onTap: () => Navigator.of(context).pushNamed('registration'),
|
onTap: () => Navigator.of(context).pushNamed('registration'),
|
||||||
),
|
),
|
||||||
Spacer(flex: 2),
|
Spacer(flex: 2),
|
||||||
InkWell(
|
InkWell(
|
||||||
child: Text(AppLocalizations.of(context).translate('I forgot the password')),
|
child: Text(t('I forgot the password')),
|
||||||
onTap: () => Navigator.of(context).pushNamed('resetPassword'),
|
onTap: () => Navigator.of(context).pushNamed('resetPassword'),
|
||||||
),
|
),
|
||||||
Spacer(flex: 2),
|
Spacer(flex: 2),
|
||||||
InkWell(
|
InkWell(
|
||||||
child: Text(AppLocalizations.of(context).translate('Privacy')),
|
child: Text(t('Privacy')),
|
||||||
onTap: () => {
|
onTap: () => {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
|
@ -83,15 +83,12 @@ class _MyDevelopmentMuscleState extends State<MyDevelopmentMusclePage> with Comm
|
|||||||
),
|
),
|
||||||
backgroundColor: Colors.orange,
|
backgroundColor: Colors.orange,
|
||||||
));
|
));
|
||||||
} else if (state is DevelopmentByMuscleLoadingState) {
|
|
||||||
//LoadingDialog.show(context);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
if (state is DevelopmentByMuscleStateInitial) {
|
if (state is DevelopmentByMuscleStateInitial) {
|
||||||
return Container();
|
return Container();
|
||||||
} else {
|
} else {
|
||||||
//LoadingDialog.hide(context);
|
|
||||||
return TreeView(
|
return TreeView(
|
||||||
startExpanded: false,
|
startExpanded: false,
|
||||||
children: _getTreeChildren(bloc.workoutTreeRepository.sortedTree, bloc),
|
children: _getTreeChildren(bloc.workoutTreeRepository.sortedTree, bloc),
|
||||||
|
@ -77,6 +77,25 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
|
|||||||
},
|
},
|
||||||
isLocked: true,
|
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(
|
ImageButton(
|
||||||
width: imageWidth,
|
width: imageWidth,
|
||||||
textAlignment: Alignment.topLeft,
|
textAlignment: Alignment.topLeft,
|
||||||
|
196
lib/view/mydevelopment_sizes_page.dart
Normal file
@ -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<SizesDevelopmentPage> with Trans {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
setContext(context);
|
||||||
|
return BlocProvider(
|
||||||
|
create: (context) => DevelopmentSizesBloc(customerRepository: CustomerRepository())..add(DevelopmentSizesLoad()),
|
||||||
|
child: BlocConsumer<DevelopmentSizesBloc, DevelopmentSizesState>(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<DevelopmentSizesBloc>(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<Widget> 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<Widget> 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>[
|
||||||
|
Shadow(
|
||||||
|
offset: Offset(5.0, 5.0),
|
||||||
|
blurRadius: 3.0,
|
||||||
|
color: Colors.black54,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
fontSize: 20,
|
||||||
|
color: Colors.orange[500],
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Widget> getSizeElements(DevelopmentSizesBloc bloc) {
|
||||||
|
List<Widget> 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));
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,6 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:aitrainer_app/bloc/account/account_bloc.dart';
|
import 'package:aitrainer_app/bloc/account/account_bloc.dart';
|
||||||
import 'package:aitrainer_app/bloc/login/login_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/repository/user_repository.dart';
|
||||||
import 'package:aitrainer_app/util/trans.dart';
|
import 'package:aitrainer_app/util/trans.dart';
|
||||||
import 'package:aitrainer_app/widgets/app_bar_min.dart';
|
import 'package:aitrainer_app/widgets/app_bar_min.dart';
|
||||||
@ -208,12 +207,12 @@ class RegistrationPage extends StatelessWidget with Trans {
|
|||||||
),
|
),
|
||||||
Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: <Widget>[
|
Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: <Widget>[
|
||||||
InkWell(
|
InkWell(
|
||||||
child: Text(AppLocalizations.of(context).translate('Login')),
|
child: Text(t('Login')),
|
||||||
onTap: () => Navigator.of(context).pushNamed('login'),
|
onTap: () => Navigator.of(context).pushNamed('login'),
|
||||||
),
|
),
|
||||||
Spacer(flex: 2),
|
Spacer(flex: 2),
|
||||||
InkWell(
|
InkWell(
|
||||||
child: Text(AppLocalizations.of(context).translate('Privacy')),
|
child: Text(t('Privacy')),
|
||||||
onTap: () => {
|
onTap: () => {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import 'package:aitrainer_app/bloc/reset_password_bloc.dart';
|
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/repository/user_repository.dart';
|
||||||
import 'package:aitrainer_app/util/trans.dart';
|
import 'package:aitrainer_app/util/trans.dart';
|
||||||
import 'package:aitrainer_app/widgets/app_bar_min.dart';
|
import 'package:aitrainer_app/widgets/app_bar_min.dart';
|
||||||
@ -77,8 +76,7 @@ class ResetPasswordPage extends StatelessWidget with Trans {
|
|||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
new InkWell(
|
new InkWell(
|
||||||
child: new Text(AppLocalizations.of(context).translate('I forgot the password'),
|
child: new Text(t('I forgot the password'), style: TextStyle(fontWeight: FontWeight.bold, fontSize: 24)),
|
||||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 24)),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -119,7 +117,7 @@ class ResetPasswordPage extends StatelessWidget with Trans {
|
|||||||
),
|
),
|
||||||
Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: <Widget>[
|
Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: <Widget>[
|
||||||
new InkWell(
|
new InkWell(
|
||||||
child: new Text(AppLocalizations.of(context).translate('Login')),
|
child: new Text(t('Login')),
|
||||||
onTap: () => Navigator.of(context).pushNamed('login'),
|
onTap: () => Navigator.of(context).pushNamed('login'),
|
||||||
),
|
),
|
||||||
Spacer(flex: 1),
|
Spacer(flex: 1),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
|
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
|
||||||
import 'package:aitrainer_app/bloc/settings/settings_bloc.dart';
|
import 'package:aitrainer_app/bloc/settings/settings_bloc.dart';
|
||||||
import 'package:aitrainer_app/library/custom_icon_icons.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/cache.dart';
|
||||||
import 'package:aitrainer_app/util/common.dart';
|
import 'package:aitrainer_app/util/common.dart';
|
||||||
import 'package:aitrainer_app/util/trans.dart';
|
import 'package:aitrainer_app/util/trans.dart';
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
|
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/model/cache.dart';
|
||||||
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||||
import 'package:aitrainer_app/util/common.dart';
|
import 'package:aitrainer_app/util/common.dart';
|
||||||
@ -69,6 +70,8 @@ class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin, C
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
menuBloc = BlocProvider.of<MenuBloc>(context);
|
menuBloc = BlocProvider.of<MenuBloc>(context);
|
||||||
|
// ignore: close_sinks
|
||||||
|
final TimerBloc timerBloc = BlocProvider.of<TimerBloc>(context);
|
||||||
|
|
||||||
return AppBar(
|
return AppBar(
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
@ -91,6 +94,7 @@ class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin, C
|
|||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
icon: Icon(Icons.arrow_back, color: Colors.white),
|
icon: Icon(Icons.arrow_back, color: Colors.white),
|
||||||
onPressed: () => {
|
onPressed: () => {
|
||||||
|
timerBloc.add(TimerEnd()),
|
||||||
if (widget.isMenu != null)
|
if (widget.isMenu != null)
|
||||||
{
|
{
|
||||||
if (menuBloc.workoutItem != null)
|
if (menuBloc.workoutItem != null)
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
|
import 'package:aitrainer_app/bloc/timer/timer_bloc.dart';
|
||||||
import 'package:aitrainer_app/model/cache.dart';
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
import 'package:aitrainer_app/util/common.dart';
|
import 'package:aitrainer_app/util/common.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
// ignore: must_be_immutable
|
// ignore: must_be_immutable
|
||||||
@ -24,6 +26,8 @@ class _AppBarNav extends State<AppBarMin> with Common {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
// ignore: close_sinks
|
||||||
|
final TimerBloc timerBloc = BlocProvider.of<TimerBloc>(context);
|
||||||
return AppBar(
|
return AppBar(
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
title: Row(
|
title: Row(
|
||||||
@ -44,6 +48,7 @@ class _AppBarNav extends State<AppBarMin> with Common {
|
|||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
icon: Icon(Icons.arrow_back, color: widget.back ? Colors.white : Colors.black),
|
icon: Icon(Icons.arrow_back, color: widget.back ? Colors.white : Colors.black),
|
||||||
onPressed: () => {
|
onPressed: () => {
|
||||||
|
timerBloc.add(TimerEnd()),
|
||||||
if (widget.back) {Navigator.of(context).pop()}
|
if (widget.back) {Navigator.of(context).pop()}
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
|
import 'package:aitrainer_app/bloc/timer/timer_bloc.dart';
|
||||||
import 'package:aitrainer_app/util/common.dart';
|
import 'package:aitrainer_app/util/common.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:liquid_progress_indicator/liquid_progress_indicator.dart';
|
import 'package:liquid_progress_indicator/liquid_progress_indicator.dart';
|
||||||
|
|
||||||
class AppBarProgress extends StatefulWidget implements PreferredSizeWidget {
|
class AppBarProgress extends StatefulWidget implements PreferredSizeWidget {
|
||||||
@ -23,14 +25,12 @@ class _AppBarNav extends State<AppBarProgress> with SingleTickerProviderStateMix
|
|||||||
_animationController = AnimationController(
|
_animationController = AnimationController(
|
||||||
lowerBound: (widget.min).toDouble(),
|
lowerBound: (widget.min).toDouble(),
|
||||||
upperBound: (widget.max).toDouble(),
|
upperBound: (widget.max).toDouble(),
|
||||||
//upperBound: (widget.value / 100).toDouble(),
|
|
||||||
vsync: this,
|
vsync: this,
|
||||||
duration: Duration(seconds: 3),
|
duration: Duration(seconds: 3),
|
||||||
);
|
);
|
||||||
|
|
||||||
_animationController.addListener(() => setState(() {}));
|
_animationController.addListener(() => setState(() {}));
|
||||||
_animationController.forward();
|
_animationController.forward();
|
||||||
//Future.delayed(Duration(seconds: 3)).then((value) => _animationController.repeat());
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,12 +42,15 @@ class _AppBarNav extends State<AppBarProgress> with SingleTickerProviderStateMix
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
// ignore: close_sinks
|
||||||
|
final TimerBloc timerBloc = BlocProvider.of<TimerBloc>(context);
|
||||||
|
|
||||||
return AppBar(
|
return AppBar(
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
title: getAnimatedWidget(),
|
title: getAnimatedWidget(),
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
icon: Icon(Icons.arrow_back, color: Colors.white),
|
icon: Icon(Icons.arrow_back, color: Colors.white),
|
||||||
onPressed: () => {Navigator.of(context).pop()},
|
onPressed: () => {timerBloc.add(TimerEnd()), Navigator.of(context).pop()},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import 'package:aitrainer_app/bloc/exercise_new/exercise_new_bloc.dart';
|
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:aitrainer_app/util/trans.dart';
|
||||||
import 'package:animated_widgets/widgets/rotation_animated.dart';
|
import 'package:animated_widgets/widgets/rotation_animated.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
@ -73,7 +73,7 @@ class _BMIState extends State<BMI> with Trans {
|
|||||||
double mediaWidth = MediaQuery.of(context).size.width * .8;
|
double mediaWidth = MediaQuery.of(context).size.width * .8;
|
||||||
double mediaHeight = MediaQuery.of(context).size.height * .8;
|
double mediaHeight = MediaQuery.of(context).size.height * .8;
|
||||||
//print("w " + mediaWidth.toString() + "h " + mediaHeight.toString());
|
//print("w " + mediaWidth.toString() + "h " + mediaHeight.toString());
|
||||||
widget.exerciseBloc.setMediaDimensions(mediaWidth, mediaHeight);
|
widget.exerciseBloc.customerRepository.setMediaDimensions(mediaWidth, mediaHeight);
|
||||||
widget.exerciseBloc.getBMI();
|
widget.exerciseBloc.getBMI();
|
||||||
return Form(
|
return Form(
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import 'package:aitrainer_app/bloc/exercise_new/exercise_new_bloc.dart';
|
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/model/fitness_state.dart';
|
||||||
import 'package:aitrainer_app/util/trans.dart';
|
import 'package:aitrainer_app/util/trans.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.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/model/cache.dart';
|
||||||
import 'package:aitrainer_app/service/logging.dart';
|
import 'package:aitrainer_app/service/logging.dart';
|
||||||
import 'package:aitrainer_app/util/common.dart';
|
import 'package:aitrainer_app/util/common.dart';
|
||||||
@ -94,7 +94,12 @@ class _NawDrawerWidget extends State<BottomNavigator> with Trans, Logging {
|
|||||||
backgroundColor: bgrColor,
|
backgroundColor: bgrColor,
|
||||||
icon: Icon(Icons.settings, color: inactive),
|
icon: Icon(Icons.settings, color: inactive),
|
||||||
activeIcon: Icon(Icons.settings, color: active),
|
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) {
|
onTap: (index) {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
@ -3,8 +3,11 @@ import 'dart:ui';
|
|||||||
|
|
||||||
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
|
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
|
||||||
import 'package:aitrainer_app/library/custom_icon_icons.dart';
|
import 'package:aitrainer_app/library/custom_icon_icons.dart';
|
||||||
import 'package:aitrainer_app/localization/app_language.dart';
|
import 'package:aitrainer_app/util/enums.dart';
|
||||||
import 'package:aitrainer_app/localization/app_localization.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/cache.dart';
|
||||||
import 'package:aitrainer_app/model/workout_menu_tree.dart';
|
import 'package:aitrainer_app/model/workout_menu_tree.dart';
|
||||||
import 'package:aitrainer_app/service/logging.dart';
|
import 'package:aitrainer_app/service/logging.dart';
|
||||||
@ -233,86 +236,50 @@ class _MenuPageWidgetState extends State<MenuPageWidget> with Trans, Logging {
|
|||||||
return sliverList;
|
return sliverList;
|
||||||
}
|
}
|
||||||
|
|
||||||
SliverList getInfoWidget(BuildContext context, MenuBloc menuBloc) {
|
SliverAppBar getInfoWidget(BuildContext context, MenuBloc menuBloc) {
|
||||||
List<Widget> widgets = List();
|
menuBloc.setContext(context);
|
||||||
|
menuBloc.setMenuInfo();
|
||||||
|
|
||||||
if (context != null) {
|
SliverAppBar sliverAppBar = SliverAppBar(
|
||||||
menuBloc.setContext(context);
|
backgroundColor: Colors.transparent,
|
||||||
menuBloc.setMenuInfo();
|
title: Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [
|
||||||
widgets.add(SizedBox(
|
SizedBox(
|
||||||
height: 10,
|
width: 10,
|
||||||
));
|
),
|
||||||
|
GestureDetector(
|
||||||
widgets.add(
|
onTap: () => {
|
||||||
GestureDetector(
|
showDialog(
|
||||||
onTap: () => {
|
context: context,
|
||||||
showDialog(
|
barrierDismissible: false,
|
||||||
context: context,
|
builder: (BuildContext context) {
|
||||||
barrierDismissible: false,
|
return DialogCommon(
|
||||||
builder: (BuildContext context) {
|
title: menuBloc.infoTitle,
|
||||||
return DialogCommon(
|
descriptions: menuBloc.infoText,
|
||||||
title: menuBloc.infoTitle,
|
description2: menuBloc.infoText2,
|
||||||
descriptions: menuBloc.infoText,
|
description3: menuBloc.infoText3,
|
||||||
description2: menuBloc.infoText2,
|
text: "OK",
|
||||||
description3: menuBloc.infoText3,
|
onTap: () => {Navigator.of(context).pop()},
|
||||||
text: "OK",
|
onCancel: () => {Navigator.of(context).pop()},
|
||||||
onTap: () => {Navigator.of(context).pop()},
|
);
|
||||||
onCancel: () => {Navigator.of(context).pop()},
|
})
|
||||||
);
|
},
|
||||||
})
|
child: Icon(
|
||||||
},
|
CustomIcon.question_circle,
|
||||||
child: Align(
|
color: Colors.orange[400],
|
||||||
alignment: Alignment.center,
|
size: 40,
|
||||||
child: SizedBox(
|
)),
|
||||||
height: 35,
|
MenuSearchBar(
|
||||||
child: AnimatedSwitcher(
|
listItems: menuBloc.menuTreeRepository.menuAsExercise,
|
||||||
duration: Duration(milliseconds: 800),
|
onFind: (value) => {
|
||||||
transitionBuilder: (Widget child, Animation<double> animation) {
|
Track().track(TrackingEvent.search, eventValue: value.exerciseType.name),
|
||||||
return ScaleTransition(child: child, scale: animation);
|
Navigator.of(context).pushNamed('exerciseNewPage', arguments: value.exerciseType)
|
||||||
},
|
},
|
||||||
child: isFirst && !wait
|
),
|
||||||
? Icon(
|
SizedBox(
|
||||||
CustomIcon.question_circle,
|
width: 10,
|
||||||
color: Colors.yellow[300],
|
),
|
||||||
size: 40,
|
]));
|
||||||
)
|
return sliverAppBar;
|
||||||
: Offstage())))),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
SliverList sliverList = SliverList(delegate: SliverChildListDelegate(widgets));
|
|
||||||
return sliverList;
|
|
||||||
}
|
|
||||||
|
|
||||||
SliverGrid getInfoWidget2(BuildContext context, MenuBloc menuBloc) {
|
|
||||||
final List<Widget> _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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void menuClick(WorkoutMenuTree workoutTree, MenuBloc menuBloc, BuildContext context) {
|
void menuClick(WorkoutMenuTree workoutTree, MenuBloc menuBloc, BuildContext context) {
|
||||||
|
277
lib/widgets/menu_search_bar.dart
Normal file
@ -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<bool> streamController = StreamController<bool>.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<AnimatedSearch> {
|
||||||
|
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<WorkoutMenuTree>(
|
||||||
|
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<AnimateExpansion> with SingleTickerProviderStateMixin {
|
||||||
|
AnimationController _animationController;
|
||||||
|
Animation<double> _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();
|
||||||
|
}
|
||||||
|
}
|
@ -53,7 +53,7 @@ class _SizeState extends State<SizeWidget> with Trans {
|
|||||||
double mediaWidth = MediaQuery.of(context).size.width * .8;
|
double mediaWidth = MediaQuery.of(context).size.width * .8;
|
||||||
double mediaHeight = MediaQuery.of(context).size.height * .8;
|
double mediaHeight = MediaQuery.of(context).size.height * .8;
|
||||||
//print("w " + mediaWidth.toString() + "h " + mediaHeight.toString());
|
//print("w " + mediaWidth.toString() + "h " + mediaHeight.toString());
|
||||||
widget.exerciseBloc.setMediaDimensions(mediaWidth, mediaHeight);
|
widget.exerciseBloc.customerRepository.setMediaDimensions(mediaWidth, mediaHeight);
|
||||||
List<Widget> list = List();
|
List<Widget> list = List();
|
||||||
list.add(GestureDetector(
|
list.add(GestureDetector(
|
||||||
onTap: () => {print("Save"), widget.exerciseBloc.add(ExerciseNewSaveWeight())},
|
onTap: () => {print("Save"), widget.exerciseBloc.add(ExerciseNewSaveWeight())},
|
||||||
@ -63,7 +63,7 @@ class _SizeState extends State<SizeWidget> with Trans {
|
|||||||
)));
|
)));
|
||||||
|
|
||||||
list.add(
|
list.add(
|
||||||
widget.exerciseBloc.isMan
|
widget.exerciseBloc.customerRepository.isMan
|
||||||
? Image.asset(
|
? Image.asset(
|
||||||
"asset/image/man_sizes.png",
|
"asset/image/man_sizes.png",
|
||||||
height: mediaHeight,
|
height: mediaHeight,
|
||||||
@ -76,10 +76,13 @@ class _SizeState extends State<SizeWidget> with Trans {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
list.add(Positioned(
|
list.add(Positioned(
|
||||||
top: widget.exerciseBloc.getWeightCoordinate(widget.exerciseBloc.isMan, isTop: true).toDouble(),
|
top: widget.exerciseBloc.customerRepository.getWeightCoordinate(widget.exerciseBloc.customerRepository.isMan, isTop: true).toDouble(),
|
||||||
left: widget.exerciseBloc.getWeightCoordinate(widget.exerciseBloc.isMan, isTop: false, isLeft: true).toDouble() - 45,
|
left: widget.exerciseBloc.customerRepository
|
||||||
|
.getWeightCoordinate(widget.exerciseBloc.customerRepository.isMan, isTop: false, isLeft: true)
|
||||||
|
.toDouble() -
|
||||||
|
45,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () => onPressed(widget.exerciseBloc.getPropertyByName("Weight")),
|
onTap: () => onPressed(widget.exerciseBloc.customerRepository.getPropertyByName("Weight")),
|
||||||
child: Image.asset(
|
child: Image.asset(
|
||||||
"asset/image/merleg.png",
|
"asset/image/merleg.png",
|
||||||
height: 120,
|
height: 120,
|
||||||
@ -92,7 +95,7 @@ class _SizeState extends State<SizeWidget> with Trans {
|
|||||||
list.add(
|
list.add(
|
||||||
Positioned(
|
Positioned(
|
||||||
top: mediaHeight * .07,
|
top: mediaHeight * .07,
|
||||||
left: widget.exerciseBloc.isMan ? mediaWidth * .62 : mediaWidth * .65,
|
left: widget.exerciseBloc.customerRepository.isMan ? mediaWidth * .62 : mediaWidth * .65,
|
||||||
child: Stack(
|
child: Stack(
|
||||||
alignment: Alignment.topLeft,
|
alignment: Alignment.topLeft,
|
||||||
children: [
|
children: [
|
||||||
@ -129,7 +132,7 @@ class _SizeState extends State<SizeWidget> with Trans {
|
|||||||
List<Widget> getSizeElements() {
|
List<Widget> getSizeElements() {
|
||||||
List<Widget> list = List();
|
List<Widget> list = List();
|
||||||
|
|
||||||
widget.exerciseBloc.manSizes.forEach((element) {
|
widget.exerciseBloc.customerRepository.manSizes.forEach((element) {
|
||||||
list.add(
|
list.add(
|
||||||
Positioned(
|
Positioned(
|
||||||
top: element.top.toDouble(),
|
top: element.top.toDouble(),
|
||||||
@ -139,7 +142,7 @@ class _SizeState extends State<SizeWidget> with Trans {
|
|||||||
width: 20,
|
width: 20,
|
||||||
height: 20,
|
height: 20,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: widget.exerciseBloc.isMan ? Colors.green[800] : Color(0xFFEA776C),
|
color: widget.exerciseBloc.customerRepository.isMan ? Colors.green[800] : Color(0xFFEA776C),
|
||||||
borderRadius: BorderRadius.all(
|
borderRadius: BorderRadius.all(
|
||||||
Radius.circular(20),
|
Radius.circular(20),
|
||||||
),
|
),
|
||||||
@ -156,7 +159,7 @@ class _SizeState extends State<SizeWidget> with Trans {
|
|||||||
height: 20,
|
height: 20,
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: widget.exerciseBloc.isMan ? Color(0xFF369fb9) : Color(0xFFEA776C),
|
color: widget.exerciseBloc.customerRepository.isMan ? Color(0xFF369fb9) : Color(0xFFEA776C),
|
||||||
borderRadius: BorderRadius.all(
|
borderRadius: BorderRadius.all(
|
||||||
Radius.circular(20),
|
Radius.circular(20),
|
||||||
),
|
),
|
||||||
|
34
lib/widgets/timer_widget.dart
Normal file
@ -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>[
|
||||||
|
OverlayEntry(
|
||||||
|
opaque: true,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return Container(color: Colors.transparent, child: Clock(bloc: bloc));
|
||||||
|
})
|
||||||
|
])));
|
||||||
|
}
|
||||||
|
}
|
13
pubspec.lock
@ -50,6 +50,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.5.0-nullsafety.1"
|
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:
|
badges:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -259,7 +266,7 @@ packages:
|
|||||||
name: dropdown_search
|
name: dropdown_search
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.8"
|
version: "0.4.9"
|
||||||
equatable:
|
equatable:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -397,7 +404,7 @@ packages:
|
|||||||
name: flutter_bloc
|
name: flutter_bloc
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.1.1"
|
version: "6.1.2"
|
||||||
flutter_facebook_auth:
|
flutter_facebook_auth:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -1005,7 +1012,7 @@ packages:
|
|||||||
name: sqflite
|
name: sqflite
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.2+2"
|
version: "1.3.2+3"
|
||||||
sqflite_common:
|
sqflite_common:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
22
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.
|
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||||
# Read more about iOS versioning at
|
# Read more about iOS versioning at
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
version: 1.1.6+55
|
version: 1.1.7+56
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.7.0 <3.0.0"
|
sdk: ">=2.7.0 <3.0.0"
|
||||||
@ -28,7 +28,7 @@ dependencies:
|
|||||||
google_fonts: ^1.1.1
|
google_fonts: ^1.1.1
|
||||||
devicelocale: ^0.3.3
|
devicelocale: ^0.3.3
|
||||||
sentry: ^4.0.3
|
sentry: ^4.0.3
|
||||||
flutter_bloc: ^6.1.1
|
flutter_bloc: ^6.1.2
|
||||||
equatable: ^1.2.5
|
equatable: ^1.2.5
|
||||||
#freezed: ^0.12.2
|
#freezed: ^0.12.2
|
||||||
flutter_form_bloc: ^0.19.0
|
flutter_form_bloc: ^0.19.0
|
||||||
@ -40,7 +40,6 @@ dependencies:
|
|||||||
infinite_listview: ^1.0.1+1
|
infinite_listview: ^1.0.1+1
|
||||||
toggle_switch: ^0.1.8
|
toggle_switch: ^0.1.8
|
||||||
keyboard_actions: ^3.3.1+1
|
keyboard_actions: ^3.3.1+1
|
||||||
dropdown_search: ^0.4.8
|
|
||||||
badges: ^1.1.4
|
badges: ^1.1.4
|
||||||
#health: ^3.0.0
|
#health: ^3.0.0
|
||||||
stop_watch_timer: ^0.6.0+1
|
stop_watch_timer: ^0.6.0+1
|
||||||
@ -53,6 +52,8 @@ dependencies:
|
|||||||
network_image_to_byte: ^0.0.1
|
network_image_to_byte: ^0.0.1
|
||||||
package_info: ^0.4.3+4
|
package_info: ^0.4.3+4
|
||||||
liquid_progress_indicator: ^0.3.2
|
liquid_progress_indicator: ^0.3.2
|
||||||
|
dropdown_search: ^0.4.9
|
||||||
|
audioplayer: ^0.8.1
|
||||||
|
|
||||||
|
|
||||||
firebase_core: ^0.5.0
|
firebase_core: ^0.5.0
|
||||||
@ -71,7 +72,7 @@ dependencies:
|
|||||||
animated_widgets: ^1.0.6
|
animated_widgets: ^1.0.6
|
||||||
|
|
||||||
mockito: ^4.1.3
|
mockito: ^4.1.3
|
||||||
sqflite: ^1.3.2+2
|
sqflite: ^1.3.2+3
|
||||||
flutter_secure_storage: ^3.3.5
|
flutter_secure_storage: ^3.3.5
|
||||||
|
|
||||||
flutter_localizations:
|
flutter_localizations:
|
||||||
@ -212,6 +213,7 @@ flutter:
|
|||||||
- asset/menu/1.2.anaerob.jpg
|
- asset/menu/1.2.anaerob.jpg
|
||||||
- asset/menu/2.strength.jpg
|
- asset/menu/2.strength.jpg
|
||||||
- asset/menu/2.1.endurance.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.6.core.jpg
|
||||||
- asset/menu/2.1.1.1RM.jpg
|
- asset/menu/2.1.1.1RM.jpg
|
||||||
- asset/menu/2.2.1.1.chest.jpg
|
- asset/menu/2.2.1.1.chest.jpg
|
||||||
@ -234,6 +236,7 @@ flutter:
|
|||||||
- asset/menu/bent_arm_barbell_pullovers.jpg
|
- asset/menu/bent_arm_barbell_pullovers.jpg
|
||||||
- asset/menu/bent_knee_situps.jpg
|
- asset/menu/bent_knee_situps.jpg
|
||||||
- asset/menu/bent_over_lateral_raises_with_dumbbells.jpg
|
- asset/menu/bent_over_lateral_raises_with_dumbbells.jpg
|
||||||
|
- asset/menu/bent_over_rows.jpg
|
||||||
- asset/menu/biceps_machine.jpg
|
- asset/menu/biceps_machine.jpg
|
||||||
- asset/menu/bmi.jpg
|
- asset/menu/bmi.jpg
|
||||||
- asset/menu/bmr.jpg
|
- asset/menu/bmr.jpg
|
||||||
@ -244,14 +247,18 @@ flutter:
|
|||||||
- asset/menu/chest_press_machine.jpg
|
- asset/menu/chest_press_machine.jpg
|
||||||
- asset/menu/chest_press.jpg
|
- asset/menu/chest_press.jpg
|
||||||
- asset/menu/chins.jpg
|
- asset/menu/chins.jpg
|
||||||
|
- asset/menu/close_grip_bench_press.jpg
|
||||||
- asset/menu/close_grip_front_lat_pulldown.jpg
|
- asset/menu/close_grip_front_lat_pulldown.jpg
|
||||||
- asset/menu/close_grip_pull_ups.jpg
|
- asset/menu/close_grip_pull_ups.jpg
|
||||||
|
- asset/menu/close_reverse_grip_lat_pulldown.jpg
|
||||||
- asset/menu/concentration.jpg
|
- asset/menu/concentration.jpg
|
||||||
- asset/menu/cooper.jpg
|
- asset/menu/cooper.jpg
|
||||||
- asset/menu/crisscross.jpg
|
- asset/menu/crisscross.jpg
|
||||||
- asset/menu/cross_bench_dumbbell_pullover.jpg
|
- asset/menu/cross_bench_dumbbell_pullover.jpg
|
||||||
- asset/menu/deadlift.jpg
|
- asset/menu/deadlift.jpg
|
||||||
|
- asset/menu/decline_bench_press.jpg
|
||||||
- asset/menu/decline_dumbbell_bench_press.jpg
|
- asset/menu/decline_dumbbell_bench_press.jpg
|
||||||
|
- asset/menu/decline_flyes.jpg
|
||||||
- asset/menu/decline_cable_flyes.jpg
|
- asset/menu/decline_cable_flyes.jpg
|
||||||
- asset/menu/donkey_calf_raises.jpg
|
- asset/menu/donkey_calf_raises.jpg
|
||||||
- asset/menu/dumbbell_alternate_bicep_curl.jpg
|
- asset/menu/dumbbell_alternate_bicep_curl.jpg
|
||||||
@ -266,6 +273,7 @@ flutter:
|
|||||||
- asset/menu/hanging_leg_raises.jpg
|
- asset/menu/hanging_leg_raises.jpg
|
||||||
- asset/menu/head-on-bench_dumbbell_rear_delt_raise.jpg
|
- asset/menu/head-on-bench_dumbbell_rear_delt_raise.jpg
|
||||||
- asset/menu/hyperextension.jpg
|
- asset/menu/hyperextension.jpg
|
||||||
|
- asset/menu/hyperextension_floor.jpg
|
||||||
- asset/menu/incline_cable_flyes.jpg
|
- asset/menu/incline_cable_flyes.jpg
|
||||||
- asset/menu/incline_curl_with_dumbbels.jpg
|
- asset/menu/incline_curl_with_dumbbels.jpg
|
||||||
- asset/menu/incline_dumbbell_press.jpg
|
- asset/menu/incline_dumbbell_press.jpg
|
||||||
@ -292,10 +300,13 @@ flutter:
|
|||||||
- asset/menu/peck_deck_flyes.jpg
|
- asset/menu/peck_deck_flyes.jpg
|
||||||
- asset/menu/plank.jpg
|
- asset/menu/plank.jpg
|
||||||
- asset/menu/pull_up.jpg
|
- asset/menu/pull_up.jpg
|
||||||
|
- asset/menu/pulldown_machine.jpg
|
||||||
- asset/menu/pullups.jpg
|
- asset/menu/pullups.jpg
|
||||||
- asset/menu/pushups.jpg
|
- asset/menu/pushups.jpg
|
||||||
|
- asset/menu/pushups_dip.jpg
|
||||||
- asset/menu/reverse_crunches.jpg
|
- asset/menu/reverse_crunches.jpg
|
||||||
- asset/menu/roman_chair_situps.jpg
|
- asset/menu/roman_chair_situps.jpg
|
||||||
|
- asset/menu/row_machine.jpg
|
||||||
- asset/menu/russian_twist.jpg
|
- asset/menu/russian_twist.jpg
|
||||||
- asset/menu/seated_bar_twist.jpg
|
- asset/menu/seated_bar_twist.jpg
|
||||||
- asset/menu/seated_dumbbell_curl.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_bent_over_cable_reverse_fly.jpg
|
||||||
- asset/menu/single_arm_t-bar_rows.jpg
|
- asset/menu/single_arm_t-bar_rows.jpg
|
||||||
- asset/menu/single_hand_lateral_raises.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_knee_ups.jpg
|
||||||
- asset/menu/sitting_machine_calf_raises.jpg
|
- asset/menu/sitting_machine_calf_raises.jpg
|
||||||
- asset/menu/situps.jpg
|
- asset/menu/situps.jpg
|
||||||
@ -340,6 +351,7 @@ flutter:
|
|||||||
- asset/menu/weighted_bench_dip.jpg
|
- asset/menu/weighted_bench_dip.jpg
|
||||||
- asset/menu/wide_grip_behind_the_neck_pull_ups.jpg
|
- asset/menu/wide_grip_behind_the_neck_pull_ups.jpg
|
||||||
- asset/menu/wide_grip_front_lat_pulldown.jpg
|
- asset/menu/wide_grip_front_lat_pulldown.jpg
|
||||||
|
- asset/wine-glass.mp3
|
||||||
|
|
||||||
|
|
||||||
- i18n/en.json
|
- i18n/en.json
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
//import 'package:aitrainer_app/bloc/login_form_bloc.dart';
|
//import 'package:aitrainer_app/bloc/login_form_bloc.dart';
|
||||||
import 'package:aitrainer_app/helper/database.dart';
|
import 'package:aitrainer_app/helper/database.dart';
|
||||||
import 'package:aitrainer_app/library_keys.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/model/user.dart';
|
||||||
import 'package:aitrainer_app/repository/user_repository.dart';
|
import 'package:aitrainer_app/repository/user_repository.dart';
|
||||||
import 'package:aitrainer_app/util/common.dart';
|
import 'package:aitrainer_app/util/common.dart';
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
import 'package:aitrainer_app/bloc/login/login_bloc.dart';
|
import 'package:aitrainer_app/bloc/login/login_bloc.dart';
|
||||||
import 'package:aitrainer_app/helper/database.dart';
|
import 'package:aitrainer_app/helper/database.dart';
|
||||||
import 'package:aitrainer_app/library_keys.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/model/user.dart';
|
||||||
import 'package:aitrainer_app/repository/user_repository.dart';
|
import 'package:aitrainer_app/repository/user_repository.dart';
|
||||||
import 'package:aitrainer_app/util/common.dart';
|
import 'package:aitrainer_app/util/common.dart';
|
||||||
|