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:
Juan José Mata
2025-11-16 21:12:48 +01:00
committed by GitHub
parent 066fdf4ed5
commit d47aa2fe90
14 changed files with 208 additions and 21 deletions

View File

@@ -1,6 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="300" height="300" viewBox="0 0 160 145" fill="none">
<path d="M116.51 119.37C120.062 119.37 122.809 118.751 124.752 117.513C126.696 116.274 127.701 114.58 127.768 112.429L158.828 122.303C157.621 126.409 155.042 130.156 151.088 133.545C147.201 136.869 142.276 139.509 136.312 141.464C130.348 143.419 123.68 144.397 116.309 144.397C110.01 144.397 104.113 143.712 98.6179 142.344C93.19 140.975 88.3986 138.922 84.2439 136.185C80.1562 133.382 76.9397 129.896 74.5943 125.725C72.2489 121.553 71.0762 116.698 71.0762 111.158C71.0762 105.618 72.2489 100.763 74.5943 96.5919C76.9397 92.4208 80.1562 88.9666 84.2439 86.2293C88.3986 83.4268 93.2234 81.3412 98.7184 79.9726C104.213 78.6039 110.077 77.9196 116.309 77.9196C122.675 77.9196 128.505 78.6039 133.799 79.9726C139.16 81.3412 143.75 83.4594 147.57 86.327C151.456 89.1295 154.438 92.714 156.516 97.0807C158.66 101.382 159.732 106.498 159.732 112.429H104.95C104.95 112.429 104.917 112.429 104.85 112.429C104.85 112.429 104.85 112.462 104.85 112.527C104.85 113.504 105.118 114.417 105.654 115.264C106.19 116.111 106.927 116.861 107.865 117.513C108.871 118.099 110.077 118.555 111.484 118.881C112.958 119.207 114.634 119.37 116.51 119.37ZM116.309 102.653C113.025 102.653 110.311 103.24 108.167 104.413C106.023 105.521 104.95 107.117 104.95 109.203C104.95 109.268 104.95 109.333 104.95 109.399C105.017 109.399 105.051 109.399 105.051 109.399H127.466C127.533 109.399 127.567 109.399 127.567 109.399C127.567 109.333 127.567 109.268 127.567 109.203C127.567 108.16 127.265 107.248 126.662 106.466C126.126 105.618 125.355 104.934 124.35 104.413C123.345 103.826 122.139 103.403 120.732 103.142C119.391 102.816 117.917 102.653 116.309 102.653Z" fill="#62a446"/>
<path d="M37.5666 81.9011C37.5666 85.8115 37.5666 89.7546 37.5666 93.7301C37.5666 97.6406 37.5666 101.584 37.5666 105.559C37.5666 109.47 37.5666 113.413 37.5666 117.388C37.5666 121.559 37.5666 125.73 37.5666 129.902C37.5666 134.073 37.5666 138.276 37.5666 142.513H2.74774C2.74774 136.06 2.74774 129.608 2.74774 123.156C2.74774 116.704 2.74774 110.252 2.74774 103.799C2.74774 100.15 2.74774 96.5 2.74774 92.8503C2.74774 89.2006 2.74774 85.5508 2.74774 81.9011H37.5666ZM37.466 119.246L42.9001 92.9481C43.5039 90.1456 44.678 87.8319 46.4222 86.0071C48.2336 84.117 50.3469 82.6832 52.7621 81.7056C55.1773 80.728 57.6596 80.1414 60.2089 79.9459C62.7583 79.6852 65.1063 79.783 67.2532 80.2392C69.4 80.6302 71.1108 81.3146 72.3854 82.2922L64.7374 118.659C62.7918 117.095 60.4102 116.02 57.5925 115.433C54.8418 114.846 52.0577 114.651 49.24 114.846C46.4223 114.977 43.94 115.433 41.7932 116.215C39.6463 116.997 38.2039 118.007 37.466 119.246Z" fill="#61a446"/>
<path d="M155.301 0.291725C155.301 4.65836 155.301 20.0576 155.301 24.4894C155.301 28.9212 155.301 33.353 155.301 37.7848C155.301 41.5649 155.301 45.3776 155.301 49.2228C155.301 53.0029 155.301 56.783 155.301 60.563C155.301 64.3431 155.301 68.1232 155.301 71.9033H121.476C121.476 69.166 121.476 66.3961 121.476 63.5936C121.476 60.7912 121.476 57.9887 121.476 55.1862C121.476 52.3186 121.476 49.5487 121.476 46.8766C121.476 40.8154 121.476 34.8846 121.476 29.0841C121.476 23.2185 121.476 6.28771 121.476 0.291725H155.301ZM111.113 5.29173C111.113 8.74593 111.113 18.2327 111.113 21.7521C111.113 25.2063 111.113 28.6605 111.113 32.1147C111.113 35.5689 111.113 39.0557 111.113 42.5751C111.113 44.0089 111.341 45.182 111.798 46.0945C112.319 46.9417 112.971 47.5609 113.753 47.9519C114.6 48.2778 115.48 48.4407 116.392 48.4407C117.305 48.4407 118.217 48.2778 119.13 47.9519C120.107 47.6261 120.889 47.235 121.476 46.7788L113.655 70.9257C111.83 71.8381 109.582 72.5876 106.909 73.1742C104.303 73.7607 101.565 74.054 98.6976 74.054C96.0906 74.054 93.5163 73.7281 90.9745 73.0764C88.4327 72.4898 86.1191 71.4796 84.0335 70.0458C82.0131 68.612 80.3838 66.722 79.1455 64.3757C77.9072 62.0295 77.288 59.0966 77.288 55.5773C77.288 50.8848 77.288 46.1922 77.288 41.4997C77.288 36.8072 77.288 32.1147 77.288 27.4222C77.288 24.7501 77.288 22.078 77.288 19.4058C77.288 16.6686 77.288 7.96384 77.288 5.29173H111.113Z" fill="black"/>
<path d="M0.698853 30.6484C0.698853 26.9335 1.74163 23.7074 3.82719 20.9701C5.97792 18.2328 8.87815 15.9517 12.5279 14.1269C16.1776 12.2368 20.3161 10.8356 24.9435 9.92315C29.5708 9.01072 34.3937 8.5545 39.412 8.5545C45.6035 8.5545 51.3388 9.10848 56.6179 10.2164C61.9621 11.3244 66.785 12.7908 71.0864 14.6157V37.2961C69.2616 35.9275 66.8502 34.7543 63.8522 33.7767C60.9194 32.7991 57.791 32.0496 54.4672 31.5282C51.2085 31.0068 48.1127 30.7461 45.1799 30.7461C43.2247 30.7461 41.4324 30.8765 39.8031 31.1372C38.2389 31.3327 36.968 31.6586 35.9904 32.1148C35.078 32.571 34.6218 33.1576 34.6218 33.8745C34.6218 34.2655 34.7521 34.5588 35.0128 34.7543C35.3387 34.9499 35.7949 35.0802 36.3815 35.1454C36.968 35.2105 37.7175 35.2431 38.63 35.2431C40.1289 35.2431 41.465 35.2431 42.6381 35.2431C43.8113 35.2431 45.1147 35.2431 46.5486 35.2431C49.8072 35.2431 53.0659 35.4712 56.3246 35.9275C59.6485 36.3185 62.6465 37.1332 65.3186 38.3715C68.0559 39.6098 70.2392 41.402 71.8685 43.7483C73.4979 46.0294 74.3125 49.06 74.3125 52.84C74.3125 56.8156 73.2046 60.2047 70.9887 63.0071C68.838 65.7444 65.8726 67.9929 62.0925 69.7526C58.3776 71.4471 54.1739 72.6854 49.4814 73.4675C44.854 74.2496 40.0312 74.6406 35.0128 74.6406C29.082 74.6406 23.2164 74.0867 17.4159 72.9787C11.6806 71.8708 6.76001 70.2414 2.65406 68.0907V44.2371C4.28341 45.9968 6.59707 47.4632 9.59506 48.6363C12.6582 49.7443 15.9495 50.5915 19.4689 51.1781C23.0534 51.6995 26.4099 51.9602 29.5382 51.9602C31.5586 51.9602 33.3835 51.8624 35.0128 51.6669C36.6421 51.4062 37.913 51.0478 38.8255 50.5915C39.8031 50.0701 40.2919 49.4184 40.2919 48.6363C40.2919 48.3105 40.1941 48.0823 39.9986 47.952C39.8031 47.8217 39.4772 47.7239 39.021 47.6587C38.63 47.5936 38.076 47.561 37.3591 47.561C36.3815 47.561 35.3713 47.561 34.3285 47.561C33.2857 47.561 32.3407 47.561 31.4934 47.561C29.2123 47.561 26.6706 47.4958 23.8681 47.3654C21.1308 47.1699 18.3935 46.8115 15.6562 46.2901C12.9189 45.7035 10.4097 44.8237 8.12865 43.6505C5.91275 42.4122 4.12047 40.7503 2.75182 38.6648C1.38318 36.514 0.698853 33.8419 0.698853 30.6484Z" fill="black"/>
</svg>
<path d="M155.301 0.291725C155.301 4.65836 155.301 20.0576 155.301 24.4894C155.301 28.9212 155.301 33.353 155.301 37.7848C155.301 41.5649 155.301 45.3776 155.301 49.2228C155.301 53.0029 155.301 56.783 155.301 60.563C155.301 64.3431 155.301 68.1232 155.301 71.9033H121.476C121.476 69.166 121.476 66.3961 121.476 63.5936C121.476 60.7912 121.476 57.9887 121.476 55.1862C121.476 52.3186 121.476 49.5487 121.476 46.8766C121.476 40.8154 121.476 34.8846 121.476 29.0841C121.476 23.2185 121.476 6.28771 121.476 0.291725H155.301ZM111.113 5.29173C111.113 8.74593 111.113 18.2327 111.113 21.7521C111.113 25.2063 111.113 28.6605 111.113 32.1147C111.113 35.5689 111.113 39.0557 111.113 42.5751C111.113 44.0089 111.341 45.182 111.798 46.0945C112.319 46.9417 112.971 47.5609 113.753 47.9519C114.6 48.2778 115.48 48.4407 116.392 48.4407C117.305 48.4407 118.217 48.2778 119.13 47.9519C120.107 47.6261 120.889 47.235 121.476 46.7788L113.655 70.9257C111.83 71.8381 109.582 72.5876 106.909 73.1742C104.303 73.7607 101.565 74.054 98.6976 74.054C96.0906 74.054 93.5163 73.7281 90.9745 73.0764C88.4327 72.4898 86.1191 71.4796 84.0335 70.0458C82.0131 68.612 80.3838 66.722 79.1455 64.3757C77.9072 62.0295 77.288 59.0966 77.288 55.5773C77.288 50.8848 77.288 46.1922 77.288 41.4997C77.288 36.8072 77.288 32.1147 77.288 27.4222C77.288 24.7501 77.288 22.078 77.288 19.4058C77.288 16.6686 77.288 7.96384 77.288 5.29173H111.113Z" fill="grey"/>
<path d="M0.698853 30.6484C0.698853 26.9335 1.74163 23.7074 3.82719 20.9701C5.97792 18.2328 8.87815 15.9517 12.5279 14.1269C16.1776 12.2368 20.3161 10.8356 24.9435 9.92315C29.5708 9.01072 34.3937 8.5545 39.412 8.5545C45.6035 8.5545 51.3388 9.10848 56.6179 10.2164C61.9621 11.3244 66.785 12.7908 71.0864 14.6157V37.2961C69.2616 35.9275 66.8502 34.7543 63.8522 33.7767C60.9194 32.7991 57.791 32.0496 54.4672 31.5282C51.2085 31.0068 48.1127 30.7461 45.1799 30.7461C43.2247 30.7461 41.4324 30.8765 39.8031 31.1372C38.2389 31.3327 36.968 31.6586 35.9904 32.1148C35.078 32.571 34.6218 33.1576 34.6218 33.8745C34.6218 34.2655 34.7521 34.5588 35.0128 34.7543C35.3387 34.9499 35.7949 35.0802 36.3815 35.1454C36.968 35.2105 37.7175 35.2431 38.63 35.2431C40.1289 35.2431 41.465 35.2431 42.6381 35.2431C43.8113 35.2431 45.1147 35.2431 46.5486 35.2431C49.8072 35.2431 53.0659 35.4712 56.3246 35.9275C59.6485 36.3185 62.6465 37.1332 65.3186 38.3715C68.0559 39.6098 70.2392 41.402 71.8685 43.7483C73.4979 46.0294 74.3125 49.06 74.3125 52.84C74.3125 56.8156 73.2046 60.2047 70.9887 63.0071C68.838 65.7444 65.8726 67.9929 62.0925 69.7526C58.3776 71.4471 54.1739 72.6854 49.4814 73.4675C44.854 74.2496 40.0312 74.6406 35.0128 74.6406C29.082 74.6406 23.2164 74.0867 17.4159 72.9787C11.6806 71.8708 6.76001 70.2414 2.65406 68.0907V44.2371C4.28341 45.9968 6.59707 47.4632 9.59506 48.6363C12.6582 49.7443 15.9495 50.5915 19.4689 51.1781C23.0534 51.6995 26.4099 51.9602 29.5382 51.9602C31.5586 51.9602 33.3835 51.8624 35.0128 51.6669C36.6421 51.4062 37.913 51.0478 38.8255 50.5915C39.8031 50.0701 40.2919 49.4184 40.2919 48.6363C40.2919 48.3105 40.1941 48.0823 39.9986 47.952C39.8031 47.8217 39.4772 47.7239 39.021 47.6587C38.63 47.5936 38.076 47.561 37.3591 47.561C36.3815 47.561 35.3713 47.561 34.3285 47.561C33.2857 47.561 32.3407 47.561 31.4934 47.561C29.2123 47.561 26.6706 47.4958 23.8681 47.3654C21.1308 47.1699 18.3935 46.8115 15.6562 46.2901C12.9189 45.7035 10.4097 44.8237 8.12865 43.6505C5.91275 42.4122 4.12047 40.7503 2.75182 38.6648C1.38318 36.514 0.698853 33.8419 0.698853 30.6484Z" fill="grey"/>
</svg>

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@@ -5,3 +5,16 @@ import "controllers";
Turbo.StreamActions.redirect = function () {
Turbo.visit(this.target);
};
// Register service worker for PWA offline support
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker')
.then(registration => {
console.log('Service Worker registered with scope:', registration.scope);
})
.catch(error => {
console.log('Service Worker registration failed:', error);
});
});
}

