1const CACHE_NAME = 'mubtakirun-v1'; 2const urlsToCache = [ 3 '/', 4 '/index.html', 5 '/manifest.json', 6 '/src/main.tsx', 7 '/src/index.css' 8]; 9 10// ØªØ«Ø¨ÙØª Service Worker 11self.addEventListener('install', (event) => { 12 event.waitUntil( 13 caches.open(CACHE_NAME).then((cache) => { 14 return cache.addAll(urlsToCache); 15 }) 16 ); 17 self.skipWaiting(); 18}); 19 20// ØªÙØ¹ÙÙ Service Worker 21self.addEventListener('activate', (event) => { 22 event.waitUntil( 23 caches.keys().then((cacheNames) => { 24 return Promise.all( 25 cacheNames.map((cacheName) => { 26 if (cacheName !== CACHE_NAME) { 27 return caches.delete(cacheName); 28 } 29 }) 30 ); 31 }) 32 ); 33 self.clients.claim(); 34}); 35 36// Ø§Ø³ØªØ±Ø§ØªÙØ¬ÙØ© اÙÙ Cache: Network First 37self.addEventListener('fetch', (event) => { 38 // ØªØ®Ø·Ù Ø§ÙØ·Ùبات ØºÙØ± GET 39 if (event.request.method !== 'GET') { 40 return; 41 } 42 43 // ØªØ®Ø·Ù Ø§ÙØ·Ùبات Ø¥ÙÙ API 44 if (event.request.url.includes('/api/')) { 45 event.respondWith( 46 fetch(event.request) 47 .then((response) => { 48 // ØÙظ Ø§ÙØ§Ø³ØªØ¬Ø§Ø¨Ø© Ù٠اÙÙ Cache 49 const responseClone = response.clone(); 50 caches.open(CACHE_NAME).then((cache) => { 51 cache.put(event.request, responseClone); 52 }); 53 return response; 54 }) 55 .catch(() => { 56 // ÙÙ ØØ§ÙØ© Ø¹Ø¯Ù ÙØ¬Ùد Ø¥ÙØªØ±ÙØªØ Ø§Ø³ØªØ®Ø¯Ù Ø§ÙÙ Cache 57 return caches.match(event.request); 58 }) 59 ); 60 return; 61 } 62 63 // Ø§Ø³ØªØ±Ø§ØªÙØ¬ÙØ© Cache First ÙÙÙ ÙÙØ§Øª Ø§ÙØ«Ø§Ø¨ØªØ© 64 event.respondWith( 65 caches.match(event.request).then((response) => { 66 if (response) { 67 return response; 68 } 69 70 return fetch(event.request).then((response) => { 71 // تخزÙÙ Ø§ÙØ§Ø³ØªØ¬Ø§Ø¨Ø© Ø§ÙØ¬Ø¯Ùدة 72 const responseClone = response.clone(); 73 caches.open(CACHE_NAME).then((cache) => { 74 cache.put(event.request, responseClone); 75 }); 76 return response; 77 }); 78 }) 79 ); 80}); 81 82// Ù Ø¹Ø§ÙØ¬Ø© Ø§ÙØ¥Ø´Ø¹Ø§Ø±Ø§Øª 83self.addEventListener('push', (event) => { 84 const data = event.data ? event.data.json() : {}; 85 const options = { 86 body: data.body || 'إشعار Ø¬Ø¯ÙØ¯ Ù Ù Ù Ø¨ØªÙØ±ÙÙ', 87 icon: '/manifest.json', 88 badge: '/manifest.json', 89 tag: data.tag || 'notification', 90 requireInteraction: data.requireInteraction || false 91 }; 92 93 event.waitUntil( 94 self.registration.showNotification(data.title || 'Ù Ø¨ØªÙØ±ÙÙ', options) 95 ); 96}); 97 98// Ù Ø¹Ø§ÙØ¬Ø© اÙÙÙØ± عÙÙ Ø§ÙØ¥Ø´Ø¹Ø§Ø± 99self.addEventListener('notificationclick', (event) => { 100 event.notification.close(); 101 102 event.waitUntil( 103 clients.matchAll({ type: 'window' }).then((clientList) => { 104 // Ø§ÙØ¨ØØ« Ø¹Ù ÙØ§Ùذة Ù ÙØªÙØØ© باÙÙØ¹Ù 105 for (let i = 0; i < clientList.length; i++) { 106 const client = clientList[i]; 107 if (client.url === '/' && 'focus' in client) { 108 return client.focus(); 109 } 110 } 111 // ÙØªØ ÙØ§Ùذة Ø¬Ø¯ÙØ¯Ø© إذا ÙÙ ØªÙØ¬Ø¯ 112 if (clients.openWindow) { 113 return clients.openWindow(event.notification.data.url || '/'); 114 } 115 }) 116 ); 117});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.