Adding PWA support.

This commit is contained in:
Johnnybegood90
2026-03-13 23:46:14 +01:00
parent 2172202d25
commit 79a077a85f
10 changed files with 117 additions and 2 deletions
+1 -2
View File
@@ -1,3 +1,2 @@
config.json config.json
.DS_Store .DS_Store
GridTV Beta.sublime-project
Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 578 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

+24
View File
@@ -0,0 +1,24 @@
{
"name": "GridTV",
"short_name": "GridTV",
"description": "Self-hosted IPTV TV guide",
"start_url": "/",
"display": "standalone",
"background_color": "#0a0b0d",
"theme_color": "#0a0b0d",
"orientation": "any",
"icons": [
{
"src": "assets/icon-192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "assets/icon-512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any maskable"
}
]
}
+8
View File
@@ -9,5 +9,13 @@ foreach ($js_modules as $mod) {
} }
?> ?>
</script> </script>
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js').catch(() => {});
});
}
</script>
</body> </body>
</html> </html>
+8
View File
@@ -4,6 +4,14 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GridTV <?= $group_name ?></title> <title>GridTV <?= $group_name ?></title>
<link rel="manifest" href="/manifest.json">
<link rel="icon" href="/favicon.ico" type="image/x-icon">
<link rel="apple-touch-icon" href="/assets/apple-touch-icon.png">
<meta name="theme-color" content="#0a0b0d">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="GridTV">
<link href="https://fonts.googleapis.com/css2?family=Share+Tech+Mono&family=Barlow+Condensed:wght@300;400;600;700&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Share+Tech+Mono&family=Barlow+Condensed:wght@300;400;600;700&display=swap" rel="stylesheet">
<?php <?php
$css_dir = __DIR__ . '/../css/'; $css_dir = __DIR__ . '/../css/';
+76
View File
@@ -0,0 +1,76 @@
const CACHE_NAME = 'gridtv-v1';
// Ressources statiques à mettre en cache immédiatement
const STATIC_ASSETS = [
'/',
'/index.php',
'/manifest.json',
'/assets/icon-192.png',
'/assets/icon-512.png',
'https://fonts.googleapis.com/css2?family=Share+Tech+Mono&family=Barlow+Condensed:wght@300;400;600;700&display=swap',
'https://cdnjs.cloudflare.com/ajax/libs/hls.js/1.4.12/hls.min.js'
];
// Install : mise en cache des assets statiques
self.addEventListener('install', e => {
e.waitUntil(
caches.open(CACHE_NAME)
.then(cache => cache.addAll(STATIC_ASSETS))
.then(() => self.skipWaiting())
);
});
// Activate : purger les anciens caches
self.addEventListener('activate', e => {
e.waitUntil(
caches.keys().then(keys =>
Promise.all(keys.filter(k => k !== CACHE_NAME).map(k => caches.delete(k)))
).then(() => self.clients.claim())
);
});
// Fetch : stratégie selon le type de ressource
self.addEventListener('fetch', e => {
const url = new URL(e.request.url);
// Flux EPG/M3U et API GitHub : network only (pas de cache)
if (
url.pathname.includes('xmltv') ||
url.pathname.includes('.m3u') ||
url.hostname === 'api.github.com' ||
url.pathname.includes('proxy.php')
) {
return;
}
// Assets statiques : cache first
if (
e.request.destination === 'style' ||
e.request.destination === 'script' ||
e.request.destination === 'font' ||
e.request.destination === 'image' ||
url.pathname.endsWith('.json') ||
url.pathname.endsWith('.css') ||
url.pathname.endsWith('.js')
) {
e.respondWith(
caches.match(e.request).then(cached => cached || fetch(e.request).then(res => {
const clone = res.clone();
caches.open(CACHE_NAME).then(cache => cache.put(e.request, clone));
return res;
}))
);
return;
}
// Pages PHP (index.php) : network first, fallback cache
e.respondWith(
fetch(e.request)
.then(res => {
const clone = res.clone();
caches.open(CACHE_NAME).then(cache => cache.put(e.request, clone));
return res;
})
.catch(() => caches.match(e.request))
);
});