70 lines
4.7 KiB
TypeScript
70 lines
4.7 KiB
TypeScript
'use client';
|
|
|
|
import { useEffect, useId, useState } from 'react';
|
|
import { authClient } from '@/lib/auth/client';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Checkbox } from '@/components/ui/checkbox';
|
|
import { Field, FieldLabel } from '@/components/ui/field';
|
|
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';
|
|
import { disableSitePush, setSitePushDisabled, sitePushDisabled, syncSitePush, useSitePushDisabled } from './push-client';
|
|
|
|
const dismissedKey = 'site-push-dont-ask';
|
|
const askedKey = 'site-push-asked';
|
|
export function SitePushPrompt({ configured }: { configured: boolean }) {
|
|
const { data } = authClient.useSession();
|
|
const userId = data?.user.id;
|
|
const id = useId();
|
|
const disabled = useSitePushDisabled();
|
|
const [open, setOpen] = useState(false);
|
|
const [dontAsk, setDontAsk] = useState(false);
|
|
const [busy, setBusy] = useState(false);
|
|
const [error, setError] = useState('');
|
|
useEffect(() => {
|
|
if (!configured || !window.isSecureContext || !('Notification' in window) || !('PushManager' in window) || !('serviceWorker' in navigator)) return;
|
|
let active = true;
|
|
function show() { setError(''); setOpen(true); }
|
|
window.addEventListener('notifications:enable', show);
|
|
void Promise.resolve().then(async () => {
|
|
if (!active || sitePushDisabled()) return;
|
|
if (Notification.permission === 'granted') {
|
|
if (userId && !sessionStorage.getItem(`site-push-synced-${userId}`)) await syncSitePush(userId);
|
|
} else if (Notification.permission === 'default' && !localStorage.getItem(dismissedKey) && !sessionStorage.getItem(askedKey)) {
|
|
sessionStorage.setItem(askedKey, '1');
|
|
setOpen(true);
|
|
}
|
|
}).catch(() => undefined);
|
|
return () => { active = false; window.removeEventListener('notifications:enable', show); };
|
|
}, [configured, userId, disabled]);
|
|
function close() {
|
|
if (dontAsk) localStorage.setItem(dismissedKey, '1');
|
|
setOpen(false);
|
|
}
|
|
async function enable() {
|
|
setBusy(true); setError('');
|
|
try {
|
|
if (await Notification.requestPermission() !== 'granted') {
|
|
setError('ยังไม่ได้อนุญาตการแจ้งเตือน เปิดสิทธิ์ในการตั้งค่าเว็บไซต์ของเบราว์เซอร์');
|
|
return;
|
|
}
|
|
if (userId) await syncSitePush(userId, true);
|
|
setSitePushDisabled(false);
|
|
close();
|
|
} catch { setError('เปิดการแจ้งเตือนไม่สำเร็จ กรุณาลองอีกครั้ง'); }
|
|
finally { setBusy(false); }
|
|
}
|
|
async function disable() {
|
|
setBusy(true); setError('');
|
|
try { await disableSitePush(userId); close(); }
|
|
catch { setError('ปิดการแจ้งเตือนไม่สำเร็จ กรุณาลองอีกครั้ง'); }
|
|
finally { setBusy(false); }
|
|
}
|
|
return <Dialog open={open} onOpenChange={value => { if (!value && !busy) close(); }}><DialogContent showCloseButton={!busy}>
|
|
<DialogHeader><DialogTitle>ตั้งค่าการแจ้งเตือน</DialogTitle><DialogDescription>รับข้อความ Commission คำตอบกลับความคิดเห็น และการแจ้งเตือนอื่นๆ ของเว็บไซต์ในอนาคต แม้ปิดแท็บแล้ว</DialogDescription></DialogHeader>
|
|
{disabled && <p className="text-sm text-muted-foreground">ปิดการแจ้งเตือนชั่วคราวในเบราว์เซอร์นี้จนกว่าจะเปิดอีกครั้ง</p>}
|
|
{!userId && <p className="text-sm text-muted-foreground">หลังเข้าสู่ระบบ เราจะเชื่อมการแจ้งเตือนกับบัญชีของคุณ</p>}
|
|
<Field orientation="horizontal"><Checkbox id={id} checked={dontAsk} onCheckedChange={setDontAsk} disabled={busy} /><FieldLabel htmlFor={id}>ไม่ต้องถามอีก</FieldLabel></Field>
|
|
{error && <p role="alert" className="text-sm text-destructive">{error}</p>}
|
|
<DialogFooter><Button variant="outline" disabled={busy} onClick={close}>ไว้ก่อน</Button>{!disabled && <Button variant="outline" disabled={busy} onClick={() => void disable()}>ปิดชั่วคราว</Button>}<Button disabled={busy} onClick={() => void enable()}>{disabled ? 'เปิดอีกครั้ง' : 'เปิดการแจ้งเตือน'}</Button></DialogFooter>
|
|
</DialogContent></Dialog>;
|
|
}
|