WT 1.1.20 Training Plan improvements, InApp Messageing
This commit is contained in:
parent
a595ffb358
commit
211307e63e
BIN
asset/menu/FG_2_edz.jpg
Normal file
BIN
asset/menu/FG_2_edz.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 68 KiB |
BIN
asset/menu/stretching.jpg
Normal file
BIN
asset/menu/stretching.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 93 KiB |
BIN
asset/menu/warmup.jpg
Normal file
BIN
asset/menu/warmup.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 124 KiB |
@ -436,7 +436,7 @@
|
|||||||
"Do you want to restart, or select a new Training Plan?": "Do you want to restart, or select a new Training Plan?",
|
"Do you want to restart, or select a new Training Plan?": "Do you want to restart, or select a new Training Plan?",
|
||||||
"New Training Plan": "New Training Plan",
|
"New Training Plan": "New Training Plan",
|
||||||
"Restart": "Restart",
|
"Restart": "Restart",
|
||||||
"Training Day": "Training Day",
|
"Training Day": "Day",
|
||||||
"No Active Training Plan": "No Active Training Plan",
|
"No Active Training Plan": "No Active Training Plan",
|
||||||
"Please select one in the Training menu, or create your custom plan": "Please select one in the Training menu, or create your custom plan",
|
"Please select one in the Training menu, or create your custom plan": "Please select one in the Training menu, or create your custom plan",
|
||||||
"Continue your training": "Continue your training",
|
"Continue your training": "Continue your training",
|
||||||
@ -473,5 +473,8 @@
|
|||||||
"A new version of Workout Test is available!": "A new version of Workout Test is available!",
|
"A new version of Workout Test is available!": "A new version of Workout Test is available!",
|
||||||
"Update Now": "Update Now",
|
"Update Now": "Update Now",
|
||||||
"Update App?": "Update App?",
|
"Update App?": "Update App?",
|
||||||
"Want to update?": "Please update the app"
|
"Want to update?": "Please update the app",
|
||||||
|
"Attention!": "Attention!",
|
||||||
|
"The safe and exact execution of this exercise you need a training buddy or a trainer": "The safe and exact execution of this exercise you need a training buddy or a trainer",
|
||||||
|
"Execution at your own risk!": "Execution at your own risk!"
|
||||||
}
|
}
|
@ -434,7 +434,7 @@
|
|||||||
"Do you want to restart, or select a new Training Plan?": "Újra akarod indítani, vagy inkább egy másikat választasz?",
|
"Do you want to restart, or select a new Training Plan?": "Újra akarod indítani, vagy inkább egy másikat választasz?",
|
||||||
"New Training Plan": "Másik edzésterv",
|
"New Training Plan": "Másik edzésterv",
|
||||||
"Restart": "Újraindítom",
|
"Restart": "Újraindítom",
|
||||||
"Training Day": "Edzésnap",
|
"Training Day": "Nap",
|
||||||
"No Active Training Plan": "Nincs aktív edzésterv",
|
"No Active Training Plan": "Nincs aktív edzésterv",
|
||||||
"Please select one in the Training menu, or create your custom plan": "Kérlek válassz egyet a Tréning menüben, vagy hozd létre a saját egyéni edzésedet",
|
"Please select one in the Training menu, or create your custom plan": "Kérlek válassz egyet a Tréning menüben, vagy hozd létre a saját egyéni edzésedet",
|
||||||
"Continue your training": "Folytasd az edzést",
|
"Continue your training": "Folytasd az edzést",
|
||||||
@ -471,5 +471,8 @@
|
|||||||
"A new version of Workout Test is available!": "Egy új Workout Test verzió elérhető!",
|
"A new version of Workout Test is available!": "Egy új Workout Test verzió elérhető!",
|
||||||
"Update Now": "Töltsd le most",
|
"Update Now": "Töltsd le most",
|
||||||
"Update App?": "App frissítés",
|
"Update App?": "App frissítés",
|
||||||
"Want to update?": "Kérlek töltsd le"
|
"Want to update?": "Kérlek töltsd le",
|
||||||
|
"Attention!": "Figyelem!",
|
||||||
|
"The safe and exact execution of this exercise you need a training buddy or a trainer": "A gyakorlat biztonságos és maximális pontosságú végrehajtásához edzőtárs vagy edző segítsége szükséges",
|
||||||
|
"Execution at your own risk!": "Végrehajtás CSAK saját felelőségre!"
|
||||||
}
|
}
|
@ -4,7 +4,7 @@ PODS:
|
|||||||
- AppAuth/ExternalUserAgent (= 1.4.0)
|
- AppAuth/ExternalUserAgent (= 1.4.0)
|
||||||
- AppAuth/Core (1.4.0)
|
- AppAuth/Core (1.4.0)
|
||||||
- AppAuth/ExternalUserAgent (1.4.0)
|
- AppAuth/ExternalUserAgent (1.4.0)
|
||||||
- apple_sign_in (0.0.1):
|
- awesome_notifications (0.0.2):
|
||||||
- Flutter
|
- Flutter
|
||||||
- device_info (0.0.1):
|
- device_info (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
@ -116,10 +116,10 @@ PODS:
|
|||||||
- FirebaseInstallations (~> 8.0)
|
- FirebaseInstallations (~> 8.0)
|
||||||
- GoogleUtilities/Environment (~> 7.4)
|
- GoogleUtilities/Environment (~> 7.4)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 7.4)"
|
- "GoogleUtilities/NSData+zlib (~> 7.4)"
|
||||||
- flurry (0.0.4):
|
- Flurry-iOS-SDK/FlurrySDK (11.2.1)
|
||||||
|
- flurry_data (0.0.1):
|
||||||
- Flurry-iOS-SDK/FlurrySDK
|
- Flurry-iOS-SDK/FlurrySDK
|
||||||
- Flutter
|
- Flutter
|
||||||
- Flurry-iOS-SDK/FlurrySDK (11.2.1)
|
|
||||||
- Flutter (1.0.0)
|
- Flutter (1.0.0)
|
||||||
- flutter_app_badger (0.0.1):
|
- flutter_app_badger (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
@ -127,8 +127,6 @@ PODS:
|
|||||||
- FBSDKCoreKit (~> 9.1.0)
|
- FBSDKCoreKit (~> 9.1.0)
|
||||||
- FBSDKLoginKit (~> 9.1.0)
|
- FBSDKLoginKit (~> 9.1.0)
|
||||||
- Flutter
|
- Flutter
|
||||||
- flutter_local_notifications (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- flutter_secure_storage (3.3.1):
|
- flutter_secure_storage (3.3.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- flutter_uxcam (2.0.0-beta.1):
|
- flutter_uxcam (2.0.0-beta.1):
|
||||||
@ -215,6 +213,8 @@ PODS:
|
|||||||
- Sentry (~> 7.0.3)
|
- Sentry (~> 7.0.3)
|
||||||
- shared_preferences (0.0.1):
|
- shared_preferences (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- sign_in_with_apple (0.0.1):
|
||||||
|
- Flutter
|
||||||
- sqflite (0.0.2):
|
- sqflite (0.0.2):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FMDB (>= 2.7.5)
|
- FMDB (>= 2.7.5)
|
||||||
@ -229,7 +229,7 @@ PODS:
|
|||||||
- Flutter
|
- Flutter
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- apple_sign_in (from `.symlinks/plugins/apple_sign_in/ios`)
|
- awesome_notifications (from `.symlinks/plugins/awesome_notifications/ios`)
|
||||||
- device_info (from `.symlinks/plugins/device_info/ios`)
|
- device_info (from `.symlinks/plugins/device_info/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`)
|
||||||
@ -237,11 +237,10 @@ DEPENDENCIES:
|
|||||||
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
||||||
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
||||||
- firebase_remote_config (from `.symlinks/plugins/firebase_remote_config/ios`)
|
- firebase_remote_config (from `.symlinks/plugins/firebase_remote_config/ios`)
|
||||||
- flurry (from `.symlinks/plugins/flurry/ios`)
|
- flurry_data (from `.symlinks/plugins/flurry_data/ios`)
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
- flutter_app_badger (from `.symlinks/plugins/flutter_app_badger/ios`)
|
- flutter_app_badger (from `.symlinks/plugins/flutter_app_badger/ios`)
|
||||||
- flutter_facebook_auth (from `.symlinks/plugins/flutter_facebook_auth/ios`)
|
- flutter_facebook_auth (from `.symlinks/plugins/flutter_facebook_auth/ios`)
|
||||||
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
|
||||||
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
||||||
- flutter_uxcam (from `.symlinks/plugins/flutter_uxcam/ios`)
|
- flutter_uxcam (from `.symlinks/plugins/flutter_uxcam/ios`)
|
||||||
- google_sign_in (from `.symlinks/plugins/google_sign_in/ios`)
|
- google_sign_in (from `.symlinks/plugins/google_sign_in/ios`)
|
||||||
@ -252,6 +251,7 @@ DEPENDENCIES:
|
|||||||
- purchases_flutter (from `.symlinks/plugins/purchases_flutter/ios`)
|
- purchases_flutter (from `.symlinks/plugins/purchases_flutter/ios`)
|
||||||
- sentry_flutter (from `.symlinks/plugins/sentry_flutter/ios`)
|
- sentry_flutter (from `.symlinks/plugins/sentry_flutter/ios`)
|
||||||
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
|
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
|
||||||
|
- sign_in_with_apple (from `.symlinks/plugins/sign_in_with_apple/ios`)
|
||||||
- sqflite (from `.symlinks/plugins/sqflite/ios`)
|
- sqflite (from `.symlinks/plugins/sqflite/ios`)
|
||||||
- url_launcher (from `.symlinks/plugins/url_launcher/ios`)
|
- url_launcher (from `.symlinks/plugins/url_launcher/ios`)
|
||||||
- video_player (from `.symlinks/plugins/video_player/ios`)
|
- video_player (from `.symlinks/plugins/video_player/ios`)
|
||||||
@ -289,8 +289,8 @@ SPEC REPOS:
|
|||||||
- UXCam
|
- UXCam
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
apple_sign_in:
|
awesome_notifications:
|
||||||
:path: ".symlinks/plugins/apple_sign_in/ios"
|
:path: ".symlinks/plugins/awesome_notifications/ios"
|
||||||
device_info:
|
device_info:
|
||||||
:path: ".symlinks/plugins/device_info/ios"
|
:path: ".symlinks/plugins/device_info/ios"
|
||||||
devicelocale:
|
devicelocale:
|
||||||
@ -305,16 +305,14 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/firebase_messaging/ios"
|
:path: ".symlinks/plugins/firebase_messaging/ios"
|
||||||
firebase_remote_config:
|
firebase_remote_config:
|
||||||
:path: ".symlinks/plugins/firebase_remote_config/ios"
|
:path: ".symlinks/plugins/firebase_remote_config/ios"
|
||||||
flurry:
|
flurry_data:
|
||||||
:path: ".symlinks/plugins/flurry/ios"
|
:path: ".symlinks/plugins/flurry_data/ios"
|
||||||
Flutter:
|
Flutter:
|
||||||
:path: Flutter
|
:path: Flutter
|
||||||
flutter_app_badger:
|
flutter_app_badger:
|
||||||
:path: ".symlinks/plugins/flutter_app_badger/ios"
|
:path: ".symlinks/plugins/flutter_app_badger/ios"
|
||||||
flutter_facebook_auth:
|
flutter_facebook_auth:
|
||||||
:path: ".symlinks/plugins/flutter_facebook_auth/ios"
|
:path: ".symlinks/plugins/flutter_facebook_auth/ios"
|
||||||
flutter_local_notifications:
|
|
||||||
:path: ".symlinks/plugins/flutter_local_notifications/ios"
|
|
||||||
flutter_secure_storage:
|
flutter_secure_storage:
|
||||||
:path: ".symlinks/plugins/flutter_secure_storage/ios"
|
:path: ".symlinks/plugins/flutter_secure_storage/ios"
|
||||||
flutter_uxcam:
|
flutter_uxcam:
|
||||||
@ -335,6 +333,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/sentry_flutter/ios"
|
:path: ".symlinks/plugins/sentry_flutter/ios"
|
||||||
shared_preferences:
|
shared_preferences:
|
||||||
:path: ".symlinks/plugins/shared_preferences/ios"
|
:path: ".symlinks/plugins/shared_preferences/ios"
|
||||||
|
sign_in_with_apple:
|
||||||
|
:path: ".symlinks/plugins/sign_in_with_apple/ios"
|
||||||
sqflite:
|
sqflite:
|
||||||
:path: ".symlinks/plugins/sqflite/ios"
|
:path: ".symlinks/plugins/sqflite/ios"
|
||||||
url_launcher:
|
url_launcher:
|
||||||
@ -348,7 +348,7 @@ EXTERNAL SOURCES:
|
|||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
AppAuth: 31bcec809a638d7bd2f86ea8a52bd45f6e81e7c7
|
AppAuth: 31bcec809a638d7bd2f86ea8a52bd45f6e81e7c7
|
||||||
apple_sign_in: 7716c7ddfa195aeab7dec0dc374ef4ff45d1adb4
|
awesome_notifications: 74462bc8e68b11f8235d78422266886759e9da61
|
||||||
device_info: d7d233b645a32c40dfdc212de5cf646ca482f175
|
device_info: d7d233b645a32c40dfdc212de5cf646ca482f175
|
||||||
devicelocale: b22617f40038496deffba44747101255cee005b0
|
devicelocale: b22617f40038496deffba44747101255cee005b0
|
||||||
FBSDKCoreKit: a00fe2efd780c195a5e09201bf51c56106245b40
|
FBSDKCoreKit: a00fe2efd780c195a5e09201bf51c56106245b40
|
||||||
@ -367,12 +367,11 @@ SPEC CHECKSUMS:
|
|||||||
FirebaseInstallations: c4aab1005d6547b00a7529777fe52f5d4d45165b
|
FirebaseInstallations: c4aab1005d6547b00a7529777fe52f5d4d45165b
|
||||||
FirebaseMessaging: 1a33b4af3c8042ed6ddacb6c031894af2064bfab
|
FirebaseMessaging: 1a33b4af3c8042ed6ddacb6c031894af2064bfab
|
||||||
FirebaseRemoteConfig: 055f6b5ba1751547596ded5032c4d5c6054ca501
|
FirebaseRemoteConfig: 055f6b5ba1751547596ded5032c4d5c6054ca501
|
||||||
flurry: 15b01f664ab1367c62b50291541ea7f78ca85aad
|
|
||||||
Flurry-iOS-SDK: 5831da8fc6bedb31fa1f94aac6fd204d36dd351d
|
Flurry-iOS-SDK: 5831da8fc6bedb31fa1f94aac6fd204d36dd351d
|
||||||
|
flurry_data: 49b7066a283aa41f4306974c1f2d74c61231ad74
|
||||||
Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
|
Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
|
||||||
flutter_app_badger: 65de4d6f0c34a891df49e6cfb8a1c0496426fa68
|
flutter_app_badger: 65de4d6f0c34a891df49e6cfb8a1c0496426fa68
|
||||||
flutter_facebook_auth: 4b170c07b7fce791497093fcc3f134fb215f3f07
|
flutter_facebook_auth: 4b170c07b7fce791497093fcc3f134fb215f3f07
|
||||||
flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743
|
|
||||||
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
|
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
|
||||||
flutter_uxcam: ab8e5d3954eb448febd581375e2622e9eecb1066
|
flutter_uxcam: ab8e5d3954eb448febd581375e2622e9eecb1066
|
||||||
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
||||||
@ -396,6 +395,7 @@ SPEC CHECKSUMS:
|
|||||||
Sentry: 5b16f877da362d23716d827e04db642455b26b40
|
Sentry: 5b16f877da362d23716d827e04db642455b26b40
|
||||||
sentry_flutter: 602dc1902e152269256115e2386e1029511f3440
|
sentry_flutter: 602dc1902e152269256115e2386e1029511f3440
|
||||||
shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
|
shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
|
||||||
|
sign_in_with_apple: 34f3f5456a45fd7ac5fb42905e2ad31dae061b4a
|
||||||
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
|
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
|
||||||
url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
|
url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
|
||||||
UXCam: c2c00873595ab89be227f197213dc3679ff88ae5
|
UXCam: c2c00873595ab89be227f197213dc3679ff88ae5
|
||||||
|
@ -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 = 11;
|
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.18;
|
MARKETING_VERSION = 1.1.20;
|
||||||
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 = 11;
|
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.18;
|
MARKETING_VERSION = 1.1.20;
|
||||||
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 = 11;
|
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.18;
|
MARKETING_VERSION = 1.1.20;
|
||||||
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";
|
||||||
|
@ -87,9 +87,9 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
|
|||||||
yield LoginSuccess();
|
yield LoginSuccess();
|
||||||
} else if (event is RegistrationSubmit) {
|
} else if (event is RegistrationSubmit) {
|
||||||
yield LoginLoading();
|
yield LoginLoading();
|
||||||
if (!this.dataPolicyAllowed) {
|
/* if (!this.dataPolicyAllowed) {
|
||||||
throw Exception("Please accept our data policy");
|
throw Exception("Please accept our data policy");
|
||||||
}
|
} */
|
||||||
final String? validationError = validate();
|
final String? validationError = validate();
|
||||||
if (validationError != null) {
|
if (validationError != null) {
|
||||||
yield LoginError(message: validationError);
|
yield LoginError(message: validationError);
|
||||||
@ -104,9 +104,9 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
|
|||||||
}
|
}
|
||||||
} else if (event is RegistrationFB) {
|
} else if (event is RegistrationFB) {
|
||||||
yield LoginLoading();
|
yield LoginLoading();
|
||||||
if (!this.dataPolicyAllowed) {
|
/* if (!this.dataPolicyAllowed) {
|
||||||
throw Exception("Please accept our data policy");
|
throw Exception("Please accept our data policy");
|
||||||
}
|
} */
|
||||||
Cache().setLoginType(LoginType.fb);
|
Cache().setLoginType(LoginType.fb);
|
||||||
await userRepository.addUserFB();
|
await userRepository.addUserFB();
|
||||||
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
||||||
@ -116,9 +116,9 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
|
|||||||
yield LoginSuccess();
|
yield LoginSuccess();
|
||||||
} else if (event is RegistrationGoogle) {
|
} else if (event is RegistrationGoogle) {
|
||||||
yield LoginLoading();
|
yield LoginLoading();
|
||||||
if (!this.dataPolicyAllowed) {
|
/* if (!this.dataPolicyAllowed) {
|
||||||
throw Exception("Please accept our data policy");
|
throw Exception("Please accept our data policy");
|
||||||
}
|
} */
|
||||||
Cache().setLoginType(LoginType.google);
|
Cache().setLoginType(LoginType.google);
|
||||||
await userRepository.addUserGoogle();
|
await userRepository.addUserGoogle();
|
||||||
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
||||||
@ -128,9 +128,9 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
|
|||||||
yield LoginSuccess();
|
yield LoginSuccess();
|
||||||
} else if (event is RegistrationApple) {
|
} else if (event is RegistrationApple) {
|
||||||
yield LoginLoading();
|
yield LoginLoading();
|
||||||
if (!this.dataPolicyAllowed) {
|
/* if (!this.dataPolicyAllowed) {
|
||||||
throw Exception("Please accept our data policy");
|
throw Exception("Please accept our data policy");
|
||||||
}
|
} */
|
||||||
Cache().setLoginType(LoginType.apple);
|
Cache().setLoginType(LoginType.apple);
|
||||||
await userRepository.addUserApple();
|
await userRepository.addUserApple();
|
||||||
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
||||||
|
@ -58,15 +58,16 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
|||||||
await Cache().saveMyTrainingPlan();
|
await Cache().saveMyTrainingPlan();
|
||||||
yield TrainingPlanFinished();
|
yield TrainingPlanFinished();
|
||||||
} else if (event is TrainingPlanWeightChange) {
|
} else if (event is TrainingPlanWeightChange) {
|
||||||
yield TrainingPlanLoading();
|
yield TrainingPlanExerciseLoading();
|
||||||
event.detail.weight = event.weight;
|
event.detail.weight = event.weight;
|
||||||
|
|
||||||
|
yield TrainingPlanExerciseReady();
|
||||||
yield TrainingPlanReady();
|
yield TrainingPlanReady();
|
||||||
} else if (event is TrainingPlanRepeatsChange) {
|
} else if (event is TrainingPlanRepeatsChange) {
|
||||||
yield TrainingPlanLoading();
|
yield TrainingPlanExerciseLoading();
|
||||||
|
|
||||||
event.detail.repeats = event.repeats;
|
event.detail.repeats = event.repeats;
|
||||||
|
yield TrainingPlanExerciseReady();
|
||||||
yield TrainingPlanReady();
|
yield TrainingPlanReady();
|
||||||
} else if (event is TrainingPlanSetChange) {
|
} else if (event is TrainingPlanSetChange) {
|
||||||
yield TrainingPlanLoading();
|
yield TrainingPlanLoading();
|
||||||
@ -91,10 +92,13 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
|||||||
} else if (event.detail.exercises.length >= 0) {
|
} else if (event.detail.exercises.length >= 0) {
|
||||||
event.detail.state = ExercisePlanDetailState.inProgress;
|
event.detail.state = ExercisePlanDetailState.inProgress;
|
||||||
}
|
}
|
||||||
|
// recalculate the weight to the original planned repeats for the next details
|
||||||
// recalculate the weight to the original planned repeats
|
if (exercise.unitQuantity != null && exercise.unitQuantity! > 0) {
|
||||||
if (event.detail.isTest && event.detail.exercises.length == 1) {
|
for (var nextDetail in _myPlan!.details) {
|
||||||
trainingPlanRepository.recalculateDetail(_myPlan!.trainingPlanId!, event.detail);
|
if (nextDetail.exerciseTypeId == event.detail.exerciseTypeId && nextDetail.weight == -2) {
|
||||||
|
trainingPlanRepository.recalculateDetail(_myPlan!.trainingPlanId!, event.detail, nextDetail);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exercise.trainingPlanDetailsId = _myPlan!.trainingPlanId;
|
exercise.trainingPlanDetailsId = _myPlan!.trainingPlanId;
|
||||||
@ -230,28 +234,61 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
|||||||
dayNames.clear();
|
dayNames.clear();
|
||||||
_myPlan!.days.clear();
|
_myPlan!.days.clear();
|
||||||
String dayName = ".";
|
String dayName = ".";
|
||||||
|
String previousDay = ".";
|
||||||
_myPlan!.details.forEach((element) {
|
_myPlan!.details.forEach((element) {
|
||||||
if (element.day != null && element.day != dayName) {
|
if (element.day != null && element.day != dayName) {
|
||||||
dayNames.add(element.day!);
|
dayNames.add(element.day!);
|
||||||
dayName = element.day!;
|
dayName = element.day!;
|
||||||
|
if (previousDay != ".") {
|
||||||
|
this.addExtraExerciseType("Stretching", previousDay);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (_myPlan!.days[dayName] == null) {
|
if (_myPlan!.days[dayName] == null) {
|
||||||
if (dayName == ".") {
|
if (dayName == ".") {
|
||||||
dayName = "";
|
dayName = "";
|
||||||
}
|
}
|
||||||
_myPlan!.days[dayName] = [];
|
_myPlan!.days[dayName] = [];
|
||||||
|
|
||||||
|
this.addExtraExerciseType("Warming Up", dayName);
|
||||||
|
previousDay = dayName;
|
||||||
}
|
}
|
||||||
_myPlan!.days[dayName]!.add(element);
|
_myPlan!.days[dayName]!.add(element);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (dayNames.length == 0) {
|
if (dayNames.length == 0) {
|
||||||
dayNames.add("");
|
dayName = "";
|
||||||
_myPlan!.days[""] = [];
|
dayNames.add(dayName);
|
||||||
_myPlan!.days[""]!.addAll(_myPlan!.details);
|
_myPlan!.days[dayName] = [];
|
||||||
|
_myPlan!.days[dayName]!.addAll(_myPlan!.details);
|
||||||
}
|
}
|
||||||
getActiveDayIndex();
|
getActiveDayIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addExtraExerciseType(String name, String dayName) {
|
||||||
|
if (Cache().getExerciseTypes() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (var exerciseType in Cache().getExerciseTypes()!) {
|
||||||
|
if (exerciseType.name == name) {
|
||||||
|
CustomerTrainingPlanDetails detail = CustomerTrainingPlanDetails();
|
||||||
|
detail.customerTrainingPlanDetailsId = 0;
|
||||||
|
detail.trainingPlanDetailsId = 0;
|
||||||
|
detail.exerciseTypeId = exerciseType.exerciseTypeId;
|
||||||
|
detail.repeats = 1;
|
||||||
|
detail.set = 1;
|
||||||
|
detail.day = "";
|
||||||
|
detail.parallel = false;
|
||||||
|
detail.restingTime = 0;
|
||||||
|
detail.exerciseType = exerciseType;
|
||||||
|
if (_myPlan!.days[dayName] == null) {
|
||||||
|
_myPlan!.days[dayName] = [];
|
||||||
|
}
|
||||||
|
_myPlan!.days[dayName]!.add(detail);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CustomerTrainingPlanDetails? getTrainingPlanDetail(int trainingPlanDetailsId) {
|
CustomerTrainingPlanDetails? getTrainingPlanDetail(int trainingPlanDetailsId) {
|
||||||
CustomerTrainingPlanDetails? detail;
|
CustomerTrainingPlanDetails? detail;
|
||||||
if (_myPlan == null || _myPlan!.details.isEmpty) {
|
if (_myPlan == null || _myPlan!.details.isEmpty) {
|
||||||
@ -297,13 +334,14 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
|||||||
int minStep = 99;
|
int minStep = 99;
|
||||||
for (final detail in this._myPlan!.details) {
|
for (final detail in this._myPlan!.details) {
|
||||||
if (!detail.state.equalsTo(ExercisePlanDetailState.finished)) {
|
if (!detail.state.equalsTo(ExercisePlanDetailState.finished)) {
|
||||||
if (detail.exercises.isEmpty && !detail.state.equalsTo(ExercisePlanDetailState.skipped)) {
|
final day = dayNames[this.activeDayIndex];
|
||||||
|
if (detail.exercises.isEmpty && !detail.state.equalsTo(ExercisePlanDetailState.skipped) && day == detail.day) {
|
||||||
next = detail;
|
next = detail;
|
||||||
minStep = 1;
|
minStep = 1;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
final int step = detail.exercises.length;
|
final int step = detail.exercises.length;
|
||||||
if (step < minStep && !detail.state.equalsTo(ExercisePlanDetailState.skipped)) {
|
if (step < minStep && !detail.state.equalsTo(ExercisePlanDetailState.skipped) && day == detail.day) {
|
||||||
next = detail;
|
next = detail;
|
||||||
minStep = step;
|
minStep = step;
|
||||||
if (detail.parallel != true) {
|
if (detail.parallel != true) {
|
||||||
@ -313,7 +351,7 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
print("Next detail $next");
|
//print("Next detail $next");
|
||||||
|
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
@ -379,20 +417,19 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int getActiveDayIndex() {
|
int getActiveDayIndex() {
|
||||||
|
activeDayIndex = 0;
|
||||||
if (restarting) {
|
if (restarting) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (_myPlan == null || _myPlan!.details.isEmpty) {
|
if (_myPlan == null || _myPlan!.details.isEmpty) {
|
||||||
// throw Exception("No defined Training Plan");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dayNames.isEmpty || dayNames.length == 1) {
|
if (dayNames.isEmpty || dayNames.length == 1) {
|
||||||
|
activeDayIndex = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
activeDayIndex = 0;
|
|
||||||
|
|
||||||
for (var day in dayNames) {
|
for (var day in dayNames) {
|
||||||
if (_myPlan!.days[day] == null) {
|
if (_myPlan!.days[day] == null) {
|
||||||
throw Exception("Wrong activated day: $day does not exist");
|
throw Exception("Wrong activated day: $day does not exist");
|
||||||
@ -413,7 +450,7 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
|||||||
activeDayIndex = 0;
|
activeDayIndex = 0;
|
||||||
this.add(TrainingPlanGoToRestart());
|
this.add(TrainingPlanGoToRestart());
|
||||||
}
|
}
|
||||||
|
print("ActiveDayIndex $activeDayIndex");
|
||||||
return activeDayIndex;
|
return activeDayIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,10 +15,18 @@ class TrainingPlanLoading extends TrainingPlanState {
|
|||||||
const TrainingPlanLoading();
|
const TrainingPlanLoading();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TrainingPlanExerciseLoading extends TrainingPlanState {
|
||||||
|
const TrainingPlanExerciseLoading();
|
||||||
|
}
|
||||||
|
|
||||||
class TrainingPlanReady extends TrainingPlanState {
|
class TrainingPlanReady extends TrainingPlanState {
|
||||||
const TrainingPlanReady();
|
const TrainingPlanReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TrainingPlanExerciseReady extends TrainingPlanState {
|
||||||
|
const TrainingPlanExerciseReady();
|
||||||
|
}
|
||||||
|
|
||||||
class TrainingPlanFinished extends TrainingPlanState {
|
class TrainingPlanFinished extends TrainingPlanState {
|
||||||
const TrainingPlanFinished();
|
const TrainingPlanFinished();
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ import 'dart:io';
|
|||||||
import 'package:aitrainer_app/bloc/test_set_execute/test_set_execute_bloc.dart';
|
import 'package:aitrainer_app/bloc/test_set_execute/test_set_execute_bloc.dart';
|
||||||
import 'package:aitrainer_app/bloc/training_plan/training_plan_bloc.dart';
|
import 'package:aitrainer_app/bloc/training_plan/training_plan_bloc.dart';
|
||||||
import 'package:aitrainer_app/bloc/tutorial/tutorial_bloc.dart';
|
import 'package:aitrainer_app/bloc/tutorial/tutorial_bloc.dart';
|
||||||
import 'package:aitrainer_app/push_notifications.dart';
|
|
||||||
import 'package:aitrainer_app/repository/customer_repository.dart';
|
import 'package:aitrainer_app/repository/customer_repository.dart';
|
||||||
import 'package:aitrainer_app/repository/training_plan_repository.dart';
|
import 'package:aitrainer_app/repository/training_plan_repository.dart';
|
||||||
import 'package:aitrainer_app/repository/workout_tree_repository.dart';
|
import 'package:aitrainer_app/repository/workout_tree_repository.dart';
|
||||||
@ -44,7 +43,7 @@ import 'package:aitrainer_app/widgets/home.dart';
|
|||||||
import 'package:aitrainer_app/library/facebook_app_events/facebook_app_events.dart';
|
import 'package:aitrainer_app/library/facebook_app_events/facebook_app_events.dart';
|
||||||
import 'package:firebase_analytics/firebase_analytics.dart';
|
import 'package:firebase_analytics/firebase_analytics.dart';
|
||||||
import 'package:firebase_analytics/observer.dart';
|
import 'package:firebase_analytics/observer.dart';
|
||||||
import 'package:flurry/flurry.dart';
|
import 'package:flurry_data/flurry_data.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
@ -110,6 +109,7 @@ Future<Null> main() async {
|
|||||||
if (isInDebugMode) {
|
if (isInDebugMode) {
|
||||||
// In development mode simply print to console.
|
// In development mode simply print to console.
|
||||||
FlutterError.dumpErrorToConsole(details);
|
FlutterError.dumpErrorToConsole(details);
|
||||||
|
FlurryData.logEvent("enter_test");
|
||||||
} else {
|
} else {
|
||||||
// In production mode report to the application zone to report to
|
// In production mode report to the application zone to report to
|
||||||
// Sentry.
|
// Sentry.
|
||||||
@ -192,10 +192,9 @@ Future<Null> main() async {
|
|||||||
|
|
||||||
Future<void> initThirdParty() async {
|
Future<void> initThirdParty() async {
|
||||||
if (!isInDebugMode) {
|
if (!isInDebugMode) {
|
||||||
await Flurry.initialize(androidKey: "JNYCTCWBT34FM3J8TV36", iosKey: "3QBG7BSMGPDH24S8TRQP", enableLog: true);
|
await FlurryData.initialize(androidKey: "JNYCTCWBT34FM3J8TV36", iosKey: "3QBG7BSMGPDH24S8TRQP", enableLog: true);
|
||||||
FlutterUxcam.optIntoSchematicRecordings();
|
FlutterUxcam.optIntoSchematicRecordings();
|
||||||
}
|
}
|
||||||
PushNotificationsManager().init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class WorkoutTestApp extends StatelessWidget {
|
class WorkoutTestApp extends StatelessWidget {
|
||||||
|
@ -19,6 +19,7 @@ import 'package:aitrainer_app/model/purchase.dart';
|
|||||||
import 'package:aitrainer_app/model/split_test.dart';
|
import 'package:aitrainer_app/model/split_test.dart';
|
||||||
import 'package:aitrainer_app/model/sport.dart';
|
import 'package:aitrainer_app/model/sport.dart';
|
||||||
import 'package:aitrainer_app/model/training_plan.dart';
|
import 'package:aitrainer_app/model/training_plan.dart';
|
||||||
|
import 'package:aitrainer_app/model/training_plan_day.dart';
|
||||||
import 'package:aitrainer_app/model/tutorial.dart';
|
import 'package:aitrainer_app/model/tutorial.dart';
|
||||||
import 'package:aitrainer_app/model/workout_menu_tree.dart';
|
import 'package:aitrainer_app/model/workout_menu_tree.dart';
|
||||||
import 'package:aitrainer_app/repository/customer_repository.dart';
|
import 'package:aitrainer_app/repository/customer_repository.dart';
|
||||||
@ -30,7 +31,7 @@ import 'package:aitrainer_app/util/enums.dart';
|
|||||||
import 'package:aitrainer_app/util/env.dart';
|
import 'package:aitrainer_app/util/env.dart';
|
||||||
import 'package:aitrainer_app/util/track.dart';
|
import 'package:aitrainer_app/util/track.dart';
|
||||||
import 'package:firebase_remote_config/firebase_remote_config.dart';
|
import 'package:firebase_remote_config/firebase_remote_config.dart';
|
||||||
import 'package:flurry/flurry.dart';
|
import 'package:flurry_data/flurry_data.dart';
|
||||||
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
|
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
|
||||||
import 'package:flutter_uxcam/flutter_uxcam.dart';
|
import 'package:flutter_uxcam/flutter_uxcam.dart';
|
||||||
import 'package:package_info/package_info.dart';
|
import 'package:package_info/package_info.dart';
|
||||||
@ -137,6 +138,7 @@ class Cache with Logging {
|
|||||||
List<wt_product.Product>? _products;
|
List<wt_product.Product>? _products;
|
||||||
List<Purchase> _purchases = [];
|
List<Purchase> _purchases = [];
|
||||||
List<SplitTest> _splitTests = [];
|
List<SplitTest> _splitTests = [];
|
||||||
|
List<TrainingPlanDay> _trainingPlanDays = [];
|
||||||
|
|
||||||
List<ExercisePlanTemplate> _exercisePlanTemplates = [];
|
List<ExercisePlanTemplate> _exercisePlanTemplates = [];
|
||||||
|
|
||||||
@ -184,6 +186,7 @@ class Cache with Logging {
|
|||||||
String testEnv = EnvironmentConfig.test_env;
|
String testEnv = EnvironmentConfig.test_env;
|
||||||
this.testEnvironment = testEnv;
|
this.testEnvironment = testEnv;
|
||||||
if (testEnv == "1") {
|
if (testEnv == "1") {
|
||||||
|
print("testEnv $testEnv");
|
||||||
baseUrl = baseUrlTest;
|
baseUrl = baseUrlTest;
|
||||||
liveServer = false;
|
liveServer = false;
|
||||||
}
|
}
|
||||||
@ -668,7 +671,7 @@ class Cache with Logging {
|
|||||||
await PackageApi().getCustomerPackage(customerId);
|
await PackageApi().getCustomerPackage(customerId);
|
||||||
|
|
||||||
if (!isInDebugMode) {
|
if (!isInDebugMode) {
|
||||||
Flurry.setUserId(customerId.toString());
|
FlurryData.setUserId(customerId.toString());
|
||||||
//Smartlook.setUserIdentifier(customerId.toString());
|
//Smartlook.setUserIdentifier(customerId.toString());
|
||||||
FlutterUxcam.setUserProperty("username", customerId.toString());
|
FlutterUxcam.setUserProperty("username", customerId.toString());
|
||||||
FlutterUxcam.setUserIdentity(customerId.toString());
|
FlutterUxcam.setUserIdentity(customerId.toString());
|
||||||
@ -737,4 +740,7 @@ class Cache with Logging {
|
|||||||
|
|
||||||
List<SplitTest> getSplitTests() => this._splitTests;
|
List<SplitTest> getSplitTests() => this._splitTests;
|
||||||
setSplitTests(value) => this._splitTests = value;
|
setSplitTests(value) => this._splitTests = value;
|
||||||
|
|
||||||
|
List<TrainingPlanDay> getTrainingPlanDays() => this._trainingPlanDays;
|
||||||
|
setTrainingPlanDays(value) => this._trainingPlanDays = value;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ class CustomerProperty {
|
|||||||
int? customerPropertyId;
|
int? customerPropertyId;
|
||||||
late int propertyId;
|
late int propertyId;
|
||||||
late int customerId;
|
late int customerId;
|
||||||
late DateTime dateAdd;
|
DateTime? dateAdd;
|
||||||
late double propertyValue;
|
late double propertyValue;
|
||||||
bool newData = false;
|
bool newData = false;
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ class CustomerProperty {
|
|||||||
this.customerPropertyId = json['customerPropertyId'];
|
this.customerPropertyId = json['customerPropertyId'];
|
||||||
this.propertyId = json['propertyId'];
|
this.propertyId = json['propertyId'];
|
||||||
this.customerId = json['customerId'];
|
this.customerId = json['customerId'];
|
||||||
this.dateAdd = json['propertyName'];
|
this.dateAdd = json['dataAdd'] ?? DateTime.now();
|
||||||
this.propertyValue = json['propertyValue'];
|
this.propertyValue = json['propertyValue'];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,14 +24,14 @@ class CustomerProperty {
|
|||||||
"customerPropertyId": this.customerPropertyId,
|
"customerPropertyId": this.customerPropertyId,
|
||||||
"propertyId": this.propertyId,
|
"propertyId": this.propertyId,
|
||||||
"customerId": this.customerId,
|
"customerId": this.customerId,
|
||||||
"dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd),
|
"dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd!),
|
||||||
"propertyValue": this.propertyValue
|
"propertyValue": this.propertyValue
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
"propertyId": this.propertyId,
|
"propertyId": this.propertyId,
|
||||||
"customerId": this.customerId,
|
"customerId": this.customerId,
|
||||||
"dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd),
|
"dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd!),
|
||||||
"propertyValue": this.propertyValue
|
"propertyValue": this.propertyValue
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ 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_plan_detail.dart';
|
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
|
||||||
import 'package:aitrainer_app/model/exercise_type.dart';
|
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||||
|
import 'package:aitrainer_app/repository/training_plan_day_repository.dart';
|
||||||
|
|
||||||
class CustomerTrainingPlanDetails {
|
class CustomerTrainingPlanDetails {
|
||||||
/// customerTrainingPlanDetails
|
/// customerTrainingPlanDetails
|
||||||
@ -26,6 +27,8 @@ class CustomerTrainingPlanDetails {
|
|||||||
bool? parallel;
|
bool? parallel;
|
||||||
String? day;
|
String? day;
|
||||||
|
|
||||||
|
int? dayId;
|
||||||
|
|
||||||
/// exerciseType
|
/// exerciseType
|
||||||
ExerciseType? exerciseType;
|
ExerciseType? exerciseType;
|
||||||
|
|
||||||
@ -63,10 +66,10 @@ class CustomerTrainingPlanDetails {
|
|||||||
: json['parallel'] == "true"
|
: json['parallel'] == "true"
|
||||||
? true
|
? true
|
||||||
: null;
|
: null;
|
||||||
this.day = json['day'].toString();
|
this.dayId = json['dayId'] == "null" ? null : json['dayId'];
|
||||||
if (this.day == null || this.day == "null") {
|
TrainingPlanDayRepository trainingPlanDayRepository = TrainingPlanDayRepository();
|
||||||
this.day = "";
|
this.day = trainingPlanDayRepository.getNameById(this.dayId);
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
Iterable iterable = json['exercises'];
|
Iterable iterable = json['exercises'];
|
||||||
this.exercises = iterable.map((exercise) => Exercise.fromJson(exercise)).toList();
|
this.exercises = iterable.map((exercise) => Exercise.fromJson(exercise)).toList();
|
||||||
@ -114,15 +117,30 @@ class CustomerTrainingPlanDetails {
|
|||||||
'exercises': exercises.isEmpty ? [].toString() : exercises.map((exercise) => exercise.toJson()).toList().toString(),
|
'exercises': exercises.isEmpty ? [].toString() : exercises.map((exercise) => exercise.toJson()).toList().toString(),
|
||||||
'state': this.state.toStr(),
|
'state': this.state.toStr(),
|
||||||
"isTest": this.isTest,
|
"isTest": this.isTest,
|
||||||
|
"dayId": this.dayId,
|
||||||
};
|
};
|
||||||
if (this.day != null && this.day!.isNotEmpty) {
|
|
||||||
jsonMap["day"] = this.day;
|
|
||||||
}
|
|
||||||
|
|
||||||
//print("Detail $jsonMap");
|
//print("Detail toJson $jsonMap");
|
||||||
return jsonMap;
|
return jsonMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => this.toJsonWithExercises().toString();
|
String toString() => this.toJsonWithExercises().toString();
|
||||||
|
|
||||||
|
void copy(CustomerTrainingPlanDetails from) {
|
||||||
|
this.customerTrainingPlanDetailsId = from.customerTrainingPlanDetailsId;
|
||||||
|
this.trainingPlanDetailsId = from.trainingPlanDetailsId;
|
||||||
|
this.exerciseTypeId = from.exerciseTypeId;
|
||||||
|
this.exerciseType = from.exerciseType;
|
||||||
|
this.set = from.set;
|
||||||
|
this.repeats = from.repeats;
|
||||||
|
this.weight = from.weight;
|
||||||
|
this.restingTime = from.restingTime;
|
||||||
|
this.parallel = from.parallel;
|
||||||
|
this.exercises = from.exercises;
|
||||||
|
this.state = from.state;
|
||||||
|
this.isTest = from.isTest;
|
||||||
|
this.day = from.day;
|
||||||
|
this.dayId = from.dayId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import 'package:aitrainer_app/model/evaluation_attribute.dart';
|
import 'package:aitrainer_app/model/evaluation_attribute.dart';
|
||||||
|
|
||||||
class Evaluation {
|
class Evaluation {
|
||||||
late int evaluationId;
|
int? evaluationId;
|
||||||
late String name;
|
late String name;
|
||||||
late int exerciseTypeId;
|
int? exerciseTypeId;
|
||||||
late String unit;
|
String? unit;
|
||||||
late List attributes;
|
late List attributes;
|
||||||
|
|
||||||
Evaluation.fromJson(Map json) {
|
Evaluation.fromJson(Map json) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
class EvaluationAttribute {
|
class EvaluationAttribute {
|
||||||
late int evaluationAttrId;
|
late int evaluationAttrId;
|
||||||
late int evaluationId;
|
int? evaluationId;
|
||||||
late String name;
|
late String name;
|
||||||
late String sex;
|
late String sex;
|
||||||
late int ageMin;
|
late int ageMin;
|
||||||
|
@ -17,7 +17,7 @@ class ExerciseType {
|
|||||||
late String unit;
|
late String unit;
|
||||||
|
|
||||||
/// unitQuantity
|
/// unitQuantity
|
||||||
late String unitQuantity;
|
String? unitQuantity;
|
||||||
|
|
||||||
/// unitQuantityUnit
|
/// unitQuantityUnit
|
||||||
String? unitQuantityUnit;
|
String? unitQuantityUnit;
|
||||||
@ -28,6 +28,8 @@ class ExerciseType {
|
|||||||
/// base
|
/// base
|
||||||
late bool base;
|
late bool base;
|
||||||
|
|
||||||
|
late bool buddyWarning;
|
||||||
|
|
||||||
/// imageUrl
|
/// imageUrl
|
||||||
String imageUrl = "";
|
String imageUrl = "";
|
||||||
|
|
||||||
@ -65,6 +67,7 @@ class ExerciseType {
|
|||||||
this.unitQuantityUnit = json['unitQuantityUnit'];
|
this.unitQuantityUnit = json['unitQuantityUnit'];
|
||||||
this.active = json['active'];
|
this.active = json['active'];
|
||||||
this.base = json['base'];
|
this.base = json['base'];
|
||||||
|
this.buddyWarning = json['buddyWarning'];
|
||||||
if (json['images'].length > 0) {
|
if (json['images'].length > 0) {
|
||||||
this.imageUrl = json['images'][0]['url'];
|
this.imageUrl = json['images'][0]['url'];
|
||||||
}
|
}
|
||||||
@ -105,6 +108,8 @@ class ExerciseType {
|
|||||||
"unitQuantity": unitQuantity,
|
"unitQuantity": unitQuantity,
|
||||||
"unitQuantityUnit": unitQuantityUnit,
|
"unitQuantityUnit": unitQuantityUnit,
|
||||||
"active": active,
|
"active": active,
|
||||||
|
"base": base,
|
||||||
|
"buddyWarning": buddyWarning,
|
||||||
"devices": this.devices.toString(),
|
"devices": this.devices.toString(),
|
||||||
"nameTranslation": this.nameTranslation,
|
"nameTranslation": this.nameTranslation,
|
||||||
"parents": this.parents.toString()
|
"parents": this.parents.toString()
|
||||||
|
@ -4,10 +4,10 @@ import 'package:aitrainer_app/model/training_plan_detail.dart';
|
|||||||
|
|
||||||
class TrainingPlan {
|
class TrainingPlan {
|
||||||
late int trainingPlanId;
|
late int trainingPlanId;
|
||||||
late String type;
|
String? type;
|
||||||
late String name;
|
late String name;
|
||||||
late String internalName;
|
String? internalName;
|
||||||
late String description;
|
String? description;
|
||||||
late bool free;
|
late bool free;
|
||||||
late bool active;
|
late bool active;
|
||||||
int? treeId;
|
int? treeId;
|
||||||
@ -28,7 +28,7 @@ class TrainingPlan {
|
|||||||
this.treeId = json['treeId'];
|
this.treeId = json['treeId'];
|
||||||
|
|
||||||
nameTranslations['en'] = name;
|
nameTranslations['en'] = name;
|
||||||
descriptionTranslations['en'] = description;
|
descriptionTranslations['en'] = description ?? "";
|
||||||
if (json['translations'] != null && json['translations'].length > 0) {
|
if (json['translations'] != null && json['translations'].length > 0) {
|
||||||
json['translations'].forEach((translation) {
|
json['translations'].forEach((translation) {
|
||||||
nameTranslations[translation['languageCode']] = translation['nameTranslation'];
|
nameTranslations[translation['languageCode']] = translation['nameTranslation'];
|
||||||
|
29
lib/model/training_plan_day.dart
Normal file
29
lib/model/training_plan_day.dart
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import 'dart:collection';
|
||||||
|
|
||||||
|
class TrainingPlanDay {
|
||||||
|
late int dayId;
|
||||||
|
late String name;
|
||||||
|
|
||||||
|
HashMap<String, String> nameTranslations = HashMap();
|
||||||
|
|
||||||
|
TrainingPlanDay.fromJson(Map json) {
|
||||||
|
this.dayId = json['dayId'];
|
||||||
|
this.name = json['name'];
|
||||||
|
|
||||||
|
nameTranslations['en'] = name;
|
||||||
|
if (json['translations'] != null && json['translations'].length > 0) {
|
||||||
|
json['translations'].forEach((translation) {
|
||||||
|
nameTranslations[translation['languageCode']] = translation['nameTranslation'];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => {
|
||||||
|
"dayId": this.dayId,
|
||||||
|
"name": this.name,
|
||||||
|
"nameTranslation": this.nameTranslations.toString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => this.toJson().toString();
|
||||||
|
}
|
@ -1,14 +1,15 @@
|
|||||||
class TrainingPlanDetail {
|
class TrainingPlanDetail {
|
||||||
late int trainingPlanDetailId;
|
late int trainingPlanDetailId;
|
||||||
late int trainingPlanId;
|
int? trainingPlanId;
|
||||||
late int exerciseTypeId;
|
late int exerciseTypeId;
|
||||||
late int sort;
|
late int sort;
|
||||||
late int set;
|
late int set;
|
||||||
late int repeats;
|
int? repeats;
|
||||||
late double weight;
|
double? weight;
|
||||||
late int restingTime;
|
int? restingTime;
|
||||||
late bool parallel;
|
bool? parallel;
|
||||||
late String day;
|
int? dayId;
|
||||||
|
String? day;
|
||||||
|
|
||||||
TrainingPlanDetail.fromJson(Map<String, dynamic> json) {
|
TrainingPlanDetail.fromJson(Map<String, dynamic> json) {
|
||||||
this.trainingPlanDetailId = json['trainingPlanDetailId'];
|
this.trainingPlanDetailId = json['trainingPlanDetailId'];
|
||||||
@ -20,7 +21,7 @@ class TrainingPlanDetail {
|
|||||||
this.weight = json['weight'];
|
this.weight = json['weight'];
|
||||||
this.restingTime = json['restingTime'];
|
this.restingTime = json['restingTime'];
|
||||||
this.parallel = json['parallel'];
|
this.parallel = json['parallel'];
|
||||||
this.day = json['day'];
|
this.dayId = json['dayId'];
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
Map<String, dynamic> toJson() => {
|
||||||
@ -32,6 +33,7 @@ class TrainingPlanDetail {
|
|||||||
"weight": this.weight,
|
"weight": this.weight,
|
||||||
"restingTime": this.restingTime,
|
"restingTime": this.restingTime,
|
||||||
"parallel": this.parallel,
|
"parallel": this.parallel,
|
||||||
|
"dayId": this.dayId,
|
||||||
"day": this.day,
|
"day": this.day,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
import 'package:aitrainer_app/service/logging.dart';
|
|
||||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
|
||||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
|
||||||
|
|
||||||
class PushNotificationsManager with Logging {
|
|
||||||
PushNotificationsManager._();
|
|
||||||
|
|
||||||
factory PushNotificationsManager() => _instance;
|
|
||||||
|
|
||||||
static final PushNotificationsManager _instance = PushNotificationsManager._();
|
|
||||||
|
|
||||||
Future<void> init() async {
|
|
||||||
log(" --- Firebase Messagein init..");
|
|
||||||
const AndroidNotificationChannel channel = AndroidNotificationChannel(
|
|
||||||
'high_importance_channel', // id
|
|
||||||
'High Importance Notifications', // title
|
|
||||||
'This channel is used for important notifications.', // description
|
|
||||||
importance: Importance.max,
|
|
||||||
);
|
|
||||||
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
|
|
||||||
|
|
||||||
await flutterLocalNotificationsPlugin
|
|
||||||
.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()
|
|
||||||
?.createNotificationChannel(channel);
|
|
||||||
|
|
||||||
await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
|
|
||||||
alert: true, // Required to display a heads up notification
|
|
||||||
badge: true,
|
|
||||||
sound: true,
|
|
||||||
);
|
|
||||||
String? token = await FirebaseMessaging.instance.getToken();
|
|
||||||
log("FirebaseMessaging token $token");
|
|
||||||
}
|
|
||||||
}
|
|
35
lib/repository/training_plan_day_repository.dart
Normal file
35
lib/repository/training_plan_day_repository.dart
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
|
import 'package:aitrainer_app/model/training_plan.dart';
|
||||||
|
import 'package:aitrainer_app/util/app_language.dart';
|
||||||
|
|
||||||
|
class TrainingPlanDayRepository {
|
||||||
|
const TrainingPlanDayRepository();
|
||||||
|
|
||||||
|
void assignTrainingPlanDays() {
|
||||||
|
List<TrainingPlan>? plans = Cache().getTrainingPlans();
|
||||||
|
if (plans == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
plans.forEach((plan) {
|
||||||
|
if (plan.details != null) {
|
||||||
|
plan.details!.forEach((element) {
|
||||||
|
element.day = this.getNameById(element.dayId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
String? getNameById(int? dayId) {
|
||||||
|
if (dayId == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
String? name;
|
||||||
|
for (var day in Cache().getTrainingPlanDays()) {
|
||||||
|
if (day.dayId == dayId) {
|
||||||
|
name = day.nameTranslations[AppLanguage().appLocal.languageCode];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ import 'package:aitrainer_app/model/exercise.dart';
|
|||||||
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
|
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
|
||||||
import 'package:aitrainer_app/model/exercise_tree.dart';
|
import 'package:aitrainer_app/model/exercise_tree.dart';
|
||||||
import 'package:aitrainer_app/model/training_plan.dart';
|
import 'package:aitrainer_app/model/training_plan.dart';
|
||||||
|
import 'package:aitrainer_app/repository/training_plan_day_repository.dart';
|
||||||
import 'package:aitrainer_app/service/training_plan_service.dart';
|
import 'package:aitrainer_app/service/training_plan_service.dart';
|
||||||
import 'package:aitrainer_app/util/common.dart';
|
import 'package:aitrainer_app/util/common.dart';
|
||||||
|
|
||||||
@ -66,6 +67,7 @@ class TrainingPlanRepository {
|
|||||||
|
|
||||||
// 3 calculate weights
|
// 3 calculate weights
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
||||||
trainingPlan.details!.forEach((elem) {
|
trainingPlan.details!.forEach((elem) {
|
||||||
CustomerTrainingPlanDetails detail = CustomerTrainingPlanDetails();
|
CustomerTrainingPlanDetails detail = CustomerTrainingPlanDetails();
|
||||||
detail.customerTrainingPlanDetailsId = ++index;
|
detail.customerTrainingPlanDetailsId = ++index;
|
||||||
@ -73,7 +75,9 @@ class TrainingPlanRepository {
|
|||||||
detail.exerciseTypeId = elem.exerciseTypeId;
|
detail.exerciseTypeId = elem.exerciseTypeId;
|
||||||
detail.repeats = elem.repeats;
|
detail.repeats = elem.repeats;
|
||||||
detail.set = elem.set;
|
detail.set = elem.set;
|
||||||
detail.day = elem.day;
|
detail.dayId = elem.dayId;
|
||||||
|
TrainingPlanDayRepository trainingPlanDayRepository = TrainingPlanDayRepository();
|
||||||
|
detail.day = trainingPlanDayRepository.getNameById(elem.dayId);
|
||||||
detail.parallel = elem.parallel;
|
detail.parallel = elem.parallel;
|
||||||
detail.restingTime = elem.restingTime;
|
detail.restingTime = elem.restingTime;
|
||||||
detail.exerciseType = Cache().getExerciseTypeById(detail.exerciseTypeId!);
|
detail.exerciseType = Cache().getExerciseTypeById(detail.exerciseTypeId!);
|
||||||
@ -83,6 +87,13 @@ class TrainingPlanRepository {
|
|||||||
} else {
|
} else {
|
||||||
detail.weight = 0;
|
detail.weight = 0;
|
||||||
}
|
}
|
||||||
|
} else if (elem.weight == -2) {
|
||||||
|
final CustomerTrainingPlanDetails calculated = this.isWeightCalculatedByExerciseType(elem.exerciseTypeId, detail, plan);
|
||||||
|
if (calculated.weight != -1) {
|
||||||
|
detail.weight = calculated.weight;
|
||||||
|
} else {
|
||||||
|
detail.weight = -2;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
detail.weight = elem.weight;
|
detail.weight = elem.weight;
|
||||||
}
|
}
|
||||||
@ -98,6 +109,19 @@ class TrainingPlanRepository {
|
|||||||
return plan;
|
return plan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CustomerTrainingPlanDetails isWeightCalculatedByExerciseType(
|
||||||
|
int exerciseTypeId, CustomerTrainingPlanDetails detail, CustomerTrainingPlan plan) {
|
||||||
|
CustomerTrainingPlanDetails calculated = detail;
|
||||||
|
for (var element in plan.details) {
|
||||||
|
if (element.exerciseTypeId == exerciseTypeId) {
|
||||||
|
calculated = element;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return calculated;
|
||||||
|
}
|
||||||
|
|
||||||
TrainingPlan? getTrainingPlanById(int trainingPlanId) {
|
TrainingPlan? getTrainingPlanById(int trainingPlanId) {
|
||||||
TrainingPlan? plan;
|
TrainingPlan? plan;
|
||||||
if (Cache().getTrainingPlans() == null) {
|
if (Cache().getTrainingPlans() == null) {
|
||||||
@ -148,8 +172,9 @@ class TrainingPlanRepository {
|
|||||||
return detail;
|
return detail;
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomerTrainingPlanDetails recalculateDetail(int trainingPlanId, CustomerTrainingPlanDetails detail) {
|
CustomerTrainingPlanDetails recalculateDetail(
|
||||||
CustomerTrainingPlanDetails recalculatedDetail = detail;
|
int trainingPlanId, CustomerTrainingPlanDetails detail, CustomerTrainingPlanDetails nextDetail) {
|
||||||
|
CustomerTrainingPlanDetails recalculatedDetail = nextDetail;
|
||||||
|
|
||||||
// 1. get original repeats
|
// 1. get original repeats
|
||||||
|
|
||||||
@ -164,14 +189,14 @@ class TrainingPlanRepository {
|
|||||||
plan.details!.forEach((element) {
|
plan.details!.forEach((element) {
|
||||||
if (element.trainingPlanDetailId == detail.trainingPlanDetailsId) {
|
if (element.trainingPlanDetailId == detail.trainingPlanDetailsId) {
|
||||||
print("element $element");
|
print("element $element");
|
||||||
originalRepeats = element.repeats;
|
originalRepeats = element.repeats ?? 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 2 get recalculated repeats
|
// 2 get recalculated repeats
|
||||||
|
|
||||||
recalculatedDetail.weight =
|
recalculatedDetail.weight =
|
||||||
Common.calculateWeigthByChangedQuantity(detail.weight!, detail.repeats!.toDouble(), originalRepeats.toDouble());
|
Common.calculateWeigthByChangedQuantity(detail.weight!, detail.repeats!.toDouble(), originalRepeats.toDouble());
|
||||||
|
recalculatedDetail.weight = Common.roundWeight(recalculatedDetail.weight!);
|
||||||
print("recalculated repeats for $originalRepeats: ${recalculatedDetail.weight}");
|
print("recalculated repeats for $originalRepeats: ${recalculatedDetail.weight}");
|
||||||
recalculatedDetail.repeats = originalRepeats;
|
recalculatedDetail.repeats = originalRepeats;
|
||||||
|
|
||||||
|
@ -112,10 +112,10 @@ class WorkoutTreeRepository with Logging {
|
|||||||
0,
|
0,
|
||||||
"");
|
"");
|
||||||
this.tree[exerciseType.name] = menuItem;
|
this.tree[exerciseType.name] = menuItem;
|
||||||
if (isRunning || is1RM) {
|
if (isRunning || is1RM || exerciseType.name == "Warming Up" || exerciseType.name == "Stretching") {
|
||||||
menuAsExercise.add(menuItem);
|
menuAsExercise.add(menuItem);
|
||||||
}
|
}
|
||||||
//log("ExerciseType in Menu item ${exerciseType.toJson()} is1RM: $is1RM");
|
//log("ExerciseType in Menu item ${exerciseType.toJson()}");
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
//log("No Parents " + exerciseType.toJson().toString());
|
//log("No Parents " + exerciseType.toJson().toString());
|
||||||
|
@ -1,15 +1,20 @@
|
|||||||
|
import 'dart:math' as math;
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'package:crypto/crypto.dart';
|
||||||
import 'package:aitrainer_app/model/cache.dart';
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
import 'package:aitrainer_app/service/logging.dart' as logging;
|
import 'package:aitrainer_app/service/logging.dart' as logging;
|
||||||
import 'package:apple_sign_in/apple_sign_in.dart';
|
import 'package:sign_in_with_apple/sign_in_with_apple.dart';
|
||||||
|
import 'package:awesome_notifications/awesome_notifications.dart';
|
||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
import 'package:firebase_core/firebase_core.dart';
|
import 'package:firebase_core/firebase_core.dart';
|
||||||
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
import 'package:firebase_remote_config/firebase_remote_config.dart';
|
import 'package:firebase_remote_config/firebase_remote_config.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
|
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
|
||||||
import 'package:google_sign_in/google_sign_in.dart';
|
import 'package:google_sign_in/google_sign_in.dart';
|
||||||
|
|
||||||
class FirebaseApi with logging.Logging {
|
class FirebaseApi with logging.Logging {
|
||||||
bool appleSignInAvailable = false;
|
bool appleSignInAvailable = false;
|
||||||
//late FirebaseApi _instance;
|
|
||||||
|
|
||||||
static final FirebaseAuth auth = FirebaseAuth.instance;
|
static final FirebaseAuth auth = FirebaseAuth.instance;
|
||||||
|
|
||||||
@ -29,15 +34,69 @@ class FirebaseApi with logging.Logging {
|
|||||||
Future<void> initializeFlutterFire() async {
|
Future<void> initializeFlutterFire() async {
|
||||||
try {
|
try {
|
||||||
// Wait for Firebase to initialize and set `_initialized` state to true
|
// Wait for Firebase to initialize and set `_initialized` state to true
|
||||||
FirebaseApp app = await Firebase.initializeApp();
|
await Firebase.initializeApp();
|
||||||
|
|
||||||
this.appleSignInAvailable = await AppleSignIn.isAvailable();
|
this.appleSignInAvailable = await SignInWithApple.isAvailable();
|
||||||
|
AwesomeNotifications().initialize(
|
||||||
|
// set the icon to null if you want to use the default app icon
|
||||||
|
null,
|
||||||
|
[
|
||||||
|
NotificationChannel(
|
||||||
|
channelKey: 'basic_channel',
|
||||||
|
channelName: 'Basic notifications',
|
||||||
|
channelDescription: 'Notification channel for basic tests',
|
||||||
|
defaultColor: Color(0xFF9D50DD),
|
||||||
|
ledColor: Colors.white)
|
||||||
|
]);
|
||||||
|
|
||||||
|
AwesomeNotifications().isNotificationAllowed().then((isAllowed) {
|
||||||
|
if (!isAllowed) {
|
||||||
|
// Insert here your friendly dialog box before call the request method
|
||||||
|
// This is very important to not harm the user experience
|
||||||
|
AwesomeNotifications().requestPermissionToSendNotifications();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
|
||||||
|
alert: true, // Required to display a heads up notification
|
||||||
|
badge: true,
|
||||||
|
sound: true,
|
||||||
|
);
|
||||||
|
String? token = await FirebaseMessaging.instance.getToken();
|
||||||
|
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
|
||||||
|
log("FirebaseMessaging token $token");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Set `_error` state to true if Firebase initialization fails
|
// Set `_error` state to true if Firebase initialization fails
|
||||||
log("Error initializing Firebase");
|
log("Error initializing Firebase");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
||||||
|
print('Handling a background message: ${message.messageId}');
|
||||||
|
|
||||||
|
if (!StringUtils.isNullOrEmpty(message.notification?.title, considerWhiteSpaceAsEmpty: true) ||
|
||||||
|
!StringUtils.isNullOrEmpty(message.notification?.body, considerWhiteSpaceAsEmpty: true)) {
|
||||||
|
print('message also contained a notification: ${message.notification}');
|
||||||
|
|
||||||
|
String? imageUrl;
|
||||||
|
imageUrl ??= message.notification!.android?.imageUrl;
|
||||||
|
imageUrl ??= message.notification!.apple?.imageUrl;
|
||||||
|
|
||||||
|
Map<String, dynamic> notificationAdapter = {
|
||||||
|
NOTIFICATION_CHANNEL_KEY: 'basic_channel',
|
||||||
|
NOTIFICATION_ID: message.data[NOTIFICATION_CONTENT]?[NOTIFICATION_ID] ?? message.messageId ?? math.Random().nextInt(2147483647),
|
||||||
|
NOTIFICATION_TITLE: message.data[NOTIFICATION_CONTENT]?[NOTIFICATION_TITLE] ?? message.notification?.title,
|
||||||
|
NOTIFICATION_BODY: message.data[NOTIFICATION_CONTENT]?[NOTIFICATION_BODY] ?? message.notification?.body,
|
||||||
|
NOTIFICATION_LAYOUT: StringUtils.isNullOrEmpty(imageUrl) ? 'Default' : 'BigPicture',
|
||||||
|
NOTIFICATION_BIG_PICTURE: imageUrl
|
||||||
|
};
|
||||||
|
|
||||||
|
AwesomeNotifications().createNotificationFromJsonData(notificationAdapter);
|
||||||
|
} else {
|
||||||
|
AwesomeNotifications().createNotificationFromJsonData(message.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<String> signInEmail(String? email, String? password) async {
|
Future<String> signInEmail(String? email, String? password) async {
|
||||||
if (email == null) {
|
if (email == null) {
|
||||||
throw Exception("Please type an email address");
|
throw Exception("Please type an email address");
|
||||||
@ -85,20 +144,33 @@ class FirebaseApi with logging.Logging {
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String generateNonce([int length = 32]) {
|
||||||
|
final charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._';
|
||||||
|
final random = math.Random.secure();
|
||||||
|
return List.generate(length, (_) => charset[random.nextInt(charset.length)]).join();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the sha256 hash of [input] in hex notation.
|
||||||
|
String sha256ofString(String input) {
|
||||||
|
final bytes = utf8.encode(input);
|
||||||
|
final digest = sha256.convert(bytes);
|
||||||
|
return digest.toString();
|
||||||
|
}
|
||||||
|
|
||||||
Future<Map<String, dynamic>> signInWithApple() async {
|
Future<Map<String, dynamic>> signInWithApple() async {
|
||||||
Map<String, dynamic> userData = Map();
|
Map<String, dynamic> userData = Map();
|
||||||
|
|
||||||
final AuthorizationResult result = await AppleSignIn.performRequests([
|
/* final apple.AuthorizationResult result = await SignInWithApple.performRequests([
|
||||||
AppleIdRequest(requestedScopes: [Scope.email, Scope.fullName])
|
apple.AppleIdRequest(requestedScopes: [apple.Scope.email, apple.Scope.fullName])
|
||||||
]);
|
]);
|
||||||
switch (result.status) {
|
switch (result.status) {
|
||||||
case AuthorizationStatus.authorized:
|
case apple.AuthorizationStatus.authorized:
|
||||||
print('User authorized');
|
print('User authorized');
|
||||||
break;
|
break;
|
||||||
case AuthorizationStatus.error:
|
case apple.AuthorizationStatus.error:
|
||||||
print('User error');
|
print('User error');
|
||||||
throw Exception("Apple Sign-In failed");
|
throw Exception("Apple Sign-In failed");
|
||||||
case AuthorizationStatus.cancelled:
|
case apple.AuthorizationStatus.cancelled:
|
||||||
print('User cancelled');
|
print('User cancelled');
|
||||||
throw Exception("Apple Sign-In cancelled");
|
throw Exception("Apple Sign-In cancelled");
|
||||||
}
|
}
|
||||||
@ -106,20 +178,36 @@ class FirebaseApi with logging.Logging {
|
|||||||
// Create an `OAuthCredential` from the credential returned by Apple.
|
// Create an `OAuthCredential` from the credential returned by Apple.
|
||||||
final oauthCredential = OAuthProvider("apple.com").credential(
|
final oauthCredential = OAuthProvider("apple.com").credential(
|
||||||
idToken: String.fromCharCodes(result.credential.identityToken),
|
idToken: String.fromCharCodes(result.credential.identityToken),
|
||||||
accessToken: String.fromCharCodes(result.credential.authorizationCode));
|
accessToken: String.fromCharCodes(result.credential.authorizationCode!));
|
||||||
|
*/
|
||||||
|
// To prevent replay attacks with the credential returned from Apple, we
|
||||||
|
// include a nonce in the credential request. When signing in with
|
||||||
|
// Firebase, the nonce in the id token returned by Apple, is expected to
|
||||||
|
// match the sha256 hash of `rawNonce`.
|
||||||
|
final rawNonce = generateNonce();
|
||||||
|
final nonce = sha256ofString(rawNonce);
|
||||||
|
|
||||||
|
// Request credential for the currently signed in Apple account.
|
||||||
|
final appleCredential = await SignInWithApple.getAppleIDCredential(
|
||||||
|
scopes: [
|
||||||
|
AppleIDAuthorizationScopes.email,
|
||||||
|
AppleIDAuthorizationScopes.fullName,
|
||||||
|
],
|
||||||
|
nonce: nonce,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create an `OAuthCredential` from the credential returned by Apple.
|
||||||
|
final oauthCredential = OAuthProvider("apple.com").credential(
|
||||||
|
idToken: appleCredential.identityToken,
|
||||||
|
rawNonce: rawNonce,
|
||||||
|
);
|
||||||
// Sign in the user with Firebase. If the nonce we generated earlier does
|
// Sign in the user with Firebase. If the nonce we generated earlier does
|
||||||
// not match the nonce in `appleCredential.identityToken`, sign in will fail.
|
// not match the nonce in `appleCredential.identityToken`, sign in will fail.
|
||||||
UserCredential userCredential = await FirebaseAuth.instance.signInWithCredential(oauthCredential);
|
UserCredential userCredential = await FirebaseAuth.instance.signInWithCredential(oauthCredential);
|
||||||
Cache().firebaseUid = userCredential.user!.uid;
|
Cache().firebaseUid = userCredential.user!.uid;
|
||||||
log("userCredential: " + userCredential.toString());
|
log("userCredential: " + userCredential.toString());
|
||||||
|
|
||||||
log("Apple Credentials: " +
|
log("Apple Credentials: ${appleCredential.userIdentifier} state ${appleCredential.state} email ${userCredential.user!.email!}");
|
||||||
result.credential.user.toString() +
|
|
||||||
" state " +
|
|
||||||
result.credential.state.toString() +
|
|
||||||
" email " +
|
|
||||||
userCredential.user!.email!);
|
|
||||||
userData['email'] = userCredential.user!.email;
|
userData['email'] = userCredential.user!.email;
|
||||||
|
|
||||||
return userData;
|
return userData;
|
||||||
@ -127,26 +215,43 @@ class FirebaseApi with logging.Logging {
|
|||||||
|
|
||||||
Future<Map<String, dynamic>> registerWithApple() async {
|
Future<Map<String, dynamic>> registerWithApple() async {
|
||||||
Map<String, dynamic> userData = Map();
|
Map<String, dynamic> userData = Map();
|
||||||
final AuthorizationResult result = await AppleSignIn.performRequests([
|
/* final apple.AuthorizationResult result = await apple.TheAppleSignIn.performRequests([
|
||||||
AppleIdRequest(requestedScopes: [Scope.email, Scope.fullName])
|
apple.AppleIdRequest(requestedScopes: [apple.Scope.email, apple.Scope.fullName])
|
||||||
]);
|
]);
|
||||||
switch (result.status) {
|
switch (result.status) {
|
||||||
case AuthorizationStatus.authorized:
|
case apple.AuthorizationStatus.authorized:
|
||||||
print('Apple User authorized');
|
print('Apple User authorized');
|
||||||
break;
|
break;
|
||||||
case AuthorizationStatus.error:
|
case apple.AuthorizationStatus.error:
|
||||||
print('Apple User error');
|
print('Apple User error');
|
||||||
throw Exception("Apple Sign-In failed");
|
throw Exception("Apple Sign-In failed");
|
||||||
case AuthorizationStatus.cancelled:
|
case apple.AuthorizationStatus.cancelled:
|
||||||
print('User cancelled');
|
print('User cancelled');
|
||||||
throw Exception("Apple Sign-In cancelled");
|
throw Exception("Apple Sign-In cancelled");
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
final rawNonce = generateNonce();
|
||||||
|
final nonce = sha256ofString(rawNonce);
|
||||||
|
|
||||||
// Create an `OAuthCredential` from the credential returned by Apple.
|
// Request credential for the currently signed in Apple account.
|
||||||
|
final appleCredential = await SignInWithApple.getAppleIDCredential(
|
||||||
|
scopes: [
|
||||||
|
AppleIDAuthorizationScopes.email,
|
||||||
|
AppleIDAuthorizationScopes.fullName,
|
||||||
|
],
|
||||||
|
nonce: nonce,
|
||||||
|
);
|
||||||
|
|
||||||
|
final oauthCredential = OAuthProvider("apple.com").credential(
|
||||||
|
idToken: appleCredential.identityToken,
|
||||||
|
rawNonce: rawNonce,
|
||||||
|
);
|
||||||
|
|
||||||
|
/* // Create an `OAuthCredential` from the credential returned by Apple.
|
||||||
final oauthCredential = OAuthProvider("apple.com").credential(
|
final oauthCredential = OAuthProvider("apple.com").credential(
|
||||||
idToken: String.fromCharCodes(result.credential.identityToken),
|
idToken: String.fromCharCodes(result.credential.identityToken),
|
||||||
accessToken: String.fromCharCodes(result.credential.authorizationCode));
|
accessToken: String.fromCharCodes(result.credential.authorizationCode));
|
||||||
|
*/
|
||||||
// Sign in the user with Firebase. If the nonce we generated earlier does
|
// Sign in the user with Firebase. If the nonce we generated earlier does
|
||||||
// not match the nonce in `appleCredential.identityToken`, sign in will fail.
|
// not match the nonce in `appleCredential.identityToken`, sign in will fail.
|
||||||
UserCredential userCredential = await FirebaseAuth.instance.signInWithCredential(oauthCredential);
|
UserCredential userCredential = await FirebaseAuth.instance.signInWithCredential(oauthCredential);
|
||||||
|
@ -19,7 +19,9 @@ import 'package:aitrainer_app/model/property.dart';
|
|||||||
import 'package:aitrainer_app/model/purchase.dart';
|
import 'package:aitrainer_app/model/purchase.dart';
|
||||||
import 'package:aitrainer_app/model/split_test.dart';
|
import 'package:aitrainer_app/model/split_test.dart';
|
||||||
import 'package:aitrainer_app/model/training_plan.dart';
|
import 'package:aitrainer_app/model/training_plan.dart';
|
||||||
|
import 'package:aitrainer_app/model/training_plan_day.dart';
|
||||||
import 'package:aitrainer_app/model/tutorial.dart';
|
import 'package:aitrainer_app/model/tutorial.dart';
|
||||||
|
import 'package:aitrainer_app/repository/training_plan_day_repository.dart';
|
||||||
import 'package:aitrainer_app/service/api.dart';
|
import 'package:aitrainer_app/service/api.dart';
|
||||||
import 'package:aitrainer_app/service/exercise_type_service.dart';
|
import 'package:aitrainer_app/service/exercise_type_service.dart';
|
||||||
import 'package:aitrainer_app/util/not_found_exception.dart';
|
import 'package:aitrainer_app/util/not_found_exception.dart';
|
||||||
@ -105,6 +107,10 @@ class PackageApi {
|
|||||||
final List<SplitTest>? tests = json.map((test) => SplitTest.fromJson(test)).toList();
|
final List<SplitTest>? tests = json.map((test) => SplitTest.fromJson(test)).toList();
|
||||||
//print("A/B tests: $tests");
|
//print("A/B tests: $tests");
|
||||||
Cache().setSplitTests(tests);
|
Cache().setSplitTests(tests);
|
||||||
|
} else if (headRecord[0] == "TrainingPlanDay") {
|
||||||
|
final Iterable json = jsonDecode(headRecord[1]);
|
||||||
|
final List<TrainingPlanDay>? days = json.map((day) => TrainingPlanDay.fromJson(day)).toList();
|
||||||
|
Cache().setTrainingPlanDays(days);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -114,9 +120,11 @@ class PackageApi {
|
|||||||
ExerciseTree tree = element as ExerciseTree;
|
ExerciseTree tree = element as ExerciseTree;
|
||||||
tree.imageUrl = await ExerciseTreeApi().buildImage(tree.imageUrl, tree.treeId);
|
tree.imageUrl = await ExerciseTreeApi().buildImage(tree.imageUrl, tree.treeId);
|
||||||
});
|
});
|
||||||
//print("tree: $exerciseTree");
|
|
||||||
Cache().setExerciseTree(exerciseTree);
|
Cache().setExerciseTree(exerciseTree);
|
||||||
|
|
||||||
|
TrainingPlanDayRepository trainingPlanDayRepository = TrainingPlanDayRepository();
|
||||||
|
trainingPlanDayRepository.assignTrainingPlanDays();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import 'package:aitrainer_app/service/tracking_service.dart';
|
|||||||
import 'package:aitrainer_app/util/enums.dart';
|
import 'package:aitrainer_app/util/enums.dart';
|
||||||
import 'package:aitrainer_app/model/tracking.dart' as model;
|
import 'package:aitrainer_app/model/tracking.dart' as model;
|
||||||
import 'package:firebase_analytics/firebase_analytics.dart';
|
import 'package:firebase_analytics/firebase_analytics.dart';
|
||||||
import 'package:flurry/flurry.dart';
|
import 'package:flurry_data/flurry_data.dart';
|
||||||
import 'package:flutter_uxcam/flutter_uxcam.dart';
|
import 'package:flutter_uxcam/flutter_uxcam.dart';
|
||||||
|
|
||||||
class Track with Logging {
|
class Track with Logging {
|
||||||
@ -20,7 +20,7 @@ class Track with Logging {
|
|||||||
|
|
||||||
void track(TrackingEvent event, {String eventValue = ""}) {
|
void track(TrackingEvent event, {String eventValue = ""}) {
|
||||||
if (!isInDebugMode) {
|
if (!isInDebugMode) {
|
||||||
Flurry.logEvent(event.toString());
|
FlurryData.logEvent(event.toString());
|
||||||
// Smartlook.setGlobalEventProperty(event.toString(), eventValue, false);
|
// Smartlook.setGlobalEventProperty(event.toString(), eventValue, false);
|
||||||
FlutterUxcam.logEventWithProperties(event.enumToString(), {"value": eventValue});
|
FlutterUxcam.logEventWithProperties(event.enumToString(), {"value": eventValue});
|
||||||
model.Tracking tracking = model.Tracking();
|
model.Tracking tracking = model.Tracking();
|
||||||
|
@ -202,8 +202,8 @@ class RegistrationPage extends StatelessWidget with Trans {
|
|||||||
Divider(
|
Divider(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
),
|
),
|
||||||
getDataProtection(loginBloc),
|
// getDataProtection(loginBloc),
|
||||||
loginBloc.emailCheckbox ? getEmailSubscription(loginBloc) : Offstage(),
|
// loginBloc.emailCheckbox ? getEmailSubscription(loginBloc) : Offstage(),
|
||||||
Divider(
|
Divider(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
),
|
),
|
||||||
|
@ -254,7 +254,7 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
|
|||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
onPrimary: Colors.white,
|
onPrimary: Colors.white,
|
||||||
primary: Colors.orange,
|
primary: restricted ? Colors.grey[600] : Colors.orange,
|
||||||
),
|
),
|
||||||
child: Text(t("Start")),
|
child: Text(t("Start")),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@ -294,15 +294,25 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
restricted
|
/* restricted
|
||||||
? Container(
|
? Container(
|
||||||
padding: EdgeInsets.only(bottom: 8),
|
padding: EdgeInsets.only(bottom: 8),
|
||||||
child: Text(
|
child: Text(
|
||||||
t("This is a premium function"),
|
t("This is a premium function"),
|
||||||
style: GoogleFonts.inter(color: Colors.blue[700]),
|
style: GoogleFonts.inter(
|
||||||
|
color: Colors.deepOrange[800],
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
shadows: <Shadow>[
|
||||||
|
Shadow(
|
||||||
|
offset: Offset(2.0, 2.0),
|
||||||
|
blurRadius: 4.0,
|
||||||
|
color: Colors.black54,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: Offstage(),
|
: Offstage(), */
|
||||||
]),
|
]),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
@ -352,7 +362,7 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
|
|||||||
Widget getPlanDetails(TrainingPlan plan, TrainingPlanBloc bloc) {
|
Widget getPlanDetails(TrainingPlan plan, TrainingPlanBloc bloc) {
|
||||||
return SfDataGrid(
|
return SfDataGrid(
|
||||||
headerRowHeight: 30,
|
headerRowHeight: 30,
|
||||||
rowHeight: 45,
|
rowHeight: 60,
|
||||||
source: TrainingPlanDetailSource(
|
source: TrainingPlanDetailSource(
|
||||||
plan: plan,
|
plan: plan,
|
||||||
menuBloc: bloc.menuBloc,
|
menuBloc: bloc.menuBloc,
|
||||||
@ -390,14 +400,33 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
|
|||||||
Navigator.of(context).pop(),
|
Navigator.of(context).pop(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
onDropsetTap: () => {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return DialogCommon(
|
||||||
|
title: t("Dropset"),
|
||||||
|
descriptions: t("A drop set is an advanced resistance training technique "),
|
||||||
|
description2:
|
||||||
|
t(" in which you focus on completing a set until failure - or the inability to do another repetition."),
|
||||||
|
text: "OK",
|
||||||
|
onTap: () => {
|
||||||
|
Navigator.of(context).pop(),
|
||||||
|
},
|
||||||
|
onCancel: () => {
|
||||||
|
Navigator.of(context).pop(),
|
||||||
|
},
|
||||||
|
);
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
headerGridLinesVisibility: GridLinesVisibility.both,
|
headerGridLinesVisibility: GridLinesVisibility.both,
|
||||||
gridLinesVisibility: GridLinesVisibility.both,
|
gridLinesVisibility: GridLinesVisibility.both,
|
||||||
columns: [
|
columns: [
|
||||||
GridTextColumn(
|
GridTextColumn(
|
||||||
//columnWidthMode: ColumnWidthMode.lastColumnFill,
|
columnWidthMode: ColumnWidthMode.lastColumnFill,
|
||||||
maximumWidth: 120,
|
maximumWidth: 160,
|
||||||
columnName: 'exerciseImage',
|
columnName: 'exerciseImage',
|
||||||
label: Container(
|
label: Container(
|
||||||
color: Colors.green[50],
|
color: Colors.green[50],
|
||||||
@ -472,11 +501,13 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
|
|||||||
class TrainingPlanDetailSource extends DataGridSource {
|
class TrainingPlanDetailSource extends DataGridSource {
|
||||||
final TrainingPlan plan;
|
final TrainingPlan plan;
|
||||||
final MenuBloc menuBloc;
|
final MenuBloc menuBloc;
|
||||||
|
final VoidCallback onDropsetTap;
|
||||||
final VoidCallback onWeightTap;
|
final VoidCallback onWeightTap;
|
||||||
final VoidCallback onRepeatTap;
|
final VoidCallback onRepeatTap;
|
||||||
TrainingPlanDetailSource({
|
TrainingPlanDetailSource({
|
||||||
required this.plan,
|
required this.plan,
|
||||||
required this.menuBloc,
|
required this.menuBloc,
|
||||||
|
required this.onDropsetTap,
|
||||||
required this.onWeightTap,
|
required this.onWeightTap,
|
||||||
required this.onRepeatTap,
|
required this.onRepeatTap,
|
||||||
}) {
|
}) {
|
||||||
@ -540,7 +571,7 @@ class TrainingPlanDetailSource extends DataGridSource {
|
|||||||
]),
|
]),
|
||||||
))
|
))
|
||||||
])
|
])
|
||||||
: dataGridCell.columnName == "weight" && dataGridCell.value == -1
|
: dataGridCell.columnName == "weight" && (dataGridCell.value == -1 || dataGridCell.value == -2)
|
||||||
? GestureDetector(
|
? GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
onWeightTap();
|
onWeightTap();
|
||||||
@ -549,21 +580,30 @@ class TrainingPlanDetailSource extends DataGridSource {
|
|||||||
CustomIcon.question_circle,
|
CustomIcon.question_circle,
|
||||||
color: Colors.indigo[300],
|
color: Colors.indigo[300],
|
||||||
))
|
))
|
||||||
: dataGridCell.columnName == "reps" && dataGridCell.value == -1
|
: dataGridCell.columnName == "weight" && dataGridCell.value == -3
|
||||||
? GestureDetector(
|
? GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
onRepeatTap();
|
onDropsetTap();
|
||||||
},
|
},
|
||||||
child: Icon(
|
child: Icon(
|
||||||
CustomIcon.question_circle,
|
CustomIcon.question_circle,
|
||||||
color: Colors.indigo[600],
|
color: Colors.orange[400],
|
||||||
))
|
))
|
||||||
: Text(dataGridCell.value.toString(),
|
: dataGridCell.columnName == "reps" && dataGridCell.value == -1
|
||||||
style: GoogleFonts.inter(
|
? GestureDetector(
|
||||||
fontSize: 14,
|
onTap: () {
|
||||||
color: Colors.indigo,
|
onRepeatTap();
|
||||||
fontWeight: FontWeight.bold,
|
},
|
||||||
)));
|
child: Icon(
|
||||||
|
CustomIcon.question_circle,
|
||||||
|
color: Colors.indigo[600],
|
||||||
|
))
|
||||||
|
: Text(dataGridCell.value.toString(),
|
||||||
|
style: GoogleFonts.inter(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.indigo,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
)));
|
||||||
}).toList());
|
}).toList());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,10 @@ import 'package:aitrainer_app/util/app_localization.dart';
|
|||||||
import 'package:aitrainer_app/util/trans.dart';
|
import 'package:aitrainer_app/util/trans.dart';
|
||||||
import 'package:aitrainer_app/widgets/app_bar.dart';
|
import 'package:aitrainer_app/widgets/app_bar.dart';
|
||||||
import 'package:aitrainer_app/widgets/dialog_common.dart';
|
import 'package:aitrainer_app/widgets/dialog_common.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/dialog_html.dart';
|
||||||
import 'package:aitrainer_app/widgets/menu_image.dart';
|
import 'package:aitrainer_app/widgets/menu_image.dart';
|
||||||
import 'package:aitrainer_app/widgets/victory_widget.dart';
|
import 'package:aitrainer_app/widgets/victory_widget.dart';
|
||||||
|
import 'package:badges/badges.dart';
|
||||||
import 'package:extended_tabs/extended_tabs.dart';
|
import 'package:extended_tabs/extended_tabs.dart';
|
||||||
import 'package:ezanimation/ezanimation.dart';
|
import 'package:ezanimation/ezanimation.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
@ -125,6 +127,7 @@ class _ExerciseTabs extends State<ExerciseTabs> with TickerProviderStateMixin {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
print("init TAB ${widget.bloc.dayNames.length} index ${widget.bloc.activeDayIndex}");
|
||||||
tabController = TabController(length: widget.bloc.dayNames.length, vsync: this);
|
tabController = TabController(length: widget.bloc.dayNames.length, vsync: this);
|
||||||
tabController.animateTo(widget.bloc.activeDayIndex, duration: Duration(milliseconds: 300));
|
tabController.animateTo(widget.bloc.activeDayIndex, duration: Duration(milliseconds: 300));
|
||||||
}
|
}
|
||||||
@ -143,6 +146,13 @@ class _ExerciseTabs extends State<ExerciseTabs> with TickerProviderStateMixin {
|
|||||||
Widget getTabs(TrainingPlanBloc bloc) {
|
Widget getTabs(TrainingPlanBloc bloc) {
|
||||||
return Column(children: [
|
return Column(children: [
|
||||||
ExtendedTabBar(
|
ExtendedTabBar(
|
||||||
|
indicator: BoxDecoration(
|
||||||
|
color: Colors.black87,
|
||||||
|
border: Border(
|
||||||
|
bottom: BorderSide(width: 4.0, color: Colors.blue),
|
||||||
|
top: BorderSide(width: 4.0, color: Colors.blue),
|
||||||
|
)),
|
||||||
|
labelPadding: EdgeInsets.only(left: 5, right: 5),
|
||||||
tabs: getTabNames(),
|
tabs: getTabNames(),
|
||||||
controller: tabController,
|
controller: tabController,
|
||||||
onTap: (index) => bloc.activeDayIndex = index,
|
onTap: (index) => bloc.activeDayIndex = index,
|
||||||
@ -168,52 +178,57 @@ class _ExerciseTabs extends State<ExerciseTabs> with TickerProviderStateMixin {
|
|||||||
List<Tab> getTabNames() {
|
List<Tab> getTabNames() {
|
||||||
List<Tab> tabs = [];
|
List<Tab> tabs = [];
|
||||||
widget.bloc.dayNames.forEach((element) {
|
widget.bloc.dayNames.forEach((element) {
|
||||||
final Widget widget = RichText(
|
final Widget widget = Container(
|
||||||
text: TextSpan(
|
//height: 50,
|
||||||
style: GoogleFonts.inter(
|
padding: EdgeInsets.only(top: 2, left: 5, right: 5, bottom: 2),
|
||||||
fontSize: 14,
|
color: Colors.white24,
|
||||||
fontWeight: FontWeight.bold,
|
child: RichText(
|
||||||
color: Colors.white,
|
textScaleFactor: 0.8,
|
||||||
),
|
text: TextSpan(
|
||||||
children: [
|
style: GoogleFonts.inter(
|
||||||
TextSpan(
|
fontSize: 14,
|
||||||
text: AppLocalizations.of(context)!.translate("Training Day") + ": \n",
|
fontWeight: FontWeight.bold,
|
||||||
style: GoogleFonts.inter(
|
color: Colors.white,
|
||||||
fontSize: 14,
|
),
|
||||||
color: Colors.white,
|
children: [
|
||||||
shadows: <Shadow>[
|
TextSpan(
|
||||||
Shadow(
|
text: AppLocalizations.of(context)!.translate("Training Day") + ": \n",
|
||||||
offset: Offset(5.0, 5.0),
|
style: GoogleFonts.inter(
|
||||||
blurRadius: 12.0,
|
fontSize: 14,
|
||||||
color: Colors.black54,
|
color: Colors.white,
|
||||||
),
|
shadows: <Shadow>[
|
||||||
Shadow(
|
Shadow(
|
||||||
offset: Offset(-3.0, 3.0),
|
offset: Offset(5.0, 5.0),
|
||||||
blurRadius: 12.0,
|
blurRadius: 12.0,
|
||||||
color: Colors.black54,
|
color: Colors.black54,
|
||||||
),
|
),
|
||||||
],
|
Shadow(
|
||||||
)),
|
offset: Offset(-3.0, 3.0),
|
||||||
TextSpan(
|
blurRadius: 12.0,
|
||||||
text: element,
|
color: Colors.black54,
|
||||||
style: GoogleFonts.inter(
|
),
|
||||||
fontSize: 14,
|
],
|
||||||
fontWeight: FontWeight.bold,
|
)),
|
||||||
color: Colors.yellow[400],
|
TextSpan(
|
||||||
shadows: <Shadow>[
|
text: element,
|
||||||
Shadow(
|
style: GoogleFonts.inter(
|
||||||
offset: Offset(5.0, 5.0),
|
fontSize: 14,
|
||||||
blurRadius: 12.0,
|
fontWeight: FontWeight.bold,
|
||||||
color: Colors.black54,
|
color: Colors.yellow[400],
|
||||||
),
|
shadows: <Shadow>[
|
||||||
Shadow(
|
Shadow(
|
||||||
offset: Offset(-3.0, 3.0),
|
offset: Offset(5.0, 5.0),
|
||||||
blurRadius: 12.0,
|
blurRadius: 12.0,
|
||||||
color: Colors.black54,
|
color: Colors.black54,
|
||||||
),
|
),
|
||||||
],
|
Shadow(
|
||||||
)),
|
offset: Offset(-3.0, 3.0),
|
||||||
]));
|
blurRadius: 12.0,
|
||||||
|
color: Colors.black54,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
])));
|
||||||
|
|
||||||
tabs.add(Tab(child: widget));
|
tabs.add(Tab(child: widget));
|
||||||
});
|
});
|
||||||
@ -559,11 +574,17 @@ class _ExerciseTileState extends State<ExerciseTile> with Trans {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
setContext(context);
|
setContext(context);
|
||||||
|
print("detail ${widget.detail}");
|
||||||
final ExercisePlanDetailState state = widget.detail.state;
|
final ExercisePlanDetailState state = widget.detail.state;
|
||||||
final bool done = state.equalsTo(ExercisePlanDetailState.finished) || state.equalsTo(ExercisePlanDetailState.skipped);
|
final bool done = state.equalsTo(ExercisePlanDetailState.finished) || state.equalsTo(ExercisePlanDetailState.skipped);
|
||||||
final String countSerie = widget.detail.set.toString();
|
final String countSerie = widget.detail.set.toString();
|
||||||
final String step = (widget.detail.exercises.length).toString();
|
final String step = (widget.detail.exercises.length).toString();
|
||||||
String weight = widget.detail.weight != null ? widget.detail.weight!.toStringAsFixed(1) : "-";
|
String weight = widget.detail.weight != null ? widget.detail.weight!.toStringAsFixed(1) : "-";
|
||||||
|
bool isDrop = false;
|
||||||
|
if (widget.detail.weight == -3) {
|
||||||
|
weight = t("DROP");
|
||||||
|
isDrop = true;
|
||||||
|
}
|
||||||
String restingTime = widget.detail.restingTime == null ? "" : widget.detail.restingTime!.toStringAsFixed(0);
|
String restingTime = widget.detail.restingTime == null ? "" : widget.detail.restingTime!.toStringAsFixed(0);
|
||||||
bool isTest = false;
|
bool isTest = false;
|
||||||
if (widget.detail.weight != null && widget.detail.weight! == -1) {
|
if (widget.detail.weight != null && widget.detail.weight! == -1) {
|
||||||
@ -574,6 +595,9 @@ class _ExerciseTileState extends State<ExerciseTile> with Trans {
|
|||||||
if (widget.detail.repeats! == -1) {
|
if (widget.detail.repeats! == -1) {
|
||||||
repeats = t("MAX");
|
repeats = t("MAX");
|
||||||
}
|
}
|
||||||
|
final bool extraExercise = widget.detail.exerciseType!.name == "Warming Up" || widget.detail.exerciseType!.name == "Stretching";
|
||||||
|
|
||||||
|
bool buddyWarning = widget.detail.exerciseType == null ? false : widget.detail.exerciseType!.buddyWarning;
|
||||||
setContext(context);
|
setContext(context);
|
||||||
return Container(
|
return Container(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
@ -620,10 +644,58 @@ class _ExerciseTileState extends State<ExerciseTile> with Trans {
|
|||||||
Container(
|
Container(
|
||||||
width: 120,
|
width: 120,
|
||||||
height: 80,
|
height: 80,
|
||||||
child: MenuImage(
|
child: Badge(
|
||||||
imageName: widget.bloc.getActualImageName(widget.detail.exerciseType!.exerciseTypeId),
|
elevation: 0,
|
||||||
workoutTreeId: widget.bloc.getActualWorkoutTreeId(widget.detail.exerciseType!.exerciseTypeId)!,
|
padding: EdgeInsets.all(0),
|
||||||
),
|
position: BadgePosition.bottomStart(start: -5),
|
||||||
|
animationDuration: Duration(milliseconds: 500),
|
||||||
|
animationType: BadgeAnimationType.slide,
|
||||||
|
badgeColor: Colors.transparent,
|
||||||
|
showBadge: true,
|
||||||
|
badgeContent: IconButton(
|
||||||
|
onPressed: () => showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return DialogHTML(
|
||||||
|
title: widget.detail.exerciseType!.nameTranslation,
|
||||||
|
htmlData: '<p>' + widget.detail.exerciseType!.descriptionTranslation + '</p>');
|
||||||
|
}),
|
||||||
|
icon: Icon(
|
||||||
|
Icons.info_outline,
|
||||||
|
color: Colors.yellow[200],
|
||||||
|
)),
|
||||||
|
child: Badge(
|
||||||
|
elevation: 0,
|
||||||
|
padding: EdgeInsets.all(0),
|
||||||
|
position: BadgePosition.topEnd(end: -8),
|
||||||
|
animationDuration: Duration(milliseconds: 500),
|
||||||
|
animationType: BadgeAnimationType.slide,
|
||||||
|
badgeColor: Colors.transparent,
|
||||||
|
showBadge: buddyWarning,
|
||||||
|
badgeContent: IconButton(
|
||||||
|
onPressed: () => showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return DialogCommon(
|
||||||
|
warning: true,
|
||||||
|
text: "Warning",
|
||||||
|
descriptions: t("Attention!"),
|
||||||
|
description2: t("The safe and exact execution of this exercise you need a training buddy or a trainer"),
|
||||||
|
description3: t("Execution at your own risk!"),
|
||||||
|
onTap: () => Navigator.of(context).pop(),
|
||||||
|
onCancel: () => Navigator.of(context).pop(),
|
||||||
|
title: t('Training Buddy'),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
icon: Icon(
|
||||||
|
CustomIcon.exclamation_circle,
|
||||||
|
color: Colors.red[800],
|
||||||
|
)),
|
||||||
|
child: MenuImage(
|
||||||
|
imageName: widget.bloc.getActualImageName(widget.detail.exerciseType!.exerciseTypeId),
|
||||||
|
workoutTreeId: widget.bloc.getActualWorkoutTreeId(widget.detail.exerciseType!.exerciseTypeId)!,
|
||||||
|
radius: 12,
|
||||||
|
))),
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: 10,
|
width: 10,
|
||||||
@ -656,18 +728,18 @@ class _ExerciseTileState extends State<ExerciseTile> with Trans {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
widget.detail.exerciseType!.unitQuantityUnit != null
|
widget.detail.exerciseType!.unitQuantityUnit != null && !extraExercise
|
||||||
? TextSpan(
|
? TextSpan(
|
||||||
text: "\n",
|
text: "\n",
|
||||||
)
|
)
|
||||||
: TextSpan(),
|
: TextSpan(),
|
||||||
widget.detail.exerciseType!.unitQuantityUnit != null
|
widget.detail.exerciseType!.unitQuantityUnit != null && !extraExercise
|
||||||
? TextSpan(
|
? TextSpan(
|
||||||
text: t(widget.detail.exerciseType!.unitQuantityUnit!) + ": ",
|
text: t(widget.detail.exerciseType!.unitQuantityUnit!) + ": ",
|
||||||
style: GoogleFonts.inter(
|
style: GoogleFonts.inter(
|
||||||
fontSize: 12, color: done ? Colors.grey[100] : Colors.yellow[400], fontWeight: FontWeight.bold))
|
fontSize: 12, color: done ? Colors.grey[100] : Colors.yellow[400], fontWeight: FontWeight.bold))
|
||||||
: TextSpan(),
|
: TextSpan(),
|
||||||
widget.detail.exerciseType!.unitQuantityUnit != null
|
widget.detail.exerciseType!.unitQuantityUnit != null && !extraExercise
|
||||||
? TextSpan(
|
? TextSpan(
|
||||||
text: weight,
|
text: weight,
|
||||||
style: GoogleFonts.inter(
|
style: GoogleFonts.inter(
|
||||||
@ -677,37 +749,50 @@ class _ExerciseTileState extends State<ExerciseTile> with Trans {
|
|||||||
TextSpan(
|
TextSpan(
|
||||||
text: "\n",
|
text: "\n",
|
||||||
),
|
),
|
||||||
TextSpan(
|
!extraExercise
|
||||||
text: t(widget.detail.exerciseType!.unit) + ": ",
|
? TextSpan(
|
||||||
style: GoogleFonts.inter(
|
text: t(widget.detail.exerciseType!.unit) + ": ",
|
||||||
fontSize: 12, color: done ? Colors.grey[100] : Colors.yellow[400], fontWeight: FontWeight.bold)),
|
style: GoogleFonts.inter(
|
||||||
TextSpan(
|
fontSize: 12, color: done ? Colors.grey[100] : Colors.yellow[400], fontWeight: FontWeight.bold))
|
||||||
text: repeats,
|
: TextSpan(),
|
||||||
style: GoogleFonts.inter(
|
!extraExercise
|
||||||
fontSize: 12,
|
? TextSpan(
|
||||||
)),
|
text: repeats,
|
||||||
|
style: GoogleFonts.inter(
|
||||||
|
fontSize: 12,
|
||||||
|
))
|
||||||
|
: TextSpan(),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: "\n",
|
text: "\n",
|
||||||
),
|
),
|
||||||
TextSpan(
|
!extraExercise
|
||||||
text: t("Set") + ": ",
|
? TextSpan(
|
||||||
style: GoogleFonts.inter(
|
text: t("Set") + ": ",
|
||||||
fontSize: 12, color: done ? Colors.grey[100] : Colors.yellow[400], fontWeight: FontWeight.bold)),
|
style: GoogleFonts.inter(
|
||||||
TextSpan(
|
fontSize: 12, color: done ? Colors.grey[100] : Colors.yellow[400], fontWeight: FontWeight.bold))
|
||||||
text: step + "/" + countSerie,
|
: TextSpan(),
|
||||||
style: GoogleFonts.inter(
|
!extraExercise
|
||||||
fontSize: 12,
|
? TextSpan(
|
||||||
)),
|
text: step + "/" + countSerie,
|
||||||
|
style: GoogleFonts.inter(
|
||||||
|
fontSize: 12,
|
||||||
|
))
|
||||||
|
: TextSpan(),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: "\n",
|
text: "\n",
|
||||||
),
|
),
|
||||||
TextSpan(
|
!extraExercise
|
||||||
text: t("Resting time") + ": ",
|
? TextSpan(
|
||||||
style: GoogleFonts.inter(
|
text: t("Resting time") + ": ",
|
||||||
fontSize: 12, color: done ? Colors.grey[100] : Colors.yellow[400], fontWeight: FontWeight.bold)),
|
style: GoogleFonts.inter(
|
||||||
TextSpan(
|
fontSize: 12, color: done ? Colors.grey[100] : Colors.yellow[400], fontWeight: FontWeight.bold))
|
||||||
text: restingTime + " " + t("min(s)"),
|
: TextSpan(),
|
||||||
style: GoogleFonts.inter(fontSize: 12, color: done ? Colors.grey[100] : Colors.white, fontWeight: FontWeight.bold)),
|
!extraExercise
|
||||||
|
? TextSpan(
|
||||||
|
text: restingTime + " " + t("min(s)"),
|
||||||
|
style:
|
||||||
|
GoogleFonts.inter(fontSize: 12, color: done ? Colors.grey[100] : Colors.white, fontWeight: FontWeight.bold))
|
||||||
|
: TextSpan(),
|
||||||
]),
|
]),
|
||||||
)),
|
)),
|
||||||
isTest
|
isTest
|
||||||
@ -740,7 +825,35 @@ class _ExerciseTileState extends State<ExerciseTile> with Trans {
|
|||||||
)),
|
)),
|
||||||
]);
|
]);
|
||||||
})
|
})
|
||||||
: Offstage()
|
: isDrop
|
||||||
|
? AnimatedBuilder(
|
||||||
|
animation: animation,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
return Column(mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () => showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return DialogCommon(
|
||||||
|
warning: false,
|
||||||
|
title: t("Drop set"),
|
||||||
|
descriptions: t("Drop set"),
|
||||||
|
description2: t("Recommended method:"),
|
||||||
|
text: "OK",
|
||||||
|
onTap: () => Navigator.of(context).pop(),
|
||||||
|
onCancel: () => {
|
||||||
|
Navigator.of(context).pop(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
child: Icon(
|
||||||
|
CustomIcon.question_circle,
|
||||||
|
color: Colors.orange[200],
|
||||||
|
size: 16,
|
||||||
|
)),
|
||||||
|
]);
|
||||||
|
})
|
||||||
|
: Offstage()
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -6,7 +6,6 @@ import 'package:aitrainer_app/model/customer_training_plan_details.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/exercise_save.dart';
|
import 'package:aitrainer_app/widgets/exercise_save.dart';
|
||||||
import 'package:aitrainer_app/widgets/number_picker.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
@ -43,7 +42,7 @@ class TrainingPlanExercise extends StatelessWidget with Trans {
|
|||||||
}, builder: (context, state) {
|
}, builder: (context, state) {
|
||||||
return ModalProgressHUD(
|
return ModalProgressHUD(
|
||||||
child: getExercises(bloc, detail),
|
child: getExercises(bloc, detail),
|
||||||
inAsyncCall: state is TrainingPlanLoading,
|
inAsyncCall: state is TrainingPlanExerciseLoading,
|
||||||
opacity: 0.5,
|
opacity: 0.5,
|
||||||
color: Colors.black54,
|
color: Colors.black54,
|
||||||
progressIndicator: CircularProgressIndicator(),
|
progressIndicator: CircularProgressIndicator(),
|
||||||
@ -52,6 +51,7 @@ class TrainingPlanExercise extends StatelessWidget with Trans {
|
|||||||
),
|
),
|
||||||
floatingActionButton: Row(mainAxisAlignment: MainAxisAlignment.end, children: [
|
floatingActionButton: Row(mainAxisAlignment: MainAxisAlignment.end, children: [
|
||||||
FloatingActionButton.extended(
|
FloatingActionButton.extended(
|
||||||
|
heroTag: "skipButton",
|
||||||
onPressed: () => {
|
onPressed: () => {
|
||||||
Navigator.of(context).pop(),
|
Navigator.of(context).pop(),
|
||||||
bloc.add(TrainingPlanSkipExercise(detail: detail)),
|
bloc.add(TrainingPlanSkipExercise(detail: detail)),
|
||||||
@ -67,6 +67,7 @@ class TrainingPlanExercise extends StatelessWidget with Trans {
|
|||||||
width: 20,
|
width: 20,
|
||||||
),
|
),
|
||||||
FloatingActionButton.extended(
|
FloatingActionButton.extended(
|
||||||
|
heroTag: "saveButton",
|
||||||
onPressed: () => {
|
onPressed: () => {
|
||||||
Navigator.of(context).pop(),
|
Navigator.of(context).pop(),
|
||||||
bloc.add(TrainingPlanSaveExercise(detail: detail)),
|
bloc.add(TrainingPlanSaveExercise(detail: detail)),
|
||||||
@ -111,7 +112,7 @@ class TrainingPlanExercise extends StatelessWidget with Trans {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget getExerciseForm(TrainingPlanBloc bloc, CustomerTrainingPlanDetails detail) {
|
/* Widget getExerciseForm(TrainingPlanBloc bloc, CustomerTrainingPlanDetails detail) {
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.only(top: 10, left: 25, right: 25),
|
padding: const EdgeInsets.only(top: 10, left: 25, right: 25),
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
@ -224,5 +225,5 @@ class TrainingPlanExercise extends StatelessWidget with Trans {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: listWidgets,
|
children: listWidgets,
|
||||||
);
|
);
|
||||||
}
|
} */
|
||||||
}
|
}
|
||||||
|
@ -85,6 +85,7 @@ class MyTrainingPlans extends StatelessWidget with Trans, Logging {
|
|||||||
getTrainingPlan(t("Training Plans for Women"), "asset/menu/training_plans_q_woman.jpg", "for_woman"),
|
getTrainingPlan(t("Training Plans for Women"), "asset/menu/training_plans_q_woman.jpg", "for_woman"),
|
||||||
getTrainingPlan(t("Training Plans of Celebrities"), "asset/menu/training_plans_q_celebrities.jpg", "celebrities"),
|
getTrainingPlan(t("Training Plans of Celebrities"), "asset/menu/training_plans_q_celebrities.jpg", "celebrities"),
|
||||||
getTrainingPlan(t("Training Plans for Gain Strength"), "asset/menu/training_plans_q_gain_strength.jpg", "gain_strength"),
|
getTrainingPlan(t("Training Plans for Gain Strength"), "asset/menu/training_plans_q_gain_strength.jpg", "gain_strength"),
|
||||||
|
getTrainingPlan(t("Physical Prepare Program for Footgolfers"), "asset/menu/FG_2_edz.jpg", "footgolf"),
|
||||||
]),
|
]),
|
||||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
crossAxisCount: 2,
|
crossAxisCount: 2,
|
||||||
|
@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:aitrainer_app/library/image_cache.dart' as wt;
|
import 'package:aitrainer_app/library/image_cache.dart' as wt;
|
||||||
import 'package:aitrainer_app/library/transparent_image.dart';
|
import 'package:aitrainer_app/library/transparent_image.dart';
|
||||||
|
|
||||||
|
// ignore: must_be_immutable
|
||||||
class MenuImage extends StatelessWidget {
|
class MenuImage extends StatelessWidget {
|
||||||
final int? workoutTreeId;
|
final int? workoutTreeId;
|
||||||
final String imageName;
|
final String imageName;
|
||||||
|
@ -25,10 +25,12 @@ class TreeviewParentWidget extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Widget parentWidget = Text(
|
Widget parentWidget = Text(this.text,
|
||||||
this.text,
|
style: GoogleFonts.archivoBlack(
|
||||||
style: GoogleFonts.archivoBlack(fontSize: fontSize, color: color ?? Colors.blue[800]!, backgroundColor: Colors.transparent),
|
fontSize: fontSize,
|
||||||
);
|
color: color ?? Colors.blue[800]!,
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
));
|
||||||
|
|
||||||
return Card(
|
return Card(
|
||||||
color: backgroundColor,
|
color: backgroundColor,
|
||||||
|
50
pubspec.lock
50
pubspec.lock
@ -22,13 +22,6 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.6"
|
version: "1.0.6"
|
||||||
apple_sign_in:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: apple_sign_in
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.1.0"
|
|
||||||
archive:
|
archive:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -50,6 +43,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.6.1"
|
version: "2.6.1"
|
||||||
|
awesome_notifications:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: awesome_notifications
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.0.6+9"
|
||||||
badges:
|
badges:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -442,13 +442,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.36.1"
|
version: "0.36.1"
|
||||||
flurry:
|
flurry_data:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flurry
|
name: flurry_data
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.0.7"
|
version: "0.0.1"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -517,20 +517,6 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.1"
|
||||||
flutter_local_notifications:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: flutter_local_notifications
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "5.0.0+4"
|
|
||||||
flutter_local_notifications_platform_interface:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: flutter_local_notifications_platform_interface
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.0"
|
|
||||||
flutter_localizations:
|
flutter_localizations:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -1064,6 +1050,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.1"
|
||||||
|
sign_in_with_apple:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: sign_in_with_apple
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.0"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -1216,13 +1209,6 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.0"
|
||||||
timezone:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: timezone
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.7.0"
|
|
||||||
timing:
|
timing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1435,4 +1421,4 @@ packages:
|
|||||||
version: "3.1.0"
|
version: "3.1.0"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.12.0 <3.0.0"
|
dart: ">=2.12.0 <3.0.0"
|
||||||
flutter: ">=2.0.0"
|
flutter: ">=2.0.4"
|
||||||
|
18
pubspec.yaml
18
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.19+89
|
version: 1.1.19+90
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.12.0 <3.0.0"
|
sdk: ">=2.12.0 <3.0.0"
|
||||||
@ -53,31 +53,28 @@ dependencies:
|
|||||||
confetti: ^0.6.0-nullsafety
|
confetti: ^0.6.0-nullsafety
|
||||||
crypto: ^3.0.0
|
crypto: ^3.0.0
|
||||||
carousel_slider: ^4.0.0-nullsafety.0
|
carousel_slider: ^4.0.0-nullsafety.0
|
||||||
#dropdown_search: ^0.5.0
|
|
||||||
convex_bottom_bar: ^3.0.0
|
convex_bottom_bar: ^3.0.0
|
||||||
flutter_app_badger: ^1.2.0
|
flutter_app_badger: ^1.2.0
|
||||||
#super_tooltip: ^1.0.1
|
|
||||||
url_launcher: ^6.0.3
|
url_launcher: ^6.0.3
|
||||||
extended_tabs: ^2.2.0
|
extended_tabs: ^2.2.0
|
||||||
upgrader: ^3.3.0
|
upgrader: ^3.3.0
|
||||||
|
|
||||||
firebase_core: ^1.2.0
|
firebase_core: ^1.2.0
|
||||||
firebase_analytics: ^8.1.0
|
firebase_analytics: ^8.1.0
|
||||||
firebase_messaging: ^10.0.0
|
firebase_messaging: ^10.0.0
|
||||||
flutter_local_notifications: ^5.0.0
|
|
||||||
firebase_auth: ^1.2.0
|
firebase_auth: ^1.2.0
|
||||||
firebase_remote_config: ^0.10.0
|
firebase_remote_config: ^0.10.0
|
||||||
|
awesome_notifications: ^0.0.6+9
|
||||||
|
|
||||||
syncfusion_flutter_gauges: ^19.1.63
|
syncfusion_flutter_gauges: ^19.1.63
|
||||||
syncfusion_flutter_datagrid: ^19.1.63
|
syncfusion_flutter_datagrid: ^19.1.63
|
||||||
|
|
||||||
flutter_facebook_auth: ^3.4.0
|
flutter_facebook_auth: ^3.4.0
|
||||||
google_sign_in: ^5.0.3
|
google_sign_in: ^5.0.3
|
||||||
apple_sign_in: ^0.1.0
|
sign_in_with_apple: ^3.0.0
|
||||||
#sign_in_with_apple: ^3.0.0
|
|
||||||
|
|
||||||
#smartlook: ^1.0.7
|
#smartlook: ^1.0.7
|
||||||
flurry: ^0.0.4
|
flurry_data: ^0.0.1
|
||||||
flutter_uxcam: ^2.0.0-beta.1
|
flutter_uxcam: ^2.0.0-beta.1
|
||||||
|
|
||||||
animated_widgets: ^1.0.6
|
animated_widgets: ^1.0.6
|
||||||
@ -249,6 +246,7 @@ flutter:
|
|||||||
- asset/menu/400m.jpg
|
- asset/menu/400m.jpg
|
||||||
- asset/menu/FG_1_test.jpg
|
- asset/menu/FG_1_test.jpg
|
||||||
- asset/menu/FG_1_training.jpg
|
- asset/menu/FG_1_training.jpg
|
||||||
|
- asset/menu/FG_2_edz.jpg
|
||||||
- asset/menu/alternate_dumbbell_presses.jpg
|
- asset/menu/alternate_dumbbell_presses.jpg
|
||||||
- asset/menu/alternate_standing_shoulder_press.jpg
|
- asset/menu/alternate_standing_shoulder_press.jpg
|
||||||
- asset/menu/arnold_press.jpg
|
- asset/menu/arnold_press.jpg
|
||||||
@ -385,6 +383,7 @@ flutter:
|
|||||||
- asset/menu/standing_triceps_extension.jpg
|
- asset/menu/standing_triceps_extension.jpg
|
||||||
- asset/menu/stiff_legged_deadlift.jpg
|
- asset/menu/stiff_legged_deadlift.jpg
|
||||||
- asset/menu/straight-arm_rope_pull-down.jpg
|
- asset/menu/straight-arm_rope_pull-down.jpg
|
||||||
|
- asset/menu/stretching.jpg
|
||||||
- asset/menu/t_bar_rows.jpg
|
- asset/menu/t_bar_rows.jpg
|
||||||
- asset/menu/test_center.jpg
|
- asset/menu/test_center.jpg
|
||||||
- asset/menu/test_on_machines.jpg
|
- asset/menu/test_on_machines.jpg
|
||||||
@ -411,6 +410,7 @@ flutter:
|
|||||||
- asset/menu/upper_body.jpg
|
- asset/menu/upper_body.jpg
|
||||||
- asset/menu/v_ups.jpg
|
- asset/menu/v_ups.jpg
|
||||||
- asset/menu/wall_sit.jpg
|
- asset/menu/wall_sit.jpg
|
||||||
|
- asset/menu/warmup.jpg
|
||||||
- asset/menu/warrior_stand.jpg
|
- asset/menu/warrior_stand.jpg
|
||||||
- asset/menu/weight_free_test.jpg
|
- asset/menu/weight_free_test.jpg
|
||||||
- asset/menu/weighted_bench_dip.jpg
|
- asset/menu/weighted_bench_dip.jpg
|
||||||
|
Loading…
Reference in New Issue
Block a user