From f0cbdec755e91fc3f02e96b03e1fc200b135815e Mon Sep 17 00:00:00 2001 From: tdro Date: Sat, 8 Apr 2023 14:35:37 -0400 Subject: static/js: Add update check In the case of heavy caching attempt a naive site update check with voluntary refresh. Not fully idempotent? --- Makefile | 1 + assets/css/default.css | 23 ++++++++--- assets/js/index.js | 43 ++++++++++++++++++++ config.json | 4 +- config.toml | 2 + config.yaml | 1 + static/icons/feather/refresh-cw.svg | 15 +++++++ static/js/index.ts | 1 + static/js/refresh.ts | 46 ++++++++++++++++++++++ themes/default/layouts/partials/base-head.html | 23 ++++++----- .../default/layouts/partials/navigator-middle.html | 37 ++++++++++------- 11 files changed, 166 insertions(+), 30 deletions(-) create mode 100644 static/icons/feather/refresh-cw.svg create mode 100644 static/js/refresh.ts diff --git a/Makefile b/Makefile index 2f12353..01a8247 100644 --- a/Makefile +++ b/Makefile @@ -82,6 +82,7 @@ icons: curl --silent --remote-name https://raw.githubusercontent.com/feathericons/feather/master/icons/home.svg --output-dir static/icons/feather curl --silent --remote-name https://raw.githubusercontent.com/feathericons/feather/master/icons/link.svg --output-dir static/icons/feather curl --silent --remote-name https://raw.githubusercontent.com/feathericons/feather/master/icons/map-pin.svg --output-dir static/icons/feather + curl --silent --remote-name https://raw.githubusercontent.com/feathericons/feather/master/icons/refresh-cw.svg --output-dir static/icons/feather curl --silent --remote-name https://raw.githubusercontent.com/feathericons/feather/master/icons/rss.svg --output-dir static/icons/feather curl --silent --remote-name https://raw.githubusercontent.com/feathericons/feather/master/icons/search.svg --output-dir static/icons/feather curl --silent --remote-name https://raw.githubusercontent.com/feathericons/feather/master/icons/tag.svg --output-dir static/icons/feather diff --git a/assets/css/default.css b/assets/css/default.css index a093b9b..e5eaa16 100644 --- a/assets/css/default.css +++ b/assets/css/default.css @@ -661,7 +661,8 @@ self-embed iframe { img { height: auto; max-width: 100%; - border: 1px solid; + border-width: 1px; + border-style: solid; border-color: #ccc; border-color: var(--border-darker); border-radius: 0.5rem; @@ -1359,6 +1360,11 @@ column-middle main > footer { margin: 1rem 0; } +icon-button, +icon-navigator { + height: 4rem; +} + icon-button a { color: inherit; display: flex; @@ -1371,9 +1377,16 @@ icon-button a { padding: 0.5rem 0; } -icon-button, -icon-navigator { - height: 4rem; +icon-button a svg:nth-of-type(2), +icon-button a small:nth-of-type(2), +icon-button a[data-update="refresh"] svg:nth-of-type(1), +icon-button a[data-update="refresh"] small:nth-of-type(1) { + display: none; +} + +icon-button a[data-update="refresh"] svg:nth-of-type(2), +icon-button a[data-update="refresh"] small:nth-of-type(2) { + display: initial; } icon-button a:hover { @@ -1578,7 +1591,7 @@ following-list aside footer { } author-list h1 a { - color: inherit; + color: inherit; } author-list aside { diff --git a/assets/js/index.js b/assets/js/index.js index cc61f84..67331da 100644 --- a/assets/js/index.js +++ b/assets/js/index.js @@ -63,6 +63,49 @@ scrollRestore(url); }); })(); +(function() { + function check(url, method, callback) { + const http = new XMLHttpRequest(); + http.onreadystatechange = function() { + if (http.readyState === 4 && http.status === 200) { + if (callback) callback(http); + } + }; + http.open(method, url); + http.setRequestHeader("Pragma", "no-cache"); + http.setRequestHeader("Cache-Control", "no-cache"); + http.send(); + } + function update(id) { + const url = self.location.href; + check(url, "HEAD", function(request) { + const local = document.querySelector('meta[name="last-modified"]').content; + const remote = request.getResponseHeader("last-modified") || local; + const localHour = local.substring(0, local.length - 9); + const remoteHour = remote.substring(0, remote.length - 9); + const modified = localHour !== remoteHour; + if (modified) { + const indicator = document.querySelector("a[data-update]"); + check(url, "GET"); + indicator.href = url; + indicator.removeAttribute("id"); + indicator.dataset.update = "refresh"; + clearInterval(id); + } + console.log("R: " + remote); + console.log("L: " + local); + console.log("M: " + modified); + }); + } + self.addEventListener("load", function() { + let meta = document.querySelector('meta[name="refresh"]'); + if (meta) meta = document.querySelector('meta[name="refresh"]').content; + const interval = meta || 3600000; + const monitor = setInterval(function() { + if (navigator.onLine) update(monitor); + }, interval); + }); +})(); (function() { const options = "targetWindow,width=700,height=500,toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes"; self.addEventListener("keydown", function(event) { diff --git a/config.json b/config.json index 4a4256c..c977045 100644 --- a/config.json +++ b/config.json @@ -88,7 +88,9 @@ "referrer": "no-referrer", "robots": "index,follow", "canonical": null, - "refresh": null + "refresh": { + "milliseconds": null + } }, "webmanifest": { "name": "Micro Blog", diff --git a/config.toml b/config.toml index d615726..3801026 100644 --- a/config.toml +++ b/config.toml @@ -82,6 +82,8 @@ enableRobotsTXT = true referrer = "no-referrer" robots = "index,follow" + [params.site.refresh] + [params.webmanifest] name = "Micro Blog" shortName = "Micro" diff --git a/config.yaml b/config.yaml index f89cdfa..bc69a0d 100644 --- a/config.yaml +++ b/config.yaml @@ -73,6 +73,7 @@ params: robots: index,follow canonical: refresh: + milliseconds: webmanifest: name: Micro Blog shortName: Micro diff --git a/static/icons/feather/refresh-cw.svg b/static/icons/feather/refresh-cw.svg new file mode 100644 index 0000000..1773a2f --- /dev/null +++ b/static/icons/feather/refresh-cw.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/static/js/index.ts b/static/js/index.ts index e00907b..6de3166 100644 --- a/static/js/index.ts +++ b/static/js/index.ts @@ -1,4 +1,5 @@ import "./pager.ts"; +import "./refresh.ts"; import "./plumber.ts"; import "./instantpage.ts"; import "./contextmenu.ts"; diff --git a/static/js/refresh.ts b/static/js/refresh.ts new file mode 100644 index 0000000..5d44854 --- /dev/null +++ b/static/js/refresh.ts @@ -0,0 +1,46 @@ +(function () { + function check(url, method, callback) { + const http = new XMLHttpRequest(); + http.onreadystatechange = function () { + if (http.readyState === 4 && http.status === 200) { + if (callback) callback(http); + } + }; + http.open(method, url); + http.setRequestHeader("Pragma", "no-cache"); + http.setRequestHeader("Cache-Control", "no-cache"); + http.send(); + } + + function update(id) { + const url = self.location.href; + check(url, "HEAD", function (request) { + const local = document.querySelector('meta[name="last-modified"]').content; + const remote = request.getResponseHeader("last-modified") || local; + const localHour = local.substring(0, local.length - 9); + const remoteHour = remote.substring(0, remote.length - 9); + const modified = localHour !== remoteHour; + + if (modified) { + const indicator = document.querySelector("a[data-update]"); + check(url, "GET"); + indicator.href = url; + indicator.removeAttribute("id"); + indicator.dataset.update = "refresh"; + clearInterval(id); + } + console.log("R: " + remote); + console.log("L: " + local); + console.log("M: " + modified); + }); + } + + self.addEventListener("load", function () { + let meta = document.querySelector('meta[name="refresh"]'); + if (meta) meta = document.querySelector('meta[name="refresh"]').content; + const interval = meta || 3600000; + const monitor = setInterval(function () { + if (navigator.onLine) update(monitor); + }, interval); + }); +})(); diff --git a/themes/default/layouts/partials/base-head.html b/themes/default/layouts/partials/base-head.html index 9decdac..acedcf0 100644 --- a/themes/default/layouts/partials/base-head.html +++ b/themes/default/layouts/partials/base-head.html @@ -7,20 +7,18 @@ {{- $author := partial "function-authors-data.html" (dict "Data" $authorData) -}} +{{- $noindex := "" -}} +{{- if or .Params.Feed .Params.Unlisted .Params.ExpiryDate -}} + {{- $noindex = "noindex,nofollow" -}} +{{- end }} + -{{ if or .Params.Feed .Params.Unlisted .Params.ExpiryDate -}} - -{{- else -}} - -{{- end }} + -{{ with .Site.Params.site.refresh -}} - -{{- end }} @@ -42,12 +40,17 @@ - -{{- partial "base-search.html" . -}} + + + + + +{{- partial "base-search.html" . -}} + {{- partial "base-discovery.html" . -}} diff --git a/themes/default/layouts/partials/navigator-middle.html b/themes/default/layouts/partials/navigator-middle.html index 46c4060..688963a 100644 --- a/themes/default/layouts/partials/navigator-middle.html +++ b/themes/default/layouts/partials/navigator-middle.html @@ -1,22 +1,28 @@ -{{ $id := .Id }} -{{ $href := .Href }} +{{- $id := .Id -}} +{{- $href := .Href -}} +{{- $icon := readFile (print (partial "function-paths.html").static "/icons/feather/arrow-up.svg") -}} +{{- $refresh := readFile (print (partial "function-paths.html").static "/icons/feather/refresh-cw.svg") -}} +{{- $label := "Top" -}} + +{{- with .Icon -}} + {{- $icon = readFile (print (partial "function-paths.html").static "/icons/feather/" . ".svg") -}} +{{- end -}} + +{{- with .IconLabel -}} + {{- $label = . -}} +{{- end -}} - + + + -- cgit v1.2.3