feat: add website wide force refresh button
This commit is contained in:
@@ -7,13 +7,17 @@ import { revalidatePath } from "next/cache";
|
||||
import { actionLog } from "@/lib/api";
|
||||
import { db } from "@/lib/db";
|
||||
import { settings } from "@/lib/db/schema";
|
||||
import { adminCheck } from "@/lib/auth";
|
||||
import { sse } from "@/lib/db/sse-endpoints";
|
||||
|
||||
export async function getEnka() {
|
||||
if (!(await adminCheck())) throw "Unauthorized";
|
||||
const [{ enka } = { enka: true }] = await db.select().from(settings).limit(1);
|
||||
return enka;
|
||||
}
|
||||
|
||||
export async function toggleEnka(state: boolean) {
|
||||
if (!(await adminCheck())) throw "Unauthorized";
|
||||
const last = await getEnka();
|
||||
if (last === state) return;
|
||||
await db
|
||||
@@ -27,9 +31,15 @@ export async function toggleEnka(state: boolean) {
|
||||
}
|
||||
|
||||
export async function syncAmber() {
|
||||
if (!(await adminCheck())) throw "Unauthorized";
|
||||
const res = await promisify(exec)("bun util/sync 2>&1", {
|
||||
env: { ...env, NO_AUTH_CHECK: "1" },
|
||||
});
|
||||
await actionLog("Triggered an Amber sync", { result: res.stdout });
|
||||
return res.stdout;
|
||||
}
|
||||
|
||||
export async function forceRefresh() {
|
||||
if (!(await adminCheck())) throw "Unauthorized";
|
||||
sse.active.pub("refresh", null);
|
||||
}
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
"use client";
|
||||
|
||||
import { FolderSync } from "lucide-react";
|
||||
import { Bomb, FolderSync } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { CdnChooser } from "@/components/chooser";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Spinner } from "@/components/ui/spinner";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { shared } from "@/lib/comms";
|
||||
import { syncAmber, toggleEnka } from "./api";
|
||||
import { forceRefresh, syncAmber, toggleEnka } from "./api";
|
||||
import { Section } from "./page";
|
||||
import { ActionButton } from "@/components/action-button";
|
||||
|
||||
export function SettingsServicesSection({
|
||||
enka: enkaInitial,
|
||||
}: {
|
||||
enka: boolean;
|
||||
}) {
|
||||
const [syncing, setSyncing] = useState(false);
|
||||
const [syncResult, setSyncResult] = useState("");
|
||||
const [enka, setEnka] = useState<boolean>();
|
||||
const [debug] = shared.state("debug");
|
||||
@@ -26,10 +24,7 @@ export function SettingsServicesSection({
|
||||
}, [enka, enkaInitial]);
|
||||
|
||||
async function sync() {
|
||||
setSyncing(true);
|
||||
syncAmber()
|
||||
.then(setSyncResult)
|
||||
.finally(() => setSyncing(false));
|
||||
return syncAmber().then(setSyncResult);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -39,10 +34,16 @@ export function SettingsServicesSection({
|
||||
<Switch checked={enka} onCheckedChange={setEnka} />
|
||||
เปิดใช้การดึงตัวละครใน Artifact
|
||||
</div>
|
||||
<Button disabled={syncing} onClick={sync} className="w-min">
|
||||
{syncing ? <Spinner /> : <FolderSync />}
|
||||
Sync Amber
|
||||
</Button>
|
||||
<div className="flex items-center gap-2">
|
||||
<ActionButton action={sync}>
|
||||
<FolderSync />
|
||||
Sync Amber
|
||||
</ActionButton>
|
||||
<ActionButton action={forceRefresh} variant="destructive">
|
||||
<Bomb />
|
||||
FORCE RELOAD
|
||||
</ActionButton>
|
||||
</div>
|
||||
{debug && (
|
||||
<div className="grid w-fit gap-1 rounded-sm border border-dashed p-1">
|
||||
<span className="text-sm text-muted-foreground">
|
||||
|
||||
+30
-24
@@ -42,36 +42,42 @@ export function VersionCheck({ headless = false }: { headless?: boolean }) {
|
||||
useEffect(() => {
|
||||
if (!readyForUpdate && window.location.hash === "#update") {
|
||||
setUpdated(true);
|
||||
setTimeout(() => toast.success("คุณอยู่ในเวอร์ชั่นล่าสุดแล้ว"), 1000);
|
||||
if (!headless)
|
||||
setTimeout(() => toast.success("คุณอยู่ในเวอร์ชั่นล่าสุดแล้ว"), 1000);
|
||||
const url = new URL(window.location.href);
|
||||
url.hash = "";
|
||||
window.history.replaceState("", "", url);
|
||||
}
|
||||
|
||||
const { clean, es } = sse.active.sub(
|
||||
"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);
|
||||
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() {
|
||||
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;
|
||||
queueMicrotask(() => window.location.reload());
|
||||
},
|
||||
},
|
||||
{
|
||||
endpoint: "/api/active",
|
||||
|
||||
@@ -48,6 +48,7 @@ export const sse = sseEndpointMap({
|
||||
active: {
|
||||
version: z.string(),
|
||||
live: z.custom<YoutubeLiveInfo>(),
|
||||
refresh: z.null(),
|
||||
},
|
||||
// Admin Live Log
|
||||
log: {
|
||||
|
||||
Reference in New Issue
Block a user