var statusElement = document.getElementById('status'); var progressElement = document.getElementById('progress'); var spinnerElement = document.getElementById('spinner'); class FilePicker { /** * @type {HTMLInputElement} */ el; /** * @type {boolean} */ visible = false; /** * @type {boolean} */ cancelled = false; /** * @type {boolean} */ closed = false; /** * @type {Array|null} */ value = null; /** * @type {boolean} */ loading = false; /** * Sets the filter of the file picker. * @param {String} filter */ setFilter(filter) { this.el.setAttribute("accept", filter) } /** * @type {boolean} */ puterEnabled = false; async openPuterFile(file) { this.loading = true; this.value = null; this.closed = false; this.visible = false; this.cancelled = false; let fileData = this.openWasmFile(file.name) let filePath = fileData.path; let handle = fileData.handle; await this.writeBlob(handle, await file.read()) this.value = [filePath]; this.cancelled = false; this.closed = true; this.visible = false; this.loading = false; } show() { this.visible = true; this.closed = false; this.cancelled = false; this.value = ""; if (this.puterEnabled) { puter.ui.showOpenFilePicker({"accept": this.el.getAttribute("accept"), "multiple": false}).then(this.openPuterFile) } else { this.el.click(); } } wasCancelled() { return !this.visible && this.cancelled } wasClosed() { return !this.visible && this.closed; } wasConfirmed() { return !this.visible && this.closed && !this.cancelled; } isLoading() { } getFileList() { if (this.wasConfirmed()) { return this.value; } else { return null; } } getFirstFile() { if (this.wasConfirmed()) { if (this.value.length > 0) { return this.value[0]; } } return null; } clearSelection() { this.closed = false; this.cancelled = false; this.visible = false; this.el.value = null; this.value = null; } makeWasmDir() { let chars ="0123456789bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ_"; let output = "/" for (let i = 0; i < 16; i++) { output += chars.charAt((Math.random() * chars.length) % chars.length) } FS.mkdir(output) output += "/"; return output; } openWasmFile(name, dir = null) { if (dir === null) { dir = this.makeWasmDir(); } let filePath = dir + "/" + name; let file = FS.open(filePath, "w+"); return { "path": filePath, "handle": file }; } async writeBlob(file, blob) { let data = null; let reader = blob.stream().getReader(); while (data !== undefined) { let data = (await reader.read()); if (data.done) { break; } FS.write(file, data.value, 0, data.value.length); } FS.close(file); } constructor() { if (puter.auth.isSignedIn()) { this.puterEnabled = true; } this.el = document.getElementById("file-picker") this.el.addEventListener("cancel", () => { this.value = null; this.cancelled = true; this.closed = true; this.visible = false; }) this.el.addEventListener("change", async () => { if (this.el.files.length > 0) { this.loading = true; this.value = null; this.closed = false; this.visible = false; this.cancelled = false; let output = this.makeWasmDir(); let newValue = [] for (let i = 0; i < this.el.files.length; i++) { let element = this.el.files[i]; let fileData = this.openWasmFile(element.name, output); let file = fileData.handle; let filePath = fileData.path; await this.writeBlob(file, element); newValue = [...newValue, filePath] } /** * @type {string[]|null} */ let oldValues = this.value; if (oldValues !== null) { setTimeout(() => { for (let i = 0; i < oldValues.length; i++) { /** * @type {string} */ let value = oldValues[i]; let lastSlash = value.lastIndexOf("/") if (lastSlash === value.length - 1) { value = value.substring(0, lastSlash - 1); lastSlash = value.lastIndexOf("/") } let parent = value.substring(0, lastSlash - 1) FS.unlink(value); if (FS.readdir(parent).length === 2) { FS.rmdir(parent) } } }, 1000) } this.value = newValue; this.cancelled = false; this.closed = true; this.visible = false; this.loading = false; } else { this.value = null; this.cancelled = true; this.closed = true; this.visible = false; } }) puter.ui.onLaunchedWithItems(function(items) { for (let i = 0; i < files.length; i++) { this.openPuterFile(files[i]); } }) } } window.filePicker = new FilePicker()