diff --git a/internal/http/request/context.go b/internal/http/request/context.go index ba6ee40d..eadff476 100644 --- a/internal/http/request/context.go +++ b/internal/http/request/context.go @@ -140,6 +140,11 @@ func LastForceRefresh(r *http.Request) int64 { return timestamp } +// Determine if the request is from a service worker. +func IsServiceWorker(r *http.Request) bool { + return r.Header.Get("Client-Type") == "service-worker" +} + // ClientIP returns the client IP address stored in the context. func ClientIP(r *http.Request) string { return getContextStringValue(r, ClientIPContextKey) diff --git a/internal/template/templates/common/layout.html b/internal/template/templates/common/layout.html index 13c8c652..03b3c7ab 100644 --- a/internal/template/templates/common/layout.html +++ b/internal/template/templates/common/layout.html @@ -132,6 +132,7 @@ {{ if .flashErrorMessage }} {{ end }} + {{template "page_header" .}} diff --git a/internal/ui/entry_unread.go b/internal/ui/entry_unread.go index 07d9007c..bd1dd2fd 100644 --- a/internal/ui/entry_unread.go +++ b/internal/ui/entry_unread.go @@ -66,7 +66,7 @@ func (h *handler) showUnreadEntryPage(w http.ResponseWriter, r *http.Request) { prevEntryRoute = route.Path(h.router, "unreadEntry", "entryID", prevEntry.ID) } - if entry.ShouldMarkAsReadOnView(user) { + if entry.ShouldMarkAsReadOnView(user) && !request.IsServiceWorker(r) { entry.Status = model.EntryStatusRead } diff --git a/internal/ui/static/js/service_worker.js b/internal/ui/static/js/service_worker.js index 379b4136..3a6f622b 100644 --- a/internal/ui/static/js/service_worker.js +++ b/internal/ui/static/js/service_worker.js @@ -3,8 +3,6 @@ const OFFLINE_VERSION = 2; const CACHE_NAME = "offline"; -console.log(USE_CACHE); - self.addEventListener("install", (event) => { event.waitUntil( (async () => { @@ -64,3 +62,37 @@ self.addEventListener("fetch", (event) => { ); } }); + +self.addEventListener("load", async (event) => { + if ( + navigator.onLine === true && + event.target.location.pathname === "/unread" && + USE_CACHE + ) { + const cache = await caches.open(CACHE_NAME); + + for (let article of document.getElementsByTagName("article")) { + const as = article.getElementsByTagName("a"); + if (as.length > 0) { + const a = as[0]; + const href = a.href; + cache + .add( + new Request(href, { + headers: new Headers({ + "Client-Type": "service-worker", + }), + }), + ) + .then(() => { + article; + }); + } + } + } +}); + +self.addEventListener("DOMContentLoaded", function () { + const offlineFlag = document.getElementById("offline-flag"); + offlineFlag.classList.toggle("hidden", navigator.onLine); +});