From d50ba892e6781fdad9285cd588712d2a653adbc6 Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Fri, 20 Oct 2017 02:43:02 +0200 Subject: [PATCH] CSS and SW cleanup --- pages/animelist/animelist.scarlet | 2 +- scripts/AnimeNotifier.ts | 94 +++--------------------------- scripts/ServiceWorkerManager.ts | 96 +++++++++++++++++++++++++++++++ styles/include/config.scarlet | 2 +- styles/sidebar.scarlet | 6 +- styles/status-message.scarlet | 2 +- styles/widgets.scarlet | 2 +- sw/service-worker.ts | 59 +++++++++++-------- 8 files changed, 148 insertions(+), 115 deletions(-) create mode 100644 scripts/ServiceWorkerManager.ts diff --git a/pages/animelist/animelist.scarlet b/pages/animelist/animelist.scarlet index 59310476..76910ce7 100644 --- a/pages/animelist/animelist.scarlet +++ b/pages/animelist/animelist.scarlet @@ -38,7 +38,7 @@ :hover .plus-episode opacity 1 - pointer-events all + pointer-events auto .anime-list-item-episodes-watched flex 0.4 diff --git a/scripts/AnimeNotifier.ts b/scripts/AnimeNotifier.ts index 81f07c5f..46c2bc33 100644 --- a/scripts/AnimeNotifier.ts +++ b/scripts/AnimeNotifier.ts @@ -1,6 +1,3 @@ -import * as actions from "./Actions" -import { displayAiringDate, displayDate } from "./DateView" -import { findAll, delay, canUseWebP, swapElements } from "./Utils" import { Application } from "./Application" import { Diff } from "./Diff" import { MutationQueue } from "./MutationQueue" @@ -10,6 +7,10 @@ import { TouchController } from "./TouchController" import { Analytics } from "./Analytics" import { SideBar } from "./SideBar" import { InfiniteScroller } from "./InfiniteScroller" +import { ServiceWorkerManager } from "./ServiceWorkerManager" +import { displayAiringDate, displayDate } from "./DateView" +import { findAll, delay, canUseWebP, swapElements } from "./Utils" +import * as actions from "./Actions" export class AnimeNotifier { app: Application @@ -21,6 +22,7 @@ export class AnimeNotifier { statusMessage: StatusMessage visibilityObserver: IntersectionObserver pushManager: PushManager + serviceWorkerManager: ServiceWorkerManager touchController: TouchController sideBar: SideBar infiniteScroller: InfiniteScroller @@ -122,6 +124,9 @@ export class AnimeNotifier { // Push manager this.pushManager = new PushManager() + // Service worker + this.serviceWorkerManager = new ServiceWorkerManager(this, "/service-worker") + // Analytics this.analytics = new Analytics() @@ -164,7 +169,7 @@ export class AnimeNotifier { onIdle() { // Service worker - this.registerServiceWorker() + this.serviceWorkerManager.register() // Analytics if(this.user) { @@ -177,87 +182,6 @@ export class AnimeNotifier { } } - registerServiceWorker() { - if(!("serviceWorker" in navigator)) { - return - } - - console.log("register service worker") - - navigator.serviceWorker.register("/service-worker").then(registration => { - // registration.update() - }) - - navigator.serviceWorker.addEventListener("message", evt => { - this.onServiceWorkerMessage(evt) - }) - - // This will send a message to the service worker that the DOM has been loaded - let sendContentLoadedEvent = () => { - if(!navigator.serviceWorker.controller) { - return - } - - // A reloadContent call should never trigger another reload - if(this.app.currentPath === this.lastReloadContentPath) { - console.log("reload finished.") - this.lastReloadContentPath = "" - return - } - - let message = { - type: "loaded", - url: "" - } - - // If mainPageLoaded is set, it means every single request is now an AJAX request for the /_/ prefixed page - if(this.mainPageLoaded) { - message.url = window.location.origin + "/_" + window.location.pathname - } else { - this.mainPageLoaded = true - message.url = window.location.href - } - - console.log("checking for updates:", message.url) - - 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) { - let message = JSON.parse(evt.data) - - switch(message.type) { - case "new content": - if(message.url.includes("/_/")) { - // Content reload - this.contentLoadedActions.then(() => { - this.reloadContent(true) - }) - } else { - // Full page reload - this.contentLoadedActions.then(() => { - this.reloadPage() - }) - } - - break - - case "reload page": - console.log("service worker instructed to reload page...disobeying in test mode") - // location.reload(true) - break - } - } - dragAndDrop() { for(let element of findAll("inventory-slot")) { // Skip elements that have their event listeners attached already diff --git a/scripts/ServiceWorkerManager.ts b/scripts/ServiceWorkerManager.ts new file mode 100644 index 00000000..a7d9d60c --- /dev/null +++ b/scripts/ServiceWorkerManager.ts @@ -0,0 +1,96 @@ +import { AnimeNotifier } from "./AnimeNotifier" + +export class ServiceWorkerManager { + arn: AnimeNotifier + uri: string + + constructor(arn: AnimeNotifier, uri: string) { + this.arn = arn + this.uri = uri + } + + register() { + if(!("serviceWorker" in navigator)) { + return + } + + console.log("register service worker") + + navigator.serviceWorker.register(this.uri).then(registration => { + // registration.update() + }) + + navigator.serviceWorker.addEventListener("message", evt => { + this.onMessage(evt) + }) + + // This will send a message to the service worker that the DOM has been loaded + let sendContentLoadedEvent = () => { + if(!navigator.serviceWorker.controller) { + return + } + + // A reloadContent call should never trigger another reload + if(this.arn.app.currentPath === this.arn.lastReloadContentPath) { + console.log("reload finished.") + this.arn.lastReloadContentPath = "" + return + } + + let message = { + type: "loaded", + url: "" + } + + // If mainPageLoaded is set, it means every single request is now an AJAX request for the /_/ prefixed page + if(this.arn.mainPageLoaded) { + message.url = window.location.origin + "/_" + window.location.pathname + } else { + this.arn.mainPageLoaded = true + message.url = window.location.href + } + + console.log("checking for updates:", message.url) + + this.postMessage(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() + } + } + + postMessage(message: any) { + navigator.serviceWorker.controller.postMessage(JSON.stringify(message)) + } + + onMessage(evt: ServiceWorkerMessageEvent) { + let message = JSON.parse(evt.data) + + switch(message.type) { + case "new content": + if(message.url.includes("/_/")) { + // Content reload + this.arn.contentLoadedActions.then(() => { + this.arn.reloadContent(true) + }) + } else { + // Full page reload + this.arn.contentLoadedActions.then(() => { + this.arn.reloadPage() + }) + } + + break + + case "reload page": + console.log("service worker instructed to reload page...disobeying in test mode") + // location.reload(true) + break + } + } +} \ No newline at end of file diff --git a/styles/include/config.scarlet b/styles/include/config.scarlet index 3e60fc87..6750fb15 100644 --- a/styles/include/config.scarlet +++ b/styles/include/config.scarlet @@ -11,7 +11,7 @@ pro-color = hsla(0, 100%, 73%, 0.87) ui-border-color = rgba(0, 0, 0, 0.1) ui-border = 1px solid ui-border-color ui-hover-border-color = rgba(0, 0, 0, 0.15) -ui-hover-border-color = 1px solid ui-hover-border-color +ui-hover-border = 1px solid ui-hover-border-color ui-background = rgb(254, 254, 254) // ui-hover-background = rgb(254, 254, 254) // ui-background = linear-gradient(to bottom, rgba(0, 0, 0, 0.02) 0%, rgba(0, 0, 0, 0.037) 100%) diff --git a/styles/sidebar.scarlet b/styles/sidebar.scarlet index 856a493b..3671d382 100644 --- a/styles/sidebar.scarlet +++ b/styles/sidebar.scarlet @@ -16,7 +16,7 @@ sidebar-spacing-y = 0.7rem pointer-events none box-shadow shadow-medium transition opacity transition-speed ease, transform transition-speed ease - will-change opacity transition + will-change opacity, transition .user-image-container horizontal @@ -29,14 +29,14 @@ sidebar-spacing-y = 0.7rem opacity 1 transform none position static - pointer-events all + pointer-events auto box-shadow none border-right ui-border background rgba(0, 0, 0, 0.03) .sidebar-visible transform translateX(0) !important - pointer-events all !important + pointer-events auto !important opacity 1 !important .sidebar-link diff --git a/styles/status-message.scarlet b/styles/status-message.scarlet index f7938bc8..d433119b 100644 --- a/styles/status-message.scarlet +++ b/styles/status-message.scarlet @@ -14,7 +14,7 @@ .status-message-action color white !important - pointer-events all !important + pointer-events auto !important .error-message color white diff --git a/styles/widgets.scarlet b/styles/widgets.scarlet index abbbecfe..d3fe8f3f 100644 --- a/styles/widgets.scarlet +++ b/styles/widgets.scarlet @@ -34,7 +34,7 @@ .widget-ui-element vertical-wrap ui-element - transition border transition-speed ease, background transition-speed ease, transform transition-speed ease, transform color ease + transition border transition-speed ease, background transition-speed ease, transform transition-speed ease, color transition-speed ease margin-bottom 1rem padding 0.5rem 1rem width 100% diff --git a/sw/service-worker.ts b/sw/service-worker.ts index 441ea201..701fa408 100644 --- a/sw/service-worker.ts +++ b/sw/service-worker.ts @@ -151,29 +151,23 @@ class MyServiceWorker { onMessage(evt: any) { let message = JSON.parse(evt.data) - - let url = message.url + + switch(message.type) { + case "loaded": + this.onDOMContentLoaded(evt, message.url) + break + } + } + + // onDOMContentLoaded is called when the client sent this service worker + // a message that the page has been loaded. + onDOMContentLoaded(evt: any, url: string) { let refresh = RELOADS.get(url) let servedETag = ETAGS.get(url) // If the user requests a sub-page we should prefetch the full page, too. if(url.includes("/_/")) { - let fullPage = new Request(url.replace("/_/", "/")) - - let fullPageRefresh = fetch(fullPage, { - credentials: "same-origin" - }).then(response => { - // Save the new version of the resource in the cache - let cacheRefresh = caches.open(this.cache.version).then(cache => { - return cache.put(fullPage, response) - }) - - CACHEREFRESH.set(fullPage.url, cacheRefresh) - return response - }) - - // Save in map - RELOADS.set(fullPage.url, fullPageRefresh) + this.prefetchFullPage(url) } if(!refresh || !servedETag) { @@ -181,13 +175,13 @@ class MyServiceWorker { } return refresh.then((response: Response) => { - // If the fresh copy was used to serve the request instead of the cache, - // we don"t need to tell the client to do a refresh. + // When the actual network request was used by the client, response.bodyUsed is set. + // In that case the client is already up to date and we don"t need to tell the client to do a refresh. if(response.bodyUsed) { return } - // Get ETag + // Get the ETag of the cached response we sent to the client earlier. let eTag = response.headers.get("ETag") // Update ETag @@ -197,6 +191,7 @@ class MyServiceWorker { let oldCSP = this.currentCSP let csp = response.headers.get("Content-Security-Policy") + // If the CSP and therefore the sha-1 hash of the CSS changed, we need to do a reload. if(csp != oldCSP) { this.currentCSP = csp @@ -206,7 +201,6 @@ class MyServiceWorker { } // If the ETag changed, we need to do a reload. - // If the CSP and therefore the sha-1 hash of the CSS changed, we need to do a reload. if(eTag !== servedETag) { return this.forceClientReloadContent(url, evt.source) } @@ -216,6 +210,25 @@ class MyServiceWorker { }) } + prefetchFullPage(url: string) { + let fullPage = new Request(url.replace("/_/", "/")) + + let fullPageRefresh = fetch(fullPage, { + credentials: "same-origin" + }).then(response => { + // Save the new version of the resource in the cache + let cacheRefresh = caches.open(this.cache.version).then(cache => { + return cache.put(fullPage, response) + }) + + CACHEREFRESH.set(fullPage.url, cacheRefresh) + return response + }) + + // Save in map + RELOADS.set(fullPage.url, fullPageRefresh) + } + onPush(evt: PushEvent) { var payload = evt.data ? evt.data.json() : {} @@ -320,7 +333,7 @@ class MyServiceWorker { return cache.addAll([ "./", "./scripts", - "https://fonts.gstatic.com/s/ubuntu/v10/2Q-AW1e_taO6pHwMXcXW5w.ttf" + "https://fonts.gstatic.com/s/ubuntu/v11/4iCs6KVjbNBYlgoKfw7z.ttf" ]) }) }