setting up timer and action management

This commit is contained in:
Joshua Burman 2024-12-01 21:23:12 -05:00
parent 9ffa0d178c
commit 29479e8aba
4 changed files with 257 additions and 118 deletions

View File

@ -1,7 +1,9 @@
import 'dart:async';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:sendtrain/models/activity_model.dart';
import 'package:sendtrain/widgets/activity_action_view.dart';
class ActivityTimerModel with ChangeNotifier {
late int _activityId;
@ -12,49 +14,135 @@ class ActivityTimerModel with ChangeNotifier {
late int _totalReps;
late String _currentState;
late Timer? _periodicTimer;
late ActivityModel _activity;
// int _viewCount = 0;
bool _active = false;
int _currentAction = 0;
int get tickCount => _tickCount;
int get currentSet => _currentSet;
int get currentRep => _currentRep;
int get currentAction => _currentAction;
int get totalSets => _totalSets;
int get totalReps => _totalReps;
bool get active => _active;
void setAction(int actionNum, int setNum, String state) {
_currentAction = actionNum;
_currentSet = setNum;
_currentState = state;
stopTimer();
if (_currentState == "rest") {
startTimer();
}
notifyListeners();
}
void incrementAction() {
_currentAction++;
if (_currentState == "rest") {
_currentState = "rep";
_currentSet++;
stopTimer();
} else {
_currentState = "rest";
startTimer();
}
notifyListeners();
}
void setupTimer(ActivityModel activity) {
_activity = activity;
_activityId = activity.id;
_currentSet = 0;
_currentRep = 0;
_totalSets = activity.actions[0].activityActionSet.total;
_totalReps = activity.actions[0].activityActionSet.reps.amounts[0];
_tickCount = activity.actions[0].activityActionSet.rest ~/ 10000;
_currentState = "rep";
// ActivityActionView av = actionViews[_viewCount];
// av.
}
void startTimer(ActivityModel activity) {
_active = true;
_periodicTimer = Timer.periodic(const Duration(seconds: 1), (Timer timer) {
if (_tickCount == 0) {
if (_currentRep + 1 ==
activity.actions[0].activityActionSet.reps.amounts[_currentSet]) {
_currentSet++;
if (_currentSet == activity.actions[0].activityActionSet.total) {
timer.cancel();
_active = false;
setupTimer(activity);
}
_currentRep = 0;
_totalReps =
activity.actions[0].activityActionSet.reps.amounts[_currentSet];
_tickCount = activity.actions[0].activityActionSet.rest ~/ 10000;
void pauseTimer() {
_active = false;
notifyListeners();
}
void stopTimer() {
_active = false;
_periodicTimer?.cancel();
notifyListeners();
}
void startTimer() {
if (_currentState == 'rep') {
// do nothing for now
} else {
_active = true;
_tickCount = _activity.actions[0].activityActionSet.rest ~/ 10000;
_periodicTimer = Timer.periodic(const Duration(seconds: 1), (Timer timer) {
if (_tickCount == 0) {
incrementAction();
// if (_currentRep + 1 ==
// _activity.actions[0].activityActionSet.reps.amounts[_currentSet]) {
// _currentSet++;
// if (_currentSet == _activity.actions[0].activityActionSet.total) {
// timer.cancel();
// _active = false;
// setupTimer(_activity);
// }
// _currentRep = 0;
// _totalReps =
// _activity.actions[0].activityActionSet.reps.amounts[_currentSet];
// _tickCount = _activity.actions[0].activityActionSet.rest ~/ 10000;
// } else {
// _currentRep++;
// }
} else {
_currentRep++;
if (_active) {
_tickCount--;
}
}
} else {
_tickCount--;
}
notifyListeners();
});
notifyListeners();
});
}
}
// void startTimer(ActivityModel activity) {
// _active = true;
// _periodicTimer = Timer.periodic(const Duration(seconds: 1), (Timer timer) {
// if (_tickCount == 0) {
// if (_currentRep + 1 ==
// activity.actions[0].activityActionSet.reps.amounts[_currentSet]) {
// _currentSet++;
// if (_currentSet == activity.actions[0].activityActionSet.total) {
// timer.cancel();
// _active = false;
// setupTimer(activity);
// }
// _currentRep = 0;
// _totalReps =
// activity.actions[0].activityActionSet.reps.amounts[_currentSet];
// _tickCount = activity.actions[0].activityActionSet.rest ~/ 10000;
// } else {
// _currentRep++;
// }
// } else {
// _tickCount--;
// }
// notifyListeners();
// });
// }
}

View File

@ -1,21 +1,47 @@
import 'dart:async';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:sendtrain/classes/activity_action.dart';
import 'package:sendtrain/models/activity_timer_model.dart';
import 'package:sendtrain/widgets/action_card.dart';
class ActivityActionView extends StatefulWidget {
ActivityActionView({super.key, required this.action});
ActivityAction action;
// ActivityTimerModel activityTimerModel;
// get incrementActivity => ActivityActionViewState().incrementActivity();
@override
State<ActivityActionView> createState() => _ActivityActionViewState();
State<ActivityActionView> createState() => ActivityActionViewState();
// void incrementActivity() => _ActivityActionViewState().incrementActivity();
}
class _ActivityActionViewState extends State<ActivityActionView> {
class ActivityActionViewState extends State<ActivityActionView> {
int _index = 0;
int _currentAction = 0;
// int _actionCount = 0;
// int _currentState = "Active"
// void incrementActivity(int actionNum) {
// setState(() {
// atm.setAction(actionNum);
// });
// }
// void setActivity(int currentAction) {
// setState(() {
// widget.atm.setAction(currentAction);
// });
// }
@override
Widget build(BuildContext context) {
int actionCount = 0;
ActivityTimerModel atm = Provider.of<ActivityTimerModel>(context, listen: true);
return Expanded(
child: ListView.builder(
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
@ -23,34 +49,61 @@ class _ActivityActionViewState extends State<ActivityActionView> {
itemBuilder: (BuildContext context, int index) {
String title = widget.action.title;
Set actionSet = widget.action.activityActionSet;
Reps setReps = widget.action.activityActionSet.reps;
Reps setReps = actionSet.reps;
int setRest = actionSet.rest ~/ 1000;
List<Card> contents = [];
int currentAction = actionCount;
// contents.add(Card(child: Text('Set ${index + 1}')));
contents.add(Card(
elevation: 0.5,
// surfaceTintColor: actionCount == _index ? Colors.white : ,
clipBehavior: Clip.antiAlias,
child: GestureDetector(
onTap: () {
log('we tappn');
setState(() {
atm.setAction(currentAction, index, "rep");
});
},
child: Row(children: [
Consumer<ActivityTimerModel>(builder: (context, atm, child) {
return Ink(
padding: const EdgeInsets.all(15),
color: currentAction == atm.currentAction
? const Color.fromARGB(255, 49, 154, 52)
: const Color(0xff3A5FB6),
child: Text('Set: ${index + 1} '));
}),
Expanded(
child: Text(
textAlign: TextAlign.center,
'$title: ${setReps.amounts[index]} reps'))
]))));
actionCount++;
for (int repCount = 0; repCount < setReps.amounts[index]; repCount++) {
contents.add(Card(
child: Padding(
padding: const EdgeInsets.fromLTRB(15, 15, 15, 15),
child: Column(
children: [
Row(children: [Text('Exercise: ${widget.action.title}')]),
Row(children: [Text('Type: ${actionSet.type}')]),
Row(children: [
Text(
'Set: ${index + 1} / ${widget.action.activityActionSet.total}')
]),
Row(children: [
Text('Rep: ${repCount + 1} / ${setReps.amounts[index]}')
]),
Row(children: [Text('Tempo: ${setReps.tempo[index]}')]),
Row(children: [
Text('Weight: ${setReps.weights[index]}')
]),
Row(children: [Text('Rest: ${setReps.rest}')])
],
))));
}
contents.add(Card(
clipBehavior: Clip.antiAlias,
child: GestureDetector(
onTap: () {
setState(() {
atm.setAction(currentAction + 1, index, "rest");
});
},
child: Row(children: [
Consumer<ActivityTimerModel>(builder: (context, atm, child) {
return Ink(
padding: const EdgeInsets.all(15),
color: currentAction + 1 == atm.currentAction
? const Color.fromARGB(255, 49, 154, 52)
: const Color(0xff3A5FB6),
child: Text('Set: ${index + 1} '));
}),
Expanded(
child: Text(
textAlign: TextAlign.center,
'Rest: $setRest seconds'))
]))));
actionCount++;
return Column(children: contents);
},

View File

@ -9,7 +9,6 @@ import 'package:sendtrain/widgets/media_card.dart';
class ActivityView extends StatefulWidget {
ActivityView({super.key, required this.activity});
ActivityModel activity;
@override
@ -20,14 +19,16 @@ class _ActivityViewState extends State<ActivityView> {
@override
Widget build(BuildContext context) {
ActivityModel activity = widget.activity;
ActivityTimerModel atm = Provider.of<ActivityTimerModel>(context, listen: false);
ActivityTimerModel atm =
Provider.of<ActivityTimerModel>(context, listen: false);
// ActivityActionView activityActionView =
// ActivityActionView(action: activity.actions[0]);
if (atm.active == false) {
atm.setupTimer(activity);
}
var content = [
return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
AppBar(
// surfaceTintColor: ThemeData.dark(useMaterial3: true).colorScheme.primary,
// backgroundColor: ThemeData.dark(useMaterial3: true).colorScheme.primaryContainer,
@ -55,55 +56,52 @@ class _ActivityViewState extends State<ActivityView> {
child: Text(
textAlign: TextAlign.left,
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
'Actions:'))
];
for (var action in activity.actions) {
content.add(ActivityActionView(action: action));
}
// add bottom bar to manage activity
content.add(Container(
height: MediaQuery.sizeOf(context).height * .07,
color: ThemeData.dark(useMaterial3: true).colorScheme.primaryContainer,
child: Row(children: [
Expanded(
flex: 1,
child: Flex(direction: Axis.horizontal, children: [
IconButton(
iconSize: 30,
icon: const Icon(Icons.play_arrow_rounded),
onPressed: () =>
atm.startTimer(activity)),
IconButton(
iconSize: 36,
icon: const Icon(Icons.skip_next_rounded),
onPressed: () {})
])),
Expanded(
flex: 1,
child: Consumer<ActivityTimerModel>(
builder: (context, atm, child) {
return Text(
style: const TextStyle(fontSize: 25),
textAlign: TextAlign.center,
'${atm.tickCount}');
},
)),
Expanded(
flex: 1,
child: Padding(
padding: const EdgeInsets.only(right: 10),
child: Consumer<ActivityTimerModel>(
builder: (context, atm, child) {
'Actions:')),
ActivityActionView(action: activity.actions[0]),
Container(
height: MediaQuery.sizeOf(context).height * .07,
color:
ThemeData.dark(useMaterial3: true).colorScheme.primaryContainer,
child: Row(children: [
Expanded(
flex: 1,
child: Flex(direction: Axis.horizontal, children: [
IconButton(
iconSize: 30,
icon: const Icon(Icons.play_arrow_rounded),
onPressed: () => {
atm.startTimer()
}),
IconButton(
iconSize: 36,
icon: const Icon(Icons.skip_next_rounded),
onPressed: () {
atm.incrementAction();
})
])),
Expanded(
flex: 1,
child: Consumer<ActivityTimerModel>(
builder: (context, atm, child) {
return Text(
style: const TextStyle(fontSize: 15),
textAlign: TextAlign.right,
'Set: ${atm.currentSet + 1}/${atm.totalSets}\nRep: ${atm.currentRep + 1}/${atm.totalReps}');
}))),
])));
return Column(
crossAxisAlignment: CrossAxisAlignment.start, children: content);
style: const TextStyle(fontSize: 25),
textAlign: TextAlign.center,
'${atm.tickCount}');
},
)),
Expanded(
flex: 1,
child: Padding(
padding: const EdgeInsets.only(right: 10),
child: Consumer<ActivityTimerModel>(
builder: (context, atm, child) {
return Text(
style: const TextStyle(fontSize: 15),
textAlign: TextAlign.right,
'Set: ${atm.currentSet + 1}/${atm.totalSets}\nRep: ${atm.currentRep + 1}/${atm.totalReps}');
}))),
]))
]);
}
}

View File

@ -39,8 +39,8 @@ class SessionCard extends StatelessWidget {
actions: [
ActivityAction(
id: 1,
title: 'test action',
description: 'test description',
title: '1, 3, 5',
description: 'Move between the first, third, and fifth rungs, alternating hands. Rest and alternate sides, to start',
media: [
Media(
id: 1,
@ -76,8 +76,8 @@ class SessionCard extends StatelessWidget {
actions: [
ActivityAction(
id: 1,
title: 'test action',
description: 'test description',
title: 'Attempt Climb',
description: 'Attempt your selected climb, if you fall off early in the climb, attempt again. 1 repitition equals roughly doing all the moves, not necessarily in 1 attempt.',
media: [
Media(
id: 1,
@ -92,15 +92,15 @@ class SessionCard extends StatelessWidget {
description: 'How to project climbs')
],
activityActionSet: Set(
type: 'drop_set',
total: 3,
type: 'standard',
total: 10,
rest: 300000,
reps: Reps(
type: 'count',
tempo: [2, 3, 5],
amounts: [5, 3, 2],
weights: [50, 70, 80],
rest: 20000))),
tempo: [],
amounts: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
weights: [],
rest: 0))),
],
resources: ['https://www.youtube.com/watch?v=dyAvbUvY_PU']),
ActivityModel(
@ -113,8 +113,8 @@ class SessionCard extends StatelessWidget {
actions: [
ActivityAction(
id: 1,
title: 'test action',
description: 'test description',
title: 'Pull Ups',
description: 'Select your desired weight to add, and pull up. Be sure to fully drop into extension at start, and make sure chin is above bar for a complete rep. Do not kip during the movement.',
media: [
Media(
id: 1,
@ -130,14 +130,14 @@ class SessionCard extends StatelessWidget {
],
activityActionSet: Set(
type: 'drop_set',
total: 3,
total: 5,
rest: 300000,
reps: Reps(
type: 'count',
tempo: [2, 3, 5],
amounts: [5, 3, 2],
weights: [50, 70, 80],
rest: 20000))),
tempo: [],
amounts: [3, 5, 5, 3, 6],
weights: [80, 80, 80, 80, 80],
rest: 0))),
],
resources: ['https://www.youtube.com/watch?v=dyAvbUvY_PU']),
],