import { isXaigenStudio } from '~/utils/videoModels' const PREF_KEY = 'aigen-notify-complete' const TAG = 'aigen-generation-complete' function appName() { try { const pub = useRuntimeConfig().public as { instanceName?: string; studio?: string } return String(pub.instanceName || (isXaigenStudio(pub) ? 'xAIGen' : 'AIGen')) } catch { return 'AIGen' } } function appIcon() { try { const pub = useRuntimeConfig().public as { instanceName?: string; studio?: string } return isXaigenStudio(pub) ? '/favicon.svg' : '/favicon-aigen.svg' } catch { return '/favicon-aigen.svg' } } export function generationNotifySupported() { return typeof window !== 'undefined' && 'Notification' in window } export function generationNotifyPref() { if (typeof window === 'undefined') return true try { return localStorage.getItem(PREF_KEY) !== '0' } catch { return true } } export function setGenerationNotifyPref(on: boolean) { try { localStorage.setItem(PREF_KEY, on ? '1' : '0') } catch { /* ignore */ } } export async function ensureGenerationNotifyPermission() { if (!generationNotifySupported() || !generationNotifyPref()) return false if (Notification.permission === 'granted') return true if (Notification.permission === 'denied') return false try { const result = await Notification.requestPermission() return result === 'granted' } catch { return false } } export async function notifyGenerationComplete(kind: 'video' | 'image' = 'video') { if (!generationNotifySupported() || !generationNotifyPref()) return if (Notification.permission !== 'granted') return if (typeof document !== 'undefined' && !document.hidden && document.hasFocus()) return const title = appName() const body = kind === 'image' ? 'Image generation is complete.' : 'Generation is complete.' const options: NotificationOptions = { body, icon: appIcon(), tag: TAG, renotify: true, silent: false } try { const registration = await navigator.serviceWorker?.ready if (registration?.showNotification) { await registration.showNotification(title, options) return } } catch { /* fall through */ } try { const note = new Notification(title, options) note.onclick = () => { window.focus() note.close() } } catch { /* ignore */ } }