Skip to content

Commit

Permalink
import ex..much progress
Browse files Browse the repository at this point in the history
  • Loading branch information
Desync-o-tron committed Sep 26, 2024
1 parent dd2df34 commit b7c0457
Show file tree
Hide file tree
Showing 11 changed files with 531 additions and 287 deletions.
3 changes: 3 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
analyzer:
errors:
library_private_types_in_public_api: ignore
include: package:flutter_lints/flutter.yaml

linter:
Expand Down
10 changes: 5 additions & 5 deletions lib/DOM/exercise_db.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import 'package:open_fitness_tracker/utils/utils.dart';
import 'package:shared_preferences/shared_preferences.dart';

class ExDB {
static get exercises => _exercises;
static get categories => _categories;
static get muscles => _muscles;
static get names => _names;
static get equipment => _equipment;
static Exercises get exercises => _exercises;
static List<String> get categories => _categories;
static List<String> get muscles => _muscles;
static List<String> get names => _names;
static List<String> get equipment => _equipment;

static final List<String> _names = [];
static final List<String> _categories = [];
Expand Down
139 changes: 104 additions & 35 deletions lib/exercises/ex_search_page.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:open_fitness_tracker/DOM/exercise_metadata.dart';
import 'package:open_fitness_tracker/DOM/training_metadata.dart';
import 'package:open_fitness_tracker/common/common_widgets.dart';
Expand All @@ -12,7 +13,22 @@ import 'package:open_fitness_tracker/utils/utils.dart';

class ExerciseSearchPage extends StatefulWidget {
final bool useForAddingToTraining;
const ExerciseSearchPage({super.key, this.useForAddingToTraining = false});
final bool useForMappingForeignExercise;
final Function? setForeignExerciseCallback;
final Exercise? foreignEx;

ExerciseSearchPage({
super.key,
this.useForAddingToTraining = false,
this.useForMappingForeignExercise = false,
this.setForeignExerciseCallback,
this.foreignEx,
}) {
if (useForMappingForeignExercise) {
assert(setForeignExerciseCallback != null);
assert(foreignEx != null);
}
}

@override
State<ExerciseSearchPage> createState() => _ExerciseSearchPageState();
Expand All @@ -35,20 +51,40 @@ class _ExerciseSearchPageState extends State<ExerciseSearchPage> {
Widget build(BuildContext context) {
final scrollController = ScrollController(initialScrollOffset: 0);
final state = context.watch<ExSearchCubit>().state;
// ignore: avoid_unnecessary_containers
return Container(
// color: Theme.of(context).colorScheme.secondary,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Exercises', style: Theme.of(context).textTheme.displayLarge),
_exercisesListView(scrollController, state),
if (widget.useForAddingToTraining) _addSelectedButton(context),
const SearchBar(),
_muscleAndCategoryFilterButtons(state, context),
_createNewExButton(context),
],
),

List<Widget> pageChildren = [];
if (!widget.useForMappingForeignExercise) {
pageChildren
.add(Text('Exercises', style: Theme.of(context).textTheme.displayLarge));
} else {
pageChildren
.add(Text('Exercise Match', style: Theme.of(context).textTheme.displayMedium));
pageChildren.add(ExerciseTile(
exercise: widget.foreignEx!,
isSelectable: false,
colorDecoration: true,
));
pageChildren.add(Text('To', style: Theme.of(context).textTheme.bodySmall));
}
pageChildren.addAll([
_exercisesListView(scrollController, state),
const SearchBar(),
_muscleAndCategoryFilterButtons(state, context),
]);

if (widget.useForAddingToTraining) pageChildren.add(_addSelectedButton(context));
if (widget.useForMappingForeignExercise) {
pageChildren.addAll([
_thisIsMyExButton(widget.setForeignExerciseCallback!),
_noExerciseMatchButton(widget.setForeignExerciseCallback!),
]);
} else {
pageChildren.add(_createNewExButton(context));
}

return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: pageChildren,
);
}

Expand All @@ -70,33 +106,37 @@ class _ExerciseSearchPageState extends State<ExerciseSearchPage> {
}

Expanded _exercisesListView(ScrollController scrollController, ExSearchState state) {
//todo scrolling on web is not perfect.using slider is a bit janky.
return Expanded(
child: ScrollConfiguration(
behavior: GenericScrollBehavior(),
child: Scrollbar(
controller: scrollController,
thumbVisibility: true,
child: ListView.builder(
controller: scrollController,
key: ValueKey(state.filteredExercises.length),
itemCount: state.filteredExercises.length,
itemBuilder: (context, index) {
return ExerciseTile(
exercise: state.filteredExercises[index],
isSelectable: widget.useForAddingToTraining,
isSelected: selectedExercises
.contains(state.filteredExercises[index]) ||
newlySelectedExercises.contains(state.filteredExercises[index]),
onSelectionChanged: (bool isSelected) {
if (isSelected) {
newlySelectedExercises.add(state.filteredExercises[index]);
} else {
newlySelectedExercises.remove(state.filteredExercises[index]);
}
setState(() {});
});
}),
controller: scrollController,
key: ValueKey(state.filteredExercises.length),
itemCount: state.filteredExercises.length,
itemBuilder: (context, index) {
return ExerciseTile(
exercise: state.filteredExercises[index],
isSelectable:
widget.useForAddingToTraining || widget.useForMappingForeignExercise,
isSelected: selectedExercises.contains(state.filteredExercises[index]) ||
newlySelectedExercises.contains(state.filteredExercises[index]),
onSelectionChanged: (bool isSelected) {
if (isSelected) {
if (widget.useForMappingForeignExercise) {
newlySelectedExercises.clear();
}
newlySelectedExercises.add(state.filteredExercises[index]);
} else {
newlySelectedExercises.remove(state.filteredExercises[index]);
}
setState(() {});
},
);
},
),
),
),
);
Expand Down Expand Up @@ -161,6 +201,35 @@ class _ExerciseSearchPageState extends State<ExerciseSearchPage> {
),
);
}

