refactor: compile service worker

This commit is contained in:
Azgaar 2022-07-07 01:50:53 +03:00
parent 5e6f599348
commit 392cc24f7c
12 changed files with 491 additions and 263 deletions

View file

@ -8,8 +8,10 @@ export function markFeatures() {
const cells = grid.cells;
const heights = grid.cells.h;
cells.f = new Uint16Array(cells.i.length); // cell feature number
cells.t = new Int8Array(cells.i.length); // cell type: 1 = land coast; -1 = water near coast
grid.features = [0];
for (let i = 1, queue = [0]; queue[0] !== -1; i++) {

View file

@ -7,20 +7,20 @@ import {P} from "utils/probabilityUtils";
import {round} from "utils/stringUtils";
window.OceanLayers = (function () {
let cells, vertices, pointsN, used;
function OceanLayers() {
function render() {
const outline = oceanLayers.attr("layers");
if (outline === "none") return;
TIME && console.time("drawOceanLayers");
const lineGen = d3.line().curve(d3.curveBasisClosed);
(cells = grid.cells), (pointsN = grid.cells.i.length), (vertices = grid.vertices);
const limits = outline === "random" ? randomizeOutline() : outline.split(",").map(s => +s);
const {cells, vertices} = grid;
const pointsN = cells.i.length;
const chains = [];
const opacity = rn(0.4 / limits.length, 2);
used = new Uint8Array(pointsN); // to detect already passed cells
const used = new Uint8Array(pointsN); // to detect already passed cells
for (const i of cells.i) {
const t = cells.t[i];
@ -29,7 +29,7 @@ window.OceanLayers = (function () {
const start = findStart(i, t);
if (!start) continue;
used[i] = 1;
const chain = connectVertices(start, t); // vertices chain to form a path
const chain = connectVertices({cells, vertices, used}, start, t); // vertices chain to form a path
if (chain.length < 4) continue;
const relax = 1 + t * -2; // select only n-th point
const relaxed = chain.filter((v, i) => !(i % relax) || vertices.c[v].some(c => c >= pointsN));
@ -71,7 +71,7 @@ window.OceanLayers = (function () {
}
// connect vertices to chain
function connectVertices(start, t) {
function connectVertices({cells, vertices, used}, start, t) {
const chain = []; // vertices chain to form a path
for (let i = 0, current = start; i === 0 || (current !== start && i < 10000); i++) {
const prev = chain[chain.length - 1]; // previous vertex in chain
@ -94,5 +94,5 @@ window.OceanLayers = (function () {
return chain;
}
return OceanLayers;
return render;
})();

View file

@ -1,5 +1,5 @@
// @ts-ignore
import {checkIfServerless} from "./loading";
import {addOnLoadListener} from "./loading";
import {assignLockBehavior} from "./options/lock";
import {addTooptipListers} from "./tooltips";
import {assignSpeakerBehavior} from "./speaker";
@ -9,12 +9,12 @@ import {addResizeListener} from "modules/ui/options";
import {addDragToUpload} from "modules/io/load";
export function addGlobalListeners() {
checkIfServerless();
if (PRODUCTION) {
registerServiceWorker();
addInstallationPrompt();
addBeforeunloadListener();
}
addOnLoadListener();
assignLockBehavior();
addTooptipListers();
addResizeListener();
@ -25,9 +25,11 @@ export function addGlobalListeners() {
function registerServiceWorker() {
"serviceWorker" in navigator &&
window.addEventListener("load", () => {
navigator.serviceWorker.register("../sw.js").catch(err => {
console.error("ServiceWorker registration failed: ", err);
});
navigator.serviceWorker
.register("/Fantasy-Map-Generator/sw.js", {scope: "/Fantasy-Map-Generator/"})
.catch(err => {
console.error("ServiceWorker registration failed: ", err);
});
});
}

View file

@ -1,92 +1,57 @@
import * as d3 from "d3";
import {ERROR, WARN} from "config/logging";
import {generateMapOnLoad} from "./generation";
import {loadMapFromURL} from "modules/io/load";
import {restoreDefaultEvents} from "scripts/events";
import {ldb} from "scripts/indexedDB";
import {getInputValue} from "utils/nodeUtils";
import {generateMapOnLoad} from "./generation";
export function checkIfServerless() {
export function addOnLoadListener() {
document.on("DOMContentLoaded", async () => {
if (!location.hostname) {
const wiki = "https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Run-FMG-locally";
alertMessage.innerHTML = `Fantasy Map Generator cannot run serverless. Follow the <a href="${wiki}" target="_blank">instructions</a> on how you can
easily run a local web-server`;
$("#alert").dialog({
resizable: false,
title: "Loading error",
width: "28em",
position: {my: "center center-4em", at: "center", of: "svg"},
buttons: {
OK: function () {
$(this).dialog("close");
}
}
});
} else {
hideLoading();
await checkLoadParameters();
}
restoreDefaultEvents(); // apply default viewbox events
await loadOrGenerateMap();
hideLoading();
restoreDefaultEvents();
});
}
// decide which map should be loaded or generated on page load
async function checkLoadParameters() {
const url = new URL(window.location.href);
const params = url.searchParams;
async function loadOrGenerateMap() {
const {searchParams} = new URL(window.location.href);
const maplink = searchParams.get("maplink");
const seed = searchParams.get("seed");
// of there is a valid maplink, try to load .map file from URL
if (params.get("maplink")) {
if (maplink) {
WARN && console.warn("Load map from URL");
const maplink = params.get("maplink");
const pattern = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/;
const valid = pattern.test(maplink);
if (valid) {
setTimeout(() => {
loadMapFromURL(maplink, 1);
}, 1000);
return;
} else showUploadErrorMessage("Map link is not a valid URL", maplink);
const isValidUrl = pattern.test(maplink);
if (!isValidUrl) return showUploadErrorMessage("Map link is not a valid URL", maplink);
setTimeout(() => {
loadMapFromURL(maplink, 1);
}, 1000);
}
// if there is a seed (user of MFCG provided), generate map for it
if (params.get("seed")) {
if (seed) {
WARN && console.warn("Generate map for seed");
await generateMapOnLoad();
return;
}
// open latest map if option is active and map is stored
const loadLastMap = () =>
new Promise((resolve, reject) => {
ldb.get("lastMap", blob => {
if (blob) {
WARN && console.warn("Load last saved map");
try {
uploadMap(blob);
resolve();
} catch (error) {
reject(error);
}
} else {
reject("No map stored");
}
});
});
if (onloadMap.value === "saved") {
if (getInputValue("onloadMap") === "saved") {
try {
await loadLastMap();
return;
} catch (error) {
ERROR && console.error(error);
WARN && console.warn("Cannot load stored map, random map to be generated");
await generateMapOnLoad();
ERROR && console.error("Cannot load stored map, random map to be generated", error);
}
} else {
WARN && console.warn("Generate random map");
await generateMapOnLoad();
}
WARN && console.warn("Generate random map");
await generateMapOnLoad();
}
export function hideLoading() {
@ -100,3 +65,22 @@ export function showLoading() {
d3.select("#optionsContainer").transition().duration(100).style("opacity", 0);
d3.select("#tooltip").transition().duration(200).style("opacity", 0);
}
// open latest map if option is active and map is stored
function loadLastMap() {
return new Promise((resolve, reject) => {
ldb.get("lastMap", blob => {
if (blob) {
WARN && console.warn("Load last saved map");
try {
uploadMap(blob);
resolve();
} catch (error) {
reject(error);
}
} else {
reject("No map stored");
}
});
});
}

View file

@ -1,14 +1,15 @@
importScripts("https://storage.googleapis.com/workbox-cdn/releases/6.2.0/workbox-sw.js");
const {Route, registerRoute} = workbox.routing;
const {CacheFirst, NetworkFirst} = workbox.strategies;
const {CacheableResponsePlugin} = workbox.cacheableResponse;
const {ExpirationPlugin} = workbox.expiration;
import {registerRoute} from "workbox-routing";
import {CacheFirst, NetworkFirst} from "workbox-strategies";
import {CacheableResponsePlugin} from "workbox-cacheable-response";
import {ExpirationPlugin} from "workbox-expiration";
const DAY = 24 * 60 * 60;
const getPolitics = ({entries, days}) => {
return [new CacheableResponsePlugin({statuses: [0, 200]}), new ExpirationPlugin({maxEntries: entries, maxAgeSeconds: days * DAY})];
return [
new CacheableResponsePlugin({statuses: [0, 200]}),
new ExpirationPlugin({maxEntries: entries, maxAgeSeconds: days * DAY})
];
};
registerRoute(
@ -21,7 +22,8 @@ registerRoute(
);
registerRoute(
({request, url}) => request.destination === "script" && !url.pathname.endsWith("min.js") && !url.pathname.includes("versioning.js"),
({request, url}) =>
request.destination === "script" && !url.pathname.endsWith("min.js") && !url.pathname.includes("versioning.js"),
new CacheFirst({
cacheName: "fmg-scripts",
plugins: getPolitics({entries: 100, days: 30})

View file

@ -15,7 +15,7 @@ const c12: Hex[] = [
"#eb8de7"
];
type ColorScheme = (n: number) => string;
type ColorScheme = d3.ScaleSequential<string>;
const colorSchemeMap: Dict<ColorScheme> = {
default: d3.scaleSequential(d3.interpolateRainbow),
bright: d3.scaleSequential(d3.interpolateSpectral),
@ -29,14 +29,14 @@ export function getColors(number: number) {
const colors = d3.shuffle(
d3
.range(number)
.map((index: number) => (index < 12 ? c12[index] : d3.color(scheme((index - 12) / (number - 12)))!.formatHex()))
.map((index: number) => (index < 12 ? c12[index] : d3.color(scheme((index - 12) / (number - 12))!)!.formatHex()))
);
return colors;
}
export function getRandomColor(): Hex {
const rgb = colorSchemeMap.default(Math.random());
return d3.color(rgb)!.formatHex() as Hex;
const rgb = colorSchemeMap.default(Math.random())!;
return d3.color(rgb)?.formatHex() as Hex;
}
// mix a color with a random color