Add PWA Registration

This commit is contained in:
gitmotion
2025-03-12 14:00:38 -07:00
parent fc83e527b7
commit c4a806604a
8 changed files with 103 additions and 0 deletions

3
.gitignore vendored
View File

@@ -196,6 +196,9 @@ Thumbs.db
!uploads/.gitkeep
!local_uploads/.gitkeep
# Generated PWA Files
/public/*manifest.json
# Misc
*.log
.env.*

3
nodemon.json Normal file
View File

@@ -0,0 +1,3 @@
{
"ignore": ["asset-manifest.json", "manifest.json"]
}

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 639 B

After

Width:  |  Height:  |  Size: 639 B

View File

@@ -7,6 +7,7 @@
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/toastify-js/src/toastify.min.css">
<script src="https://cdn.jsdelivr.net/npm/toastify-js"></script>
<link rel="manifest" href="/manifest.json">
</head>
<body>
<div class="container">

32
public/service-worker.js Normal file
View File

@@ -0,0 +1,32 @@
const CACHE_NAME = "DUMBDROP_PWA_CACHE_V1";
const ASSETS_TO_CACHE = [];
const preload = async () => {
console.log("Installing web app");
return await caches.open(CACHE_NAME)
.then(async (cache) => {
console.log("caching index and important routes");
const response = await fetch("/asset-manifest.json");
const assets = await response.json();
ASSETS_TO_CACHE.push(...assets);
console.log("Assets Cached:", ASSETS_TO_CACHE);
return cache.addAll(ASSETS_TO_CACHE);
});
}
// Fetch asset manifest dynamically
globalThis.addEventListener("install", (event) => {
event.waitUntil(preload());
});
globalThis.addEventListener("activate", (event) => {
event.waitUntil(clients.claim());
});
globalThis.addEventListener("fetch", (event) => {
event.respondWith(
caches.match(event.request).then((cachedResponse) => {
return cachedResponse || fetch(event.request);
})
);
});

View File

@@ -0,0 +1,60 @@
const fs = require("fs");
const path = require("path");
const PUBLIC_DIR = path.join(__dirname, "..", "..", "public");
function getFiles(dir, basePath = "/") {
let fileList = [];
const files = fs.readdirSync(dir);
files.forEach((file) => {
const filePath = path.join(dir, file);
const fileUrl = path.join(basePath, file).replace(/\\/g, "/");
if (fs.statSync(filePath).isDirectory()) {
fileList = fileList.concat(getFiles(filePath, fileUrl));
} else {
fileList.push(fileUrl);
}
});
return fileList;
}
function generateAssetManifest() {
const assets = getFiles(PUBLIC_DIR);
fs.writeFileSync(path.join(PUBLIC_DIR, "asset-manifest.json"), JSON.stringify(assets, null, 2));
console.log("Asset manifest generated!", assets);
}
function generatePWAManifest() {
generateAssetManifest(); // fetched later in service-worker
const siteTitle = process.env.DUMBDROP_TITLE || process.env.SITE_TITLE || "DumbDrop";
const pwaManifest = {
name: siteTitle,
short_name: siteTitle,
description: "A simple file upload application",
start_url: "/",
display: "standalone",
background_color: "#ffffff",
theme_color: "#000000",
icons: [
{
src: "/assets/icon.png",
type: "image/png",
sizes: "192x192"
},
{
src: "/assets/icon.png",
type: "image/png",
sizes: "512x512"
}
],
orientation: "any"
};
fs.writeFileSync(path.join(PUBLIC_DIR, "manifest.json"), JSON.stringify(pwaManifest, null, 2));
console.log("PWA manifest generated!", pwaManifest);
}
module.exports = { generatePWAManifest };

View File

@@ -8,6 +8,7 @@ const { app, initialize, config } = require('./app');
const logger = require('./utils/logger');
const fs = require('fs');
const { executeCleanup } = require('./utils/cleanup');
const { generatePWAManifest } = require('./scripts/pwa-manifest-generator')
// Track open connections
const connections = new Set();
@@ -40,6 +41,9 @@ async function startServer() {
}
});
// Dynamically generate PWA manifest into public folder
generatePWAManifest();
// Track new connections
server.on('connection', (connection) => {
connections.add(connection);