Files
buzz/app/client.tsx
T
dmgnr 6b64059501
Build and Push Image / build-backend (push) Successful in 1m1s
Build and Push Image / push (push) Has been cancelled
Build and Push Image / build-frontend (push) Has been cancelled
feat(don): add method toggle
2026-07-19 02:58:44 +07:00

112 lines
3.8 KiB
TypeScript
Executable File

"use client";
import { ProgressProvider } from "@bprogress/next/app";
import { use, useEffect, useRef, useState } from "react";
import { useKey } from "react-use";
import { toast } from "sonner";
import { stringify } from "yaml";
import { CdnChooserProvider } from "@/components/chooser";
import IccProvider, { IccContext, shared } from "@/lib/comms";
import { sse } from "@/lib/db/sse-endpoints";
export default function Providers({ children }: { children: React.ReactNode }) {
return (
<ProgressProvider
height="2px"
color="var(--primary)"
options={{ showSpinner: false }}
shallowRouting
>
<CdnChooserProvider>
<IccProvider>{children}</IccProvider>
</CdnChooserProvider>
</ProgressProvider>
);
}
export function VersionCheck({ headless = false }: { headless?: boolean }) {
const ver = useRef<string>("");
// oxlint-disable-next-line typescript/unbound-method
const { emit } = use(IccContext);
const [debug, setDebug] = shared.state("debug");
const [, setConnected] = shared.state("connected");
const [, setUpdated] = shared.state("updated");
const [debugData] = shared.raw();
const [readyForUpdate, setReadyForUpdate] = useState(false);
useKey("F2", () => {
if (!headless) setDebug((x) => !x);
});
// console.log(`Debug mode ${debug ? "enabled" : "disabled"}`);
useEffect(() => {
if (!readyForUpdate && window.location.hash === "#update") {
setUpdated(true);
if (!headless)
setTimeout(() => toast.success("คุณอยู่ในเวอร์ชั่นล่าสุดแล้ว"), 1000);
const url = new URL(window.location.href);
url.hash = "";
window.history.replaceState("", "", url);
}
const { clean, es } = sse.active.subMany(
{
version(newVersion) {
setConnected(true);
emit("sync");
const version = ver.current;
if (!version) console.log("Client version:", newVersion);
console.log("Server version:", newVersion);
if (version && newVersion !== version) {
setReadyForUpdate(true);
window.location.hash = "#update";
if (headless) window.location.reload();
else
toast("มีอัปเดตใหม่พร้อมใช้งาน", {
description: "รีโหลดเพื่ออัปเดตเป็นเวอร์ชันล่าสุด",
action: {
label: "รีโหลด",
// Do a full reload
onClick: () => window.location.reload(),
},
duration: Infinity,
});
}
if (newVersion !== version) ver.current = newVersion;
},
refresh(prefix) {
if (prefix && !window.location.pathname.startsWith(prefix)) return;
window.location.hash = "#update";
queueMicrotask(() => window.location.reload());
},
},
{
endpoint: "/api/active",
onerror() {
setConnected(false);
toast.promise(
new Promise((r) => {
es.onopen = r;
}),
{
loading: "กำลังพยายามเชื่อมต่อใหม่...",
success: () => "เชื่อมต่อสำเร็จ",
duration: 500,
},
);
},
},
);
return clean;
}, [headless, setConnected, setUpdated, readyForUpdate, emit]);
return debug ? (
<div className="absolute right-0 bottom-0 m-2 flex flex-col gap-2 rounded border bg-card px-1 opacity-20 transition-opacity hover:opacity-100 active:pointer-events-none">
Buzz ({ver.current.split("-")[0] || "..."})
<pre>{stringify(debugData, null, 2)}</pre>
</div>
) : (
""
);
}