WT 1.1.0+35 Design, Menü filter, Test Server

This commit is contained in:
bossanyit 2020-12-08 17:05:55 +01:00
parent f5f4ade9d5
commit 85ce68a9b8
26 changed files with 821 additions and 256 deletions

View File

@ -228,5 +228,12 @@
"select your equipments by tapping":"select your equipments by tapping",
"Available Equipments":"Available Equipments",
"select your places by tapping":"select your places by tapping",
"Available Training Places":"Available Training Places"
"Available Training Places":"Available Training Places",
"Please take a relative bigger weight and repeat 12-30 times":"Please take a relative bigger weight and repeat 12-30 times",
"Please take a medium weight and repeat 20-30 times":"Please take a medium weight and repeat 20-30 times",
"Equipment Filter":"Equipment Filter",
"Live-Server":"Live-Server",
"Test-Server":"Test-Server",
"All Exercises has been filtered out":"All Exercises has been filtered out",
"base":"base"
}

View File

@ -229,5 +229,12 @@
"select your equipments by tapping":"válaszd ki az eszközeidet, kattints a képre",
"Available Equipments":"Elérhető eszközök",
"select your places by tapping":"kattints az edzéshelyszínre",
"Available Training Places":"Elérhető edzéshelyszínek"
"Available Training Places":"Elérhető edzéshelyszínek",
"Please take a relative bigger weight and repeat 12-20 times":"Vegyél egy relatív nagyobb súlyt és végezz el 12-20 ismétlést",
"Please take a medium weight and repeat 20-30 times": "Vegyél egy közepes súlyt és végezz el 20-30 ismétlést",
"Equipment Filter":"Eszköz szűrő",
"Live-Server":"Live-Server",
"Test-Server":"Test-Server",
"All Exercises has been filtered out":"Az összes gyakorlatot kiszűrted",
"base":"alap"
}

View File

@ -9,12 +9,12 @@ PODS:
- Firebase/Messaging (6.33.0):
- Firebase/CoreOnly
- FirebaseMessaging (~> 4.7.0)
- firebase_auth (0.18.3):
- firebase_auth (0.18.3-1):
- Firebase/Auth (~> 6.33.0)
- Firebase/CoreOnly (~> 6.33.0)
- firebase_core
- Flutter
- firebase_core (0.5.2):
- firebase_core (0.5.2-1):
- Firebase/CoreOnly (~> 6.33.0)
- Flutter
- firebase_messaging (7.0.3):
@ -154,8 +154,8 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
devicelocale: feebbe5e7a30adb8c4f83185de1b50ff19b44f00
Firebase: 8db6f2d1b2c5e2984efba4949a145875a8f65fe5
firebase_auth: 240419f6b00dea39c60a2a9c4379c16c4a4b02fb
firebase_core: 350ba329d1641211bc6183a3236893cafdacfea7
firebase_auth: cb33b01b51904969161403bbcb20036519f0c578
firebase_core: 7423d688a1c6f2f2d859d64ae26991be39989781
firebase_messaging: 0aea2cd5885b65e19ede58ee3507f485c992cc75
FirebaseAuth: c92d49ada7948d1a23466e3db17bc4c2039dddc3
FirebaseCore: d889d9e12535b7f36ac8bfbf1713a0836a3012cd

View File

