Skip to content

Commit

Permalink
moving some code to commons. Added save and load game to the viewer
Browse files Browse the repository at this point in the history
  • Loading branch information
Echsecutor committed Jan 18, 2025
1 parent b8a1e20 commit 8ec43d8
Show file tree
Hide file tree
Showing 11 changed files with 101 additions and 66 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ See there for the corresponding licenses and meta-dependencies.

## License

Copyright 2024 Sebastian Schmittner
Copyright 2024-2025 Sebastian Schmittner

<a href="https://www.gnu.org/licenses/agpl-3.0.html">
<img alt="AGPLV3" style="border-width:0" src="https://www.gnu.org/graphics/agplv3-with-text-162x68.png" /><br />
Expand All @@ -69,4 +69,4 @@ GNU General Public License as published by the Free Software Foundation, either
(at your option) any later version.

For the included open source projects, different licenses might be applicable. See the respective projects pages listed above for details.
</a>

1 change: 1 addition & 0 deletions commons/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -299,3 +299,4 @@ function compare(value1, operator, value2) {
console.log(`Comparison result for ${value1} ${operator} ${value2}: ${result}`);
return result;
}

3 changes: 3 additions & 0 deletions commons/file-saver.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/* esm.sh - [email protected] */
export * from "./file-saver.mjs";
export { default } from "./file-saver.mjs";
4 changes: 4 additions & 0 deletions commons/file-saver.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/* esm.sh - esbuild bundle([email protected]) esnext production */
var __global$ = globalThis || (typeof window !== "undefined" ? window : self);
var O=Object.create;var y=Object.defineProperty;var T=Object.getOwnPropertyDescriptor;var U=Object.getOwnPropertyNames;var _=Object.getPrototypeOf,M=Object.prototype.hasOwnProperty;var S=(a,n)=>()=>(n||a((n={exports:{}}).exports,n),n.exports),k=(a,n)=>{for(var r in n)y(a,r,{get:n[r],enumerable:!0})},m=(a,n,r,l)=>{if(n&&typeof n=="object"||typeof n=="function")for(let i of U(n))!M.call(a,i)&&i!==r&&y(a,i,{get:()=>n[i],enumerable:!(l=T(n,i))||l.enumerable});return a},f=(a,n,r)=>(m(a,n,"default"),r&&m(r,n,"default")),A=(a,n,r)=>(r=a!=null?O(_(a)):{},m(n||!a||!a.__esModule?y(r,"default",{value:a,enumerable:!0}):r,a));var b=S((h,E)=>{(function(a,n){typeof define=="function"&&define.amd?define([],n):typeof h<"u"?n():(n(),a.FileSaver={})})(h,function(){"use strict";function a(e,t){return typeof t>"u"?t={autoBom:!1}:typeof t!="object"&&(console.warn("Deprecated: Expected third argument to be a object"),t={autoBom:!t}),t.autoBom&&/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)?new Blob(["\uFEFF",e],{type:e.type}):e}function n(e,t,c){var o=new XMLHttpRequest;o.open("GET",e),o.responseType="blob",o.onload=function(){p(o.response,t,c)},o.onerror=function(){console.error("could not download file")},o.send()}function r(e){var t=new XMLHttpRequest;t.open("HEAD",e,!1);try{t.send()}catch{}return 200<=t.status&&299>=t.status}function l(e){try{e.dispatchEvent(new MouseEvent("click"))}catch{var t=document.createEvent("MouseEvents");t.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),e.dispatchEvent(t)}}var i=typeof window=="object"&&window.window===window?window:typeof self=="object"&&self.self===self?self:typeof __global$=="object"&&__global$.global===__global$?__global$:void 0,L=i.navigator&&/Macintosh/.test(navigator.userAgent)&&/AppleWebKit/.test(navigator.userAgent)&&!/Safari/.test(navigator.userAgent),p=i.saveAs||(typeof window!="object"||window!==i?function(){}:"download"in HTMLAnchorElement.prototype&&!L?function(e,t,c){var o=i.URL||i.webkitURL,s=document.createElement("a");t=t||e.name||"download",s.download=t,s.rel="noopener",typeof e=="string"?(s.href=e,s.origin===location.origin?l(s):r(s.href)?n(e,t,c):l(s,s.target="_blank")):(s.href=o.createObjectURL(e),setTimeout(function(){o.revokeObjectURL(s.href)},4e4),setTimeout(function(){l(s)},0))}:"msSaveOrOpenBlob"in navigator?function(e,t,c){if(t=t||e.name||"download",typeof e!="string")navigator.msSaveOrOpenBlob(a(e,c),t);else if(r(e))n(e,t,c);else{var o=document.createElement("a");o.href=e,o.target="_blank",setTimeout(function(){l(o)})}}:function(e,t,c,o){if(o=o||open("","_blank"),o&&(o.document.title=o.document.body.innerText="downloading..."),typeof e=="string")return n(e,t,c);var s=e.type==="application/octet-stream",x=/constructor/i.test(i.HTMLElement)||i.safari,R=/CriOS\/[\d]+/.test(navigator.userAgent);if((R||s&&x||L)&&typeof FileReader<"u"){var v=new FileReader;v.onloadend=function(){var u=v.result;u=R?u:u.replace(/^data:[^;]*;/,"data:attachment/file;"),o?o.location.href=u:location=u,o=null},v.readAsDataURL(e)}else{var j=i.URL||i.webkitURL,w=j.createObjectURL(e);o?o.location=w:location.href=w,o=null,setTimeout(function(){j.revokeObjectURL(w)},4e4)}});i.saveAs=p.saveAs=p,typeof E<"u"&&(E.exports=p)})});var d={};k(d,{default:()=>H});var B=A(b());f(d,A(b()));var{default:g,...F}=B,H=g!==void 0?g:F;export{H as default};
//# sourceMappingURL=file-saver.mjs.map
31 changes: 31 additions & 0 deletions commons/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,34 @@ export const tools_files = {
},
},
};

