App import/export from the editor.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4786 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
parent
ab519342e8
commit
ad2b49b838
@ -1029,6 +1029,97 @@ function removeFile() {
|
||||
}
|
||||
}
|
||||
|
||||
async function appExport() {
|
||||
let JsZip = (await import('/static/jszip.min.js')).default;
|
||||
let owner = window.location.pathname.split('/')[1].replace('~', '');
|
||||
let name = window.location.pathname.split('/')[2];
|
||||
let zip = new JsZip();
|
||||
zip.file(`${name}.json`, JSON.stringify({
|
||||
type: "tildefriends-app",
|
||||
emoji: gApp.emoji || '📦',
|
||||
}));
|
||||
for (let file of Object.keys(gFiles)) {
|
||||
zip.file(`${name}/${file}`, gFiles[file].buffer ?? gFiles[file].doc.doc.toString());
|
||||
}
|
||||
let content = await zip.generateAsync({
|
||||
type: 'blob',
|
||||
compression: 'DEFLATE',
|
||||
});
|
||||
let a = document.createElement('a');
|
||||
a.href = URL.createObjectURL(content);
|
||||
a.download = `${owner}_${name}.zip`;
|
||||
a.click();
|
||||
}
|
||||
|
||||
async function save_file_to_blob_id(name, file) {
|
||||
console.log(`Saving ${name}.`);
|
||||
let response = await fetch('/save', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/binary',
|
||||
},
|
||||
body: file,
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error('Saving "' + name + '": ' + response.status + ' ' + response.statusText);
|
||||
}
|
||||
let blob_id = await response.text();
|
||||
if (blob_id.charAt(0) == '/') {
|
||||
blob_id = blob_id.substr(1);
|
||||
}
|
||||
return blob_id;
|
||||
}
|
||||
|
||||
async function appImport() {
|
||||
let JsZip = (await import('/static/jszip.min.js')).default;
|
||||
let input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
input.click();
|
||||
input.onchange = async function() {
|
||||
try {
|
||||
for (let file of input.files) {
|
||||
if (file.type != 'application/zip') {
|
||||
console.log('This does not look like a .zip.');
|
||||
continue;
|
||||
}
|
||||
let buffer = await file.arrayBuffer();
|
||||
let zip = new JsZip();
|
||||
await zip.loadAsync(buffer);
|
||||
let app_object;
|
||||
let app_name;
|
||||
for (let [name, object] of Object.entries(zip.files)) {
|
||||
if (name.endsWith('.json') && name.indexOf('/') == -1) {
|
||||
try {
|
||||
let parsed = JSON.parse(await object.async('text'));
|
||||
if (parsed.type == 'tildefriends-app') {
|
||||
app_object = parsed;
|
||||
app_name = name.substring(0, name.length - '.json'.length);
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (app_object) {
|
||||
app_object.files = {};
|
||||
for (let [name, object] of Object.entries(zip.files)) {
|
||||
if (!name.startsWith(app_name + '/') || name.endsWith('/')) {
|
||||
continue;
|
||||
}
|
||||
app_object.files[name.substring(app_name.length + '/'.length)] = await save_file_to_blob_id(name, await object.async('arrayBuffer'));
|
||||
}
|
||||
let path = '/' + await save_file_to_blob_id(`${app_name}.json`, JSON.stringify(app_object)) + '/';
|
||||
console.log('Redirecting to:', path);
|
||||
window.location.pathname = path;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
alert(e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("load", function() {
|
||||
window.addEventListener("hashchange", hashChange);
|
||||
window.addEventListener("focus", focus);
|
||||
@ -1040,6 +1131,8 @@ window.addEventListener("load", function() {
|
||||
document.getElementById('save').addEventListener('click', () => save());
|
||||
document.getElementById('icon').addEventListener('click', () => changeIcon());
|
||||
document.getElementById('delete').addEventListener('click', () => deleteApp());
|
||||
document.getElementById('export').addEventListener('click', () => appExport());
|
||||
document.getElementById('import').addEventListener('click', () => appImport());
|
||||
document.getElementById('trace_button').addEventListener('click', function(event) {
|
||||
event.preventDefault();
|
||||
trace();
|
||||
|
@ -35,6 +35,7 @@ let k_static_files = [
|
||||
{uri: '/', path: 'index.html', type: 'text/html; charset=UTF-8'},
|
||||
{uri: '/client.js', type: 'text/javascript; charset=UTF-8'},
|
||||
{uri: '/favicon.png', type: 'image/png'},
|
||||
{uri: '/jszip.min.js', type: 'text/javascript; charset=UTF-8'},
|
||||
{uri: '/robots.txt', type: 'text/plain; charset=UTF-8'},
|
||||
{uri: '/style.css', type: 'text/css; charset=UTF-8'},
|
||||
{uri: '/tfrpc.js', type: 'text/javascript; charset=UTF-8', headers: {'Access-Control-Allow-Origin': 'null'}},
|
||||
|
@ -22,6 +22,8 @@
|
||||
<button class="w3-bar-item w3-button w3-blue" id="closeEditor" name="closeEditor" accesskey="c" onmouseover="set_access_key_title(event)" data-tip="Close the editor">Close</button>
|
||||
<button class="w3-bar-item w3-button w3-blue" id="save" name="save" accesskey="s" onmouseover="set_access_key_title(event)" data-tip="Save the app under the given path">Save</button>
|
||||
<button class="w3-bar-item w3-button w3-blue" id="icon" name="icon" accesskey="i" onmouseover="set_access_key_title(event)" data-tip="Set an icon/emoji for the app">📦</button>
|
||||
<button class="w3-bar-item w3-button w3-blue" id="export" name="export" accesskey="e" onmouseover="set_access_key_title(event)" data-tip="Export app to .zip file">Export</button>
|
||||
<button class="w3-bar-item w3-button w3-blue" id="import" name="import" accesskey="i" onmouseover="set_access_key_title(event)" data-tip="Import app from .zip file">Import</button>
|
||||
<input class="w3-bar-item w3-input w3-border w3-blue" type="text" id="name" name="name" style="flex: 1 1; min-width: 1em"></input>
|
||||
<button class="w3-bar-item w3-button w3-blue" id="delete" name="delete" accesskey="d" onmouseover="set_access_key_title(event)" data-tip="Delete the app">Delete</button>
|
||||
<button class="w3-bar-item w3-button w3-blue" id="trace_button" accesskey="t" onmouseover="set_access_key_title(event)" data-tip="Open a performance trace for the server">Trace</button>
|
||||
|
1
core/jszip.min.js
vendored
Normal file
1
core/jszip.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user