diff --git a/assets/misuzu.js/ext/eeprom.js b/assets/misuzu.js/ext/eeprom.js index 1755429..80abdec 100644 --- a/assets/misuzu.js/ext/eeprom.js +++ b/assets/misuzu.js/ext/eeprom.js @@ -1,37 +1,95 @@ -#include utility.js +#include xhr.js -const MszEEPROM = (() => { - let eepromScript; +const MszEEPROM = function(appId, endPoint) { + if(typeof appId !== 'string') + throw 'appId must be a string'; + if(typeof endPoint !== 'string') + throw 'endPoint must be a string'; return { - init: () => { - return new Promise((resolve, reject) => { - if(eepromScript !== undefined) { - resolve(false); - return; - } + create: fileInput => { + if(!(fileInput instanceof File)) + throw 'fileInput must be an instance of window.File'; - if(typeof peepPath !== 'string') { - reject(); - return; - } + let userAborted = false; + let abortHandler; + let progressHandler; - const scriptElem = $e({ - tag: 'script', - attrs: { - src: `${peepPath}/scripts/eepromv1a.js`, - charset: 'utf-8', - type: 'text/javascript', - onerror: () => reject(), - onload: () => { - eepromScript = scriptElem; - resolve(true); - }, - }, - }); + const reportProgress = ev => { + if(progressHandler !== undefined) + progressHandler({ + loaded: ev.loaded, + total: ev.total, + progress: ev.total <= 0 ? 0 : ev.loaded / ev.total, + }); + }; - 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}`; + } }, }; -})(); +}; diff --git a/assets/misuzu.js/forum/editor.jsx b/assets/misuzu.js/forum/editor.jsx index d8f773e..4f89572 100644 --- a/assets/misuzu.js/forum/editor.jsx +++ b/assets/misuzu.js/forum/editor.jsx @@ -20,150 +20,146 @@ const MszForumEditor = function(form) { let lastPostText = '', lastPostParser; - MszEEPROM.init() - .catch(() => console.error('Failed to initialise EEPROM')) - .then(() => { - const eepromClient = new EEPROM(peepApp, peepPath); - const eepromHistory =
; + const eepromClient = new MszEEPROM(peepApp, peepPath); + const eepromHistory =
; - const eepromHandleFileUpload = async file => { - const uploadElemNameValue =
{file.name}
; - const uploadElemName = {uploadElemNameValue}; - const uploadElemProgressText =
Please wait...
; - const uploadElemProgressBarValue =
; - const uploadElem =
-
- {uploadElemName} - {uploadElemProgressText} -
-
- {uploadElemProgressBarValue} -
-
; + const eepromHandleFileUpload = async file => { + const uploadElemNameValue =
{file.name}
; + const uploadElemName = {uploadElemNameValue}; + const uploadElemProgressText =
Please wait...
; + const uploadElemProgressBarValue =
; + const uploadElem =
+
+ {uploadElemName} + {uploadElemProgressText} +
+
+ {uploadElemProgressBarValue} +
+
; - if(eepromHistory.children.length > 0) - $ib(eepromHistory.firstChild, uploadElem); - else - eepromHistory.appendChild(uploadElem); + if(eepromHistory.children.length > 0) + $ib(eepromHistory.firstChild, uploadElem); + else + eepromHistory.appendChild(uploadElem); - const explodeUploadElem = () => $r(uploadElem); - const uploadTask = eepromClient.create(file); + const explodeUploadElem = () => $r(uploadElem); + const uploadTask = eepromClient.create(file); - uploadTask.onProgress(prog => { - uploadElemProgressBarValue.style.width = `${Math.ceil(prog.progress * 100)}%`; - uploadElemProgressText.textContent = `${prog.progress.toLocaleString(undefined, { style: 'percent' })} (${prog.total - prog.loaded} bytes remaining)`; - }); + uploadTask.onProgress(prog => { + uploadElemProgressBarValue.style.width = `${Math.ceil(prog.progress * 100)}%`; + uploadElemProgressText.textContent = `${prog.progress.toLocaleString(undefined, { style: 'percent' })} (${prog.total - prog.loaded} bytes remaining)`; + }); - try { - const fileInfo = await uploadTask.start(); + try { + const fileInfo = await uploadTask.start(); - uploadElem.classList.add('eeprom-widget-file-done'); - uploadElemName.href = fileInfo.url; - uploadElemProgressText.textContent = ''; + uploadElem.classList.add('eeprom-widget-file-done'); + uploadElemName.href = fileInfo.url; + uploadElemProgressText.textContent = ''; - const insertTheLinkIntoTheBoxEx2 = () => { - const parserMode = parseInt(parserElem.value); - let insertText = location.protocol + fileInfo.url; + const insertTheLinkIntoTheBoxEx2 = () => { + const parserMode = parseInt(parserElem.value); + let insertText = location.protocol + fileInfo.url; - if(parserMode == 1) { // bbcode - if(fileInfo.isImage()) - insertText = `[img]${fileInfo.url}[/img]`; - else if(fileInfo.isAudio()) - insertText = `[audio]${fileInfo.url}[/audio]`; - else if(fileInfo.isVideo()) - insertText = `[video]${fileInfo.url}[/video]`; - } else if(parserMode == 2) { // markdown - if(fileInfo.isMedia()) - insertText = `![](${fileInfo.url})`; - } - - $insertTags(textElem, insertText, ''); - textElem.value = textElem.value.trim(); - }; - - uploadElemProgressText.appendChild( insertTheLinkIntoTheBoxEx2()}>Insert); - uploadElemProgressText.appendChild($t(' ')); - uploadElemProgressText.appendChild( { - eepromClient.delete(fileInfo) - .then(() => explodeUploadElem()) - .catch(ex => { - console.error(ex); - MszShowMessageBox(ex, 'Upload Error'); - }); - }}>Delete); - - 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'); + if(parserMode == 1) { // bbcode + if(fileInfo.isImage()) + insertText = `[img]${fileInfo.url}[/img]`; + else if(fileInfo.isAudio()) + insertText = `[audio]${fileInfo.url}[/audio]`; + else if(fileInfo.isVideo()) + insertText = `[video]${fileInfo.url}[/video]`; + } else if(parserMode == 2) { // markdown + if(fileInfo.isMedia()) + insertText = `![](${fileInfo.url})`; } + + $insertTags(textElem, insertText, ''); + textElem.value = textElem.value.trim(); }; - const eepromFormInput = { - const files = eepromFormInput.files; - for(const file of files) - eepromHandleFileUpload(file); - eepromFormInput.value = ''; - }}/>; + uploadElemProgressText.appendChild( insertTheLinkIntoTheBoxEx2()}>Insert); + uploadElemProgressText.appendChild($t(' ')); + uploadElemProgressText.appendChild( { + eepromClient.delete(fileInfo) + .then(() => explodeUploadElem()) + .catch(ex => { + console.error(ex); + MszShowMessageBox(ex, 'Upload Error'); + }); + }}>Delete); - const eepromForm = ; + insertTheLinkIntoTheBoxEx2(); + } catch(ex) { + let errorText = 'Upload aborted.'; - const eepromWidget =
- {eepromForm} -
- {eepromHistory} -
-
; + if(!ex.aborted) { + console.error(ex); + errorText = ex.toString(); + } - form.appendChild(eepromWidget); + uploadElem.classList.add('eeprom-widget-file-fail'); + uploadElemProgressText.textContent = errorText; + await MszShowMessageBox(errorText, 'Upload Error'); + } + }; - textElem.addEventListener('paste', ev => { - if(ev.clipboardData && ev.clipboardData.files.length > 0) { - ev.preventDefault(); + const eepromFormInput = { + const files = eepromFormInput.files; + for(const file of files) + eepromHandleFileUpload(file); + eepromFormInput.value = ''; + }}/>; - const files = ev.clipboardData.files; - for(const file of files) - eepromHandleFileUpload(file); - } - }); + const eepromForm = ; - 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(); + const eepromWidget =
+ {eepromForm} +
+ {eepromHistory} +
+
; - if(ev.dataTransfer && ev.dataTransfer.files.length > 0) { - const files = ev.dataTransfer.files; - for(const file of files) - eepromHandleFileUpload(file); - } - }); - }); + form.appendChild(eepromWidget); + + textElem.addEventListener('paste', ev => { + 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. buttonsElem.firstChild.addEventListener('click', () => MszForumEditorAllowClose = true); diff --git a/assets/misuzu.js/messages/reply.jsx b/assets/misuzu.js/messages/reply.jsx index e72d4a3..4660a8f 100644 --- a/assets/misuzu.js/messages/reply.jsx +++ b/assets/misuzu.js/messages/reply.jsx @@ -64,77 +64,73 @@ const MszMessagesReply = function(element) { // this implementation is godawful but it'll do for now lol // need to make it easier to share the forum's implementation - MszEEPROM.init() - .catch(() => console.error('Failed to initialise EEPROM')) - .then(() => { - const eepromClient = new EEPROM(peepApp, peepPath); - const eepromHandleFileUpload = async file => { - const uploadTask = eepromClient.create(file); + const eepromClient = new MszEEPROM(peepApp, peepPath); + const eepromHandleFileUpload = async file => { + const uploadTask = eepromClient.create(file); - try { - const fileInfo = await uploadTask.start(); - const parserMode = parseInt(parserSelect.value); - let insertText = location.protocol + fileInfo.url; + try { + const fileInfo = await uploadTask.start(); + const parserMode = parseInt(parserSelect.value); + let insertText = location.protocol + fileInfo.url; - if(parserMode == 1) { // bbcode - if(fileInfo.isImage()) - insertText = `[img]${fileInfo.url}[/img]`; - else if(fileInfo.isAudio()) - insertText = `[audio]${fileInfo.url}[/audio]`; - else if(fileInfo.isVideo()) - insertText = `[video]${fileInfo.url}[/video]`; - } else if(parserMode == 2) { // markdown - if(fileInfo.isMedia()) - insertText = `![](${fileInfo.url})`; - } + if(parserMode == 1) { // bbcode + if(fileInfo.isImage()) + insertText = `[img]${fileInfo.url}[/img]`; + else if(fileInfo.isAudio()) + insertText = `[audio]${fileInfo.url}[/audio]`; + else if(fileInfo.isVideo()) + insertText = `[video]${fileInfo.url}[/video]`; + } else if(parserMode == 2) { // markdown + if(fileInfo.isMedia()) + insertText = `![](${fileInfo.url})`; + } - $insertTags(bodyElem, insertText, ''); - bodyElem.value = bodyElem.value.trim(); - } catch(ex) { - let errorText = 'Upload aborted.'; + $insertTags(bodyElem, insertText, ''); + bodyElem.value = bodyElem.value.trim(); + } catch(ex) { + let errorText = 'Upload aborted.'; - if(!ex.aborted) { - console.error(ex); - errorText = ex.toString(); - } + if(!ex.aborted) { + console.error(ex); + errorText = ex.toString(); + } - await MszShowMessageBox(errorText, 'Upload Error'); - } - }; + await MszShowMessageBox(errorText, 'Upload Error'); + } + }; - bodyElem.addEventListener('paste', ev => { - if(ev.clipboardData && ev.clipboardData.files.length > 0) { - ev.preventDefault(); + bodyElem.addEventListener('paste', ev => { + if(ev.clipboardData && ev.clipboardData.files.length > 0) { + ev.preventDefault(); - const files = ev.clipboardData.files; - for(const file of files) - eepromHandleFileUpload(file); - } - }); + 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(); + 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); - } - }); - }); + if(ev.dataTransfer && ev.dataTransfer.files.length > 0) { + const files = ev.dataTransfer.files; + for(const file of files) + eepromHandleFileUpload(file); + } + }); return { getElement: () => element,