diff --git a/lnbits/core/static/js/service-worker.js b/lnbits/core/static/js/service-worker.js new file mode 100644 index 000000000..041b9f32f --- /dev/null +++ b/lnbits/core/static/js/service-worker.js @@ -0,0 +1,51 @@ +// the cache version gets updated every time there is a new deployment +const CACHE_VERSION = 1 +const CURRENT_CACHE = `lnbits-${CACHE_VERSION}-` + +const getApiKey = request => { + return request.headers.get('X-Api-Key') || 'none' +} + +// on activation we clean up the previously registered service workers +self.addEventListener('activate', evt => + evt.waitUntil( + caches.keys().then(cacheNames => { + return Promise.all( + cacheNames.map(cacheName => { + const currentCacheVersion = cacheName.split('-').slice(-2, 2) + if (currentCacheVersion !== CACHE_VERSION) { + return caches.delete(cacheName) + } + }) + ) + }) + ) +) + +// The fetch handler serves responses for same-origin resources from a cache. +// If no response is found, it populates the runtime cache with the response +// from the network before returning it to the page. +self.addEventListener('fetch', event => { + // Skip cross-origin requests, like those for Google Analytics. + if ( + event.request.url.startsWith(self.location.origin) && + event.request.method == 'GET' + ) { + // Open the cache + event.respondWith( + caches.open(CURRENT_CACHE + getApiKey(event.request)).then(cache => { + // Go to the network first + return fetch(event.request) + .then(fetchedResponse => { + cache.put(event.request, fetchedResponse.clone()) + + return fetchedResponse + }) + .catch(() => { + // If the network is unavailable, get + return cache.match(event.request.url) + }) + }) + ) + } +}) diff --git a/lnbits/core/static/js/wallet.js b/lnbits/core/static/js/wallet.js index 29a1025da..baa9f605f 100644 --- a/lnbits/core/static/js/wallet.js +++ b/lnbits/core/static/js/wallet.js @@ -702,3 +702,11 @@ new Vue({ ) } }) + +if (navigator.serviceWorker != null) { + navigator.serviceWorker + .register('/service-worker.js') + .then(function (registration) { + console.log('Registered events at scope: ', registration.scope) + }) +} diff --git a/lnbits/core/templates/core/wallet.html b/lnbits/core/templates/core/wallet.html index db4358664..acfcf7004 100644 --- a/lnbits/core/templates/core/wallet.html +++ b/lnbits/core/templates/core/wallet.html @@ -4,7 +4,6 @@ {% block scripts %} {{ window_vars(user, wallet) }} - {% endblock %} {% block title %} {{ wallet.name }} - {{ SITE_TITLE }} {% endblock %} diff --git a/lnbits/core/views/generic.py b/lnbits/core/views/generic.py index d9687e160..f8b98e4c6 100644 --- a/lnbits/core/views/generic.py +++ b/lnbits/core/views/generic.py @@ -17,6 +17,7 @@ from lnbits.helpers import template_renderer, url_for from lnbits.settings import ( LNBITS_ADMIN_USERS, LNBITS_ALLOWED_USERS, + LNBITS_CUSTOM_LOGO, LNBITS_SITE_TITLE, SERVICE_FEE, ) @@ -144,6 +145,7 @@ async def wallet( "user": user.dict(), "wallet": wallet.dict(), "service_fee": service_fee, + "web_manifest": f"/manifest/{user.id}.webmanifest", }, ) @@ -251,6 +253,11 @@ async def lnurlwallet(request: Request): ) +@core_html_routes.get("/service-worker.js", response_class=FileResponse) +async def service_worker(): + return FileResponse("lnbits/core/static/js/service-worker.js") + + @core_html_routes.get("/manifest/{usr}.webmanifest") async def manifest(usr: str): user = await get_user(usr) @@ -258,21 +265,23 @@ async def manifest(usr: str): raise HTTPException(status_code=HTTPStatus.NOT_FOUND) return { - "short_name": "LNbits", - "name": "LNbits Wallet", + "short_name": LNBITS_SITE_TITLE, + "name": LNBITS_SITE_TITLE + " Wallet", "icons": [ { - "src": "https://cdn.jsdelivr.net/gh/lnbits/lnbits@0.3.0/docs/logos/lnbits.png", + "src": LNBITS_CUSTOM_LOGO + if LNBITS_CUSTOM_LOGO + else "https://cdn.jsdelivr.net/gh/lnbits/lnbits@0.3.0/docs/logos/lnbits.png", "type": "image/png", "sizes": "900x900", } ], - "start_url": "/wallet?usr=" + usr, - "background_color": "#3367D6", - "description": "Weather forecast information", + "start_url": "/wallet?usr=" + usr + "&wal=" + user.wallets[0].id, + "background_color": "#1F2234", + "description": "Bitcoin Lightning Wallet", "display": "standalone", "scope": "/", - "theme_color": "#3367D6", + "theme_color": "#1F2234", "shortcuts": [ { "name": wallet.name, diff --git a/lnbits/extensions/tpos/templates/tpos/tpos.html b/lnbits/extensions/tpos/templates/tpos/tpos.html index 70b84f9b3..ca196e4a0 100644 --- a/lnbits/extensions/tpos/templates/tpos/tpos.html +++ b/lnbits/extensions/tpos/templates/tpos/tpos.html @@ -1,4 +1,3 @@ - {% extends "public.html" %} {% block toolbar_title %} {{ tpos.name }} { + this.g.offline = true + }) + + addEventListener('online', event => { + this.g.offline = false + }) + // failsafe if admin changes themes halfway if (!this.$q.localStorage.getItem('lnbits.theme')) { this.changeColor(this.g.allowedThemes[0]) diff --git a/lnbits/templates/base.html b/lnbits/templates/base.html index bf29bce68..6ab1ec840 100644 --- a/lnbits/templates/base.html +++ b/lnbits/templates/base.html @@ -16,7 +16,9 @@ /> - {% block head_scripts %}{% endblock %} + {% if web_manifest %} + + {% endif %} {% block head_scripts %}{% endblock %} @@ -51,6 +53,14 @@ > {% endblock %} + + OFFLINE +