View File

@@ -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">

View File

@@ -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)
// }

View File

@@ -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">

View File

@@ -6,7 +6,6 @@ ca:
no_account: Nou a %{product_name}?
sign_in: Inicia sessió
sign_up: Crea un compte
your_account: El teu compte
shared:
footer:
privacy_policy: Política de privacitat

View File

@@ -6,7 +6,6 @@ en:
no_account: New to %{product_name}?
sign_in: Sign in
sign_up: Create account
your_account: Your account
shared:
footer:
privacy_policy: Privacy Policy

View File

@@ -6,7 +6,6 @@ es:
no_account: ¿Nuevo en %{product_name}?
sign_in: Iniciar sesión
sign_up: Crear cuenta
your_account: Tu cuenta
shared:
footer:
privacy_policy: Política de privacidad

View File

@@ -6,7 +6,6 @@ nb:
no_account: Ny hos %{product_name}?
sign_in: Logg inn
sign_up: Opprett konto
your_account: Din konto
shared:
footer:
privacy_policy: Personvernerklæring

View File

@@ -6,7 +6,6 @@ tr:
no_account: "%{product_name}'ye yeni misiniz?"
sign_in: Giriş yap
sign_up: Hesap oluştur
your_account: Hesabınız
shared:
footer:
privacy_policy: Gizlilik Politikası

