diff --git a/client/index.html b/client/index.html
index 11223db..c23688c 100644
--- a/client/index.html
+++ b/client/index.html
@@ -2,7 +2,7 @@
-
+
go4.video – Top-Inhalte von Folx TV
@@ -29,7 +29,23 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/public/manifest.json b/client/public/manifest.json
index b44927b..c7b172b 100644
--- a/client/public/manifest.json
+++ b/client/public/manifest.json
@@ -5,18 +5,78 @@
"theme_color": "#6366f1",
"background_color": "#2D1B69",
"display": "standalone",
+ "orientation": "portrait-primary",
"start_url": "/",
+ "scope": "/",
+ "lang": "en",
+ "dir": "ltr",
+ "categories": ["entertainment", "multimedia"],
+ "prefer_related_applications": false,
"icons": [
+ {
+ "src": "/api/favicon?size=57",
+ "sizes": "57x57",
+ "type": "image/png",
+ "purpose": "any"
+ },
+ {
+ "src": "/api/favicon?size=60",
+ "sizes": "60x60",
+ "type": "image/png",
+ "purpose": "any"
+ },
+ {
+ "src": "/api/favicon?size=72",
+ "sizes": "72x72",
+ "type": "image/png",
+ "purpose": "any"
+ },
+ {
+ "src": "/api/favicon?size=76",
+ "sizes": "76x76",
+ "type": "image/png",
+ "purpose": "any"
+ },
+ {
+ "src": "/api/favicon?size=114",
+ "sizes": "114x114",
+ "type": "image/png",
+ "purpose": "any"
+ },
+ {
+ "src": "/api/favicon?size=120",
+ "sizes": "120x120",
+ "type": "image/png",
+ "purpose": "any"
+ },
+ {
+ "src": "/api/favicon?size=144",
+ "sizes": "144x144",
+ "type": "image/png",
+ "purpose": "any"
+ },
+ {
+ "src": "/api/favicon?size=152",
+ "sizes": "152x152",
+ "type": "image/png",
+ "purpose": "any"
+ },
+ {
+ "src": "/api/favicon?size=180",
+ "sizes": "180x180",
+ "type": "image/png",
+ "purpose": "any"
+ },
{
"src": "/api/favicon?size=192",
"sizes": "192x192",
- "type": "image/svg+xml",
+ "type": "image/png",
"purpose": "any maskable"
},
{
"src": "/api/favicon?size=512",
"sizes": "512x512",
- "type": "image/svg+xml",
+ "type": "image/png",
"purpose": "any maskable"
}
]
diff --git a/client/public/sw.js b/client/public/sw.js
new file mode 100644
index 0000000..31b8148
--- /dev/null
+++ b/client/public/sw.js
@@ -0,0 +1,67 @@
+// Service Worker za go4.video PWA
+const CACHE_NAME = 'go4-video-v1';
+const urlsToCache = [
+ '/',
+ '/manifest.json',
+ '/api/favicon',
+ '/api/favicon?size=192',
+ '/api/favicon?size=512'
+];
+
+// Instalacija service worker-ja
+self.addEventListener('install', (event) => {
+ event.waitUntil(
+ caches.open(CACHE_NAME)
+ .then((cache) => {
+ console.log('PWA cache opened');
+ return cache.addAll(urlsToCache);
+ })
+ );
+});
+
+// Aktivacija service worker-ja
+self.addEventListener('activate', (event) => {
+ event.waitUntil(
+ caches.keys().then((cacheNames) => {
+ return Promise.all(
+ cacheNames.map((cacheName) => {
+ if (cacheName !== CACHE_NAME) {
+ console.log('Deleting old cache:', cacheName);
+ return caches.delete(cacheName);
+ }
+ })
+ );
+ })
+ );
+});
+
+// Prestrezanje omrežnih zahtev
+self.addEventListener('fetch', (event) => {
+ event.respondWith(
+ caches.match(event.request)
+ .then((response) => {
+ // Vrni iz cache-a, če obstaja
+ if (response) {
+ return response;
+ }
+
+ // Sicer povleči iz omrežja
+ return fetch(event.request).then((response) => {
+ // Preveri ali je veljaven odgovor
+ if (!response || response.status !== 200 || response.type !== 'basic') {
+ return response;
+ }
+
+ // Kloniraj odgovor
+ const responseToCache = response.clone();
+
+ caches.open(CACHE_NAME)
+ .then((cache) => {
+ cache.put(event.request, responseToCache);
+ });
+
+ return response;
+ });
+ })
+ );
+});
\ No newline at end of file
diff --git a/client/src/index.css b/client/src/index.css
index f0c386a..d5fed7f 100644
--- a/client/src/index.css
+++ b/client/src/index.css
@@ -65,6 +65,11 @@
background: linear-gradient(135deg, hsl(250, 50%, 15%) 0%, hsl(240, 30%, 25%) 50%, hsl(260, 40%, 20%) 100%);
color: hsl(210, 40%, 98%);
min-height: 100vh;
+ /* iOS PWA optimizacije */
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -webkit-tap-highlight-color: transparent;
+ overscroll-behavior: none;
}
}
@@ -365,6 +370,44 @@ input[data-testid*="search"]::placeholder {
}
}
+/* iOS PWA safe area optimizacije */
+@supports (padding: max(0px)) {
+ .has-fixed-header {
+ padding-top: max(80px, env(safe-area-inset-top));
+ }
+}
+
+/* PWA full screen optimizacije za iOS */
+@media (display-mode: standalone) {
+ body {
+ /* Prepreči povlečenje za osvežitev na iOS */
+ overscroll-behavior-y: none;
+ /* Prilagodi safe area */
+ padding-top: env(safe-area-inset-top);
+ padding-bottom: env(safe-area-inset-bottom);
+ padding-left: env(safe-area-inset-left);
+ padding-right: env(safe-area-inset-right);
+ }
+
+ .header-sticky {
+ top: env(safe-area-inset-top) !important;
+ }
+}
+
+/* Dodatne mobile optimizacije */
+@media (max-width: 768px) {
+ /* Prepreči zoom pri fokusiranju input polj */
+ input, select, textarea {
+ font-size: 16px !important;
+ }
+
+ /* Optimiziraj touch targets za iOS */
+ button, a, [role="button"] {
+ min-height: 44px;
+ min-width: 44px;
+ }
+}
+
/* Test grid overlay */
body.show-grid::after {
content: '';
diff --git a/client/src/main.tsx b/client/src/main.tsx
index 696e0d2..0945fc0 100644
--- a/client/src/main.tsx
+++ b/client/src/main.tsx
@@ -2,4 +2,17 @@ import { createRoot } from "react-dom/client";
import App from "./App";
import "./index.css";
+// Registracija Service Worker-ja za PWA funkcionalnost
+if ('serviceWorker' in navigator) {
+ window.addEventListener('load', () => {
+ navigator.serviceWorker.register('/sw.js')
+ .then((registration) => {
+ console.log('SW registered: ', registration);
+ })
+ .catch((registrationError) => {
+ console.log('SW registration failed: ', registrationError);
+ });
+ });
+}
+
createRoot(document.getElementById("root")!).render();