import 'dart:async'; import 'package:flutter/material.dart'; import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; import 'package:sendtrain/database/database.dart'; import 'package:sendtrain/models/activity_model.dart'; class ActivityTimerModel with ChangeNotifier { int _actionCounter = 0; ActivityModel? _activityModel; Activity? _activity; List _sets = []; int _currentActionNum = 0; int _currentSetNum = 0; Timer? _periodicTimer; double _progress = 0; ItemScrollController? _isc; int _totalTime = 0; int get actionCount => _actionCounter; int get currentActionNum => _currentActionNum; dynamic get currentAction => currentSet[_currentActionNum]; int get currentSetNum => _currentSetNum; dynamic get currentSet => _sets[_currentSetNum]; ActivityModel? get activityModel => _activityModel; Activity? get activity => _activity; List get sets => _sets; Timer? get periodicTimer => _periodicTimer; bool get isActive => _isActive(); double get progress => _progress; int get totalTime => _totalTime; void setup(ActivityModel activityModel, Activity activity) { if (_activityModel == null || activityModel.id != _activityModel?.id) { _periodicTimer?.cancel(); _progress = 0; _isc = null; _activityModel = activityModel; _activity = activity; _sets = activityModel.actions[0].items(); _currentActionNum = 0; _currentSetNum = 0; setActionCount(); getTotalTime(); } moveToIndex(_currentSetNum); } void getTotalTime() { int time = 0; for(int setIndex = 0; _sets.length > setIndex; setIndex++) { for (int actionIndex = 0; _sets[setIndex].length > actionIndex; actionIndex++) { var action = _sets[setIndex][actionIndex]; if (action['type'] == 'seconds') { time = time + action['amount'] as int; } } } _totalTime = time; } void reset() { _progress = 0; _currentActionNum = 0; _currentSetNum = 0; _periodicTimer!.cancel(); setActionCount(); moveToIndex(0); } void setScrollController(ItemScrollController isc) { _isc = isc; } bool isCurrentItem(int setNum, int actionNum) { if (setNum == _currentSetNum && actionNum == _currentActionNum) { return true; } return false; } int totalActions() { int count = 0; for (int i = 0; i < _sets.length; i++) { count = count + _sets[i].length as int; } return count; } void setActionCount() { _actionCounter = currentAction['amount']; } void pause() { _periodicTimer!.cancel(); notifyListeners(); } void start() { _periodicTimer = Timer.periodic(const Duration(seconds: 1), (Timer timer) { switch (currentAction['type']) { // we don't want to count down // if its repititions case 'repititions': break; case 'seconds': if (_actionCounter > 0) { _actionCounter--; _totalTime--; } else { nextAction(_currentActionNum + 1); setActionCount(); } updateProgress(); } notifyListeners(); }); } void updateProgress() { _progress = (currentAction['actionID'] + (1.0 - _actionCounter / currentAction['amount'])) / totalActions(); notifyListeners(); } void setAction(int setNum, int actionNum, String type) { _currentActionNum = actionNum; _currentSetNum = setNum; notifyListeners(); moveToIndex(_currentSetNum); } void nextAction(int nextActionIndex) { if (currentSet.length > nextActionIndex) { setAction(_currentSetNum, nextActionIndex, 'automatic'); } else if (_sets.length > _currentSetNum + 1) { // if the item isn't in the set // increment the set and reset action index setAction(_currentSetNum + 1, 0, 'automatic'); } else { // if we're done all the sets // cancel timer and reset activity reset(); } } void moveToIndex(int index) { if (_isc != null && _isc!.isAttached) { _isc?.scrollTo( index: index, duration: Duration(milliseconds: 500), curve: Curves.easeInOutCubic); } } bool _isActive() { return (_periodicTimer != null && _periodicTimer!.isActive) ? true : false; } }