Switched to integrated EEPROM client.

This commit is contained in:
flash 2025-01-04 02:50:21 +00:00
parent 77bfc10475
commit 2a191c5b19
3 changed files with 266 additions and 216 deletions

View file

@ -1,37 +1,95 @@
#include utility.js #include xhr.js
const MszEEPROM = (() => { const MszEEPROM = function(appId, endPoint) {
let eepromScript; if(typeof appId !== 'string')
throw 'appId must be a string';
if(typeof endPoint !== 'string')
throw 'endPoint must be a string';
return { return {
init: () => { create: fileInput => {
return new Promise((resolve, reject) => { if(!(fileInput instanceof File))
if(eepromScript !== undefined) { throw 'fileInput must be an instance of window.File';
resolve(false);
return;
}
if(typeof peepPath !== 'string') { let userAborted = false;
reject(); let abortHandler;
return; let progressHandler;
}
const scriptElem = $e({ const reportProgress = ev => {
tag: 'script', if(progressHandler !== undefined)
attrs: { progressHandler({
src: `${peepPath}/scripts/eepromv1a.js`, loaded: ev.loaded,
charset: 'utf-8', total: ev.total,
type: 'text/javascript', progress: ev.total <= 0 ? 0 : ev.loaded / ev.total,
onerror: () => reject(), });
onload: () => { };
eepromScript = scriptElem;
resolve(true);
},
},
});
document.body.appendChild(scriptElem); return {
abort: () => {
userAborted = true;
if(typeof abortHandler === 'function')
abortHandler();
},
onProgress: handler => {
if(typeof handler !== 'function')
throw 'handler must be a function';
progressHandler = handler;
},
start: async () => {
if(userAborted)
throw 'File upload was cancelled by the user, it cannot be restarted.';
try {
const formData = new FormData;
formData.append('src', appId);
formData.append('file', fileInput);
const { status, body } = await $x.post(`${endPoint}/uploads`, {
type: 'json',
authed: true,
upload: reportProgress,
abort: handler => abortHandler = handler,
}, formData);
if(body === null)
throw "The upload server didn't return the metadata for some reason.";
if(status !== 201)
throw body.english ?? body.error ?? `Upload failed with status code ${status}`;
body.isImage = () => body.type.startsWith('image/');
body.isVideo = () => body.type.startsWith('video/');
body.isAudio = () => body.type.startsWith('audio/');
body.isMedia = () => body.isImage() || body.isAudio() || body.isVideo();
return Object.freeze(body);
} catch(ex) {
if(userAborted)
throw '';
console.error(ex);
throw ex;
}
},
};
},
delete: async fileInfo => {
if(typeof fileInfo !== 'object')
throw 'fileInfo must be an object';
if(typeof fileInfo.urlf !== 'string')
throw 'fileInfo.urlf must be a string';
const { status, body } = await $x.delete(fileInfo.urlf, {
type: 'json',
authed: true,
}); });
if(status !== 204) {
if(body === null)
throw `Delete failed with status code ${status}`;
throw body.english ?? body.error ?? `Delete failed with status code ${status}`;
}
}, },
}; };
})(); };

View file

