修改图标
BIN
app/favicon.ico
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 31 KiB |
@ -9,26 +9,19 @@ export const metadata: Metadata = {
|
|||||||
description: "随时了解长辈的近况,查看留言、使用动态,给长辈写问候。",
|
description: "随时了解长辈的近况,查看留言、使用动态,给长辈写问候。",
|
||||||
manifest: "/manifest.webmanifest",
|
manifest: "/manifest.webmanifest",
|
||||||
icons: {
|
icons: {
|
||||||
icon: [
|
icon: {
|
||||||
{
|
url: "/app-icon.webp",
|
||||||
url: "/pwa/icon-192x192.png",
|
sizes: "512x512",
|
||||||
sizes: "192x192",
|
type: "image/webp",
|
||||||
type: "image/png",
|
},
|
||||||
},
|
|
||||||
{
|
|
||||||
url: "/pwa/icon-512x512.png",
|
|
||||||
sizes: "512x512",
|
|
||||||
type: "image/png",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
apple: [
|
apple: [
|
||||||
{
|
{
|
||||||
url: "/pwa/apple-touch-icon.png",
|
url: "/pwa/apple-touch-icon.webp",
|
||||||
sizes: "180x180",
|
sizes: "180x180",
|
||||||
type: "image/png",
|
type: "image/webp",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
shortcut: "/pwa/icon-192x192.png",
|
shortcut: "/app-icon.webp",
|
||||||
},
|
},
|
||||||
appleWebApp: {
|
appleWebApp: {
|
||||||
capable: true,
|
capable: true,
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import Image from "next/image";
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
|
|
||||||
import { AccountAuthForm } from "@/components/account-auth-form";
|
import { AccountAuthForm } from "@/components/account-auth-form";
|
||||||
@ -15,7 +16,14 @@ export default async function LoginPage({ searchParams }: PageProps<"/login">) {
|
|||||||
<main className="app-frame" style={{ display: "flex", alignItems: "center" }}>
|
<main className="app-frame" style={{ display: "flex", alignItems: "center" }}>
|
||||||
<section style={{ width: "100%", padding: "28px 22px", display: "flex", flexDirection: "column", gap: 22 }}>
|
<section style={{ width: "100%", padding: "28px 22px", display: "flex", flexDirection: "column", gap: 22 }}>
|
||||||
<div>
|
<div>
|
||||||
<div style={{ display: "flex", width: 52, height: 52, alignItems: "center", justifyContent: "center", borderRadius: 14, background: "var(--accent)", color: "#fff", fontSize: 22, fontWeight: 700 }}>安</div>
|
<Image
|
||||||
|
src="/app-icon.webp"
|
||||||
|
alt="安智伴"
|
||||||
|
width={52}
|
||||||
|
height={52}
|
||||||
|
priority
|
||||||
|
style={{ display: "block", borderRadius: 14 }}
|
||||||
|
/>
|
||||||
<h1 style={{ margin: "16px 0 0", fontSize: 24, lineHeight: 1.35 }}>安智伴 家属端</h1>
|
<h1 style={{ margin: "16px 0 0", fontSize: 24, lineHeight: 1.35 }}>安智伴 家属端</h1>
|
||||||
<p style={{ margin: "8px 0 0", color: "var(--muted)", fontSize: 13.5, lineHeight: 1.7 }}>用同一个账号,在每一台设备上继续守护。长辈的留言、对话与动态都按账号归属。</p>
|
<p style={{ margin: "8px 0 0", color: "var(--muted)", fontSize: 13.5, lineHeight: 1.7 }}>用同一个账号,在每一台设备上继续守护。长辈的留言、对话与动态都按账号归属。</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -13,21 +13,21 @@ export default function manifest(): MetadataRoute.Manifest {
|
|||||||
categories: ["utilities", "lifestyle", "health"],
|
categories: ["utilities", "lifestyle", "health"],
|
||||||
icons: [
|
icons: [
|
||||||
{
|
{
|
||||||
src: "/pwa/icon-192x192.png",
|
src: "/pwa/icon-192x192.webp",
|
||||||
sizes: "192x192",
|
sizes: "192x192",
|
||||||
type: "image/png",
|
type: "image/webp",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
src: "/pwa/icon-512x512.png",
|
src: "/pwa/icon-512x512.webp",
|
||||||
sizes: "512x512",
|
sizes: "512x512",
|
||||||
type: "image/png",
|
type: "image/webp",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
src: "/pwa/icon-maskable-512x512.png",
|
src: "/pwa/icon-maskable-512x512.webp",
|
||||||
sizes: "512x512",
|
sizes: "512x512",
|
||||||
type: "image/png",
|
type: "image/webp",
|
||||||
purpose: "maskable",
|
purpose: "maskable",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
9
bun.lock
@ -1,6 +1,5 @@
|
|||||||
{
|
{
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"configVersion": 0,
|
|
||||||
"workspaces": {
|
"workspaces": {
|
||||||
"": {
|
"": {
|
||||||
"name": "digital-human-monitor-v2",
|
"name": "digital-human-monitor-v2",
|
||||||
@ -31,6 +30,10 @@
|
|||||||
"tailwindcss": "^4",
|
"tailwindcss": "^4",
|
||||||
"typescript": "^5",
|
"typescript": "^5",
|
||||||
},
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@tailwindcss/oxide-darwin-arm64": "4.2.2",
|
||||||
|
"lightningcss-darwin-arm64": "1.32.0",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"trustedDependencies": [
|
"trustedDependencies": [
|
||||||
@ -208,6 +211,8 @@
|
|||||||
|
|
||||||
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.2.2", "", { "optionalDependencies": { "@tailwindcss/oxide-win32-x64-msvc": "4.2.2" } }, ""],
|
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.2.2", "", { "optionalDependencies": { "@tailwindcss/oxide-win32-x64-msvc": "4.2.2" } }, ""],
|
||||||
|
|
||||||
|
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.2.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.2.2", "", { "os": "win32", "cpu": "x64" }, ""],
|
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.2.2", "", { "os": "win32", "cpu": "x64" }, ""],
|
||||||
|
|
||||||
"@tailwindcss/postcss": ["@tailwindcss/postcss@4.2.2", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "4.2.2", "@tailwindcss/oxide": "4.2.2", "postcss": "^8.5.6", "tailwindcss": "4.2.2" } }, ""],
|
"@tailwindcss/postcss": ["@tailwindcss/postcss@4.2.2", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "4.2.2", "@tailwindcss/oxide": "4.2.2", "postcss": "^8.5.6", "tailwindcss": "4.2.2" } }, ""],
|
||||||
@ -704,6 +709,8 @@
|
|||||||
|
|
||||||
"lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-win32-x64-msvc": "1.32.0" } }, ""],
|
"lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-win32-x64-msvc": "1.32.0" } }, ""],
|
||||||
|
|
||||||
|
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="],
|
||||||
|
|
||||||
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, ""],
|
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, ""],
|
||||||
|
|
||||||
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, ""],
|
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, ""],
|
||||||
|
|||||||
@ -36,6 +36,10 @@
|
|||||||
"tailwindcss": "^4",
|
"tailwindcss": "^4",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
},
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@tailwindcss/oxide-darwin-arm64": "4.2.2",
|
||||||
|
"lightningcss-darwin-arm64": "1.32.0"
|
||||||
|
},
|
||||||
"ignoreScripts": [
|
"ignoreScripts": [
|
||||||
"sharp",
|
"sharp",
|
||||||
"unrs-resolver"
|
"unrs-resolver"
|
||||||
|
|||||||
BIN
public/app-icon.webp
Normal file
|
After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 71 KiB |
BIN
public/pwa/apple-touch-icon.webp
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 24 KiB |
BIN
public/pwa/badge-96x96.webp
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 80 KiB |
BIN
public/pwa/icon-192x192.webp
Normal file
|
After Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 519 KiB |
BIN
public/pwa/icon-512x512.webp
Normal file
|
After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 334 KiB |
BIN
public/pwa/icon-maskable-512x512.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |
@ -3,8 +3,8 @@ self.addEventListener("push", (event) => {
|
|||||||
title: "安智伴 家人连线台",
|
title: "安智伴 家人连线台",
|
||||||
body: "收到一条新的家人留言。",
|
body: "收到一条新的家人留言。",
|
||||||
url: "/",
|
url: "/",
|
||||||
icon: "/pwa/icon-192x192.png",
|
icon: "/pwa/icon-192x192.webp",
|
||||||
badge: "/pwa/badge-96x96.png",
|
badge: "/pwa/badge-96x96.webp",
|
||||||
tag: "digital-human-message",
|
tag: "digital-human-message",
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -63,4 +63,4 @@ self.addEventListener("notificationclick", (event) => {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import sharp from "sharp";
|
|||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = path.dirname(__filename);
|
const __dirname = path.dirname(__filename);
|
||||||
const projectRoot = path.resolve(__dirname, "..");
|
const projectRoot = path.resolve(__dirname, "..");
|
||||||
const sourceIconPath = path.join(projectRoot, "icon.png");
|
const sourceIconPath = path.join(projectRoot, "app", "icon.png");
|
||||||
const pwaOutputDir = path.join(projectRoot, "public", "pwa");
|
const pwaOutputDir = path.join(projectRoot, "public", "pwa");
|
||||||
|
|
||||||
const androidResArg = process.argv.find((arg) =>
|
const androidResArg = process.argv.find((arg) =>
|
||||||
@ -25,16 +25,19 @@ function createCircleMask(size) {
|
|||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function writePng(size, outputPath) {
|
async function writeWebp(size, outputPath) {
|
||||||
await sharp(sourceIconPath).resize(size, size).png().toFile(outputPath);
|
await sharp(sourceIconPath)
|
||||||
|
.resize(size, size)
|
||||||
|
.webp({ quality: 88, effort: 6 })
|
||||||
|
.toFile(outputPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function writeMaskablePng(size, outputPath) {
|
async function writeMaskableWebp(size, outputPath) {
|
||||||
const foreground = await sharp(sourceIconPath)
|
const foreground = await sharp(sourceIconPath)
|
||||||
.resize(Math.round(size * 0.82), Math.round(size * 0.82), {
|
.resize(Math.round(size * 0.82), Math.round(size * 0.82), {
|
||||||
fit: "contain",
|
fit: "contain",
|
||||||
})
|
})
|
||||||
.png()
|
.webp({ quality: 88, effort: 6 })
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
|
|
||||||
await sharp({
|
await sharp({
|
||||||
@ -51,7 +54,7 @@ async function writeMaskablePng(size, outputPath) {
|
|||||||
gravity: "center",
|
gravity: "center",
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
.png()
|
.webp({ quality: 88, effort: 6 })
|
||||||
.toFile(outputPath);
|
.toFile(outputPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,15 +95,15 @@ async function writeAndroidIcons(resDir) {
|
|||||||
await mkdir(pwaOutputDir, { recursive: true });
|
await mkdir(pwaOutputDir, { recursive: true });
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
writePng(192, path.join(pwaOutputDir, "icon-192x192.png")),
|
writeWebp(192, path.join(pwaOutputDir, "icon-192x192.webp")),
|
||||||
writePng(512, path.join(pwaOutputDir, "icon-512x512.png")),
|
writeWebp(512, path.join(pwaOutputDir, "icon-512x512.webp")),
|
||||||
writePng(180, path.join(pwaOutputDir, "apple-touch-icon.png")),
|
writeWebp(180, path.join(pwaOutputDir, "apple-touch-icon.webp")),
|
||||||
writePng(96, path.join(pwaOutputDir, "badge-96x96.png")),
|
writeWebp(96, path.join(pwaOutputDir, "badge-96x96.webp")),
|
||||||
writeMaskablePng(512, path.join(pwaOutputDir, "icon-maskable-512x512.png")),
|
writeMaskableWebp(512, path.join(pwaOutputDir, "icon-maskable-512x512.webp")),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (androidResDir) {
|
if (androidResDir) {
|
||||||
await writeAndroidIcons(androidResDir);
|
await writeAndroidIcons(androidResDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Icons generated successfully.");
|
console.log("Icons generated successfully.");
|
||||||
|
|||||||