diff --git a/package.json b/package.json index 16234fb4..22a226fb 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "husky": "^8.0.3", "typescript": "^5.6.2", "vite": "^4.1.4", - "vite-plugin-html": "^3.2.0" + "vite-plugin-html": "^3.2.0", + "vite-plugin-pwa": "^1.2.0" } } \ No newline at end of file diff --git a/public/site.webmanifest b/public/site.webmanifest deleted file mode 100644 index cf1e19ba..00000000 --- a/public/site.webmanifest +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "VIA", - "short_name": "VIA", - "description": "VIA - Your keyboard's best friend", - "start_url": ".", - "icons": [ - { - "src": "/android-chrome-192x192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "/android-chrome-512x512.png", - "sizes": "512x512", - "type": "image/png" - } - ], - "theme_color": "#dadada", - "background_color": "#dadada", - "display": "standalone" -} diff --git a/src/components/panes/design.tsx b/src/components/panes/design.tsx index fb555958..521007eb 100644 --- a/src/components/panes/design.tsx +++ b/src/components/panes/design.tsx @@ -173,7 +173,7 @@ function importDefinitions( [] ).map( (e) => - `${fileName} ${e.dataPath ? e.dataPath + ': ' : 'Object: '}${ + `${fileName} ${e.instancePath ? e.instancePath + ': ' : 'Object: '}${ e.message }`, ); diff --git a/vite.config.ts b/vite.config.ts index f8e28af0..bffd0232 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -3,6 +3,7 @@ import react from '@vitejs/plugin-react'; import path from 'path'; import {splitVendorChunkPlugin} from 'vite'; import {createHtmlPlugin} from 'vite-plugin-html'; +import {VitePWA} from 'vite-plugin-pwa'; import fs from 'fs'; const hash = fs.readFileSync('public/definitions/hash.json', 'utf8'); @@ -10,6 +11,92 @@ const hash = fs.readFileSync('public/definitions/hash.json', 'utf8'); // https://vitejs.dev/config/ export default defineConfig({ plugins: [ + VitePWA({ + manifestFilename: 'site.webmanifest', + manifest: { + name: "VIA", + short_name: "VIA", + description: "VIA - Your keyboard's best friend", + id: "/", + start_url: ".", + icons: [ + { + src: "/android-chrome-192x192.png", + sizes: "192x192", + type: "image/png", + }, + { + src: "/android-chrome-512x512.png", + sizes: "512x512", + type: "image/png" + } + ], + theme_color: "#dadada", + background_color: "#dadada", + display: "standalone" + }, + includeAssets: [ + 'favicon.ico', + 'apple-touch-icon.png', + 'favicon-16x16.png', + 'favicon-32x32.png', + 'safari-pinned-tab.svg', + ], + workbox: { + runtimeCaching: [ + { + urlPattern: ({ url }) => url.origin === self.origin && (['/definitions/', '/fonts/', '/images/'].some(prefix => url.pathname.startsWith(prefix)) || url.pathname.endsWith('.glb')), + handler: 'CacheFirst', + options: { + cacheName: 'via-assets', + expiration: { maxAgeSeconds: 60 * 60 * 24 * 365 } + } + }, + { + urlPattern: ({ url }) => url.origin === 'https://fonts.googleapis.com' && url.pathname.startsWith('/css'), + handler: 'CacheFirst', + options: { + cacheName: 'google-fonts-stylesheets', + expiration: { + maxEntries: 10, + maxAgeSeconds: 60 * 60 * 24 * 365 + }, + cacheableResponse: { + statuses: [0, 200] + } + } + }, + { + urlPattern: ({ url }) => url.origin === 'https://fonts.gstatic.com', + handler: 'CacheFirst', + options: { + cacheName: 'gstatic-fonts', + expiration: { + maxEntries: 30, + maxAgeSeconds: 60 * 60 * 24 * 365 + }, + cacheableResponse: { + statuses: [0, 200] + } + } + }, + { + urlPattern: ({ url }) => url.origin === 'https://www.gstatic.com' && url.pathname.startsWith('/draco/'), + handler: 'CacheFirst', + options: { + cacheName: 'gstatic-draco', + expiration: { + maxEntries: 30, + maxAgeSeconds: 60 * 60 * 24 * 365 + }, + cacheableResponse: { + statuses: [0, 200] + } + } + } + ] + } + }), react(), createHtmlPlugin({ inject: {