@ -20,150 +20,146 @@ const MszForumEditor = function(form) {
let lastPostText = '', let lastPostText = '',
lastPostParser; lastPostParser;
MszEEPROM.init() const eepromClient = new MszEEPROM(peepApp, peepPath);
.catch(() => console.error('Failed to initialise EEPROM')) const eepromHistory = <div class="eeprom-widget-history-items"/>;
.then(() => {
const eepromClient = new EEPROM(peepApp, peepPath);
const eepromHistory = <div class="eeprom-widget-history-items"/>;
const eepromHandleFileUpload = async file => { const eepromHandleFileUpload = async file => {
const uploadElemNameValue = <div class="eeprom-widget-file-name-value" title={file.name}>{file.name}</div>; const uploadElemNameValue = <div class="eeprom-widget-file-name-value" title={file.name}>{file.name}</div>;
const uploadElemName = <a class="eeprom-widget-file-name" target="_blank">{uploadElemNameValue}</a>; const uploadElemName = <a class="eeprom-widget-file-name" target="_blank">{uploadElemNameValue}</a>;
const uploadElemProgressText = <div class="eeprom-widget-file-progress">Please wait...</div>; const uploadElemProgressText = <div class="eeprom-widget-file-progress">Please wait...</div>;
const uploadElemProgressBarValue = <div class="eeprom-widget-file-bar-fill" style={{ width: '0%' }}/>; const uploadElemProgressBarValue = <div class="eeprom-widget-file-bar-fill" style={{ width: '0%' }}/>;
const uploadElem = <div class="eeprom-widget-file"> const uploadElem = <div class="eeprom-widget-file">
<div class="eeprom-widget-file-info"> <div class="eeprom-widget-file-info">
{uploadElemName} {uploadElemName}
{uploadElemProgressText} {uploadElemProgressText}
</div> </div>
<div class="eeprom-widget-file-bar"> <div class="eeprom-widget-file-bar">
{uploadElemProgressBarValue} {uploadElemProgressBarValue}
</div> </div>
</div>; </div>;
if(eepromHistory.children.length > 0) if(eepromHistory.children.length > 0)
$ib(eepromHistory.firstChild, uploadElem); $ib(eepromHistory.firstChild, uploadElem);
else else
eepromHistory.appendChild(uploadElem); eepromHistory.appendChild(uploadElem);
const explodeUploadElem = () => $r(uploadElem); const explodeUploadElem = () => $r(uploadElem);
const uploadTask = eepromClient.create(file); const uploadTask = eepromClient.create(file);
uploadTask.onProgress(prog => { uploadTask.onProgress(prog => {
uploadElemProgressBarValue.style.width = `${Math.ceil(prog.progress * 100)}%`; uploadElemProgressBarValue.style.width = `${Math.ceil(prog.progress * 100)}%`;
uploadElemProgressText.textContent = `${prog.progress.toLocaleString(undefined, { style: 'percent' })} (${prog.total - prog.loaded} bytes remaining)`; uploadElemProgressText.textContent = `${prog.progress.toLocaleString(undefined, { style: 'percent' })} (${prog.total - prog.loaded} bytes remaining)`;
}); });
try { try {
const fileInfo = await uploadTask.start(); const fileInfo = await uploadTask.start();
uploadElem.classList.add('eeprom-widget-file-done'); uploadElem.classList.add('eeprom-widget-file-done');
uploadElemName.href = fileInfo.url; uploadElemName.href = fileInfo.url;
uploadElemProgressText.textContent = ''; uploadElemProgressText.textContent = '';
const insertTheLinkIntoTheBoxEx2 = () => { const insertTheLinkIntoTheBoxEx2 = () => {
const parserMode = parseInt(parserElem.value); const parserMode = parseInt(parserElem.value);
let insertText = location.protocol + fileInfo.url; let insertText = location.protocol + fileInfo.url;
if(parserMode == 1) { // bbcode if(parserMode == 1) { // bbcode
if(fileInfo.isImage()) if(fileInfo.isImage())
insertText = `[img]${fileInfo.url}[/img]`; insertText = `[img]${fileInfo.url}[/img]`;
else if(fileInfo.isAudio()) else if(fileInfo.isAudio())
insertText = `[audio]${fileInfo.url}[/audio]`; insertText = `[audio]${fileInfo.url}[/audio]`;
else if(fileInfo.isVideo()) else if(fileInfo.isVideo())
insertText = `[video]${fileInfo.url}[/video]`; insertText = `[video]${fileInfo.url}[/video]`;
} else if(parserMode == 2) { // markdown } else if(parserMode == 2) { // markdown
if(fileInfo.isMedia()) if(fileInfo.isMedia())
insertText = `![](${fileInfo.url})`; insertText = `![](${fileInfo.url})`;
}
$insertTags(textElem, insertText, '');
textElem.value = textElem.value.trim();
};
uploadElemProgressText.appendChild(<a href="javascript:void(0)" onclick={() => insertTheLinkIntoTheBoxEx2()}>Insert</a>);
uploadElemProgressText.appendChild($t(' '));
uploadElemProgressText.appendChild(<a href="javascript:void(0)" onclick={() => {
eepromClient.delete(fileInfo)
.then(() => explodeUploadElem())
.catch(ex => {
console.error(ex);
MszShowMessageBox(ex, 'Upload Error');
});
}}>Delete</a>);
insertTheLinkIntoTheBoxEx2();
} catch(ex) {
let errorText = 'Upload aborted.';
if(!ex.aborted) {
console.error(ex);
errorText = ex.toString();
}
uploadElem.classList.add('eeprom-widget-file-fail');
uploadElemProgressText.textContent = errorText;
await MszShowMessageBox(errorText, 'Upload Error');
} }
$insertTags(textElem, insertText, '');
textElem.value = textElem.value.trim();
}; };
const eepromFormInput = <input type="file" multiple={true} class="eeprom-widget-form-input" uploadElemProgressText.appendChild(<a href="javascript:void(0)" onclick={() => insertTheLinkIntoTheBoxEx2()}>Insert</a>);
onchange={() => { uploadElemProgressText.appendChild($t(' '));
const files = eepromFormInput.files; uploadElemProgressText.appendChild(<a href="javascript:void(0)" onclick={() => {
for(const file of files) eepromClient.delete(fileInfo)
eepromHandleFileUpload(file); .then(() => explodeUploadElem())
eepromFormInput.value = ''; .catch(ex => {
}}/>; console.error(ex);
MszShowMessageBox(ex, 'Upload Error');
});
}}>Delete</a>);
const eepromForm = <label class="eeprom-widget-form"> insertTheLinkIntoTheBoxEx2();
{eepromFormInput} } catch(ex) {
<div class="eeprom-widget-form-text"> let errorText = 'Upload aborted.';
Select Files...
</div>
</label>;
const eepromWidget = <div class="eeprom-widget"> if(!ex.aborted) {
{eepromForm} console.error(ex);
<div class="eeprom-widget-history"> errorText = ex.toString();
{eepromHistory} }
</div>
</div>;
form.appendChild(eepromWidget); uploadElem.classList.add('eeprom-widget-file-fail');
uploadElemProgressText.textContent = errorText;
await MszShowMessageBox(errorText, 'Upload Error');
}
};
textElem.addEventListener('paste', ev => { const eepromFormInput = <input type="file" multiple={true} class="eeprom-widget-form-input"
if(ev.clipboardData && ev.clipboardData.files.length > 0) { onchange={() => {
ev.preventDefault(); const files = eepromFormInput.files;
for(const file of files)
eepromHandleFileUpload(file);
eepromFormInput.value = '';
}}/>;
const files = ev.clipboardData.files; const eepromForm = <label class="eeprom-widget-form">
for(const file of files) {eepromFormInput}
eepromHandleFileUpload(file); <div class="eeprom-widget-form-text">
} Select Files...
}); </div>
</label>;
document.body.addEventListener('dragenter', ev => { const eepromWidget = <div class="eeprom-widget">
ev.preventDefault(); {eepromForm}
ev.stopPropagation(); <div class="eeprom-widget-history">
}); {eepromHistory}
document.body.addEventListener('dragover', ev => { </div>
ev.preventDefault(); </div>;
ev.stopPropagation();
});
document.body.addEventListener('dragleave', ev => {
ev.preventDefault();
ev.stopPropagation();
});
document.body.addEventListener('drop', ev => {
ev.preventDefault();
ev.stopPropagation();
if(ev.dataTransfer && ev.dataTransfer.files.length > 0) { form.appendChild(eepromWidget);
const files = ev.dataTransfer.files;
for(const file of files) textElem.addEventListener('paste', ev => {
eepromHandleFileUpload(file); if(ev.clipboardData && ev.clipboardData.files.length > 0) {
} ev.preventDefault();
});
}); const files = ev.clipboardData.files;
for(const file of files)
eepromHandleFileUpload(file);
}
});
document.body.addEventListener('dragenter', ev => {
ev.preventDefault();
ev.stopPropagation();
});
document.body.addEventListener('dragover', ev => {
ev.preventDefault();
ev.stopPropagation();
});
document.body.addEventListener('dragleave', ev => {
ev.preventDefault();
ev.stopPropagation();
});
document.body.addEventListener('drop', ev => {
ev.preventDefault();
ev.stopPropagation();
if(ev.dataTransfer && ev.dataTransfer.files.length > 0) {
const files = ev.dataTransfer.files;
for(const file of files)
eepromHandleFileUpload(file);
}
});
// hack: don't prompt user when hitting submit, really need to make this not stupid. // hack: don't prompt user when hitting submit, really need to make this not stupid.
buttonsElem.firstChild.addEventListener('click', () => MszForumEditorAllowClose = true); buttonsElem.firstChild.addEventListener('click', () => MszForumEditorAllowClose = true);

