filesafe/dist/js/home.js.map
Bobby Wibowo 1980d536db
Initialize upload filters for regular users (WIP)
Updated ESLint's ECMA version to 9 (2018).
I'll need to use some lookbehind regex directives from now on.
It's supported since Node 10, which is the oldest version I'll support.

Refactored "can not" -> "cannot".

Filtering for regular users is still work in progress.
Some features aren't working as expected yet.
2020-05-03 02:39:24 +07:00

1 line
58 KiB
Plaintext

{"version":3,"sources":["home.js"],"names":["const","lsKeys","token","chunkSize","parallelUploads","uploadsHistoryOrder","previewImages","fileLength","uploadAge","stripTags","page","localStorage","private","enableUserAccounts","maxSize","temporaryUploadAges","fileIdentifierLength","stripTagsConfig","album","maxSizeBytes","urlMaxSize","urlMaxSizeBytes","tabs","activeTab","albumSelect","albumSelectOnChange","previewTemplate","dropzone","clipboardJS","lazyLoad","urlsQueue","activeUrlsQueue","imageExts","videoExts","albumTitleMaxLength","albumDescMaxLength","onInitError","error","document","querySelector","classList","add","querySelectorAll","forEach","element","uploadButton","innerText","remove","addEventListener","location","reload","response","onAxiosError","onError","console","content","createElement","innerHTML","toString","swal","title","icon","statusText","520","521","522","523","524","525","526","527","530","status","description","data","checkClientVersion","apiVersion","match","src","text","buttons","confirm","closeModal","then","checkIfPublic","let","renderShown","axios","get","onDownloadProgress","doRender","version","parseInt","preparePage","catch","prepareUpload","verifyToken","button","href","reloadOnError","post","success","removeItem","value","prepareShareX","fetchAlbums","prepareUploadConfig","getPrettyBytes","prepareDropzone","event","addUrlsToQueue","tabsContainer","loop","i","id","dataset","tabContent","setActiveTab","push","tab","length","index","headers","Array","isArray","albums","option","name","appendChild","previewNode","parentNode","removeChild","tabDiv","div","className","previewsContainer","Dropzone","body","url","paramName","clickable","maxFilesize","uploadMultiple","createImageThumbnails","autoProcessQueue","chunking","Boolean","parallelChunkUploads","timeout","init","this","on","file","previewElement","xhr","ontimeout","instances","getUploadingFiles","filter","instance","_handleUploadError","undefined","_uplSpeedCalc","lastSent","timestamp","Date","now","bytes","upload","chunked","setRequestHeader","chunks","progress","prettyBytesPerSec","total","Math","max","size","percentage","bytesSent","toFixed","upl","prefix","skipProgress","done","last","totalChunkCount","chunkIndex","elapsed","bytesPerSec","fullSec","splice","excessDuration","duration","files","updateTemplate","test","updateTemplateIcon","chunksUploaded","uuid","original","type","albumid","filelength","age","striptags","urls","split","trim","firstChild","processUrlsQueue","shiftQueue","initUrlUpload","finishedUrlUpload","shift","templateElement","iconClass","iconElement","link","a","clipboard","clipboardText","parentElement","exec","extname","toLowerCase","includes","img","setAttribute","onerror","currentTarget","update","expirydate","expiryDate","getPrettyDate","createAlbum","cancel","download","checked","public","selected","fallback","min","config","siBytes","label","select","help","valueHandler","display","number","round","disabled","force","default","video","isNaN","suffix","uploadFields","stored","parseFloat","String","getPrettyUploadAge","form","preventDefault","configKeys","Object","keys","key","conf","field","parsed","find","sel","control","opts","j","opt","join","tmp","submit","checkValidity","elements","hours","minutes","days","window","items","clipboardData","originalEvent","item","kind","blob","getAsFile","File","addFile","onload","ClipboardJS","timer","LazyLoad","elements_selector"],"mappings":"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","file":"home.js","sourcesContent":["/* global swal, axios, Dropzone, ClipboardJS, LazyLoad */\n\nconst lsKeys = {\n token: 'token',\n chunkSize: 'chunkSize',\n parallelUploads: 'parallelUploads',\n uploadsHistoryOrder: 'uploadsHistoryOrder',\n previewImages: 'previewImages',\n fileLength: 'fileLength',\n uploadAge: 'uploadAge',\n stripTags: 'stripTags'\n}\n\nconst page = {\n // user token\n token: localStorage[lsKeys.token],\n\n // configs from api/check\n private: null,\n enableUserAccounts: null,\n maxSize: null,\n chunkSize: null,\n temporaryUploadAges: null,\n fileIdentifierLength: null,\n stripTagsConfig: null,\n\n // store album id that will be used with upload requests\n album: null,\n\n parallelUploads: 2,\n previewImages: null,\n fileLength: null,\n uploadAge: null,\n\n maxSizeBytes: null,\n urlMaxSize: null,\n urlMaxSizeBytes: null,\n\n tabs: [],\n activeTab: null,\n albumSelect: null,\n albumSelectOnChange: null,\n previewTemplate: null,\n\n dropzone: null,\n clipboardJS: null,\n lazyLoad: null,\n\n // additional vars for url uploads\n urlsQueue: [],\n activeUrlsQueue: 0,\n\n // Include BMP for uploads preview only, cause the real images will be used\n // Sharp isn't capable of making their thumbnails for dashboard and album public pages\n imageExts: ['.webp', '.jpg', '.jpeg', '.bmp', '.gif', '.png', '.tiff', '.tif', '.svg'],\n videoExts: ['.webm', '.mp4', '.wmv', '.avi', '.mov', '.mkv', '.m4v', '.m2ts'],\n\n albumTitleMaxLength: 70,\n albumDescMaxLength: 4000\n}\n\n// Handler for errors during initialization\npage.onInitError = error => {\n // Hide these elements\n document.querySelector('#albumDiv').classList.add('is-hidden')\n document.querySelector('#tabs').classList.add('is-hidden')\n document.querySelectorAll('.tab-content').forEach(element => {\n return element.classList.add('is-hidden')\n })\n\n // Update upload button\n const uploadButton = document.querySelector('#loginToUpload')\n uploadButton.innerText = 'An error occurred. Try to reload?'\n uploadButton.classList.remove('is-loading')\n uploadButton.classList.remove('is-hidden')\n\n uploadButton.addEventListener('click', () => {\n location.reload()\n })\n\n if (error.response)\n page.onAxiosError(error)\n else\n page.onError(error)\n}\n\n// Handler for regular JS errors\npage.onError = error => {\n console.error(error)\n\n const content = document.createElement('div')\n content.innerHTML = `<code>${error.toString()}</code>`\n return swal({\n title: 'An error occurred!',\n icon: 'error',\n content\n })\n}\n\n// Handler for Axios errors\npage.onAxiosError = error => {\n console.error(error)\n\n // Better Cloudflare errors\n const cloudflareErrors = {\n 520: 'Unknown Error',\n 521: 'Web Server Is Down',\n 522: 'Connection Timed Out',\n 523: 'Origin Is Unreachable',\n 524: 'A Timeout Occurred',\n 525: 'SSL Handshake Failed',\n 526: 'Invalid SSL Certificate',\n 527: 'Railgun Error',\n 530: 'Origin DNS Error'\n }\n\n const statusText = cloudflareErrors[error.response.status] || error.response.statusText\n const description = error.response.data && error.response.data.description\n ? error.response.data.description\n : 'There was an error with the request, please check the console for more information.'\n\n return swal(`${error.response.status} ${statusText}`, description, 'error')\n}\n\npage.checkClientVersion = apiVersion => {\n const self = document.querySelector('#mainScript')\n const match = self.src.match(/\\?_=(\\d+)$/)\n if (match && match[1] && match[1] !== apiVersion)\n return swal({\n title: 'Updated detected!',\n text: 'Client assets have been updated. Reload to display the latest version?',\n icon: 'info',\n buttons: {\n confirm: {\n text: 'Reload',\n closeModal: false\n }\n }\n }).then(() => {\n location.reload()\n })\n}\n\npage.checkIfPublic = () => {\n let renderShown = false\n return axios.get('api/check', {\n onDownloadProgress: () => {\n // Only show render after this request has been initiated to avoid blocking\n if (!renderShown && typeof page.doRender === 'function') {\n page.doRender()\n renderShown = true\n }\n }\n }).then(response => {\n if (response.data.version)\n page.checkClientVersion(response.data.version)\n\n page.private = response.data.private\n page.enableUserAccounts = response.data.enableUserAccounts\n page.maxSize = parseInt(response.data.maxSize)\n page.maxSizeBytes = page.maxSize * 1e6\n page.chunkSize = parseInt(response.data.chunkSize)\n page.temporaryUploadAges = response.data.temporaryUploadAges\n page.fileIdentifierLength = response.data.fileIdentifierLength\n page.stripTagsConfig = response.data.stripTags\n\n return page.preparePage()\n }).catch(page.onInitError)\n}\n\npage.preparePage = () => {\n if (page.private)\n if (page.token) {\n return page.verifyToken(page.token, true)\n } else {\n const button = document.querySelector('#loginToUpload')\n button.href = 'auth'\n button.classList.remove('is-loading')\n if (page.enableUserAccounts)\n button.innerText = 'Anonymous upload is disabled. Log in to upload.'\n else\n button.innerText = 'Running in private mode. Log in to upload.'\n }\n else\n return page.prepareUpload()\n}\n\npage.verifyToken = (token, reloadOnError) => {\n return axios.post('api/tokens/verify', { token }).then(response => {\n if (response.data.success === false)\n return swal({\n title: 'An error occurred!',\n text: response.data.description,\n icon: 'error'\n }).then(() => {\n if (!reloadOnError) return\n localStorage.removeItem('token')\n location.reload()\n })\n\n localStorage[lsKeys.token] = token\n page.token = token\n return page.prepareUpload()\n }).catch(page.onInitError)\n}\n\npage.prepareUpload = () => {\n // I think this fits best here because we need to check for a valid token before we can get the albums\n if (page.token) {\n // Display the album selection\n document.querySelector('#albumDiv').classList.remove('is-hidden')\n\n page.albumSelect = document.querySelector('#albumSelect')\n page.albumSelectOnChange = () => {\n page.album = parseInt(page.albumSelect.value)\n // Re-generate ShareX config file\n if (typeof page.prepareShareX === 'function')\n page.prepareShareX()\n }\n page.albumSelect.addEventListener('change', page.albumSelectOnChange)\n\n // Fetch albums\n page.fetchAlbums()\n }\n\n // Prepare & generate config tab\n page.prepareUploadConfig()\n\n // Update elements wherever applicable\n document.querySelector('#maxSize > span').innerHTML = page.getPrettyBytes(page.maxSizeBytes)\n document.querySelector('#loginToUpload').classList.add('is-hidden')\n\n if (!page.token && page.enableUserAccounts)\n document.querySelector('#loginLinkText').innerHTML = 'Create an account and keep track of your uploads'\n\n // Prepare & generate files upload tab\n page.prepareDropzone()\n\n // Generate ShareX config file\n if (typeof page.prepareShareX === 'function')\n page.prepareShareX()\n\n // Prepare urls upload tab\n const urlMaxSize = document.querySelector('#urlMaxSize')\n if (urlMaxSize) {\n page.urlMaxSize = parseInt(urlMaxSize.innerHTML)\n page.urlMaxSizeBytes = page.urlMaxSize * 1e6\n urlMaxSize.innerHTML = page.getPrettyBytes(page.urlMaxSizeBytes)\n document.querySelector('#uploadUrls').addEventListener('click', event => {\n page.addUrlsToQueue()\n })\n }\n\n // Get all tabs\n const tabsContainer = document.querySelector('#tabs')\n const tabs = tabsContainer.querySelectorAll('li')\n for (let i = 0; i < tabs.length; i++) {\n const id = tabs[i].dataset.id\n const tabContent = document.querySelector(`#${id}`)\n if (!tabContent) continue\n\n tabs[i].addEventListener('click', () => {\n page.setActiveTab(i)\n })\n page.tabs.push({ tab: tabs[i], content: tabContent })\n }\n\n // Set first valid tab as the default active tab\n if (page.tabs.length) {\n page.setActiveTab(0)\n tabsContainer.classList.remove('is-hidden')\n }\n}\n\npage.setActiveTab = index => {\n for (let i = 0; i < page.tabs.length; i++)\n if (i === index) {\n page.tabs[i].tab.classList.add('is-active')\n page.tabs[i].content.classList.remove('is-hidden')\n page.activeTab = index\n } else {\n page.tabs[i].tab.classList.remove('is-active')\n page.tabs[i].content.classList.add('is-hidden')\n }\n}\n\npage.fetchAlbums = () => {\n return axios.get('api/albums', { headers: { token: page.token } }).then(response => {\n if (response.data.success === false)\n return swal('An error occurred!', response.data.description, 'error')\n\n // Create an option for each album\n if (Array.isArray(response.data.albums) && response.data.albums.length)\n for (let i = 0; i < response.data.albums.length; i++) {\n const album = response.data.albums[i]\n const option = document.createElement('option')\n option.value = album.id\n option.innerHTML = album.name\n page.albumSelect.appendChild(option)\n }\n }).catch(page.onInitError)\n}\n\npage.prepareDropzone = () => {\n // Parse template element\n const previewNode = document.querySelector('#tpl')\n page.previewTemplate = previewNode.innerHTML\n previewNode.parentNode.removeChild(previewNode)\n\n // Generate files upload tab\n const tabDiv = document.querySelector('#tab-files')\n const div = document.createElement('div')\n div.className = 'control is-expanded'\n div.innerHTML = `\n <div id=\"dropzone\" class=\"button is-danger is-outlined is-fullwidth is-unselectable\">\n <span class=\"icon\">\n <i class=\"icon-upload-cloud\"></i>\n </span>\n <span>Click here or drag & drop files</span>\n </div>\n `\n tabDiv.querySelector('.dz-container').appendChild(div)\n\n const previewsContainer = tabDiv.querySelector('#tab-files .field.uploads')\n\n page.dropzone = new Dropzone(document.body, {\n url: 'api/upload',\n paramName: 'files[]',\n clickable: tabDiv.querySelector('#dropzone'),\n maxFilesize: page.maxSizeBytes / 1024 / 1024, // this option expects MiB\n parallelUploads: page.parallelUploads,\n uploadMultiple: false,\n previewsContainer,\n previewTemplate: page.previewTemplate,\n createImageThumbnails: false,\n autoProcessQueue: true,\n headers: { token: page.token },\n chunking: Boolean(page.chunkSize),\n chunkSize: page.chunkSize * 1e6, // this option expects Bytes\n parallelChunkUploads: false, // for now, enabling this breaks descriptive upload progress\n timeout: 0,\n\n init () {\n this.on('addedfile', file => {\n // Set active tab to file uploads, if necessary\n if (page.activeTab !== 0)\n page.setActiveTab(0)\n\n // Add file entry\n tabDiv.querySelector('.uploads').classList.remove('is-hidden')\n\n file.previewElement.querySelector('.name').innerHTML = file.name\n file.previewElement.querySelector('.descriptive-progress').innerHTML = 'Waiting in queue\\u2026'\n })\n\n this.on('sending', (file, xhr) => {\n // Add timeout listener (hacky method due to lack of built-in timeout handler)\n if (!xhr.ontimeout)\n xhr.ontimeout = () => {\n const instances = page.dropzone.getUploadingFiles()\n .filter(instance => instance.xhr === xhr)\n page.dropzone._handleUploadError(instances, xhr, 'Connection timed out. Try to reduce upload chunk size.')\n }\n\n // Attach necessary data for initial upload speed calculation\n if (xhr._uplSpeedCalc === undefined)\n xhr._uplSpeedCalc = {\n lastSent: 0,\n data: [{ timestamp: Date.now(), bytes: 0 }]\n }\n\n // If not chunked uploads, add extra headers\n if (!file.upload.chunked) {\n if (page.album !== null) xhr.setRequestHeader('albumid', page.album)\n if (page.fileLength !== null) xhr.setRequestHeader('filelength', page.fileLength)\n if (page.uploadAge !== null) xhr.setRequestHeader('age', page.uploadAge)\n if (page.stripTags !== null) xhr.setRequestHeader('striptags', page.stripTags)\n }\n\n if (!file.upload.chunked)\n file.previewElement.querySelector('.descriptive-progress').innerHTML = 'Uploading\\u2026'\n else if (file.upload.chunks.length === 1)\n file.previewElement.querySelector('.descriptive-progress').innerHTML = `Uploading chunk 1/${file.upload.totalChunkCount}\\u2026`\n })\n\n // Update descriptive progress\n this.on('uploadprogress', (file, progress) => {\n // Total bytes will eventually be bigger than file size when chunked\n const total = Math.max(file.size, file.upload.total)\n const percentage = (file.upload.bytesSent / total * 100).toFixed(0)\n\n const upl = file.upload.chunked\n ? file.upload.chunks[file.upload.chunks.length - 1]\n : file.upload\n const xhr = upl.xhr || file.xhr\n\n let prefix = 'Uploading\\u2026'\n let skipProgress = false\n if (file.upload.chunked) {\n const done = upl.bytesSent === upl.total\n const last = file.upload.chunks.length === file.upload.totalChunkCount\n let chunkIndex = file.upload.chunks.length\n if (done && !last) {\n chunkIndex++\n skipProgress = true\n }\n prefix = `Uploading chunk ${chunkIndex}/${file.upload.totalChunkCount}\\u2026`\n }\n\n // Real-time upload speed calculation\n let prettyBytesPerSec\n if (!skipProgress) {\n const now = Date.now()\n const bytesSent = upl.bytesSent - xhr._uplSpeedCalc.lastSent\n\n // Push data of current iteration\n xhr._uplSpeedCalc.lastSent = upl.bytesSent\n xhr._uplSpeedCalc.data.push({ timestamp: now, bytes: bytesSent })\n\n // Wait till at least the 2nd iteration (3 data including initial data)\n const length = xhr._uplSpeedCalc.data.length\n if (length > 2) {\n // Calculate using data from all iterations\n let elapsed = 0\n let bytesPerSec = 0\n let fullSec = false\n let i = length - 1 // Always start with 2nd from last item\n while (i--) {\n // Splice data of unrequired iterations\n if (fullSec) {\n xhr._uplSpeedCalc.data.splice(i, 1)\n continue\n }\n // Sum data\n elapsed = now - xhr._uplSpeedCalc.data[i].timestamp\n if (elapsed > 1000) {\n const excessDuration = elapsed - 1000\n const newerIterationElapsed = now - xhr._uplSpeedCalc.data[i + 1].timestamp\n const duration = elapsed - newerIterationElapsed\n const fragment = (duration - excessDuration) / duration * xhr._uplSpeedCalc.data[i + 1].bytes\n bytesPerSec += fragment\n fullSec = true\n } else {\n bytesPerSec += xhr._uplSpeedCalc.data[i + 1].bytes\n }\n }\n\n // If not enough data\n if (!fullSec)\n bytesPerSec = 1000 / elapsed * bytesPerSec\n\n // Get pretty bytes\n prettyBytesPerSec = page.getPrettyBytes(bytesPerSec)\n }\n }\n\n file.previewElement.querySelector('.descriptive-progress').innerHTML =\n `${prefix} ${percentage}%${prettyBytesPerSec ? ` at ${prettyBytesPerSec}/s` : ''}`\n })\n\n this.on('success', (file, data) => {\n if (!data) return\n file.previewElement.querySelector('.descriptive-progress').classList.add('is-hidden')\n\n if (data.success === false) {\n file.previewElement.querySelector('.error').innerHTML = data.description\n file.previewElement.querySelector('.error').classList.remove('is-hidden')\n }\n\n if (Array.isArray(data.files) && data.files[0])\n page.updateTemplate(file, data.files[0])\n })\n\n this.on('error', (file, error) => {\n // Clean up file size errors\n if ((typeof error === 'string' && /^File is too big/.test(error)) ||\n (typeof error === 'object' && /File too large/.test(error.description)))\n error = `File too large (${page.getPrettyBytes(file.size)}).`\n\n page.updateTemplateIcon(file.previewElement, 'icon-block')\n\n file.previewElement.querySelector('.descriptive-progress').classList.add('is-hidden')\n\n file.previewElement.querySelector('.error').innerHTML = error.description || error\n file.previewElement.querySelector('.error').classList.remove('is-hidden')\n })\n },\n\n chunksUploaded (file, done) {\n file.previewElement.querySelector('.descriptive-progress').innerHTML =\n `Rebuilding ${file.upload.totalChunkCount} chunks\\u2026`\n\n return axios.post('api/upload/finishchunks', {\n // This API supports an array of multiple files\n files: [{\n uuid: file.upload.uuid,\n original: file.name,\n type: file.type,\n albumid: page.album,\n filelength: page.fileLength,\n age: page.uploadAge\n }]\n }, {\n headers: {\n token: page.token,\n // Unlike the options above (e.g. albumid, filelength, etc.),\n // strip tags cannot yet be configured per file with this API\n striptags: page.stripTags\n }\n }).catch(error => {\n // Format error for display purpose\n return error.response.data ? error.response : {\n data: {\n success: false,\n description: error.toString()\n }\n }\n }).then(response => {\n file.previewElement.querySelector('.descriptive-progress').classList.add('is-hidden')\n\n if (response.data.success === false) {\n file.previewElement.querySelector('.error').innerHTML = response.data.description\n file.previewElement.querySelector('.error').classList.remove('is-hidden')\n }\n\n if (response.data.files && response.data.files[0])\n page.updateTemplate(file, response.data.files[0])\n\n return done()\n })\n }\n })\n}\n\npage.addUrlsToQueue = () => {\n const urls = document.querySelector('#urls').value\n .split(/\\r?\\n/)\n .filter(url => {\n return url.trim().length\n })\n\n if (!urls.length)\n return swal('An error occurred!', 'You have not entered any URLs.', 'error')\n\n const tabDiv = document.querySelector('#tab-urls')\n tabDiv.querySelector('.uploads').classList.remove('is-hidden')\n\n for (let i = 0; i < urls.length; i++) {\n const previewTemplate = document.createElement('template')\n previewTemplate.innerHTML = page.previewTemplate.trim()\n\n const previewElement = previewTemplate.content.firstChild\n previewElement.querySelector('.name').innerHTML = urls[i]\n previewElement.querySelector('.descriptive-progress').innerHTML = 'Waiting in queue\\u2026'\n\n const previewsContainer = tabDiv.querySelector('.uploads')\n previewsContainer.appendChild(previewElement)\n\n page.urlsQueue.push({\n url: urls[i],\n previewElement\n })\n }\n\n page.processUrlsQueue()\n document.querySelector('#urls').value = ''\n}\n\npage.processUrlsQueue = () => {\n if (!page.urlsQueue.length) return\n\n function finishedUrlUpload (file, data) {\n file.previewElement.querySelector('.descriptive-progress').classList.add('is-hidden')\n\n if (data.success === false) {\n const match = data.description.match(/ over limit: (\\d+)$/)\n if (match && match[1])\n data.description = `File exceeded limit of ${page.getPrettyBytes(match[1])}.`\n\n file.previewElement.querySelector('.error').innerHTML = data.description\n file.previewElement.querySelector('.error').classList.remove('is-hidden')\n }\n\n if (Array.isArray(data.files) && data.files[0])\n page.updateTemplate(file, data.files[0])\n\n page.activeUrlsQueue--\n return shiftQueue()\n }\n\n function initUrlUpload (file) {\n file.previewElement.querySelector('.descriptive-progress').innerHTML =\n 'Waiting for server to fetch URL\\u2026'\n\n return axios.post('api/upload', {\n urls: [file.url]\n }, {\n headers: {\n token: page.token,\n albumid: page.album,\n age: page.uploadAge,\n filelength: page.fileLength\n }\n }).catch(error => {\n // Format error for display purpose\n return error.response.data ? error.response : {\n data: {\n success: false,\n description: error.toString()\n }\n }\n }).then(response => {\n return finishedUrlUpload(file, response.data)\n })\n }\n\n function shiftQueue () {\n while (page.urlsQueue.length && (page.activeUrlsQueue < page.parallelUploads)) {\n page.activeUrlsQueue++\n initUrlUpload(page.urlsQueue.shift())\n }\n }\n\n return shiftQueue()\n}\n\npage.updateTemplateIcon = (templateElement, iconClass) => {\n const iconElement = templateElement.querySelector('.icon')\n if (!iconElement) return\n\n iconElement.classList.add(iconClass)\n iconElement.classList.remove('is-hidden')\n}\n\npage.updateTemplate = (file, response) => {\n if (!response.url) return\n\n const link = file.previewElement.querySelector('.link')\n const a = link.querySelector('a')\n const clipboard = file.previewElement.querySelector('.clipboard-mobile > .clipboard-js')\n a.href = a.innerHTML = clipboard.dataset.clipboardText = response.url\n\n link.classList.remove('is-hidden')\n clipboard.parentElement.classList.remove('is-hidden')\n\n const exec = /.[\\w]+(\\?|$)/.exec(response.url)\n const extname = exec && exec[0]\n ? exec[0].toLowerCase()\n : null\n\n if (page.imageExts.includes(extname))\n if (page.previewImages) {\n const img = file.previewElement.querySelector('img')\n img.setAttribute('alt', response.name || '')\n img.dataset.src = response.url\n img.classList.remove('is-hidden')\n img.onerror = event => {\n // Hide image elements that fail to load\n // Consequently include WEBP in browsers that do not have WEBP support (e.g. IE)\n event.currentTarget.classList.add('is-hidden')\n page.updateTemplateIcon(file.previewElement, 'icon-picture')\n }\n page.lazyLoad.update(file.previewElement.querySelectorAll('img'))\n } else {\n page.updateTemplateIcon(file.previewElement, 'icon-picture')\n }\n else if (page.videoExts.includes(extname))\n page.updateTemplateIcon(file.previewElement, 'icon-video')\n else\n page.updateTemplateIcon(file.previewElement, 'icon-doc-inv')\n\n if (response.expirydate) {\n const expiryDate = file.previewElement.querySelector('.expiry-date')\n expiryDate.innerHTML = `EXP: ${page.getPrettyDate(new Date(response.expirydate * 1000))}`\n expiryDate.classList.remove('is-hidden')\n }\n}\n\npage.createAlbum = () => {\n const div = document.createElement('div')\n div.innerHTML = `\n <div class=\"field\">\n <div class=\"controls\">\n <input id=\"swalName\" class=\"input\" type=\"text\" placeholder=\"Name\" maxlength=\"${page.albumTitleMaxLength}\">\n </div>\n <p class=\"help\">Max length is ${page.albumTitleMaxLength} characters.</p>\n </div>\n <div class=\"field\">\n <div class=\"control\">\n <textarea id=\"swalDescription\" class=\"textarea\" placeholder=\"Description\" rows=\"2\" maxlength=\"${page.albumDescMaxLength}\"></textarea>\n </div>\n <p class=\"help\">Max length is ${page.albumDescMaxLength} characters.</p>\n </div>\n <div class=\"field\">\n <div class=\"control\">\n <label class=\"checkbox\">\n <input id=\"swalDownload\" type=\"checkbox\" checked>\n Enable download\n </label>\n </div>\n </div>\n <div class=\"field\">\n <div class=\"control\">\n <label class=\"checkbox\">\n <input id=\"swalPublic\" type=\"checkbox\" checked>\n Enable public link\n </label>\n </div>\n </div>\n `\n\n swal({\n title: 'Create new album',\n icon: 'info',\n content: div,\n buttons: {\n cancel: true,\n confirm: {\n closeModal: false\n }\n }\n }).then(value => {\n if (!value) return\n\n const name = document.querySelector('#swalName').value.trim()\n axios.post('api/albums', {\n name,\n description: document.querySelector('#swalDescription').value.trim(),\n download: document.querySelector('#swalDownload').checked,\n public: document.querySelector('#swalPublic').checked\n }, {\n headers: {\n token: page.token\n }\n }).then(response => {\n if (response.data.success === false)\n return swal('An error occurred!', response.data.description, 'error')\n\n const option = document.createElement('option')\n page.albumSelect.appendChild(option)\n option.value = response.data.id\n option.innerHTML = name\n option.selected = true\n page.albumSelectOnChange()\n\n swal('Woohoo!', 'Album was created successfully.', 'success')\n }).catch(page.onError)\n })\n}\n\npage.prepareUploadConfig = () => {\n const fallback = {\n chunkSize: page.chunkSize,\n parallelUploads: page.parallelUploads\n }\n\n const temporaryUploadAges = Array.isArray(page.temporaryUploadAges) && page.temporaryUploadAges.length\n const fileIdentifierLength = page.fileIdentifierLength &&\n typeof page.fileIdentifierLength.min === 'number' &&\n typeof page.fileIdentifierLength.max === 'number'\n\n const config = {\n siBytes: {\n label: 'File size display',\n select: [\n { value: 'default', text: '1000 B = 1 kB = 1 Kilobyte' },\n { value: '0', text: '1024 B = 1 KiB = 1 Kibibyte' }\n ],\n help: 'This will be used in our homepage, dashboard, and album public pages.',\n valueHandler () {} // Do nothing\n },\n fileLength: {\n display: fileIdentifierLength,\n label: 'File identifier length',\n number: fileIdentifierLength ? {\n min: page.fileIdentifierLength.min,\n max: page.fileIdentifierLength.max,\n round: true\n } : undefined,\n help: true, // true means auto-generated, for number-based configs only\n disabled: fileIdentifierLength && page.fileIdentifierLength.force\n },\n uploadAge: {\n display: temporaryUploadAges,\n label: 'Upload age',\n select: [],\n help: 'Whether to automatically delete your uploads after a certain amount of time.'\n },\n stripTags: {\n display: page.stripTagsConfig,\n label: 'Strip tags',\n select: page.stripTagsConfig ? [\n { value: page.stripTagsConfig.default ? 'default' : '1', text: 'Yes' },\n { value: page.stripTagsConfig.default ? '0' : 'default', text: 'No' }\n ] : null,\n help: `Whether to strip tags (e.g. EXIF) from your uploads.<br>\n This only applies to regular image${page.stripTagsConfig && page.stripTagsConfig.video ? ' and video' : ''} uploads (i.e. not URL uploads).`,\n disabled: page.stripTagsConfig && page.stripTagsConfig.force\n },\n chunkSize: {\n display: !isNaN(page.chunkSize),\n label: 'Upload chunk size (MB)',\n number: {\n min: 1,\n max: 95,\n suffix: ' MB',\n round: true\n },\n help: true\n },\n parallelUploads: {\n label: 'Parallel uploads',\n number: {\n min: 1,\n max: 10,\n round: true\n },\n help: true\n },\n uploadsHistoryOrder: {\n label: 'Uploads history order',\n select: [\n { value: 'default', text: 'Older files on top' },\n { value: '0', text: 'Newer files on top' }\n ],\n help: `\"Newer files on top\" will use a CSS technique, which unfortunately come with <a href=\"https://developer.mozilla.org/en-US/docs/Web/CSS/flex-direction#Accessibility_Concerns\" target=\"_blank\" rel=\"noopener\">some undesirable side effects</a>.<br>\n This also affects text selection, such as when trying to select text from top to bottom will result in them being selected from bottom to top instead, and vice versa.`,\n valueHandler (value) {\n if (value === '0') {\n const uploadFields = document.querySelectorAll('.tab-content > .uploads')\n for (let i = 0; i < uploadFields.length; i++)\n uploadFields[i].classList.add('is-reversed')\n }\n }\n },\n previewImages: {\n label: 'Load images for preview',\n select: [\n { value: 'default', text: 'Yes' },\n { value: '0', text: 'No' }\n ],\n help: 'By default, uploaded images will be loaded as their previews.',\n valueHandler (value) {\n page.previewImages = value !== '0'\n }\n }\n }\n\n if (temporaryUploadAges) {\n const stored = parseFloat(localStorage[lsKeys.uploadAge])\n for (let i = 0; i < page.temporaryUploadAges.length; i++) {\n const age = page.temporaryUploadAges[i]\n config.uploadAge.select.push({\n value: i === 0 ? 'default' : String(age),\n text: page.getPrettyUploadAge(age)\n })\n if (age === stored)\n config.uploadAge.value = stored\n }\n }\n\n if (fileIdentifierLength) {\n fallback.fileLength = page.fileIdentifierLength.default || undefined\n const stored = parseInt(localStorage[lsKeys.fileLength])\n if (!page.fileIdentifierLength.force &&\n !isNaN(stored) &&\n stored >= page.fileIdentifierLength.min &&\n stored <= page.fileIdentifierLength.max)\n config.fileLength.value = stored\n }\n\n const tabContent = document.querySelector('#tab-config')\n const form = document.createElement('form')\n form.addEventListener('submit', event => event.preventDefault())\n\n const configKeys = Object.keys(config)\n for (let i = 0; i < configKeys.length; i++) {\n const key = configKeys[i]\n const conf = config[key]\n\n // Skip only if display attribute is explicitly set to false\n if (conf.display === false)\n continue\n\n const field = document.createElement('div')\n field.className = 'field'\n\n let value\n if (!conf.disabled) {\n if (conf.value !== undefined) {\n value = conf.value\n } else if (conf.number !== undefined) {\n const parsed = parseInt(localStorage[lsKeys[key]])\n if (!isNaN(parsed))\n value = parsed\n } else {\n const stored = localStorage[lsKeys[key]]\n if (Array.isArray(conf.select))\n value = conf.select.find(sel => sel.value === stored) ? stored : undefined\n else\n value = stored\n }\n\n // If valueHandler function exists, defer to the function,\n // otherwise pass value to global page object\n if (typeof conf.valueHandler === 'function')\n conf.valueHandler(value)\n else if (value !== undefined)\n page[key] = value\n }\n\n let control\n if (Array.isArray(conf.select)) {\n control = document.createElement('div')\n control.className = 'select is-fullwidth'\n\n const opts = []\n for (let j = 0; j < conf.select.length; j++) {\n const opt = conf.select[j]\n const selected = (value && (opt.value === String(value))) ||\n (value === undefined && opt.value === 'default')\n opts.push(`\n <option value=\"${opt.value}\"${selected ? ' selected' : ''}>\n ${opt.text}${opt.value === 'default' ? ' (default)' : ''}\n </option>\n `)\n }\n\n control.innerHTML = `\n <select id=\"${key}\">\n ${opts.join('\\n')}\n </select>\n `\n } else if (conf.number !== undefined) {\n control = document.createElement('input')\n control.id = control.name = key\n control.className = 'input is-fullwidth'\n control.type = 'number'\n\n if (conf.number.min !== undefined)\n control.min = conf.number.min\n if (conf.number.max !== undefined)\n control.max = conf.number.max\n if (typeof value === 'number')\n control.value = value\n else if (fallback[key] !== undefined)\n control.value = fallback[key]\n }\n\n let help\n if (conf.disabled) {\n if (Array.isArray(conf.select))\n control.querySelector('select').disabled = conf.disabled\n else\n control.disabled = conf.disabled\n help = 'This option is currently not configurable.'\n } else if (typeof conf.help === 'string') {\n help = conf.help\n } else if (conf.help === true && conf.number !== undefined) {\n const tmp = []\n\n if (fallback[key] !== undefined)\n tmp.push(`Default is ${fallback[key]}${conf.number.suffix || ''}.`)\n if (conf.number.min !== undefined)\n tmp.push(`Min is ${conf.number.min}${conf.number.suffix || ''}.`)\n if (conf.number.max !== undefined)\n tmp.push(`Max is ${conf.number.max}${conf.number.suffix || ''}.`)\n\n help = tmp.join(' ')\n }\n\n field.innerHTML = `\n <label class=\"label\">${conf.label}</label>\n <div class=\"control\"></div>\n ${help ? `<p class=\"help\">${help}</p>` : ''}\n `\n field.querySelector('div.control').appendChild(control)\n\n form.appendChild(field)\n }\n\n const submit = document.createElement('div')\n submit.className = 'field'\n submit.innerHTML = `\n <p class=\"control\">\n <button id=\"saveConfig\" type=\"submit\" class=\"button is-danger is-outlined is-fullwidth\">\n <span class=\"icon\">\n <i class=\"icon-floppy\"></i>\n </span>\n <span>Save & reload</span>\n </button>\n </p>\n <p class=\"help\">\n This configuration will only be used in this browser.<br>\n After reloading the page, some of them will also be applied to the ShareX config that you can download by clicking on the ShareX icon below.\n </p>\n `\n\n form.appendChild(submit)\n form.querySelector('#saveConfig').addEventListener('click', () => {\n if (!form.checkValidity())\n return\n\n const keys = Object.keys(config)\n .filter(key => config[key].display !== false && config[key].disabled !== true)\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i]\n\n let value\n if (config[key].select !== undefined) {\n if (form.elements[key].value !== 'default')\n value = form.elements[key].value\n } else if (config[key].number !== undefined) {\n const parsed = parseInt(form.elements[key].value)\n if (!isNaN(parsed))\n value = Math.min(Math.max(parsed, config[key].number.min), config[key].number.max)\n }\n\n if (value !== undefined && value !== fallback[key])\n localStorage[lsKeys[key]] = value\n else\n localStorage.removeItem(lsKeys[key])\n }\n\n swal({\n title: 'Woohoo!',\n text: 'Configuration saved into this browser.',\n icon: 'success'\n }).then(() => {\n location.reload()\n })\n })\n\n tabContent.appendChild(form)\n}\n\npage.getPrettyUploadAge = hours => {\n if (hours === 0) {\n return 'Permanent'\n } else if (hours < 1) {\n const minutes = hours * 60\n return `${minutes} minute${minutes === 1 ? '' : 's'}`\n } else if (hours >= 24) {\n const days = hours / 24\n return `${days} day${days === 1 ? '' : 's'}`\n } else {\n return `${hours} hour${hours === 1 ? '' : 's'}`\n }\n}\n\n// Handle image paste event\nwindow.addEventListener('paste', event => {\n const items = (event.clipboardData || event.originalEvent.clipboardData).items\n const index = Object.keys(items)\n for (let i = 0; i < index.length; i++) {\n const item = items[index[i]]\n if (item.kind === 'file') {\n const blob = item.getAsFile()\n /* eslint-disable-next-line compat/compat */\n const file = new File([blob], `pasted-image.${blob.type.match(/(?:[^/]*\\/)([^;]*)/)[1]}`, {\n type: blob.type\n })\n page.dropzone.addFile(file)\n }\n }\n})\n\nwindow.onload = () => {\n page.checkIfPublic()\n\n page.clipboardJS = new ClipboardJS('.clipboard-js')\n\n page.clipboardJS.on('success', () => {\n return swal('', 'The link has been copied to clipboard.', 'success', {\n buttons: false,\n timer: 1500\n })\n })\n\n page.clipboardJS.on('error', page.onError)\n\n page.lazyLoad = new LazyLoad({\n elements_selector: '.field.uploads img'\n })\n\n document.querySelector('#createAlbum').addEventListener('click', () => {\n page.createAlbum()\n })\n}\n"]}