@ -362,7 +362,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 34;
CURRENT_PROJECT_VERSION = 36;
DEVELOPMENT_TEAM = SFJJBDCU6Z;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@ -505,7 +505,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 34;
CURRENT_PROJECT_VERSION = 36;
DEVELOPMENT_TEAM = SFJJBDCU6Z;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@ -540,7 +540,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 34;
CURRENT_PROJECT_VERSION = 36;
DEVELOPMENT_TEAM = SFJJBDCU6Z;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (

View File

@ -1,7 +1,9 @@
import 'dart:async';
import 'dart:collection';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/workout_menu_tree.dart';
import 'package:aitrainer_app/repository/exercise_device_repository.dart';
import 'package:aitrainer_app/repository/exercise_repository.dart';
import 'package:aitrainer_app/repository/workout_tree_repository.dart';
import 'package:aitrainer_app/util/trans.dart';
@ -13,11 +15,15 @@ import 'package:meta/meta.dart';
part 'menu_event.dart';
part 'menu_state.dart';
enum ExerciseAbility { oneRepMax, endurance, none }
class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans {
final WorkoutTreeRepository menuTreeRepository;
final ExerciseRepository exerciseRepository = ExerciseRepository();
ExerciseDeviceRepository exerciseDeviceRepository = ExerciseDeviceRepository();
int parent;
WorkoutMenuTree workoutItem;
List<int> listFilterDevice = List();
String infoTitle = "";
String infoText = "";
@ -29,41 +35,47 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans {
BuildContext context;
ExerciseAbility ability;
MenuBloc({this.menuTreeRepository}) : super(MenuInitial()) {
parent = 0;
}
void setMenuInfo() {
double percent = Cache().getPercentExercises();
if ( percent == -1 ) {
if (percent == -1) {
exerciseRepository.getBaseExerciseFinishedPercent();
percent = Cache().getPercentExercises();
}
if ( context == null ) return;
if (context == null) return;
percent = percent * 100;
print("Percent " + percent.toString());
if ( percent == -1 || percent == 0) {
if (percent == -1 || percent == 0) {
infoTitle = t("Greetings!");
infoText = t("The purpose is to measure you physical condition") + " " + t("The suggested order of the exercises: chest - biceps - triceps - back - shoulders - core - tigh - calf.");
infoText = t("The purpose is to measure you physical condition") +
" " +
t("The suggested order of the exercises: chest - biceps - triceps - back - shoulders - core - tigh - calf.");
infoText2 = t("I suggest begin your tests with a");
infoText3 = t("Go to the menu Strength - One Rep Max - Chest, and select your favourite exercise.");
infoLink = t("Bring me there");
} else if ( percent > 0 && percent < 20) {
} else if (percent > 0 && percent < 20) {
infoTitle = t("Nice! This is a good start");
} else if ( percent > 20 && percent < 40) {
} else if (percent > 20 && percent < 40) {
infoTitle = t("Go on!") + " " + t("You are on track");
} else if ( percent > 60 && percent < 80) {
} else if (percent > 60 && percent < 80) {
infoTitle = t("Persistence!") + " " + t("Not so much left");
} else if ( percent > 80 && percent < 100) {
} else if (percent > 80 && percent < 100) {
infoTitle = t("Almost!") + " " + t("You have only 1-2 exercise left to finish!");
}
menuTreeRepository.sortByMuscleType();
missingTreeName = exerciseRepository.nextMissingBaseExercise(menuTreeRepository.sortedTree);
print("Missing " + missingTreeName);
if ( percent > 0) {
infoText = t("Please continue your tests with a") + " '" + missingTreeName + "' " + t("exercise!");
infoLink = t("Bring me there");
//print("Missing " + missingTreeName);
if (missingTreeName != null) {
if (percent > 0) {
infoText = t("Please continue your tests with a") + " '" + missingTreeName + "' " + t("exercise!");
infoLink = t("Bring me there");
}
}
}
@ -76,10 +88,14 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans {
MenuEvent event,
) async* {
try {
if ( event is MenuCreate ) {
if (event is MenuCreate) {
yield MenuLoading();
await menuTreeRepository.createTree();
//await menuTreeRepository.createTree();
setMenuInfo();
exerciseDeviceRepository.setDevices(Cache().getDevices());
exerciseDeviceRepository.getGymDevices().forEach((element) {
listFilterDevice.add(element.exerciseDeviceId);
});
yield MenuReady();
} else if (event is MenuRecreateTree) {
// ie. at language changes
@ -90,6 +106,7 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans {
yield MenuLoading();
parent = event.parent;
workoutItem = event.item;
setAbility(workoutItem.nameEnglish);
//print("menuitem " + workoutItem.id.toString() + " parent "+workoutItem.parent.toString());
menuTreeRepository.getBranch(event.parent);
yield MenuReady();
@ -98,27 +115,84 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans {
// get parent menus or exercises
parent = event.parent;
workoutItem = menuTreeRepository.getParentItem(parent);
if ( workoutItem != null) {
if (workoutItem != null) {
//print("UP menuitem " + workoutItem.id.toString() + " parent " + workoutItem.parent.toString());
menuTreeRepository.getBranch(workoutItem.parent);
setAbility(workoutItem.nameEnglish);
}
yield MenuReady();
} else if (event is MenuTreeJump) {
yield MenuLoading();
parent = event.parent;
workoutItem = menuTreeRepository.getParentItem(parent);
if ( workoutItem != null) {
if (workoutItem != null) {
//print("JUMP menuitem " + workoutItem.id.toString() + " parent " + workoutItem.parent.toString());
menuTreeRepository.getBranch(workoutItem.parent);
setAbility(workoutItem.nameEnglish);
}
yield MenuReady();
} else if (event is MenuClickExercise) {
yield MenuLoading();
// get exercise page
yield MenuReady();
} else if (event is MenuFilterExerciseType) {
yield MenuLoading();
final int deviceId = event.deviceId;
print("Defilter " + deviceId.toString());
if (selectedDevice(deviceId)) {
listFilterDevice.remove(deviceId);
} else {
listFilterDevice.add(deviceId);
}
yield MenuReady();
}
} on Exception catch(ex) {
} on Exception catch (ex) {
yield MenuError(message: ex.toString());
}
}
void setAbility(String name) {
switch (name) {
case "One Rep Max":
ability = ExerciseAbility.oneRepMax;
break;
case "Endurance":
ability = ExerciseAbility.endurance;
break;
case "Cardio":
case "Body Compositions":
ability = ExerciseAbility.none;
break;
}
print("Ability: " + ability.toString() + " name:" + name);
}
bool selectedDevice(int deviceId) {
return listFilterDevice.contains(deviceId);
}
LinkedHashMap<String, WorkoutMenuTree> getFilteredBranch(int parent) {
if (parent == null) return LinkedHashMap();
LinkedHashMap<String, WorkoutMenuTree> branch = menuTreeRepository.getBranch(parent);
if (!menuTreeRepository.isChild(parent) || ability.toString() == ExerciseAbility.none.toString()) {
return branch;
}
LinkedHashMap<String, WorkoutMenuTree> filtered = LinkedHashMap();
branch.forEach((key, value) {
final WorkoutMenuTree elem = value;
if (elem.exerciseType != null) {
for (int i = 0; i < elem.exerciseType.devices.length; i++) {
if (listFilterDevice.contains(elem.exerciseType.devices[i])) {
filtered[elem.name] = elem;
}
}
}
});
return filtered;
}
}

View File

@ -53,3 +53,7 @@ class MenuRecreateTree extends MenuEvent {
const MenuRecreateTree();
}
class MenuFilterExerciseType extends MenuEvent {
final int deviceId;
const MenuFilterExerciseType({this.deviceId});
}

View File

@ -10,6 +10,7 @@ import 'package:aitrainer_app/model/workout_menu_tree.dart';
import 'package:aitrainer_app/repository/customer_repository.dart';
import 'package:aitrainer_app/repository/exercise_repository.dart';
import 'package:aitrainer_app/service/customer_exercise_device_service.dart';
import 'package:aitrainer_app/service/exercise_device_service.dart';
import 'package:aitrainer_app/service/exercise_tree_service.dart';
import 'package:aitrainer_app/service/exercisetype_service.dart';
import 'package:aitrainer_app/util/env.dart';
@ -53,6 +54,7 @@ class Cache {
static final String isRegisteredKey = 'is_registered';
static final String isLoggedInKey = 'is_logged_in';
static final String langKey = 'lang';
static final String serverKey = 'live';
static String baseUrl = 'http://aitrainer.info:8888/api/';
static final String mediaUrl = 'https://aitrainer.info:4343/media/';
@ -88,6 +90,8 @@ class Cache {
List deviceLanguages;
String startPage;
String testEnvironment;
bool liveServer = true;
factory Cache() {
return _singleton;
@ -95,8 +99,10 @@ class Cache {
Cache._internal() {
String testEnv = EnvironmentConfig.test_env;
this.testEnvironment = testEnv;
if (testEnv == "1") {
baseUrl = 'http://aitrainer.app:8899/api/';
liveServer = false;
}
}
@ -108,6 +114,33 @@ class Cache {
return this.authToken;
}
void setServer(bool live) async {
if (this.testEnvironment == "1") {
liveServer = false;
live = false;
}
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
SharedPreferences sharedPreferences;
sharedPreferences = await prefs;
liveServer = live;
print("Set Live servier. live? " + live.toString() + " env? " + this.testEnvironment);
sharedPreferences.setBool(Cache.serverKey, live);
}
void setServerAddress(SharedPreferences prefs) {
if (this.testEnvironment == "1") {
return;
}
final bool live = prefs.getBool(Cache.serverKey);
if (live == null) {
return;
}
liveServer = live;
if (live) {
baseUrl = 'http://aitrainer.info:8888/api/';
}
}
static String getToken(SharedPreferences prefs) {
return prefs.getString(authTokenKey);
}
@ -163,27 +196,29 @@ class Cache {
ExerciseRepository exerciseRepository = ExerciseRepository();
if (type == SharePrefsChange.registration) {
Cache().startPage = "home";
Flurry.setUserId(customerId.toString());
sharedPreferences.setInt(Cache.customerIdKey, customerId);
sharedPreferences.setBool(Cache.isRegisteredKey, true);
sharedPreferences.setBool(Cache.isLoggedInKey, true);
sharedPreferences.setString(Cache.firebaseUidKey, firebaseUid);
await ExerciseTypeApi().getExerciseTypes();
await ExerciseTreeApi().getExerciseTree();
await ExerciseDeviceApi().getDevices();
final customerDevices = await CustomerExerciseDeviceApi().getDevices(customerId);
Cache().setCustomerDevices(customerDevices);
await exerciseRepository.getExercisesByCustomer(customerId);
Flurry.setUserId(customerId.toString());
} else if (type == SharePrefsChange.login) {
Flurry.setUserId(customerId.toString());
Cache().startPage = "home";
sharedPreferences.setInt(Cache.customerIdKey, customerId);
sharedPreferences.setString(Cache.firebaseUidKey, firebaseUid);
sharedPreferences.setBool(Cache.isLoggedInKey, true);
await ExerciseTypeApi().getExerciseTypes();
await ExerciseTreeApi().getExerciseTree();
await ExerciseDeviceApi().getDevices();
final customerDevices = await CustomerExerciseDeviceApi().getDevices(customerId);
Cache().setCustomerDevices(customerDevices);
await exerciseRepository.getExercisesByCustomer(customerId);
Flurry.setUserId(customerId.toString());
} else if (type == SharePrefsChange.logout) {
sharedPreferences.setBool(Cache.isLoggedInKey, false);
sharedPreferences.setInt(Cache.customerIdKey, 0);

View File

@ -7,6 +7,8 @@ class ExerciseDevice {
int sort;
bool place;
bool isGym;
ExerciseDevice.fromJson(Map json) {
this.exerciseDeviceId = json['exerciseDeviceId'];
this.name = json['name'];

View File

@ -6,15 +6,38 @@ class ExerciseTree {
bool active;
String nameTranslation;
ExerciseTree();
ExerciseTree.fromJson(Map json) {
this.treeId = json['treeId'];
this.name = json['name'];
this.parentId = json['parentId'];
this.parentId = -1;
this.imageUrl = json['imageUrl'];
this.active = json['active'];
this.nameTranslation =
json['translations'] != null && (json['translations']).length > 0
? json['translations'][0]['name']
: this.name;
this.nameTranslation = json['translations'] != null && (json['translations']).length > 0 ? json['translations'][0]['name'] : this.name;
}
Map<String, dynamic> toJson() {
return {
"treeId": treeId,
"parentId": parentId,
"name": name,
"imageUrl": imageUrl,
"active": active.toString(),
"nameTranslation": nameTranslation,
};
}
ExerciseTree copy(int parentId) {
ExerciseTree newTree = ExerciseTree();
newTree.treeId = this.treeId;
newTree.name = this.name;
newTree.imageUrl = this.imageUrl;
newTree.nameTranslation = this.nameTranslation;
if (parentId != -1) {
newTree.parentId = parentId;
}
return newTree;
}
}

View File

@ -0,0 +1,11 @@
class ExerciseTreeParents {
int exerciseTreeParentsId;
int exerciseTreeParentId;
int exerciseTreeChildId;
ExerciseTreeParents.fromJson(Map json) {
this.exerciseTreeParentsId = json['exerciseTreeParentsId'];
this.exerciseTreeParentId = json['exerciseTreeParentId'];
this.exerciseTreeChildId = json['exerciseTreeChildId'];
}
}

View File

@ -2,7 +2,7 @@ import 'package:flutter/services.dart';
class ExerciseType {
int exerciseTypeId;
int treeId;
//int treeId;
String name;
String description;
BinaryCodec video;
@ -11,17 +11,20 @@ class ExerciseType {
String unitQuantityUnit;
bool active;
bool base;
String imageUrl;
String nameTranslation;
String descriptionTranslation;
String imageUrl = "";
String nameTranslation = "";
String descriptionTranslation = "";
List<int> devices = List();
List<int> parents = List();
bool is1RM;
bool isEndurance;
ExerciseType({this.name, this.description});
ExerciseType.fromJson(Map json) {
this.exerciseTypeId = json['exerciseTypeId'];
this.treeId = json['treeId'];
//this.treeId = json['treeId'];
this.name = json['name'];
this.description = json['description'];
this.unit = json['unit'];
@ -29,19 +32,42 @@ class ExerciseType {
this.unitQuantityUnit = json['unitQuantityUnit'];
this.active = json['active'];
this.base = json['base'];
this.imageUrl = json['images'][0]['url'];
this.nameTranslation = json['translations'][0]['name'];
this.descriptionTranslation = json['translations'][0]['description'];
if (json['images'].length > 0) {
this.imageUrl = json['images'][0]['url'];
}
if (json['translations'].length > 0) {
this.nameTranslation = json['translations'][0]['name'];
this.descriptionTranslation = json['translations'][0]['description'];
}
if (json['devices'].length > 0) {
final List jsonDevices = json['devices'];
jsonDevices.forEach((device) {
this.devices.add(device['exerciseDeviceId']);
});
}
if (json['parents'].length > 0) {
final List jsonParents = json['parents'];
jsonParents.forEach((parent) {
this.parents.add(parent['exerciseTreeId']);
});
}
;
}
Map<String, dynamic> toJson() =>
{
Map<String, dynamic> toJson() => {
"name": name,
"description": description,
"unit": unit,
"unitQuantity": unitQuantity,
"unitQuantityUnit": unitQuantityUnit,
"active": active
"active": active,
"devices": this.devices.toString(),
"nameTranslation": this.nameTranslation,
"parents": this.parents.toString()
};
void set1RM(bool is1RM) {
@ -51,4 +77,12 @@ class ExerciseType {
bool get1RM() {
return this.is1RM;
}
}
void setEndurance(bool isEndurance) {
this.isEndurance = isEndurance;
}
bool getEndurance() {
return this.isEndurance;
}
}

View File

@ -0,0 +1,11 @@
class ExerciseTypeDevice {
int exerciseTypeDeviceId;
int exerciseDeviceId;
ExerciseTypeDevice();
ExerciseTypeDevice.fromJson(Map json) {
this.exerciseTypeDeviceId = json['exerciseTypeDeviceId'];
this.exerciseDeviceId = json['exerciseDeviceId'];
}
}

View File

@ -15,13 +15,14 @@ class WorkoutMenuTree {
bool base;
bool is1RM;
bool isEndurance;
bool selected = false;
bool executed = false;
String exerciseDetail;
String nameEnglish;
WorkoutMenuTree(this.id, this.parent, this.name, this.imageName, this.color, this.fontSize, this.child,
this.exerciseTypeId, this.exerciseType, this.base, this.is1RM, this.nameEnglish);
WorkoutMenuTree(this.id, this.parent, this.name, this.imageName, this.color, this.fontSize, this.child, this.exerciseTypeId,
this.exerciseType, this.base, this.is1RM, this.isEndurance, this.nameEnglish);
Map<String, dynamic> toJson() {
return {
@ -35,6 +36,12 @@ class WorkoutMenuTree {
"exerciseTypeId": exerciseTypeId.toString(),
"base": base.toString(),
"is1RM": is1RM.toString(),
"isEndurance": isEndurance.toString(),
};
}
@override
String toString() {
return this.toJson().toString();
}
}

View File

@ -1,3 +1,4 @@
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/exercise_device.dart';
import 'package:aitrainer_app/service/exercise_device_service.dart';
@ -8,8 +9,37 @@ class ExerciseDeviceRepository {
return this._devices;
}
void setDevices(List<ExerciseDevice> list) {
_devices = list;
}
Future<List<ExerciseDevice>> getDBDevices() async {
this._devices = await ExerciseDeviceApi().getDevices();
return this._devices;
}
bool isGym(int deviceId) {
bool isGym = false;
_devices.forEach((element) {
isGym = isGymElement(element.name);
});
return isGym;
}
bool isGymElement(String name) {
return name == "Cable" || name == "Baar" || name == "Gym Machine" || name == "Dumbbells" || name == "Barbell";
}
List<ExerciseDevice> getGymDevices() {
final List<ExerciseDevice> gymDevices = List();
if (_devices == null || _devices.isEmpty) {
_devices = Cache().getDevices();
}
_devices.forEach((element) {
if (isGymElement(element.name)) {
gymDevices.add(element);
}
});
return gymDevices;
}
}

View File

@ -50,17 +50,31 @@ class WorkoutTreeRepository {
List<ExerciseTree> exerciseTree = Cache().getExerciseTree();
if (exerciseTree == null || exerciseTree.length == 0) {
await ExerciseTreeApi().getExerciseTree();
exerciseTree = await ExerciseTreeApi().getExerciseTree();
}
List<ExerciseType> exerciseTypes = Cache().getExerciseTypes();
if (exerciseTypes == null || exerciseTypes.length == 0) {
exerciseTypes = await ExerciseTypeApi().getExerciseTypes();
}
exerciseTree.forEach((treeItem) async {
//print(" -- TreeItem " + treeItem.toJson().toString());
String treeName = isEnglish ? treeItem.name : treeItem.nameTranslation;
String assetImage = 'asset/menu/' + treeItem.imageUrl.substring(7);
bool is1RM = treeItem.name == 'One Rep Max' ? true : false;
if (is1RM == false && treeItem.parentId != 0) {
is1RM = isParent1RM(treeItem.parentId);
}
this.tree[treeItem.name] = WorkoutMenuTree(
bool isEndurance = treeItem.name == 'Endurance' ? true : false;
if (isEndurance == false && treeItem.parentId != 0) {
isEndurance = isParentEndurance(treeItem.parentId);
}
final WorkoutMenuTree menuItem = WorkoutMenuTree(
treeItem.treeId,
treeItem.parentId,
treeName,
@ -72,22 +86,40 @@ class WorkoutTreeRepository {
null,
false,
is1RM,
isEndurance,
treeItem.name,
);
this.tree[treeItem.name + "_" + treeItem.parentId.toString()] = menuItem;
//print("WorkoutMenuTree item " + menuItem.toJson().toString());
});
List<ExerciseType> exerciseTypes = Cache().getExerciseTypes();
if (exerciseTypes == null || exerciseTypes.length == 0) {
await ExerciseTypeApi().getExerciseTypes();
}
exerciseTypes.forEach((exerciseType) {
String exerciseTypeName = isEnglish ? exerciseType.name : exerciseType.nameTranslation;
String assetImage = 'asset/menu/' + exerciseType.imageUrl.substring(7);
bool is1RM = this.isParent1RM(exerciseType.treeId);
exerciseType.is1RM = is1RM;
this.tree[exerciseType.name] = WorkoutMenuTree(exerciseType.exerciseTypeId, exerciseType.treeId, exerciseTypeName, assetImage,
Colors.white, 24, true, exerciseType.exerciseTypeId, exerciseType, exerciseType.base, is1RM, exerciseType.name);
if (!(exerciseType.imageUrl.isEmpty || exerciseType.name.isEmpty || exerciseType.nameTranslation.isEmpty)) {
String exerciseTypeName = isEnglish ? exerciseType.name : exerciseType.nameTranslation;
String assetImage = 'asset/menu/' + exerciseType.imageUrl.substring(7);
if (exerciseType.parents.isNotEmpty) {
exerciseType.parents.forEach((parentId) {
bool is1RM = this.isParent1RM(parentId);
bool isEndurance = this.isParentEndurance(parentId);
exerciseType.is1RM = is1RM;
exerciseType.isEndurance = isEndurance;
WorkoutMenuTree menuItem = WorkoutMenuTree(exerciseType.exerciseTypeId, parentId, exerciseTypeName, assetImage, Colors.white,
24, true, exerciseType.exerciseTypeId, exerciseType, exerciseType.base, is1RM, isEndurance, exerciseType.name);
this.tree[exerciseType.name] = menuItem;
//print("WorkoutMenuTree item " + menuItem.toJson().toString());
/*print("ExerciseType in Menu item " +
exerciseType.toJson().toString() +
" is1RM: " +
is1RM.toString() +
" isEndurance: " +
isEndurance.toString());*/
});
} else {
//print("No Parents " + exerciseType.toJson().toString());
}
} else {
//print("ExerciseType missing data: " + exerciseType.exerciseTypeId.toString());
}
});
Cache().setWorkoutMenuTree(tree);
@ -101,7 +133,7 @@ class WorkoutTreeRepository {
this.tree.forEach((key, value) {
WorkoutMenuTree treeItem = value as WorkoutMenuTree;
if (treeItem.id == treeId) {
isTreeItem1RM = treeItem.is1RM;
isTreeItem1RM = isTreeItem1RM || treeItem.is1RM;
//print (treeItem.name + " 1RM " + treeItem.is1RM.toString() );
}
});
@ -109,8 +141,45 @@ class WorkoutTreeRepository {
return isTreeItem1RM;
}
LinkedHashMap getBranch(int parent) {
LinkedHashMap branch = LinkedHashMap<String, WorkoutMenuTree>();
bool isParentEndurance(int treeId) {
bool isTreeItemEndurance = false;
this.tree.forEach((key, value) {
WorkoutMenuTree treeItem = value as WorkoutMenuTree;
if (treeItem.id == treeId) {
isTreeItemEndurance = isTreeItemEndurance || treeItem.isEndurance;
//print(treeItem.id.toString() + " " + treeItem.name + " Endurance? " + treeItem.isEndurance.toString());
}
});
return isTreeItemEndurance;
}
bool isChild(int parentId) {
bool isChild = true;
this.getBranch(parentId).forEach((key, value) {
WorkoutMenuTree workoutTree = value;
isChild = isChild && workoutTree.child;
});
//print("Check child " + parentId.toString() + " child: " + isChild.toString());
return isChild;
}
bool isChildAndGym(int parentId) {
bool isChild = true;
bool isGym = true;
this.getBranch(parentId).forEach((key, value) {
WorkoutMenuTree workoutTree = value;
isChild = isChild && workoutTree.child;
isGym = isGym && (workoutTree.is1RM || workoutTree.isEndurance);
});
return isChild && isGym;
}
LinkedHashMap<String, WorkoutMenuTree> getBranch(int parent, {bool filtering = false}) {
LinkedHashMap<String, WorkoutMenuTree> branch = LinkedHashMap<String, WorkoutMenuTree>();
tree.forEach((key, value) {
WorkoutMenuTree workoutTree = value as WorkoutMenuTree;
if (parent == workoutTree.parent) {

View File

@ -7,6 +7,7 @@ import 'package:aitrainer_app/model/cache.dart';
class APIClient with Common {
Future<String> get(String endPoint, String param) async {
final url = Cache.getBaseUrl() + endPoint + param;
print("-------- API get " + url);
String authToken = Cache().getAuthToken();
if (authToken.length == 0) {
var responseJson = await APIClient.authenticateUser(Cache.username, Cache.password);

View File

@ -2,18 +2,61 @@ import 'dart:convert';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/exercise_tree.dart';
import 'package:aitrainer_app/model/exercise_tree_parents.dart';
import 'api.dart';
class ExerciseTreeApi {
final APIClient _client = new APIClient();
Future<List<ExerciseTree>> getExerciseTree() async {
final body = await _client.get("exercise_tree", "");
final Iterable json = jsonDecode(body);
final List<ExerciseTree> exerciseTree = json.map((exerciseTree) =>
ExerciseTree.fromJson(exerciseTree)).toList();
final String body = await _client.get("exercise_tree", "");
Iterable json = jsonDecode(body);
List<ExerciseTree> exerciseTree = json.map((exerciseTree) => ExerciseTree.fromJson(exerciseTree)).toList();
exerciseTree = await getExerciseTreeParents(exerciseTree);
Cache().setExerciseTree(exerciseTree);
return exerciseTree;
}
Future<List<ExerciseTree>> getExerciseTreeParents(List<ExerciseTree> exerciseTree) async {
List<ExerciseTree> copyList = this._copyList(exerciseTree);
final String body = await _client.get("exercise_tree_parents", "");
Iterable json = jsonDecode(body);
final List<ExerciseTreeParents> exerciseTreeParents =
json.map((exerciseTreeParent) => ExerciseTreeParents.fromJson(exerciseTreeParent)).toList();
int treeIndex = 0;
copyList.forEach((element) async {
int index = 0;
exerciseTreeParents.forEach((parent) {
if (parent.exerciseTreeChildId == element.treeId) {
if (index > 0) {
ExerciseTree newElement = element.copy(parent.exerciseTreeParentId);
exerciseTree.add(newElement);
print("ExerciseTree " + newElement.toJson().toString());
} else {
element.parentId = parent.exerciseTreeParentId;
exerciseTree[treeIndex].parentId = parent.exerciseTreeParentId;
}
index++;
}
});
print("ExerciseTree " + element.toJson().toString());
treeIndex++;
});
return exerciseTree;
}
List<ExerciseTree> _copyList(List<ExerciseTree> tree) {
final List<ExerciseTree> copyList = List();
tree.forEach((element) {
final ExerciseTree copy = element.copy(-1);
copyList.add(copy);
});
return copyList;
}
}

View File

@ -3,31 +3,26 @@ import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/exercise_type.dart';
import 'package:aitrainer_app/service/api.dart';
class ExerciseTypeApi {
final APIClient _client=new APIClient();
final APIClient _client = new APIClient();
Future<List<ExerciseType>> getExerciseTypes() async {
final body = await _client.get("exercise_type/active", "");
final body = await _client.get("exercise_type", "");
final Iterable json = jsonDecode(body);
final List<ExerciseType> exerciseTypes = json.map( (exerciseType) => ExerciseType.fromJson(exerciseType) ).toList();
final List<ExerciseType> exerciseTypes = json.map((exerciseType) => ExerciseType.fromJson(exerciseType)).toList();
Cache().setExerciseTypes(exerciseTypes);
return exerciseTypes;
}
Future<void> saveExerciseType(ExerciseType exerciseType) async {
String body = JsonEncoder().convert(exerciseType.toJson());
print(" ===== saving exerciseType id: " + exerciseType.exerciseTypeId.toString() + ":" + body );
await _client.post(
"exercise_type/"+exerciseType.exerciseTypeId.toString(),
body);
print(" ===== saving exerciseType id: " + exerciseType.exerciseTypeId.toString() + ":" + body);
await _client.post("exercise_type/" + exerciseType.exerciseTypeId.toString(), body);
}
Future<void> addExerciseType(ExerciseType exerciseType) async {
String body = JsonEncoder().convert(exerciseType.toJson());
print(" ===== add new exerciseType: " + body );
await _client.post(
"exercise_type",
body);
print(" ===== add new exerciseType: " + body);
await _client.post("exercise_type", body);
}
}
}

View File

@ -30,6 +30,7 @@ class Session {
await AppLanguage().getLocale(_sharedPreferences);
await AppLocalizations.delegate.load(AppLanguage().appLocal);
print(" -- Session: fetch token..");
Cache().setServerAddress(_sharedPreferences);
await _fetchToken(_sharedPreferences);
print(" -- FireBase init..");
await FirebaseApi().initializeFlutterFire();
@ -101,18 +102,17 @@ class Session {
await CustomerApi().getCustomer(customerId);
Cache().startPage = "home";
Flurry.setUserId(customerId.toString());
await ExerciseTypeApi().getExerciseTypes();
await ExerciseTreeApi().getExerciseTree();
await ExerciseDeviceApi().getDevices();
final customerDevices = await CustomerExerciseDeviceApi().getDevices(customerId);
Cache().setCustomerDevices(customerDevices);
if (customerId > 0) {
ExerciseRepository exerciseRepository = ExerciseRepository();
await exerciseRepository.getExercisesByCustomer(customerId);
}
}
}
await ExerciseTypeApi().getExerciseTypes();
await ExerciseTreeApi().getExerciseTree();
final customerDevices = await CustomerExerciseDeviceApi().getDevices(customerId);
Cache().setCustomerDevices(customerDevices);
if (customerId > 0) {
ExerciseRepository exerciseRepository = ExerciseRepository();
await exerciseRepository.getExercisesByCustomer(customerId);
}
await ExerciseDeviceApi().getDevices();
print("--- Session finished");
}
}

View File

@ -12,7 +12,6 @@ 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/splash.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
@ -102,12 +101,12 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans {
//LoadingDialog.hide(context);
}
final exerciseBloc = BlocProvider.of<ExerciseNewBloc>(context);
return getExerciseWidget(exerciseBloc, exerciseType);
return getExerciseWidget(exerciseBloc, exerciseType, menuBloc);
},
));
}
Widget getExerciseWidget(ExerciseNewBloc exerciseBloc, ExerciseType exerciseType) {
Widget getExerciseWidget(ExerciseNewBloc exerciseBloc, ExerciseType exerciseType, MenuBloc menuBloc) {
exerciseBloc.exerciseRepository.setExerciseType(exerciseType);
final String exerciseName = AppLanguage().appLocal == Locale("en")
? exerciseBloc.exerciseRepository.exerciseType.name
@ -120,7 +119,7 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans {
exerciseDescription = "";
}
print(exerciseBloc.exerciseRepository.exerciseType.name);
//print(exerciseBloc.exerciseRepository.exerciseType.name);
if (exerciseBloc.exerciseRepository.exerciseType.name == "BMR") {
return BMR(exerciseBloc: exerciseBloc);
@ -132,8 +131,17 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans {
return SizeWidget(exerciseBloc: exerciseBloc);
}
String exerciseTask = "";
if (exerciseBloc.exerciseRepository.exerciseType.is1RM && menuBloc.ability.toString() == ExerciseAbility.oneRepMax.toString()) {
exerciseTask = "Please take a relative bigger weight and repeat 12-20 times";
exerciseBloc.quantity = 12;
} else if (exerciseBloc.exerciseRepository.exerciseType.isEndurance &&
menuBloc.ability.toString() == ExerciseAbility.endurance.toString()) {
exerciseTask = "Please take a medium weight and repeat 20-30 times";
exerciseBloc.quantity = 20;
}
return Form(
//autovalidateMode: AutovalidateMode.disabled,
child: Scaffold(
resizeToAvoidBottomInset: true,
appBar: AppBarNav(depth: 1),
@ -189,6 +197,21 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans {
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,
@ -269,7 +292,7 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans {
borderSide: BorderSide(color: Colors.black26, width: 0.4),
),
),
initialValue: "12",
initialValue: bloc.quantity.toStringAsFixed(0),
keyboardType: TextInputType.number,
textInputAction: TextInputAction.next,
style: GoogleFonts.archivoBlack(fontSize: 80, color: Colors.orange[200]),
@ -340,6 +363,13 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans {
args['readonly'] = false,
Navigator.of(context).pushNamed('exerciseControlPage', arguments: args)
}
else if (bloc.exerciseRepository.exerciseType.isEndurance)
{
args['exerciseRepository'] = bloc.exerciseRepository,
args['percent'] = 0.50,
args['readonly'] = false,
Navigator.of(context).pushNamed('exerciseControlPage', arguments: args)
}
},
)
],

View File

@ -1,38 +1,28 @@
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
import 'package:aitrainer_app/bloc/settings/settings_bloc.dart';
import 'package:aitrainer_app/localization/app_language.dart';
import 'package:aitrainer_app/localization/app_localization.dart';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/widgets/app_bar_min.dart';
import 'package:aitrainer_app/widgets/bottom_nav.dart';
import 'package:aitrainer_app/widgets/splash.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:toggle_switch/toggle_switch.dart';
class SettingsPage extends StatelessWidget {
// ignore: must_be_immutable
class SettingsPage extends StatelessWidget with Trans {
@override
Widget build(BuildContext context) {
// ignore: close_sinks
SettingsBloc settingsBloc = BlocProvider.of<SettingsBloc>(context);
settingsBloc.setLocale(AppLanguage().appLocal);
settingsBloc.context = context;
setContext(context);
MenuBloc menuBloc = BlocProvider.of<MenuBloc>(context);
return Scaffold(
appBar: AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(AppLocalizations.of(context).translate('Settings')),
Image.asset(
'asset/image/WT_long_logo.png',
fit: BoxFit.cover,
height: 65.0,
),
],
),
//title: Text(AppLocalizations.of(context).translate('Settings')),
backgroundColor: Colors.transparent,
),
appBar: AppBarMin(),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
@ -70,13 +60,10 @@ class SettingsPage extends StatelessWidget {
return ListView(padding: EdgeInsets.only(top: 150), children: <Widget>[
ListTile(
leading: Icon(Icons.language),
subtitle: Text(AppLocalizations.of(context).translate("Change App Language")),
subtitle: Text(t("Change App Language")),
title: DropdownButton(
value: settingsBloc.getLocale() == Locale('en')
? AppLocalizations.of(context).translate("English")
: AppLocalizations.of(context).translate("Hungarian"),
items: [AppLocalizations.of(context).translate("English"), AppLocalizations.of(context).translate("Hungarian")]
.map<DropdownMenuItem<String>>((String value) {
value: settingsBloc.getLocale() == Locale('en') ? t("English") : t("Hungarian"),
items: [t("English"), t("Hungarian")].map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
@ -85,6 +72,37 @@ class SettingsPage extends StatelessWidget {
onChanged: (String lang) => {
settingsBloc.add(SettingsChangeLanguage(language: lang)),
})),
getServer(),
]);
}
ListTile getServer() {
if (Cache().userLoggedIn.admin != 1) {
return ListTile(
title: Container(),
);
}
return ListTile(
leading: Icon(Icons.data_usage_sharp),
subtitle: Text("For Test purpuses select Test-Server. After that please restart the the App"),
title: ToggleSwitch(
minWidth: 120.0,
minHeight: 30.0,
fontSize: 14.0,
initialLabelIndex: Cache().liveServer
? Cache().testEnvironment == "1"
? 1
: 0
: 1,
activeBgColor: Colors.indigo,
activeFgColor: Colors.white,
inactiveBgColor: Colors.white60,
inactiveFgColor: Colors.grey[900],
labels: [t('Live-Server'), t('Test-Server')],
onToggle: (index) {
Cache().setServer(index == 0);
},
),
);
}
}

View File

@ -8,11 +8,11 @@ import 'package:aitrainer_app/util/common.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:percent_indicator/linear_percent_indicator.dart';
import 'package:rainbow_color/rainbow_color.dart';
class AppBarNav extends StatefulWidget implements PreferredSizeWidget {
class AppBarNav extends StatefulWidget implements PreferredSizeWidget {
final MenuBloc menuBloc;
final bool isMenu;
final int depth;
@ -25,18 +25,17 @@ class AppBarNav extends StatefulWidget implements PreferredSizeWidget {
Size get preferredSize => const Size.fromHeight(50);
}
class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin, Common {
class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin, Common {
Animation<Color> colorAnim;
AnimationController colorController;
MenuBloc menuBloc;
@override
void initState() {
colorController = AnimationController(duration: Duration(seconds: 4), vsync: this);
colorController =
AnimationController(duration: Duration(seconds: 4), vsync:this);
colorAnim = RainbowColorTween([Colors.white70,
colorAnim = RainbowColorTween([
Colors.white70,
Colors.blueGrey,
Colors.blueAccent,
Colors.lightBlue,
@ -45,18 +44,20 @@ class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin,
Colors.orange,
Colors.orangeAccent,
Colors.yellowAccent,
Color(0xffcce6ff)])
.animate(colorController)
..addListener(() { setState(() {}); })
Color(0xffcce6ff)
]).animate(colorController)
..addListener(() {
setState(() {});
})
..addStatusListener((status) {
if (status == AnimationStatus.completed) {
Timer(Duration(seconds: 10), () {
if ( mounted ) {
if (mounted) {
colorController.forward();
}
});
} else if (status == AnimationStatus.dismissed) {
colorController.forward();
colorController.forward();
}
});
colorController.forward();
@ -72,33 +73,35 @@ class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin,
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
getAnimatedWidget(),
Image.asset(
'asset/image/WT_long_logo.png',
//fit: BoxFit.cover,
height: 45.0,
Stack(
children: [
Image.asset(
'asset/image/WT_long_logo.png',
//fit: BoxFit.cover,
height: 45.0,
),
getTestServer(),
],
),
],
),
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.white),
onPressed: () =>
{
if ( widget.isMenu != null ) {
if ( menuBloc.workoutItem != null ) {
menuBloc.add(MenuTreeUp(parent: menuBloc.workoutItem.parent)),
onPressed: () => {
if (widget.isMenu != null)
{
if (menuBloc.workoutItem != null)
{
menuBloc.add(MenuTreeUp(parent: menuBloc.workoutItem.parent)),
}
}
} else if ( widget.depth != null ) {
if ( widget.depth == 0 ) {
Navigator.of(context).pushNamed('home')
} else {
Navigator.of(context).pop()
else if (widget.depth != null)
{
if (widget.depth == 0) {Navigator.of(context).pushNamed('home')} else {Navigator.of(context).pop()}
}
}
},
)
);
));
}
@override
@ -107,48 +110,70 @@ class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin,
super.dispose();
}
Widget getTestServer() {
if (Cache().liveServer) {
return Container();
} else {
return Text("TEST",
style: GoogleFonts.archivoBlack(
color: Colors.red,
fontWeight: FontWeight.bold,
shadows: <Shadow>[
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,
),
],
));
}
}
Widget getAnimatedWidget() {
double cWidth = mediaSizeWidth(context);
double percent = Cache().getPercentExercises();
if ( percent == -1) {
if (percent == -1) {
menuBloc.menuTreeRepository.createTree();
ExerciseRepository exerciseRepository = ExerciseRepository();
exerciseRepository.getBaseExerciseFinishedPercent();
percent = Cache().getPercentExercises();
}
int sizeExerciseList = Cache().getExercises() == null? 0 : Cache().getExercises().length;
if ( sizeExerciseList == 0 ) {
int sizeExerciseList = Cache().getExercises() == null ? 0 : Cache().getExercises().length;
if (sizeExerciseList == 0) {
String text = AppLocalizations.of(context).translate("Make your first test");
double fontSize = text.length > 24 ? 13 : 16;
return Stack(
alignment: Alignment.topLeft,
overflow: Overflow.clip,
children: [
Text(text,
style: TextStyle(fontSize: fontSize, color: colorAnim.value, shadows: [Shadow(color: Colors.purple , blurRadius: 15)]),
),
//TestProgress(animation: sizeAnim),
]
);
return Stack(alignment: Alignment.topLeft, overflow: Overflow.clip, children: [
Text(
text,
style: TextStyle(fontSize: fontSize, color: colorAnim.value, shadows: [Shadow(color: Colors.purple, blurRadius: 15)]),
),
//TestProgress(animation: sizeAnim),
]);
} else {
return Stack(
alignment: Alignment.topLeft,
children: [
LinearPercentIndicator(
width: cWidth / 4,
lineHeight: 14.0,
percent: percent,
center: Text(
(percent * 100).toStringAsFixed(0) + "% " + AppLocalizations.of(context).translate("finished"),
style: new TextStyle(fontSize: 10.0),
),
trailing: Icon(percent > 0.6 ? Icons.mood : Icons.mood_bad, color: colorAnim.value,),
linearStrokeCap: LinearStrokeCap.roundAll,
backgroundColor: colorAnim.value,
progressColor: Color(0xff73e600),
animation: true,
LinearPercentIndicator(
width: cWidth / 4,
lineHeight: 14.0,
percent: percent,
center: Text(
(percent * 100).toStringAsFixed(0) + "% " + AppLocalizations.of(context).translate("finished"),
style: new TextStyle(fontSize: 10.0),
),
trailing: Icon(
percent > 0.6 ? Icons.mood : Icons.mood_bad,
color: colorAnim.value,
),
linearStrokeCap: LinearStrokeCap.roundAll,
backgroundColor: colorAnim.value,
progressColor: Color(0xff73e600),
animation: true,
),
],
);

View File

@ -1,6 +1,8 @@
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/util/common.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
// ignore: must_be_immutable
class AppBarMin extends StatefulWidget implements PreferredSizeWidget {
@ -27,10 +29,15 @@ class _AppBarNav extends State<AppBarMin> with Common {
title: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Image.asset(
'asset/image/WT_long_logo.png',
//fit: BoxFit.cover,
height: 45.0,
Stack(
children: [
Image.asset(
'asset/image/WT_long_logo.png',
//fit: BoxFit.cover,
height: 45.0,
),
getTestServer(),
],
),
],
),
@ -46,4 +53,28 @@ class _AppBarNav extends State<AppBarMin> with Common {
void dispose() {
super.dispose();
}
Widget getTestServer() {
if (Cache().liveServer) {
return Container();
} else {
return Text("TEST",
style: GoogleFonts.archivoBlack(
color: Colors.red,
fontWeight: FontWeight.bold,
shadows: <Shadow>[
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,
),
],
));
}
}
}

View File

@ -58,31 +58,26 @@ class MenuInfoWidget extends StatelessWidget with Common {
title,
maxLines: 4,
textAlign: TextAlign.center,
style: TextStyle(
color: titleColor,
fontSize: titleSize,
fontWeight: titleWeight),
style: TextStyle(color: titleColor, fontSize: titleSize, fontWeight: titleWeight),
),
Divider(),
Text(
text,
maxLines: 6,
style: TextStyle(
color: textColor, fontSize: textSize, fontWeight: textWeight),
style: TextStyle(color: textColor, fontSize: textSize, fontWeight: textWeight),
),
Divider(),
/* Divider(),
Text(
text2,
maxLines: 6,
style: TextStyle(
color: textColor, fontSize: textSize, fontWeight: textWeight),
),
), */
Divider(),
Text(
text3,
maxLines: 6,
style: TextStyle(
color: textColor, fontSize: textSize, fontWeight: textWeight),
style: TextStyle(color: textColor, fontSize: textSize, fontWeight: textWeight),
),
getLink(),
],
@ -97,15 +92,10 @@ class MenuInfoWidget extends StatelessWidget with Common {
return InkWell(
child: new Text(
link,
style: TextStyle(
color: Colors.lightBlueAccent,
fontSize: textSize,
fontFamily: 'Arial',
fontWeight: textWeight),
style: TextStyle(color: Colors.lightBlueAccent, fontSize: textSize, fontFamily: 'Arial', fontWeight: textWeight),
),
onTap: () => {
missingId = bloc.menuTreeRepository
.getMissingTreeIdByName(bloc.missingTreeName),
missingId = bloc.menuTreeRepository.getMissingTreeIdByName(bloc.missingTreeName),
print("menu " + missingId.toString()),
bloc.add(MenuTreeJump(parent: missingId))
});

View File

@ -1,6 +1,7 @@
import 'dart:ui';
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
import 'package:aitrainer_app/localization/app_language.dart';
import 'package:aitrainer_app/localization/app_localization.dart';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/workout_menu_tree.dart';
@ -17,6 +18,8 @@ import 'menu_info_widget.dart';
// ignore: must_be_immutable
class MenuPageWidget extends StatelessWidget with Trans {
int parent;
final double baseWidth = 312;
final double baseHeight = 675.2;
MenuPageWidget({this.parent});
@ -27,13 +30,172 @@ class MenuPageWidget extends StatelessWidget with Trans {
double cWidth = MediaQuery.of(context).size.width;
double cHeight = MediaQuery.of(context).size.height;
return CustomScrollView(
scrollDirection: Axis.vertical, slivers: <Widget>[buildMenuColumn(parent, context, menuBloc, cWidth, cHeight)]);
return CustomScrollView(scrollDirection: Axis.vertical, slivers: buildMenuColumn(parent, context, menuBloc, cWidth, cHeight));
}
SliverGrid buildMenuColumn(int parent, BuildContext context, MenuBloc menuBloc, double cWidth, double cHeight) {
final List<Widget> _columnChildren = List();
List<Widget> buildMenuColumn(int parent, BuildContext context, MenuBloc menuBloc, double cWidth, double cHeight) {
final List<Widget> slivers = List();
bool isChild = menuBloc.menuTreeRepository.isChildAndGym(menuBloc.parent);
if (!isChild) {
slivers.add(getInfoWidget(context, menuBloc));
} else {
slivers.add(getFilterWidget(parent, menuBloc));
slivers.add(getFilterElements(menuBloc));
}
final List<Widget> _columnChildren = List();
final double distortionHeight = cHeight / baseHeight;
if (menuBloc.getFilteredBranch(menuBloc.parent).isEmpty) {
_columnChildren.add(Container(
padding: EdgeInsets.only(top: 15.0),
child: Center(
child: Stack(alignment: Alignment.bottomLeft, children: [
Text(t("All Exercises has been filtered out"), style: GoogleFonts.inter(color: Colors.white)),
]))));
} else {
menuBloc.getFilteredBranch(menuBloc.parent).forEach((treeName, value) {
WorkoutMenuTree workoutTree = value;
/* double textLength = workoutTree.name.length * workoutTree.fontSize;
double top = textLength < cWidth - 30
? (cHeight / 3 - 2.5 * workoutTree.fontSize) / distortionHeight
: (cHeight / 3 - 3.6 * workoutTree.fontSize) / distortionHeight;
print(" dH: " +
distortionHeight.toStringAsFixed(1) +
" W: " +
cWidth.toStringAsFixed(0) +
" H: " +
cHeight.toStringAsFixed(0) +
" TOP: " +
top.toStringAsFixed(0) +
" tL: " +
textLength.toStringAsFixed(0)); */
_columnChildren.add(Container(
padding: EdgeInsets.only(top: 15.0, left: 15, right: 15),
height: 225, //cHeight / 3 * distortionHeight,
child: Badge(
padding: EdgeInsets.all(8),
position: BadgePosition.bottomEnd(end: 0),
animationDuration: Duration(milliseconds: 500),
animationType: BadgeAnimationType.slide,
badgeColor: Colors.orange[800],
showBadge: workoutTree.base,
badgeContent: Text(t("base"),
style: TextStyle(
color: Colors.white,
fontSize: 12,
)),
child: Stack(alignment: Alignment.bottomLeft, children: [
FlatButton(
child: badgedIcon(workoutTree, cWidth, cHeight),
padding: EdgeInsets.only(left: 0.0, bottom: 0),
onPressed: () => menuClick(workoutTree, menuBloc, context),
),
Container(
padding: EdgeInsets.only(left: 15, bottom: 10),
child: InkWell(
onTap: () => menuClick(workoutTree, menuBloc, context),
child: Text(
workoutTree.name,
maxLines: 3,
style: GoogleFonts.archivoBlack(color: workoutTree.color, fontSize: workoutTree.fontSize, height: 1.1),
),
highlightColor: workoutTree.color,
),
),
]))));
});
}
SliverList sliverList = SliverList(
delegate: SliverChildListDelegate(_columnChildren),
/* gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 1,
mainAxisSpacing: 6.0,
crossAxisSpacing: 10.0,
childAspectRatio: cWidth > 375 ? 1.8 : 1.8,
) */
);
slivers.add(sliverList);
return slivers;
}
SliverGrid getFilterWidget(int parent, MenuBloc menuBloc) {
SliverGrid sliverList = SliverGrid(
delegate: SliverChildListDelegate([
Column(mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [
Text(
t("Equipment Filter"),
textAlign: TextAlign.center,
style: GoogleFonts.archivoBlack(
fontSize: 24,
color: Colors.white,
shadows: <Shadow>[
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,
),
],
),
),
])
]),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 1,
mainAxisSpacing: 5.0,
crossAxisSpacing: 5.0,
childAspectRatio: 9,
));
return sliverList;
}
SliverGrid getFilterElements(MenuBloc menuBloc) {
List<Widget> list = List();
menuBloc.exerciseDeviceRepository.getGymDevices().forEach((element) {
String deviceName = AppLanguage().appLocal == Locale('en') ? element.name : element.nameTranslation;
ChoiceChip chip = ChoiceChip(
//padding: EdgeInsets.zero,
labelPadding: EdgeInsets.only(right: 5),
avatar: Icon(
Icons.remove_circle_outline,
color: Colors.orange,
size: 18,
),
label: Text(deviceName),
labelStyle: TextStyle(fontSize: 9, color: Colors.black),
selectedColor: Colors.white,
selected: menuBloc.selectedDevice(element.exerciseDeviceId),
backgroundColor: Colors.blue[100],
shadowColor: Colors.black54,
onSelected: (value) => menuBloc.add(MenuFilterExerciseType(deviceId: element.exerciseDeviceId)),
);
list.add(chip);
});
SliverGrid sliverList = SliverGrid(
delegate: SliverChildListDelegate(list),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 1.0,
crossAxisSpacing: 1.0,
childAspectRatio: 3,
));
return sliverList;
}
SliverGrid getInfoWidget(BuildContext context, MenuBloc menuBloc) {
final List<Widget> _columnChildren = List();
if (context != null) {
menuBloc.setContext(context);
menuBloc.setMenuInfo();
@ -53,55 +215,14 @@ class MenuPageWidget extends StatelessWidget with Trans {
);
_columnChildren.add(info);
}
menuBloc.menuTreeRepository.getBranch(menuBloc.parent).forEach((treeName, value) {
WorkoutMenuTree workoutTree = value as WorkoutMenuTree;
_columnChildren.add(Container(
padding: EdgeInsets.only(top: 15.0),
child: Center(
child: Stack(alignment: Alignment.bottomLeft,
//clipBehavior: Clip.antiAliasWithSaveLayer,
children: [
FlatButton(
child: badgedIcon(workoutTree, cWidth, cHeight),
padding: EdgeInsets.only(left: 0.0, bottom: 0),
shape: getShape(workoutTree),
onPressed: () => menuClick(workoutTree, menuBloc, context),
),
Positioned(
top: workoutTree.name.length > 15 ?
workoutTree.fontSize > 25 ? 130 : 140 :
workoutTree.fontSize > 25 ? 165 : 175,
left: 8,
child: Container(
height: cWidth * .95,
width: 280,
child: InkWell(
onTap: () => menuClick(workoutTree, menuBloc, context),
child: Text(workoutTree.name,
maxLines: 2,
style: GoogleFonts.archivoBlack(
color: workoutTree.color,
fontSize: workoutTree.fontSize,
),
),
highlightColor: workoutTree.color,
),
color: Colors.transparent,
),
),
]))));
});
SliverGrid sliverList = SliverGrid(
delegate: SliverChildListDelegate(_columnChildren),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 1,
mainAxisSpacing: 8.0,
crossAxisSpacing: 10.0,
childAspectRatio: cWidth > 375 ? 1.8 : 2.0,
mainAxisSpacing: 5.0,
crossAxisSpacing: 5.0,
childAspectRatio: 2,
));
return sliverList;
}
@ -114,8 +235,7 @@ class MenuPageWidget extends StatelessWidget with Trans {
if (Cache().userLoggedIn == null) {
Scaffold.of(context).showSnackBar(SnackBar(
backgroundColor: Colors.orange,
content:
Text(AppLocalizations.of(context).translate('Please log in'), style: TextStyle(color: Colors.white))));
content: Text(AppLocalizations.of(context).translate('Please log in'), style: TextStyle(color: Colors.white))));
} else {
if (workoutTree.exerciseType.name == "Custom" && Cache().userLoggedIn.admin == 1) {
Navigator.of(context).pushNamed('exerciseCustomPage', arguments: workoutTree.exerciseType);
@ -130,11 +250,9 @@ class MenuPageWidget extends StatelessWidget with Trans {
bool base = workoutTree.base;
dynamic returnCode = (base == true)
? RoundedRectangleBorder(
side: BorderSide(width: 4, color: Colors.orangeAccent),
borderRadius: BorderRadius.all(Radius.circular(12.0)))
side: BorderSide(width: 6, color: Colors.orangeAccent), borderRadius: BorderRadius.all(Radius.circular(24.0)))
: RoundedRectangleBorder(
side: BorderSide(width: 1, color: Colors.transparent),
borderRadius: BorderRadius.all(Radius.circular(8.0)));
side: BorderSide(width: 1, color: Colors.transparent), borderRadius: BorderRadius.all(Radius.circular(8.0)));
return returnCode;
}
@ -142,10 +260,10 @@ class MenuPageWidget extends StatelessWidget with Trans {
dynamic image;
try {
image = ClipRRect(
borderRadius: BorderRadius.circular(12.0),
borderRadius: BorderRadius.circular(24),
child: Image.asset(
workoutTree.imageName,
height: cHeight * 0.85,
height: cHeight,
errorBuilder: (context, error, stackTrace) {
String url = Cache.mediaUrl + 'images/' + workoutTree.imageName.substring(11);
Widget image = FadeInImage.assetNetwork(

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.2+35
version: 1.1.2+36
environment:
sdk: ">=2.10.0 <3.0.0"