mirror of
https://github.com/ourongxing/newsnow.git
synced 2025-01-19 03:09:14 +08:00
feat: support pwa
This commit is contained in:
parent
55b6710e49
commit
6d07702faf
3
.gitignore
vendored
3
.gitignore
vendored
@ -7,4 +7,5 @@ dist/
|
|||||||
.data
|
.data
|
||||||
.wrangler
|
.wrangler
|
||||||
.env
|
.env
|
||||||
.env.*
|
.env.*
|
||||||
|
dev-dist
|
54
index.html
54
index.html
@ -1,27 +1,33 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
<head>
|
||||||
<link rel="icon" type="image/svg+xml" href="/icon.svg" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<link rel="icon" type="image/svg+xml" href="/icon.svg" />
|
||||||
<script>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
function safeParseString(str) {
|
<meta name="description" content="Elegant reading of real-time and hottest news" />
|
||||||
try {
|
<meta name="theme-color" content="#F14D42" />
|
||||||
return JSON.parse(str)
|
<link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180" />
|
||||||
} catch {
|
<script>
|
||||||
return ""
|
function safeParseString(str) {
|
||||||
}
|
try {
|
||||||
|
return JSON.parse(str)
|
||||||
|
} catch {
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
const theme = safeParseString(localStorage.getItem("color-scheme")) || "auto"
|
}
|
||||||
const isDark = window.matchMedia("(prefers-color-scheme: dark)").matches
|
const theme = safeParseString(localStorage.getItem("color-scheme")) || "auto"
|
||||||
if (theme === "auto" ? isDark : theme === "dark") {
|
const isDark = window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||||
document.documentElement.classList.add("dark")
|
if (theme === "auto" ? isDark : theme === "dark") {
|
||||||
}
|
document.documentElement.classList.add("dark")
|
||||||
</script>
|
}
|
||||||
<title>NewsNow</title>
|
</script>
|
||||||
</head>
|
<title>NewsNow</title>
|
||||||
<body>
|
</head>
|
||||||
<div id="app"></div>
|
|
||||||
<script type="module" src="/src/app.tsx"></script>
|
<body>
|
||||||
</body>
|
<div id="app"></div>
|
||||||
</html>
|
<script type="module" src="/src/app.tsx"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
@ -3,6 +3,7 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"commit-id": "",
|
||||||
"packageManager": "pnpm@9.12.1",
|
"packageManager": "pnpm@9.12.1",
|
||||||
"author": {
|
"author": {
|
||||||
"url": "https://github.com/ourongxing/",
|
"url": "https://github.com/ourongxing/",
|
||||||
@ -88,9 +89,11 @@
|
|||||||
"unocss": "^0.63.4",
|
"unocss": "^0.63.4",
|
||||||
"unplugin-auto-import": "^0.18.3",
|
"unplugin-auto-import": "^0.18.3",
|
||||||
"vite": "^5.4.8",
|
"vite": "^5.4.8",
|
||||||
|
"vite-plugin-pwa": "^0.20.5",
|
||||||
"vite-plugin-with-nitro": "0.0.2",
|
"vite-plugin-with-nitro": "0.0.2",
|
||||||
"vite-tsconfig-paths": "^5.0.1",
|
"vite-tsconfig-paths": "^5.0.1",
|
||||||
"vitest": "^2.1.2",
|
"vitest": "^2.1.2",
|
||||||
|
"workbox-window": "^7.1.0",
|
||||||
"wrangler": "^3.80.3"
|
"wrangler": "^3.80.3"
|
||||||
},
|
},
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
|
2214
pnpm-lock.yaml
generated
2214
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
BIN
public/apple-touch-icon.png
Normal file
BIN
public/apple-touch-icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.0 KiB |
BIN
public/pwa-192x192.png
Normal file
BIN
public/pwa-192x192.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.4 KiB |
BIN
public/pwa-512x512.png
Normal file
BIN
public/pwa-512x512.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
2
public/robots.txt
Normal file
2
public/robots.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
User-agent: *
|
||||||
|
Allow: /
|
@ -5,7 +5,7 @@ export function Toast() {
|
|||||||
return (
|
return (
|
||||||
<Toaster
|
<Toaster
|
||||||
toastOptions={{
|
toastOptions={{
|
||||||
duration: 10000000,
|
duration: 5000,
|
||||||
unstyled: true,
|
unstyled: true,
|
||||||
classNames: {
|
classNames: {
|
||||||
toast: clsx(
|
toast: clsx(
|
||||||
@ -17,10 +17,10 @@ export function Toast() {
|
|||||||
"data-[type=warning]:(bg-yellow)",
|
"data-[type=warning]:(bg-yellow)",
|
||||||
),
|
),
|
||||||
icon: "text-white ml-1 dark:text-dark-600 text-op-80!",
|
icon: "text-white ml-1 dark:text-dark-600 text-op-80!",
|
||||||
content: "bg-base bg-op-70! p-2 rounded-lg color-base w-full backdrop-blur-md",
|
content: "bg-base bg-op-70! p-2 rounded-lg color-base w-full backdrop-blur-xl",
|
||||||
title: "font-normal text-base",
|
title: "font-normal text-base",
|
||||||
description: "color-base text-op-80! text-sm",
|
description: "color-base text-op-80! text-sm",
|
||||||
actionButton: "bg-base bg-op-70! rounded-lg py-2 w-4em backdrop-blur-md hover:(bg-base bg-op-60!)",
|
actionButton: "bg-base bg-op-70! rounded-lg py-2 w-4em backdrop-blur-lg hover:(bg-base bg-op-60!)",
|
||||||
closeButton: "bg-base bg-op-50! border-0 hover:(bg-base bg-op-70!)",
|
closeButton: "bg-base bg-op-50! border-0 hover:(bg-base bg-op-70!)",
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
@ -62,7 +62,7 @@ export function Header() {
|
|||||||
</p>
|
</p>
|
||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
<a target="_blank" href={`${Homepage}/release/tag/${Version}`} className="btn text-sm ml-1 font-mono">
|
<a target="_blank" href={`${Homepage}/releases/tag/v${Version}`} className="btn text-sm ml-1 font-mono">
|
||||||
{`v${Version}`}
|
{`v${Version}`}
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
|
28
src/hooks/usePWA.ts
Normal file
28
src/hooks/usePWA.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { useEffect } from "react"
|
||||||
|
import { toast } from "sonner"
|
||||||
|
import { useRegisterSW } from "virtual:pwa-register/react"
|
||||||
|
|
||||||
|
export function usePWA() {
|
||||||
|
const {
|
||||||
|
offlineReady: [offlineReady, setOfflineReady],
|
||||||
|
needRefresh: [needRefresh, setNeedRefresh],
|
||||||
|
updateServiceWorker,
|
||||||
|
} = useRegisterSW()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (offlineReady) {
|
||||||
|
toast.info("PWA 准备好了")
|
||||||
|
} else if (needRefresh) {
|
||||||
|
toast("有更新,点击更新", {
|
||||||
|
action: {
|
||||||
|
label: "更新",
|
||||||
|
onClick: () => updateServiceWorker(true),
|
||||||
|
},
|
||||||
|
onDismiss: () => {
|
||||||
|
setOfflineReady(false)
|
||||||
|
setNeedRefresh(false)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [offlineReady, needRefresh, updateServiceWorker, setOfflineReady, setNeedRefresh])
|
||||||
|
}
|
@ -11,6 +11,7 @@ import { GlobalOverlayScrollbar } from "~/components/common/overlay-scrollbar"
|
|||||||
import { useSync } from "~/hooks/useSync"
|
import { useSync } from "~/hooks/useSync"
|
||||||
import { Footer } from "~/components/footer"
|
import { Footer } from "~/components/footer"
|
||||||
import { Toast } from "~/components/common/toast"
|
import { Toast } from "~/components/common/toast"
|
||||||
|
import { usePWA } from "~/hooks/usePWA"
|
||||||
|
|
||||||
export const Route = createRootRouteWithContext<{
|
export const Route = createRootRouteWithContext<{
|
||||||
queryClient: QueryClient
|
queryClient: QueryClient
|
||||||
@ -37,6 +38,7 @@ function NotFoundComponent() {
|
|||||||
function RootComponent() {
|
function RootComponent() {
|
||||||
useOnReload()
|
useOnReload()
|
||||||
useSync()
|
useSync()
|
||||||
|
usePWA()
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<GlobalOverlayScrollbar className={clsx([
|
<GlobalOverlayScrollbar className={clsx([
|
||||||
|
3
src/vite-env.d.ts
vendored
3
src/vite-env.d.ts
vendored
@ -1,3 +1,6 @@
|
|||||||
/// <reference types="vite/client" />
|
/// <reference types="vite/client" />
|
||||||
|
/// <reference types="vite-plugin-pwa/react" />
|
||||||
|
/// <reference types="vite-plugin-pwa/info" />
|
||||||
|
/// <reference lib="webworker" />
|
||||||
declare const __G_CLIENT_ID__: string
|
declare const __G_CLIENT_ID__: string
|
||||||
declare const __ENABLE_LOGIN__: boolean
|
declare const __ENABLE_LOGIN__: boolean
|
||||||
|
@ -7,15 +7,56 @@ import { TanStackRouterVite } from "@tanstack/router-plugin/vite"
|
|||||||
import tsconfigPath from "vite-tsconfig-paths"
|
import tsconfigPath from "vite-tsconfig-paths"
|
||||||
import unocss from "unocss/vite"
|
import unocss from "unocss/vite"
|
||||||
import dotenv from "dotenv"
|
import dotenv from "dotenv"
|
||||||
|
import type { VitePWAOptions } from "vite-plugin-pwa"
|
||||||
|
import { VitePWA } from "vite-plugin-pwa"
|
||||||
import { projectDir } from "./shared/dir"
|
import { projectDir } from "./shared/dir"
|
||||||
|
|
||||||
const isCF = process.env.CF_PAGES
|
const isCF = process.env.CF_PAGES
|
||||||
|
|
||||||
dotenv.config({
|
dotenv.config({
|
||||||
path: join(projectDir, ".env.server"),
|
path: join(projectDir, ".env.server"),
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const pwaOption: Partial<VitePWAOptions> = {
|
||||||
|
includeAssets: ["icon.svg", "apple-touch-icon.png"],
|
||||||
|
manifest: {
|
||||||
|
name: "NewsNow",
|
||||||
|
short_name: "NewsNow",
|
||||||
|
description: "Elegant reading of real-time and hottest news",
|
||||||
|
theme_color: "#F14D42",
|
||||||
|
icons: [
|
||||||
|
{
|
||||||
|
src: "pwa-192x192.png",
|
||||||
|
sizes: "192x192",
|
||||||
|
type: "image/png",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "pwa-512x512.png",
|
||||||
|
sizes: "512x512",
|
||||||
|
type: "image/png",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "pwa-512x512.png",
|
||||||
|
sizes: "512x512",
|
||||||
|
type: "image/png",
|
||||||
|
purpose: "any",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "pwa-512x512.png",
|
||||||
|
sizes: "512x512",
|
||||||
|
type: "image/png",
|
||||||
|
purpose: "maskable",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
devOptions: {
|
||||||
|
enabled: process.env.SW_DEV === "true",
|
||||||
|
type: "module",
|
||||||
|
navigateFallback: "index.html",
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
define: {
|
define: {
|
||||||
__G_CLIENT_ID__: `"${process.env.G_CLIENT_ID}"`,
|
__G_CLIENT_ID__: `"${process.env.G_CLIENT_ID}"`,
|
||||||
@ -28,6 +69,7 @@ export default defineConfig({
|
|||||||
}),
|
}),
|
||||||
unocss(),
|
unocss(),
|
||||||
react(),
|
react(),
|
||||||
|
VitePWA(pwaOption),
|
||||||
nitro({
|
nitro({
|
||||||
experimental: {
|
experimental: {
|
||||||
database: true,
|
database: true,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user