export function formatTime(ms: number) { const abs = Math.abs(ms); const totalSeconds = Math.floor(abs / 1000); const hours = Math.floor(totalSeconds / 3600); const minutes = Math.floor((totalSeconds % 3600) / 60); const seconds = totalSeconds % 60; const milliseconds = Math.floor(abs % 1000); return { hours: hours.toString().padStart(2, "0"), minutes: minutes.toString().padStart(2, "0"), seconds: seconds.toString().padStart(2, "0"), milliseconds: milliseconds.toString().padStart(3, "0"), full: `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}.${milliseconds.toString().padStart(3, "0")}`, }; } export function playAlarm() { try { const ctx = new (window.AudioContext || (window as unknown as { webkitAudioContext: typeof AudioContext }).webkitAudioContext)(); const playBeep = (freq: number, startTime: number, duration: number) => { const osc = ctx.createOscillator(); const gain = ctx.createGain(); osc.connect(gain); gain.connect(ctx.destination); osc.frequency.value = freq; osc.type = "sine"; gain.gain.setValueAtTime(0.3, startTime); gain.gain.exponentialRampToValueAtTime(0.01, startTime + duration); osc.start(startTime); osc.stop(startTime + duration); }; const now = ctx.currentTime; playBeep(880, now, 0.15); playBeep(880, now + 0.25, 0.15); playBeep(1100, now + 0.5, 0.15); playBeep(880, now + 0.75, 0.15); playBeep(880, now + 1.0, 0.15); playBeep(1100, now + 1.25, 0.3); setTimeout(() => ctx.close(), 3000); } catch { // Audio not available } } export function requestNotificationPermission() { if (typeof window !== "undefined" && "Notification" in window) { if (Notification.permission === "default") { Notification.requestPermission(); } } } export function sendNotification(label: string) { if (typeof window !== "undefined" && "Notification" in window) { if (Notification.permission === "granted") { new Notification("⏰ Minuteur terminé", { body: label ? `${label} est terminé !` : "Le minuteur est terminé !", }); } } } export function toggleFullscreen() { if (!document.fullscreenElement) { document.documentElement.requestFullscreen().catch(() => {}); } else { document.exitFullscreen().catch(() => {}); } } export function copyToClipboard(text: string): Promise { return navigator.clipboard .writeText(text) .then(() => true) .catch(() => false); }