action display, and full display, started action editor
This commit is contained in:
173
lib/providers/action_timer.dart
Normal file
173
lib/providers/action_timer.dart
Normal file
@ -0,0 +1,173 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
||||
import 'package:sendtrain/database/database.dart';
|
||||
import 'package:sendtrain/models/action_model.dart';
|
||||
|
||||
class ActionTimer with ChangeNotifier {
|
||||
ActionModel? actionModel;
|
||||
double _progress = 0;
|
||||
int _currentTime = 0;
|
||||
final List<ItemScrollController> _scrollControllers = [];
|
||||
|
||||
ActionTimer();
|
||||
|
||||
Map get state => actionModel?.state ?? _stateConstructor();
|
||||
ActionStatus get status => actionModel?.status ?? ActionStatus.pending;
|
||||
bool get started => status == ActionStatus.started;
|
||||
bool get paused => status == ActionStatus.paused;
|
||||
bool get pending => status == ActionStatus.pending;
|
||||
bool get complete => status == ActionStatus.complete;
|
||||
bool get available => paused | pending;
|
||||
List<Set> get sets => actionModel!.sets;
|
||||
List<Item> get items => actionModel!.items;
|
||||
Set get currentSet => sets[state['currentSet']];
|
||||
Reps get currentRep => currentSet.reps[state['currentRep']];
|
||||
Item get currentAction => allActions[state['currentAction']];
|
||||
int get currentTime => _currentTime;
|
||||
dynamic get currentValue => currentAction.valueType == RepType.time
|
||||
? currentTime
|
||||
: currentAction.value;
|
||||
List<Item> get allActions => actionModel?.allItems ?? [];
|
||||
String get repType =>
|
||||
actionModel!.action.repType == RepType.time ? 'Seconds' : 'Reps';
|
||||
int? get repLength => currentRep.value;
|
||||
int? get repCount => currentRep.count;
|
||||
dynamic get repValue =>
|
||||
actionModel!.action.repType == RepType.time ? repLength : repCount;
|
||||
double get progress => _progress;
|
||||
int get totalTime => actionModel!.totalTime;
|
||||
Timer? _periodicTimer;
|
||||
|
||||
Map _stateConstructor() {
|
||||
return {
|
||||
'currentSet': 0,
|
||||
'currentRep': 0,
|
||||
'currentTime': 0,
|
||||
'currentAction': 0
|
||||
};
|
||||
}
|
||||
|
||||
void setup(ActionModel actionModel, ItemScrollController scrollController,
|
||||
[bool resetOnLoad = true]) {
|
||||
if (resetOnLoad) {
|
||||
if (this.actionModel == actionModel) {
|
||||
reset();
|
||||
}
|
||||
|
||||
this.actionModel = actionModel;
|
||||
setAction(currentAction.id);
|
||||
}
|
||||
|
||||
_scrollControllers.add(scrollController);
|
||||
}
|
||||
|
||||
Future pause() async =>
|
||||
await actionModel?.updateStatus(ActionStatus.paused).whenComplete(() {
|
||||
_periodicTimer?.cancel();
|
||||
notifyListeners();
|
||||
});
|
||||
|
||||
Future start() async {
|
||||
await actionModel!.updateStatus(ActionStatus.started);
|
||||
|
||||
// start timer
|
||||
if (_periodicTimer == null || _periodicTimer!.isActive == false) {
|
||||
_periodicTimer =
|
||||
Timer.periodic(const Duration(seconds: 1), (Timer timer) async {
|
||||
switch (currentAction.valueType) {
|
||||
case RepType.count:
|
||||
break;
|
||||
case RepType.time:
|
||||
_currentTime--;
|
||||
|
||||
if (_currentTime == 0) {
|
||||
// move to next action
|
||||
await setAction(state['currentAction'] + 1);
|
||||
}
|
||||
|
||||
await updateProgress();
|
||||
notifyListeners();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future close() async =>
|
||||
await actionModel!.updateStatus(ActionStatus.complete).whenComplete(() {
|
||||
_periodicTimer!.cancel();
|
||||
notifyListeners();
|
||||
});
|
||||
|
||||
Future reset() async {
|
||||
await actionModel!.updateStatus(ActionStatus.pending);
|
||||
await actionModel!.updateState(json.encode(_stateConstructor()));
|
||||
_periodicTimer?.cancel();
|
||||
_progress = 0;
|
||||
_scrollControllers.clear();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future clear() async {
|
||||
await reset();
|
||||
}
|
||||
|
||||
double timeUsed() {
|
||||
Iterable<Item> usedItems = allActions.getRange(0, state['currentAction']);
|
||||
return usedItems.fold(0.0, (p, c) => p + c.value!);
|
||||
}
|
||||
|
||||
double totalComplete() {
|
||||
Iterable<Item> usedItems = allActions.getRange(0, state['currentAction']);
|
||||
return usedItems.length / allActions.length;
|
||||
}
|
||||
|
||||
updateProgress() {
|
||||
double repUsed = (currentAction.value - currentTime) / currentAction.value;
|
||||
_progress =
|
||||
totalComplete() + ((repUsed < 0 ? 0 : repUsed) / allActions.length);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
setAction(int actionNum, [bool isManual = false]) async {
|
||||
Item item = allActions[actionNum];
|
||||
Map newState = state;
|
||||
|
||||
newState['currentAction'] = actionNum;
|
||||
newState['currentSet'] = item.parentId;
|
||||
newState['currentRep'] = item.id;
|
||||
newState['currentTime'] = _currentTime = item.value!;
|
||||
|
||||
await actionModel!
|
||||
.updateState(json.encode(newState))
|
||||
.whenComplete(() async {
|
||||
if (isManual) {
|
||||
await pause();
|
||||
await updateProgress();
|
||||
}
|
||||
|
||||
int index = currentAction.parentId != null
|
||||
? currentAction.parentId!
|
||||
: currentAction.id;
|
||||
|
||||
for (int i = 0; i < _scrollControllers.length; i++) {
|
||||
ItemScrollController sc = _scrollControllers[i];
|
||||
|
||||
sc.scrollTo(
|
||||
index: index,
|
||||
duration: Duration(milliseconds: 500),
|
||||
curve: Curves.easeInOutCubic);
|
||||
}
|
||||
// _scrollController?.scrollTo(
|
||||
// index: index,
|
||||
// duration: Duration(milliseconds: 500),
|
||||
// curve: Curves.easeInOutCubic);
|
||||
});
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user