mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-22 03:51:23 +01:00
feat: streamline saving options
This commit is contained in:
parent
2424c66475
commit
5300b997b3
7 changed files with 104 additions and 69 deletions
27
index.html
27
index.html
|
|
@ -1775,6 +1775,18 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<tr data-tip="Set what Generator should do on load">
|
||||||
|
<td></td>
|
||||||
|
<td>Onload behavior</td>
|
||||||
|
<td>
|
||||||
|
<select id="onloadBehavior" data-stored="onloadBehavior">
|
||||||
|
<option value="random" selected>Generate random map</option>
|
||||||
|
<option value="lastSaved">Open last saved map</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr data-tip="Select speech synthesis voice to pronounce generated names">
|
<tr data-tip="Select speech synthesis voice to pronounce generated names">
|
||||||
<td></td>
|
<td></td>
|
||||||
<td>Speaker voice</td>
|
<td>Speaker voice</td>
|
||||||
|
|
@ -5884,17 +5896,13 @@
|
||||||
<div id="saveMapData" style="display: none" class="dialog">
|
<div id="saveMapData" style="display: none" class="dialog">
|
||||||
<div style="margin-top: 0.3em">
|
<div style="margin-top: 0.3em">
|
||||||
<strong>Save map to</strong>
|
<strong>Save map to</strong>
|
||||||
<button onclick="downloadMap()" data-tip="Download map file to your local disk" data-shortcut="Ctrl + S">
|
<button onclick="saveMap('machine')" data-tip="Download map file to your local disk" data-shortcut="Ctrl + S">
|
||||||
machine
|
machine
|
||||||
</button>
|
</button>
|
||||||
<button onclick="saveToDropbox()" data-tip="Save map file to your Dropbox" data-shortcut="Ctrl + C">
|
<button onclick="saveMap('dropbox')" data-tip="Save map file to your Dropbox" data-shortcut="Ctrl + C">
|
||||||
dropbox
|
dropbox
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button onclick="saveMap('storage')" data-tip="Save the project to browser storage only" data-shortcut="F6">
|
||||||
onclick="quickSave()"
|
|
||||||
data-tip="Save the project to browser storage. It will overwrite the latest autosave"
|
|
||||||
data-shortcut="F6"
|
|
||||||
>
|
|
||||||
browser
|
browser
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -5918,9 +5926,12 @@
|
||||||
</button>
|
</button>
|
||||||
<button onclick="quickLoad()" data-tip="Load map from browser storage (if saved before)">storage</button>
|
<button onclick="quickLoad()" data-tip="Load map from browser storage (if saved before)">storage</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<p>Click on <i>storage</i> to open the last saved map.</p>
|
||||||
|
|
||||||
<div id="loadFromDropbox">
|
<div id="loadFromDropbox">
|
||||||
<p style="margin-bottom: 0.3em">
|
<p style="margin-bottom: 0.3em">
|
||||||
From your Dropbox account
|
Or load from your Dropbox account
|
||||||
<button
|
<button
|
||||||
id="dropboxConnectButton"
|
id="dropboxConnectButton"
|
||||||
onclick="connectToDropbox()"
|
onclick="connectToDropbox()"
|
||||||
|
|
|
||||||
19
main.js
19
main.js
|
|
@ -292,17 +292,20 @@ async function checkLoadParameters() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if there is a map saved to indexedDB
|
// check if there is a map saved to indexedDB
|
||||||
try {
|
if (byId("onloadBehavior").value === "lastSaved") {
|
||||||
const blob = await ldb.get("lastMap");
|
try {
|
||||||
if (blob) {
|
const blob = await ldb.get("lastMap");
|
||||||
WARN && console.warn("Loading last stored map");
|
if (blob) {
|
||||||
uploadMap(blob);
|
WARN && console.warn("Loading last stored map");
|
||||||
return;
|
uploadMap(blob);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
ERROR && console.error(error);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// else generate random map
|
||||||
WARN && console.warn("Generate random map");
|
WARN && console.warn("Generate random map");
|
||||||
generateMapOnLoad();
|
generateMapOnLoad();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -186,7 +186,7 @@ function showUploadMessage(type, mapData, mapVersion) {
|
||||||
title = "Newer file";
|
title = "Newer file";
|
||||||
canBeLoaded = false;
|
canBeLoaded = false;
|
||||||
} else if (type === "outdated") {
|
} else if (type === "outdated") {
|
||||||
message = `The map version (${mapVersion}) does not match the Generator version (${version}).<br>Click OK to get map <b>auto-updated</b>.<br>In case of issues please keep using an ${archive} of the Generator`;
|
message = `The map version (${mapVersion}) does not match the Generator version (${version}).<br>That is fine, click OK to the get map <b style="color: #005000">auto-updated</b>.<br>In case of issues please keep using an ${archive} of the Generator`;
|
||||||
title = "Outdated file";
|
title = "Outdated file";
|
||||||
canBeLoaded = true;
|
canBeLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,43 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
// functions to save project as .gz file
|
|
||||||
|
|
||||||
// prepare map data for saving
|
// functions to save the project to a file
|
||||||
function getMapData() {
|
async function saveMap(method) {
|
||||||
|
if (customization) return tip("Map cannot be saved in EDIT mode, please complete the edit and retry", false, "error");
|
||||||
|
closeDialogs("#alert");
|
||||||
|
|
||||||
|
try {
|
||||||
|
const compressedMapData = await compressData(prepareMapData());
|
||||||
|
const filename = getFileName() + ".gz";
|
||||||
|
|
||||||
|
saveToStorage(compressedMapData, method === "storage"); // any method saves to indexedDB
|
||||||
|
if (method === "machine") saveToMachine(compressedMapData, filename);
|
||||||
|
if (method === "dropbox") saveToDropbox(compressedMapData, filename);
|
||||||
|
} catch (error) {
|
||||||
|
ERROR && console.error(error);
|
||||||
|
alertMessage.innerHTML = /* html */ `An error is occured on map saving. If the issue persists, please copy the message below and report it on ${link(
|
||||||
|
"https://github.com/Azgaar/Fantasy-Map-Generator/issues",
|
||||||
|
"GitHub"
|
||||||
|
)}. <p id="errorBox">${parseError(error)}</p>`;
|
||||||
|
|
||||||
|
$("#alert").dialog({
|
||||||
|
resizable: false,
|
||||||
|
title: "Saving error",
|
||||||
|
width: "28em",
|
||||||
|
buttons: {
|
||||||
|
Retry: function () {
|
||||||
|
$(this).dialog("close");
|
||||||
|
saveMap(method);
|
||||||
|
},
|
||||||
|
Close: function () {
|
||||||
|
$(this).dialog("close");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
position: {my: "center", at: "center", of: "svg"}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepareMapData() {
|
||||||
const date = new Date();
|
const date = new Date();
|
||||||
const dateString = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
|
const dateString = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
|
||||||
const license = "File can be loaded in azgaar.github.io/Fantasy-Map-Generator";
|
const license = "File can be loaded in azgaar.github.io/Fantasy-Map-Generator";
|
||||||
|
|
@ -117,50 +152,30 @@ function getMapData() {
|
||||||
return mapData;
|
return mapData;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function compressData(uncompressedData) {
|
// save map file to indexedDB
|
||||||
const compressedStream = new Blob([uncompressedData]).stream().pipeThrough(new CompressionStream("gzip"));
|
async function saveToStorage(compressedMapData, showTip = false) {
|
||||||
|
const blob = new Blob([compressedMapData], {type: "text/plain"});
|
||||||
let compressedData = [];
|
await ldb.set("lastMap", blob);
|
||||||
for await (const chunk of compressedStream) {
|
showTip && tip("Map is saved to the browser storage", false, "success");
|
||||||
compressedData = compressedData.concat(Array.from(chunk));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Uint8Array(compressedData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// download .gz file
|
// download .gz file
|
||||||
async function downloadMap() {
|
function saveToMachine(compressedMapData, filename) {
|
||||||
if (customization)
|
|
||||||
return tip("Map cannot be saved when edit mode is active, please exit the mode and retry", false, "error");
|
|
||||||
closeDialogs("#alert");
|
|
||||||
|
|
||||||
const compressedMapData = await compressData(getMapData());
|
|
||||||
const blob = new Blob([compressedMapData], {type: "text/plain"});
|
const blob = new Blob([compressedMapData], {type: "text/plain"});
|
||||||
const URL = window.URL.createObjectURL(blob);
|
const URL = window.URL.createObjectURL(blob);
|
||||||
|
|
||||||
const link = document.createElement("a");
|
const link = document.createElement("a");
|
||||||
link.download = getFileName() + ".gz";
|
link.download = filename;
|
||||||
link.href = URL;
|
link.href = URL;
|
||||||
link.click();
|
link.click();
|
||||||
tip(`${link.download} is saved. Open "Downloads" screen (CTRL + J) to check`, true, "success", 7000);
|
|
||||||
|
tip('Map is saved to the "Downloads" folder (CTRL + J to open)', true, "success", 8000);
|
||||||
window.URL.revokeObjectURL(URL);
|
window.URL.revokeObjectURL(URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveToDropbox() {
|
async function saveToDropbox(compressedMapData, filename) {
|
||||||
if (customization)
|
await Cloud.providers.dropbox.save(filename, compressedMapData);
|
||||||
return tip("Map cannot be saved when edit mode is active, please exit the mode and retry", false, "error");
|
tip("Map is saved to your Dropbox", true, "success", 8000);
|
||||||
closeDialogs("#alert");
|
|
||||||
|
|
||||||
const compressedMapData = await compressData(getMapData());
|
|
||||||
const filename = getFileName() + ".gz";
|
|
||||||
|
|
||||||
try {
|
|
||||||
await Cloud.providers.dropbox.save(filename, compressedMapData);
|
|
||||||
tip("Map is saved to your Dropbox", true, "success", 8000);
|
|
||||||
} catch (msg) {
|
|
||||||
ERROR && console.error(msg);
|
|
||||||
tip("Cannot save .gz to your Dropbox", true, "error", 8000);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function initiateAutosave() {
|
async function initiateAutosave() {
|
||||||
|
|
@ -175,25 +190,30 @@ async function initiateAutosave() {
|
||||||
if (diffInMinutes < timeoutMinutes) return;
|
if (diffInMinutes < timeoutMinutes) return;
|
||||||
if (customization) return tip("Autosave: map cannot be saved in edit mode", false, "warning", 2000);
|
if (customization) return tip("Autosave: map cannot be saved in edit mode", false, "warning", 2000);
|
||||||
|
|
||||||
tip("Autosave: saving map...", false, "warning", 3000);
|
try {
|
||||||
const compressedMapData = await compressData(getMapData());
|
tip("Autosave: saving map...", false, "warning", 3000);
|
||||||
const blob = new Blob([compressedMapData], {type: "text/plain"});
|
const compressedMapData = await compressData(prepareMapData());
|
||||||
await ldb.set("lastMap", blob);
|
await saveToStorage(compressedMapData);
|
||||||
INFO && console.log("Autosaved at", new Date().toLocaleTimeString());
|
tip("Autosave: map is saved", false, "success", 2000);
|
||||||
lastSavedAt = Date.now();
|
|
||||||
|
lastSavedAt = Date.now();
|
||||||
|
} catch (error) {
|
||||||
|
ERROR && console.error(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setInterval(autosave, MINUTE / 2);
|
setInterval(autosave, MINUTE / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function quickSave() {
|
async function compressData(uncompressedData) {
|
||||||
if (customization)
|
const compressedStream = new Blob([uncompressedData]).stream().pipeThrough(new CompressionStream("gzip"));
|
||||||
return tip("Map cannot be saved when edit mode is active, please exit the mode first", false, "error");
|
|
||||||
|
|
||||||
const compressedMapData = await compressData(getMapData());
|
let compressedData = [];
|
||||||
const blob = new Blob([compressedMapData], {type: "text/plain"});
|
for await (const chunk of compressedStream) {
|
||||||
await ldb.set("lastMap", blob); // auto-save map
|
compressedData = compressedData.concat(Array.from(chunk));
|
||||||
tip("Map is saved to browser memory. Please also save to your desktop to secure the progress", true, "success", 2000);
|
}
|
||||||
|
|
||||||
|
return new Uint8Array(compressedData);
|
||||||
}
|
}
|
||||||
|
|
||||||
const saveReminder = function () {
|
const saveReminder = function () {
|
||||||
|
|
|
||||||
|
|
@ -25,15 +25,15 @@ function handleKeyup(event) {
|
||||||
|
|
||||||
if (code === "F1") showInfo();
|
if (code === "F1") showInfo();
|
||||||
else if (code === "F2") regeneratePrompt();
|
else if (code === "F2") regeneratePrompt();
|
||||||
else if (code === "F6") quickSave();
|
else if (code === "F6") saveMap("storage");
|
||||||
else if (code === "F9") quickLoad();
|
else if (code === "F9") quickLoad();
|
||||||
else if (code === "Tab") toggleOptions(event);
|
else if (code === "Tab") toggleOptions(event);
|
||||||
else if (code === "Escape") closeAllDialogs();
|
else if (code === "Escape") closeAllDialogs();
|
||||||
else if (code === "Delete") removeElementOnKey();
|
else if (code === "Delete") removeElementOnKey();
|
||||||
else if (code === "KeyO" && document.getElementById("canvas3d")) toggle3dOptions();
|
else if (code === "KeyO" && document.getElementById("canvas3d")) toggle3dOptions();
|
||||||
else if (ctrl && code === "KeyQ") toggleSaveReminder();
|
else if (ctrl && code === "KeyQ") toggleSaveReminder();
|
||||||
else if (ctrl && code === "KeyS") downloadMap();
|
else if (ctrl && code === "KeyS") saveMap("machine");
|
||||||
else if (ctrl && code === "KeyC") saveToDropbox();
|
else if (ctrl && code === "KeyC") saveMap("dropbox");
|
||||||
else if (ctrl && code === "KeyZ" && undo?.offsetParent) undo.click();
|
else if (ctrl && code === "KeyZ" && undo?.offsetParent) undo.click();
|
||||||
else if (ctrl && code === "KeyY" && redo?.offsetParent) redo.click();
|
else if (ctrl && code === "KeyY" && redo?.offsetParent) redo.click();
|
||||||
else if (shift && code === "KeyH") editHeightmap();
|
else if (shift && code === "KeyH") editHeightmap();
|
||||||
|
|
|
||||||
|
|
@ -793,7 +793,7 @@ async function showLoadPane() {
|
||||||
$("#loadMapData").dialog({
|
$("#loadMapData").dialog({
|
||||||
title: "Load map",
|
title: "Load map",
|
||||||
resizable: false,
|
resizable: false,
|
||||||
width: "24em",
|
width: "auto",
|
||||||
position: {my: "center", at: "center", of: "svg"},
|
position: {my: "center", at: "center", of: "svg"},
|
||||||
buttons: {
|
buttons: {
|
||||||
Close: function () {
|
Close: function () {
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ const version = "1.93.00"; // generator version, update each time
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<strong>Latest changes:</strong>
|
<strong>Latest changes:</strong>
|
||||||
|
<li>Auto-load of the last saved map is now optional (see <i>Onload behavior</i> in Options)</li>
|
||||||
<li>Save files compression (file extension is changed to <i>.gz</i>). Old <i>.map</i> files are still supported</li>
|
<li>Save files compression (file extension is changed to <i>.gz</i>). Old <i>.map</i> files are still supported</li>
|
||||||
<li>New label placement algorithm for states</li>
|
<li>New label placement algorithm for states</li>
|
||||||
<li>North and South Poles temperature can be set independently</li>
|
<li>North and South Poles temperature can be set independently</li>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue