Notify from the installed web app when a generation finishes.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
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 */ }
|
||||
}
|
||||
Reference in New Issue
Block a user