diff --git a/public/icon-192.png b/public/icon-192.png new file mode 100644 index 0000000..62fe69f Binary files /dev/null and b/public/icon-192.png differ diff --git a/public/icon-512.png b/public/icon-512.png new file mode 100644 index 0000000..08e1608 Binary files /dev/null and b/public/icon-512.png differ diff --git a/public/index.html b/public/index.html index 1f46447..bb05e78 100644 --- a/public/index.html +++ b/public/index.html @@ -3,6 +3,15 @@ + + + + + + + + + Camila AI @@ -202,5 +211,19 @@ + + diff --git a/public/manifest.json b/public/manifest.json new file mode 100644 index 0000000..5686b74 --- /dev/null +++ b/public/manifest.json @@ -0,0 +1,26 @@ +{ + "name": "Camila AI", + "short_name": "Camila", + "description": "Assistente virtual da Camila", + "start_url": "/", + "display": "standalone", + "background_color": "#0a0a0a", + "theme_color": "#10a37f", + "orientation": "portrait-primary", + "icons": [ + { + "src": "/icon-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "/icon-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "any maskable" + } + ], + "categories": ["education", "productivity"], + "lang": "pt-BR" +} \ No newline at end of file diff --git a/public/sw.js b/public/sw.js new file mode 100644 index 0000000..365abd5 --- /dev/null +++ b/public/sw.js @@ -0,0 +1,68 @@ +const CACHE_NAME = 'camila-ai-v1'; +const urlsToCache = [ + '/', + '/index.html', + '/style.css', + '/app.js', + '/manifest.json', + '/icon-192.png', + '/icon-512.png' +]; + +// Install event - cache assets +self.addEventListener('install', (event) => { + event.waitUntil( + caches.open(CACHE_NAME) + .then((cache) => { + console.log('Camila AI: Cache opened'); + return cache.addAll(urlsToCache); + }) + .then(() => self.skipWaiting()) + ); +}); + +// Activate event - clean old caches +self.addEventListener('activate', (event) => { + event.waitUntil( + caches.keys().then((cacheNames) => { + return Promise.all( + cacheNames.map((cacheName) => { + if (cacheName !== CACHE_NAME) { + console.log('Camila AI: Deleting old cache:', cacheName); + return caches.delete(cacheName); + } + }) + ); + }).then(() => self.clients.claim()) + ); +}); + +// Fetch event - serve from cache, fallback to network +self.addEventListener('fetch', (event) => { + event.respondWith( + caches.match(event.request) + .then((response) => { + if (response) { + return response; + } + return fetch(event.request).then((response) => { + // Don't cache non-successful responses or non-GET requests + if (!response || response.status !== 200 || event.request.method !== 'GET') { + return response; + } + // Clone the response + const responseToCache = response.clone(); + caches.open(CACHE_NAME).then((cache) => { + cache.put(event.request, responseToCache); + }); + return response; + }); + }) + .catch(() => { + // If both cache and network fail, show offline page for HTML requests + if (event.request.headers.get('accept').includes('text/html')) { + return caches.match('/'); + } + }) + ); +}); \ No newline at end of file