diff --git a/fastlane/metadata/android/en-US/changelogs/191.txt b/fastlane/metadata/android/en-US/changelogs/191.txt index 190ff4f2..0a190667 100644 --- a/fastlane/metadata/android/en-US/changelogs/191.txt +++ b/fastlane/metadata/android/en-US/changelogs/191.txt @@ -6,12 +6,16 @@ ✨ Enhancements -* Added count setting to math tasks +* Added count setting to math and retype tasks * Added option to select default UI for selecting time * Added credits to about page +* Improved timer fullscreen button UI on smaller devices +* Improved timer fullscreen layout in landscape mode 🐛 Fixes * Fixed numbers appearing after melody name * Fixed alarm screen not updating after adding alarm through external app * Fixed snackbar text clipping +* Fixed alarm tasks not getting deleted properly +* Fixed alarm tasks not working properly when same task is added multiple times diff --git a/fastlane/metadata/android/en-US/changelogs/192.txt b/fastlane/metadata/android/en-US/changelogs/192.txt index 816cfce6..0a190667 100644 --- a/fastlane/metadata/android/en-US/changelogs/192.txt +++ b/fastlane/metadata/android/en-US/changelogs/192.txt @@ -6,11 +6,16 @@ ✨ Enhancements -* Added count setting to math tasks +* Added count setting to math and retype tasks * Added option to select default UI for selecting time - +* Added credits to about page +* Improved timer fullscreen button UI on smaller devices +* Improved timer fullscreen layout in landscape mode 🐛 Fixes * Fixed numbers appearing after melody name * Fixed alarm screen not updating after adding alarm through external app +* Fixed snackbar text clipping +* Fixed alarm tasks not getting deleted properly +* Fixed alarm tasks not working properly when same task is added multiple times diff --git a/fastlane/metadata/android/en-US/changelogs/193.txt b/fastlane/metadata/android/en-US/changelogs/193.txt index 816cfce6..0a190667 100644 --- a/fastlane/metadata/android/en-US/changelogs/193.txt +++ b/fastlane/metadata/android/en-US/changelogs/193.txt @@ -6,11 +6,16 @@ ✨ Enhancements -* Added count setting to math tasks +* Added count setting to math and retype tasks * Added option to select default UI for selecting time - +* Added credits to about page +* Improved timer fullscreen button UI on smaller devices +* Improved timer fullscreen layout in landscape mode 🐛 Fixes * Fixed numbers appearing after melody name * Fixed alarm screen not updating after adding alarm through external app +* Fixed snackbar text clipping +* Fixed alarm tasks not getting deleted properly +* Fixed alarm tasks not working properly when same task is added multiple times diff --git a/lib/alarm/data/alarm_task_schemas.dart b/lib/alarm/data/alarm_task_schemas.dart index 09255326..bb32d11a 100644 --- a/lib/alarm/data/alarm_task_schemas.dart +++ b/lib/alarm/data/alarm_task_schemas.dart @@ -37,6 +37,8 @@ Map alarmTaskSchemasMap = { SliderSetting("Number of characters", 5, 20, 5, snapLength: 1), SwitchSetting("Include numbers", false), SwitchSetting("Include lowercase", false), + SliderSetting("Number of problems", 1, 10, 1, snapLength: 1), + ]), (onSolve, settings) { return RetypeTask(onSolve: onSolve, settings: settings); diff --git a/lib/alarm/screens/alarm_notification_screen.dart b/lib/alarm/screens/alarm_notification_screen.dart index 89ad197b..9bc4dc88 100644 --- a/lib/alarm/screens/alarm_notification_screen.dart +++ b/lib/alarm/screens/alarm_notification_screen.dart @@ -51,6 +51,7 @@ class _AlarmNotificationScreenState extends State { _currentWidget = alarm.tasks[_currentIndex].builder(_setNextWidget); } _currentIndex++; + print("######################## $_currentIndex"); }); } diff --git a/lib/alarm/types/alarm_task.dart b/lib/alarm/types/alarm_task.dart index b9b58c46..c6db1bc9 100644 --- a/lib/alarm/types/alarm_task.dart +++ b/lib/alarm/types/alarm_task.dart @@ -49,21 +49,27 @@ class AlarmTaskSchema extends JsonSerializable { } class AlarmTask extends CustomizableListItem { - late AlarmTaskType type; - late AlarmTaskSchema _schema; + late int _id; + late AlarmTaskType type; + late AlarmTaskSchema _schema; - AlarmTask(this.type) : _schema = alarmTaskSchemasMap[type]!.copy(); + AlarmTask(this.type) + : _schema = alarmTaskSchemasMap[type]!.copy(), + _id = UniqueKey().hashCode; AlarmTask.from(AlarmTask task) : type = task.type, + _id = UniqueKey().hashCode, _schema = task._schema.copy(); AlarmTask.fromJson(Json json) { if (json == null) { + _id = UniqueKey().hashCode; type = AlarmTaskType.math; _schema = alarmTaskSchemasMap[type]!.copy(); return; } + _id = json['id'] ?? UniqueKey().hashCode; type = AlarmTaskType.values.byName(json['type']); _schema = alarmTaskSchemasMap[type]!.copy(); _schema.loadFromJson(json['schema']); @@ -74,14 +80,14 @@ class AlarmTask extends CustomizableListItem { return AlarmTask.from(this); } - @override + @override void copyFrom(dynamic other) { - type = other.type; - _schema = other._schema.copy(); + type = other.type; + _schema = other._schema.copy(); } @override - int get id => _schema.name.hashCode; + int get id => _id; @override bool get isDeletable => true; AlarmTaskSchema get schema => _schema; @@ -93,6 +99,7 @@ class AlarmTask extends CustomizableListItem { @override Json toJson() { return { + 'id': _id, 'schema': _schema.toJson(), 'type': type.name, }; diff --git a/lib/alarm/widgets/tasks/math_task.dart b/lib/alarm/widgets/tasks/math_task.dart index 4b9b5017..1a6cf396 100644 --- a/lib/alarm/widgets/tasks/math_task.dart +++ b/lib/alarm/widgets/tasks/math_task.dart @@ -81,12 +81,25 @@ class MathTask extends StatefulWidget { class _MathTaskState extends State { final TextEditingController _textController = TextEditingController(); - late final MathTaskDifficultyLevel _difficultyLevel = - widget.settings.getSetting("Difficulty").value; - late final _problemCount = - widget.settings.getSetting("Number of problems").value; + late MathTaskDifficultyLevel _difficultyLevel; + late double _problemCount; int _problemsSolved = 0; + void initialize() { + _difficultyLevel = widget.settings.getSetting("Difficulty").value; + _problemCount = widget.settings.getSetting("Number of problems").value; + _problemsSolved = 0; + _difficultyLevel.generateProblem(); + _textController.clear(); + + } + + @override + void didUpdateWidget(covariant MathTask oldWidget) { + super.didUpdateWidget(oldWidget); + initialize(); + } + @override void initState() { super.initState(); @@ -94,16 +107,17 @@ class _MathTaskState extends State { if (_textController.text == _difficultyLevel._answer && _problemsSolved < _problemCount) { _problemsSolved += 1; - setState(() { - _difficultyLevel.generateProblem(); - _textController.clear(); - }); - } - if (_problemsSolved >= _problemCount) { - widget.onSolve(); + if (_problemsSolved >= _problemCount) { + widget.onSolve(); + } else { + setState(() { + _difficultyLevel.generateProblem(); + _textController.clear(); + }); + } } }); - _difficultyLevel.generateProblem(); + initialize(); } @override diff --git a/lib/alarm/widgets/tasks/retype_task.dart b/lib/alarm/widgets/tasks/retype_task.dart index 92660828..998a953f 100644 --- a/lib/alarm/widgets/tasks/retype_task.dart +++ b/lib/alarm/widgets/tasks/retype_task.dart @@ -24,27 +24,51 @@ class _RetypeTaskState extends State { final TextEditingController _textController = TextEditingController(); final Random _random = Random(); - late final int characterCount = - widget.settings.getSetting("Number of characters").value.toInt(); - late final bool includeNumbers = - widget.settings.getSetting("Include numbers").value; - late final bool includeLowercase = - widget.settings.getSetting("Include lowercase").value; - late final String _chars = - "ABCDEFGHIJKLMNOPQRSTUVWXYZ${includeLowercase ? "abcdefghijklmnopqrstuvwxyz" : ""}${includeNumbers ? "0123456789" : ""}"; + late int characterCount; + late bool includeNumbers; + late bool includeLowercase; + late String _chars; + late double _problemCount; + int _problemsSolved = 0; - late final String string = _generateRandomString(characterCount); - bool _isSolved = false; + late String string; + + void initialize() { + characterCount = + widget.settings.getSetting("Number of characters").value.toInt(); + includeNumbers = widget.settings.getSetting("Include numbers").value; + includeLowercase = widget.settings.getSetting("Include lowercase").value; + _chars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ${includeLowercase ? "abcdefghijklmnopqrstuvwxyz" : ""}${includeNumbers ? "0123456789" : ""}"; + _problemCount = widget.settings.getSetting("Number of problems").value; + _problemsSolved = 0; + string = _generateRandomString(characterCount); + _textController.clear(); + } + + @override + void didUpdateWidget(covariant RetypeTask oldWidget) { + super.didUpdateWidget(oldWidget); + initialize(); + } @override void initState() { super.initState(); _textController.addListener(() { - if (_textController.text == string && !_isSolved) { - _isSolved = true; - widget.onSolve.call(); + if (_textController.text == string && _problemsSolved < _problemCount) { + _problemsSolved += 1; + if (_problemsSolved >= _problemCount) { + widget.onSolve(); + } else { + setState(() { + string = _generateRandomString(characterCount); + _textController.clear(); + }); + } } }); + initialize(); } @override @@ -68,6 +92,7 @@ class _RetypeTaskState extends State { Widget build(BuildContext context) { ThemeData theme = Theme.of(context); TextTheme textTheme = theme.textTheme; + ColorScheme colorScheme = theme.colorScheme; Size textSize = calcTextSizeFromLength(characterCount + 5, textTheme.displaySmall!); @@ -80,6 +105,20 @@ class _RetypeTaskState extends State { style: Theme.of(context).textTheme.headlineMedium, ), const SizedBox(height: 16.0), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + for (int i = 0; i < _problemCount; i++) + Padding( + padding: const EdgeInsets.all(4.0), + child: Icon( + _problemsSolved > i ? Icons.circle : Icons.circle_outlined, + color: colorScheme.primary, + ), + ), + ], + ), + const SizedBox(height: 16.0), CardContainer( child: SizedBox( width: double.infinity, diff --git a/lib/common/widgets/card_container.dart b/lib/common/widgets/card_container.dart index e061c55f..202433c3 100644 --- a/lib/common/widgets/card_container.dart +++ b/lib/common/widgets/card_container.dart @@ -38,28 +38,7 @@ class CardContainer extends StatelessWidget { Widget build(BuildContext context) { ThemeData theme = Theme.of(context); ColorScheme colorScheme = theme.colorScheme; - return - // Card.filled( - // elevation: 1, - // // margin: margin ?? const EdgeInsets.all(4), - // // clipBehavior: Clip.hardEdge, - // // shape: RoundedRectangleBorder( - // // borderRadius: BorderRadius.circular(16), - // // side: showLightBorder - // // ? BorderSide( - // // color: Theme.of(context).colorScheme.onBackground.withOpacity(0.1), - // // width: 1, - // // ) - // // : BorderSide.none, - // // ), - // color: color, - // child: InkWell( - // onTap: onTap, - // child: child, - // ), - // - // ); - Container( + return Container( alignment: alignment, margin: margin ?? const EdgeInsets.all(4), clipBehavior: Clip.hardEdge, diff --git a/lib/common/widgets/circular_progress_bar.dart b/lib/common/widgets/circular_progress_bar.dart index 219ba61c..9a1a798d 100644 --- a/lib/common/widgets/circular_progress_bar.dart +++ b/lib/common/widgets/circular_progress_bar.dart @@ -120,7 +120,7 @@ class _CircularProgressBarState extends State final double minSweepAngle = 0.015; late double circleLength; - late double widgetSize; + // late double widgetSize; late double startAngle; late double correctAngle; @@ -135,7 +135,7 @@ class _CircularProgressBarState extends State void updateState() { setState(() { - widgetSize = (widget.size <= 0) ? 100.0 : widget.size; + // widgetSize = (widget.size <= 0) ? 100.0 : widget.size; // Check value notifier if (widget.valueNotifier != null) { @@ -149,7 +149,7 @@ class _CircularProgressBarState extends State // Calculate the real starting angle and correction angle. // Correction angle - the angle to which the main line should be // shifted in order for the SweepGradient to be displayed correctly. - circleLength = pi * widgetSize; + circleLength = pi * widget.size; final k = _doublePi / circleLength; correctAngle = widget.progressStrokeWidth * k; @@ -255,7 +255,7 @@ class _CircularProgressBarState extends State Transform.rotate( angle: _degToRad(widget.startAngle - 90), child: CustomPaint( - size: Size(widgetSize, widgetSize), + size: Size(widget.size, widget.size), painter: _SimpleCircularProgressBarPainter( progressStrokeWidth: widget.progressStrokeWidth, backStrokeWidth: widget.backStrokeWidth, diff --git a/lib/common/widgets/list/custom_list_view.dart b/lib/common/widgets/list/custom_list_view.dart index 76dcf996..c84e61df 100644 --- a/lib/common/widgets/list/custom_list_view.dart +++ b/lib/common/widgets/list/custom_list_view.dart @@ -2,6 +2,7 @@ import 'package:clock_app/common/logic/get_list_filter_chips.dart'; import 'package:clock_app/common/types/list_controller.dart'; import 'package:clock_app/common/types/list_filter.dart'; import 'package:clock_app/common/types/list_item.dart'; +import 'package:clock_app/common/utils/json_serialize.dart'; import 'package:clock_app/common/utils/reorderable_list_decorator.dart'; import 'package:clock_app/common/widgets/list/delete_alert_dialogue.dart'; import 'package:clock_app/common/widgets/list/list_filter_chip.dart'; @@ -198,6 +199,8 @@ class _CustomListViewState [bool callOnModifyList = true]) async { int index = _getItemIndex(deletedItem); + // print(listToString(widget.items)); + setState(() { widget.items.removeWhere((element) => element.id == deletedItem.id); updateCurrentList(); diff --git a/lib/settings/widgets/list_setting_screen.dart b/lib/settings/widgets/list_setting_screen.dart index 68b2f7ca..e99d2a7b 100644 --- a/lib/settings/widgets/list_setting_screen.dart +++ b/lib/settings/widgets/list_setting_screen.dart @@ -87,7 +87,7 @@ class _ListSettingScreenState onPressed: () async { Item? item = await _openAddBottomSheet(); if (item == null) return; - _listController.addItem(item); + _listController.addItem(item.copy()); }, ) ], diff --git a/lib/timer/screens/timer_fullscreen.dart b/lib/timer/screens/timer_fullscreen.dart index 2c8f8a65..4e088667 100644 --- a/lib/timer/screens/timer_fullscreen.dart +++ b/lib/timer/screens/timer_fullscreen.dart @@ -62,136 +62,203 @@ class _TimerFullscreenState extends State { ThemeData theme = Theme.of(context); ColorScheme colorScheme = theme.colorScheme; TextTheme textTheme = theme.textTheme; - Orientation orientation = MediaQuery.of(context).orientation; - double buttonSize = orientation == Orientation.portrait ? 84 : 64; - double largeButtonSize = orientation == Orientation.portrait ? 96 : 72; - double width = MediaQuery.of(context).size.width - 64; - double height = MediaQuery.of(context).size.height - 128; + // Orientation orientation = MediaQuery.of(context).orientation; return Scaffold( - appBar: AppTopBar(actions: [ - TextButton( - onPressed: () async { - ClockTimer? newTimer = await widget.onCustomize(timer); - if (newTimer != null) { - setState(() { - timer.copyFrom(newTimer); - updateTimer(); - }); - } - }, - child: const Text("Edit")) - ]), - body: SizedBox( - width: orientation == Orientation.portrait ? double.infinity : null, - height: orientation == Orientation.landscape ? double.infinity : null, - child: Flex( - direction: orientation == Orientation.portrait - ? Axis.vertical - : Axis.horizontal, - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Text( - timer.label, - style: Theme.of(context).textTheme.displayMedium?.copyWith( - color: Theme.of(context) - .colorScheme - .onBackground - .withOpacity(0.6), - ), - maxLines: 1, - overflow: TextOverflow.ellipsis, - softWrap: false, - ), - ), - const SizedBox(height: 32), - TimerProgressBar( - timer: timer, - size: orientation == Orientation.portrait ? width : height), - const SizedBox(height: 32), - Padding( - padding: - const EdgeInsets.only(left: 20.0, right: 20.0, bottom: 20.0), - child: Flex( - direction: orientation == Orientation.portrait - ? Axis.horizontal - : Axis.vertical, - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - if (timer.state != TimerState.stopped) - SizedBox( - width: buttonSize, - height: buttonSize, - child: CardContainer( - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Icon( - Icons.replay_rounded, - color: colorScheme.primary, - size: 32, - // size: 64, - )), - onTap: () async { - await widget.onReset(timer); - updateTimer(); - }, - ), - ), - Expanded( - flex: 999, - child: CardContainer( - alignment: Alignment.center, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: timer.isRunning - ? Icon( - Icons.pause_rounded, + appBar: AppTopBar( + title: Text(timer.label, + style: textTheme.titleMedium?.copyWith( + color: colorScheme.onBackground.withOpacity(0.6), + )), + actions: [ + TextButton( + onPressed: () async { + ClockTimer? newTimer = await widget.onCustomize(timer); + if (newTimer != null) { + setState(() { + timer.copyFrom(newTimer); + updateTimer(); + }); + } + }, + child: const Text("Edit")) + ]), + body: OrientationBuilder(builder: (context, orientation) { + double buttonSize = orientation == Orientation.portrait ? 32 : 32; + double largeButtonSize = orientation == Orientation.portrait ? 96 : 72; + double width = MediaQuery.of(context).size.width - 64; + double height = MediaQuery.of(context).size.height - 136; - color: colorScheme.primary, - size: largeButtonSize, - // size: 64, - ) - : Icon( - Icons.play_arrow_rounded, - color: colorScheme.primary, - size: largeButtonSize, + print('$width $height'); - // size: 64, + return SizedBox( + width: orientation == Orientation.portrait ? double.infinity : null, + height: orientation == Orientation.landscape ? double.infinity : null, + child: Flex( + direction: orientation == Orientation.portrait + ? Axis.vertical + : Axis.horizontal, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 32, width: 32), + TimerProgressBar( + timer: timer, + textScale: orientation == Orientation.portrait ? 1 : 0.75, + size: orientation == Orientation.portrait ? width : height), + const SizedBox(height: 32, width: 32), + Expanded( + child: Padding( + padding: const EdgeInsets.only( + left: 20.0, right: 20.0, bottom: 20.0), + child: Flex( + direction: orientation == Orientation.portrait + ? Axis.vertical + : Axis.horizontal, + children: [ + if (timer.state != TimerState.stopped) + Expanded( + flex: 1, + child: Flex( + direction: orientation == Orientation.portrait + ? Axis.horizontal + : Axis.vertical, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + flex: 2, + child: CardContainer( + onTap: () async { + await widget.onReset(timer); + updateTimer(); + }, + alignment: Alignment.center, + child: SizedBox.expand( + child: Flex( + direction: + orientation == Orientation.portrait + ? Axis.vertical + : Axis.horizontal, + children: [ + Expanded( + child: Padding( + padding: + const EdgeInsets.symmetric( + vertical: 8.0), + child: Icon( + Icons.replay_rounded, + color: colorScheme.primary, + size: buttonSize, + // size: 64, + )), + ), + ], + ), + ), + ), + ), + Expanded( + flex: 2, + child: CardContainer( + onTap: () async { + await widget.onAddTime(timer); + updateTimer(); + }, + alignment: Alignment.center, + child: SizedBox.expand( + child: Flex( + direction: + orientation == Orientation.portrait + ? Axis.vertical + : Axis.horizontal, + children: [ + Expanded( + child: Container( + alignment: Alignment.center, + child: Padding( + padding: + const EdgeInsets.symmetric( + vertical: 8.0), + child: Text( + '+${timer.addLength.floor()}:00', + style: orientation == + Orientation.portrait + ? textTheme.displaySmall + : textTheme.titleSmall), + ), + ), + ), + ], + ), + ), + ), ), + + /// CardContainer( + // alignment: Alignment.center, + // onTap: () async { + // await widget.onAddTime(timer); + // updateTimer(); + // }, + // child: Column( + // children: [ + // Expanded( + // child: Padding( + // padding: const EdgeInsets.all(8.0), + // child: ), + // ), + // ], + // ), + // ), + ], + ), + ), + Expanded( + flex: 2, + child: CardContainer( + alignment: Alignment.center, + child: SizedBox.expand( + child: Flex( + direction: orientation == Orientation.portrait + ? Axis.vertical + : Axis.horizontal, + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8.0), + child: timer.isRunning + ? Icon( + Icons.pause_rounded, + color: colorScheme.primary, + size: largeButtonSize, + // size: 64, + ) + : Icon( + Icons.play_arrow_rounded, + color: colorScheme.primary, + size: largeButtonSize, + // size: 64, + ), + ), + ), + ], + ), + ), + onTap: () async { + await widget.onToggleState(timer); + updateTimer(); + }, + ), ), - onTap: () async { - await widget.onToggleState(timer); - updateTimer(); - }, - ), + ], ), - if (timer.state != TimerState.stopped) - SizedBox( - width: buttonSize, - height: buttonSize, - child: CardContainer( - alignment: Alignment.center, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Text('+${timer.addLength.floor()}:00', - style: orientation == Orientation.portrait - ? textTheme.displaySmall - : textTheme.titleSmall)), - onTap: () async { - await widget.onAddTime(timer); - updateTimer(); - }, - ), - ), - ], - ), - ) - ], - ), - ), + ), + ) + ], + ), + ); + }), ); } } diff --git a/lib/timer/widgets/timer_preset_picker.dart b/lib/timer/widgets/timer_preset_picker.dart index ae563048..999ae50b 100644 --- a/lib/timer/widgets/timer_preset_picker.dart +++ b/lib/timer/widgets/timer_preset_picker.dart @@ -1,4 +1,5 @@ import 'package:clock_app/common/widgets/modal.dart'; +import 'package:clock_app/timer/logic/get_duration_picker.dart'; import 'package:clock_app/timer/types/time_duration.dart'; import 'package:clock_app/timer/types/timer_preset.dart'; import 'package:clock_app/timer/widgets/dial_duration_picker.dart'; @@ -52,19 +53,12 @@ Future showTimerPresetPicker(BuildContext context, Text(timerPreset.duration.toString(), style: textTheme.displayMedium), const SizedBox(height: 16), - SizedBox( - height: width - 64, - width: width - 64, - child: DialDurationPicker( - duration: timerPreset.duration, - onChange: (TimeDuration newDuration) { - setState(() { - timerPreset.duration = newDuration; - }); - }, - showHours: true, - ), - ), + getDurationPicker(context, timerPreset.duration, + (TimeDuration newDuration) { + setState(() { + timerPreset.duration = newDuration; + }); + }), ], ), ); diff --git a/lib/timer/widgets/timer_progress_bar.dart b/lib/timer/widgets/timer_progress_bar.dart index 09faec67..2bf44807 100644 --- a/lib/timer/widgets/timer_progress_bar.dart +++ b/lib/timer/widgets/timer_progress_bar.dart @@ -5,10 +5,11 @@ import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; class TimerProgressBar extends StatefulWidget { - const TimerProgressBar({super.key, required this.timer, required this.size, this.centerWidget}); + const TimerProgressBar({super.key, required this.timer, required this.size, this.centerWidget, this.textScale = 1.0}); final ClockTimer timer; final double size; + final double textScale; final Widget? centerWidget; @override @@ -64,7 +65,7 @@ class _TimerProgressBarState extends State { return Text( TimeDuration.fromSeconds(remainingSeconds).toTimeString(), style: Theme.of(context).textTheme.displayMedium?.copyWith( - fontSize: remainingSeconds > 3600 ? 48 : 64, + fontSize: (remainingSeconds > 3600 ? 48 : 64) * widget.textScale, ), ); },