Skip to content
Open
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 60 additions & 2 deletions static/extensions/Faunks/Blobs.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,31 @@
},
},
},
{
opcode: "readBlob",
blockType: Scratch.BlockType.REPORTER,
text: "Read blob [URL] as a [TYPE]",
arguments: {
URL: {
type: Scratch.ArgumentType.STRING
},
TYPE: {
type: Scratch.ArgumentType.STRING,
defaultValue: "text/plain",
menu: "types"
}
},
},
{
opcode: "revokeBlob",
blockType: Scratch.BlockType.COMMAND,
text: "Revoke blob with the URL of [URL]",
arguments: {
URL: {
type: Scratch.ArgumentType.STRING
}
},
},
]
,menus: {
types: {
Expand Down Expand Up @@ -103,10 +128,43 @@
}

toBlob(args, util) {
const text = String(args.DATA); // ensure it's a string (why can't it be just like python or smth)
const text = String(args.DATA);
const blob = new Blob([text], { type: args.TYPE });
return URL.createObjectURL(blob);
}
}

revokeBlob(args, util){
URL.revokeObjectURL(args.URL);
}

readBlob(args, util) {
async function readBlobContent(url, mime) {

if (!url.startsWith("blob:")) return ""; // I WOULD return "Url Error", but it would make it a bit harder to track if an output has been returned or not
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could throw an error. So throw new URIError("must be a blob url"); or something similar.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks. I've just added it so it would do that (I hope it also acts as a return method)


const response = await fetch(url);
const blob = await response.blob();


if (blob.size === 0) return ""; // js for u TheShovel

if (mime.startsWith("text/") || mime === "application/json") {
return await blob.text();
}

const buffer = await blob.arrayBuffer();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After doing a bit of looking at the MDN documentation for Blob, there may be a way of doing this with a readable stream, although I'd need to check how efficient that is. Also quick note that the text method doesn't seem to require text to actually be text, so it can pretty much be anything and still be interpreted as text.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could also be wrong about this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's worth spending time on concidering the extension already runs really fast and uploading bigger files would be an issue by it's one to be honest, I think it would be better for this chunk of the code to be as is instead of spending time on how we could improve it right now, a think that we can and probably may happen at some point.

const view = new DataView(buffer);

let binary = ''; // = decoder.decode(bytes); Decoder doesn't work with btoa, and replacing it reduces efficiency.

for (let i = 0; i < view.byteLength; i++) {
binary += String.fromCharCode(view.getUint8(i));
}
return btoa(binary);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the purpose of reading the text as Base64? PenguinMod will be able to handle direct binary-encoded data, pretty sure.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I think that outputting it as b64 could be considered unexpected behavior, mostly because input isn't given in base 64.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so what do you recommend the output being?, if you're just saying to output the raw data then sure I would just return it if you like.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think outputting the raw information is the best option.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just spent like 2 hours, scratch cannot handle raw bytes,
image
this just destroyes the image.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thats not a scratch thing though, thats the javascript

The block explicitly casts any input to a string before saving it to an object URL. Whether this is Scratch's or JavaScript's fault is, for all purposes, entirely irrelevant. Non-JS string safe characters cannot be added to an object URL due to the limitations of this extension, and so no non-JS string safe characters couldn't possibly be read from an object URL, unless someone is utilizing another extension that allows for that, or are directly encoding things to an object URL through a JavaScript eval extension. That was my point in the first place.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it was the point of my reply, and what you said there doesnt match what you say now in how you lay it out

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wgat

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

read should not be using string btoa, js strings will naturally corrupt binary data due to how they work
if its intention is just to return some handle for the data that can be referenced later, this will need a custom base64 encoder
however if its intention is instead to provide data in a way the project can read all on its own, it must be in a raw byte format, such as 0,255,127,63,31,15,7,3,1
i am fairly certain that the later is the intention, not the former, since the block provides types for things like gltf and obj, where the intent of loading such a file is likely specifically to get something that the project intends to manually render, and also provides formats like json and text as the actual data rather then as a base64 string

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it was the point of my reply, and what you said there doesnt match what you say now in how you lay it out

That's what the intended meaning of my point was, if that doesn't come across at all then that's my bad.

}

return readBlobContent(args.URL, args.TYPE);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure if this is all you're doing, you don't even need to have another function inside here, just make the function root async; in any case, this will be returning a promise, so it really doesn't matter that you did it this way.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another note about this because I feel like this is important, I'm asking for the method to be made async and for it to directly return rather than routing it through another function. This is all around more readable, at least in my opinion.

async readBlob(args, util) {
  ...
  return btoa(binary);
}

feel free to disagree, here, though.

}
}
Scratch.extensions.register(new faunks_Blobs());
})(Scratch);