Merge branch 'feature/enhance-pwa'
This commit is contained in:
commit
ac1731d123
18 changed files with 229 additions and 53 deletions
|
@ -115,6 +115,9 @@ assets:
|
||||||
# only works if `assets.self_host.enabled` is 'true'
|
# only works if `assets.self_host.enabled` is 'true'
|
||||||
env: # [development|production]
|
env: # [development|production]
|
||||||
|
|
||||||
|
pwa:
|
||||||
|
enabled: true # the option for PWA feature
|
||||||
|
|
||||||
paginate: 10
|
paginate: 10
|
||||||
|
|
||||||
# ------------ The following options are not recommended to be modified ------------------
|
# ------------ The following options are not recommended to be modified ------------------
|
||||||
|
|
|
@ -45,6 +45,10 @@ meta: Powered by :PLATFORM with :THEME theme.
|
||||||
not_found:
|
not_found:
|
||||||
statment: Sorry, we've misplaced that URL or it's pointing to something that doesn't exist.
|
statment: Sorry, we've misplaced that URL or it's pointing to something that doesn't exist.
|
||||||
|
|
||||||
|
notification:
|
||||||
|
update_found: A new version of content is available.
|
||||||
|
update: Update
|
||||||
|
|
||||||
# ----- Posts related labels -----
|
# ----- Posts related labels -----
|
||||||
|
|
||||||
post:
|
post:
|
||||||
|
|
|
@ -45,6 +45,10 @@ meta: Hecho con :PLATFORM usando el tema :THEME.
|
||||||
not_found:
|
not_found:
|
||||||
statment: Lo sentimos, hemos perdido esa URL o apunta a algo que no existe.
|
statment: Lo sentimos, hemos perdido esa URL o apunta a algo que no existe.
|
||||||
|
|
||||||
|
notification:
|
||||||
|
update_found: Hay una nueva versión de contenido disponible.
|
||||||
|
update: Actualizar
|
||||||
|
|
||||||
# ----- Posts related labels -----
|
# ----- Posts related labels -----
|
||||||
|
|
||||||
post:
|
post:
|
||||||
|
|
|
@ -45,6 +45,10 @@ meta: Propulsé par :PLATFORM avec le thème :THEME
|
||||||
not_found:
|
not_found:
|
||||||
statment: Désolé, nous avons égaré cette URL ou elle pointe vers quelque chose qui n'existe pas.
|
statment: Désolé, nous avons égaré cette URL ou elle pointe vers quelque chose qui n'existe pas.
|
||||||
|
|
||||||
|
notification:
|
||||||
|
update_found: Une nouvelle version du contenu est disponible.
|
||||||
|
update: Mise à jour
|
||||||
|
|
||||||
# ----- Posts related labels -----
|
# ----- Posts related labels -----
|
||||||
|
|
||||||
post:
|
post:
|
||||||
|
|
|
@ -45,6 +45,10 @@ meta: Didukung oleh :PLATFORM dengan tema :THEME.
|
||||||
not_found:
|
not_found:
|
||||||
statment: Maaf, kami gagal menemukan URL itu atau memang mengarah ke sesuatu yang tidak ada.
|
statment: Maaf, kami gagal menemukan URL itu atau memang mengarah ke sesuatu yang tidak ada.
|
||||||
|
|
||||||
|
notification:
|
||||||
|
update_found: Versi konten baru tersedia.
|
||||||
|
update: Perbarui
|
||||||
|
|
||||||
# ----- Posts related labels -----
|
# ----- Posts related labels -----
|
||||||
|
|
||||||
post:
|
post:
|
||||||
|
|
|
@ -45,6 +45,10 @@ meta: Powered by :PLATFORM with :THEME theme.
|
||||||
not_found:
|
not_found:
|
||||||
statment: 해당 URL은 존재하지 않습니다.
|
statment: 해당 URL은 존재하지 않습니다.
|
||||||
|
|
||||||
|
notification:
|
||||||
|
update_found: 새 버전의 콘텐츠를 사용할 수 있습니다.
|
||||||
|
update: 업데이트
|
||||||
|
|
||||||
# ----- Posts related labels -----
|
# ----- Posts related labels -----
|
||||||
|
|
||||||
post:
|
post:
|
||||||
|
|
|
@ -45,6 +45,10 @@ meta: Powered by :PLATFORM with :THEME theme.
|
||||||
not_found:
|
not_found:
|
||||||
statment: ဝမ်းနည်းပါသည်၊ ကျွန်ုပ်တို့သည် အဆိုပါ URL ကို မှားယွင်းစွာ နေရာချထားခြင်း သို့မဟုတ် ၎င်းသည် မရှိသောအရာကို ညွှန်ပြနေပါသည်။
|
statment: ဝမ်းနည်းပါသည်၊ ကျွန်ုပ်တို့သည် အဆိုပါ URL ကို မှားယွင်းစွာ နေရာချထားခြင်း သို့မဟုတ် ၎င်းသည် မရှိသောအရာကို ညွှန်ပြနေပါသည်။
|
||||||
|
|
||||||
|
notification:
|
||||||
|
update_found: အကြောင်းအရာဗားရှင်းအသစ်ကို ရနိုင်ပါပြီ။
|
||||||
|
update: အပ်ဒိတ်
|
||||||
|
|
||||||
# ----- Posts related labels -----
|
# ----- Posts related labels -----
|
||||||
|
|
||||||
post:
|
post:
|
||||||
|
|
|
@ -45,6 +45,10 @@ meta: Feito com :PLATFORM usando o tema :THEME.
|
||||||
not_found:
|
not_found:
|
||||||
statment: Desculpe, a página não foi encontrada.
|
statment: Desculpe, a página não foi encontrada.
|
||||||
|
|
||||||
|
notification:
|
||||||
|
update_found: Uma nova versão do conteúdo está disponível.
|
||||||
|
update: atualização
|
||||||
|
|
||||||
# ----- Posts related labels -----
|
# ----- Posts related labels -----
|
||||||
|
|
||||||
post:
|
post:
|
||||||
|
|
|
@ -45,6 +45,10 @@ meta: Powered by :PLATFORM with :THEME theme.
|
||||||
not_found:
|
not_found:
|
||||||
statment: Извините, эта ссылка указывает на ресурс который не существует.
|
statment: Извините, эта ссылка указывает на ресурс который не существует.
|
||||||
|
|
||||||
|
notification:
|
||||||
|
update_found: Доступна новая версия контента.
|
||||||
|
update: Обновлять
|
||||||
|
|
||||||
# ----- Posts related labels -----
|
# ----- Posts related labels -----
|
||||||
|
|
||||||
post:
|
post:
|
||||||
|
|
|
@ -45,6 +45,10 @@ meta: Powered by :PLATFORM with :THEME theme.
|
||||||
not_found:
|
not_found:
|
||||||
statment: Вибачте, це посилання вказує на ресурс, що не існує.
|
statment: Вибачте, це посилання вказує на ресурс, що не існує.
|
||||||
|
|
||||||
|
notification:
|
||||||
|
update_found: Доступна нова версія вмісту.
|
||||||
|
update: Оновлення
|
||||||
|
|
||||||
# ----- Posts related labels -----
|
# ----- Posts related labels -----
|
||||||
|
|
||||||
post:
|
post:
|
||||||
|
|
|
@ -43,6 +43,10 @@ meta: Trang web này được tạo bởi :PLATFORM với chủ đề :THEME.
|
||||||
not_found:
|
not_found:
|
||||||
statment: Xin lỗi, chúng tôi đã đặt nhầm URL hoặc đường dẫn trỏ đến một trang nào đó không tồn tại.
|
statment: Xin lỗi, chúng tôi đã đặt nhầm URL hoặc đường dẫn trỏ đến một trang nào đó không tồn tại.
|
||||||
|
|
||||||
|
notification:
|
||||||
|
update_found: Đã có phiên bản mới của nội dung.
|
||||||
|
update: Cập nhật
|
||||||
|
|
||||||
# ----- Posts related labels -----
|
# ----- Posts related labels -----
|
||||||
|
|
||||||
post:
|
post:
|
||||||
|
|
|
@ -44,6 +44,10 @@ meta: 本站由 :PLATFORM 生成,采用 :THEME 主题。
|
||||||
not_found:
|
not_found:
|
||||||
statment: 抱歉,我们放错了该 URL,或者它指向了不存在的内容。
|
statment: 抱歉,我们放错了该 URL,或者它指向了不存在的内容。
|
||||||
|
|
||||||
|
notification:
|
||||||
|
update_found: 发现新版本的内容。
|
||||||
|
update: 更新
|
||||||
|
|
||||||
# ----- Posts related labels -----
|
# ----- Posts related labels -----
|
||||||
|
|
||||||
post:
|
post:
|
||||||
|
|
|
@ -90,7 +90,11 @@
|
||||||
|
|
||||||
{% if jekyll.environment == 'production' %}
|
{% if jekyll.environment == 'production' %}
|
||||||
<!-- PWA -->
|
<!-- PWA -->
|
||||||
<script defer src="{{ '/app.js' | relative_url }}"></script>
|
{% if site.pwa.enabled %}
|
||||||
|
<script defer src="{{ '/app.js' | relative_url }}"></script>
|
||||||
|
{% else %}
|
||||||
|
<script defer src="{{ '/unregister.js' | relative_url }}"></script>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<!-- GA -->
|
<!-- GA -->
|
||||||
{% if site.google_analytics.id != empty and site.google_analytics.id %}
|
{% if site.google_analytics.id != empty and site.google_analytics.id %}
|
||||||
|
|
|
@ -48,6 +48,23 @@ layout: compress
|
||||||
<i class="fas fa-angle-up"></i>
|
<i class="fas fa-angle-up"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
{% if site.pwa.enabled %}
|
||||||
|
<div id="notification" class="toast" role="alert" aria-live="assertive" aria-atomic="true"
|
||||||
|
data-animation="true" data-autohide="false">
|
||||||
|
<div class="toast-header">
|
||||||
|
<button type="button" class="ml-2 ml-auto close" data-dismiss="toast" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="toast-body text-center pt-0">
|
||||||
|
<p class="pl-2 pr-2 mb-3">{{ site.data.locales[lang].notification.update_found }}</p>
|
||||||
|
<button type="button" class="btn btn-primary" aria-label="Update">
|
||||||
|
{{ site.data.locales[lang].notification.update }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% include search-loader.html %}
|
{% include search-loader.html %}
|
||||||
|
|
||||||
{% include js-selector.html %}
|
{% include js-selector.html %}
|
||||||
|
|
|
@ -1150,6 +1150,51 @@ $sidebar-display: "sidebar-display";
|
||||||
-webkit-transform: translate3d(0, -5px, 0);
|
-webkit-transform: translate3d(0, -5px, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#notification {
|
||||||
|
@keyframes popup {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.toast-header {
|
||||||
|
background: none;
|
||||||
|
border-bottom: none;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toast-body {
|
||||||
|
font-family: 'Lato';
|
||||||
|
line-height: 1.25rem;
|
||||||
|
|
||||||
|
button {
|
||||||
|
font-size: 90%;
|
||||||
|
min-width: 4rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.toast {
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
&.show {
|
||||||
|
display: block;
|
||||||
|
min-width: 20rem;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
-webkit-backdrop-filter: blur(10px);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
background-color: rgba(255, 255, 255, 0.5);
|
||||||
|
color: #1b1b1eba;
|
||||||
|
position: fixed;
|
||||||
|
left: 50%;
|
||||||
|
bottom: 20%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
animation: popup 0.8s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Responsive Design:
|
Responsive Design:
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,56 @@ layout: compress
|
||||||
permalink: '/app.js'
|
permalink: '/app.js'
|
||||||
---
|
---
|
||||||
|
|
||||||
/* Registering Service Worker */
|
const keyWaiting = 'sw-waiting';
|
||||||
if('serviceWorker' in navigator) {
|
const $notification = $('#notification');
|
||||||
navigator.serviceWorker.register('{{ "/sw.js" | relative_url }}');
|
const $btnRefresh = $('#notification .toast-body>button');
|
||||||
};
|
|
||||||
|
function skipWating(registration) {
|
||||||
|
registration.waiting.postMessage('SKIP_WAITING');
|
||||||
|
localStorage.removeItem(keyWaiting);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('serviceWorker' in navigator) {
|
||||||
|
/* Registering Service Worker */
|
||||||
|
navigator.serviceWorker.register('{{ "/sw.js" | relative_url }}')
|
||||||
|
.then(registration => {
|
||||||
|
if (registration) {
|
||||||
|
registration.addEventListener('updatefound', () => {
|
||||||
|
/* console.log('updatefound'); */
|
||||||
|
let serviceWorker = registration.installing;
|
||||||
|
|
||||||
|
serviceWorker.addEventListener('statechange', () => {
|
||||||
|
/* console.log(`statechange -> ${serviceWorker.state}`); */
|
||||||
|
if (serviceWorker.state === 'installed') {
|
||||||
|
/* console.log('installed'); */
|
||||||
|
if (navigator.serviceWorker.controller) {
|
||||||
|
$notification.toast('show');
|
||||||
|
/* in case the user ignores the notification */
|
||||||
|
localStorage.setItem(keyWaiting, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$btnRefresh.click(() => {
|
||||||
|
skipWating(registration);
|
||||||
|
$notification.toast('hide');
|
||||||
|
});
|
||||||
|
|
||||||
|
/* there's a new Service Worker waiting to be activated */
|
||||||
|
if (localStorage.getItem(keyWaiting)) {
|
||||||
|
$notification.toast('show');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let refreshing = false;
|
||||||
|
|
||||||
|
/* Detect controller change and refresh all the opened tabs */
|
||||||
|
navigator.serviceWorker.addEventListener('controllerchange', () => {
|
||||||
|
if (!refreshing) {
|
||||||
|
window.location.reload();
|
||||||
|
refreshing = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ permalink: '/sw.js'
|
||||||
|
|
||||||
self.importScripts('{{ "/assets/js/data/swcache.js" | relative_url }}');
|
self.importScripts('{{ "/assets/js/data/swcache.js" | relative_url }}');
|
||||||
|
|
||||||
const cacheName = 'chirpy-{{ "now" | date: "%Y%m%d.%H%M" }}';
|
const cacheName = 'chirpy-{{ "now" | date: "%Y%m%d.%H%M%S" }}';
|
||||||
|
|
||||||
function verifyDomain(url) {
|
function verifyDomain(url) {
|
||||||
for (const domain of allowedDomains) {
|
for (const domain of allowedDomains) {
|
||||||
|
@ -28,60 +28,62 @@ function isExcluded(url) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.addEventListener('install', e => {
|
self.addEventListener('install', event => {
|
||||||
self.skipWaiting();
|
event.waitUntil(
|
||||||
e.waitUntil(
|
|
||||||
caches.open(cacheName).then(cache => {
|
caches.open(cacheName).then(cache => {
|
||||||
return cache.addAll(resource);
|
return cache.addAll(resource);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
self.addEventListener('fetch', event => {
|
self.addEventListener('activate', event => {
|
||||||
event.respondWith(
|
event.waitUntil(
|
||||||
caches.match(event.request)
|
|
||||||
.then(response => {
|
|
||||||
if (response) {
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fetch(event.request)
|
|
||||||
.then(response => {
|
|
||||||
const url = event.request.url;
|
|
||||||
|
|
||||||
if (event.request.method !== 'GET' ||
|
|
||||||
!verifyDomain(url) ||
|
|
||||||
isExcluded(url)) {
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
see: <https://developers.google.com/web/fundamentals/primers/service-workers#cache_and_return_requests>
|
|
||||||
*/
|
|
||||||
let responseToCache = response.clone();
|
|
||||||
|
|
||||||
caches.open(cacheName)
|
|
||||||
.then(cache => {
|
|
||||||
/* console.log('[sw] Caching new resource: ' + event.request.url); */
|
|
||||||
cache.put(event.request, responseToCache);
|
|
||||||
});
|
|
||||||
|
|
||||||
return response;
|
|
||||||
});
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
self.addEventListener('activate', e => {
|
|
||||||
e.waitUntil(
|
|
||||||
caches.keys().then(keyList => {
|
caches.keys().then(keyList => {
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
keyList.map(key => {
|
keyList.map(key => {
|
||||||
if(key !== cacheName) {
|
if (key !== cacheName) {
|
||||||
return caches.delete(key);
|
return caches.delete(key);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener('message', (event) => {
|
||||||
|
if (event.data === 'SKIP_WAITING') {
|
||||||
|
self.skipWaiting();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener('fetch', event => {
|
||||||
|
event.respondWith(
|
||||||
|
caches.match(event.request).then(response => {
|
||||||
|
if (response) {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fetch(event.request).then(response => {
|
||||||
|
const url = event.request.url;
|
||||||
|
|
||||||
|
if (event.request.method !== 'GET' ||
|
||||||
|
!verifyDomain(url) ||
|
||||||
|
isExcluded(url)) {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
see: <https://developers.google.com/web/fundamentals/primers/service-workers#cache_and_return_requests>
|
||||||
|
*/
|
||||||
|
let responseToCache = response.clone();
|
||||||
|
|
||||||
|
caches.open(cacheName).then(cache => {
|
||||||
|
/* console.log('[sw] Caching new resource: ' + event.request.url); */
|
||||||
|
cache.put(event.request, responseToCache);
|
||||||
|
});
|
||||||
|
|
||||||
|
return response;
|
||||||
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
12
assets/js/pwa/unregister.js
Normal file
12
assets/js/pwa/unregister.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
layout: compress
|
||||||
|
permalink: '/unregister.js'
|
||||||
|
---
|
||||||
|
|
||||||
|
if ('serviceWorker' in navigator) {
|
||||||
|
navigator.serviceWorker.getRegistrations().then((registrations) => {
|
||||||
|
for (let reg of registrations) {
|
||||||
|
reg.unregister();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in a new issue