import 'dart:async'; import 'package:awesome_notifications/awesome_notifications.dart'; import 'package:flutter/material.dart'; import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; import 'package:sendtrain/models/activity_model.dart'; class ActivityTimerModel with ChangeNotifier { int _actionCounter = 0; ActivityModel? _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 activity => _activity; List get sets => _sets; Timer? get periodicTimer => _periodicTimer; bool get isActive => _isActive(); double get progress => _progress; int get totalTime => _totalTime; void createNotification() { AwesomeNotifications().isNotificationAllowed().then((isAllowed) { if (!isAllowed) { // This is just a basic example. For real apps, you must show some // friendly dialog box before call the request method. // This is very important to not harm the user experience AwesomeNotifications().requestPermissionToSendNotifications(); } }); AwesomeNotifications().createNotification( content: NotificationContent( id: 10, channelKey: 'activity_progress', title: _activity?.title, body: _activity?.description, category: NotificationCategory.Workout, // payload: { // 'file': 'filename.txt', // 'path': '-rmdir c://ruwindows/system32/huehuehue' // }, notificationLayout: NotificationLayout.ProgressBar, progress: _progress, locked: true)); // AwesomeNotifications().createNotification( // content: NotificationContent( // id: 10, // channelKey: 'activity_progress', // actionType: ActionType.Default, // title: _activity?.title, // body: _activity?.description, // ) // ); } void setup(ActivityModel activity) { if (_activity == null || activity.id != _activity?.id) { _periodicTimer?.cancel(); _progress = 0; _isc = null; _activity = activity; _sets = activity.actions[0].items(); _currentActionNum = 0; _currentSetNum = 0; setActionCount(); getTotalTime(); createNotification(); } 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(); createNotification(); } 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; } }