Add pwa support

This commit is contained in:
2026-02-28 06:32:39 -06:00
parent 02b10131f9
commit 28b7138547
25 changed files with 870 additions and 48 deletions

View File

@@ -0,0 +1,4 @@
<div>
<h1>Cannot connect to the TYTD2025 server.</h1>
Refresh page to add to offline queue
</div>

View File

@@ -0,0 +1,106 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TYTD2025 is Offline</title>
<link rel="stylesheet" href="/beer.min.css">
<link rel="stylesheet" href="/theme.css">
<script src="/offline.js" defer></script>
<script type="module" src="/beer.min.js" defer></script>
</head>
<body>
<main>
<div class="row">
<div class="max"></div>
<div class="min">
<img src="tytd-128.png" alt="tytd-logo">
</div>
<div class="max"></div>
</div>
<div class="row">
<div class="max"></div>
<div class="min">
<h3>Cannot connect to the TYTD2025 server.</h3>
</div>
<div class="max"></div>
</div>
<div class="row">
<div class="max"></div>
<div class="min">
<form>
<div class="field label border small fill">
<input id="url" type="text">
<label>Url or id</label>
</div>
<div class="row">
<div class="max">
<div class="field label suffix border fill">
<select id="res">
<option value="NoDownload">Don't Download</option>
<option value="LowVideo" selected="">Low (muxed by YouTube)</option>
<option value="VideoOnly">Highest video (no audio)</option>
<option value="AudioOnly">Highest audio (no video)</option>
<option value="MP3">Convert to MP3</option>
<option value="FLAC">Convert to FLAC</option>
<option value="MP4">Convert to MP4</option>
<option value="MKV">Mux to MKV (no transcoding)</option>
<option value="DontConvert">Don't convert or Mux</option>
</select>
<label>Resolution</label>
<i>arrow_drop_down</i>
</div>
</div>
<div class="min">
<button id="btn">
<i>add</i>
Add when online
</button>
</div>
</div>
</form>
</div>
<div class="max"></div>
</div>
</main>
<script>
btn.onclick = (evt)=>{
evt.preventDefault();
addOffline(url.value, res.value);
};
</script>
</body>
</html>

View File

@@ -0,0 +1,54 @@
function addOffline(url,res)
{
var videos = JSON.parse(localStorage.getItem("videos") ?? "[]");
videos.push({
url: url,
res: res
});
localStorage.setItem('videos',JSON.stringify(videos));
}
async function syncOffline()
{
const json = localStorage.getItem("videos") ?? "[]";
if(json !== "[]")
{
const resp = await fetch('/api/v1/add',{
body: json,
headers: {
'Content-Type': 'application/json'
},
method: "POST"
});
if(resp.ok)
{
localStorage.removeItem('videos');
}
}
}
if(navigator.online)
{
syncOffline();
}
window.addEventListener('online',()=>{
syncOffline();
});
async function getPersonalTempLink()
{
const searchParams = new URLSearchParams(window.location.search);
const ent = searchParams.get("name");
if(ent)
{
const resp=await fetch(`./api/v1/personal_tmp_link?name=${encodeURIComponent(ent)}`);
if(resp.ok)
{
const text = await resp.text();
the_playlist_url.innerText = text;
the_playlist_url.href = text;
ui("#dialog");
}
}
}

View File

@@ -0,0 +1,42 @@
const assets = ["<@ASSETS@>"];
const staticCacheName = "tytd-static-<@BUILD_TIME@>";
self.addEventListener('install',evt => {
evt.waitUntil(
caches.open(staticCacheName).then(cache =>{
cache.addAll(assets);
})
);
});
self.addEventListener('activate',(evt)=>{
evt.waitUntil(
caches.keys().then(keys => {
return Promise.all(keys.filter(key => key !== staticCacheName).map(key => caches.delete(key)));
})
);
});
self.addEventListener('fetch', evt => {
const uri = new URL(evt.request.url);
evt.respondWith(
caches.match(evt.request).then(cacheRes=>{
return cacheRes || fetch(evt.request);
}).catch(()=>{
if(uri.pathname === '/queue-size')
{
return new Response('<span hx-trigger="every 5000ms" hx-target="this" hx-push-url="false" hx-indicator="none" hx-get="./queue-size" hx-swap="outerHTML" class="badge">?</span>',{
headers: { 'Content-Type': 'text/html' }
});
}
if(uri.pathname === "/progress")
{
return caches.match("/offline-progress.html");
}
return caches.match('/offline.html');
})
);
});

View File

@@ -0,0 +1,73 @@
{
"short_name": "TYTD2025",
"name": "Tesses YouTubeDownloader 2025",
"start_url": "/",
"display": "standalone",
"theme_color": "#ffb2be",
"background_color": "#241e1f",
"description": "A web based YouTube archiver to preserve videos that might be removed",
"icons": [
{
"src": "/tytd.svg",
"sizes": "192x192 256x256 384x384 512x512",
"type": "image/svg+xml",
"purpose": "any"
},
{
"src": "/tytd-128.png",
"sizes": "128x128",
"type": "image/png"
},
{
"src": "/tytd-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/tytd-256.png",
"sizes": "256x256",
"type": "image/png"
},
{
"src": "/tytd-384.png",
"sizes": "384x384",
"type": "image/png"
},
{
"src": "/tytd-512.png",
"sizes": "512x512",
"type": "image/png"
},
{
"src": "/tytd-1024.png",
"sizes": "1024x1024",
"type": "image/png"
}
],
"shortcuts": [
{
"name": "Open Downloads",
"short_name": "Downloads",
"description": "Open Downloads page",
"url": "/downloads"
},
{
"name": "Open Installed Plugins",
"short_name": "Installed plugins",
"description": "Open the installed plugins page",
"url": "/plugins"
},
{
"name": "Open Download Plugins",
"short_name": "Download plugins",
"description": "Open the download plugins page",
"url": "/plugins-download"
},
{
"name": "Open Settings",
"short_name": "Settings",
"description": "Open settings page",
"url": "/settings"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB