From a62e03b439b22d42598f2e29fd839cde7f18125f Mon Sep 17 00:00:00 2001 From: diced Date: Sun, 22 Sep 2024 15:10:36 -0700 Subject: [PATCH] feat: pwa --- prisma/schema.prisma | 7 + public/favicon-128x128.png | Bin 0 -> 5132 bytes public/favicon-16x16.png | Bin 0 -> 582 bytes public/favicon-32x32.png | Bin 0 -> 1133 bytes public/favicon-512x512.png | Bin 0 -> 31267 bytes public/favicon-64x64.png | Bin 0 -> 2493 bytes src/components/pages/serverSettings/index.tsx | 7 +- .../parts/ServerSettingsPWA.tsx | 126 ++++++++++++++++++ src/lib/config/read.ts | 15 +++ src/lib/config/validate.ts | 8 ++ src/pages/_app.tsx | 2 +- src/server/routes/api/server/settings.ts | 7 + src/server/routes/manifest.ts | 35 +++++ 13 files changed, 204 insertions(+), 3 deletions(-) create mode 100644 public/favicon-128x128.png create mode 100644 public/favicon-16x16.png create mode 100644 public/favicon-32x32.png create mode 100644 public/favicon-512x512.png create mode 100644 public/favicon-64x64.png create mode 100644 src/components/pages/serverSettings/parts/ServerSettingsPWA.tsx create mode 100644 src/server/routes/manifest.ts diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 5fb03dec..b38daafa 100755 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -116,6 +116,13 @@ model Zipline { discordOnShortenAvatarUrl String? discordOnShortenContent String? discordOnShortenEmbed Json? + + pwaEnabled Boolean @default(false) + pwaTitle String @default("Zipline") + pwaShortName String @default("Zipline") + pwaDescription String @default("Zipline") + pwaThemeColor String @default("#000000") + pwaBackgroundColor String @default("#000000") } model User { diff --git a/public/favicon-128x128.png b/public/favicon-128x128.png new file mode 100644 index 0000000000000000000000000000000000000000..d209dd19379788227ee844f21d1175cae70dfdc3 GIT binary patch literal 5132 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 UoGZ}#jQ{`u07*qoM6N<$g8gLq6#xJL literal 0 HcmV?d00001 diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..3ffa45963d9fe857aa3c886f9e3f65bf63025f88 GIT binary patch literal 1133 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 Hu0mjfkQ1Dc literal 0 HcmV?d00001 diff --git a/src/components/pages/serverSettings/index.tsx b/src/components/pages/serverSettings/index.tsx index 5f88e926..96e02b9c 100644 --- a/src/components/pages/serverSettings/index.tsx +++ b/src/components/pages/serverSettings/index.tsx @@ -14,6 +14,7 @@ import ServerSettingsRatelimit from './parts/ServerSettingsRatelimit'; import ServerSettingsTasks from './parts/ServerSettingsTasks'; import ServerSettingsUrls from './parts/ServerSettingsUrls'; import ServerSettingsWebsite from './parts/ServerSettingsWebsite'; +import ServerSettingsPWA from './parts/ServerSettingsPWA'; export default function DashboardSettings() { const { data, isLoading, error } = useSWR('/api/server/settings'); @@ -44,6 +45,10 @@ export default function DashboardSettings() { + + + + )} @@ -53,8 +58,6 @@ export default function DashboardSettings() {
Error loading server settings
) : ( <> - - )} diff --git a/src/components/pages/serverSettings/parts/ServerSettingsPWA.tsx b/src/components/pages/serverSettings/parts/ServerSettingsPWA.tsx new file mode 100644 index 00000000..1b170be5 --- /dev/null +++ b/src/components/pages/serverSettings/parts/ServerSettingsPWA.tsx @@ -0,0 +1,126 @@ +import { Response } from '@/lib/api/response'; +import { + Button, + ColorInput, + LoadingOverlay, + Paper, + SimpleGrid, + Switch, + TextInput, + Title, +} from '@mantine/core'; +import { useForm } from '@mantine/form'; +import { IconDeviceFloppy } from '@tabler/icons-react'; +import { useRouter } from 'next/router'; +import { useEffect } from 'react'; +import { settingsOnSubmit } from '../settingsOnSubmit'; + +export default function ServerSettingsPWA({ + swr: { data, isLoading }, +}: { + swr: { data: Response['/api/server/settings'] | undefined; isLoading: boolean }; +}) { + const router = useRouter(); + const form = useForm({ + initialValues: { + pwaEnabled: false, + pwaTitle: '', + pwaShortName: '', + pwaDescription: '', + pwaThemeColor: '', + pwaBackgroundColor: '', + }, + }); + + const onSubmit = async (values: typeof form.values) => { + const sendValues: Record = {}; + + sendValues.pwaTitle = values.pwaTitle.trim() === '' ? null : values.pwaTitle.trim(); + sendValues.pwaShortName = values.pwaShortName.trim() === '' ? null : values.pwaShortName.trim(); + sendValues.pwaDescription = values.pwaDescription.trim() === '' ? null : values.pwaDescription.trim(); + + return settingsOnSubmit( + router, + form, + )({ + ...sendValues, + pwaEnabled: values.pwaEnabled, + pwaThemeColor: values.pwaThemeColor, + pwaBackgroundColor: values.pwaBackgroundColor, + }); + }; + + useEffect(() => { + form.setValues({ + pwaEnabled: data?.pwaEnabled ?? false, + pwaTitle: data?.pwaTitle ?? '', + pwaShortName: data?.pwaShortName ?? '', + pwaDescription: data?.pwaDescription ?? '', + pwaThemeColor: data?.pwaThemeColor ?? '', + pwaBackgroundColor: data?.pwaBackgroundColor ?? '', + }); + }, [data]); + + return ( + + + + PWA + +
+ + + + + + + + + + + + + + + + +
+ ); +} diff --git a/src/lib/config/read.ts b/src/lib/config/read.ts index acee7f66..76385777 100755 --- a/src/lib/config/read.ts +++ b/src/lib/config/read.ts @@ -129,6 +129,14 @@ export const rawConfig: any = { key: undefined, cert: undefined, }, + pwa: { + enabled: undefined, + title: undefined, + shortName: undefined, + description: undefined, + backgroundColor: undefined, + themeColor: undefined, + }, }; export const PROP_TO_ENV = { @@ -256,6 +264,13 @@ export const DATABASE_TO_PROP = { discordOnShortenAvatarUrl: 'discord.onShorten.avatarUrl', discordOnShortenContent: 'discord.onShorten.content', discordOnShortenEmbed: 'discord.onShorten.embed', + + pwaEnabled: 'pwa.enabled', + pwaTitle: 'pwa.title', + pwaShortName: 'pwa.shortName', + pwaDescription: 'pwa.description', + pwaThemeColor: 'pwa.themeColor', + pwaBackgroundColor: 'pwa.backgroundColor', }; const logger = log('config').c('read'); diff --git a/src/lib/config/validate.ts b/src/lib/config/validate.ts index 3bf2722e..75d7d614 100755 --- a/src/lib/config/validate.ts +++ b/src/lib/config/validate.ts @@ -297,6 +297,14 @@ export const schema = z.object({ .nullable() .default(null), }), + pwa: z.object({ + enabled: z.boolean().default(true), + title: z.string().default('Zipline'), + shortName: z.string().default('Zipline'), + description: z.string().default('Zipline'), + themeColor: z.string().default('#000000'), + backgroundColor: z.string().default('#000000'), + }), }); export type Config = z.infer; diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index ef11b905..093a1883 100755 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -12,7 +12,6 @@ import '@mantine/dropzone/styles.css'; import '@mantine/notifications/styles.css'; import 'mantine-datatable/styles.css'; -import '@/lib/theme/override.css'; import '@/components/render/code/HighlightCode.theme.css'; const fetcher = async (url: RequestInfo | URL) => { @@ -35,6 +34,7 @@ export default function App({ Component, pageProps }: AppProps) { Zipline + ({ + src: `/favicon-${size}x${size}.png`, + sizes: `${size}x${size}`, + type: 'image/png', + })); +} + +export const PATH = '/manifest.json'; +export default fastifyPlugin( + (server, _, done) => { + server.get(PATH, async (_, res) => { + if (!config.pwa.enabled) return res.notFound(); + + return { + name: config.pwa.title, + short_name: config.pwa.shortName, + description: config.pwa.description, + theme_color: config.pwa.themeColor, + background_color: config.pwa.backgroundColor, + + start_url: '/', + display: 'standalone', + icons: generateIcons([16, 32, 64, 128, 512]), + } satisfies MetadataRoute.Manifest; + }); + + done(); + }, + { name: PATH }, +);