WT1.1.23 fix changes

This commit is contained in:
bossanyit 2021-09-16 18:40:59 +02:00
parent d969a55458
commit 9c72df1d67
16 changed files with 524 additions and 157 deletions

View File

@ -541,5 +541,8 @@
"Based on your initial data, we will generate the personalized training plan for you.": "Based on your initial data, we will generate the personalized training plan for you.",
"No selected Training Plan": "No selected Training Plan",
"Min. 10 minutes": "Min. 10 minutes",
"You want to skip really the entire exercise?": "You want to skip really the entire exercise?"
"You want to skip really the entire exercise?": "You want to skip really the entire exercise?",
"Premium function": "Premium function",
"This is a premium function, you can reach it outside of the trial period only with a valid subscription": "This is a premium function, you can reach it outside of the trial period only with a valid subscription",
"This is a premium function, you can reach it only with a valid subscription": "This is a premium function, you can reach it only with a valid subscription"
}

View File

@ -541,5 +541,8 @@
"Based on your initial data, we will generate the personalized training plan for you.": "A megadott adataid alapján most személyre szabott edzéstervet generálunk neked.",
"No selected Training Plan": "Nincs kiválasztott edzésterved",
"Min. 10 minutes": "Minimum 10 perc",
"You want to skip really the entire exercise?": "Átugrod az egész gyakorlatot?"
"You want to skip really the entire exercise?": "Átugrod az egész gyakorlatot?",
"Premium function": "Prémium tartalom",
"This is a premium function, you can reach it outside of the trial period only with a valid subscription": "Ezt a tartalmat az ingyenes időszakon kívül csak aktív előfizetéssel éred el",
"This is a premium function, you can reach it only with a valid subscription": "Ezt a tartalmat csak aktív előfizetéssel éred el"
}

View File

