Files
aigen/utils/generationNotify.ts

87 lines
2.4 KiB
TypeScript

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' | 'music' = '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.'
: kind === 'music'
? 'Music 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 */ }
}