20% battery left
This commit is contained in:
@@ -24,7 +24,7 @@ import {
|
||||
SidebarProvider,
|
||||
} from "@/components/ui/sidebar";
|
||||
import { getArtifactConfig, random, wipe } from "@/lib/api";
|
||||
import { apiAuthCheck } from "@/lib/auth";
|
||||
import { adminCheck } from "@/lib/auth";
|
||||
import { db } from "@/lib/db";
|
||||
import { submissions } from "@/lib/db/schema";
|
||||
import { LimitManager, SubmissionList, Watcher } from "./client";
|
||||
@@ -34,7 +34,7 @@ export default async function AdminLayout({
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
if (!(await apiAuthCheck())) redirect("/");
|
||||
if (!(await adminCheck())) redirect("/");
|
||||
const subs = await db
|
||||
.select({
|
||||
id: submissions.id,
|
||||
|
||||
@@ -27,8 +27,11 @@ export async function getEndgameConfig() {
|
||||
const full = ngm?.limit !== -1 && count >= (ngm?.limit || 0);
|
||||
|
||||
return {
|
||||
// @ts-expect-error
|
||||
locked: false,
|
||||
// @ts-expect-error
|
||||
limit: -1,
|
||||
// @ts-expect-error
|
||||
enka: false,
|
||||
count,
|
||||
full,
|
||||
|
||||
+2
-2
@@ -46,7 +46,7 @@ export default function Home() {
|
||||
<ItemTitle>
|
||||
<span className="hidden md:block">เสือกไอดีชาวบ้าน</span>
|
||||
<span className="block md:hidden">
|
||||
ตรวจแฟลกเกนชินรายแพทช์
|
||||
ตรวจแฟกต์เกนชินรายแพทช์
|
||||
</span>
|
||||
</ItemTitle>
|
||||
<ItemDescription className="line-clamp-none hidden md:block">
|
||||
@@ -110,7 +110,7 @@ export default function Home() {
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
<p className="text-xs text-center text-muted-foreground">
|
||||
buzz.gunshiz.top is not affiliated with HoYoverse. Game content
|
||||
buzz.sudloh.com is not affiliated with HoYoverse. Game content
|
||||
and materials are trademarks and copyrights of HoYoverse.
|
||||
</p>
|
||||
</CardFooter>
|
||||
|
||||
@@ -7,13 +7,7 @@ import {
|
||||
useDroppable,
|
||||
} from "@dnd-kit/core";
|
||||
import { rectSortingStrategy, SortableContext } from "@dnd-kit/sortable";
|
||||
import {
|
||||
Calculator,
|
||||
ChevronDown,
|
||||
ChevronUp,
|
||||
Smartphone,
|
||||
X,
|
||||
} from "lucide-react";
|
||||
import { Calculator, ChevronDown, ChevronUp, X } from "lucide-react";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import {
|
||||
@@ -53,6 +47,7 @@ import {
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import { tlPlacements, tlState } from "@/lib/api";
|
||||
import { comms } from "@/lib/comms";
|
||||
import type {
|
||||
characters,
|
||||
tierlistBadges,
|
||||
@@ -127,6 +122,7 @@ export function TierList({
|
||||
download: boolean;
|
||||
ev: "unknown" | "connecting" | "ready";
|
||||
}>({ upload: false, download: false, ev: "unknown" });
|
||||
const [updated] = comms.var("updated");
|
||||
|
||||
//#region error handling
|
||||
useEffect(() => {
|
||||
@@ -345,14 +341,14 @@ export function TierList({
|
||||
onDragEnd={handleDragEnd}
|
||||
>
|
||||
<div className="flex flex-col justify-between h-full">
|
||||
<Blocker inner className="not-portrait:hidden md:hidden">
|
||||
{/*}<Blocker inner className="not-portrait:hidden md:hidden">
|
||||
<div className="flex flex-col items-center font-bold text-2xl gap-16">
|
||||
<Smartphone size={128} className="animate-phonerotate" />
|
||||
โปรดปรับจอเป็นแนวนอน
|
||||
</div>
|
||||
</Blocker>
|
||||
{version.disclaimer && disclaimer ? (
|
||||
<Blocker inner className="hidden not-portrait:block md:block">
|
||||
</Blocker>*/}
|
||||
{version.disclaimer && disclaimer && !updated ? (
|
||||
<Blocker inner className=" not-portrait:block md:block">
|
||||
<Image
|
||||
src={`/cdn/${version.disclaimer}`}
|
||||
alt="Disclaimer"
|
||||
|
||||
@@ -3,10 +3,6 @@ import { sse } from "@/lib/utils";
|
||||
const VERSION = crypto.randomUUID();
|
||||
|
||||
export function GET({ signal }: Request) {
|
||||
sse.publish(VERSION, {
|
||||
topic: "active",
|
||||
event: "version",
|
||||
});
|
||||
// +1 because this connection is not yet counted
|
||||
sse.publish(sse.count("active") + 1, {
|
||||
topic: "active",
|
||||
@@ -18,6 +14,10 @@ export function GET({ signal }: Request) {
|
||||
// no need to -1 because this connection is already removed
|
||||
sse.publish(sse.count("active"), { topic: "active", event: "count" });
|
||||
},
|
||||
motd: {
|
||||
data: VERSION,
|
||||
event: "version",
|
||||
},
|
||||
signal,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { apiAuthCheck } from "@/lib/auth";
|
||||
import { adminCheck } from "@/lib/auth";
|
||||
import { sse } from "@/lib/utils";
|
||||
|
||||
export async function GET(
|
||||
_req: Request,
|
||||
{ params }: { params: Promise<{ topic: string }> },
|
||||
) {
|
||||
if (!(await apiAuthCheck()))
|
||||
return new Response("Unauthorized", { status: 401 });
|
||||
if (!(await adminCheck())) return new Response("Unauthorized", { status: 401 });
|
||||
const { topic } = await params;
|
||||
return sse.new(topic);
|
||||
}
|
||||
|
||||
+37
-15
@@ -5,6 +5,7 @@ import { useEffect, useState } from "react";
|
||||
import { useKey } from "react-use";
|
||||
import ReconnectingEventSource from "reconnecting-eventsource";
|
||||
import { toast } from "sonner";
|
||||
import { stringify } from "yaml";
|
||||
import CommsProvider, { comms } from "@/lib/comms";
|
||||
|
||||
export default function Providers({ children }: { children: React.ReactNode }) {
|
||||
@@ -20,39 +21,58 @@ export default function Providers({ children }: { children: React.ReactNode }) {
|
||||
);
|
||||
}
|
||||
|
||||
export function VersionCheck() {
|
||||
export function VersionCheck({ headless = false }: { headless?: boolean }) {
|
||||
const [version, setVersion] = useState<string>();
|
||||
const [count, setCount] = useState<string | number>("...");
|
||||
const [debug, setDebug] = comms.var("debug");
|
||||
const [, setConnected] = comms.var("connected");
|
||||
const [, setUpdated] = comms.var("updated");
|
||||
const [debugData] = comms.raw();
|
||||
const [readyForUpdate, setReadyForUpdate] = useState(false);
|
||||
|
||||
useKey("F2", () => {
|
||||
setDebug((x) => !x);
|
||||
if (!headless) setDebug((x) => !x);
|
||||
});
|
||||
// console.log(`Debug mode ${debug ? "enabled" : "disabled"}`);
|
||||
|
||||
useEffect(() => {
|
||||
if (!readyForUpdate && window.location.hash === "#update") {
|
||||
setUpdated(true);
|
||||
toast.success("คุณอยู่ในเวอร์ชั่นล่าสุดแล้ว");
|
||||
const url = new URL(window.location.href);
|
||||
url.hash = "";
|
||||
window.history.replaceState("", "", url);
|
||||
}
|
||||
|
||||
const es = new ReconnectingEventSource(`/api/active`, {});
|
||||
es.addEventListener("version", (d) => {
|
||||
setConnected(true);
|
||||
const newVersion = JSON.parse(d.data);
|
||||
if (!version) console.log("Client version:", newVersion);
|
||||
console.log("Server version:", newVersion);
|
||||
if (version && newVersion !== version)
|
||||
toast("เวอร์ชั่นใหม่ออกแล้ว", {
|
||||
description: "โปรดรีโหลดเพื่อใช้งานต่อ",
|
||||
action: {
|
||||
label: "Reload",
|
||||
// Do a full reload
|
||||
onClick: () => window.location.reload(),
|
||||
},
|
||||
duration: Infinity,
|
||||
});
|
||||
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) setVersion(newVersion);
|
||||
});
|
||||
es.addEventListener("count", (d) => {
|
||||
const count = JSON.parse(d.data);
|
||||
setCount(count);
|
||||
});
|
||||
es.onerror = () =>
|
||||
es.onerror = () => {
|
||||
setConnected(false);
|
||||
toast.promise(
|
||||
new Promise((r) => {
|
||||
es.onopen = r;
|
||||
@@ -63,12 +83,14 @@ export function VersionCheck() {
|
||||
duration: 500,
|
||||
},
|
||||
);
|
||||
};
|
||||
return () => es.close();
|
||||
}, [version]);
|
||||
}, [version, headless, setConnected, setUpdated, readyForUpdate]);
|
||||
|
||||
return debug ? (
|
||||
<div className="absolute bottom-0 right-0 m-2 px-1 rounded flex gap-2 bg-card border active:pointer-events-none opacity-20 hover:opacity-100 transition-opacity">
|
||||
<div className="absolute bottom-0 right-0 m-2 px-1 rounded flex flex-col gap-2 bg-card border active:pointer-events-none opacity-20 hover:opacity-100 transition-opacity">
|
||||
{count} ผู้ใช้งานออนไลน์
|
||||
<pre>{stringify(debugData, null, 2)}</pre>
|
||||
</div>
|
||||
) : (
|
||||
""
|
||||
|
||||
+1
-1
@@ -92,7 +92,7 @@ export default function ErrorPage({
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<Link href="https://status.gunshiz.top" className="m-2">
|
||||
<Link href="https://status.sudloh.com" className="m-2">
|
||||
<Button variant="link" className="text-secondary-foreground">
|
||||
<Activity />
|
||||
สถานะเว็บไซต์
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ const geistMono = Geist_Mono({
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
metadataBase: new URL(process.env.BASE_URL || "https://buzz.gunshiz.top"),
|
||||
metadataBase: new URL(process.env.BASE_URL || "https://buzz.sudloh.com"),
|
||||
title: "เกนชินไม่ใช่เกมมือถือ",
|
||||
description: "ระบบอีเวนท์ของเกนชินไม่ใช่เกมมือถือ",
|
||||
icons: `/favicon.webp`, // TODO: CHANGE BACK TO buzz
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ export default function ErrorPage() {
|
||||
กลับหน้าแรก
|
||||
</Button>
|
||||
</Link>
|
||||
<Link href="https://status.gunshiz.top">
|
||||
<Link href="https://status.sudloh.com">
|
||||
<Button variant="link" className="text-secondary-foreground">
|
||||
<Activity />
|
||||
สถานะเว็บไซต์
|
||||
|
||||
@@ -1,16 +1,33 @@
|
||||
import { Kanit } from "next/font/google";
|
||||
import { Watcher } from "@/app/(ui)/artifact/admin/client";
|
||||
import { VersionCheck } from "@/app/client";
|
||||
import AutoFitText from "@/components/fit";
|
||||
import { getArtifactConfig } from "@/lib/api";
|
||||
import { db } from "@/lib/db";
|
||||
import { submissions } from "@/lib/db/schema";
|
||||
|
||||
const kanit = Kanit({
|
||||
variable: "--font-kanit",
|
||||
subsets: ["latin", "thai"],
|
||||
weight: ["100", "200", "300", "400", "500", "600", "700"],
|
||||
});
|
||||
|
||||
export default async function ArtifactCountWidget() {
|
||||
const config = await getArtifactConfig();
|
||||
const count = await db.$count(submissions);
|
||||
|
||||
const display = `${count} / ${config.limit < 0 ? "∞" : config.limit}`;
|
||||
|
||||
return (
|
||||
<span className="p-1">
|
||||
{count} / {config.limit < 0 ? "∞" : config.limit}
|
||||
<div
|
||||
className={`${kanit.variable} w-screen h-screen font-medium`}
|
||||
style={{
|
||||
fontFamily: "Kanit",
|
||||
}}
|
||||
>
|
||||
<AutoFitText className="count">{display}</AutoFitText>
|
||||
<Watcher />
|
||||
</span>
|
||||
<VersionCheck headless />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user