@ -388,7 +388,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 5;
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 = 2;
CURRENT_PROJECT_VERSION = 5;
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 = 2;
CURRENT_PROJECT_VERSION = 5;
DEVELOPMENT_TEAM = SFJJBDCU6Z;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (

View File

@ -11,7 +11,7 @@
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>WorkoutTest</string>
<string>Workout Test</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>

View File

@ -18,6 +18,7 @@ import 'package:aitrainer_app/util/app_language.dart';
import 'package:aitrainer_app/util/common.dart';
import 'package:aitrainer_app/util/enums.dart';
import 'package:aitrainer_app/util/track.dart';
import 'package:aitrainer_app/widgets/exercise_save.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
@ -74,15 +75,54 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
yield TrainingPlanExerciseLoading();
event.detail.weight = event.weight;
yield TrainingPlanExerciseReady();
yield TrainingPlanReady();
} else if (event is TrainingPlanWeightChangeUp) {
yield TrainingPlanExerciseLoading();
if (event.detail.weight != null) {
event.detail.repeats =
Common.reCalculateRepeatsByChangedWeight(event.detail.weight!, event.detail.repeats!.toDouble(), event.detail.weight! + 1);
event.detail.weight = event.detail.weight! + 1;
ExerciseSaveStream().weight = event.detail.weight!;
ExerciseSaveStream().repeats = event.detail.repeats!;
ExerciseSaveStream().getStreamController().add(true);
}
yield TrainingPlanExerciseReady();
yield TrainingPlanReady();
} else if (event is TrainingPlanWeightChangeDown) {
yield TrainingPlanExerciseLoading();
if (event.detail.weight != null) {
event.detail.repeats =
Common.reCalculateRepeatsByChangedWeight(event.detail.weight!, event.detail.repeats!.toDouble(), event.detail.weight! - 1);
event.detail.weight = event.detail.weight! - 1;
ExerciseSaveStream().weight = event.detail.weight!;
ExerciseSaveStream().repeats = event.detail.repeats!;
ExerciseSaveStream().getStreamController().add(true);
}
yield TrainingPlanExerciseReady();
yield TrainingPlanReady();
} else if (event is TrainingPlanWeightChangeRecalculate) {
yield TrainingPlanExerciseLoading();
/* double weightFromPlan = trainingPlanRepository.getOriginalWeight(this.getMyPlan()!.trainingPlanId!, event.detail);
print("Plan Wieght: $weightFromPlan");
if (weightFromPlan != -1 || (weightFromPlan == -1 && event.detail.set! > 1)) {
bool isTest = weightFromPlan != -1 || weightFromPlan != -2;
if (!isTest || (isTest && event.detail.set! > 1)) {
//&& event.detail.exercises.length > 0
event.detail.repeats =
Common.reCalculateRepeatsByChangedWeight(event.detail.weight!, event.detail.repeats!.toDouble(), event.weight);
event.detail.weight = event.weight;
if (event.detail.repeats! < 3) {
event.detail.repeats = 4;
}
ExerciseSaveStream().repeats = event.detail.repeats!;
ExerciseSaveStream().getStreamController().add(true);
} */
event.detail.weight = event.weight;
yield TrainingPlanExerciseReady();
yield TrainingPlanReady();
} else if (event is TrainingPlanRepeatsChange) {
yield TrainingPlanExerciseLoading();
@ -102,6 +142,7 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
yield TrainingPlanReady();
throw Exception("Please type your repeats!");
}
print("ExerciseTypeUID: ${event.detail.exerciseTypeId}");
if (event.detail.weight == -3) {
print("DropSet");
event.detail.state = ExercisePlanDetailState.finished;
@ -123,8 +164,8 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
// recalculate the weight to the original planned repeats for the next details
if (exercise.unitQuantity != null && exercise.unitQuantity! > 0) {
for (var nextDetail in _myPlan!.details) {
print("NextDetail detail: $nextDetail");
double weightFromPlan = trainingPlanRepository.getOriginalWeight(this.getMyPlan()!.trainingPlanId!, nextDetail);
print("NextDetail detail: $nextDetail *** PlanWeight: $weightFromPlan");
if (nextDetail.exerciseTypeId == event.detail.exerciseTypeId &&
nextDetail.weight == -2 &&
nextDetail.customerTrainingPlanDetailsId != event.detail.customerTrainingPlanDetailsId) {
@ -136,6 +177,12 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
} else if (nextDetail.exerciseTypeId == event.detail.exerciseTypeId && nextDetail.weight == -1 && nextDetail.set! == 1) {
print("recalculating -1, set 1 ${event.detail.customerTrainingPlanDetailsId}");
nextDetail = trainingPlanRepository.recalculateDetailFixRepeatsSet1(_myPlan!.trainingPlanId!, nextDetail, event.detail);
} else if (nextDetail.exerciseTypeId == event.detail.exerciseTypeId &&
weightFromPlan == -2 &&
nextDetail.set! == 1 &&
nextDetail.exercises.length == 0) {
print("recalculating -1/ no exercise, set 1 ${event.detail.customerTrainingPlanDetailsId}");
nextDetail = trainingPlanRepository.recalculateDetailFixRepeatsSet1(_myPlan!.trainingPlanId!, nextDetail, event.detail);
}
}
}

View File

@ -28,6 +28,22 @@ class TrainingPlanWeightChange extends TrainingPlanEvent {
List<Object> get props => [weight, detail];
}
class TrainingPlanWeightChangeUp extends TrainingPlanEvent {
final CustomerTrainingPlanDetails detail;
const TrainingPlanWeightChangeUp({required this.detail});
@override
List<Object> get props => [detail];
}
class TrainingPlanWeightChangeDown extends TrainingPlanEvent {
final CustomerTrainingPlanDetails detail;
const TrainingPlanWeightChangeDown({required this.detail});
@override
List<Object> get props => [detail];
}
class TrainingPlanWeightChangeRecalculate extends TrainingPlanEvent {
final CustomerTrainingPlanDetails detail;
final double weight;

View File

@ -166,8 +166,9 @@ class TrainingPlanRepository {
}
Exercise? lastExercise1RM;
DateTime dt = DateTime.now().subtract(Duration(days: 30));
Cache().getExercises()!.forEach((exercise) {
if (exercise.exercisePlanDetailId == 0 && exercise.exerciseTypeId == exerciseTypeId) {
if (exercise.exerciseTypeId == exerciseTypeId && exercise.dateAdd!.compareTo(dt) >= 0) {
detail.weight = weight;
lastExercise1RM = exercise;
}
@ -179,13 +180,13 @@ class TrainingPlanRepository {
return detail;
}
//double oneRepMax = Common.calculate1RM(lastExercise1RM!.unitQuantity!, lastExercise1RM!.quantity!);
//print("Exercise $exerciseTypeId - 1RM : $oneRepMax");
//weight = oneRepMax * Common.get1RMPercent(detail.repeats!);
//print("Exercise $exerciseTypeId - weight : $weight");
double oneRepMax = Common.calculate1RM(lastExercise1RM!.unitQuantity!, lastExercise1RM!.quantity!);
print("Exercise $exerciseTypeId - 1RM : $oneRepMax");
weight = oneRepMax * Common.get1RMPercent(detail.repeats!);
print("Exercise $exerciseTypeId - weight : $weight");
//weight = Common.roundWeight(weight);
//detail.weight = Common.calculateWeigthByChangedQuantity(detail.weight!, detail.repeats!.toDouble(), lastExercise1RM!.quantity!);
weight = lastExercise1RM!.unitQuantity! * detail.repeats! / lastExercise1RM!.quantity!;
//weight = lastExercise1RM!.unitQuantity! * detail.repeats! / lastExercise1RM!.quantity!;
weight = Common.roundWeight(weight);
print("Recaluclated weight ${detail.weight} - repeat: ${detail.repeats}");

View File

@ -179,11 +179,11 @@ mixin Common {
if (weight > 35) {
final double remainder = weight % 5;
if (remainder < 1.25) {
if (remainder < 1) {
rounded = ((weight / 5).floor() * 5).toDouble();
} else if (remainder > 1.25 && remainder <= 2.5) {
} else if (remainder > 1 && remainder <= 2.5) {
rounded = (weight / 5).floor() * 5 + 2.5;
} else if (remainder > 2.5 && remainder < 3.75) {
} else if (remainder > 2.5 && remainder < 3.25) {
rounded = (weight / 5).floor() * 5 + 2.5;
} else {
rounded = (((weight / 5).ceil() * 5) + 5).toDouble();

View File

@ -2,7 +2,6 @@ import 'dart:collection';
import 'package:aitrainer_app/bloc/exercise_control/exercise_control_bloc.dart';
import 'package:aitrainer_app/bloc/timer/timer_bloc.dart';
import 'package:aitrainer_app/bloc/tutorial/tutorial_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';

View File

@ -2,7 +2,9 @@ import 'dart:collection';
import 'package:aitrainer_app/bloc/exercise_log/exercise_log_bloc.dart';
import 'package:aitrainer_app/widgets/app_bar.dart';
import 'package:aitrainer_app/widgets/bottom_nav.dart';
import 'package:aitrainer_app/widgets/dialog_common.dart';
import 'package:aitrainer_app/widgets/dialog_premium.dart';
import 'package:badges/badges.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:intl/intl.dart';
@ -193,16 +195,72 @@ class ExerciseLogPage extends StatelessWidget with Trans, Common {
)),
GestureDetector(
onTap: () => evaluation(exerciseRepository, exercise),
child: Badge(
elevation: 0,
padding: EdgeInsets.all(0),
position: BadgePosition.topStart(top: -25, start: -25),
animationDuration: Duration(milliseconds: 1500),
animationType: BadgeAnimationType.fade,
badgeColor: Colors.transparent,
showBadge: true,
badgeContent: IconButton(
iconSize: 36,
onPressed: () => showDialog(
context: context,
builder: (BuildContext context) {
return DialogCommon(
title: t("Premium function"),
descriptions: Cache().canTrial()
? t("This is a premium function, you can reach it outside of the trial period only with a valid subscription")
: t("This is a premium function, you can reach it only with a valid subscription"),
onCancel: () => Navigator.of(context).pop(),
onTap: () => Navigator.of(context).pop(),
text: '',
);
}),
icon: Icon(
Icons.star,
size: 14,
color: Colors.orange[400],
)),
child: Image.asset(
"asset/image/kupa.png",
width: 35,
))),
Badge(
elevation: 0,
padding: EdgeInsets.all(0),
position: BadgePosition.topStart(top: -18, start: -17),
animationDuration: Duration(milliseconds: 1500),
animationType: BadgeAnimationType.fade,
badgeColor: Colors.transparent,
showBadge: true,
badgeContent: IconButton(
iconSize: 36,
onPressed: () => showDialog(
context: context,
builder: (BuildContext context) {
return DialogCommon(
title: t("Premium function"),
descriptions: Cache().canTrial()
? t("This is a premium function, you can reach it outside of the trial period only with a valid subscription")
: t("This is a premium function, you can reach it only with a valid subscription"),
onCancel: () => Navigator.of(context).pop(),
onTap: () => Navigator.of(context).pop(),
text: '',
);
}),
icon: Icon(
Icons.star,
size: 14,
color: Colors.orange[400],
)),
IconButton(
child: IconButton(
icon: Icon(Icons.delete, color: Colors.black12),
onPressed: () {
confirmationDialog(exerciseLogBloc, exercise);
},
),
)),
]),
)),
);

View File

@ -6,8 +6,10 @@ import 'package:aitrainer_app/repository/exercise_repository.dart';
import 'package:aitrainer_app/util/enums.dart';
import 'package:aitrainer_app/util/track.dart';
import 'package:aitrainer_app/widgets/dialog_common.dart';
import 'package:aitrainer_app/widgets/dialog_html.dart';
import 'package:aitrainer_app/widgets/dialog_premium.dart';
import 'package:badges/badges.dart';
import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/widgets/app_bar.dart';
@ -77,13 +79,43 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
onTap: () => this.callBackExerciseLog(exerciseRepository, customerRepository),
isLocked: false,
)),
ImageButton(
Badge(
elevation: 0,
padding: EdgeInsets.all(0),
position: BadgePosition.topStart(top: -12, start: -12),
animationDuration: Duration(milliseconds: 1500),
animationType: BadgeAnimationType.fade,
badgeColor: Colors.transparent,
showBadge: Cache().hasPurchased,
badgeContent: IconButton(
iconSize: 36,
onPressed: () => showDialog(
context: context,
builder: (BuildContext context) {
return DialogCommon(
title: t("Premium function"),
descriptions: Cache().canTrial()
? t("This is a premium function, you can reach it outside of the trial period only with a valid subscription")
: t("This is a premium function, you can reach it only with a valid subscription"),
onCancel: () => Navigator.of(context).pop(),
onTap: () => Navigator.of(context).pop(),
text: '',
);
}),
icon: Icon(
Icons.star,
color: Colors.orange[600],
)),
child: ImageButton(
width: imageWidth,
textAlignment: Alignment.topLeft,
text: t("My Whole Body Development"),
style: GoogleFonts.robotoMono(
textStyle: TextStyle(
fontSize: 14, color: Colors.white, fontWeight: FontWeight.bold, backgroundColor: Colors.black54.withOpacity(0.4)),
fontSize: 14,
color: Colors.white,
fontWeight: FontWeight.bold,
backgroundColor: Colors.black54.withOpacity(0.4)),
),
image: "asset/image/testemfejl400x400.jpg",
left: 5,
@ -114,8 +146,35 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
}
},
isLocked: true,
),
)),
Badge(
elevation: 0,
padding: EdgeInsets.all(0),
position: BadgePosition.topStart(top: -12, start: -12),
animationDuration: Duration(milliseconds: 1500),
animationType: BadgeAnimationType.fade,
badgeColor: Colors.transparent,
showBadge: Cache().hasPurchased,
badgeContent: IconButton(
iconSize: 36,
onPressed: () => showDialog(
context: context,
builder: (BuildContext context) {
return DialogCommon(
title: t("Premium function"),
descriptions: Cache().canTrial()
? t("This is a premium function, you can reach it outside of the trial period only with a valid subscription")
: t("This is a premium function, you can reach it only with a valid subscription"),
onCancel: () => Navigator.of(context).pop(),
onTap: () => Navigator.of(context).pop(),
text: '',
);
}),
icon: Icon(
Icons.star,
color: Colors.orange[600],
)),
child: Badge(
padding: EdgeInsets.all(8),
position: BadgePosition.topEnd(top: -5, end: -3),
animationDuration: Duration(milliseconds: 500),
@ -141,8 +200,35 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
left: 5,
onTap: () => {Navigator.of(context).pushNamed('mydevelopmentMusclePage', arguments: args)},
isLocked: true,
))),
Badge(
elevation: 0,
padding: EdgeInsets.all(0),
position: BadgePosition.topStart(top: -12, start: -12),
animationDuration: Duration(milliseconds: 1500),
animationType: BadgeAnimationType.fade,
badgeColor: Colors.transparent,
showBadge: Cache().hasPurchased,
badgeContent: IconButton(
iconSize: 36,
onPressed: () => showDialog(
context: context,
builder: (BuildContext context) {
return DialogCommon(
title: t("Premium function"),
descriptions: Cache().canTrial()
? t("This is a premium function, you can reach it outside of the trial period only with a valid subscription")
: t("This is a premium function, you can reach it only with a valid subscription"),
onCancel: () => Navigator.of(context).pop(),
onTap: () => Navigator.of(context).pop(),
text: '',
);
}),
icon: Icon(
Icons.star,
color: Colors.orange[600],
)),
ImageButton(
child: ImageButton(
width: imageWidth,
left: 5,
textAlignment: Alignment.topLeft,
@ -172,7 +258,8 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
}
},
isLocked: true,
),
)),
//developmentWidget(imageWidth, "Development Size", "asset/image/predictions.jpg", TrackingEvent.my_size_development, args),
hiddenWidget(customerRepository, exerciseRepository),
]),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
@ -186,6 +273,41 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
bottomNavigationBar: BottomNavigator(bottomNavIndex: 1));
}
Widget developmentWidget(double imageWidth, String title, String imageUrl, TrackingEvent trackingEvent, LinkedHashMap args) {
return ImageButton(
width: imageWidth,
left: 5,
textAlignment: Alignment.topLeft,
text: t(title),
style: GoogleFonts.robotoMono(
textStyle:
TextStyle(fontSize: 14, color: Colors.white, fontWeight: FontWeight.bold, backgroundColor: Colors.black54.withOpacity(0.4))),
image: imageUrl,
onTap: () => {
if (Cache().userLoggedIn != null)
{
Track().track(trackingEvent),
SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft]),
Future.delayed(Duration(seconds: 400)),
Navigator.of(context).pushNamed('mydevelopmentSizesPage', arguments: args),
/* showDialog(
context: context,
builder: (BuildContext context) {
return DialogPremium(
unlocked: Cache().hasPurchased,
unlockRound: 12,
function: "Predictions",
unlockedText: null,
onTap: () => {Navigator.of(context).pop()},
);
}) */
}
},
isLocked: true,
);
}
Widget hiddenWidget(CustomerRepository customerRepository, ExerciseRepository exerciseRepository) {
final LinkedHashMap args = LinkedHashMap();
if (Cache().getTrainee() != null) {

View File

@ -15,6 +15,7 @@ import 'package:aitrainer_app/widgets/dialog_common.dart';
import 'package:aitrainer_app/widgets/dialog_premium.dart';
import 'package:aitrainer_app/widgets/menu_image.dart';
import 'package:aitrainer_app/widgets/treeview_parent_widget.dart';
import 'package:badges/badges.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@ -186,8 +187,36 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
listWidget.add(explanation);
plans.forEach((element) {
bool restricted = (!element.free);
listWidget.add(Container(
margin: const EdgeInsets.only(left: 4.0),
child: Badge(
elevation: 0,
padding: EdgeInsets.all(0),
position: BadgePosition.topStart(top: -15, start: -18),
animationDuration: Duration(milliseconds: 1500),
animationType: BadgeAnimationType.fade,
badgeColor: Colors.transparent,
showBadge: restricted,
badgeContent: IconButton(
iconSize: 36,
onPressed: () => showDialog(
context: context,
builder: (BuildContext context) {
return DialogCommon(
title: t("Premium function"),
descriptions: Cache().canTrial()
? t("This is a premium function, you can reach it outside of the trial period only with a valid subscription")
: t("This is a premium function, you can reach it only with a valid subscription"),
onCancel: () => Navigator.of(context).pop(),
onTap: () => Navigator.of(context).pop(),
text: '',
);
}),
icon: Icon(
Icons.star,
color: Colors.orange[400],
)),
child: TreeViewChild(
startExpanded: false,
parent: TreeviewParentWidget(
@ -199,7 +228,7 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
color: Colors.blue[800],
),
children: _getDays(element, bloc),
)));
))));
});
return listWidget;

