mirror of
https://github.com/arthur-pbty/chrono.git
synced 2026-06-03 23:36:31 +02:00
78 lines
2.5 KiB
TypeScript
78 lines
2.5 KiB
TypeScript
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<boolean> {
|
|
return navigator.clipboard
|
|
.writeText(text)
|
|
.then(() => true)
|
|
.catch(() => false);
|
|
}
|