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.", "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", "No selected Training Plan": "No selected Training Plan",
"Min. 10 minutes": "Min. 10 minutes", "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.", "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", "No selected Training Plan": "Nincs kiválasztott edzésterved",
"Min. 10 minutes": "Minimum 10 perc", "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; 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 = 2; CURRENT_PROJECT_VERSION = 5;
DEVELOPMENT_TEAM = SFJJBDCU6Z; DEVELOPMENT_TEAM = SFJJBDCU6Z;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
@ -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 = 2; CURRENT_PROJECT_VERSION = 5;
DEVELOPMENT_TEAM = SFJJBDCU6Z; DEVELOPMENT_TEAM = SFJJBDCU6Z;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
@ -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 = 2; CURRENT_PROJECT_VERSION = 5;
DEVELOPMENT_TEAM = SFJJBDCU6Z; DEVELOPMENT_TEAM = SFJJBDCU6Z;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (

View File

@ -11,7 +11,7 @@
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>WorkoutTest</string> <string>Workout Test</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <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/common.dart';
import 'package:aitrainer_app/util/enums.dart'; import 'package:aitrainer_app/util/enums.dart';
import 'package:aitrainer_app/util/track.dart'; import 'package:aitrainer_app/util/track.dart';
import 'package:aitrainer_app/widgets/exercise_save.dart';
import 'package:bloc/bloc.dart'; import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -74,15 +75,54 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
yield TrainingPlanExerciseLoading(); yield TrainingPlanExerciseLoading();
event.detail.weight = event.weight; 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 TrainingPlanExerciseReady();
yield TrainingPlanReady(); yield TrainingPlanReady();
} else if (event is TrainingPlanWeightChangeRecalculate) { } else if (event is TrainingPlanWeightChangeRecalculate) {
yield TrainingPlanExerciseLoading(); 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 = event.detail.repeats =
Common.reCalculateRepeatsByChangedWeight(event.detail.weight!, event.detail.repeats!.toDouble(), event.weight); 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(); yield TrainingPlanReady();
} else if (event is TrainingPlanRepeatsChange) { } else if (event is TrainingPlanRepeatsChange) {
yield TrainingPlanExerciseLoading(); yield TrainingPlanExerciseLoading();
@ -102,6 +142,7 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
yield TrainingPlanReady(); yield TrainingPlanReady();
throw Exception("Please type your repeats!"); throw Exception("Please type your repeats!");
} }
print("ExerciseTypeUID: ${event.detail.exerciseTypeId}");
if (event.detail.weight == -3) { if (event.detail.weight == -3) {
print("DropSet"); print("DropSet");
event.detail.state = ExercisePlanDetailState.finished; 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 // recalculate the weight to the original planned repeats for the next details
if (exercise.unitQuantity != null && exercise.unitQuantity! > 0) { if (exercise.unitQuantity != null && exercise.unitQuantity! > 0) {
for (var nextDetail in _myPlan!.details) { for (var nextDetail in _myPlan!.details) {
print("NextDetail detail: $nextDetail");
double weightFromPlan = trainingPlanRepository.getOriginalWeight(this.getMyPlan()!.trainingPlanId!, nextDetail); double weightFromPlan = trainingPlanRepository.getOriginalWeight(this.getMyPlan()!.trainingPlanId!, nextDetail);
print("NextDetail detail: $nextDetail *** PlanWeight: $weightFromPlan");
if (nextDetail.exerciseTypeId == event.detail.exerciseTypeId && if (nextDetail.exerciseTypeId == event.detail.exerciseTypeId &&
nextDetail.weight == -2 && nextDetail.weight == -2 &&
nextDetail.customerTrainingPlanDetailsId != event.detail.customerTrainingPlanDetailsId) { 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) { } else if (nextDetail.exerciseTypeId == event.detail.exerciseTypeId && nextDetail.weight == -1 && nextDetail.set! == 1) {
print("recalculating -1, set 1 ${event.detail.customerTrainingPlanDetailsId}"); print("recalculating -1, set 1 ${event.detail.customerTrainingPlanDetailsId}");
nextDetail = trainingPlanRepository.recalculateDetailFixRepeatsSet1(_myPlan!.trainingPlanId!, nextDetail, event.detail); 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]; 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 { class TrainingPlanWeightChangeRecalculate extends TrainingPlanEvent {
final CustomerTrainingPlanDetails detail; final CustomerTrainingPlanDetails detail;
final double weight; final double weight;

View File

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

View File

@ -179,11 +179,11 @@ mixin Common {
if (weight > 35) { if (weight > 35) {
final double remainder = weight % 5; final double remainder = weight % 5;
if (remainder < 1.25) { if (remainder < 1) {
rounded = ((weight / 5).floor() * 5).toDouble(); 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; 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; rounded = (weight / 5).floor() * 5 + 2.5;
} else { } else {
rounded = (((weight / 5).ceil() * 5) + 5).toDouble(); 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/exercise_control/exercise_control_bloc.dart';
import 'package:aitrainer_app/bloc/timer/timer_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/library/custom_icon_icons.dart';
import 'package:aitrainer_app/util/app_language.dart'; import 'package:aitrainer_app/util/app_language.dart';
import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/cache.dart';

View File

@ -2,7 +2,9 @@ import 'dart:collection';
import 'package:aitrainer_app/bloc/exercise_log/exercise_log_bloc.dart'; import 'package:aitrainer_app/bloc/exercise_log/exercise_log_bloc.dart';
import 'package:aitrainer_app/widgets/app_bar.dart'; import 'package:aitrainer_app/widgets/app_bar.dart';
import 'package:aitrainer_app/widgets/bottom_nav.dart'; import 'package:aitrainer_app/widgets/bottom_nav.dart';
import 'package:aitrainer_app/widgets/dialog_common.dart';
import 'package:aitrainer_app/widgets/dialog_premium.dart'; import 'package:aitrainer_app/widgets/dialog_premium.dart';
import 'package:badges/badges.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
@ -193,16 +195,72 @@ class ExerciseLogPage extends StatelessWidget with Trans, Common {
)), )),
GestureDetector( GestureDetector(
onTap: () => evaluation(exerciseRepository, exercise), 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( child: Image.asset(
"asset/image/kupa.png", "asset/image/kupa.png",
width: 35, 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), icon: Icon(Icons.delete, color: Colors.black12),
onPressed: () { onPressed: () {
confirmationDialog(exerciseLogBloc, exercise); 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/enums.dart';
import 'package:aitrainer_app/util/track.dart'; import 'package:aitrainer_app/util/track.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/dialog_premium.dart'; import 'package:aitrainer_app/widgets/dialog_premium.dart';
import 'package:badges/badges.dart'; import 'package:badges/badges.dart';
import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.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';
@ -77,13 +79,43 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
onTap: () => this.callBackExerciseLog(exerciseRepository, customerRepository), onTap: () => this.callBackExerciseLog(exerciseRepository, customerRepository),
isLocked: false, 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, width: imageWidth,
textAlignment: Alignment.topLeft, textAlignment: Alignment.topLeft,
text: t("My Whole Body Development"), text: t("My Whole Body Development"),
style: GoogleFonts.robotoMono( style: GoogleFonts.robotoMono(
textStyle: TextStyle( 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", image: "asset/image/testemfejl400x400.jpg",
left: 5, left: 5,
@ -114,8 +146,35 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
} }
}, },
isLocked: true, isLocked: true,
), )),
Badge( 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), padding: EdgeInsets.all(8),
position: BadgePosition.topEnd(top: -5, end: -3), position: BadgePosition.topEnd(top: -5, end: -3),
animationDuration: Duration(milliseconds: 500), animationDuration: Duration(milliseconds: 500),
@ -141,8 +200,35 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
left: 5, left: 5,
onTap: () => {Navigator.of(context).pushNamed('mydevelopmentMusclePage', arguments: args)}, onTap: () => {Navigator.of(context).pushNamed('mydevelopmentMusclePage', arguments: args)},
isLocked: true, 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, width: imageWidth,
left: 5, left: 5,
textAlignment: Alignment.topLeft, textAlignment: Alignment.topLeft,
@ -172,7 +258,8 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
} }
}, },
isLocked: true, isLocked: true,
), )),
//developmentWidget(imageWidth, "Development Size", "asset/image/predictions.jpg", TrackingEvent.my_size_development, args),
hiddenWidget(customerRepository, exerciseRepository), hiddenWidget(customerRepository, exerciseRepository),
]), ]),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
@ -186,6 +273,41 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
bottomNavigationBar: BottomNavigator(bottomNavIndex: 1)); 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) { Widget hiddenWidget(CustomerRepository customerRepository, ExerciseRepository exerciseRepository) {
final LinkedHashMap args = LinkedHashMap(); final LinkedHashMap args = LinkedHashMap();
if (Cache().getTrainee() != null) { 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/dialog_premium.dart';
import 'package:aitrainer_app/widgets/menu_image.dart'; import 'package:aitrainer_app/widgets/menu_image.dart';
import 'package:aitrainer_app/widgets/treeview_parent_widget.dart'; import 'package:aitrainer_app/widgets/treeview_parent_widget.dart';
import 'package:badges/badges.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
@ -186,8 +187,36 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
listWidget.add(explanation); listWidget.add(explanation);
plans.forEach((element) { plans.forEach((element) {
bool restricted = (!element.free);
listWidget.add(Container( listWidget.add(Container(
margin: const EdgeInsets.only(left: 4.0), 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( child: TreeViewChild(
startExpanded: false, startExpanded: false,
parent: TreeviewParentWidget( parent: TreeviewParentWidget(
@ -199,7 +228,7 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
color: Colors.blue[800], color: Colors.blue[800],
), ),
children: _getDays(element, bloc), children: _getDays(element, bloc),
))); ))));
}); });
return listWidget; return listWidget;

View File

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

View File

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

View File

@ -1188,13 +1188,27 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0" 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: syncfusion_flutter_core:
dependency: transitive dependency: transitive
description: description:
name: syncfusion_flutter_core name: syncfusion_flutter_core
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "19.1.64" version: "19.2.60"
syncfusion_flutter_datagrid: syncfusion_flutter_datagrid:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1202,13 +1216,20 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "19.1.64-beta" 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: syncfusion_flutter_gauges:
dependency: "direct main" dependency: "direct main"
description: description:
name: syncfusion_flutter_gauges name: syncfusion_flutter_gauges
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "19.1.63" version: "19.2.60"
synchronized: synchronized:
dependency: transitive dependency: transitive
description: description:
@ -1251,6 +1272,13 @@ 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:

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