diff --git a/.gitignore b/.gitignore index c43fb26..3980cdb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ config.json -.DS_Store -GridTV Beta.sublime-project \ No newline at end of file +.DS_Store \ No newline at end of file diff --git a/assets/apple-touch-icon.png b/assets/apple-touch-icon.png new file mode 100644 index 0000000..e17f1e0 Binary files /dev/null and b/assets/apple-touch-icon.png differ diff --git a/assets/icon-192.png b/assets/icon-192.png new file mode 100644 index 0000000..c2197a2 Binary files /dev/null and b/assets/icon-192.png differ diff --git a/assets/icon-512.png b/assets/icon-512.png new file mode 100644 index 0000000..5dc7085 Binary files /dev/null and b/assets/icon-512.png differ diff --git a/assets/icon.png b/assets/icon.png new file mode 100644 index 0000000..27d7178 Binary files /dev/null and b/assets/icon.png differ diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000..95ff786 Binary files /dev/null and b/favicon.ico differ diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..d1563ec --- /dev/null +++ b/manifest.json @@ -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" + } + ] +} diff --git a/src/tpl/footer.php b/src/tpl/footer.php index 3962be4..f7d5605 100644 --- a/src/tpl/footer.php +++ b/src/tpl/footer.php @@ -9,5 +9,13 @@ foreach ($js_modules as $mod) { } ?> + + diff --git a/src/tpl/head.php b/src/tpl/head.php index 6ca2685..126953c 100644 --- a/src/tpl/head.php +++ b/src/tpl/head.php @@ -4,6 +4,14 @@ GridTV — <?= $group_name ?> + + + + + + + + { + 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)) + ); +});