export function get_file_safe_title(story) {
if (!story?.meta?.title) {
return "story_adventure";
}
return story.meta.title.replaceAll(/[^a-z0-9-_]/gi, "_");
}

export function load_file(content_handler, read_as_data) {
var input = document.createElement("input");
input.type = "file";
input.onchange = (e) => {
const file = e.target.files[0];
read_blob_and_handle(file, content_handler, read_as_data);
};
input.click();
}

function read_blob_and_handle(blob, content_handler, read_as_data) {
const reader = new FileReader();
if (read_as_data) {
reader.readAsDataURL(blob);
} else {
reader.readAsText(blob, "UTF-8");
}
reader.onload = (readerEvent) => {
const content = readerEvent.target.result;
//console.log(content);
content_handler(content);
};
}
47 changes: 10 additions & 37 deletions editor/code.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import {
create_element_with_classes_and_attributes,
get_text_from_section,
tools_files,
get_file_safe_title,
load_file
} from "./utils.js";

import { save_story, get_story } from "./storage.js";
Expand Down Expand Up @@ -681,7 +683,7 @@ async function download_as_is() {
var blob = new Blob([JSON.stringify(story, null, 2)], {
type: "text/json;charset=utf-8",
});
return save_file(blob, get_file_safe_title() + ".json");
return save_file(blob, get_file_safe_title(story) + ".json");
}