View File

@ -21,7 +21,6 @@ class TrainingPlanExercise extends StatelessWidget with Trans {
final CustomerTrainingPlanDetails detail = args['customerTrainingPlanDetails'];
// ignore: close_sinks
final TrainingPlanBloc bloc = BlocProvider.of<TrainingPlanBloc>(context);
final bool isDropSet = detail.weight == -3;
setContext(context);
return Scaffold(
appBar: AppBarNav(depth: 1),
@ -98,7 +97,9 @@ class TrainingPlanExercise extends StatelessWidget with Trans {
repeats: detail.repeats == -1 ? 99 : detail.repeats,
set: detail.set,
exerciseNr: detail.exercises.length + 1,
onUnitQuantityChanged: (value) => bloc.add(TrainingPlanWeightChange(weight: value, detail: detail)),
onUnitQuantityChanged: (value) => bloc.add(TrainingPlanWeightChangeRecalculate(weight: value, detail: detail)),
onUnitQuantityChangeUp: () => bloc.add(TrainingPlanWeightChangeUp(detail: detail)),
onUnitQuantityChangeDown: () => bloc.add(TrainingPlanWeightChangeDown(detail: detail)),
onQuantityChanged: (value) => bloc.add(TrainingPlanRepeatsChange(repeats: value.toInt(), detail: detail)),
exerciseTypeId: detail.exerciseType!.exerciseTypeId,
originalQuantity: originalQuantity,

View File

@ -16,6 +16,24 @@ import 'package:stop_watch_timer/stop_watch_timer.dart';
import 'package:wakelock/wakelock.dart';
import 'dialog_html.dart';
class ExerciseSaveStream {
static final ExerciseSaveStream _singleton = ExerciseSaveStream._internal();
final StreamController<bool> streamController = StreamController<bool>.broadcast();
int repeats = 0;
double weight = 0;
Stream get stream => streamController.stream;
StreamController getStreamController() => streamController;
factory ExerciseSaveStream() => _singleton;
ExerciseSaveStream._internal();
void dispose() {
streamController.close();
}
}
enum Explanations { intro, introBold, explanationWeight, explanationRepeats, explanationButton, explanationButtonExt }
extension ExplanationsExt on Explanations {
@ -112,6 +130,8 @@ class ExplanationExt {
class ExerciseSave extends StatefulWidget {
final ValueChanged<double> onQuantityChanged;
final ValueChanged<double>? onUnitQuantityChanged;
final VoidCallback? onUnitQuantityChangeUp;
final VoidCallback? onUnitQuantityChangeDown;
final VoidCallback? onSubmit;
final bool hasUnitQuantity;
final String? unitQuantityUnit;
@ -131,6 +151,8 @@ class ExerciseSave extends StatefulWidget {
ExerciseSave(
{required this.onQuantityChanged,
this.onUnitQuantityChanged,
this.onUnitQuantityChangeUp,
this.onUnitQuantityChangeDown,
this.onSubmit,
required this.hasUnitQuantity,
this.unitQuantityUnit,
@ -158,6 +180,9 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
final StopWatchTimer stopWatchTimer = StopWatchTimer(
isLapHours: false,
);
final Stream stream = ExerciseSaveStream().stream;
late StreamSubscription<dynamic> subscription;
bool changable = false;
@override
Widget build(BuildContext context) {
@ -188,16 +213,24 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
}
SchedulerBinding.instance!.addPostFrameCallback((_) {
subscription = stream.listen((event) {
_controller1.text = ExerciseSaveStream().weight.toStringAsFixed(0);
_controller2.text = ExerciseSaveStream().repeats.toStringAsFixed(0);
});
print("ExerciseSave weight ${widget.weight}");
_controller1.text = widget.weight == null || widget.weight == -1
? "--"
? "TEST"
: widget.weight! % widget.weight!.round() == 0
? widget.weight!.toStringAsFixed(0)
: widget.weight!.toStringAsFixed(1);
_controller2.text = widget.repeats == null
? "--"
? "TEST"
: widget.repeats! == 99
? "MAX"
: widget.weight == -1 || widget.weight == -2
? "TEST"
: widget.repeats!.toStringAsFixed(0);
changable = (_controller2.text != "TEST" && _controller1.text != "TEST");
if (widget.unitQuantityUnit != null && widget.tip != null && Cache().isActivityDone(widget.tip!) == false) {
Timer(
Duration(milliseconds: 2000),
@ -220,9 +253,16 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
dispose() {
_controller1.dispose();
stopWatchTimer.dispose();
subscription.cancel();
super.dispose();
}
void isChangable() {
changable = !(widget.weight == -1 || widget.weight == -2 || widget.weight == null);
}
KeyboardActionsConfig _buildConfig(BuildContext context) {
return KeyboardActionsConfig(
keyboardActionsPlatform: KeyboardActionsPlatform.ALL,
@ -507,14 +547,20 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
}
Widget columnQuantityUnit() {
//changable = (_controller2.text != "TEST" && _controller1.text != "TEST");
isChangable();
changable = false;
//print("PlusMinus: $changable - con2: ${_controller2.text} con1: ${_controller1.text}");
Widget row = Padding(padding: const EdgeInsets.only(top: 10, left: 55, right: 55), child: Column());
if (widget.hasUnitQuantity) {
row = Padding(
padding: const EdgeInsets.only(top: 10, left: 55, right: 55),
child: Column(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [
TextFormField(
child: Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [
Flexible(
child: TextFormField(
focusNode: _nodeText1,
controller: _controller1,
maxLength: 5,
decoration: InputDecoration(
contentPadding: EdgeInsets.only(left: 25, top: 5, bottom: 5),
labelText: t(widget.unitQuantityUnit!),
@ -529,14 +575,26 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
),
keyboardType: TextInputType.numberWithOptions(decimal: true),
textInputAction: TextInputAction.done,
style: GoogleFonts.archivoBlack(fontSize: 80, color: Colors.yellow[300]),
style: GoogleFonts.archivoBlack(fontSize: 75, color: Colors.yellow[300]),
onChanged: (value) {
if (value.isNotEmpty) {
value = value.replaceFirst(",", ".");
value = value.replaceAll(RegExp(r'[^0-9.]'), "");
widget.onUnitQuantityChanged!(double.parse(value));
}
}),
})),
changable
? Column(children: [
IconButton(
onPressed: () => widget.onUnitQuantityChangeUp!(),
icon: Icon(CustomIcon.plus_circle, color: Colors.orange, size: 20),
),
IconButton(
onPressed: () => widget.onUnitQuantityChangeDown!(),
icon: Icon(CustomIcon.minus_circle, color: Colors.orange, size: 20),
),
])
: Offstage()
]));
}
return row;
@ -646,7 +704,7 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
),
keyboardType: TextInputType.number,
textInputAction: TextInputAction.next,
style: GoogleFonts.archivoBlack(fontSize: 80, color: Colors.orange[200]),
style: GoogleFonts.archivoBlack(fontSize: 75, color: Colors.orange[200]),
onChanged: (value) {
if (value.isNotEmpty) {
value = value.replaceFirst(",", ".");

View File

@ -1188,13 +1188,27 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
syncfusion_flutter_calendar:
dependency: "direct main"
description:
name: syncfusion_flutter_calendar
url: "https://pub.dartlang.org"
source: hosted
version: "19.2.60"
syncfusion_flutter_charts:
dependency: "direct main"
description:
name: syncfusion_flutter_charts
url: "https://pub.dartlang.org"
source: hosted
version: "19.2.60"
syncfusion_flutter_core:
dependency: transitive
description:
name: syncfusion_flutter_core
url: "https://pub.dartlang.org"
source: hosted
version: "19.1.64"
version: "19.2.60"
syncfusion_flutter_datagrid:
dependency: "direct main"
description:
@ -1202,13 +1216,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "19.1.64-beta"
syncfusion_flutter_datepicker:
dependency: transitive
description:
name: syncfusion_flutter_datepicker
url: "https://pub.dartlang.org"
source: hosted
version: "19.2.60"
syncfusion_flutter_gauges:
dependency: "direct main"
description:
name: syncfusion_flutter_gauges
url: "https://pub.dartlang.org"
source: hosted
version: "19.1.63"
version: "19.2.60"
synchronized:
dependency: transitive
description:
@ -1251,6 +1272,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
timezone:
dependency: transitive
description:
name: timezone
url: "https://pub.dartlang.org"
source: hosted
version: "0.7.0"
timing:
dependency: transitive
description:

View File

@ -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.23+95
version: 1.1.23+98
environment:
sdk: ">=2.12.0 <3.0.0"
@ -69,8 +69,10 @@ dependencies:
firebase_dynamic_links: ^2.0.8
firebase_in_app_messaging: ^0.5.0+8
syncfusion_flutter_gauges: ^19.1.63
syncfusion_flutter_gauges: ^19.2.60
syncfusion_flutter_datagrid: ^19.1.63
syncfusion_flutter_charts: ^19.2.60
syncfusion_flutter_calendar: ^19.2.60
flutter_facebook_auth: ^3.5.1
google_sign_in: ^5.0.3