From 84dba895899d372f69912ddd2c34867412705003 Mon Sep 17 00:00:00 2001 From: Hans5958 Date: Wed, 13 Sep 2023 19:43:24 +0700 Subject: [PATCH 01/37] Fix top margin addition when announcement shown --- web/_css/style.css | 6 ++++++ web/_js/main/main.js | 6 ++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/web/_css/style.css b/web/_css/style.css index 93e383da2..30662ca45 100644 --- a/web/_css/style.css +++ b/web/_css/style.css @@ -448,6 +448,12 @@ body:not([data-dev]) .show-only-on-dev { display: none !important } +#objectsList, +#offcanvasList, +#offcanvasDraw { + margin-top: var(--global-top-padding); +} + /* about.html */ #credits a { diff --git a/web/_js/main/main.js b/web/_js/main/main.js index 180b3cdef..f7076c8ef 100644 --- a/web/_js/main/main.js +++ b/web/_js/main/main.js @@ -528,10 +528,12 @@ const announcementText = announcementEl.querySelector('p').textContent.trim() if (announcementText && announcementText !== window.localStorage.getItem('announcement-closed')) { announcementButton.click() - document.querySelector('#objectsList').style.marginTop = '2.8rem' + setTimeout(() => { + document.body.style.setProperty("--global-top-padding", announcementEl.offsetHeight + 'px') + }, 500) } announcementEl.querySelector('[role=button]').addEventListener('click', () => { window.localStorage.setItem('announcement-closed', announcementText) - document.querySelector('#objectsList').style.marginTop = '0' + document.body.style.setProperty("--global-top-padding", null) }) From e56ca078dd01549b043997eb89e9319a536ff4fc Mon Sep 17 00:00:00 2001 From: Hans5958 Date: Wed, 13 Sep 2023 19:48:01 +0700 Subject: [PATCH 02/37] Rename announcement system to notice system --- web/_js/main/main.js | 23 ++++++++++++++--------- web/index.html | 4 ++-- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/web/_js/main/main.js b/web/_js/main/main.js index f7076c8ef..63b6af0b6 100644 --- a/web/_js/main/main.js +++ b/web/_js/main/main.js @@ -520,20 +520,25 @@ function generateAtlasAll(atlas = atlasAll) { return newAtlas } -// Announcement system +// Notice system -const announcementEl = document.querySelector("#headerAnnouncement") -const announcementButton = announcementEl.querySelector('[role=button]') -const announcementText = announcementEl.querySelector('p').textContent.trim() +const noticeEl = document.querySelector("#headerNotice") +const noticeButton = noticeEl.querySelector('[role=button]') +const noticeText = noticeEl.querySelector('p').textContent.trim() -if (announcementText && announcementText !== window.localStorage.getItem('announcement-closed')) { - announcementButton.click() +if (window.localStorage.getItem('announcement-closed')) { + window.localStorage.setItem('closed-notice', window.localStorage.getItem('announcement-closed')) + window.localStorage.removeItem('announcement-closed') +} + +if (noticeText && noticeText !== window.localStorage.getItem('closed-notice')) { + noticeButton.click() setTimeout(() => { - document.body.style.setProperty("--global-top-padding", announcementEl.offsetHeight + 'px') + document.body.style.setProperty("--global-top-padding", noticeEl.offsetHeight + 'px') }, 500) } -announcementEl.querySelector('[role=button]').addEventListener('click', () => { - window.localStorage.setItem('announcement-closed', announcementText) +noticeEl.querySelector('[role=button]').addEventListener('click', () => { + window.localStorage.setItem('closed-notice', noticeText) document.body.style.setProperty("--global-top-padding", null) }) diff --git a/web/index.html b/web/index.html index 294e7cf7c..5f976050e 100644 --- a/web/index.html +++ b/web/index.html @@ -114,11 +114,11 @@
-
diff --git a/web/index.html b/web/index.html index 5f976050e..4223f8271 100644 --- a/web/index.html +++ b/web/index.html @@ -1,7 +1,7 @@ @@ -11,7 +11,7 @@ The 2023 r/place Atlas - + @@ -26,7 +26,6 @@ - @@ -82,7 +81,7 @@ }, { "@type": "Organization", - "name": "Place Atlas", + "name": "Place Atlas Initiative", "alternateName": "r/placeAtlas2023", "url": "https://github.com/placeAtlas", "image": "http://2023.place-atlas.stefanocoding.me/_img/logo.png", @@ -271,7 +270,7 @@
Atlas Entries List
- Code by Place Atlas. Source on GitHub. Site powered by Netlify. + Code by Place Atlas Initiative. Source on GitHub. Site powered by Netlify.
From ea084fd1620c92b42d0337404e95bc7fbde213d8 Mon Sep 17 00:00:00 2001 From: Hans5958 Date: Wed, 13 Sep 2023 20:02:29 +0700 Subject: [PATCH 04/37] Make #author grow less --- web/_css/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/_css/style.css b/web/_css/style.css index e90ffa7da..2176c6e3a 100644 --- a/web/_css/style.css +++ b/web/_css/style.css @@ -262,7 +262,7 @@ body[data-init-done] .listTransitioning #innerContainer { } #author { - flex: 1 1 auto; + flex: 0.5 1 auto; } #variantControls { From 90ab062585cb57861c35135228194d44ef5c7a36 Mon Sep 17 00:00:00 2001 From: Hans5958 Date: Wed, 13 Sep 2023 20:41:17 +0700 Subject: [PATCH 05/37] Few fixes on meta tags --- web/index.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/index.html b/web/index.html index 4223f8271..4355be0c8 100644 --- a/web/index.html +++ b/web/index.html @@ -12,7 +12,7 @@ The 2023 r/place Atlas - + @@ -22,7 +22,7 @@ - + @@ -84,7 +84,7 @@ "name": "Place Atlas Initiative", "alternateName": "r/placeAtlas2023", "url": "https://github.com/placeAtlas", - "image": "http://2023.place-atlas.stefanocoding.me/_img/logo.png", + "image": "https://place-atlas.stefanocoding.me/assets/logo.png", "founder": { "@type": "Person", "@id": "#Codixer", From cd945e0d59e52d2eef61a021b43e17993c03e6d0 Mon Sep 17 00:00:00 2001 From: Hans5958 Date: Fri, 15 Sep 2023 22:08:18 +0700 Subject: [PATCH 06/37] Add support for TemplateManager Resolves #290 --- web/_js/main/main.js | 11 +++++++ web/_js/main/time.js | 36 +++++++++++++++++++-- web/_js/main/view.js | 74 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 2 deletions(-) diff --git a/web/_js/main/main.js b/web/_js/main/main.js index 553025b14..47423ef63 100644 --- a/web/_js/main/main.js +++ b/web/_js/main/main.js @@ -100,6 +100,17 @@ async function init() { } } + // Experimental: TemplateManager support + // Add a .json file of TemplateManager on the "template" URL param. + // e.g. ?template=https://osu.place/e/osuplace2023.json + // CORS bypass is required (e.g. a proxy, CORS Anywhere). + if (params.get("template")) { + const [ templateDatas ] = await loadTemplateData(params.get("template")) + const templateLayers = await loadTemplateImages(templateDatas) + additionalLayers.push(...templateLayers) + updateAdditionalLayer(additionalLayers) + } + if (mode === "about") window.location.replace("./about.html") // For Reviewing Reddit Changes diff --git a/web/_js/main/time.js b/web/_js/main/time.js index 7620cd4c4..9ddb01e4f 100644 --- a/web/_js/main/time.js +++ b/web/_js/main/time.js @@ -35,6 +35,9 @@ window.currentPeriod = currentPeriod let atlasDisplay = {} window.atlasDisplay = atlasDisplay +const additionalLayers = [] +const additionalLayerCanvas = document.createElement('canvas') + // SETUP if (variationsConfig[currentVariation].versions.length === 1) bottomBar.classList.add('no-time-slider') @@ -131,13 +134,21 @@ async function updateBackground(newPeriod = currentPeriod, newVariation = curren } })) - if (currentUpdateIndex !== myUpdateIndex) { + if (myAbortController.signal.aborted || newPeriod !== currentPeriod || newVariation !== currentVariation || currentUpdateIndex !== myUpdateIndex) { return false } - + for (const imageLayer of layers) { context.drawImage(imageLayer, 0, 0) } + + context.drawImage(additionalLayerCanvas, 0, 0) + + if (myAbortController.signal.aborted || newPeriod !== currentPeriod || newVariation !== currentVariation || currentUpdateIndex !== myUpdateIndex) { + return false + } + + if (currentUpdateIndex !== myUpdateIndex) return [configObject, newPeriod, newVariation] const blob = await new Promise(resolve => canvas.toBlob(resolve)) canvasUrl = URL.createObjectURL(blob) image.src = canvasUrl @@ -402,3 +413,24 @@ function getNearestPeriod(entry, targetPeriod, targetVariation) { return [ nearestPeriod, nearestVariation, nearestKey ] } + +const updateAdditionalLayer = () => { + const layers = additionalLayers + const canvas = additionalLayerCanvas + const context = additionalLayerCanvas.getContext('2d') + canvas.width = 0 + canvas.height = 0 + + + for (const layer of layers) { + if (!layer.imageLayer) continue + canvas.width = Math.max(layer.x + layer.imageLayer.width, canvas.width) + canvas.height = Math.max(layer.y + layer.imageLayer.height, canvas.height) + } + + for (const layer of layers) { + if (!layer.imageLayer) continue + context.drawImage(layer.imageLayer, layer.x, layer.y) + console.log(layer.imageLayer) + } +} diff --git a/web/_js/main/view.js b/web/_js/main/view.js index b1be1ff4e..dea84516e 100644 --- a/web/_js/main/view.js +++ b/web/_js/main/view.js @@ -837,3 +837,77 @@ function initViewGlobal() { drawButton.href = "./?mode=draw" + formatHash(null, event.detail.period, event.detail.variation) }) } + + +async function loadTemplateData(initUrl, datas, blacklistUrls, level = 0) { + datas ??= {} + blacklistUrls ??= new Set() + + if (datas[initUrl] || blacklistUrls.has(initUrl)) return [ datas, blacklistUrls ] + + datas[initUrl] = {} + + try { + const data = await (await fetch(initUrl)).json() + datas[initUrl] = data + for (const blacklisted of data?.blacklist) { + blacklistUrls.add(blacklisted.url) + } + await Promise.all(data?.whitelist.map(async wl => { + const [ wlDatas, wlBlacklistUrls ] = await loadTemplateData(wl.url, datas, blacklistUrls, level + 1) + Object.assign(datas, wlDatas) + blacklistUrls.add(...wlBlacklistUrls) + })) + } catch (e) {} + + return [ datas, [...blacklistUrls] ] +} + +async function loadTemplateImages(datas) { + + const templates = [] + + for (const data of Object.values(datas)) { + if (!data?.templates) continue + for (const template of data?.templates) { + templates.push(template) + } + } + + await Promise.all(templates.map(async (template, i) => { + + if (!template.sources) return + + for (const source of template.sources) { + try { + const sourceResponse = await (await fetch(source)).blob() + template.blob = URL.createObjectURL(sourceResponse) + break + } catch (e) {} + } + delete template.sources + + if (!template.blob) return + + const imageLayer = new Image() + await new Promise(resolve => { + imageLayer.onload = () => { + template.imageLayer = imageLayer + delete template.blob + resolve() + } + imageLayer.onerror = () => { + delete template + resolve() + } + imageLayer.src = template.blob + }) + })) + + for (const layer of templates) { + if (!layer.imageLayer) delete layer + } + + return templates + +} From a74668083a98d16741a0b90a167832eeec5ca9e8 Mon Sep 17 00:00:00 2001 From: Hans5958 Date: Sun, 24 Sep 2023 00:31:48 +0700 Subject: [PATCH 07/37] Adjust canvas caching - Change back to CacheFirst strategy - Extend Cache-Control to 4 weeks to match SW cache - Capitalize Cache-Control --- web/_headers | 4 ++-- web/sw.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/web/_headers b/web/_headers index 881b275a5..af96640e7 100644 --- a/web/_headers +++ b/web/_headers @@ -2,7 +2,7 @@ Access-Control-Allow-Origin: * /_img/canvas/*/*.png - cache-control: public, max-age=604800 + Cache-Control: public, max-age=2419200 /_img/canvas/*.png - cache-control: public, max-age=604800 + Cache-Control: public, max-age=2419200 diff --git a/web/sw.js b/web/sw.js index 7def25167..eff8f8b55 100644 --- a/web/sw.js +++ b/web/sw.js @@ -24,7 +24,7 @@ workbox.routing.registerRoute( workbox.routing.registerRoute( ({ url }) => url.pathname.startsWith('/_img/canvas/'), - new workbox.strategies.StaleWhileRevalidate({ + new workbox.strategies.CacheFirst({ cacheName: "canvas", plugins: [ new workbox.backgroundSync.BackgroundSyncPlugin( From f9bf7c700a271ad3b6b803e21da5e70cb8eff27e Mon Sep 17 00:00:00 2001 From: Hans5958 Date: Sun, 24 Sep 2023 09:36:37 +0700 Subject: [PATCH 08/37] Adjust canvas caching (2) - Add Cache-Control for /_js/ and /_css/ - Remove background sync when caching canvas - Extend caching to 1 year for canvas and 4 weeks for other resources - Add and remove comments --- web/_headers | 22 ++++++++++++++++++---- web/sw.js | 17 ++++++----------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/web/_headers b/web/_headers index af96640e7..eb2d8ad12 100644 --- a/web/_headers +++ b/web/_headers @@ -1,8 +1,22 @@ /* Access-Control-Allow-Origin: * - -/_img/canvas/*/*.png - Cache-Control: public, max-age=2419200 + Cache-Control: public + +# Hashed resources: 4 weeks + +/_js/* + Cache-Control: immutable, max-age=2419200 + +/_css/* + Cache-Control: immutable, max-age=2419200 + +# Canvas images: 1 year + +/_img/canvas/* + Cache-Control: max-age=31536000 /_img/canvas/*.png - Cache-Control: public, max-age=2419200 + Cache-Control: max-age=31536000 + +/_img/canvas/*/*.png + Cache-Control: max-age=31536000 diff --git a/web/sw.js b/web/sw.js index eff8f8b55..fcc904445 100644 --- a/web/sw.js +++ b/web/sw.js @@ -1,5 +1,3 @@ -// This is the "Offline copy of assets" service worker - importScripts('https://cdn.jsdelivr.net/npm/workbox-sw@6.5.4/build/workbox-sw.js'); self.addEventListener("message", event => { @@ -10,12 +8,14 @@ self.addEventListener("message", event => { workbox.routing.registerRoute( ({ url }) => {!url.pathname.startsWith('/_img/canvas/')}, + // `workbox.strategies.StaleWhileRevalidate` is used to reduce server contact. + // Change to `workbox.strategies.NetworkFirst` when updating is required. new workbox.strategies.NetworkFirst({ cacheName: "main", plugins: [ new workbox.backgroundSync.BackgroundSyncPlugin( "main-queue", { - maxRetentionTime: 24 * 60 // 24 hours (in minutes) + maxRetentionTime: 4 * 7 * 24 * 60 // 4 weeks (in minutes) } ) ] @@ -24,14 +24,9 @@ workbox.routing.registerRoute( workbox.routing.registerRoute( ({ url }) => url.pathname.startsWith('/_img/canvas/'), + // `workbox.strategies.CacheFirst` is used to reduce server contact. + // Change to `workbox.strategies.StateWhileRevalidate` when updating is required. new workbox.strategies.CacheFirst({ - cacheName: "canvas", - plugins: [ - new workbox.backgroundSync.BackgroundSyncPlugin( - "canvas-queue", { - maxRetentionTime: 4 * 7 * 24 * 60 // 4 weeks (in minutes) - } - ) - ] + cacheName: "canvas" }) ); \ No newline at end of file From daea59f2de39e2e0b2862527345018a67804ef4d Mon Sep 17 00:00:00 2001 From: Hans5958 Date: Sun, 24 Sep 2023 09:44:45 +0700 Subject: [PATCH 09/37] Adjust canvas caching (3) - Prefetch atlas.json - Cache hashed resources to one year --- web/_headers | 13 ++++++------- web/index.html | 1 + 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/web/_headers b/web/_headers index eb2d8ad12..ed8d9f92c 100644 --- a/web/_headers +++ b/web/_headers @@ -1,22 +1,21 @@ /* Access-Control-Allow-Origin: * - Cache-Control: public -# Hashed resources: 4 weeks +# Hashed resources: 1 year and immutable /_js/* - Cache-Control: immutable, max-age=2419200 + Cache-Control: public, immutable, max-age=31536000 /_css/* - Cache-Control: immutable, max-age=2419200 + Cache-Control: public, immutable, max-age=31536000 # Canvas images: 1 year /_img/canvas/* - Cache-Control: max-age=31536000 + Cache-Control: public, max-age=31536000 /_img/canvas/*.png - Cache-Control: max-age=31536000 + Cache-Control: public, max-age=31536000 /_img/canvas/*/*.png - Cache-Control: max-age=31536000 + Cache-Control: public, max-age=31536000 diff --git a/web/index.html b/web/index.html index 4355be0c8..511bc5ae1 100644 --- a/web/index.html +++ b/web/index.html @@ -50,6 +50,7 @@ + -