feat : ask for noti
This commit is contained in:
@@ -1,26 +1,9 @@
|
||||
"use client";
|
||||
|
||||
export async function subscribeCommissionPush(scope: "customer" | "admin", publicKey: string) {
|
||||
if (await Notification.requestPermission() !== "granted") return false;
|
||||
await syncCommissionPush(scope, publicKey);
|
||||
return true;
|
||||
}
|
||||
|
||||
export async function syncCommissionPush(scope: "customer" | "admin", publicKey: string) {
|
||||
const registration = await navigator.serviceWorker.register("/commission-push-sw.js", { scope: "/" });
|
||||
const subscription = await registration.pushManager.getSubscription() ??
|
||||
await registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: publicKey });
|
||||
const response = await fetch("/api/commission/push-subscription", { method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ ...subscription.toJSON(), scope }) });
|
||||
if (!response.ok) throw new Error("Could not save push subscription");
|
||||
sessionStorage.setItem(`commission-push-synced-${scope}`, "1");
|
||||
}
|
||||
|
||||
export async function unsubscribeCommissionPush() {
|
||||
sessionStorage.removeItem("commission-push-synced-customer");
|
||||
sessionStorage.removeItem("commission-push-synced-admin");
|
||||
for (const key of Object.keys(sessionStorage)) if (key.startsWith("comment-push-synced-")) sessionStorage.removeItem(key);
|
||||
for (const key of Object.keys(sessionStorage)) if (key.startsWith("comment-push-synced-") || key.startsWith("site-push-synced-")) sessionStorage.removeItem(key);
|
||||
if (!("serviceWorker" in navigator)) return;
|
||||
const registration = await navigator.serviceWorker.getRegistration("/");
|
||||
const subscription = await registration?.pushManager.getSubscription();
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
|
||||
import { subscribeCommissionPush, syncCommissionPush } from "./push-client";
|
||||
|
||||
type PushRequest = { scope: "customer" | "admin"; publicKey: string };
|
||||
const askedKey = "commission-push-asked";
|
||||
|
||||
export function CommissionPushEntryPrompt({ scope }: { scope: "customer" | "admin" }) {
|
||||
const [request, setRequest] = useState<PushRequest | null>(null);
|
||||
const [busy, setBusy] = useState(false);
|
||||
const [error, setError] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
if (!window.isSecureContext ||
|
||||
!("Notification" in window) || !("PushManager" in window) || !("serviceWorker" in navigator) ||
|
||||
Notification.permission === "denied" ||
|
||||
(Notification.permission === "default" && sessionStorage.getItem(askedKey)) ||
|
||||
(Notification.permission === "granted" && (sessionStorage.getItem(`commission-push-synced-${scope}`) ||
|
||||
(scope === "customer" && sessionStorage.getItem("commission-push-synced-admin"))))) return;
|
||||
|
||||
let active = true;
|
||||
void fetch("/api/commission/push-subscription", { cache: "no-store" }).then(async (response) => {
|
||||
if (!response.ok) return;
|
||||
const config = await response.json() as { publicKey: string; canAdmin: boolean };
|
||||
if (!active || (scope === "admin" && !config.canAdmin)) return;
|
||||
const subscriptionScope = config.canAdmin ? "admin" : scope;
|
||||
if (Notification.permission === "granted") {
|
||||
await syncCommissionPush(subscriptionScope, config.publicKey);
|
||||
return;
|
||||
}
|
||||
if (Notification.permission !== "default") return;
|
||||
sessionStorage.setItem(askedKey, "1");
|
||||
setRequest({ scope: subscriptionScope, publicKey: config.publicKey });
|
||||
}).catch(() => undefined);
|
||||
return () => { active = false; };
|
||||
}, [scope]);
|
||||
|
||||
async function enable() {
|
||||
if (!request) return;
|
||||
setBusy(true);
|
||||
setError("");
|
||||
try {
|
||||
await subscribeCommissionPush(request.scope, request.publicKey);
|
||||
setRequest(null);
|
||||
} catch {
|
||||
setError("เปิดการแจ้งเตือนไม่สำเร็จ กรุณาลองอีกครั้ง");
|
||||
} finally { setBusy(false); }
|
||||
}
|
||||
|
||||
return <Dialog open={request !== null} onOpenChange={(open) => { if (!open) setRequest(null); }}>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>รับการแจ้งเตือนข้อความใหม่?</DialogTitle>
|
||||
<DialogDescription>เมื่อมีข้อความใหม่ใน Ticket เราจะแจ้งเตือนพร้อมชื่อผู้ส่งและข้อความ แม้ปิดแท็บแล้ว</DialogDescription>
|
||||
</DialogHeader>
|
||||
{error && <p role="alert" className="text-sm text-destructive">{error}</p>}
|
||||
<DialogFooter>
|
||||
<Button type="button" variant="outline" disabled={busy} onClick={() => setRequest(null)}>ไว้ก่อน</Button>
|
||||
<Button type="button" disabled={busy} onClick={() => void enable()}>เปิดการแจ้งเตือน</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>;
|
||||
}
|
||||
@@ -80,7 +80,6 @@ import {
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { parseCommissionMessageEvent } from "@/lib/commission/message-event";
|
||||
import { CommissionPushEntryPrompt } from "./push-entry-prompt";
|
||||
import { keepCommissionTitle } from "./keep-title";
|
||||
|
||||
type ChatMessage = {
|
||||
@@ -626,7 +625,6 @@ export function CommissionTicketChat({
|
||||
|
||||
return (
|
||||
<>
|
||||
{!admin && <CommissionPushEntryPrompt scope="customer" />}
|
||||
<AlertDialog open={closedAlertOpen} onOpenChange={setClosedAlertOpen}>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
|
||||
Reference in New Issue
Block a user