View File

@@ -15,7 +15,7 @@ en:
forgot_password: Forgot your password?
password: Password
submit: Log in
title: Sign in to your account
title: Sure
password_placeholder: Enter your password
openid_connect: Sign in with OpenID Connect
google_auth_connect: Sign in with Google

6
public/logo-offline.svg Normal file
View File

@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 145" fill="none">
<path d="M116.51 119.37C120.062 119.37 122.809 118.751 124.752 117.513C126.696 116.274 127.701 114.58 127.768 112.429L158.828 122.303C157.621 126.409 155.042 130.156 151.088 133.545C147.201 136.869 142.276 139.509 136.312 141.464C130.348 143.419 123.68 144.397 116.309 144.397C110.01 144.397 104.113 143.712 98.6179 142.344C93.19 140.975 88.3986 138.922 84.2439 136.185C80.1562 133.382 76.9397 129.896 74.5943 125.725C72.2489 121.553 71.0762 116.698 71.0762 111.158C71.0762 105.618 72.2489 100.763 74.5943 96.5919C76.9397 92.4208 80.1562 88.9666 84.2439 86.2293C88.3986 83.4268 93.2234 81.3412 98.7184 79.9726C104.213 78.6039 110.077 77.9196 116.309 77.9196C122.675 77.9196 128.505 78.6039 133.799 79.9726C139.16 81.3412 143.75 83.4594 147.57 86.327C151.456 89.1295 154.438 92.714 156.516 97.0807C158.66 101.382 159.732 106.498 159.732 112.429H104.95C104.95 112.429 104.917 112.429 104.85 112.429C104.85 112.429 104.85 112.462 104.85 112.527C104.85 113.504 105.118 114.417 105.654 115.264C106.19 116.111 106.927 116.861 107.865 117.513C108.871 118.099 110.077 118.555 111.484 118.881C112.958 119.207 114.634 119.37 116.51 119.37ZM116.309 102.653C113.025 102.653 110.311 103.24 108.167 104.413C106.023 105.521 104.95 107.117 104.95 109.203C104.95 109.268 104.95 109.333 104.95 109.399C105.017 109.399 105.051 109.399 105.051 109.399H127.466C127.533 109.399 127.567 109.399 127.567 109.399C127.567 109.333 127.567 109.268 127.567 109.203C127.567 108.16 127.265 107.248 126.662 106.466C126.126 105.618 125.355 104.934 124.35 104.413C123.345 103.826 122.139 103.403 120.732 103.142C119.391 102.816 117.917 102.653 116.309 102.653Z" fill="#62a446"/>
<path d="M37.5666 81.9011C37.5666 85.8115 37.5666 89.7546 37.5666 93.7301C37.5666 97.6406 37.5666 101.584 37.5666 105.559C37.5666 109.47 37.5666 113.413 37.5666 117.388C37.5666 121.559 37.5666 125.73 37.5666 129.902C37.5666 134.073 37.5666 138.276 37.5666 142.513H2.74774C2.74774 136.06 2.74774 129.608 2.74774 123.156C2.74774 116.704 2.74774 110.252 2.74774 103.799C2.74774 100.15 2.74774 96.5 2.74774 92.8503C2.74774 89.2006 2.74774 85.5508 2.74774 81.9011H37.5666ZM37.466 119.246L42.9001 92.9481C43.5039 90.1456 44.678 87.8319 46.4222 86.0071C48.2336 84.117 50.3469 82.6832 52.7621 81.7056C55.1773 80.728 57.6596 80.1414 60.2089 79.9459C62.7583 79.6852 65.1063 79.783 67.2532 80.2392C69.4 80.6302 71.1108 81.3146 72.3854 82.2922L64.7374 118.659C62.7918 117.095 60.4102 116.02 57.5925 115.433C54.8418 114.846 52.0577 114.651 49.24 114.846C46.4223 114.977 43.94 115.433 41.7932 116.215C39.6463 116.997 38.2039 118.007 37.466 119.246Z" fill="#61a446"/>
<path d="M155.301 0.291725C155.301 4.65836 155.301 20.0576 155.301 24.4894C155.301 28.9212 155.301 33.353 155.301 37.7848C155.301 41.5649 155.301 45.3776 155.301 49.2228C155.301 53.0029 155.301 56.783 155.301 60.563C155.301 64.3431 155.301 68.1232 155.301 71.9033H121.476C121.476 69.166 121.476 66.3961 121.476 63.5936C121.476 60.7912 121.476 57.9887 121.476 55.1862C121.476 52.3186 121.476 49.5487 121.476 46.8766C121.476 40.8154 121.476 34.8846 121.476 29.0841C121.476 23.2185 121.476 6.28771 121.476 0.291725H155.301ZM111.113 5.29173C111.113 8.74593 111.113 18.2327 111.113 21.7521C111.113 25.2063 111.113 28.6605 111.113 32.1147C111.113 35.5689 111.113 39.0557 111.113 42.5751C111.113 44.0089 111.341 45.182 111.798 46.0945C112.319 46.9417 112.971 47.5609 113.753 47.9519C114.6 48.2778 115.48 48.4407 116.392 48.4407C117.305 48.4407 118.217 48.2778 119.13 47.9519C120.107 47.6261 120.889 47.235 121.476 46.7788L113.655 70.9257C111.83 71.8381 109.582 72.5876 106.909 73.1742C104.303 73.7607 101.565 74.054 98.6976 74.054C96.0906 74.054 93.5163 73.7281 90.9745 73.0764C88.4327 72.4898 86.1191 71.4796 84.0335 70.0458C82.0131 68.612 80.3838 66.722 79.1455 64.3757C77.9072 62.0295 77.288 59.0966 77.288 55.5773C77.288 50.8848 77.288 46.1922 77.288 41.4997C77.288 36.8072 77.288 32.1147 77.288 27.4222C77.288 24.7501 77.288 22.078 77.288 19.4058C77.288 16.6686 77.288 7.96384 77.288 5.29173H111.113Z" fill="gray"/>
<path d="M0.698853 30.6484C0.698853 26.9335 1.74163 23.7074 3.82719 20.9701C5.97792 18.2328 8.87815 15.9517 12.5279 14.1269C16.1776 12.2368 20.3161 10.8356 24.9435 9.92315C29.5708 9.01072 34.3937 8.5545 39.412 8.5545C45.6035 8.5545 51.3388 9.10848 56.6179 10.2164C61.9621 11.3244 66.785 12.7908 71.0864 14.6157V37.2961C69.2616 35.9275 66.8502 34.7543 63.8522 33.7767C60.9194 32.7991 57.791 32.0496 54.4672 31.5282C51.2085 31.0068 48.1127 30.7461 45.1799 30.7461C43.2247 30.7461 41.4324 30.8765 39.8031 31.1372C38.2389 31.3327 36.968 31.6586 35.9904 32.1148C35.078 32.571 34.6218 33.1576 34.6218 33.8745C34.6218 34.2655 34.7521 34.5588 35.0128 34.7543C35.3387 34.9499 35.7949 35.0802 36.3815 35.1454C36.968 35.2105 37.7175 35.2431 38.63 35.2431C40.1289 35.2431 41.465 35.2431 42.6381 35.2431C43.8113 35.2431 45.1147 35.2431 46.5486 35.2431C49.8072 35.2431 53.0659 35.4712 56.3246 35.9275C59.6485 36.3185 62.6465 37.1332 65.3186 38.3715C68.0559 39.6098 70.2392 41.402 71.8685 43.7483C73.4979 46.0294 74.3125 49.06 74.3125 52.84C74.3125 56.8156 73.2046 60.2047 70.9887 63.0071C68.838 65.7444 65.8726 67.9929 62.0925 69.7526C58.3776 71.4471 54.1739 72.6854 49.4814 73.4675C44.854 74.2496 40.0312 74.6406 35.0128 74.6406C29.082 74.6406 23.2164 74.0867 17.4159 72.9787C11.6806 71.8708 6.76001 70.2414 2.65406 68.0907V44.2371C4.28341 45.9968 6.59707 47.4632 9.59506 48.6363C12.6582 49.7443 15.9495 50.5915 19.4689 51.1781C23.0534 51.6995 26.4099 51.9602 29.5382 51.9602C31.5586 51.9602 33.3835 51.8624 35.0128 51.6669C36.6421 51.4062 37.913 51.0478 38.8255 50.5915C39.8031 50.0701 40.2919 49.4184 40.2919 48.6363C40.2919 48.3105 40.1941 48.0823 39.9986 47.952C39.8031 47.8217 39.4772 47.7239 39.021 47.6587C38.63 47.5936 38.076 47.561 37.3591 47.561C36.3815 47.561 35.3713 47.561 34.3285 47.561C33.2857 47.561 32.3407 47.561 31.4934 47.561C29.2123 47.561 26.6706 47.4958 23.8681 47.3654C21.1308 47.1699 18.3935 46.8115 15.6562 46.2901C12.9189 45.7035 10.4097 44.8237 8.12865 43.6505C5.91275 42.4122 4.12047 40.7503 2.75182 38.6648C1.38318 36.514 0.698853 33.8419 0.698853 30.6484Z" fill="gray"/>
</svg>

