Notify from the installed web app when a generation finishes.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Towsty
2026-09-01 07:11:12 -05:00
co-authored by Cursor
parent fa32fb0a8e
commit 2635b8838c
7 changed files with 195 additions and 2 deletions
+40
View File
@@ -48,6 +48,24 @@
</div>
<p v-if="gpuMessage" class="text-xs" :class="gpuError ? 'text-red-300' : 'text-zinc-500'">{{ gpuMessage }}</p>
</div>
<label class="mt-4 flex cursor-pointer items-center justify-between gap-3 rounded-2xl border border-white/10 bg-zinc-950/50 px-4 py-3 text-sm">
<span>
<span class="block text-zinc-200">Notify when a generation finishes</span>
<span class="mt-0.5 block text-xs text-zinc-500">Works in the installed web app. Asks for notification permission the first time you turn this on or generate.</span>
</span>
<input
v-model="notifyComplete"
type="checkbox"
class="peer sr-only"
role="switch"
@change="onNotifyCompleteChange"
>
<span class="relative inline-flex h-6 w-11 shrink-0 items-center">
<span class="absolute inset-0 rounded-full transition" :class="notifyComplete ? 'bg-amber-400' : 'bg-zinc-700'" />
<span class="absolute left-0.5 top-0.5 h-5 w-5 rounded-full bg-white transition" :class="notifyComplete ? 'translate-x-5' : ''" />
</span>
</label>
<p v-if="notifyMessage" class="mt-2 text-xs text-zinc-500">{{ notifyMessage }}</p>
</section>
<section v-if="activePanel === 'storage'" class="glass rounded-3xl p-5 sm:p-6">
@@ -460,6 +478,8 @@ const gpuSleeping = ref(false)
const gpuWaking = ref(false)
const gpuError = ref(false)
const gpuMessage = ref('')
const notifyComplete = ref(true)
const notifyMessage = ref('')
const storage = ref<{
libraryBytes: number
breakdown: { clips: number; stills: number; tmp: number; other: number }
@@ -533,6 +553,7 @@ async function loadAccount() {
}
onMounted(() => {
notifyComplete.value = generationNotifyPref()
void loadAccount()
void loadPresets()
void loadStorage()
@@ -620,6 +641,25 @@ async function loadStorage() {
}
}
async function onNotifyCompleteChange() {
const on = notifyComplete.value
setGenerationNotifyPref(on)
notifyMessage.value = ''
if (!on) return
if (!generationNotifySupported()) {
notifyMessage.value = 'This browser does not support notifications.'
return
}
const granted = await ensureGenerationNotifyPermission()
if (!granted) {
notifyComplete.value = false
setGenerationNotifyPref(false)
notifyMessage.value = Notification.permission === 'denied'
? 'Notifications are blocked in the browser. Allow them for this site, then turn this on again.'
: 'Could not enable notifications.'
}
}
async function sleepGpu() {
if (gpuSleeping.value || gpuWaking.value) return
gpuSleeping.value = true