From d4f6db436a1d0ea0a0353b4323673ea3babd5fab Mon Sep 17 00:00:00 2001 From: hamster1963 <1410514192@qq.com> Date: Thu, 13 Feb 2025 11:21:53 +0800 Subject: [PATCH] feat: add PWA support with manifest, icons, and theme color management --- .cert/cert.pem | 19 +++++++++++++ .cert/key.pem | 28 +++++++++++++++++++ index.html | 9 +++++++ public/android-chrome-192x192.png | Bin 0 -> 4863 bytes public/manifest.json | 17 ++++++++++++ src/components/ThemeColorManager.tsx | 39 +++++++++++++++++++++++++++ src/main.tsx | 2 ++ vite.config.ts | 5 ++++ 8 files changed, 119 insertions(+) create mode 100644 .cert/cert.pem create mode 100644 .cert/key.pem create mode 100644 public/android-chrome-192x192.png create mode 100644 public/manifest.json create mode 100644 src/components/ThemeColorManager.tsx diff --git a/.cert/cert.pem b/.cert/cert.pem new file mode 100644 index 0000000..22a7231 --- /dev/null +++ b/.cert/cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDCTCCAfGgAwIBAgIUQxY5HJAktPoEWU9osMraUrm/DEAwDQYJKoZIhvcNAQEL +BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI1MDIxMzAzMTA0MVoXDTI2MDIx +MzAzMTA0MVowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAraDt2UXkzKLRskNtVDo1iXe1tBTYTAFtl+m7JOvdYdmS +oenV3Cn/8Cd8JuusQVl9jovcMFb3pwrQzodSQ9oN70B/MSqA/Pjgpji+uu4Hjcas +VhaAHregBsV8ULl+OikPPFWcGKRZMtRyta3Sy/2E5Y44wr8vdERKDl/6ydDVioe5 +dQQS+klyzamy9ayQj8fpSTR96H+WpDd6gGuDf+XlrqlnrgatiUIJiDkeJPCIUNJi +VSw8lq3KO8O4K376smCAdngdyYg+q/Sk2r5MnHi9VqNknwmos06yPk6vTWIpZ+mK +bz9W2HW4sukU0nwRXP0p29SKoW5ZKPvrLvfNDp0P3QIDAQABo1MwUTAdBgNVHQ4E +FgQUYSHtj6LjfaQ0BmuCdlHf/EXKm5AwHwYDVR0jBBgwFoAUYSHtj6LjfaQ0BmuC +dlHf/EXKm5AwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAQnM/ +MIYunEp8ITMtllILW9TJhZVertfuux4S1rgRZ3VADmHgHftCgUKpm4kh8w2gEZ0M +DXTmnIwqaBa+lpiCcALECUQ1L2jPcwCYowmEfnKLF6Ob3Tnznz0eqr8TnvuKCX4c +ehSlfqOcUn8rveLDX91j+FJ+LSggf/kYjhE0ACtZHJyEM9csWu5chu8cCjpq5pn/ +ahiPw5eUnxsyBWdqlkMvY+lofH7SaunXrbLcIDg67wMl0FpZ39z/UAhIVNiyUIDe +k7pNzRu99r5hIqdyfx5zULG2mzJCSsJj63t4BeDwr6u+zXSlyVMqh5cXj9mk4LJ6 +DhJlnudcCV5t/RGyOw== +-----END CERTIFICATE----- diff --git a/.cert/key.pem b/.cert/key.pem new file mode 100644 index 0000000..53b20f4 --- /dev/null +++ b/.cert/key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCtoO3ZReTMotGy +Q21UOjWJd7W0FNhMAW2X6bsk691h2ZKh6dXcKf/wJ3wm66xBWX2Oi9wwVvenCtDO +h1JD2g3vQH8xKoD8+OCmOL667geNxqxWFoAet6AGxXxQuX46KQ88VZwYpFky1HK1 +rdLL/YTljjjCvy90REoOX/rJ0NWKh7l1BBL6SXLNqbL1rJCPx+lJNH3of5akN3qA +a4N/5eWuqWeuBq2JQgmIOR4k8IhQ0mJVLDyWrco7w7grfvqyYIB2eB3JiD6r9KTa +vkyceL1Wo2SfCaizTrI+Tq9NYiln6YpvP1bYdbiy6RTSfBFc/Snb1Iqhblko++su +980OnQ/dAgMBAAECggEAI/6N+GI9N7AUVUaVqmWj1iL/Q/0jRwRvxhOyFIoiG6gp +dg/+IhWB5bUlz4LBc8270fqME+hfkF1VYs9aXk8c3unJxHVJhsgIeGUgoyt33Owg +K3ugJV4PWoAD0M9Xi/KZojokMVaW2EsDGcdWgSwGKjmk6jiMu6dxi8/Zc4+ryTsY +3+KMUocFyqMfYK1/sYSTPzlPWcCGMuaO36Df++cAzKLlqHRh7BLgSiCXBrV8ITFf +LTkQFDf/c+yVC6mJG/GXzqdKXS3OT97sW34tdmQPNhReCSkSEDVQt+tnFa5be1R2 +18mODkaSv4DxnMXnlfexon/pGuXukgrMTZQXq2+pIQKBgQDaNvBmJrSCU9NSDNSj +I0yTX8DUzEv1bxErbfptSlSoUcEIPcLsxt+xZFVfU8IcMvQ43gHSsRquCfZsUZ0r +/ZIfJ7pWTqbxd/EybsMiC2ZSS8NdVX3MJhKinrZXMTRAA8l5a4AFr2YKMtNqQpGY +xWu8TS7PR8N9B6vZqGC9hhID4QKBgQDLsZLrezomWTthFAOfACj/ebIEyZ30YVNw +7IaaVTkeWtYGJXasMrts1+n15dPwR6a18c65hSywJKsCEYD6z/uXxaoX1bK32oLw +49thMw+qSilA1jMQ/XQxx9TFsmrCvwSm5xIjSV+0pD1sApiivGQAU+2oHZeEwLue +v51JxnaLfQKBgQDVYUWgThbTHk8U+7DuObVGoyp3q7JXNJ1wf2GTf0zbLt54RZSX +Xj0dRMRqrAey9Wx1MzpLIZ26M8nAz+nGO3Woe3utq8l5c9TqgP7VCpqqvKU0XkXd +3Bj65gHdryKtukZIMgOFC6fXLy4mySOAZQRdpIeybzVMzLSR6SF4EmMJYQKBgGtz +xVlLrCVGtThE4pQh9X6vp+U2poigPvA3FdqcUoFc0cJ0SOIV8SE91UHOd7stURhx +8ueTBTv2W++/ZBbrWIF72HqyVJEASErjKHtiAEWI0bJOTKoNyhnonKmdsQwC0GVr +R/otXrtgWLZ9uB9A2lAB9kDVO3TgZxkbY9HjS+3RAoGBAKVKcJFErNZhQxCx5ll3 +u9wtE7duiVcS3jZhFa7tvcSc4O5+ahEQG/gy2M6kgqB/f3nMH6Rd9wsTzwPp1uZz +qiumr3ZOvpTWuLiIMQi3sE9pBGz7p+ZTeP8Z0Wez98v9MVmgsCsPqDOpa1JhnJIq +2AgG3D/RUJylOPYnMq8vdAyx +-----END PRIVATE KEY----- diff --git a/index.html b/index.html index f2114e7..e87d011 100644 --- a/index.html +++ b/index.html @@ -108,6 +108,15 @@ 哪吒监控 Nezha Monitoring + + + + + + + + + diff --git a/public/android-chrome-192x192.png b/public/android-chrome-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..0e09ce167cbee42ceed8522e2c7405dced747936 GIT binary patch literal 4863 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 D^*f { + const updateThemeColor = () => { + const currentTheme = theme + const meta = document.querySelector('meta[name="theme-color"]') + + if (!meta) { + const newMeta = document.createElement("meta") + newMeta.name = "theme-color" + document.head.appendChild(newMeta) + } + + const themeColor = + currentTheme === "dark" + ? "hsl(30 15% 8%)" // 深色模式背景色 + : "hsl(0 0% 98%)" // 浅色模式背景色 + + document.querySelector('meta[name="theme-color"]')?.setAttribute("content", themeColor) + } + + // Update on mount and theme change + updateThemeColor() + + // Listen for system theme changes + const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)") + mediaQuery.addEventListener("change", updateThemeColor) + + return () => mediaQuery.removeEventListener("change", updateThemeColor) + }, [theme]) + + return null +} diff --git a/src/main.tsx b/src/main.tsx index 1be15b4..a8048c8 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -4,6 +4,7 @@ import ReactDOM from "react-dom/client" import { Toaster } from "sonner" import App from "./App" +import { ThemeColorManager } from "./components/ThemeColorManager" import { ThemeProvider } from "./components/ThemeProvider" import { MotionProvider } from "./components/motion/motion-provider" import { SortProvider } from "./context/sort-provider" @@ -18,6 +19,7 @@ const queryClient = new QueryClient() ReactDOM.createRoot(document.getElementById("root")!).render( + diff --git a/vite.config.ts b/vite.config.ts index e9011f8..d17ebb5 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,5 +1,6 @@ import react from "@vitejs/plugin-react-swc" import { execSync } from "child_process" +import fs from "fs" import path from "path" import { defineConfig } from "vite" @@ -26,6 +27,10 @@ export default defineConfig({ }, }, server: { + https: { + key: fs.readFileSync("./.cert/key.pem"), + cert: fs.readFileSync("./.cert/cert.pem"), + }, proxy: { "/api/v1/ws/server": { target: "ws://localhost:8008",