feat : notify new update income
This commit is contained in:
@@ -7,8 +7,29 @@ import {
|
||||
hasDeploymentChanged,
|
||||
normalizeDeploymentId,
|
||||
} from "@/lib/deployment/version";
|
||||
import {
|
||||
parseDeploymentStatusEvent,
|
||||
type DeploymentStatus,
|
||||
} from "@/lib/deployment/status";
|
||||
|
||||
const UPDATE_TOAST_ID = "deployment-update";
|
||||
const NOTICE_DURATION_MS = 10_000;
|
||||
|
||||
function noticeKey(deploymentId: string, status: DeploymentStatus): string {
|
||||
return `deployment-notice:${deploymentId}:${status}`;
|
||||
}
|
||||
|
||||
function rememberNotice(seen: Set<string>, key: string): boolean {
|
||||
if (seen.has(key)) return false;
|
||||
try {
|
||||
if (sessionStorage.getItem(key)) return false;
|
||||
sessionStorage.setItem(key, "1");
|
||||
} catch {
|
||||
// In-memory deduplication still works when storage is unavailable.
|
||||
}
|
||||
seen.add(key);
|
||||
return true;
|
||||
}
|
||||
|
||||
export function DeploymentUpdateNotifier({
|
||||
deploymentId,
|
||||
@@ -17,23 +38,12 @@ export function DeploymentUpdateNotifier({
|
||||
}) {
|
||||
const currentDeployment = useRef(normalizeDeploymentId(deploymentId));
|
||||
const updateAvailable = useRef(false);
|
||||
const seenNotices = useRef(new Set<string>());
|
||||
|
||||
useEffect(() => {
|
||||
const source = new EventSource("/api/active");
|
||||
const receiveDeployment = (event: Event) => {
|
||||
if (
|
||||
updateAvailable.current ||
|
||||
!(event instanceof MessageEvent) ||
|
||||
typeof event.data !== "string"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nextDeployment = normalizeDeploymentId(event.data);
|
||||
if (!hasDeploymentChanged(currentDeployment.current, nextDeployment)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const showReady = () => {
|
||||
if (updateAvailable.current) return;
|
||||
updateAvailable.current = true;
|
||||
toast("มีอัปเดตใหม่พร้อมใช้งาน", {
|
||||
id: UPDATE_TOAST_ID,
|
||||
@@ -45,10 +55,52 @@ export function DeploymentUpdateNotifier({
|
||||
duration: Infinity,
|
||||
});
|
||||
};
|
||||
const receiveDeployment = (event: Event) => {
|
||||
if (!(event instanceof MessageEvent) || typeof event.data !== "string") {
|
||||
return;
|
||||
}
|
||||
const nextDeployment = normalizeDeploymentId(event.data);
|
||||
if (hasDeploymentChanged(currentDeployment.current, nextDeployment)) {
|
||||
showReady();
|
||||
}
|
||||
};
|
||||
const receiveStatus = (event: Event) => {
|
||||
if (!(event instanceof MessageEvent) || typeof event.data !== "string") {
|
||||
return;
|
||||
}
|
||||
const update = parseDeploymentStatusEvent(event.data);
|
||||
if (
|
||||
!update ||
|
||||
update.deploymentId === currentDeployment.current ||
|
||||
updateAvailable.current
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const key = noticeKey(update.deploymentId, update.status);
|
||||
if (!rememberNotice(seenNotices.current, key)) return;
|
||||
|
||||
if (update.status === "ready") {
|
||||
showReady();
|
||||
} else if (update.status === "deploying") {
|
||||
toast("กำลังอัปเดตเว็บไซต์", {
|
||||
id: UPDATE_TOAST_ID,
|
||||
description: "เวอร์ชันใหม่จะพร้อมใช้งานในอีกไม่กี่นาที",
|
||||
duration: NOTICE_DURATION_MS,
|
||||
});
|
||||
} else {
|
||||
toast("การอัปเดตล่าช้า", {
|
||||
id: UPDATE_TOAST_ID,
|
||||
description: "เวอร์ชันปัจจุบันยังใช้งานได้ตามปกติ",
|
||||
duration: NOTICE_DURATION_MS,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
source.addEventListener("deployment", receiveDeployment);
|
||||
source.addEventListener("deployment-status", receiveStatus);
|
||||
return () => {
|
||||
source.removeEventListener("deployment", receiveDeployment);
|
||||
source.removeEventListener("deployment-status", receiveStatus);
|
||||
source.close();
|
||||
};
|
||||
}, []);
|
||||
|
||||
Reference in New Issue
Block a user