mirror of
https://github.com/fankes/komari-theme-purcarte.git
synced 2025-12-13 21:11:09 +08:00
feat: 尝试支持配置视频背景
This commit is contained in:
@@ -13,7 +13,7 @@ import { useEffect, useState } from "react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { useIsMobile } from "@/hooks/useMobile";
|
||||
import { useConfigItem } from "@/config";
|
||||
import type { Appearance } from "@/hooks/useTheme";
|
||||
import { useTheme } from "@/hooks/useTheme";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
@@ -24,8 +24,6 @@ import {
|
||||
interface HeaderProps {
|
||||
viewMode: "grid" | "table";
|
||||
setViewMode: (mode: "grid" | "table") => void;
|
||||
appearance: Appearance;
|
||||
setAppearance: (appearance: Appearance) => void;
|
||||
searchTerm: string;
|
||||
setSearchTerm: (term: string) => void;
|
||||
}
|
||||
@@ -33,11 +31,10 @@ interface HeaderProps {
|
||||
export const Header = ({
|
||||
viewMode,
|
||||
setViewMode,
|
||||
appearance,
|
||||
setAppearance,
|
||||
searchTerm,
|
||||
setSearchTerm,
|
||||
}: HeaderProps) => {
|
||||
const { appearance, setAppearance } = useTheme();
|
||||
const [isSearchOpen, setIsSearchOpen] = useState(false);
|
||||
const location = useLocation();
|
||||
const isInstancePage = location.pathname.startsWith("/instance");
|
||||
@@ -56,8 +53,7 @@ export const Header = ({
|
||||
}, [sitename]);
|
||||
|
||||
const toggleAppearance = () => {
|
||||
const newAppearance = appearance === "light" ? "dark" : "light";
|
||||
setAppearance(newAppearance);
|
||||
setAppearance(appearance === "light" ? "dark" : "light");
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// 配置类型定义
|
||||
export interface ConfigOptions {
|
||||
backgroundImage?: string; // 背景图片URL
|
||||
enableVideoBackground?: boolean; // 是否启用视频背景
|
||||
videoBackgroundUrl?: string; // 视频背景URL
|
||||
blurValue?: number; // 磨砂玻璃模糊值
|
||||
blurBackgroundColor?: string; // 磨砂玻璃背景颜色
|
||||
tagDefaultColorList?: string; // 标签默认颜色列表
|
||||
@@ -27,6 +29,8 @@ export interface ConfigOptions {
|
||||
// 默认配置值
|
||||
export const DEFAULT_CONFIG: ConfigOptions = {
|
||||
backgroundImage: "/assets/Moonlit-Scenery.webp",
|
||||
enableVideoBackground: false,
|
||||
videoBackgroundUrl: "/assets/Mortis_1080p30fps2Mbps.mp4",
|
||||
blurValue: 10,
|
||||
blurBackgroundColor: "rgba(255, 255, 255, 0.5)|rgba(0, 0, 0, 0.5)",
|
||||
tagDefaultColorList:
|
||||
|
||||
@@ -86,6 +86,16 @@ export const useTheme = () => {
|
||||
return (defaultColor as Colors) || THEME_DEFAULTS.color;
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (appearance === "system") {
|
||||
const systemTheme = window.matchMedia("(prefers-color-scheme: dark)")
|
||||
.matches
|
||||
? "dark"
|
||||
: "light";
|
||||
setAppearance(systemTheme);
|
||||
}
|
||||
}, [appearance]);
|
||||
|
||||
useEffect(() => {
|
||||
const root = window.document.documentElement;
|
||||
root.classList.remove("light", "dark");
|
||||
|
||||
69
src/main.tsx
69
src/main.tsx
@@ -21,7 +21,7 @@ import { useConfigItem } from "@/config";
|
||||
|
||||
// 内部应用组件,在 ConfigProvider 内部使用配置
|
||||
export const AppContent = () => {
|
||||
const { appearance, setAppearance, color } = useTheme();
|
||||
const { appearance, color } = useTheme();
|
||||
const defaultView = useConfigItem("selectedDefaultView");
|
||||
const enableLocalStorage = useConfigItem("enableLocalStorage");
|
||||
|
||||
@@ -36,6 +36,8 @@ export const AppContent = () => {
|
||||
return defaultView || "grid";
|
||||
});
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const enableVideoBackground = useConfigItem("enableVideoBackground");
|
||||
const videoBackgroundUrl = useConfigItem("videoBackgroundUrl");
|
||||
|
||||
useEffect(() => {
|
||||
if (enableLocalStorage) {
|
||||
@@ -44,33 +46,44 @@ export const AppContent = () => {
|
||||
}, [enableLocalStorage, viewMode]);
|
||||
|
||||
return (
|
||||
<Theme
|
||||
appearance={appearance === "system" ? "inherit" : appearance}
|
||||
accentColor={color}
|
||||
scaling="110%"
|
||||
style={{ backgroundColor: "transparent" }}>
|
||||
<div className="min-h-screen flex flex-col text-sm">
|
||||
<Header
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
appearance={appearance}
|
||||
setAppearance={setAppearance}
|
||||
searchTerm={searchTerm}
|
||||
setSearchTerm={setSearchTerm}
|
||||
/>
|
||||
<Suspense fallback={<Loading />}>
|
||||
<Routes>
|
||||
<Route
|
||||
path="/"
|
||||
element={<HomePage viewMode={viewMode} searchTerm={searchTerm} />}
|
||||
/>
|
||||
<Route path="/instance/:uuid" element={<InstancePage />} />
|
||||
<Route path="*" element={<NotFoundPage />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
<Footer />
|
||||
</div>
|
||||
</Theme>
|
||||
<>
|
||||
{enableVideoBackground && videoBackgroundUrl && (
|
||||
<video
|
||||
src={videoBackgroundUrl as string}
|
||||
autoPlay
|
||||
loop
|
||||
muted
|
||||
playsInline
|
||||
className="fixed right-0 bottom-0 min-w-full min-h-full w-auto h-auto -z-1 object-cover"></video>
|
||||
)}
|
||||
<Theme
|
||||
appearance={appearance === "system" ? "inherit" : appearance}
|
||||
accentColor={color}
|
||||
scaling="110%"
|
||||
style={{ backgroundColor: "transparent" }}>
|
||||
<div className="min-h-screen flex flex-col text-sm">
|
||||
<Header
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
searchTerm={searchTerm}
|
||||
setSearchTerm={setSearchTerm}
|
||||
/>
|
||||
<Suspense fallback={<Loading />}>
|
||||
<Routes>
|
||||
<Route
|
||||
path="/"
|
||||
element={
|
||||
<HomePage viewMode={viewMode} searchTerm={searchTerm} />
|
||||
}
|
||||
/>
|
||||
<Route path="/instance/:uuid" element={<InstancePage />} />
|
||||
<Route path="*" element={<NotFoundPage />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
<Footer />
|
||||
</div>
|
||||
</Theme>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user