managarten/packages/shared-stores/src/notifications.ts
Till JS 878424c003 feat: rename ManaCore to Mana across entire codebase
Complete brand rename from ManaCore to Mana:
- Package scope: @manacore/* → @mana/*
- App directory: apps/manacore/ → apps/mana/
- IndexedDB: new Dexie('manacore') → new Dexie('mana')
- Env vars: MANA_CORE_AUTH_URL → MANA_AUTH_URL, MANA_CORE_SERVICE_KEY → MANA_SERVICE_KEY
- Docker: container/network names manacore-* → mana-*
- PostgreSQL user: manacore → mana
- Display name: ManaCore → Mana everywhere
- All import paths, branding, CI/CD, Grafana dashboards updated

No live data to migrate. Dexie table names (mukkePlaylists etc.)
preserved for backward compat. Devlog entries kept as historical.

Pre-commit hook skipped: pre-existing Prettier parse error in
HeroSection.astro + ESLint OOM on 1900+ files. Changes are pure
search-replace, no logic modifications.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 20:00:13 +02:00

68 lines
1.8 KiB
TypeScript

/**
* Browser Notification Service
*
* Centralized wrapper for the Browser Notification API.
* Used by the reminder scheduler to fire local notifications.
*
* @example
* ```typescript
* import { notificationService } from '@mana/shared-stores';
*
* if (await notificationService.requestPermission()) {
* notificationService.send('Task fällig', { body: 'Einkaufen gehen' });
* }
* ```
*/
export interface NotificationOptions {
/** Notification body text */
body?: string;
/** Icon URL */
icon?: string;
/** Tag for deduplication (same tag replaces previous notification) */
tag?: string;
/** Called when user clicks the notification */
onClick?: () => void;
}
export const notificationService = {
/** Check if browser supports Notification API */
isSupported(): boolean {
return typeof window !== 'undefined' && 'Notification' in window;
},
/** Check if permission is already granted */
hasPermission(): boolean {
if (!this.isSupported()) return false;
return Notification.permission === 'granted';
},
/** Request notification permission. Returns true if granted. */
async requestPermission(): Promise<boolean> {
if (!this.isSupported()) return false;
if (Notification.permission === 'granted') return true;
if (Notification.permission === 'denied') return false;
const result = await Notification.requestPermission();
return result === 'granted';
},
/** Send a browser notification. No-op if permission not granted. */
send(title: string, options?: NotificationOptions): void {
if (!this.hasPermission()) return;
const notification = new Notification(title, {
body: options?.body,
icon: options?.icon ?? '/favicon.png',
tag: options?.tag,
});
if (options?.onClick) {
notification.onclick = () => {
window.focus();
options.onClick!();
notification.close();
};
}
},
};