perf(booth): optimize assets and result flow

WebP reduces UI payload; JPEG keeps portrait saves compatible.\nFinish ends the visit without prompting another portrait.
This commit is contained in:
Ajasra committed 2026-10-30 00:00:16 +08:00
1 parent 56da9c86d2
commit 6772e0cf37
41 files changed
+225 -97

No files matched your search

+1 -1
View File
@@ -41,7 +41,7 @@ export async function GET(
"Content-Type": contentType,
"X-Content-Type-Options": "nosniff",
"Content-Security-Policy": "default-src 'none'; sandbox",
"Content-Disposition": `inline; filename="${filename}"`,
"Content-Disposition": `${req.nextUrl.searchParams.get("download") === "1" ? "attachment" : "inline"}; filename="${filename}"`,
"Cache-Control": "public, max-age=31536000, immutable",
},
});
+18
View File
@@ -171,6 +171,24 @@ body {
border-width: 0 !important;
box-shadow: none !important;
}
/* Tailwind's 12px text-xs was too small for the touch-first booth screens. */
.kiosk-viewport .text-xs {
font-size: 0.875rem;
line-height: 1.25rem;
}
.kiosk-viewport [class~="text-[10px]"],
.kiosk-viewport [class~="text-[11px]"],
.kiosk-viewport [class~="text-[12px]"] {
font-size: 0.875rem;
line-height: 1.25rem;
}
.kiosk-viewport .kiosk-footer-label {
font-size: 0.625rem !important;
line-height: 0.875rem !important;
}
}
/* Fullscreen Mode URL parameter reset (?mode=fullscreen) */
+2 -3
View File
@@ -6,15 +6,14 @@ export const metadata: Metadata = {
description:
"上海健志空手道馆万圣节专属照相馆 (Shanghai Karate Club Halloween Photobooth) - 凝聚万圣气合,定格武道英姿!",
icons: {
icon: "/assets/brand/shanghai_karate_logo.png",
icon: "/assets/brand/shanghai_karate_logo.webp",
},
};
export const viewport: Viewport = {
width: "device-width",
initialScale: 1,
maximumScale: 1,
userScalable: false,
userScalable: true,
viewportFit: "cover",
themeColor: "#0b0714",
};
+17 -3
View File
@@ -9,6 +9,7 @@ import { ConfirmScreen } from "@/components/screens/ConfirmScreen";
import { StyleScreen } from "@/components/screens/StyleScreen";
import { LoadingScreen } from "@/components/screens/LoadingScreen";
import { ResultScreen } from "@/components/screens/ResultScreen";
import { FinishedScreen } from "@/components/screens/FinishedScreen";
import { RateLimitedScreen } from "@/components/screens/RateLimitedScreen";
import { BoothConfig, BoothStyle, ScreenState } from "@/types/booth";
import { I18nProvider, useI18n } from "@/lib/i18n";
@@ -50,9 +51,11 @@ function PhotoBoothApp() {
const params = new URLSearchParams(window.location.search);
const previewScreen = params.get("preview") as ScreenState | null;
if (previewScreen === "result") {
const previewImg = params.get("image") || "/assets/styles/jack_o_lantern_sensei.jpg";
const previewImg = params.get("image") || "/assets/styles/jack_o_lantern_sensei.webp";
setResultImage(previewImg);
setScreen("result");
} else if (previewScreen === "finished") {
setScreen("finished");
}
}
})
@@ -63,7 +66,7 @@ function PhotoBoothApp() {
if (idleTimerRef.current) {
clearTimeout(idleTimerRef.current);
}
if (!config?.kiosk?.enableAutoReset || screen === "standby") {
if (!config?.kiosk?.enableAutoReset || screen === "standby" || screen === "finished") {
return;
}
const timeoutMs = (config.kiosk.idleTimeoutSeconds || 90) * 1000;
@@ -178,6 +181,15 @@ function PhotoBoothApp() {
setScreen("standby");
};
const handleFinish = () => {
setCapturedPhoto(null);
setSelectedStyle(null);
setResultImage(null);
setErrorMessage(null);
setSafetyWarning(null);
setScreen("finished");
};
if (!config) {
return (
<div className="flex h-screen w-screen items-center justify-center bg-[#090314] text-white">
@@ -246,10 +258,12 @@ function PhotoBoothApp() {
config={config}
resultImageUrl={resultImage}
providerInfo={providerInfo}
onStartOver={handleStartOver}
onFinish={handleFinish}
/>
)}
{screen === "finished" && <FinishedScreen />}
{screen === "rate_limited" && (
<RateLimitedScreen
config={config}