Skip to content

Commit

Permalink
Zip extraction & general files work
Browse files Browse the repository at this point in the history
  • Loading branch information
Jdsle committed Oct 25, 2024
1 parent 326d024 commit f976c8b
Show file tree
Hide file tree
Showing 5 changed files with 316 additions and 50 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@

Website source code for RSDK-Library

### Building
## Known issues
* Uploading files *might* just hang. This can be caused by having an insufficient amount of disk space available.

## Building
###### [(You're gonna need node.js for this.)](https://nodejs.org/en/download/package-manager)
##### Simply run this command, and you should be good to go -
```
Expand All @@ -22,3 +25,6 @@ python -m http.server
```

###### You don't *have* to build it - though! this website is hosted via github pages - [you can find that here :)](https://jdsle.github.io/RSDK)

###### TODO (?)
###### - Give each engines their own IDBFS instance
8 changes: 3 additions & 5 deletions app/pages/files.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,11 @@ const FilesPage: React.FC = () => {
};

const Toolbar_Export_OnClick = async () => {
if (selectedFiles.length !== 1) {
// todo: allow multiple (via zip?)
alert('Currently, only one item is allowed');
if (selectedFiles.length === 0) {
return;
}
const path = joinPath(engineFS.currentPath, selectedFiles[0]);
await engineFS.FileDownload(path);
const paths = selectedFiles.map(file => joinPath(engineFS.currentPath, file));
await engineFS.FileDownload(paths);
};

const Toolbar_ItemCut_OnClick = async () => {
Expand Down
177 changes: 137 additions & 40 deletions lib/EngineFS.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
declare const FS: any;
declare const PATH: any;
declare const IDBFS: any;

import JSZip from 'jszip';

let once = false;

// Bad programming ahead, be warned
Expand Down Expand Up @@ -34,7 +37,7 @@ class EngineFS {
FS.mount(IDBFS, {}, 'FileSystem');

await this.Init();

console.log('FileSystem initialized');
once = true;
} catch (errorInit: any) {
Expand Down Expand Up @@ -125,7 +128,7 @@ class EngineFS {
}
await this.DirCopyRecursive(src, dst);
return;
}
}
FS.writeFile(dst, FS.readFile(src));
}

Expand Down Expand Up @@ -159,8 +162,8 @@ class EngineFS {
await this.ItemDoCopy(item, oldPath, newPath);
}
} catch (error) {
alert('Error during paste operation for ' + item.name + ':' + error);
console.error(`Error during paste operation for ${item.name}:`, error);
alert('Error pasting ' + item.name + ':' + error);
console.error(`Error pasting ${item.name}:`, error);
this.actionInProgress = false;
}
});
Expand Down Expand Up @@ -211,52 +214,118 @@ class EngineFS {
}
}

async ZipExtract(file: File, fsPath: string): Promise<void> {
return new Promise<void>(async (resolve, reject) => {
try {
const zip = await JSZip.loadAsync(file);
console.log("Loaded ZIP file");

// Setting some stuff up, just get the info about the zip
const directoryList: string[] = [];
const fileList: { path: string; entry: JSZip.JSZipObject }[] = [];

zip.forEach((i, zentry) => {
const fullPath = `${fsPath}/${i}`;
if (zentry.dir) {
directoryList.push(fullPath);
} else {
fileList.push({ path: fullPath, entry: zentry });
}
});

// Make the directories first, before adding files to them
// reason for this should be obvious!
directoryList.forEach(dirPath => {
const parts = dirPath.split('/');
let currentPath = parts.shift() || '';

parts.forEach(part => {
currentPath += `/${part}`;
if (!FS.analyzePath(currentPath).exists) {
FS.mkdir(currentPath);
}
});
});

// Now, we can start working on the files...
await Promise.all(fileList.map(async ({ path, entry }) => {
const data = await entry.async('uint8array');
const p = PATH.dirname(path);

// If the requested directory doesn't exist (SOMEHOW), make it
if (!FS.analyzePath(p).exists) {
FS.mkdir(p);
}

FS.writeFile(path, data, { encoding: 'binary' });
}));

console.log('Zip extraction complete! Synchronizing FileSystem...');
await this.Save();
this.actionInProgress = false;
resolve();
} catch (error) {
console.error("Error during ZIP extraction:", error);
reject(error);
}
});
}

