import { promptUpload } from "./prompt_upload.js"; import { downloadFile, slugify } from "./utils.js"; import { HtmlExporter } from "./html_exporter.js"; import { KarlkoderCodec } from "./karlkoder_codec.js"; export class ProjectSaveHandler { constructor(editor, assetEditor, assetProvider, projectName) { this.editor = editor; this.assetEditor = assetEditor; this.projectName = projectName; this.htmlExporter = new HtmlExporter(assetProvider); this.saveName = null; this.isSaved = true; editor.addEventListener("change", () => { this.isSaved = false; }); assetEditor.addChangeListener(() => { this.isSaved = false; }); } async showLoadFilePrompt() { const files = await promptUpload(".karlkode", false); if (files.length === 0) { return; } if (files.length > 1) { throw new Error( `unreachable: something went wrong ! files.length > 1 : files.length = ${files.length}`, ); } this.loadFromFile(files[0]); } async loadFromFile(file) { if ( !this.isSaved && !confirm( "Your project has not been saved. Loading a new project will override your current one. Continue?", ) ) { return; } const items = KarlkoderCodec.de( await fetch(URL.createObjectURL(file)).then((x) => x.bytes()), ); const assets = items .filter((x) => x.tag === "asset") .map((x) => { delete x.tag; return x; }); const code = items.find((x) => x.tag === "code"); delete code.tag; await this.assetEditor.importAssets( assets.map(({ name, mime, content }) => { const file = new File([content], name, { type: mime }); return { name, file }; }), ); this.projectName.value = code.name; const dec = new TextDecoder(); this.editor.setValue(dec.decode(code.content)); this.isSaved = true; } async saveFile() { const filename = prompt("Filename?", this.getSaveFileName()); if (!filename) { return; } this.saveName = filename; this.isSaved = true; downloadFile( filename, await KarlkoderCodec.en( this.projectName.value, this.editor.getValue(), await this.assetEditor.getAssets(), ), ".karlkode", ); } async exportProject() { const filename = prompt("Filename?", this.getSaveFileName()); if (!filename) { return; } this.saveName = filename; const html = await this.htmlExporter.export(this.projectName.value, this.editor.getValue()); downloadFile(filename, html, ".html", "text/html"); } getSaveFileName() { if (this.saveName) { return this.saveName; } return slugify(this.projectName.value) || "project"; } }