import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; import 'package:sendtrain/database/database.dart'; import 'package:sendtrain/extensions/string_extensions.dart'; import 'package:sendtrain/models/action_model.dart'; import 'package:sendtrain/providers/action_timer.dart'; import 'package:sendtrain/widgets/generic/elements/add_card_generic.dart'; class ActivityActionView extends StatefulWidget { const ActivityActionView({super.key, required this.actions, this.resetOnLoad = true}); final List actions; final bool resetOnLoad; @override State createState() => ActivityActionViewState(); } class ActivityActionViewState extends State { // class ActivityActionView extends StatelessWidget { // ActivityActionView({super.key, required this.actions}); // final List actions; final ItemScrollController itemScrollController = ItemScrollController(); final ScrollOffsetController scrollOffsetController = ScrollOffsetController(); final ItemPositionsListener itemPositionsListener = ItemPositionsListener.create(); final ScrollOffsetListener scrollOffsetListener = ScrollOffsetListener.create(); late final ActionTimer at; int actionCount = 0; GestureDetector gtBuild( ActionTimer at, Item item, int actionNum, int selectedIndex, {int? order}) { // default, for rests String setItemRef = '-'; // non rests decimal reference to item if (order != null) { setItemRef = '${order + 1}.${item.position + 1}'; } return GestureDetector(onTap: () { at.setAction(actionNum, true); }, child: Consumer(builder: (context, at, child) { return Row(children: [ Ink( width: 70, padding: const EdgeInsets.all(15), color: item == at.currentAction ? Theme.of(context).colorScheme.primaryContainer : Theme.of(context).colorScheme.onPrimary, child: Text(textAlign: TextAlign.center, setItemRef)), Expanded( child: Ink( padding: const EdgeInsets.all(15), color: item == at.currentAction ? Theme.of(context).colorScheme.surfaceBright : Theme.of(context).colorScheme.surfaceContainerLow, child: Text( textAlign: TextAlign.center, '${item.name}: ${item.value} ${item.humanValueType}' .toTitleCase()))) ]); })); } @override void initState() { super.initState(); at = Provider.of(context, listen: false); } @override Widget build(BuildContext context) { if (widget.actions.isNotEmpty) { at.setup(ActionModel( action: widget.actions.first, db: Provider.of(context)), itemScrollController, widget.resetOnLoad); // WidgetsBinding.instance.addPostFrameCallback((_) { // if (itemScrollController.isAttached) { // itemScrollController.scrollTo( // index: at.currentAction.parentId != null // ? at.currentAction.parentId! // : at.currentAction.id, // duration: Duration(milliseconds: 500), // curve: Curves.easeInOutCubic); // } // }); return Expanded( child: Column(children: [ Padding( padding: const EdgeInsets.only(left: 10, right: 10), child: Card( clipBehavior: Clip.antiAlias, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.only( topLeft: Radius.circular(10), topRight: Radius.circular(10)), ), color: Theme.of(context).colorScheme.onPrimary, child: Row(children: [ Ink( width: 70, color: Theme.of(context).colorScheme.primaryContainer, child: Consumer( builder: (context, at, child) { return IconButton( alignment: AlignmentDirectional.center, icon: at.available ? const Icon(Icons.play_arrow_rounded) : const Icon(Icons.pause_rounded), onPressed: () => { if (at.started) {at.pause()} else if (at.available) {at.start()} }); }, )), Expanded( flex: 1, child: Stack(alignment: Alignment.center, children: [ Container( alignment: Alignment.center, child: Consumer( builder: (context, at, child) { return Text( style: const TextStyle(fontSize: 20), textAlign: TextAlign.center, '${at.currentValue} ${at.currentAction.humanValueType}' .toTitleCase()); }, ), ), Container( alignment: Alignment.centerRight, padding: EdgeInsets.only(right: 15), child: Consumer( builder: (context, at, child) { return Text( style: const TextStyle(fontSize: 12), textAlign: TextAlign.right, '${at.state['currentAction'] + 1} of ${at.allActions.length}'); })), ])), ]))), Padding( padding: EdgeInsets.only(left: 14, right: 14), child: Consumer(builder: (context, at, child) { return LinearProgressIndicator( value: at.progress, semanticsLabel: 'Activity Progress', ); })), Expanded( child: ScrollablePositionedList.builder( padding: const EdgeInsets.fromLTRB(10, 0, 10, 20), itemCount: at.items.length, // initialScrollIndex: at.currentAction.parentId != null // ? at.currentAction.parentId! // : at.currentAction.id, itemScrollController: itemScrollController, scrollOffsetController: scrollOffsetController, itemPositionsListener: itemPositionsListener, scrollOffsetListener: scrollOffsetListener, itemBuilder: (BuildContext context, int itemNum) { if (itemNum == 0) { actionCount = 0; } List content = []; Item item = at.items[itemNum]; if (item.runtimeType == Rest) { content.add(gtBuild(at, item, actionCount++, itemNum)); } else if (item.runtimeType == Set) { List setItems = item.items; for (int setItemNum = 0; setItemNum < setItems.length; setItemNum++) { Item setItem = setItems[setItemNum]; content.add(gtBuild(at, setItem, actionCount++, itemNum, order: (item as Set).setOrder)); } } if (itemNum == 0) { return Card( shape: const RoundedRectangleBorder( borderRadius: BorderRadius.only( topLeft: Radius.circular(0), topRight: Radius.circular(0), bottomLeft: Radius.circular(10), bottomRight: Radius.circular(10)), ), clipBehavior: Clip.antiAlias, child: Column(children: content)); } else { return Card( shape: const RoundedRectangleBorder( borderRadius: BorderRadius.only( topLeft: Radius.circular(10), topRight: Radius.circular(10), bottomLeft: Radius.circular(10), bottomRight: Radius.circular(10)), ), clipBehavior: Clip.antiAlias, child: Column(children: content)); } })) ])); } else { return AddCardGeneric( title: 'Add an Action!', description: 'Click here to create an exercise template (sets and reps, etc) for your activity!', action: () { print('teset'); }); } } }