From dd526ead0fa3f4c92277d03d22e8a0a61079cb4e Mon Sep 17 00:00:00 2001 From: Alexander Bocken Date: Mon, 6 Apr 2026 21:23:38 +0200 Subject: [PATCH] feat: play double-beep sound when rest timer completes --- package.json | 2 +- src/lib/js/workout.svelte.ts | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 2d2936d..fc536ed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "homepage", - "version": "1.4.0", + "version": "1.4.1", "private": true, "type": "module", "scripts": { diff --git a/src/lib/js/workout.svelte.ts b/src/lib/js/workout.svelte.ts index ce2a847..ad1d2aa 100644 --- a/src/lib/js/workout.svelte.ts +++ b/src/lib/js/workout.svelte.ts @@ -162,11 +162,32 @@ export function createWorkout() { } } + function _playRestDoneSound() { + if (typeof window === 'undefined') return; + try { + const ctx = new AudioContext(); + // Double beep — sine wave for a clean tone + for (let rep = 0; rep < 2; rep++) { + const offset = rep * 0.25; + const osc = ctx.createOscillator(); + const gain = ctx.createGain(); + osc.type = 'sine'; + osc.frequency.value = 880; // A5 + gain.gain.setValueAtTime(0.3, ctx.currentTime + offset); + gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + offset + 0.3); + osc.connect(gain).connect(ctx.destination); + osc.start(ctx.currentTime + offset); + osc.stop(ctx.currentTime + offset + 0.3); + } + } catch {} + } + function _computeRestSeconds() { if (!_restActive || !_restStartedAt) return; const elapsed = Math.floor((Date.now() - _restStartedAt) / 1000); _restSeconds = Math.max(0, _restTotal - elapsed); if (_restSeconds <= 0) { + _playRestDoneSound(); _stopRestTimer(); _persist(); }