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",