Merge pull request #979 from Retrospring/fix/pwa-issues
Fix various PWA issues
|
@ -6,8 +6,8 @@ class ManifestsController < ApplicationController
|
|||
def show
|
||||
render json: {
|
||||
name: APP_CONFIG["site_name"],
|
||||
description: t("about.about.subtitle"),
|
||||
start_url: root_url(source: "pwa"),
|
||||
description: t("about.index.subtitle"),
|
||||
start_url: root_url,
|
||||
scope: root_url,
|
||||
display: "standalone",
|
||||
categories: %w[social],
|
||||
|
@ -37,10 +37,12 @@ class ManifestsController < ApplicationController
|
|||
end
|
||||
|
||||
def webapp_icons
|
||||
%i[1024 512 384 192 128 96 72 48].map do |size|
|
||||
%i[1024 512 384 192 144 128 96 72 48].map do |size|
|
||||
[
|
||||
{ src: "/icons/maskable_icon_x#{size}.webp", size: "#{size}x#{size}", type: "image/webp" },
|
||||
{ src: "/icons/maskable_icon_x#{size}.png", size: "#{size}x#{size}", type: "image/png" }
|
||||
{ src: "/icons/icon_x#{size}.webp", sizes: "#{size}x#{size}", type: "image/webp", purpose: "any" },
|
||||
{ src: "/icons/icon_x#{size}.png", sizes: "#{size}x#{size}", type: "image/png", purpose: "any" },
|
||||
{ src: "/icons/maskable_icon_x#{size}.webp", sizes: "#{size}x#{size}", type: "image/webp", purpose: "maskable" },
|
||||
{ src: "/icons/maskable_icon_x#{size}.png", sizes: "#{size}x#{size}", type: "image/png", purpose: "maskable" }
|
||||
]
|
||||
end.flatten
|
||||
end
|
||||
|
|
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 183 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 6.3 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 750 B |
After Width: | Height: | Size: 8.4 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 183 KiB After Width: | Height: | Size: 0 B |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 0 B |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 0 B |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 0 B |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 926 B |
Before Width: | Height: | Size: 750 B After Width: | Height: | Size: 0 B |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 0 B |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 0 B |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 0 B |
|
@ -0,0 +1,148 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>You are offline</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<meta name="theme-color" content="#f0edf4">
|
||||
<style>
|
||||
:root {
|
||||
--primary: #5e35b1;
|
||||
--muted: 108, 117, 125;
|
||||
--background: #f0edf4;
|
||||
}
|
||||
|
||||
*, *:before, *:after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--primary);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
body {
|
||||
padding: 2rem 1rem 1rem 1rem;
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
|
||||
background-color: var(--background);
|
||||
}
|
||||
|
||||
.text-primary {
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.text-muted {
|
||||
color: rgb(var(--muted));
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.font-weight-bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.d-none {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.links {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.links li {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.links li:not(:last-child):after {
|
||||
content: ' • ';
|
||||
}
|
||||
|
||||
.mb-0 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.mt-0 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.error-artwork-container {
|
||||
display:flex;
|
||||
justify-content: center;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.error-artwork-container picture {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.error-artwork-container picture img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.error-text-container {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
body {
|
||||
padding: 3rem 1rem 1rem 1rem;
|
||||
}
|
||||
|
||||
.error-artwork-container picture {
|
||||
width: 576px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
body {
|
||||
padding: 5rem 1rem 3rem 1rem;
|
||||
}
|
||||
|
||||
.error {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.error-text-container {
|
||||
align-self: center;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="error">
|
||||
<div class="error-artwork-container">
|
||||
<picture>
|
||||
<source
|
||||
srcset="/images/errors/small/404.png 576w,
|
||||
/images/errors/medium/404.png 768w,
|
||||
/images/errors/original/404.png 1200w">
|
||||
<img src="/images/errors/small/404.png" alt="A raccoon peeking out of a bin, looking confused" />
|
||||
</picture>
|
||||
</div>
|
||||
<div class="error-text-container">
|
||||
<h1>
|
||||
<small class="text-primary">You are offline</small>
|
||||
</h1>
|
||||
<p>
|
||||
This content is not available offline.
|
||||
</p>
|
||||
<ul class="links">
|
||||
<li>
|
||||
<a href="/">Retry</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
window.addEventListener('online', () => {
|
||||
window.location.reload();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,3 +1,14 @@
|
|||
const OFFLINE_CACHE_NAME = "offline";
|
||||
// Bumping this version will force an update of the service worker
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const OFFLINE_PAGE_VERSION = 1;
|
||||
const OFFLINE_CACHE_PATHS = [
|
||||
"/pwa_offline.html",
|
||||
"/images/errors/small/404.png",
|
||||
"/images/errors/medium/404.png",
|
||||
"/images/errors/original/404.png"
|
||||
];
|
||||
|
||||
self.addEventListener('push', function (event) {
|
||||
if (event.data) {
|
||||
const notification = event.data.json();
|
||||
|
@ -23,3 +34,31 @@ self.addEventListener('notificationclick', async event => {
|
|||
console.warn(`Unhandled notification tag: ${event.notification.tag}`);
|
||||
}
|
||||
});
|
||||
|
||||
self.addEventListener('install', function (event) {
|
||||
event.waitUntil(
|
||||
(async () => {
|
||||
const cache = await caches.open(OFFLINE_CACHE_NAME);
|
||||
await cache.addAll(OFFLINE_CACHE_PATHS);
|
||||
})()
|
||||
);
|
||||
// Immediately activate new versions of the service worker instead of waiting
|
||||
self.skipWaiting();
|
||||
});
|
||||
|
||||
self.addEventListener('fetch', function (event) {
|
||||
event.respondWith(
|
||||
(async () => {
|
||||
try {
|
||||
// Try to load the resource
|
||||
return await fetch(event.request);
|
||||
} catch (error) {
|
||||
// Show an error page if offline
|
||||
console.log("Fetch failed; returning offline page instead.", error);
|
||||
|
||||
const cache = await caches.open(OFFLINE_CACHE_NAME);
|
||||
return await cache.match(OFFLINE_CACHE_PATHS[0]);
|
||||
}
|
||||
})()
|
||||
);
|
||||
});
|
||||
|
|
|
@ -21,7 +21,7 @@ describe ManifestsController, type: :controller do
|
|||
body = JSON.parse(response.body)
|
||||
|
||||
expect(body["name"]).to eq("Specspring")
|
||||
expect(body["start_url"]).to eq("http://test.host/?source=pwa")
|
||||
expect(body["start_url"]).to eq("http://test.host/")
|
||||
expect(body["scope"]).to eq("http://test.host/")
|
||||
expect(body["theme_color"]).to eq("#5e35b1")
|
||||
end
|
||||
|
|