//import 'dart:ffi'; import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:habitrack_app/function_widgets/widget_settings_menu/setting_entry.dart'; import 'package:habitrack_app/function_widgets/widget_settings_menu/widget_settings.dart'; import 'package:habitrack_app/infrastructure/widget_wall/items_controller.dart'; import 'package:habitrack_app/infrastructure/widget_wall/items_state.dart'; import 'package:habitrack_app/main.dart'; import 'package:habitrack_app/sembast/timer.dart'; import 'package:logger/logger.dart'; // ignore: must_be_immutable class CompoundWidgetTimer extends ConsumerStatefulWidget { CompoundWidgetTimer({required this.item, super.key}); TimerItem item; double getProgress() { return (item.current / item.goal) / 60; } @override ConsumerState createState() => _CompoundWidgetTimerState(); } class _CompoundWidgetTimerState extends ConsumerState with WidgetsBindingObserver { _CompoundWidgetTimerState(); String button1text = ''; Timer _timer = Timer(Duration.zero, () => ()); DateTime calcDue() { final now = DateTime.now(); const secondsToAdd = 10; const duration = Duration(seconds: secondsToAdd); final futureTime = now.add(duration); Logger().i(futureTime); return DateTime.now(); } void handleButton1() { //start timer from 0 const oneSec = Duration(seconds: 1); if (widget.item.state == 'initial') { widget.item = widget.item.copyWith(state: 'running'); ref.watch(homeControllerProvider).edit(widget.item); _timer = Timer.periodic( oneSec, (Timer funcTimer) { if (widget.item.current == (widget.item.goal * 60)) { setState(() { final now = DateTime.now(); widget.item = widget.item.copyWith( state: 'completed', completedOn: now.toString(), ); ref.watch(homeControllerProvider).edit(widget.item); funcTimer.cancel(); }); } else { setState(() { widget.item = widget.item.copyWith(current: widget.item.current + 1); ref.watch(homeControllerProvider).edit(widget.item); }); } }, ); } // continue timer else if (widget.item.state == 'paused') { widget.item = widget.item.copyWith(state: 'running'); ref.watch(homeControllerProvider).edit(widget.item); _timer = Timer.periodic( const Duration(seconds: 1), (Timer funcTimer) { if (widget.item.current == (widget.item.goal * 60)) { setState(() { final now = DateTime.now(); widget.item = widget.item.copyWith( state: 'completed', completedOn: now.toString(), ); ref.watch(homeControllerProvider).edit(widget.item); funcTimer.cancel(); }); } else { setState(() { widget.item = widget.item.copyWith(current: widget.item.current + 1); ref.watch(homeControllerProvider).edit(widget.item); }); } }, ); } else if (widget.item.state == 'running') { widget.item = widget.item.copyWith(state: 'paused'); ref.watch(homeControllerProvider).edit(widget.item); _timer.cancel(); } else if (widget.item.state == 'completed') {} } void stopTimer() { setState(() { if (_timer.isActive) { _timer.cancel(); } widget.item = widget.item.copyWith( current: 0, state: 'initial', ); ref.watch(homeControllerProvider).edit(widget.item); }); } String _formatCurrent() { final hours = (widget.item.current / 3600).floor(); final minutes = ((widget.item.current - (hours * 3600)) / 60).floor(); return '$hours hours : $minutes minutes'; } String _formattedTime() { final minutesTotal = widget.item.goal; final hours = (minutesTotal / 60).floor(); final minutes = minutesTotal - (hours * 60); return '$hours hours : $minutes minutes'; } void _toggleExpansion() { setState(() { widget.item = widget.item.copyWith(isExpanded: !widget.item.isExpanded); ref.watch(homeControllerProvider).edit(widget.item); }); } String _getButton1Text(BuildContext context) { if (widget.item.state == 'initial') { return AppLocalizations.of(context)!.timerWidget_buttonStart; } else if (widget.item.state == 'running') { return AppLocalizations.of(context)!.timerWidget_buttonPause; } else if (widget.item.state == 'paused') { return AppLocalizations.of(context)!.timerWidget_buttonContinue; } return 'Done'; } @override Widget build(BuildContext context) { ref ..watch(homeControllerProvider) ..watch(itemsProvider); return Container( margin: const EdgeInsets.only(left: 10, top: 10, right: 10, bottom: 10), padding: const EdgeInsets.only(left: 10, top: 15, right: 10, bottom: 15), decoration: BoxDecoration( color: Theme.of(context).colorScheme.primary, borderRadius: const BorderRadius.all(Radius.circular(7)), boxShadow: [ BoxShadow( color: const Color(0x00000000).withOpacity(0.25), spreadRadius: 2, blurRadius: 5, // changes position of shadow ), ], ), width: double.infinity, child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ if (!widget.item.isExpanded) ...[ Icon( Icons.timer, size: 20, color: Theme.of(context).colorScheme.onPrimary, ), Expanded( flex: 2, child: Container( margin: const EdgeInsets.only(left: 10, right: 10), height: 30, child: ClipRRect( borderRadius: const BorderRadius.all( Radius.circular(5), ), // Rounded corners child: LinearProgressIndicator( value: widget.getProgress(), // Progress value (0.0 - 1.0) backgroundColor: Colors.grey.withOpacity(0.5), // Background color valueColor: const AlwaysStoppedAnimation( Color(0xffA4E8FD), ), // Progress color ), ), ), ), Expanded( child: Text( widget.item.name, style: TextStyle( color: Theme.of(context).colorScheme.onPrimary, // alignment: TextAlign.left, ), ), ), ], if (widget.item.isExpanded) ...[ Expanded( child: Text( widget.item.name, textScaler: const TextScaler.linear(2), style: TextStyle( color: Theme.of(context).colorScheme.onPrimary, // alignment: TextAlign.left, ), ), ), Expanded( flex: 0, child: IconButton( icon: Icon( Icons.settings, color: Theme.of(context).colorScheme.onPrimary, ), onPressed: () => _showSettingsMenu(ref), ), ), ], Expanded( flex: 0, child: IconButton( icon: Icon( widget.item.isExpanded ? Icons.arrow_drop_up_outlined : Icons.arrow_drop_down_circle_outlined, color: Theme.of(context).colorScheme.onPrimary, ), onPressed: _toggleExpansion, ), ), ], ), if (widget.item.isExpanded) ...[ // Additional child elements when expanded SizedBox( height: 300, width: MediaQuery.of(context).size.width, child: Column( children: [ Stack( children: [ Container( alignment: Alignment.center, // color: Colors.blueAccent, width: MediaQuery.of(context).size.width, height: 250, child: SizedBox( height: 150, // color: Colors.greenAccent, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( // ignore: lines_longer_than_80_chars '${AppLocalizations.of(context)!.timerWidget_current}: ${_formatCurrent()} \n ${AppLocalizations.of(context)!.timerWidget_goal}: ${_formattedTime()}', style: Theme.of(context) .textTheme .bodyMedium! .copyWith( color: Theme.of(context) .colorScheme .onPrimary, ), ), ], ), ), ), Positioned( top: 10, left: MediaQuery.of(context).size.width * 0.15, width: MediaQuery.of(context).size.width * 0.60, height: 220, child: CircularProgressIndicator( color: Theme.of(context).colorScheme.onPrimary, strokeWidth: 7, value: widget.getProgress(), semanticsLabel: 'Circular progress indicator', ), ), ], ), Expanded( child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.center, children: [ TextButton( onPressed: handleButton1, child: Text( _getButton1Text(context), style: Theme.of(context) .textTheme .bodyMedium! .copyWith( color: Theme.of(context) .colorScheme .onPrimary, ), ), ), TextButton( onPressed: stopTimer, child: Text( AppLocalizations.of(context)! .timerWidget_buttonReset, style: Theme.of(context) .textTheme .bodyMedium! .copyWith( color: Theme.of(context) .colorScheme .onPrimary, ), ), ), ], ), ], ), ), ], ), ), // Add more widgets here as needed ], ], ), ); } Future _showSettingsMenu(WidgetRef ref) async { logger.i('Opening settings'); final settingEntries = WidgetSettingsData( entries: { 'name': SettingEntryText( name: AppLocalizations.of(context)!.widgetSettings_name, defaultValue: widget.item.name, ), 'duration': SettingEntryDuration( name: AppLocalizations.of(context)!.timerWidgetSettings_duration, defaultValue: widget.item.goal, ), }, ); if (widget.item.state == 'running') { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( AppLocalizations.of(context)!.timerWidget_pausedForEdit, ), ), ); } else { return showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { return AlertDialog( backgroundColor: Theme.of(context).colorScheme.primaryContainer, content: WidgetSettings( entries: settingEntries, ), actions: [ OutlinedButton( style: OutlinedButton.styleFrom( backgroundColor: Colors.red, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), onPressed: () async { ref.watch(itemsProvider); final items = ref.watch(homeControllerProvider); widget.item = widget.item.copyWith(isVisible: false); setState(() { items.edit(widget.item); }); logger.i('Attempting delete'); // ignore: use_build_context_synchronously Navigator.of(context).pop(); }, child: Text( AppLocalizations.of(context)!.widgetSettings_deleteButton, style: Theme.of(context).textTheme.bodyMedium!.copyWith( color: Theme.of(context).colorScheme.onPrimary, fontWeight: FontWeight.bold, ), ), ), ElevatedButton( style: ElevatedButton.styleFrom( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), backgroundColor: Theme.of(context).colorScheme.onPrimary, ), onPressed: () { _timer.cancel(); ref.watch(homeControllerProvider); logger.i('Attempting edit of name and/or duration'); final name = settingEntries.getValue('name') as String; logger.i('New name: $name'); final duration = settingEntries.getValue('duration') as int; widget.item = widget.item.copyWith(goal: duration, name: name); setState(() { ref.watch(homeControllerProvider).edit(widget.item); }); logger.i('NAME AND DURATION SUCCESSFULLY UPDATED'); Navigator.of(context).pop(); }, child: Text( AppLocalizations.of(context)!.widgetSettings_saveButton, style: Theme.of(context).textTheme.bodyMedium!.copyWith( color: Theme.of(context).colorScheme.primary, fontWeight: FontWeight.bold, ), ), ), ], ); }, ); } } }