async function download_graph_in_one() {
Expand All @@ -699,7 +701,7 @@ async function download_graph_split() {
toast_ok("Extracting images into separate files");
const story_deep_copy = JSON.parse(JSON.stringify(story));
var zip = new JSZip();
var folder = zip.folder("stories").folder(get_file_safe_title());
var folder = zip.folder("stories").folder(get_file_safe_title(story));

const wait_for_all = [];
for (const section_id in story.sections) {
Expand All @@ -714,7 +716,7 @@ async function download_graph_split() {
console.log("Adding image for section", section, "to zip");
const file_name = section_id + "." + type;
story_deep_copy.sections[section.id].media.src =
"../stories/" + get_file_safe_title() + "/" + file_name;
"../stories/" + get_file_safe_title(story) + "/" + file_name;
folder.file(file_name, data, { base64: true });
} else {
console.debug(
Expand All @@ -730,7 +732,7 @@ async function download_graph_split() {
}
const file_name = section_id + "." + type;
story_deep_copy.sections[section.id].media.src =
"../stories/" + get_file_safe_title() + "/" + file_name;
"../stories/" + get_file_safe_title(story) + "/" + file_name;
wait_for_all.push(
fetch(section.media.src)
.then((response) => response.blob())
Expand All @@ -749,7 +751,7 @@ async function download_graph_split() {

toast_ok("Saving Story");

folder.file(get_file_safe_title() + ".json", JSON.stringify(story_deep_copy));
folder.file(get_file_safe_title(story) + ".json", JSON.stringify(story_deep_copy));

add_stroy_adventure_files(zip)
.then(() => {
Expand All @@ -760,7 +762,7 @@ async function download_graph_split() {
percentage.innerHTML = metadata.percent.toFixed(2) + " %";
})
.then(function (content) {
return save_file(content, get_file_safe_title() + ".zip");
return save_file(content, get_file_safe_title(story) + ".zip");
});
})
.catch((err) => {
Expand Down Expand Up @@ -806,7 +808,7 @@ async function add_to_zip(zip, folder, global_path = "../") {
async function add_stroy_adventure_files(zip) {
toast_ok("Adding tools to archive");
return add_to_zip(zip, tools_files).then(() => {
const story_name = get_file_safe_title();
const story_name = get_file_safe_title(story);
zip.file(
"index.html",
`<!DOCTYPE html>
Expand All @@ -826,36 +828,7 @@ async function add_stroy_adventure_files(zip) {
});
}

function get_file_safe_title() {
if (!story?.meta?.title) {
return "story_adventure";
}
return story.meta.title.replaceAll(/[^a-z0-9-_]/gi, "_");
}

function load_file(content_handler, read_as_data) {
var input = document.createElement("input");
input.type = "file";
input.onchange = (e) => {
const file = e.target.files[0];
read_blob_and_handle(file, content_handler, read_as_data);
};
input.click();
}

function read_blob_and_handle(blob, content_handler, read_as_data) {
const reader = new FileReader();
if (read_as_data) {
reader.readAsDataURL(blob);
} else {
reader.readAsText(blob, "UTF-8");
}
reader.onload = (readerEvent) => {
const content = readerEvent.target.result;
//console.log(content);
content_handler(content);
};
}

function load_graph() {
load_file((content) => {
Expand Down Expand Up @@ -1120,7 +1093,7 @@ async function create_linear_story() {
return;
}
var blob = new Blob([markdown], { type: "text/plain;charset=utf-8" });
save_file(blob, get_file_safe_title() + ".md");
save_file(blob, get_file_safe_title(story) + ".md");
})
.catch((error) => {
console.error(error);
Expand Down
3 changes: 0 additions & 3 deletions editor/file-saver.js

This file was deleted.

1 change: 1 addition & 0 deletions editor/file-saver.js
4 changes: 0 additions & 4 deletions editor/file-saver.mjs

This file was deleted.

1 change: 1 addition & 0 deletions editor/file-saver.mjs
66 changes: 46 additions & 20 deletions viewer/code.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ import {
replace_variables,
get_text_from_section,
create_element_with_classes_and_attributes,
load_file,
get_file_safe_title,
} from "./utils.js";

import saveAs from "./file-saver.js";

var story = {};

const viewer_states = Object.freeze({
Expand All @@ -20,6 +24,48 @@ const hot_keys = {
description: "One step back",
action: one_step_back,
},
s: {
description: "Save your progress for the current adventure",
action: () => {
var blob = new Blob(
[
JSON.stringify(
{
meta: story.meta,
state: story.state,
},
null,
2
),
],
{
type: "text/json;charset=utf-8",
}
);
return saveAs(blob, get_file_safe_title(story) + "_save.json");
},
},
l: {
description:
"Load progress for the current adventure. (load the adventure first)",
action: () => {
load_file((content) => {
const saved = JSON.parse(content);
if (!story?.meta?.title) {
toast_alert("Please load the story first!");
return;
}
if (story.meta.title != saved.meta?.title) {
toast_alert(
`The loaded story is '${story.meta.title}' but the save game is for '${saved.meta?.title}'`
);
return;
}
story.state = saved.state;
start_playing();
});
},
},
f: {
description: "Toggle full screen",
action: () => {
Expand Down Expand Up @@ -66,26 +112,6 @@ function one_step_back() {
load_section(story.state.history.pop(), false);
}

function load_file(content_handler, read_as_data) {
var input = document.createElement("input");
input.type = "file";
input.onchange = (e) => {
var file = e.target.files[0];
var reader = new FileReader();
if (read_as_data) {
reader.readAsDataURL(file);
} else {
reader.readAsText(file, "UTF-8");
}
reader.onload = (readerEvent) => {
const content = readerEvent.target.result;
//console.log(content);
content_handler(content);
};
};
input.click();
}

function load_graph_from_file() {
load_file((content) => {
try {
Expand Down
1 change: 1 addition & 0 deletions viewer/file-saver.js
1 change: 1 addition & 0 deletions viewer/file-saver.mjs

0 comments on commit 8ec43d8

Please sign in to comment.