From 2b5230f60fb8ab4930b3075997f7aa71bc617549 Mon Sep 17 00:00:00 2001 From: Adrien Siami Date: Mon, 20 Nov 2023 12:15:25 +0100 Subject: [PATCH 1/4] Refactor the way scroll is saved and restored to avoid premature restoration --- .../hotwire-livereload-turbo-stream.js | 25 ++++++++++ app/assets/javascripts/hotwire-livereload.js | 49 ++++++++----------- app/javascript/hotwire-livereload.js | 22 ++------- .../lib/hotwire-livereload-received.js | 2 + 4 files changed, 51 insertions(+), 47 deletions(-) diff --git a/app/assets/javascripts/hotwire-livereload-turbo-stream.js b/app/assets/javascripts/hotwire-livereload-turbo-stream.js index cd69d20..a3a6e9c 100644 --- a/app/assets/javascripts/hotwire-livereload-turbo-stream.js +++ b/app/assets/javascripts/hotwire-livereload-turbo-stream.js @@ -81,6 +81,30 @@ // app/javascript/lib/hotwire-livereload-received.js var import_debounce = __toESM(require_debounce()); + + // app/javascript/lib/hotwire-livereload-scroll-position.js + var KEY = "hotwire-livereload-scrollPosition"; + function read() { + const value = localStorage.getItem(KEY); + if (!value) + return 0; + return parseInt(value); + } + function save() { + const pos = window.scrollY; + localStorage.setItem(KEY, pos.toString()); + } + function reset() { + localStorage.setItem(KEY, "0"); + } + function restore() { + const value = read(); + console.log("[Hotwire::Livereload] Restoring scroll position to", value); + window.scrollTo(0, value); + } + var hotwire_livereload_scroll_position_default = { read, save, restore, reset }; + + // app/javascript/lib/hotwire-livereload-received.js var hotwire_livereload_received_default = (0, import_debounce.default)(({ force_reload }) => { const onErrorPage = document.title === "Action Controller: Exception caught"; if (onErrorPage || force_reload) { @@ -88,6 +112,7 @@ document.location.reload(); } else { console.log("[Hotwire::Livereload] Files changed. Reloading.."); + hotwire_livereload_scroll_position_default.save(); Turbo.visit(window.location.href, { action: "replace" }); } }, 300); diff --git a/app/assets/javascripts/hotwire-livereload.js b/app/assets/javascripts/hotwire-livereload.js index 42bb9c5..68c346a 100644 --- a/app/assets/javascripts/hotwire-livereload.js +++ b/app/assets/javascripts/hotwire-livereload.js @@ -607,7 +607,7 @@ // node_modules/debounce/index.js var require_debounce = __commonJS({ "node_modules/debounce/index.js"(exports, module) { - function debounce3(func, wait, immediate) { + function debounce2(func, wait, immediate) { var timeout, args, context, timestamp, result; if (null == wait) wait = 100; @@ -653,8 +653,8 @@ }; return debounced; } - debounce3.debounce = debounce3; - module.exports = debounce3; + debounce2.debounce = debounce2; + module.exports = debounce2; } }); @@ -663,16 +663,6 @@ // app/javascript/lib/hotwire-livereload-received.js var import_debounce = __toESM(require_debounce()); - var hotwire_livereload_received_default = (0, import_debounce.default)(({ force_reload }) => { - const onErrorPage = document.title === "Action Controller: Exception caught"; - if (onErrorPage || force_reload) { - console.log("[Hotwire::Livereload] Files changed. Force reloading.."); - document.location.reload(); - } else { - console.log("[Hotwire::Livereload] Files changed. Reloading.."); - Turbo.visit(window.location.href, { action: "replace" }); - } - }, 300); // app/javascript/lib/hotwire-livereload-scroll-position.js var KEY = "hotwire-livereload-scrollPosition"; @@ -696,8 +686,20 @@ } var hotwire_livereload_scroll_position_default = { read, save, restore, reset }; + // app/javascript/lib/hotwire-livereload-received.js + var hotwire_livereload_received_default = (0, import_debounce.default)(({ force_reload }) => { + const onErrorPage = document.title === "Action Controller: Exception caught"; + if (onErrorPage || force_reload) { + console.log("[Hotwire::Livereload] Files changed. Force reloading.."); + document.location.reload(); + } else { + console.log("[Hotwire::Livereload] Files changed. Reloading.."); + hotwire_livereload_scroll_position_default.save(); + Turbo.visit(window.location.href, { action: "replace" }); + } + }, 300); + // app/javascript/hotwire-livereload.js - var import_debounce2 = __toESM(require_debounce()); var consumer = (0, import_actioncable.createConsumer)(); consumer.subscriptions.create("Hotwire::Livereload::ReloadChannel", { received: hotwire_livereload_received_default, @@ -708,19 +710,8 @@ console.log("[Hotwire::Livereload] Websocket disconnected"); } }); - var debouncedScroll = (0, import_debounce2.default)(() => { - if (window.scrollY !== 0) - return hotwire_livereload_scroll_position_default.save(); - setTimeout(() => { - if (window.scrollY !== 0) - return; - hotwire_livereload_scroll_position_default.save(); - }, 1e3); - }, 100); - window.addEventListener("scroll", debouncedScroll); - document.addEventListener("turbo:click", hotwire_livereload_scroll_position_default.reset); - document.addEventListener("turbo:before-visit", hotwire_livereload_scroll_position_default.restore); - document.addEventListener("turbo:load", hotwire_livereload_scroll_position_default.restore); - document.addEventListener("DOMContentLoaded", hotwire_livereload_scroll_position_default.restore); - document.addEventListener("turbo:frame-load", hotwire_livereload_scroll_position_default.restore); + document.addEventListener("turbo:load", () => { + hotwire_livereload_scroll_position_default.restore(); + hotwire_livereload_scroll_position_default.reset(); + }); })(); diff --git a/app/javascript/hotwire-livereload.js b/app/javascript/hotwire-livereload.js index a9ac237..3e580d2 100644 --- a/app/javascript/hotwire-livereload.js +++ b/app/javascript/hotwire-livereload.js @@ -1,7 +1,6 @@ import { createConsumer } from "@rails/actioncable" import received from "./lib/hotwire-livereload-received" import scrollPosition from "./lib/hotwire-livereload-scroll-position" -import debounce from "debounce" const consumer = createConsumer() consumer.subscriptions.create("Hotwire::Livereload::ReloadChannel", { @@ -16,21 +15,8 @@ consumer.subscriptions.create("Hotwire::Livereload::ReloadChannel", { }, }) -const debouncedScroll = debounce(() => { - if (window.scrollY !== 0) return scrollPosition.save(); - - // On a second update, the page mysteriously jumps to the top and sends a scroll event. - // So we wait a bit and if the page is still is at the top, it was likely on purpose. - setTimeout(() => { - if (window.scrollY !== 0) return; - scrollPosition.save(); - }, 1000); -}, 100) -window.addEventListener("scroll", debouncedScroll) - -document.addEventListener("turbo:click", scrollPosition.reset) -document.addEventListener("turbo:before-visit", scrollPosition.restore) -document.addEventListener("turbo:load", scrollPosition.restore) -document.addEventListener("DOMContentLoaded", scrollPosition.restore) -document.addEventListener("turbo:frame-load", scrollPosition.restore) +document.addEventListener("turbo:load", () => { + scrollPosition.restore() + scrollPosition.reset() +}) diff --git a/app/javascript/lib/hotwire-livereload-received.js b/app/javascript/lib/hotwire-livereload-received.js index 8fd7cfa..6aee6da 100644 --- a/app/javascript/lib/hotwire-livereload-received.js +++ b/app/javascript/lib/hotwire-livereload-received.js @@ -1,4 +1,5 @@ import debounce from "debounce" +import scrollPosition from "./hotwire-livereload-scroll-position" export default debounce(({force_reload}) => { const onErrorPage = document.title === "Action Controller: Exception caught" @@ -8,6 +9,7 @@ export default debounce(({force_reload}) => { document.location.reload() } else { console.log("[Hotwire::Livereload] Files changed. Reloading..") + scrollPosition.save() Turbo.visit(window.location.href, { action: 'replace' }) } }, 300) From 4a5a3a44a4a54a9e1905832915b5588437cca8f2 Mon Sep 17 00:00:00 2001 From: Adrien Siami Date: Tue, 28 Nov 2023 09:57:32 +0100 Subject: [PATCH 2/4] Destroy stored position after reset to avoid un-necessary restores --- .../hotwire-livereload-turbo-stream.js | 14 ++++++++------ app/assets/javascripts/hotwire-livereload.js | 18 ++++++++++-------- app/javascript/hotwire-livereload.js | 2 +- .../lib/hotwire-livereload-scroll-position.js | 15 +++++++++------ 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/app/assets/javascripts/hotwire-livereload-turbo-stream.js b/app/assets/javascripts/hotwire-livereload-turbo-stream.js index a3a6e9c..f2c019c 100644 --- a/app/assets/javascripts/hotwire-livereload-turbo-stream.js +++ b/app/assets/javascripts/hotwire-livereload-turbo-stream.js @@ -87,22 +87,24 @@ function read() { const value = localStorage.getItem(KEY); if (!value) - return 0; + return null; return parseInt(value); } function save() { const pos = window.scrollY; localStorage.setItem(KEY, pos.toString()); } - function reset() { - localStorage.setItem(KEY, "0"); + function remove() { + localStorage.removeItem(KEY, "0"); } function restore() { const value = read(); - console.log("[Hotwire::Livereload] Restoring scroll position to", value); - window.scrollTo(0, value); + if (value) { + console.log("[Hotwire::Livereload] Restoring scroll position to", value); + window.scrollTo(0, value); + } } - var hotwire_livereload_scroll_position_default = { read, save, restore, reset }; + var hotwire_livereload_scroll_position_default = { read, save, restore, remove }; // app/javascript/lib/hotwire-livereload-received.js var hotwire_livereload_received_default = (0, import_debounce.default)(({ force_reload }) => { diff --git a/app/assets/javascripts/hotwire-livereload.js b/app/assets/javascripts/hotwire-livereload.js index 68c346a..772f0ec 100644 --- a/app/assets/javascripts/hotwire-livereload.js +++ b/app/assets/javascripts/hotwire-livereload.js @@ -453,7 +453,7 @@ this.subscribe(subscription); return subscription; }; - Subscriptions2.prototype.remove = function remove(subscription) { + Subscriptions2.prototype.remove = function remove2(subscription) { this.forget(subscription); if (!this.findAll(subscription.identifier).length) { this.sendCommand(subscription, "unsubscribe"); @@ -669,22 +669,24 @@ function read() { const value = localStorage.getItem(KEY); if (!value) - return 0; + return null; return parseInt(value); } function save() { const pos = window.scrollY; localStorage.setItem(KEY, pos.toString()); } - function reset() { - localStorage.setItem(KEY, "0"); + function remove() { + localStorage.removeItem(KEY, "0"); } function restore() { const value = read(); - console.log("[Hotwire::Livereload] Restoring scroll position to", value); - window.scrollTo(0, value); + if (value) { + console.log("[Hotwire::Livereload] Restoring scroll position to", value); + window.scrollTo(0, value); + } } - var hotwire_livereload_scroll_position_default = { read, save, restore, reset }; + var hotwire_livereload_scroll_position_default = { read, save, restore, remove }; // app/javascript/lib/hotwire-livereload-received.js var hotwire_livereload_received_default = (0, import_debounce.default)(({ force_reload }) => { @@ -712,6 +714,6 @@ }); document.addEventListener("turbo:load", () => { hotwire_livereload_scroll_position_default.restore(); - hotwire_livereload_scroll_position_default.reset(); + hotwire_livereload_scroll_position_default.remove(); }); })(); diff --git a/app/javascript/hotwire-livereload.js b/app/javascript/hotwire-livereload.js index 3e580d2..cdac474 100644 --- a/app/javascript/hotwire-livereload.js +++ b/app/javascript/hotwire-livereload.js @@ -17,6 +17,6 @@ consumer.subscriptions.create("Hotwire::Livereload::ReloadChannel", { document.addEventListener("turbo:load", () => { scrollPosition.restore() - scrollPosition.reset() + scrollPosition.remove() }) diff --git a/app/javascript/lib/hotwire-livereload-scroll-position.js b/app/javascript/lib/hotwire-livereload-scroll-position.js index 852aeee..2e166a5 100644 --- a/app/javascript/lib/hotwire-livereload-scroll-position.js +++ b/app/javascript/lib/hotwire-livereload-scroll-position.js @@ -2,7 +2,7 @@ const KEY = "hotwire-livereload-scrollPosition" export function read() { const value = localStorage.getItem(KEY) - if (!value) return 0; + if (!value) return null; return parseInt(value) } @@ -11,14 +11,17 @@ export function save() { localStorage.setItem(KEY, pos.toString()) } -export function reset() { - localStorage.setItem(KEY, "0"); +export function remove() { + localStorage.removeItem(KEY, "0"); } export function restore() { const value = read() - console.log("[Hotwire::Livereload] Restoring scroll position to", value) - window.scrollTo(0, value) + if (value) { + console.log("[Hotwire::Livereload] Restoring scroll position to", value) + window.scrollTo(0, value) + } + } -export default { read, save, restore, reset } +export default { read, save, restore, remove } From b3bdbbd52cd71bf90c83d7ce81f2ee196d6be415 Mon Sep 17 00:00:00 2001 From: Adrien S Date: Tue, 28 Nov 2023 10:15:13 +0100 Subject: [PATCH 3/4] Update app/javascript/lib/hotwire-livereload-scroll-position.js Co-authored-by: Kirill Platonov --- app/javascript/lib/hotwire-livereload-scroll-position.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/lib/hotwire-livereload-scroll-position.js b/app/javascript/lib/hotwire-livereload-scroll-position.js index 2e166a5..c73fa7c 100644 --- a/app/javascript/lib/hotwire-livereload-scroll-position.js +++ b/app/javascript/lib/hotwire-livereload-scroll-position.js @@ -12,7 +12,7 @@ export function save() { } export function remove() { - localStorage.removeItem(KEY, "0"); + localStorage.removeItem(KEY) } export function restore() { From 688c980d345d5e16998ecb0132ac87997fbee285 Mon Sep 17 00:00:00 2001 From: Adrien S Date: Tue, 28 Nov 2023 10:15:36 +0100 Subject: [PATCH 4/4] Update app/javascript/lib/hotwire-livereload-scroll-position.js Co-authored-by: Kirill Platonov --- app/javascript/lib/hotwire-livereload-scroll-position.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/lib/hotwire-livereload-scroll-position.js b/app/javascript/lib/hotwire-livereload-scroll-position.js index c73fa7c..8320273 100644 --- a/app/javascript/lib/hotwire-livereload-scroll-position.js +++ b/app/javascript/lib/hotwire-livereload-scroll-position.js @@ -2,7 +2,7 @@ const KEY = "hotwire-livereload-scrollPosition" export function read() { const value = localStorage.getItem(KEY) - if (!value) return null; + if (!value) return return parseInt(value) }