Widget _thisIsMyExButton(Function setForeignExerciseCallback) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 6.0),
child: MyGenericButton(
label: "This Is My Exercise",
color: Theme.of(context).colorScheme.primary,
onPressed: () {
if (newlySelectedExercises.isEmpty) return;
setForeignExerciseCallback(newlySelectedExercises.first);
context.pop();
},
),
);
}

Widget _noExerciseMatchButton(Function setForeignExerciseCallback) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 6.0),
child: MyGenericButton(
label: "None of these exercises match mine",
color: Theme.of(context).colorScheme.primary,
onPressed: () {
setForeignExerciseCallback(null); // Passing null to indicate no match
context.pop();
},
),
);
}
}

class SearchMultiSelectModal extends StatelessWidget {
Expand Down
38 changes: 18 additions & 20 deletions lib/exercises/ex_tile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,43 +8,40 @@ class ExerciseTile extends StatelessWidget {
final bool isSelectable;
final bool isSelected;
final Function? onSelectionChanged;
final bool colorDecoration;
final Color? borderColor;

const ExerciseTile({
super.key,
required this.exercise,
this.isSelectable = false,
this.isSelected = false,
this.onSelectionChanged,
this.colorDecoration = false,
this.borderColor,
});

@override
Widget build(BuildContext context) {
String musclesUsed = exercise.primaryMuscles.map((muscle) => muscle.capTheFirstLetter()).join(', ');
String musclesUsed =
exercise.primaryMuscles.map((muscle) => muscle.capTheFirstLetter()).join(', ');
if (exercise.secondaryMuscles != null && exercise.secondaryMuscles!.isNotEmpty) {
musclesUsed +=
" + ${exercise.secondaryMuscles!.map((muscle) => muscle.capTheFirstLetter()).join(', ')}";
}

BoxDecoration tileDecoration = const BoxDecoration();
if (isSelectable) {
tileDecoration = BoxDecoration(
border: Border.all(
color: isSelected ? Colors.blue : Colors.black,
width: 1,
),
);
} else {
tileDecoration = BoxDecoration(
border: Border.all(
color: Colors.black,
width: 1,
),
);
}
BoxDecoration tileDecoration = BoxDecoration(
border: Border.all(
color: (borderColor != null)
? borderColor!
: (isSelectable ? (isSelected ? Colors.blue : Colors.black) : Colors.black),
width: (borderColor == null) ? 1 : 2,
),
color: colorDecoration ? Colors.grey[200] : null,
);

return Container(
margin: const EdgeInsets.only(bottom: 5, right: 6, left: 6),
// decoration: BoxDecoration(border: Border.all(color: Colors.black, width: 1)),
decoration: tileDecoration,
child: ListTile(
title: Text(exercise.name, style: Theme.of(context).textTheme.titleLarge),
Expand All @@ -60,6 +57,7 @@ class ExerciseTile extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//todo..replace w/ history!
Text("2 uses ", style: Theme.of(context).textTheme.bodyLarge),
Text("60lb (x12) ", style: Theme.of(context).textTheme.bodyLarge),
],
Expand All @@ -71,8 +69,8 @@ class ExerciseTile extends StatelessWidget {
builder: (context) => ExerciseDialog(exercise: exercise),
useSafeArea: true,
);
} else if (isSelectable) {
onSelectionChanged!(!isSelected);
} else {
onSelectionChanged?.call(!isSelected);
}
},
onLongPress: () {
Expand Down
Loading

0 comments on commit b7c0457

Please sign in to comment.