openscad / openscad-playground

OpenSCAD Web Playground
https://ochafik.com/openscad2
Other
107 stars 30 forks source link

Uploading New Files #42

Open jaydenlo08 opened 4 months ago

jaydenlo08 commented 4 months ago

First of all thank you @ochafik for all your hard work. It's absolutely amazing and I love it.

The options for file management are greyed out, with no way to upload or create new files (or libraries).

I see that the current content appears to be saved as base64 in the URL (or encoded) which could potentially allow me to put a new file there but I'm slightly too stupid to do so...

Is this feature not implemented yet, or is it to do with persistent storage with browser? image

ochafik commented 4 months ago

Hi @jaydenlo08, thanks for the kind feedback!

Sorry about the greyed out menu, that was just some teasing meant to pressure me into implementing it quickly, and... it's still not completely there, but actually it now just needs a bit of UI support.

Also, you're right to assume just modifying the URL would do the trick. It's literally just some gzipped JSON state, and here's the snippet you'd need to add a single scad file (adapted from fragment-state.ts; can just paste this in the JS debugger console and go check your new file in the file picker / include it from /playground.scad):

async function compressString(input) {
  return btoa(String.fromCharCode(...new Uint8Array(await new Response(new ReadableStream({
    start(controller) {
      controller.enqueue(new TextEncoder().encode(input));
      controller.close();
    }
  }).pipeThrough(new CompressionStream('gzip'))).arrayBuffer())));
}

async function decompressString(compressedInput) {
  return new TextDecoder().decode(await new Response(new ReadableStream({
    start(controller) {
      controller.enqueue(Uint8Array.from(atob(compressedInput), c => c.charCodeAt(0)));
      controller.close();
    }
  }).pipeThrough(new DecompressionStream('gzip'))).arrayBuffer());
}

async function addFile(path, content) {
  const state = JSON.parse(await decompressString(window.location.hash.substring(1)));
  // console.log(JSON.stringify(state, null, 2)); // Put a breakpoint here if you wanna peek into the state
  state.params.sources.push({ path, content });
  window.history.pushState(state, '', '#' + await compressString(JSON.stringify(state)));
  window.location.reload();
}

addFile("/include_me.scad", "echo(\"Hello, World!\");").then(() => console.log("File added!"));

As to how the UI should look like to expose this functionality, suggestions are welcome! (there's also partial support for url instead of string content in file entries, but completely untested for now haha)

jaydenlo08 commented 4 months ago

Wow! Thanks for the prompt detailed explanation ... This snippet simply works flawlessly.

The current not-yet-implemented UI looks great, but to me I would find it easier if the menu button was in the dropdown

image Something like this minus the wonky drawing; or perhaps a file manager-like UI similar to the native "save file" picker on local OS?

Another suggestion is perhaps something like a dedicated tab called "Library" or "My designs" that allows files to be "opened" like a traditional desktop app - although it could potentially overcomplicate the UI image

Not so related, but using a 'file' svg icon to replace the home svg might make it easier to navigate.

Sorry for yapping too much - I might have a go at exposing the files if I have more time later but might find it slightly challenging with my current skills and limited ability (never used nodejs + I'm a student).