View file

@ -64,77 +64,73 @@ const MszMessagesReply = function(element) {
// this implementation is godawful but it'll do for now lol // this implementation is godawful but it'll do for now lol
// need to make it easier to share the forum's implementation // need to make it easier to share the forum's implementation
MszEEPROM.init() const eepromClient = new MszEEPROM(peepApp, peepPath);
.catch(() => console.error('Failed to initialise EEPROM')) const eepromHandleFileUpload = async file => {
.then(() => { const uploadTask = eepromClient.create(file);
const eepromClient = new EEPROM(peepApp, peepPath);
const eepromHandleFileUpload = async file => {
const uploadTask = eepromClient.create(file);
try { try {
const fileInfo = await uploadTask.start(); const fileInfo = await uploadTask.start();
const parserMode = parseInt(parserSelect.value); const parserMode = parseInt(parserSelect.value);
let insertText = location.protocol + fileInfo.url; let insertText = location.protocol + fileInfo.url;
if(parserMode == 1) { // bbcode if(parserMode == 1) { // bbcode
if(fileInfo.isImage()) if(fileInfo.isImage())
insertText = `[img]${fileInfo.url}[/img]`; insertText = `[img]${fileInfo.url}[/img]`;
else if(fileInfo.isAudio()) else if(fileInfo.isAudio())
insertText = `[audio]${fileInfo.url}[/audio]`; insertText = `[audio]${fileInfo.url}[/audio]`;
else if(fileInfo.isVideo()) else if(fileInfo.isVideo())
insertText = `[video]${fileInfo.url}[/video]`; insertText = `[video]${fileInfo.url}[/video]`;
} else if(parserMode == 2) { // markdown } else if(parserMode == 2) { // markdown
if(fileInfo.isMedia()) if(fileInfo.isMedia())
insertText = `![](${fileInfo.url})`; insertText = `![](${fileInfo.url})`;
} }
$insertTags(bodyElem, insertText, ''); $insertTags(bodyElem, insertText, '');
bodyElem.value = bodyElem.value.trim(); bodyElem.value = bodyElem.value.trim();
} catch(ex) { } catch(ex) {
let errorText = 'Upload aborted.'; let errorText = 'Upload aborted.';
if(!ex.aborted) { if(!ex.aborted) {
console.error(ex); console.error(ex);
errorText = ex.toString(); errorText = ex.toString();
} }
await MszShowMessageBox(errorText, 'Upload Error'); await MszShowMessageBox(errorText, 'Upload Error');
} }
}; };
bodyElem.addEventListener('paste', ev => { bodyElem.addEventListener('paste', ev => {
if(ev.clipboardData && ev.clipboardData.files.length > 0) { if(ev.clipboardData && ev.clipboardData.files.length > 0) {
ev.preventDefault(); ev.preventDefault();
const files = ev.clipboardData.files; const files = ev.clipboardData.files;
for(const file of files) for(const file of files)
eepromHandleFileUpload(file); eepromHandleFileUpload(file);
} }
}); });
document.body.addEventListener('dragenter', ev => { document.body.addEventListener('dragenter', ev => {
ev.preventDefault(); ev.preventDefault();
ev.stopPropagation(); ev.stopPropagation();
}); });
document.body.addEventListener('dragover', ev => { document.body.addEventListener('dragover', ev => {
ev.preventDefault(); ev.preventDefault();
ev.stopPropagation(); ev.stopPropagation();
}); });
document.body.addEventListener('dragleave', ev => { document.body.addEventListener('dragleave', ev => {
ev.preventDefault(); ev.preventDefault();
ev.stopPropagation(); ev.stopPropagation();
}); });
document.body.addEventListener('drop', ev => { document.body.addEventListener('drop', ev => {
ev.preventDefault(); ev.preventDefault();
ev.stopPropagation(); ev.stopPropagation();
if(ev.dataTransfer && ev.dataTransfer.files.length > 0) { if(ev.dataTransfer && ev.dataTransfer.files.length > 0) {
const files = ev.dataTransfer.files; const files = ev.dataTransfer.files;
for(const file of files) for(const file of files)
eepromHandleFileUpload(file); eepromHandleFileUpload(file);
} }
}); });
});
return { return {
getElement: () => element, getElement: () => element,