add all funtionality to file browser and style it a bit

This commit is contained in:
thelamer 2022-01-08 13:53:26 -08:00
parent 2285047e4e
commit e5e478c3ea
3 changed files with 168 additions and 12 deletions

View File

@ -0,0 +1,40 @@
.hidden {
display: none;
}
.right {
float: right;
margin-right: 5px;
}
.directory, .file {
cursor: pointer;
}
button {
border: 2px solid #000;
background: transparent;
cursor: pointer;
margin: 5px;
}
.fileTable {
font-family: Arial, Helvetica, sans-serif;
border-collapse: collapse;
width: 100%;
margin-top: 10px;
}
td, th {
border: 2px solid #ddd;
padding: 8px;
}
tr:nth-child(even){
background-color: #f2f2f2;
}
tr:hover {
background-color: #ddd;
}

View File

@ -9,7 +9,13 @@
</head>
<body>
<span id="buttons">
<button onclick="downloadBackup()">DL Full Backup</button>
<input id="folderName" type="text" placeholder="Enter Directory Name"></input>
<button onclick="createFolder()">Create Folder</button>
<button onclick="$('#uploadInput').trigger( 'click' )">Upload File</button>
<input class="hidden" id="uploadInput" type='file' onchange="upload(this);" />
<button class="right" onclick="downloadBackup()">DL Full Backup</button>
<button class="right" onclick="$('#uploadBackup').trigger( 'click' )">Upload Full Backup</button>
<input class="hidden" id="uploadBackup" type='file' onchange="uploadBackup(this);" />
</span>
<div id="filebrowser"></div>
</body>

View File

@ -1,4 +1,5 @@
//Default vars
var storeName = 'RetroArch';
var afs;
BrowserFS.install(window);
var fs = require('fs');
@ -16,21 +17,36 @@ async function renderFiles(directory) {
let items = await fs.readdirSync(directory);
let baseName = directory.split('/').at(-1);
let parentFolder = directory.replace(baseName,'');
let parentLink = $('<div>').addClass('directory').attr('onclick', 'renderFiles(\'' + parentFolder + '\');').text('..');
if (directory == '/') {
directory = '';
let parentLink = $('<td>').addClass('directory').attr('onclick', 'renderFiles(\'' + parentFolder + '\');').text('..');
if (directoryClean == '/') {
directoryClean = '';
}
$('#filebrowser').append(parentLink);
let table = $('<table>').addClass('fileTable');
let tableHeader = $('<tr>');
for await (name of ['Name', 'Type', 'Delete']) {
tableHeader.append($('<th>').text(name));
}
let parentRow = $('<tr>');
for await (item of [parentLink, $('<td>').text('Parent'), $('<td>')]) {
parentRow.append(item);
}
table.append(tableHeader,parentRow);
$('#filebrowser').append(table);
if (items.length > 0) {
for await (let item of items) {
let tableRow = $('<tr>');
let itemClean = item.replace("'","|");
if (fs.lstatSync(directory + '/' + item).isDirectory()) {
let link = $('<div>').addClass('directory').attr('onclick', 'renderFiles(\'' + directoryClean + '/' + itemClean + '\');').text(item);
$('#filebrowser').append(link);
var link = $('<td>').addClass('directory').attr('onclick', 'renderFiles(\'' + directoryClean + '/' + itemClean + '\');').text(item);
var type = $('<td>').text('Dir');
} else {
let link = $('<div>').addClass('file').attr('onclick', 'downloadFile(\'' + directoryClean + '/' + itemClean + '\');').text(item);
$('#filebrowser').append(link);
var link = $('<td>').addClass('file').attr('onclick', 'downloadFile(\'' + directoryClean + '/' + itemClean + '\');').text(item);
var type = $('<td>').text('File');
}
for await (item of [link, type, $('<td>')]) {
tableRow.append(item);
}
table.append(tableRow);
}
}
}
@ -51,6 +67,48 @@ async function downloadFile(file) {
$("body").remove(a);
}
// Upload file to current directory
async function upload(input) {
let directory = $('#filebrowser').data('directory');
if (directory == '/') {
directoryUp = '';
} else {
directoryUp = directory;
}
if (input.files && input.files[0]) {
let reader = new FileReader();
reader.onload = function(e) {
let fileName = input.files[0].name;
let data = e.target.result;
fs.writeFileSync(directoryUp + '/' + fileName, Buffer.from(data));
renderFiles(directory);
}
reader.readAsArrayBuffer(input.files[0]);
}
}
// Create a directory
async function createFolder() {
let folderName = $('#folderName').val();
$('#folderName').val('');
if ((folderName.length == 0) || (folderName.includes('/'))) {
alert('Bad or Null Directory Name');
return '';
}
let directory = $('#filebrowser').data('directory');
if (directory == '/') {
directoryUp = '';
} else {
directoryUp = directory;
}
let createD = directoryUp + '/' + folderName;
if (!fs.existsSync(createD)){
fs.mkdirSync(createD);
}
renderFiles(directory);
}
// Download a full backup of all files
async function downloadBackup() {
var zip = new JSZip();
@ -77,7 +135,7 @@ async function downloadBackup() {
let url = window.URL || window.webkitURL;
link = url.createObjectURL(blob);
let a = $("<a />");
a.attr("download", 'emulatorjs.zip');
a.attr("download", storeName + '.zip');
a.attr("href", link);
$("body").append(a);
a[0].click();
@ -85,7 +143,59 @@ async function downloadBackup() {
});
}
// Create IndexDB filestore
// Upload a full backup
async function uploadBackup(input) {
if (input.files && input.files[0]) {
let reader = new FileReader();
reader.onload = async function(e) {
let data = e.target.result;
var zip = new JSZip();
// Load zip from data
zip.loadAsync(data).then(async function(contents) {
// Purge current storage
async function rmDir(dirPath, removeSelf) {
try { var files = fs.readdirSync(dirPath); }
catch(e) { return; }
if (files.length > 0) {
for await (let file of files) {
var filePath = dirPath + '/' + file;
if (fs.statSync(filePath).isFile()) {
fs.unlinkSync(filePath);
} else {
rmDir(filePath);
}
}
}
if (dirPath !== '/') {
fs.rmdirSync(dirPath)
}
return '';
}
await rmDir('/');
// Unzip the files to the FS by name
for await (let fileName of Object.keys(contents.files)) {
if (fileName.endsWith('/')) {
if (! fs.existsSync('/' + fileName)) {
fs.mkdirSync('/' + fileName);
}
}
}
for await (let fileName of Object.keys(contents.files)) {
if (! fileName.endsWith('/')) {
zip.file(fileName).async('arraybuffer').then(function(content) {
fs.writeFileSync('/' + fileName, Buffer.from(content));
});
}
}
await new Promise(resolve => setTimeout(resolve, 2000));
renderFiles('/');
});
}
reader.readAsArrayBuffer(input.files[0]);
}
}
// Create Async filestore
async function setupFileSystem() {
var imfs = new BrowserFS.FileSystem.InMemory();
afs = new BrowserFS.FileSystem.AsyncMirror(imfs,
@ -95,7 +205,7 @@ async function setupFileSystem() {
setupMounts();
});
},
'RetroArch'));
storeName));
};
// Setup mounts