From 197ef0197acef254463687cce629edfe3c68076c Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Wed, 19 Jul 2017 05:23:06 +0200 Subject: [PATCH] Implemented full page diffs --- scripts/AnimeNotifier.ts | 50 +++++++++++++++++++++++++++++++++------- scripts/Application.ts | 3 --- scripts/Diff.ts | 13 +++++++++++ 3 files changed, 55 insertions(+), 11 deletions(-) diff --git a/scripts/AnimeNotifier.ts b/scripts/AnimeNotifier.ts index fbdb4655..d44ce36c 100644 --- a/scripts/AnimeNotifier.ts +++ b/scripts/AnimeNotifier.ts @@ -108,9 +108,6 @@ export class AnimeNotifier { // Let"s start this.app.run() - // Service worker - this.registerServiceWorker() - // Push manager this.pushManager = new PushManager() } @@ -158,8 +155,13 @@ export class AnimeNotifier { } onIdle() { + // Service worker + this.registerServiceWorker() + + // Analytics this.pushAnalytics() + // Offline message if(navigator.onLine === false) { this.statusMessage.showError("You are viewing an offline version of the site now.") } @@ -170,6 +172,8 @@ export class AnimeNotifier { return } + console.log("register service worker") + navigator.serviceWorker.register("/service-worker").then(registration => { registration.update() }) @@ -178,7 +182,7 @@ export class AnimeNotifier { this.onServiceWorkerMessage(evt) }) - document.addEventListener("DOMContentLoaded", () => { + let sendContentLoadedEvent = () => { if(!navigator.serviceWorker.controller) { return } @@ -194,8 +198,18 @@ export class AnimeNotifier { message.url = window.location.href } + console.log("send loaded event to service worker") + navigator.serviceWorker.controller.postMessage(JSON.stringify(message)) - }) + } + + // For future loaded events + document.addEventListener("DOMContentLoaded", sendContentLoadedEvent) + + // If the page is loaded already, send the loaded event right now. + if(document.readyState !== "loading") { + sendContentLoadedEvent() + } } onServiceWorkerMessage(evt: ServiceWorkerMessageEvent) { @@ -307,7 +321,6 @@ export class AnimeNotifier { return Promise.reject("old request") } - this.app.eTag = response.headers.get("ETag") return Promise.resolve(response) }) .then(response => response.text()) @@ -316,7 +329,29 @@ export class AnimeNotifier { } reloadPage() { - location.reload() + console.log("reload page") + + let headers = new Headers() + headers.append("X-Reload", "true") + + let path = this.app.currentPath + + return fetch(path, { + credentials: "same-origin", + headers + }) + .then(response => { + if(this.app.currentPath !== path) { + return Promise.reject("old request") + } + + return Promise.resolve(response) + }) + .then(response => response.text()) + .then(html => { + Diff.root(document.documentElement, html) + }) + .then(() => this.app.emit("DOMContentLoaded")) } loading(isLoading: boolean) { @@ -477,7 +512,6 @@ export class AnimeNotifier { credentials: "same-origin" }) .then(response => { - this.app.eTag = response.headers.get("ETag") return response.text() }) diff --git a/scripts/Application.ts b/scripts/Application.ts index 3e041285..4f4057cd 100644 --- a/scripts/Application.ts +++ b/scripts/Application.ts @@ -13,7 +13,6 @@ export class Application { loading: HTMLElement currentPath: string originalPath: string - eTag: string lastRequest: XMLHttpRequest constructor() { @@ -46,8 +45,6 @@ export class Application { request.onerror = () => reject(new Error("You are either offline or the requested page doesn't exist.")) request.ontimeout = () => reject(new Error("The page took too much time to respond.")) request.onload = () => { - this.eTag = request.getResponseHeader("ETag") - if(request.status < 200 || request.status >= 400) reject(request.responseText) else diff --git a/scripts/Diff.ts b/scripts/Diff.ts index 6fa223c0..e26ca35c 100644 --- a/scripts/Diff.ts +++ b/scripts/Diff.ts @@ -3,6 +3,7 @@ export class Diff { // Reuse container for diffs to avoid memory allocation static container: HTMLElement + static rootContainer: HTMLElement // innerHTML will diff the element with the given HTML string and apply DOM mutations. static innerHTML(aRoot: HTMLElement, html: string) { @@ -14,6 +15,18 @@ export class Diff { Diff.childNodes(aRoot, Diff.container) } + // root will diff the document root element with the given HTML string and apply DOM mutations. + static root(aRoot: HTMLElement, html: string) { + if(!Diff.rootContainer) { + Diff.rootContainer = document.createElement("html") + } + + Diff.rootContainer.innerHTML = html.replace("", "") + + console.log(Diff.rootContainer) + Diff.childNodes(aRoot, Diff.rootContainer) + } + // childNodes diffs the child nodes of 2 given elements and applies DOM mutations. static childNodes(aRoot: Node, bRoot: Node) { let aChild = [...aRoot.childNodes]