diff --git a/fry.png b/fry.png new file mode 100644 index 0000000..c6166fd Binary files /dev/null and b/fry.png differ diff --git a/index.html b/index.html index f87529c..56e34b3 100644 --- a/index.html +++ b/index.html @@ -3,7 +3,9 @@ - Browser Notepad + noted. + + @@ -228,6 +230,19 @@ notepad.addEventListener('click', (e) => { e.stopPropagation(); }); + + // Register service worker for PWA functionality + if ('serviceWorker' in navigator) { + window.addEventListener('load', () => { + navigator.serviceWorker.register('service-worker.js') + .then(registration => { + console.log('ServiceWorker registration successful with scope: ', registration.scope); + }) + .catch(err => { + console.log('ServiceWorker registration failed: ', err); + }); + }); + } \ No newline at end of file diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..d1a8fed --- /dev/null +++ b/manifest.json @@ -0,0 +1,24 @@ +{ + "name": "Browser Notepad", + "short_name": "Notepad", + "description": "A simple browser-based notepad application", + "start_url": "./index.html", + "display": "standalone", + "background_color": "#ffffff", + "theme_color": "#f1f1f1", + "orientation": "portrait-primary", + "icons": [ + { + "src": "https://radical.omar-c29.workers.dev/memes/fry.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "https://radical.omar-c29.workers.dev/memes/fry.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "any maskable" + } + ] +} \ No newline at end of file diff --git a/noted.gif b/noted.gif new file mode 100644 index 0000000..5851b53 Binary files /dev/null and b/noted.gif differ diff --git a/service-worker.js b/service-worker.js new file mode 100644 index 0000000..bddc85c --- /dev/null +++ b/service-worker.js @@ -0,0 +1,78 @@ +const CACHE_NAME = 'browser-notepad-v1'; +const urlsToCache = [ + './', + './index.html', + './manifest.json', + 'https://radical.omar-c29.workers.dev/memes/fry.png', + 'https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;700&display=swap', + 'https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap', + 'https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;700&display=swap', + 'https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap' +]; + +// Install event - cache assets +self.addEventListener('install', event => { + event.waitUntil( + caches.open(CACHE_NAME) + .then(cache => { + console.log('Opened cache'); + return cache.addAll(urlsToCache); + }) + ); +}); + +// Activate event - clean up old caches +self.addEventListener('activate', event => { + const cacheWhitelist = [CACHE_NAME]; + event.waitUntil( + caches.keys().then(cacheNames => { + return Promise.all( + cacheNames.map(cacheName => { + if (cacheWhitelist.indexOf(cacheName) === -1) { + return caches.delete(cacheName); + } + }) + ); + }) + ); +}); + +// Fetch event - serve cached content when offline +self.addEventListener('fetch', event => { + event.respondWith( + caches.match(event.request) + .then(response => { + // Cache hit - return response + if (response) { + return response; + } + + // Clone the request + const fetchRequest = event.request.clone(); + + return fetch(fetchRequest).then( + response => { + // Check if we received a valid response + if(!response || response.status !== 200 || response.type !== 'basic') { + return response; + } + + // Clone the response + const responseToCache = response.clone(); + + caches.open(CACHE_NAME) + .then(cache => { + cache.put(event.request, responseToCache); + }); + + return response; + } + ).catch(() => { + // If fetch fails (offline), try to return the cached HTML + if (event.request.mode === 'navigate') { + return caches.match('./index.html'); + } + }); + }) + ); +}); \ No newline at end of file