From 55259e748318e0f4ab3fb7b4e44e99d975a2ab74 Mon Sep 17 00:00:00 2001 From: Anupthor007 <77157035+Anupthor007@users.noreply.github.com> Date: Mon, 1 Dec 2025 18:49:09 +0530 Subject: [PATCH] feat: add configurable sound & vibration when countdown finishes (Fixes #1012) --- lib/widgets/routines/gym_mode/timer.dart | 78 +++++++++++++++++++++--- 1 file changed, 71 insertions(+), 7 deletions(-) diff --git a/lib/widgets/routines/gym_mode/timer.dart b/lib/widgets/routines/gym_mode/timer.dart index f4a00a28..3f8163e6 100644 --- a/lib/widgets/routines/gym_mode/timer.dart +++ b/lib/widgets/routines/gym_mode/timer.dart @@ -18,6 +18,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:intl/intl.dart'; import 'package:wger/l10n/generated/app_localizations.dart'; import 'package:wger/theme/theme.dart'; @@ -70,7 +71,8 @@ class _TimerWidgetState extends State { child: Center( child: Text( DateFormat('m:ss').format(displayTime), - style: Theme.of(context).textTheme.displayLarge!.copyWith(color: wgerPrimaryColor), + style: + Theme.of(context).textTheme.displayLarge!.copyWith(color: wgerPrimaryColor), ), ), ), @@ -97,6 +99,11 @@ class _TimerCountdownWidgetState extends State { late DateTime _endTime; late Timer _uiTimer; + // NEW: settings + one-time notification flag + bool _soundEnabled = true; + bool _vibrationEnabled = true; + bool _hasNotified = false; + @override void initState() { super.initState(); @@ -118,7 +125,19 @@ class _TimerCountdownWidgetState extends State { Widget build(BuildContext context) { final remaining = _endTime.difference(DateTime.now()); final remainingSeconds = remaining.inSeconds <= 0 ? 0 : remaining.inSeconds; - final displayTime = DateTime(2000, 1, 1, 0, 0, 0).add(Duration(seconds: remainingSeconds)); + final displayTime = + DateTime(2000, 1, 1, 0, 0, 0).add(Duration(seconds: remainingSeconds)); + + // When countdown finishes, notify ONCE, and respect settings + if (remainingSeconds == 0 && !_hasNotified) { + if (_soundEnabled) { + SystemSound.play(SystemSoundType.alert); + } + if (_vibrationEnabled) { + HapticFeedback.mediumImpact(); + } + _hasNotified = true; + } return Column( children: [ @@ -127,11 +146,56 @@ class _TimerCountdownWidgetState extends State { widget._controller, ), Expanded( - child: Center( - child: Text( - DateFormat('m:ss').format(displayTime), - style: Theme.of(context).textTheme.displayLarge!.copyWith(color: wgerPrimaryColor), - ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // countdown time + Text( + DateFormat('m:ss').format(displayTime), + style: Theme.of(context) + .textTheme + .displayLarge! + .copyWith(color: wgerPrimaryColor), + ), + const SizedBox(height: 16), + // NEW: simple settings row (Sound / Vibration) + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Switch( + value: _soundEnabled, + onChanged: (value) { + setState(() { + _soundEnabled = value; + }); + }, + ), + const SizedBox(width: 4), + const Text('Sound'), + ], + ), + const SizedBox(width: 24), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Switch( + value: _vibrationEnabled, + onChanged: (value) { + setState(() { + _vibrationEnabled = value; + }); + }, + ), + const SizedBox(width: 4), + const Text('Vibration'), + ], + ), + ], + ), + ], ), ), NavigationFooter(widget._controller),