diff --git a/i18n/en.json b/i18n/en.json index 0cf60d7..e019450 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -469,5 +469,9 @@ "During the exercise you should try your best:": "During the exercise you should try your best:", "do it with the possible maximum repeats.": "do it with the possible maximum repeats.", "Maximum repeats": "Maximum repeats", - "TEST": "TEST" + "TEST": "TEST", + "A new version of Workout Test is available!": "A new version of Workout Test is available!", + "Update Now": "Update Now", + "Update App?": "Update App?", + "Want to update?": "Please update the app" } \ No newline at end of file diff --git a/i18n/hu.json b/i18n/hu.json index cc62fb7..b2663bd 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -467,5 +467,9 @@ "During the exercise you should try your best:": "A gyakorlat végrehajtása alatt a hozd a legjobbadat:", "do it with the possible maximum repeats.": "A lehetséges maximum ismétlésszámot hajtsd végre.", "Maximum repeats": "Maximum ismétlésszám", - "TEST": "TESZT" + "TEST": "TESZT", + "A new version of Workout Test is available!": "Egy új Workout Test verzió elérhető!", + "Update Now": "Töltsd le most", + "Update App?": "App frissítés", + "Want to update?": "Kérlek töltsd le" } \ No newline at end of file diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 90d462c..d9f910d 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -6,6 +6,8 @@ PODS: - AppAuth/ExternalUserAgent (1.4.0) - apple_sign_in (0.0.1): - Flutter + - device_info (0.0.1): + - Flutter - devicelocale (0.0.1): - Flutter - FBSDKCoreKit (9.1.0): @@ -228,6 +230,7 @@ PODS: DEPENDENCIES: - apple_sign_in (from `.symlinks/plugins/apple_sign_in/ios`) + - device_info (from `.symlinks/plugins/device_info/ios`) - devicelocale (from `.symlinks/plugins/devicelocale/ios`) - firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`) - firebase_auth (from `.symlinks/plugins/firebase_auth/ios`) @@ -288,6 +291,8 @@ SPEC REPOS: EXTERNAL SOURCES: apple_sign_in: :path: ".symlinks/plugins/apple_sign_in/ios" + device_info: + :path: ".symlinks/plugins/device_info/ios" devicelocale: :path: ".symlinks/plugins/devicelocale/ios" firebase_analytics: @@ -344,6 +349,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: AppAuth: 31bcec809a638d7bd2f86ea8a52bd45f6e81e7c7 apple_sign_in: 7716c7ddfa195aeab7dec0dc374ef4ff45d1adb4 + device_info: d7d233b645a32c40dfdc212de5cf646ca482f175 devicelocale: b22617f40038496deffba44747101255cee005b0 FBSDKCoreKit: a00fe2efd780c195a5e09201bf51c56106245b40 FBSDKLoginKit: d98498c598ec09de657385a9349a1f21119b7f86 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 8ef63ee..47784aa 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -388,7 +388,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 9; + CURRENT_PROJECT_VERSION = 11; DEVELOPMENT_TEAM = SFJJBDCU6Z; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -531,7 +531,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 9; + CURRENT_PROJECT_VERSION = 11; DEVELOPMENT_TEAM = SFJJBDCU6Z; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -566,7 +566,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 9; + CURRENT_PROJECT_VERSION = 11; DEVELOPMENT_TEAM = SFJJBDCU6Z; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( diff --git a/lib/main.dart b/lib/main.dart index c2bfaf4..b7c2d06 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,8 +19,6 @@ import 'package:aitrainer_app/view/customer_welcome_page.dart'; import 'package:aitrainer_app/view/evaluation_page.dart'; import 'package:aitrainer_app/view/exercise_control_page.dart'; import 'package:aitrainer_app/view/exercise_log_page.dart'; -import 'package:aitrainer_app/view/exercise_plan_custom_page.dart'; -import 'package:aitrainer_app/view/exercise_plan_custom_detail_add_page.dart'; import 'package:aitrainer_app/view/faq_page.dart'; import 'package:aitrainer_app/view/login.dart'; import 'package:aitrainer_app/view/exercise_new_page.dart'; @@ -31,7 +29,6 @@ import 'package:aitrainer_app/view/mydevelopment_body_page.dart'; import 'package:aitrainer_app/view/mydevelopment_muscle_page.dart'; import 'package:aitrainer_app/view/mydevelopment_page.dart'; import 'package:aitrainer_app/view/mydevelopment_sizes_page.dart'; -import 'package:aitrainer_app/view/myexcercise_plan_page.dart'; import 'package:aitrainer_app/view/registration.dart'; import 'package:aitrainer_app/view/reset_password.dart'; import 'package:aitrainer_app/view/sales_page.dart'; @@ -57,6 +54,7 @@ import 'package:aitrainer_app/util/app_localization.dart'; import 'package:flutter_uxcam/flutter_uxcam.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:upgrader/upgrader.dart'; import 'bloc/account/account_bloc.dart'; import 'bloc/body_development/body_development_bloc.dart'; import 'bloc/development_by_muscle/development_by_muscle_bloc.dart'; @@ -207,6 +205,16 @@ class WorkoutTestApp extends StatelessWidget { SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); final FirebaseAnalytics analytics = FirebaseAnalytics(); + // Only call clearSavedSettings() during testing to reset internal values. + Upgrader().clearSavedSettings(); // REMOVE this for release builds + Upgrader().installAppStoreListingURL(Platform.isAndroid + ? "https://play.google.com/store/apps/details?id=com.aitrainer.aitrainer_app" + : "https://apps.apple.com/hu/app/workouttest/id1515271425"); + //Upgrader().installAppStoreVersion("1.1.19"); + // On iOS, the default behavior will be to use the App Store version of + // the app, so update the Bundle Identifier in example/ios/Runner with a + // valid identifier already in the App Store. + //facebookAppEvents.setAdvertiserTracking(enabled: true); initThirdParty(); return MaterialApp( @@ -252,10 +260,7 @@ class WorkoutTestApp extends StatelessWidget { 'account': (context) => AccountPage(), 'settings': (context) => SettingsPage(), 'myDevelopment': (context) => MyDevelopmentPage(), - 'myExercisePlan': (context) => MyExercisePlanPage(), 'exerciseLogPage': (context) => ExerciseLogPage(), - 'exercisePlanCustomPage': (context) => ExercisePlanCustomPage(), - 'exercisePlanDetailAdd': (context) => ExercisePlanDetailAddPage(), 'mydevelopmentMusclePage': (context) => MyDevelopmentMusclePage(), 'mydevelopmentBodyPage': (context) => MyDevelopmentBodyPage(), 'mydevelopmentSizesPage': (context) => SizesDevelopmentPage(), diff --git a/lib/util/session.dart b/lib/util/session.dart index 7fbc1e1..f5369ad 100644 --- a/lib/util/session.dart +++ b/lib/util/session.dart @@ -8,8 +8,6 @@ import 'package:aitrainer_app/service/logging.dart'; import 'package:aitrainer_app/service/package_service.dart'; import 'package:aitrainer_app/util/purchases.dart'; import 'package:devicelocale/devicelocale.dart'; -import 'package:firebase_core/firebase_core.dart'; -import 'package:firebase_remote_config/firebase_remote_config.dart'; import 'package:flutter/services.dart'; import 'package:flutter_app_badger/flutter_app_badger.dart'; import 'package:package_info/package_info.dart'; diff --git a/lib/view/exercise_plan_custom_detail_add_page.dart b/lib/view/exercise_plan_custom_detail_add_page.dart deleted file mode 100644 index 1f6f921..0000000 --- a/lib/view/exercise_plan_custom_detail_add_page.dart +++ /dev/null @@ -1,300 +0,0 @@ -import 'dart:collection'; - -import 'package:aitrainer_app/bloc/exercise_plan/exercise_plan_bloc.dart'; -import 'package:aitrainer_app/bloc/exercise_plan_custom_add/exercise_plan_custom_add_bloc.dart'; -import 'package:aitrainer_app/util/app_language.dart'; -import 'package:aitrainer_app/model/workout_menu_tree.dart'; -import 'package:aitrainer_app/repository/exercise_plan_repository.dart'; -import 'package:aitrainer_app/util/trans.dart'; -import 'package:aitrainer_app/widgets/app_bar.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:keyboard_actions/keyboard_actions.dart'; -import 'package:keyboard_actions/keyboard_actions_config.dart'; -import 'package:keyboard_actions/keyboard_actions_item.dart'; -import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; - -class ExercisePlanDetailAddPage extends StatefulWidget { - @override - _ExercisePlanDetailAddPage createState() => _ExercisePlanDetailAddPage(); -} - -class _ExercisePlanDetailAddPage extends State with Trans { - final FocusNode _nodeText1 = FocusNode(); - final FocusNode _nodeText2 = FocusNode(); - final FocusNode _nodeText3 = FocusNode(); - - KeyboardActionsConfig _buildConfig(BuildContext context) { - return KeyboardActionsConfig( - keyboardActionsPlatform: KeyboardActionsPlatform.ALL, - keyboardBarColor: Colors.grey[200], - nextFocus: true, - actions: [ - KeyboardActionsItem(focusNode: _nodeText2, toolbarButtons: [ - (node) { - return GestureDetector( - onTap: () => node.unfocus(), - child: Container( - padding: EdgeInsets.all(8.0), - color: Colors.orange[500], - child: Text( - t("Done"), - style: TextStyle(color: Colors.white), - ), - ), - ); - } - ]), - KeyboardActionsItem( - focusNode: _nodeText1, - toolbarButtons: [ - //button 2 - (node) { - return GestureDetector( - onTap: () => node.unfocus(), - child: Container( - color: Colors.orange, - padding: EdgeInsets.all(8.0), - child: Text( - t("Done"), - style: TextStyle(color: Colors.white), - ), - ), - ); - } - ], - ), - KeyboardActionsItem( - focusNode: _nodeText3, - toolbarButtons: [ - //button 2 - (node) { - return GestureDetector( - onTap: () => node.unfocus(), - child: Container( - color: Colors.orange, - padding: EdgeInsets.all(8.0), - child: Text( - t("Done"), - style: TextStyle(color: Colors.white), - ), - ), - ); - } - ], - ), - ], - ); - } - - @override - Widget build(BuildContext context) { - LinkedHashMap args = ModalRoute.of(context)!.settings.arguments as LinkedHashMap; - // ignore: close_sinks - final ExercisePlanBloc planBloc = args['bloc']; - final WorkoutMenuTree workoutMenuTree = args['workoutTreeItem']; - final ExercisePlanRepository exercisePlanRepository = planBloc.exercisePlanRepository; - setContext(context); - - return BlocProvider( - create: (context) => - ExercisePlanCustomAddBloc(exercisePlanRepository: exercisePlanRepository, planBloc: planBloc, workoutMenuTree: workoutMenuTree) - ..add(ExercisePlanCustomAddLoad()), - child: BlocConsumer( - listener: (context, state) { - if (state is ExercisePlanCustomAddError) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white)))); - } - }, - builder: (context, state) { - // ignore: close_sinks - final bloc = BlocProvider.of(context); - return ModalProgressHUD( - child: getForm(bloc, workoutMenuTree), - inAsyncCall: state is ExercisePlanCustomAddLoading, - opacity: 0.5, - color: Colors.black54, - progressIndicator: CircularProgressIndicator(), - ); - }, - )); - } - - Widget getForm(ExercisePlanCustomAddBloc bloc, WorkoutMenuTree workoutMenuTree) { - String exerciseName = ""; - if (bloc.exercisePlanRepository.getActualPlanDetail() == null || bloc.serie == null) { - return Offstage(); - } - - exerciseName = AppLanguage().appLocal == Locale("en") - ? bloc.exercisePlanRepository.getActualPlanDetail()!.exerciseType!.name - : bloc.exercisePlanRepository.getActualPlanDetail()!.exerciseType!.nameTranslation; - - final bool weightVisible = bloc.exercisePlanRepository.getActualPlanDetail()!.exerciseType!.unitQuantityUnit != null; - String summary = bloc.serie!.toStringAsFixed(0) + " x " + bloc.quantity.toStringAsFixed(0); - if (bloc.quantityUnit > 0) { - summary += " x " + bloc.quantityUnit.toStringAsFixed(1) + " kg"; - } - final String unit = bloc.exercisePlanRepository.getActualPlanDetail()!.exerciseType!.unit; - return Form( - child: Scaffold( - resizeToAvoidBottomInset: true, - appBar: AppBarNav(depth: 1), - body: Container( - width: MediaQuery.of(context).size.width, - height: MediaQuery.of(context).size.height, - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage('asset/image/WT_black_background.jpg'), - fit: BoxFit.fill, - alignment: Alignment.center, - ), - ), - child: KeyboardActions( - config: _buildConfig(context), - child: Container( - child: SingleChildScrollView( - padding: const EdgeInsets.only(top: 25, left: 95, right: 95), - scrollDirection: Axis.vertical, - child: Column(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - Text(t('Save The Exercise To The Exercise Plan'), - textAlign: TextAlign.center, - style: GoogleFonts.inter( - fontSize: 14, - color: Colors.white, - )), - Text( - exerciseName, - textAlign: TextAlign.center, - style: GoogleFonts.archivoBlack(fontSize: 18, color: Colors.yellow[200]), - overflow: TextOverflow.fade, - maxLines: 3, - softWrap: true, - ), - - Divider( - color: Colors.transparent, - height: 30, - ), - - TextFormField( - decoration: InputDecoration( - contentPadding: EdgeInsets.only(left: 25, top: 5, bottom: 5), - labelText: t('Serie'), - labelStyle: GoogleFonts.inter(fontSize: 20, color: Colors.yellow[50], decorationColor: Colors.black12), - fillColor: Colors.white24, - filled: true, - border: OutlineInputBorder( - gapPadding: 8.0, - borderRadius: BorderRadius.circular(12.0), - borderSide: BorderSide(color: Colors.black26, width: 0.4), - ), - ), - initialValue: bloc.serie!.toStringAsFixed(0), - focusNode: _nodeText1, - keyboardType: TextInputType.number, - style: GoogleFonts.archivoBlack(fontSize: 60, color: Colors.yellow[200]), - onChanged: (value) => {bloc.add(ExercisePlanCustomAddChangeSerie(quantity: double.parse(value)))}), - //] ), - Divider(), - - TextFormField( - decoration: InputDecoration( - contentPadding: EdgeInsets.only(left: 25, top: 5, bottom: 5), - labelText: t(unit), - fillColor: Colors.white24, - labelStyle: GoogleFonts.inter(fontSize: 20, color: Colors.yellow[50]), - filled: true, - border: OutlineInputBorder( - gapPadding: 4.0, - borderRadius: BorderRadius.circular(12.0), - borderSide: BorderSide(color: Colors.green[50]!, width: 0.4), - ), - ), - focusNode: _nodeText2, - initialValue: bloc.quantity.toStringAsFixed(0), - keyboardType: TextInputType.number, - style: GoogleFonts.archivoBlack(fontSize: 60, color: Colors.yellow[200]), - onChanged: (value) => {bloc.add(ExercisePlanCustomAddChangeQuantity(quantity: double.parse(value)))}), - - Divider(), - - weightVisible - ? TextFormField( - decoration: InputDecoration( - contentPadding: EdgeInsets.only(left: 25, top: 5, bottom: 5), - labelText: t('Weight'), - fillColor: Colors.white24, - labelStyle: GoogleFonts.inter(fontSize: 20, color: Colors.yellow[50]), - filled: true, - border: OutlineInputBorder( - gapPadding: 2.0, - borderRadius: BorderRadius.circular(12.0), - borderSide: BorderSide(color: Colors.green[50]!, width: 0.4), - ), - ), - focusNode: _nodeText3, - initialValue: bloc.quantityUnit.toStringAsFixed(1), - keyboardType: TextInputType.numberWithOptions(decimal: true), - style: GoogleFonts.archivoBlack(fontSize: 60, color: Colors.yellow[200]), - onChanged: (value) => { - if (value.isNotEmpty) - { - value = value.replaceFirst(",", "."), - value = value.replaceAll(RegExp(r'[^0-9.]'), ""), - bloc.add(ExercisePlanCustomAddChangeQuantityUnit(quantity: double.parse(value))) - } - }) - : Offstage(), - - Divider(), - Text( - summary, - style: TextStyle(fontSize: 24, fontWeight: FontWeight.normal, color: Colors.yellow[50]), - ), - Divider(), - - Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - TextButton( - onPressed: () => { - bloc.add(ExercisePlanCustomAddRemove()), - Navigator.of(context).pop(), - }, - child: Stack( - alignment: Alignment.center, - children: [ - Image.asset('asset/icon/gomb_pink_b.png', width: 140, height: 60), - Text( - t("Delete"), - style: TextStyle(fontSize: 16, color: Colors.white), - ), - ], - ), - ), - TextButton( - onPressed: () => { - bloc.add(ExercisePlanCustomAddSubmit()), - Navigator.of(context).pop(), - }, - child: Stack( - alignment: Alignment.center, - children: [ - Image.asset('asset/icon/gomb_zold_b-1.png', width: 140, height: 60), - Text( - t("Save"), - style: TextStyle(fontSize: 16, color: Colors.white), - ), - ], - )), - ], - ), - ]), - )))), - )); - } -} diff --git a/lib/view/exercise_plan_custom_page.dart b/lib/view/exercise_plan_custom_page.dart deleted file mode 100644 index 963189b..0000000 --- a/lib/view/exercise_plan_custom_page.dart +++ /dev/null @@ -1,202 +0,0 @@ -import 'dart:collection'; - -import 'package:aitrainer_app/bloc/exercise_plan/exercise_plan_bloc.dart'; - -import 'package:aitrainer_app/model/cache.dart'; -import 'package:aitrainer_app/model/workout_menu_tree.dart'; -import 'package:aitrainer_app/library/tree_view.dart'; -import 'package:aitrainer_app/util/trans.dart'; -import 'package:aitrainer_app/widgets/app_bar.dart'; -import 'package:aitrainer_app/widgets/bottom_nav.dart'; -import 'package:aitrainer_app/widgets/treeview_parent_widget.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/scheduler.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; - -class ExercisePlanCustomPage extends StatefulWidget { - @override - _ExercisePlanCustomPage createState() => _ExercisePlanCustomPage(); -} - -class _ExercisePlanCustomPage extends State with Trans { - final GlobalKey _scaffoldKey = new GlobalKey(); - // ignore: close_sinks - late ExercisePlanBloc bloc; - - @override - void initState() { - super.initState(); - - /// We require the initializers to run after the loading screen is rendered - SchedulerBinding.instance!.addPostFrameCallback((_) { - BlocProvider.of(context).add(ExercisePlanLoad()); - }); - } - - @override - Widget build(BuildContext context) { - LinkedHashMap arguments = ModalRoute.of(context)!.settings.arguments as LinkedHashMap; - final int customerId = arguments['customerId']; - bloc = BlocProvider.of(context); - bloc.customerId = customerId; - setContext(context); - - return Scaffold( - key: _scaffoldKey, - appBar: AppBarNav(depth: 1), - body: Container( - padding: EdgeInsets.all(20), - decoration: BoxDecoration( - image: DecorationImage( - image: customerId == Cache().userLoggedIn!.customerId - ? AssetImage('asset/image/WT_black_background.jpg') - : AssetImage('asset/image/WT_light_background.jpg'), - fit: BoxFit.cover, - alignment: Alignment.center, - ), - ), - child: BlocConsumer(listener: (context, state) { - if (state is ExercisePlanError) { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text( - state.message, - ), - backgroundColor: Colors.orange, - )); - } - }, builder: (context, state) { - return ModalProgressHUD( - child: exerciseWidget(bloc), - inAsyncCall: state is ExercisePlanLoading, - opacity: 0.5, - color: Colors.black54, - progressIndicator: CircularProgressIndicator(), - ); - })), - bottomNavigationBar: BottomNavigator(bottomNavIndex: 2), - ); - } - - Widget exerciseWidget(ExercisePlanBloc bloc) { - return TreeView( - startExpanded: false, - children: _getTreeChildren(bloc), - ); - } - - List _getTreeChildren(ExercisePlanBloc bloc) { - List exerciseTypes = []; - - Card explanation = Card( - color: Colors.white60, - child: Container( - padding: EdgeInsets.only(left: 10, right: 5, top: 12, bottom: 8), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - Row( - children: [ - Icon( - Icons.info, - color: Colors.orangeAccent, - ), - Text(" "), - Text( - t("Custom Exercise Plan"), - style: GoogleFonts.archivoBlack(fontSize: 20), - ), - ], - ), - Divider( - color: Colors.transparent, - ), - Text( - t("Select manually the exercises what you would like to have in your plan. At the end don't forget to save."), - style: GoogleFonts.inter(fontSize: 12, fontWeight: FontWeight.normal), - ), - ], - ))); - exerciseTypes.add(explanation); - - bloc.menuTreeRepository.sortedTree.forEach((name, list) { - exerciseTypes.add(Container( - margin: const EdgeInsets.only(left: 4.0), - child: TreeViewChild( - startExpanded: false, - parent: TreeviewParentWidget(text: name), - children: _getChildList(list, bloc), - ))); - }); - - return exerciseTypes; - } - - List _getChildList(List listWorkoutTree, ExercisePlanBloc bloc) { - List list = []; - listWorkoutTree.forEach((element) { - final String unitQuantityUnit = - element.exerciseType != null && element.exerciseType!.unitQuantityUnit != null ? element.exerciseType!.unitQuantityUnit! : ""; - list.add(TreeViewChild( - startExpanded: false, - parent: Card( - margin: EdgeInsets.only(left: 10, top: 5), - color: Colors.white54, - child: Container( - padding: const EdgeInsets.only(left: 5, top: 0, right: 5, bottom: 0), - child: Row(mainAxisAlignment: MainAxisAlignment.start, children: [ - IconButton( - icon: element.selected - ? Icon( - Icons.check, - color: Colors.green[300], - ) - : Icon( - Icons.add, - color: Colors.indigo, - ), - onPressed: () => clickAddDetail(bloc, element), - ), - SizedBox(width: 10), - Flexible( - fit: FlexFit.tight, - flex: 8, - child: InkWell( - child: Text( - element.name, - textAlign: TextAlign.start, - style: GoogleFonts.inter(fontSize: 16, color: Colors.black), - ), - onTap: () => clickAddDetail(bloc, element), - ), - ), - InkWell( - child: !element.selected || - bloc.exercisePlanRepository.exercisePlanDetails[element.exerciseTypeId] == null || - bloc.exercisePlanRepository.exercisePlanDetails[element.exerciseTypeId]!.change == null - ? Text("") - : Text( - bloc.exercisePlanRepository.exercisePlanDetails[element.exerciseTypeId]!.repeats.toString() + - " x " + - bloc.exercisePlanRepository.exercisePlanDetails[element.exerciseTypeId]!.weightEquation! + - unitQuantityUnit, - style: TextStyle(fontSize: 9, color: Colors.green), - ), - onTap: () => clickAddDetail(bloc, element), - ), - ]), - )), - children: [])); - }); - return list; - } - - void clickAddDetail(ExercisePlanBloc bloc, WorkoutMenuTree workoutMenuTree) { - final LinkedHashMap args = LinkedHashMap(); - args['bloc'] = bloc; - args['workoutTreeItem'] = workoutMenuTree; - Navigator.of(context).pushNamed("exercisePlanDetailAdd", arguments: args); - } -} diff --git a/lib/view/myexcercise_plan_page.dart b/lib/view/myexcercise_plan_page.dart deleted file mode 100644 index 9a7c458..0000000 --- a/lib/view/myexcercise_plan_page.dart +++ /dev/null @@ -1,218 +0,0 @@ -import 'dart:collection'; -import 'package:aitrainer_app/model/cache.dart'; -import 'package:aitrainer_app/repository/exercise_repository.dart'; -import 'package:aitrainer_app/service/logging.dart'; -import 'package:aitrainer_app/util/enums.dart'; -import 'package:aitrainer_app/util/track.dart'; -import 'package:aitrainer_app/util/trans.dart'; -import 'package:aitrainer_app/widgets/app_bar.dart'; -import 'package:aitrainer_app/widgets/bottom_nav.dart'; -import 'package:aitrainer_app/widgets/dialog_premium.dart'; -import 'package:aitrainer_app/widgets/image_button.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; - -class MyExercisePlanPage extends StatefulWidget { - @override - _MyExercisePlanPage createState() => _MyExercisePlanPage(); -} - -class _MyExercisePlanPage extends State with Trans, Logging { - @override - Widget build(BuildContext context) { - final ExerciseRepository exerciseRepository = ExerciseRepository(); - final LinkedHashMap args = LinkedHashMap(); - setContext(context); - - double mediaWidth = MediaQuery.of(context).size.width; - double imageWidth = (mediaWidth - 45) / 2; - - return Scaffold( - appBar: AppBarNav(depth: 0), - body: Container( - padding: EdgeInsets.all(10), - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage('asset/image/WT_menu_dark.jpg'), - fit: BoxFit.cover, - alignment: Alignment.center, - ), - ), - child: CustomScrollView(scrollDirection: Axis.vertical, slivers: [ - SliverGrid( - delegate: SliverChildListDelegate([ - ImageButton( - width: imageWidth, - textAlignment: Alignment.topLeft, - text: t("Edit My Custom Plan"), - style: GoogleFonts.robotoMono( - textStyle: TextStyle( - fontSize: 14, - color: Colors.white, - fontWeight: FontWeight.bold, - backgroundColor: Colors.black54.withOpacity(0.4))), - image: "asset/image/exercise_plan_custom.jpg", - left: 5, - onTap: () => { - if (Cache().userLoggedIn != null) - { - args['exerciseRepository'] = exerciseRepository, - args['customerId'] = Cache().userLoggedIn!.customerId, - Navigator.of(context).pushNamed('exercisePlanCustomPage', arguments: args) - } - }, - isLocked: false, - ), - ImageButton( - width: imageWidth, - textAlignment: Alignment.topLeft, - text: t("Execute My Selected Training Plan"), - style: GoogleFonts.robotoMono( - textStyle: TextStyle( - fontSize: 14, - color: Colors.white, - fontWeight: FontWeight.bold, - backgroundColor: Colors.black54.withOpacity(0.4))), - image: "asset/image/exercise_plan_execute.jpg", - top: 130, - left: 5, - onTap: () => { - if (Cache().userLoggedIn != null) - { - args['customerId'] = Cache().userLoggedIn!.customerId, - Navigator.of(context).pushNamed('exerciseExecutePlanPage', arguments: args) - } - }, - isLocked: false, - ), - ImageButton( - width: imageWidth, - textAlignment: Alignment.topLeft, - text: t("Suggested Training Plan"), - style: GoogleFonts.robotoMono( - textStyle: TextStyle( - fontSize: 14, - color: Colors.white, - fontWeight: FontWeight.bold, - backgroundColor: Colors.black54.withOpacity(0.4))), - image: "asset/image/exercise_plan_suggested.jpg", - left: 2, - onTap: () => { - if (Cache().userLoggedIn != null) - { - Track().track(TrackingEvent.my_suggested_plan), - showDialog( - context: context, - builder: (BuildContext context) { - return DialogPremium( - unlocked: Cache().hasPurchased, - unlockRound: 2, - function: "Suggested Training Plan", - unlockedText: null, - onTap: () => {Navigator.of(context).pop()}, - onCancel: () => {Navigator.of(context).pop()}, - ); - }) - } - }, - isLocked: true, - ), - ImageButton( - width: imageWidth, - textAlignment: Alignment.topLeft, - text: t("Training Programs"), - style: GoogleFonts.robotoMono( - textStyle: TextStyle( - fontSize: 14, - color: Colors.white, - fontWeight: FontWeight.bold, - backgroundColor: Colors.black54.withOpacity(0.4))), - image: "asset/image/exercise_plan_stars.jpg", - left: 5, - onTap: () => { - if (Cache().userLoggedIn != null) - { - Track().track(TrackingEvent.my_special_plan), - showDialog( - context: context, - builder: (BuildContext context) { - return DialogPremium( - unlocked: Cache().hasPurchased, - unlockRound: 1, - function: "Training Programs", - unlockedText: null, - onTap: () => {Navigator.of(context).pop()}, - onCancel: () => {Navigator.of(context).pop()}, - ); - }) - } - }, - isLocked: true, - ), - hiddenPlanWidget(exerciseRepository), - hiddenTrainingWidget(), - ]), - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - mainAxisSpacing: 15.0, - crossAxisSpacing: 15.0, - childAspectRatio: 1.0, - ), - ) - ])), - bottomNavigationBar: BottomNavigator(bottomNavIndex: 2)); - } - - Widget hiddenPlanWidget(ExerciseRepository exerciseRepository) { - final LinkedHashMap args = LinkedHashMap(); - if (Cache().getTrainee() != null) { - return TextButton( - style: TextButton.styleFrom( - padding: EdgeInsets.all(20), - primary: Colors.white, - onSurface: Colors.black12, - ), - onPressed: () => { - if (Cache().getTrainee() != null) - { - args['exerciseRepository'] = exerciseRepository, - args['customerId'] = Cache().getTrainee()!.customerId, - Navigator.of(context).pushNamed('exercisePlanCustomPage', arguments: args) - } - }, - child: Text( - t("My Trainee's Plan"), - style: TextStyle(fontSize: 18), - )); - } else { - return Container(); - } - } - - Widget hiddenTrainingWidget() { - final LinkedHashMap args = LinkedHashMap(); - if (Cache().getTrainee() != null) { - log("!!Trainee: " + Cache().getTrainee()!.firstname! + " " + Cache().getTrainee()!.name!); - return TextButton( - style: TextButton.styleFrom( - padding: EdgeInsets.all(20), - primary: Colors.white, - onSurface: Colors.black12, - ), - onPressed: () => { - if (Cache().getTrainee() != null) - { - args['customerId'] = Cache().getTrainee()!.customerId, - Navigator.of(context).pushNamed('exerciseExecutePlanPage', arguments: args) - } - }, - child: Text( - t("Execute My Trainee's Training Plan"), - style: TextStyle(fontSize: 18), - )); - } else { - return Container(); - } - } -} diff --git a/lib/view/training_plan_activate_page.dart b/lib/view/training_plan_activate_page.dart index 4f48735..3473152 100644 --- a/lib/view/training_plan_activate_page.dart +++ b/lib/view/training_plan_activate_page.dart @@ -35,7 +35,9 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans { parentName = args['parentName']; return Scaffold( - appBar: AppBarNav(depth: 1), + appBar: AppBarNav( + depth: 0, + ), body: Container( padding: EdgeInsets.all(20), decoration: BoxDecoration( diff --git a/lib/widgets/home.dart b/lib/widgets/home.dart index 775d588..9f649ec 100644 --- a/lib/widgets/home.dart +++ b/lib/widgets/home.dart @@ -1,7 +1,10 @@ +import 'dart:io'; + import 'package:aitrainer_app/bloc/session/session_bloc.dart'; import 'package:aitrainer_app/bloc/settings/settings_bloc.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/service/logging.dart'; +import 'package:aitrainer_app/util/app_language.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/view/login.dart'; import 'package:aitrainer_app/view/menu_page.dart'; @@ -12,6 +15,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:upgrader/upgrader.dart'; import 'loading.dart'; // ignore: must_be_immutable @@ -53,48 +57,62 @@ class _HomePageState extends State with Logging, Trans { @override Widget build(BuildContext context) { setContext(context); + final appcastURL = "https://raw.githubusercontent.com/bossanyit/appcast/main/android_rss.xml"; + final cfg = AppcastConfiguration(url: appcastURL, supportedOS: ['android']); + print("Packageinfo ${Cache().packageInfo}"); return Scaffold( - key: _scaffoldKey, - body: BlocConsumer(listener: (context, state) { - if (state is SessionFailure) { - showDialog( - context: context, - builder: (BuildContext context) { - return DialogCommon( - title: t("Error"), - descriptions: t(state.message), - text: "OK", - onTap: () => { - Navigator.of(context).pop(), - }, - onCancel: () => { - Navigator.of(context).pop(), - }, - ); - }); - } - }, builder: (context, state) { - if (state is SessionInitial) { - return LoadingScreenMain(); - } else if (state is SessionLoading) { - log("loading"); - return LoadingScreenMain(); - } else if (state is SessionReady) { - log("ready menu with " + Cache().startPage); - if (Cache().startPage == 'login') { - return LoginPage(); - } else if (Cache().startPage == 'registration') { - return RegistrationPage(); - } else { - return MenuPage(parent: 0); - } - } else { - log("home: unknown state"); - return MenuPage(parent: 0); - //return LoginPage(); - } - }), - ); + key: _scaffoldKey, + body: UpgradeAlert( + appcastConfig: cfg, + dialogStyle: UpgradeDialogStyle.cupertino, + countryCode: AppLanguage().appLocal.languageCode, + showIgnore: false, + showLater: false, + showReleaseNotes: false, + debugLogging: true, + //debugAlwaysUpgrade: true, + //debugDisplayOnce: true, + //minAppVersion: Cache().packageInfo != null ? Cache().packageInfo!.version : "99.99.99", + messages: MyLocalizedUpgraderMessages(context: context), + child: BlocConsumer(listener: (context, state) { + if (state is SessionFailure) { + showDialog( + context: context, + builder: (BuildContext context) { + return DialogCommon( + title: t("Error"), + descriptions: t(state.message), + text: "OK", + onTap: () => { + Navigator.of(context).pop(), + }, + onCancel: () => { + Navigator.of(context).pop(), + }, + ); + }); + } + }, builder: (context, state) { + if (state is SessionInitial) { + return LoadingScreenMain(); + } else if (state is SessionLoading) { + log("loading"); + return LoadingScreenMain(); + } else if (state is SessionReady) { + log("ready menu with " + Cache().startPage); + if (Cache().startPage == 'login') { + return LoginPage(); + } else if (Cache().startPage == 'registration') { + return RegistrationPage(); + } else { + return MenuPage(parent: 0); + } + } else { + log("home: unknown state"); + return MenuPage(parent: 0); + } + }), + )); } @override @@ -102,3 +120,30 @@ class _HomePageState extends State with Logging, Trans { super.dispose(); } } + +class MyLocalizedUpgraderMessages extends UpgraderMessages with Trans { + /// Override the message function to provide custom language localization. + final BuildContext context; + MyLocalizedUpgraderMessages({required this.context}) : super(); + @override + String message(UpgraderMessage messageKey) { + setContext(context); + switch (messageKey) { + case UpgraderMessage.body: + return t('A new version of Workout Test is available!'); + case UpgraderMessage.buttonTitleIgnore: + return t('Ignore'); + case UpgraderMessage.buttonTitleLater: + return t('Later'); + case UpgraderMessage.buttonTitleUpdate: + return t('Update Now'); + case UpgraderMessage.prompt: + return t('Want to update?'); + case UpgraderMessage.title: + return t('Update App?'); + } + + // Messages that are not provided above can still use the default values. + //return super.message(messageKey); + } +} diff --git a/lib/widgets/menu_page_widget.dart b/lib/widgets/menu_page_widget.dart index 1f545d8..f92759b 100644 --- a/lib/widgets/menu_page_widget.dart +++ b/lib/widgets/menu_page_widget.dart @@ -163,42 +163,23 @@ class _MenuPageWidgetState extends State with Trans, Logging { color: Colors.white, fontSize: 12, )), - child: Badge( - showBadge: workoutTree.nameEnglish == "One Rep Max" || workoutTree.nameEnglish == "Endurance", - animationDuration: Duration(milliseconds: 800), - animationType: BadgeAnimationType.fade, - badgeColor: Colors.blue[100]!, - badgeContent: GestureDetector( - onTap: () => { - showDialog( - context: context, - builder: (BuildContext context) { - return DialogHTML( - title: workoutTree.name, - htmlData: workoutTree.nameEnglish == "Endurance" - ? AppLocalizations.of(context)!.translate("Endurance_desc") - : AppLocalizations.of(context)!.translate("OneRepMax_desc"), - ); - }) - }, - child: Icon(Icons.info_outline_rounded)), - child: Stack(alignment: Alignment.bottomLeft, children: [ - TextButton( - child: badgedIcon(workoutTree, cWidth, cHeight), - onPressed: () => menuClick(workoutTree, menuBloc), + child: Stack(alignment: Alignment.bottomLeft, children: [ + TextButton( + child: badgedIcon(workoutTree, cWidth, cHeight), + onPressed: () => menuClick(workoutTree, menuBloc), + ), + Container( + padding: EdgeInsets.only(left: 15, bottom: 8, right: 15), + child: GestureDetector( + onTap: () => menuClick(workoutTree, menuBloc), + child: Text( + workoutTree.name, + maxLines: 4, + style: GoogleFonts.archivoBlack(color: workoutTree.color, fontSize: workoutTree.fontSize, height: 1.1), ), - Container( - padding: EdgeInsets.only(left: 15, bottom: 8, right: 15), - child: GestureDetector( - onTap: () => menuClick(workoutTree, menuBloc), - child: Text( - workoutTree.name, - maxLines: 4, - style: GoogleFonts.archivoBlack(color: workoutTree.color, fontSize: workoutTree.fontSize, height: 1.1), - ), - ), - ), - ]))))); + ), + ), + ])))); }); } diff --git a/pubspec.lock b/pubspec.lock index a1c72ad..d571604 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -49,7 +49,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.5.0" + version: "2.6.1" badges: dependency: "direct main" description: @@ -260,6 +260,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.0" + device_info: + dependency: transitive + description: + name: device_info + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + device_info_platform_interface: + dependency: transitive + description: + name: device_info_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" devicelocale: dependency: "direct main" description: @@ -741,7 +755,7 @@ packages: name: node_preamble url: "https://pub.dartlang.org" source: hosted - version: "1.4.13" + version: "2.0.0" package_config: dependency: transitive description: @@ -1082,7 +1096,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.1" spider_chart: dependency: "direct main" description: @@ -1180,21 +1194,21 @@ packages: name: test url: "https://pub.dartlang.org" source: hosted - version: "1.16.5" + version: "1.16.8" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.19" + version: "0.3.0" test_core: dependency: transitive description: name: test_core url: "https://pub.dartlang.org" source: hosted - version: "0.3.15" + version: "0.3.19" timeline_tile: dependency: "direct main" description: @@ -1237,6 +1251,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.0" + upgrader: + dependency: "direct main" + description: + name: upgrader + url: "https://pub.dartlang.org" + source: hosted + version: "3.3.0" url_launcher: dependency: "direct main" description: @@ -1293,6 +1314,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + version: + dependency: transitive + description: + name: version + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" video_player: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 25cbe46..8477fa9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.1.18+88 +version: 1.1.19+89 environment: sdk: ">=2.12.0 <3.0.0" @@ -38,7 +38,7 @@ dependencies: infinite_listview: ^1.1.0 toggle_switch: ^0.1.9 keyboard_actions: ^3.4.0 - badges: ^ 2.0.1 + badges: ^2.0.1 #health: ^3.0.0 stop_watch_timer: ^1.2.0+1 #location: ^3.2.4 @@ -59,6 +59,7 @@ dependencies: #super_tooltip: ^1.0.1 url_launcher: ^6.0.3 extended_tabs: ^2.2.0 + upgrader: ^3.3.0 firebase_core: ^1.2.0 firebase_analytics: ^8.1.0