import 'dart:collection'; import 'package:aitrainer_app/bloc/exercise_new/exercise_new_bloc.dart'; import 'package:aitrainer_app/bloc/menu/menu_bloc.dart'; import 'package:aitrainer_app/library/custom_icon_icons.dart'; import 'package:aitrainer_app/util/app_language.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/exercise_ability.dart'; import 'package:aitrainer_app/model/exercise_type.dart'; import 'package:aitrainer_app/repository/customer_repository.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/service/logging.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/widgets/app_bar.dart'; import 'package:aitrainer_app/widgets/bmi_widget.dart'; import 'package:aitrainer_app/widgets/bmr_widget.dart'; import 'package:aitrainer_app/widgets/size_widget.dart'; import 'package:aitrainer_app/widgets/time_picker.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_form_bloc/flutter_form_bloc.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:keyboard_actions/keyboard_actions.dart'; import 'package:modal_progress_hud/modal_progress_hud.dart'; import 'package:stop_watch_timer/stop_watch_timer.dart'; import 'package:wakelock/wakelock.dart'; class ExerciseNewPage extends StatefulWidget { _ExerciseNewPageState createState() => _ExerciseNewPageState(); } class _ExerciseNewPageState extends State with Trans, Logging { final FocusNode _nodeText1 = FocusNode(); final FocusNode _nodeText2 = FocusNode(); final _controller1 = TextEditingController(); final _controller2 = TextEditingController(); initState() { super.initState(); _controller1.text = "30"; _nodeText1.addListener(() { if (_nodeText1.hasFocus) { _controller1.selection = TextSelection(baseOffset: 0, extentOffset: _controller1.text.length); } }); SchedulerBinding.instance.addPostFrameCallback((_) { // ignore: close_sinks final menuBloc = BlocProvider.of(context); _controller2.text = menuBloc.ability.toString() == ExerciseAbility.oneRepMax.toString() ? "12" : "20"; _nodeText2.addListener(() { if (_nodeText2.hasFocus) { _controller2.selection = TextSelection(baseOffset: 0, extentOffset: _controller2.text.length); } }); }); } KeyboardActionsConfig _buildConfig(BuildContext context) { return KeyboardActionsConfig( keyboardActionsPlatform: KeyboardActionsPlatform.ALL, keyboardBarColor: Colors.grey[200], keyboardSeparatorColor: Colors.black26, 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), ), ), ); } ], ), ], ); } @override Widget build(BuildContext context) { final ExerciseType exerciseType = ModalRoute.of(context).settings.arguments; // ignore: close_sinks final menuBloc = BlocProvider.of(context); setContext(context); return BlocProvider( create: (context) => ExerciseNewBloc( exerciseRepository: ExerciseRepository(), menuBloc: menuBloc, customerRepository: CustomerRepository(), exerciseType: exerciseType) ..add(ExerciseNewLoad()), child: BlocConsumer( listener: (context, state) { if (state is ExerciseNewLoading) { } else if (state is ExerciseNewError) { Scaffold.of(context).showSnackBar( SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white)))); } }, builder: (context, state) { final exerciseBloc = BlocProvider.of(context); return ModalProgressHUD( child: getExerciseWidget(exerciseBloc, exerciseType, menuBloc), inAsyncCall: state is ExerciseNewLoading, opacity: 0.5, color: Colors.black54, progressIndicator: CircularProgressIndicator(), ); }, )); } Widget getExerciseWidget(ExerciseNewBloc exerciseBloc, ExerciseType exerciseType, MenuBloc menuBloc) { exerciseBloc.exerciseRepository.setExerciseType(exerciseType); final String exerciseName = AppLanguage().appLocal == Locale("en") ? exerciseBloc.exerciseRepository.exerciseType.name : exerciseBloc.exerciseRepository.exerciseType.nameTranslation; String exerciseDescription = AppLanguage().appLocal == Locale("en") ? exerciseBloc.exerciseRepository.exerciseType.description : exerciseBloc.exerciseRepository.exerciseType.descriptionTranslation; if (exerciseDescription == null) { exerciseDescription = ""; } //log(exerciseBloc.exerciseRepository.exerciseType.name); if (exerciseBloc.exerciseRepository.exerciseType.name == "BMR") { return BMR(exerciseBloc: exerciseBloc); } if (exerciseBloc.exerciseRepository.exerciseType.name == "BMI") { return BMI(exerciseBloc: exerciseBloc); } if (exerciseBloc.exerciseRepository.exerciseType.name == "Sizes") { return SizeWidget(exerciseBloc: exerciseBloc); } final String exerciseTask = exerciseBloc.setExerciseTask(); 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( padding: const EdgeInsets.only(top: 25, left: 55, right: 55), child: SingleChildScrollView( scrollDirection: Axis.vertical, child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( exerciseName, style: GoogleFonts.archivoBlack( fontWeight: FontWeight.bold, fontSize: 24, color: Colors.white, shadows: [ Shadow( offset: Offset(5.0, 5.0), blurRadius: 12.0, color: Colors.black54, ), Shadow( offset: Offset(-3.0, 3.0), blurRadius: 12.0, color: Colors.black54, ), ], ), overflow: TextOverflow.fade, maxLines: 4, softWrap: true, textAlign: TextAlign.center, ), SizedBox( height: 15, ), Text( exerciseDescription, style: GoogleFonts.inter(fontSize: 12, color: Colors.yellow[300]), maxLines: 1, overflow: TextOverflow.fade, softWrap: true, ), InkWell( child: Text( t("More ยป"), style: GoogleFonts.inter(fontSize: 12, color: Colors.blue[200]), ), onTap: () => { Navigator.of(context).pushNamed('exerciseTypeDescription', arguments: exerciseBloc.exerciseRepository), }, ), Divider( color: Colors.transparent, ), Text( t(exerciseTask), style: GoogleFonts.inter( fontSize: 14, color: Colors.orange, fontWeight: FontWeight.bold, ), maxLines: 3, textAlign: TextAlign.center, overflow: TextOverflow.fade, softWrap: true, ), Divider( color: Colors.transparent, ), columnQuantityUnit(exerciseBloc), Divider( color: Colors.transparent, ), columnQuantity(exerciseBloc), Divider( color: Colors.transparent, ), exerciseBloc.exerciseRepository.exerciseType.unitQuantity == "1" ? Text( t("Step") + ": " + "1/4", style: GoogleFonts.inter( fontSize: 22, color: Colors.white, fontWeight: FontWeight.bold, ), maxLines: 3, textAlign: TextAlign.center, overflow: TextOverflow.fade, softWrap: true, ) : Offstage(), Divider( color: Colors.transparent, ), Divider( color: Colors.transparent, ), FlatButton( onPressed: () => { confirmationDialog(exerciseBloc, menuBloc), }, child: Stack( alignment: Alignment.center, children: [ Image.asset('asset/icon/gomb_orange_c.png', width: 140, height: 60), Text( t("Save"), style: TextStyle(fontSize: 16, color: Colors.white), ), ], )), ]), ))), ), )); } Column columnQuantityUnit(ExerciseNewBloc bloc) { Column row = Column(); if (bloc.exerciseRepository.exerciseType != null && bloc.exerciseRepository.exerciseType.unitQuantity == "1") { row = Column(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ TextFormField( focusNode: _nodeText1, controller: _controller1, decoration: InputDecoration( contentPadding: EdgeInsets.only(left: 25, top: 5, bottom: 5), labelText: t(bloc.exerciseRepository.exerciseType.unitQuantityUnit), labelStyle: GoogleFonts.inter(fontSize: 20, color: Colors.yellow[50]), fillColor: Colors.black38, filled: true, border: OutlineInputBorder( gapPadding: 8.0, borderRadius: BorderRadius.circular(12.0), borderSide: BorderSide(color: Colors.white12, width: 0.4), ), ), //initialValue: "30", keyboardType: TextInputType.numberWithOptions(decimal: true), textInputAction: TextInputAction.done, style: GoogleFonts.archivoBlack(fontSize: 80, color: Colors.yellow[300]), onChanged: (value) => {bloc.add(ExerciseNewQuantityUnitChange(quantity: double.parse(value)))}), //] ), ]); } return row; } Column columnQuantity(ExerciseNewBloc bloc) { if (bloc.exerciseRepository.exerciseType.unit == "second") { return Column(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Padding( padding: const EdgeInsets.only(bottom: 0), child: StreamBuilder( stream: bloc.stopWatchTimer.rawTime, initialData: bloc.stopWatchTimer.rawTime.value, builder: (context, snap) { final value = snap.data; final displayTime = StopWatchTimer.getDisplayTime(value, hours: false); return Column(children: [ Padding( padding: const EdgeInsets.all(8), child: Text( displayTime, style: const TextStyle(fontSize: 40, fontFamily: 'Helvetica', fontWeight: FontWeight.bold, color: Colors.white), ), ), ]); })), Padding( padding: const EdgeInsets.all(2), child: Column( children: [ Padding( padding: const EdgeInsets.only(bottom: 0), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 10), child: IconButton( padding: const EdgeInsets.all(2), color: Colors.white70, //shape: const StadiumBorder(), onPressed: () async { bloc.stopWatchTimer.onExecute.add(StopWatchExecute.start); Wakelock.enable(); // prevent sleep the phone }, icon: Icon(CustomIcon.play_1), iconSize: 40, ), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 10), child: IconButton( padding: const EdgeInsets.all(2), iconSize: 40, color: Colors.white70, //shape: const StadiumBorder(), onPressed: () async { bloc.stopWatchTimer.onExecute.add(StopWatchExecute.stop); Wakelock.disable(); }, icon: Icon(CustomIcon.stop), ), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 10), child: IconButton( padding: const EdgeInsets.all(2), iconSize: 40, color: Colors.white70, onPressed: () async { bloc.stopWatchTimer.onExecute.add(StopWatchExecute.reset); }, icon: Icon(CustomIcon.creative_commons_zero), ), ), ], ), ), ], ), ), Divider(), Divider(), Text(t("Or type the time manually:"), style: GoogleFonts.inter(color: Colors.white)), TimePickerWidget( onChange: (value) => {print("timer"), bloc.add(ExerciseNewQuantityChange(quantity: value))}, ) ]); } Column row = Column(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ TextFormField( focusNode: _nodeText2, controller: _controller2, decoration: InputDecoration( contentPadding: EdgeInsets.only(left: 25, top: 5, bottom: 5), labelText: t(bloc.exerciseRepository.exerciseType.unit), labelStyle: GoogleFonts.inter(fontSize: 20, color: Colors.orange[50], decorationColor: Colors.black12), fillColor: Colors.black38, filled: true, border: OutlineInputBorder( gapPadding: 8.0, borderRadius: BorderRadius.circular(12.0), borderSide: BorderSide(color: Colors.black26, width: 0.4), ), ), //initialValue: bloc.quantity.toStringAsFixed(0), keyboardType: TextInputType.number, textInputAction: TextInputAction.next, style: GoogleFonts.archivoBlack(fontSize: 80, color: Colors.orange[200]), onChanged: (value) => {bloc.add(ExerciseNewQuantityChange(quantity: double.parse(value)))}, ), ]); return row; } void confirmationDialog(ExerciseNewBloc bloc, MenuBloc menuBloc) { LinkedHashMap args = LinkedHashMap(); print("quantity: " + bloc.quantity.toString()); if (bloc.exerciseRepository.exercise.quantity == null) { return; } String quantity = bloc.exerciseRepository.exercise.quantity % 1 == 0 ? bloc.exerciseRepository.exercise.quantity.round().toString() : bloc.exerciseRepository.exercise.quantity.toString(); String unitQuantity = ""; if (bloc.exerciseRepository.exercise.unitQuantity != null) { unitQuantity = bloc.exerciseRepository.exercise.unitQuantity % 1 == 0 ? bloc.exerciseRepository.exercise.unitQuantity.round().toString() : bloc.exerciseRepository.exercise.unitQuantity.toString(); } showCupertinoDialog( useRootNavigator: true, context: context, builder: (_) => CupertinoAlertDialog( title: Text(t("Do you save this exercise with these parameters?")), content: Column(children: [ Divider(), Text( t("Exercise") + ": " + bloc.exerciseRepository.exerciseType.name, style: (TextStyle(color: Colors.blue)), ), Text( quantity + " " + t(bloc.exerciseRepository.exerciseType.unit), style: (TextStyle(color: Colors.deepOrange)), ), Text( bloc.exerciseRepository.exerciseType.unitQuantity == "1" ? t("with") + " " + unitQuantity + " " + t(bloc.exerciseRepository.exerciseType.unitQuantityUnit) : "", style: (TextStyle(color: Colors.deepOrange)), ), ]), actions: [ FlatButton( child: Text(t("No")), onPressed: () => Navigator.pop(context), ), FlatButton( child: Text(t("Yes")), onPressed: () => { bloc.exerciseRepository.setCustomer(Cache().userLoggedIn), bloc.add(ExerciseNewSubmit()), Navigator.pop(context), Navigator.pop(context), log("Ability " + menuBloc.ability.toString() + " exerciseType 1rm " + bloc.exerciseRepository.exerciseType.is1RM().toString()), if (bloc.exerciseRepository.exerciseType.unitQuantityUnit == null) { args['exerciseRepository'] = bloc.exerciseRepository, Navigator.of(context).pushNamed('evaluationPage', arguments: args) } else if (menuBloc.ability.equalsTo(ExerciseAbility.oneRepMax)) { args['exerciseRepository'] = bloc.exerciseRepository, args['percent'] = 0.75, args['readonly'] = false, Navigator.of(context).pushNamed('exerciseControlPage', arguments: args) } else if (menuBloc.ability.equalsTo(ExerciseAbility.endurance)) { args['exerciseRepository'] = bloc.exerciseRepository, args['percent'] = 0.50, args['readonly'] = false, Navigator.of(context).pushNamed('exerciseControlPage', arguments: args) } }, ) ], )); } }