feat(prototype): add upload manager and docker ci
- add prototype upload, list, view, and delete api routes - add prototype manager ui with search, modal, and theme toggle - add filesystem-backed zip extraction and serving logic - switch project to pnpm with updated lockfile and tooling - add multi-stage dockerfile with standalone next.js output - add github actions to lint, build, and publish docker images
This commit is contained in:
30 files changed
+5369
-6899
No files matched your search
@@ -0,0 +1,51 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { THEME_STORAGE_KEY } from "@/lib/prototype";
|
||||
|
||||
function getInitialTheme() {
|
||||
if (typeof window === "undefined") {
|
||||
return false;
|
||||
}
|
||||
|
||||
const saved = localStorage.getItem(THEME_STORAGE_KEY);
|
||||
|
||||
if (saved === "true") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (saved === "false") {
|
||||
return false;
|
||||
}
|
||||
|
||||
return window.matchMedia("(prefers-color-scheme: dark)").matches;
|
||||
}
|
||||
|
||||
function applyTheme(isDark: boolean) {
|
||||
document.documentElement.classList.toggle("dark", isDark);
|
||||
}
|
||||
|
||||
export function ThemeToggle() {
|
||||
const [darkMode, setDarkMode] = useState(getInitialTheme);
|
||||
|
||||
useEffect(() => {
|
||||
applyTheme(darkMode);
|
||||
localStorage.setItem(THEME_STORAGE_KEY, String(darkMode));
|
||||
}, [darkMode]);
|
||||
|
||||
const toggle = () => {
|
||||
setDarkMode((prev) => !prev);
|
||||
};
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
onClick={toggle}
|
||||
className="fixed right-8 bottom-8 z-50 flex h-12 w-12 items-center justify-center rounded-full border border-slate-200 bg-white text-xl shadow-md transition hover:-translate-y-0.5 dark:border-slate-700 dark:bg-slate-900"
|
||||
aria-label={darkMode ? "切换到浅色模式" : "切换到深色模式"}
|
||||
title={darkMode ? "浅色模式" : "深色模式"}
|
||||
>
|
||||
{darkMode ? "☀️" : "🌙"}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user