Timer Signal on Mobile with Notification

This commit is contained in:
AG
2025-12-19 13:00:47 +02:00
parent 1d8bcdd626
commit 4e8feba5fe
4 changed files with 318 additions and 14 deletions

View File

@@ -0,0 +1,80 @@
/**
* Request notification permissions from the user.
* Safe to call multiple times (idempotent).
*/
export const requestNotificationPermission = async () => {
if (!('Notification' in window)) {
console.log('This browser does not support desktop notification');
return;
}
console.log('Current notification permission:', Notification.permission);
if (Notification.permission === 'granted') {
return;
}
if (Notification.permission !== 'denied') {
try {
const permission = await Notification.requestPermission();
console.log('Notification permission request result:', permission);
return permission;
} catch (e) {
console.error('Error requesting notification permission', e);
}
} else {
console.warn('Notification permission is denied. User must enable it in settings.');
}
return Notification.permission;
};
/**
* Send a system notification.
* @param title Notification title
* @param body Notification body text
*/
export const sendNotification = (title: string, body?: string) => {
if (!('Notification' in window)) return;
if (Notification.permission === 'granted') {
try {
// Check if service worker is available for more reliable notifications on mobile
if ('serviceWorker' in navigator && navigator.serviceWorker.ready) {
navigator.serviceWorker.ready.then(registration => {
registration.showNotification(title, {
body,
icon: '/assets/favicon.svg',
vibrate: [200, 100, 200],
tag: 'rest-timer',
renotify: true
} as any); // Cast to any to allow extended properties
});
} else {
// Fallback to standard notification API
new Notification(title, {
body,
icon: '/assets/favicon.svg',
tag: 'rest-timer',
renotify: true,
vibrate: [200, 100, 200]
} as any);
}
} catch (e) {
console.error('Error sending notification', e);
}
}
};
/**
* Trigger device vibration.
* @param pattern settings for navigator.vibrate
*/
export const vibrateDevice = (pattern: number | number[] = [200, 100, 200, 100, 200]) => {
if ('vibrate' in navigator) {
try {
navigator.vibrate(pattern);
} catch (e) {
console.error('Error vibrating device', e);
}
}
};