// -----
// Files
// -----

// TODO: ZIP EXTRACTION
async FileUpload() {
return new Promise<void>((resolve, reject) => {
const fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.multiple = true;

const self = this;

fileInput.onchange = async () => {
if (fileInput.files!.length > 0) {
self.actionInProgress = true;
const totalFiles = fileInput.files!.length;

for (let i = 0; i < totalFiles; i++) {
const file = fileInput.files![i];
const fileName = file.name.toLowerCase();
const filePath = `${this.currentPath}/${file.name}`;

const reader = new FileReader();
reader.onload = async function (event) {
const fileData = new Uint8Array(event.target!.result as ArrayBuffer);
FS.writeFile(filePath, fileData, { encoding: 'binary' });

self.actionProgress = Math.round(((i + 1) / totalFiles) * 100);
console.log(`Upload Progress: ${self.actionProgress}%`);

await new Promise(resolve => setTimeout(resolve, 0));

if (i === totalFiles - 1) {
FS.syncfs(function (err: any) {
if (err) {
alert('Error syncing FS: ' + err);
console.error('Error syncing FS:', err);
} else {
self.actionInProgress = false;
}
resolve();
});

if (fileName.endsWith('.zip')) {
try {
await self.ZipExtract(file, this.currentPath);
resolve();
} catch (error) {
alert('Error extracting ZIP file: ' + error);
console.error('Error extracting ZIP file:', error);
}
};

reader.readAsArrayBuffer(file);
} else {
const reader = new FileReader();
reader.onload = async function (event) {
const fileData = new Uint8Array(event.target!.result as ArrayBuffer);
FS.writeFile(filePath, fileData, { encoding: 'binary' });

self.actionProgress = Math.round(((i + 1) / totalFiles) * 100);
console.log(`Upload Progress: ${self.actionProgress}%`);

await new Promise(resolve => setTimeout(resolve, 0));

if (i === totalFiles - 1) {
FS.syncfs(function (err: any) {
if (err) {
alert('Error syncing FS: ' + err);
console.error('Error syncing FS:', err);
} else {
self.actionInProgress = false;
}
resolve();
});
}
};
reader.readAsArrayBuffer(file);
}
}
} else {
reject('No files selected');
Expand All @@ -266,13 +335,41 @@ class EngineFS {
});
}

async FileDownload(path: string) {
async FileDownload(paths: string[]) {
try {
const blob = new Blob([FS.readFile(path)], { type: 'application/octet-stream' });
const zip = new JSZip();

const ZipFile = async (path: string, zipPath: string) => {
if (!FS.lookupPath(path).node) {
console.warn(`Tried to add ${path} to zip for export. Doesn't exist!`);
return;
}

if (this.DirCheck(path)) {
const files = FS.readdir(path);
for (const file of files) {
// these are invalid
if (file === '.' || file === '..') continue;

const filePath = `${path}/${file}`;
const zipFilePath = `${zipPath}/${file}`;

await ZipFile(filePath, zipFilePath);
}
} else {
const fileData = FS.readFile(path);
zip.file(zipPath, fileData);
}
};

for (const i of paths) {
await ZipFile(i, i.split('/').pop()!);
}

const content = await zip.generateAsync({ type: 'blob' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = path.split('/').pop() || 'download';
link.href = URL.createObjectURL(content);
link.download = 'export.zip';

document.body.appendChild(link);
link.click();
Expand All @@ -282,8 +379,8 @@ class EngineFS {
URL.revokeObjectURL(link.href);
}, 100);
} catch (error: any) {
alert('Error downloading file: ' + error);
console.error('Error downloading file:', error);
alert('Error downloading files: ' + error);
console.error('Error downloading files:', error);
throw error;
}
}
Expand Down Expand Up @@ -385,12 +482,12 @@ class EngineFS {
if (!window.confirm(`Are you sure you want to reset the FileSystem?\nJust making sure.`)) {
return;
}

// warned you twice, anything that happens after this is your fault

try {
const fsPath = '//FileSystem';

if (this.DirCheck(fsPath)) {
this.ResetFSLogic(fsPath);
await this.Save();
Expand Down
Loading

0 comments on commit f976c8b

Please sign in to comment.