mirror of
https://github.com/we-promise/sure.git
synced 2026-04-19 03:54:08 +00:00
PWA offline error page + login page cleanup (#327)
* Add friendly PWA offline error page When the PWA fails to connect to the server, users now see a branded offline page with a friendly "technical difficulties" message, the app logo, and a reload button. The page automatically attempts to reload when connectivity is restored. Changes: - Created public/offline.html with branded offline experience - Updated service worker to cache and serve offline page on network failures - Added service worker registration in application.js - Service worker now handles navigation requests with offline fallback * Extract PWA offline logo to separate cached asset Move the inline SVG logo from offline.html to a separate file at public/logo-offline.svg. This makes the logo asset easily identifiable and maintainable, as it may diverge from other logo versions in the future. Changes: - Created public/logo-offline.svg with the offline page logo - Updated service worker to cache logo as part of OFFLINE_ASSETS array - Updated fetch handler to serve cached offline assets - Updated offline.html to reference logo file instead of inline SVG * Update offline message for better readability Signed-off-by: Juan José Mata <juanjo.mata@gmail.com> * CodeRabbit comments * Keep 40x and 50x flowing * Dark mode * Logo tweaks * Login/sign up cleanup --------- Signed-off-by: Juan José Mata <juanjo.mata@gmail.com> Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -4,12 +4,9 @@
|
||||
<div class="grow flex flex-col justify-center">
|
||||
<div class="sm:mx-auto sm:w-full sm:max-w-md">
|
||||
<div class="flex justify-center mt-2 md:mb-6">
|
||||
<%= image_tag "logo-color.png", class: "w-16 mb-6" %>
|
||||
<%= image_tag "logomark.svg", class: "w-16 mb-6" %>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<h2 class="text-3xl font-medium text-primary text-center">
|
||||
<%= content_for?(:header_title) ? yield(:header_title).html_safe : t(".your_account") %>
|
||||
</h2>
|
||||
<% if (controller_name == "sessions" && action_name == "new") || (controller_name == "registrations" && action_name == "new") %>
|
||||
<div class="space-y-3 md:hidden w-full my-4">
|
||||
<div class="bg-surface-inset rounded-lg p-1 flex">
|
||||
|
||||
@@ -1,10 +1,69 @@
|
||||
const CACHE_VERSION = 'v1';
|
||||
const OFFLINE_ASSETS = [
|
||||
'/offline.html',
|
||||
'/logo-offline.svg'
|
||||
];
|
||||
|
||||
// Install event - cache the offline page and assets
|
||||
self.addEventListener('install', (event) => {
|
||||
event.waitUntil(
|
||||
caches.open(CACHE_VERSION).then((cache) => {
|
||||
return cache.addAll(OFFLINE_ASSETS);
|
||||
})
|
||||
);
|
||||
// Activate immediately
|
||||
self.skipWaiting();
|
||||
});
|
||||
|
||||
// Activate event - clean up old caches
|
||||
self.addEventListener('activate', (event) => {
|
||||
event.waitUntil(
|
||||
caches.keys().then((cacheNames) => {
|
||||
return Promise.all(
|
||||
cacheNames.map((cacheName) => {
|
||||
if (cacheName !== CACHE_VERSION) {
|
||||
return caches.delete(cacheName);
|
||||
}
|
||||
})
|
||||
);
|
||||
}).then(() => {
|
||||
// Take control of all pages immediately
|
||||
return self.clients.claim();
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
// Fetch event - serve offline page when network fails
|
||||
self.addEventListener('fetch', (event) => {
|
||||
// Handle navigation requests (page loads)
|
||||
if (event.request.mode === 'navigate') {
|
||||
event.respondWith(
|
||||
fetch(event.request).catch((error) => {
|
||||
// Only show offline page for network errors
|
||||
if (error.name === 'TypeError' || !navigator.onLine) {
|
||||
return caches.match('/offline.html');
|
||||
}
|
||||
throw error;
|
||||
})
|
||||
);
|
||||
}
|
||||
// Handle offline assets (logo, etc.)
|
||||
else if (OFFLINE_ASSETS.some(asset => new URL(event.request.url).pathname === asset)) {
|
||||
event.respondWith(
|
||||
caches.match(event.request).then((response) => {
|
||||
return response || fetch(event.request);
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Add a service worker for processing Web Push notifications:
|
||||
//
|
||||
// self.addEventListener("push", async (event) => {
|
||||
// const { title, options } = await event.data.json()
|
||||
// event.waitUntil(self.registration.showNotification(title, options))
|
||||
// })
|
||||
//
|
||||
//
|
||||
// self.addEventListener("notificationclick", function(event) {
|
||||
// event.notification.close()
|
||||
// event.waitUntil(
|
||||
@@ -12,12 +71,12 @@
|
||||
// for (let i = 0; i < clientList.length; i++) {
|
||||
// let client = clientList[i]
|
||||
// let clientPath = (new URL(client.url)).pathname
|
||||
//
|
||||
//
|
||||
// if (clientPath == event.notification.data.path && "focus" in client) {
|
||||
// return client.focus()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// if (clients.openWindow) {
|
||||
// return clients.openWindow(event.notification.data.path)
|
||||
// }
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
<%
|
||||
header_title t(".title")
|
||||
%>
|
||||
|
||||
<% if @prefill_demo_credentials %>
|
||||
<div class="mb-4 rounded-lg border bg-blue-50 text-blue-700 border-blue-200 theme-dark:bg-blue-900/20 theme-dark:text-blue-400 theme-dark:border-blue-800 p-4" role="status" aria-live="polite">
|
||||
<div class="flex items-start gap-3">
|
||||
|
||||
Reference in New Issue
Block a user