After

Width:  |  Height:  |  Size: 6.0 KiB

121
public/offline.html Normal file
View File

@@ -0,0 +1,121 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="theme-color" content="#1a1a1a" media="(prefers-color-scheme: dark)">
<title>Offline - Maybe</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
background: #F9F9F9;
color: #1a1a1a;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.container {
max-width: 400px;
text-align: center;
}
.logo {
width: 120px;
height: auto;
margin: 0 auto 32px;
}
h1 {
font-size: 24px;
font-weight: 600;
margin-bottom: 12px;
color: #1a1a1a;
}
p {
font-size: 16px;
color: #666;
margin-bottom: 32px;
line-height: 1.5;
}
.reload-button {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
background: #62a446;
color: white;
border: none;
border-radius: 8px;
padding: 12px 24px;
font-size: 16px;
font-weight: 500;
cursor: pointer;
text-decoration: none;
transition: background 0.2s ease;
}
.reload-button:hover {
background: #528938;
}
.reload-button:active {
background: #467730;
}
.reload-icon {
width: 20px;
height: 20px;
}
@media (prefers-color-scheme: dark) {
body {
background: #1a1a1a;
color: #f9f9f9;
}
h1 {
color: #f9f9f9;
}
p {
color: #999;
}
}
</style>
</head>
<body>
<div class="container">
<img src="/logo-offline.svg" alt="Logo" class="logo">
<h1>We're experiencing <br/> technical difficulties</h1>
<p>It looks like you're offline or we can't reach our servers right now. Please check your connection and try again.</p>
<button class="reload-button" onclick="window.location.reload()">
<svg class="reload-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21.5 2v6h-6M2.5 22v-6h6M2 11.5a10 10 0 0 1 18.8-4.3M22 12.5a10 10 0 0 1-18.8 4.2"/>
</svg>
Reload
</button>
</div>
<script>
// Automatically reload when connection is restored
window.addEventListener('online', function() {
setTimeout(function() {
window.location.reload();
}, 1000);
});
</script>
</body>
</html>

View File

@@ -30,7 +30,7 @@ class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
click_button "Logout"
# Trigger Capybara's wait mechanism to avoid timing issues with logout
find("h2", text: "Sign in to your account")
find("a", text: "Sign in")
end
def within_testid(testid)