From cd69b63583107d52ed11ef856cd9514ff0922416 Mon Sep 17 00:00:00 2001 From: Wim Brand Date: Mon, 27 Jan 2020 16:56:16 +0100 Subject: [PATCH] go from classes to prototypes --- res/include/img/icons/pixeldrain.svg | 3 + .../script/dependencies/UploadManager.js | 302 +++++++------- .../script/file_viewer/DetailsWindow.js | 294 +++++++------- .../script/file_viewer/ListNavigator.js | 307 +++++++------- res/include/script/file_viewer/Toolbar.js | 307 +++++++------- res/include/script/file_viewer/Viewer.js | 373 +++++++++--------- .../file_viewer/viewer_scripts/AudioViewer.js | 56 ++- .../file_viewer/viewer_scripts/FileViewer.js | 48 ++- .../file_viewer/viewer_scripts/ImageViewer.js | 146 ++++--- .../file_viewer/viewer_scripts/PDFViewer.js | 24 +- .../file_viewer/viewer_scripts/TextViewer.js | 106 +++-- .../file_viewer/viewer_scripts/VideoViewer.js | 40 +- res/include/script/homepage.js | 144 ++++--- res/include/script/textupload.js | 2 +- res/include/style/layout.css | 80 +++- res/include/style/viewer.css | 6 + res/template/file_viewer.html | 9 +- res/template/home.html | 13 +- webcontroller/{viewer.go => file_viewer.go} | 1 - 19 files changed, 1147 insertions(+), 1114 deletions(-) create mode 100644 res/include/img/icons/pixeldrain.svg rename webcontroller/{viewer.go => file_viewer.go} (99%) diff --git a/res/include/img/icons/pixeldrain.svg b/res/include/img/icons/pixeldrain.svg new file mode 100644 index 0000000..ad45108 --- /dev/null +++ b/res/include/img/icons/pixeldrain.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/include/script/dependencies/UploadManager.js b/res/include/script/dependencies/UploadManager.js index 7e45758..7492e52 100644 --- a/res/include/script/dependencies/UploadManager.js +++ b/res/include/script/dependencies/UploadManager.js @@ -1,170 +1,168 @@ -class UploadManager { - constructor(apiAddress, uploadsFinished) {let um = this; +function UploadManager(apiAddress, uploadsFinished) {let um = this; - um.apiAddress = apiAddress; + um.apiAddress = apiAddress; - // Callback function for when the queue is empty - um.uploadsFinished = uploadsFinished; + // Callback function for when the queue is empty + um.uploadsFinished = uploadsFinished; - // Counts the total number of upload jobs - um.jobCounter = 0; + // Counts the total number of upload jobs + um.jobCounter = 0; - // Queue of files to be uploaded. Format: - // { - // jobID: number, - // file: Blob, - // name: string, - // onProgress: function, - // onFinished: function, - // onFailure: function, - // tries: number - // } - um.uploadQueue = []; + // Queue of files to be uploaded. Format: + // { + // jobID: number, + // file: Blob, + // name: string, + // onProgress: function, + // onFinished: function, + // onFailure: function, + // tries: number + // } + um.uploadQueue = []; - // Here we put successful jobs. The array should be sorted by job ID. - // Format: - // { jobID: number, fileID: string, fileName: string } - um.uploadLog = []; + // Here we put successful jobs. The array should be sorted by job ID. + // Format: + // { jobID: number, fileID: string, fileName: string } + um.uploadLog = []; - // Max number of uploading threads at once - um.maxWorkers = 3; + // Max number of uploading threads at once + um.maxWorkers = 3; - // Threads which are currently uploading - um.activeWorkers = 0; + // Threads which are currently uploading + um.activeWorkers = 0; - // Total number of jobs accepted - um.jobCounter = 0; - } + // Total number of jobs accepted + um.jobCounter = 0; +} - finishedUploads() {let um = this; - um.uploadLog.sort(function(a, b) { - return a.jobID - b.jobID; - }) - return um.uploadLog; - } +UploadManager.prototype.finishedUploads = function() {let um = this; + um.uploadLog.sort(function(a, b) { + return a.jobID - b.jobID; + }) + return um.uploadLog; +} - addFile( - file, // Blob - name, // string - onProgress, // func (progress: number) - onFinished, // func (id: string) - onFailure // func (errorID: string, errorMessage: string) - ) {let um = this; - um.uploadQueue.push({ - jobID: um.jobCounter, - file: file, - name: name, - onProgress: onProgress, - onFinished: onFinished, - onFailure: onFailure, - tries: 0 - }); +UploadManager.prototype.addFile = function( + file, // Blob + name, // string + onProgress, // func (progress: number) + onFinished, // func (id: string) + onFailure // func (errorID: string, errorMessage: string) +) {let um = this; + um.uploadQueue.push({ + jobID: um.jobCounter, + file: file, + name: name, + onProgress: onProgress, + onFinished: onFinished, + onFailure: onFailure, + tries: 0 + }); - // Increment the job counter - um.jobCounter++ + // Increment the job counter + um.jobCounter++ - if (um.activeWorkers < um.maxWorkers) { - // Run the upload function - um.startUpload(); - } - } - - startUpload() {let um = this; - if (um.uploadQueue.length === 0) { - return; // Nothing to upload - } - - if (um.activeWorkers < um.maxWorkers) { - um.activeWorkers++; - um.uploadThread(); - } - } - - finishUpload() {let um = this; - um.activeWorkers--; - - if ( - um.uploadQueue.length === 0 && - um.activeWorkers === 0 && - typeof(um.uploadsFinished) === "function" - ) { - um.uploadsFinished(); - return; - } - - // Run the upload function for the next file + if (um.activeWorkers < um.maxWorkers) { + // Run the upload function um.startUpload(); } +} - uploadThread() {let um = this; - let job = um.uploadQueue.shift(); // Get the first element of the array - console.debug("Starting upload of " + job.name); +UploadManager.prototype.startUpload = function() {let um = this; + if (um.uploadQueue.length === 0) { + return; // Nothing to upload + } - let form = new FormData(); - form.append("name", job.name); - form.append('file', job.file); - - let xhr = new XMLHttpRequest(); - xhr.open("POST", um.apiAddress + "/file", true); - xhr.timeout = 21600000; // 6 hours, to account for slow connections - - // Report progress updates back to the caller - xhr.upload.addEventListener("progress", function (evt) { - if (evt.lengthComputable && typeof(job.onProgress) === "function") { - job.onProgress(evt.loaded / evt.total); - } - }); - - xhr.onreadystatechange = function () { - // readystate 4 means the upload is done - if (xhr.readyState !== 4) { return; } - - if (xhr.status >= 100 && xhr.status < 400) { - // Request is a success - let resp = JSON.parse(xhr.response); - addUploadHistory(resp.id) - - // Log the successful job - um.uploadLog.push({ - jobID: job.jobID, - fileID: resp.id, - fileName: job.name - }); - - if (typeof(job.onFinished) === "function") { - job.onFinished(resp.id); - } - - // Finish the upload job - um.finishUpload(); - } else if (xhr.status >= 400) { - // Request failed - console.log("Upload error. status: " + xhr.status + " response: " + xhr.response); - let resp = JSON.parse(xhr.response); - if (job.tries === 3) { // Upload failed - job.onFailure(resp.value, resp.message); - } else { // Try again - job.tries++; - um.uploadQueue.push(job); - } - - // Sleep the upload thread for 5 seconds - window.setTimeout(() => { um.finishUpload(); }, 5000); - } else { - // Request did not arrive - if (job.tries === 3) { // Upload failed - if (typeof(job.onFailure) === "function") { - job.onFailure(xhr.response, xhr.response); - } - } else { // Try again - job.tries++; - um.uploadQueue.push(job); - } - - // Sleep the upload thread for 5 seconds - window.setTimeout(() => { um.finishUpload(); }, 5000); - } - }; - xhr.send(form); + if (um.activeWorkers < um.maxWorkers) { + um.activeWorkers++; + um.uploadThread(); } } + +UploadManager.prototype.finishUpload = function() {let um = this; + um.activeWorkers--; + + if ( + um.uploadQueue.length === 0 && + um.activeWorkers === 0 && + typeof(um.uploadsFinished) === "function" + ) { + um.uploadsFinished(); + return; + } + + // Run the upload function for the next file + um.startUpload(); +} + +UploadManager.prototype.uploadThread = function() {let um = this; + let job = um.uploadQueue.shift(); // Get the first element of the array + console.debug("Starting upload of " + job.name); + + let form = new FormData(); + form.append("name", job.name); + form.append('file', job.file); + + let xhr = new XMLHttpRequest(); + xhr.open("POST", um.apiAddress + "/file", true); + xhr.timeout = 21600000; // 6 hours, to account for slow connections + + // Report progress updates back to the caller + xhr.upload.addEventListener("progress", function (evt) { + if (evt.lengthComputable && typeof(job.onProgress) === "function") { + job.onProgress(evt.loaded / evt.total); + } + }); + + xhr.onreadystatechange = function () { + // readystate 4 means the upload is done + if (xhr.readyState !== 4) { return; } + + if (xhr.status >= 100 && xhr.status < 400) { + // Request is a success + let resp = JSON.parse(xhr.response); + addUploadHistory(resp.id) + + // Log the successful job + um.uploadLog.push({ + jobID: job.jobID, + fileID: resp.id, + fileName: job.name + }); + + if (typeof(job.onFinished) === "function") { + job.onFinished(resp.id); + } + + // Finish the upload job + um.finishUpload(); + } else if (xhr.status >= 400) { + // Request failed + console.log("Upload error. status: " + xhr.status + " response: " + xhr.response); + let resp = JSON.parse(xhr.response); + if (job.tries === 3) { // Upload failed + job.onFailure(resp.value, resp.message); + } else { // Try again + job.tries++; + um.uploadQueue.push(job); + } + + // Sleep the upload thread for 5 seconds + window.setTimeout(() => { um.finishUpload(); }, 5000); + } else { + // Request did not arrive + if (job.tries === 3) { // Upload failed + if (typeof(job.onFailure) === "function") { + job.onFailure(xhr.response, xhr.response); + } + } else { // Try again + job.tries++; + um.uploadQueue.push(job); + } + + // Sleep the upload thread for 5 seconds + window.setTimeout(() => { um.finishUpload(); }, 5000); + } + }; + xhr.send(form); +} diff --git a/res/include/script/file_viewer/DetailsWindow.js b/res/include/script/file_viewer/DetailsWindow.js index df8a5c9..f2d0a12 100644 --- a/res/include/script/file_viewer/DetailsWindow.js +++ b/res/include/script/file_viewer/DetailsWindow.js @@ -1,154 +1,152 @@ -class DetailsWindow { - constructor(viewer) {let dw = this; - dw.viewer = viewer; +function DetailsWindow(viewer) {let dw = this; + dw.viewer = viewer; + dw.visible = false; + dw.fileID = ""; + dw.graph = 0; + + dw.divPopup = document.getElementById("details_popup"); + dw.btnDetails = document.getElementById("btn_details"); + dw.btnCloseDetails = document.getElementById("btn_close_details"); + dw.divFileDetails = document.getElementById("info_file_details"); + + dw.btnDetails.addEventListener("click", () => { dw.toggle(); }); + dw.btnCloseDetails.addEventListener("click", () => { dw.toggle(); }); +} + +DetailsWindow.prototype.toggle = function() {let dw = this; + if (dw.visible) { + dw.divPopup.style.opacity = "0"; + dw.divPopup.style.visibility = "hidden"; + dw.btnDetails.classList.remove("button_highlight"); dw.visible = false; - dw.fileID = ""; - dw.graph = 0; + } else { + dw.divPopup.style.opacity = "1"; + dw.divPopup.style.visibility = "visible"; + dw.btnDetails.classList.add("button_highlight"); + dw.visible = true; - dw.divPopup = document.getElementById("details_popup"); - dw.btnDetails = document.getElementById("btn_details"); - dw.btnCloseDetails = document.getElementById("btn_close_details"); - dw.divFileDetails = document.getElementById("info_file_details"); + // This is a workaround for a chrome bug which makes it so hidden + // windows can't be scrolled after they are shown + dw.divPopup.focus(); - dw.btnDetails.addEventListener("click", () => { dw.toggle(); }); - dw.btnCloseDetails.addEventListener("click", () => { dw.toggle(); }); - } - - toggle() {let dw = this; - if (dw.visible) { - dw.divPopup.style.opacity = "0"; - dw.divPopup.style.visibility = "hidden"; - dw.btnDetails.classList.remove("button_highlight"); - dw.visible = false; - } else { - dw.divPopup.style.opacity = "1"; - dw.divPopup.style.visibility = "visible"; - dw.btnDetails.classList.add("button_highlight"); - dw.visible = true; - - // This is a workaround for a chrome bug which makes it so hidden - // windows can't be scrolled after they are shown - dw.divPopup.focus(); - - if (dw.graph === 0) { - dw.renderGraph(); - } - dw.updateGraph(dw.fileID); + if (dw.graph === 0) { + dw.renderGraph(); } - } - - setDetails(file) {let dw = this; - let desc = ""; - if (dw.viewer.isList) { - desc = file.description; - } - dw.fileID = file.id; - dw.divFileDetails.innerHTML = "" - + "" - + "" - + "" - + "" - + "" - + "" - + "" - + "" - + "
Name" + escapeHTML(file.name) + "
URL"+domainURL()+"/u/" + file.id + "
Mime Type" + escapeHTML(file.mime_type) + "
ID" + file.id + "
Size" + formatDataVolume(file.size, 4) + "
Bandwidth" + formatDataVolume(file.bandwidth_used, 4) + "
Upload Date" + file.date_upload + "
Description" + escapeHTML(desc) + "
"; - - if(dw.visible) { - dw.updateGraph(file.id); - } - } - - updateGraph(fileID) {let dw = this; - console.log("updating graph "+fileID); - fetch(apiEndpoint+"/file/" + fileID + "/timeseries?interval=60?days=14").then(resp => { - if (!resp.ok) {return null;} - return resp.json(); - }).then(resp => { - dw.graph.data.labels = resp.labels; - dw.graph.data.datasets[0].data = resp.downloads; - dw.graph.data.datasets[1].data = resp.views; - dw.graph.update(); - }) - } - - renderGraph() {let dw = this; - console.log("rendering graph"); - Chart.defaults.global.defaultFontColor = "#b3b3b3"; - Chart.defaults.global.defaultFontSize = 15; - Chart.defaults.global.defaultFontFamily = "Ubuntu"; - Chart.defaults.global.aspectRatio = 2.5; - Chart.defaults.global.elements.point.radius = 0; - Chart.defaults.global.tooltips.mode = "index"; - Chart.defaults.global.tooltips.axis = "x"; - Chart.defaults.global.tooltips.intersect = false; - dw.graph = new Chart( - document.getElementById('bandwidth_chart'), - { - type: 'line', - data: { - datasets: [ - { - label: "Downloads", - backgroundColor: "rgba(64, 255, 64, .05)", - borderColor: "rgba(128, 255, 128, 1)", - borderWidth: 1.5, - lineTension: 0.1, - fill: true, - yAxisID: "y_bandwidth", - }, { - label: "Views", - backgroundColor: "rgba(64, 64, 255, .1)", - borderColor: "rgba(128, 128, 255, 1)", - borderWidth: 1.5, - lineTension: 0.1, - fill: true, - yAxisID: "y_views", - } - ] - }, - options: { - scales: { - yAxes: [ - { - type: "linear", - display: true, - position: "left", - id: "y_bandwidth", - scaleLabel: { - display: true, - labelString: "Downloads" - }, - gridLines: { - color: "rgba(100, 255, 100, .1)" - } - }, { - type: "linear", - display: true, - position: "right", - id: "y_views", - scaleLabel: { - display: true, - labelString: "Views" - }, - gridLines: { - color: "rgba(128, 128, 255, .2)" - } - } - ], - xAxes: [ - { - ticks: { - maxRotation: 20 - }, - gridLines: { - display: false - } - } - ] - } - } - } - ); + dw.updateGraph(dw.fileID); } } + +DetailsWindow.prototype.setDetails = function(file) {let dw = this; + let desc = ""; + if (dw.viewer.isList) { + desc = file.description; + } + dw.fileID = file.id; + dw.divFileDetails.innerHTML = "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "
Name" + escapeHTML(file.name) + "
URL"+domainURL()+"/u/" + file.id + "
Mime Type" + escapeHTML(file.mime_type) + "
ID" + file.id + "
Size" + formatDataVolume(file.size, 4) + "
Bandwidth" + formatDataVolume(file.bandwidth_used, 4) + "
Upload Date" + file.date_upload + "
Description" + escapeHTML(desc) + "
"; + + if(dw.visible) { + dw.updateGraph(file.id); + } +} + +DetailsWindow.prototype.updateGraph = function(fileID) {let dw = this; + console.log("updating graph "+fileID); + fetch(apiEndpoint+"/file/" + fileID + "/timeseries?interval=60?days=14").then(resp => { + if (!resp.ok) {return null;} + return resp.json(); + }).then(resp => { + dw.graph.data.labels = resp.labels; + dw.graph.data.datasets[0].data = resp.downloads; + dw.graph.data.datasets[1].data = resp.views; + dw.graph.update(); + }) +} + +DetailsWindow.prototype.renderGraph = function() {let dw = this; + console.log("rendering graph"); + Chart.defaults.global.defaultFontColor = "#b3b3b3"; + Chart.defaults.global.defaultFontSize = 15; + Chart.defaults.global.defaultFontFamily = "Ubuntu"; + Chart.defaults.global.aspectRatio = 2.5; + Chart.defaults.global.elements.point.radius = 0; + Chart.defaults.global.tooltips.mode = "index"; + Chart.defaults.global.tooltips.axis = "x"; + Chart.defaults.global.tooltips.intersect = false; + dw.graph = new Chart( + document.getElementById('bandwidth_chart'), + { + type: 'line', + data: { + datasets: [ + { + label: "Downloads", + backgroundColor: "rgba(64, 255, 64, .05)", + borderColor: "rgba(128, 255, 128, 1)", + borderWidth: 1.5, + lineTension: 0.1, + fill: true, + yAxisID: "y_bandwidth", + }, { + label: "Views", + backgroundColor: "rgba(64, 64, 255, .1)", + borderColor: "rgba(128, 128, 255, 1)", + borderWidth: 1.5, + lineTension: 0.1, + fill: true, + yAxisID: "y_views", + } + ] + }, + options: { + scales: { + yAxes: [ + { + type: "linear", + display: true, + position: "left", + id: "y_bandwidth", + scaleLabel: { + display: true, + labelString: "Downloads" + }, + gridLines: { + color: "rgba(100, 255, 100, .1)" + } + }, { + type: "linear", + display: true, + position: "right", + id: "y_views", + scaleLabel: { + display: true, + labelString: "Views" + }, + gridLines: { + color: "rgba(128, 128, 255, .2)" + } + } + ], + xAxes: [ + { + ticks: { + maxRotation: 20 + }, + gridLines: { + display: false + } + } + ] + } + } + } + ); +} diff --git a/res/include/script/file_viewer/ListNavigator.js b/res/include/script/file_viewer/ListNavigator.js index bc17efe..29d9451 100644 --- a/res/include/script/file_viewer/ListNavigator.js +++ b/res/include/script/file_viewer/ListNavigator.js @@ -1,181 +1,180 @@ -class ListNavigator { - constructor(viewer, data){let ln = this; - ln.viewer = viewer; - ln.data = data; - ln.length = data.length; +function ListNavigator(viewer, data) {let ln = this; + ln.viewer = viewer; + ln.data = data; + ln.length = data.length; + ln.position = 0; + ln.history = []; + ln.shuffle = false; + + ln.divListNavigator = document.getElementById("list_navigator"); + + ln.btnDownloadList = document.getElementById("btn_download_list"); + ln.btnDownloadList.style.display = ""; + ln.btnDownloadList.addEventListener("click", () => { ln.downloadList(); }); + + ln.btnShuffle = document.getElementById("btn_shuffle"); + ln.btnShuffle.style.display = ""; + ln.btnShuffle.addEventListener("click", () => { ln.toggleShuffle(); }); + + // Render list contents in list navigator div + data.forEach((item, i) => { + let filename; + if(item.name !== "null"){ + filename = item.name; + }else{ + filename = "Removed File"; + } + + let d = document.createElement("div"); + d.classList = "file_button list_item"; + d.addEventListener("click", () => { ln.setItem(i); }); + d.innerText = filename; + ln.divListNavigator.appendChild(d); + }); + + // Make the navigator visible + ln.divListNavigator.style.display = "inline-block"; + + // Skip to the file defined in the link hash + if(Number.isInteger(parseInt(getHashValue("item")))){ + ln.setItem(parseInt(getHashValue("item"))); + }else{ + ln.setItem(0); + } +} + +ListNavigator.prototype.nextItem = function() {let ln = this; + if(ln.shuffle){ + ln.randItem(); + return; + } + + if (ln.position >= ln.length) { ln.position = 0; - ln.history = []; - ln.shuffle = false; - - ln.divListNavigator = document.getElementById("list_navigator"); - - ln.btnDownloadList = document.getElementById("btn_download_list"); - ln.btnDownloadList.style.display = ""; - ln.btnDownloadList.addEventListener("click", () => { ln.downloadList(); }); - - ln.btnShuffle = document.getElementById("btn_shuffle"); - ln.btnShuffle.style.display = ""; - ln.btnShuffle.addEventListener("click", () => { ln.toggleShuffle(); }); - - // Render list contents in list navigator div - data.forEach((item, i) => { - let filename; - if(item.name !== "null"){ - filename = item.name; - }else{ - filename = "Removed File"; - } - - let d = document.createElement("div"); - d.classList = "file_button list_item"; - d.addEventListener("click", () => { ln.setItem(i); }); - d.innerText = filename; - ln.divListNavigator.appendChild(d); - }); - - // Make the navigator visible - ln.divListNavigator.style.display = "inline-block"; - - // Skip to the file defined in the link hash - if(Number.isInteger(parseInt(getHashValue("item")))){ - ln.setItem(parseInt(getHashValue("item"))); - }else{ - ln.setItem(0); - } + } else { + ln.position++; } - nextItem(){let ln = this; - if(ln.shuffle){ - ln.randItem(); - return; - } + ln.setItem(ln.position); +} - if (ln.position >= ln.length) { - ln.position = 0; - } else { - ln.position++; - } - - ln.setItem(ln.position); +ListNavigator.prototype.previousItem = function() {let ln = this; + if(ln.position === 0){ + ln.position = ln.length - 1; + }else{ + ln.position--; } - previousItem(){let ln = this; - if(ln.position === 0){ - ln.position = ln.length - 1; - }else{ - ln.position--; - } + ln.setItem(ln.position); +} - ln.setItem(ln.position); +ListNavigator.prototype.randItem = function() {let ln = this; + // Avoid viewing the same file multiple times + let rand; + do { + rand = Math.round(Math.random() * ln.length); + console.log("rand is " + rand); + } while(ln.history.indexOf(rand) > -1); + + ln.setItem(rand); +} + +ListNavigator.prototype.setItem = function(index) {let ln = this; + if(index >= ln.length){ + ln.position = 0; + }else{ + ln.position = index; } - randItem(){let ln = this; - // Avoid viewing the same file multiple times - let rand; - do { - rand = Math.round(Math.random() * ln.length); - console.log("rand is " + rand); - } while(ln.history.indexOf(rand) > -1); + // Set the URL hash + location.hash = "item=" + ln.position; + ln.viewer.setFile(ln.data[ln.position]); - ln.setItem(rand); + ln.addToHistory(index); + ln.loadThumbnails(index); + + document.querySelectorAll("#list_navigator > .file_button_selected").forEach(el => { + el.classList.remove("file_button_selected"); + }); + + let selectedItem = ln.divListNavigator.children[ln.position]; + selectedItem.classList.add("file_button_selected"); + + let cst = window.getComputedStyle(selectedItem); + let itemWidth = selectedItem.offsetWidth + parseInt(cst.marginLeft) + parseInt(cst.marginRight); + + let start = ln.divListNavigator.scrollLeft; + let end = ((ln.position * itemWidth) + (itemWidth / 2)) - (ln.divListNavigator.clientWidth / 2); + let steps = 60; // One second + let stepSize = (end - start)/steps; + + let animateScroll = (pos, step) => { + ln.divListNavigator.scrollLeft = pos; + + if (step < steps) { + requestAnimationFrame(() => { + animateScroll(pos+stepSize, step+1); + }); + } + }; + animateScroll(start, 0); +} + +ListNavigator.prototype.downloadList = function() {let ln = this; + document.getElementById("download_frame").src = "/api/list/" + ln.viewer.listId + "/zip"; +} + +ListNavigator.prototype.addToHistory = function(index) {let ln = this; + if(ln.history.length >= (ln.length - 6)){ + ln.history.shift(); } - setItem(index){let ln = this; - if(index >= ln.length){ - ln.position = 0; - }else{ - ln.position = index; - } + ln.history.push(index); +} - // Set the URL hash - location.hash = "item=" + ln.position; - ln.viewer.setFile(ln.data[ln.position]); +ListNavigator.prototype.toggleShuffle = function() {let ln = this; + ln.shuffle = !ln.shuffle; // :P - ln.addToHistory(index); - ln.loadThumbnails(index); + if(ln.shuffle){ + document.querySelector("#btn_shuffle > span").innerHTML = "Shuffle ☑"; // Check icon + ln.btnShuffle.classList.add("button_highlight"); + }else{ + document.querySelector("#btn_shuffle > span").innerHTML = "Shuffle ☐"; // Empty checkbox + ln.btnShuffle.classList.remove("button_highlight"); + } +} - document.querySelectorAll("#list_navigator > .file_button_selected").forEach(el => { - el.classList.remove("file_button_selected"); - }); +ListNavigator.prototype.loadThumbnails = function(index) {let ln = this; + let startPos = +index - 50; + let endPos = +index + 50; + // fyi, the + is to let javascript know it's actually a number instead of a string - let selectedItem = ln.divListNavigator.children[ln.position]; - selectedItem.classList.add("file_button_selected"); - - let cst = window.getComputedStyle(selectedItem); - let itemWidth = selectedItem.offsetWidth + parseInt(cst.marginLeft) + parseInt(cst.marginRight); - - let start = ln.divListNavigator.scrollLeft; - let end = ((ln.position * itemWidth) + (itemWidth / 2)) - (ln.divListNavigator.clientWidth / 2); - let steps = 60; // One second - let stepSize = (end - start)/steps; - - let animateScroll = (pos, step) => { - ln.divListNavigator.scrollLeft = pos; - - if (step < steps) { - requestAnimationFrame(() => { - animateScroll(pos+stepSize, step+1); - }); - } - }; - animateScroll(start, 0); + if(startPos < 0){ + startPos = 0; } - downloadList(){let ln = this; - document.getElementById("download_frame").src = "/api/list/" + ln.viewer.listId + "/zip"; + if(endPos >= ln.length){ + endPos = ln.length - 1; } - addToHistory(index){let ln = this; - if(ln.history.length >= (ln.length - 6)){ - ln.history.shift(); + let navigatorItems = document.getElementById("list_navigator").children + + for (let i = startPos; i <= endPos; i++){ + if (navigatorItems[i].innerHTML.includes("list_item_thumbnail")) { + continue; // Thumbnail already loaded } - ln.history.push(index); + let thumb = "/api/file/" + ln.data[i].id + "/thumbnail?width=48&height=48"; + let name = ln.data[i].name; + + let itemHtml = "\""" + + escapeHTML(name); + + navigatorItems[i].innerHTML = itemHtml; } +} - toggleShuffle(){let ln = this; - ln.shuffle = !ln.shuffle; // :P - - if(ln.shuffle){ - document.querySelector("#btn_shuffle > span").innerHTML = "Shuffle ☑"; // Check icon - ln.btnShuffle.classList.add("button_highlight"); - }else{ - document.querySelector("#btn_shuffle > span").innerHTML = "Shuffle ☐"; // Empty checkbox - ln.btnShuffle.classList.remove("button_highlight"); - } - } - - loadThumbnails(index){let ln = this; - let startPos = +index - 50; - let endPos = +index + 50; - // fyi, the + is to let javascript know it's actually a number instead of a string - - if(startPos < 0){ - startPos = 0; - } - - if(endPos >= ln.length){ - endPos = ln.length - 1; - } - - let navigatorItems = document.getElementById("list_navigator").children - - for (let i = startPos; i <= endPos; i++){ - if (navigatorItems[i].innerHTML.includes("list_item_thumbnail")) { - continue; // Thumbnail already loaded - } - - let thumb = "/api/file/" + ln.data[i].id + "/thumbnail?width=48&height=48"; - let name = ln.data[i].name; - - let itemHtml = "\""" - + escapeHTML(name); - - navigatorItems[i].innerHTML = itemHtml; - } - } -}; // Misc function, don't really know where else to put it diff --git a/res/include/script/file_viewer/Toolbar.js b/res/include/script/file_viewer/Toolbar.js index 9223a38..12d0e56 100644 --- a/res/include/script/file_viewer/Toolbar.js +++ b/res/include/script/file_viewer/Toolbar.js @@ -1,161 +1,160 @@ -class Toolbar { - constructor(viewer) {let t = this; - t.viewer = viewer; +function Toolbar(viewer) {let t = this; + t.viewer = viewer; + t.visible = false; + t.sharebarVisible = false; + + t.divToolbar = document.getElementById("toolbar"); + t.divFilePreview = document.getElementById("filepreview"); + t.downloadFrame = document.getElementById("download_frame"); + t.spanViews = document.getElementById("stat_views"); + t.spanDownloads = document.getElementById("stat_downloads"); + t.spanSize = document.getElementById("stat_size"); + + t.btnToggleToolbar = document.getElementById("btn_toggle_toolbar"); + t.btnDownload = document.getElementById("btn_download"); + t.btnCopyLink = document.getElementById("btn_copy"); + t.spanCopyLink = document.querySelector("#btn_copy > span"); + t.btnShare = document.getElementById("btn_share"); + t.divSharebar = document.getElementById("sharebar"); + + t.btnToggleToolbar.addEventListener("click", () => { t.toggle(); }); + t.btnDownload.addEventListener("click", () => { t.download(); }); + t.btnCopyLink.addEventListener("click", () => { t.copyUrl(); }); + t.btnShare.addEventListener("click", () => { t.toggleSharebar(); }); +} + +Toolbar.prototype.toggle = function() {let t = this; + if (t.visible) { + if (t.sharebarVisible) { t.toggleSharebar(); } + + t.divToolbar.style.left = "-8em"; + t.divFilePreview.style.left = "0px"; + t.btnToggleToolbar.classList.remove("button_highlight"); t.visible = false; - t.sharebarVisible = false; - - t.divToolbar = document.getElementById("toolbar"); - t.divFilePreview = document.getElementById("filepreview"); - t.downloadFrame = document.getElementById("download_frame"); - t.spanViews = document.getElementById("stat_views"); - t.spanDownloads = document.getElementById("stat_downloads"); - t.spanSize = document.getElementById("stat_size"); - - t.btnToggleToolbar = document.getElementById("btn_toggle_toolbar"); - t.btnDownload = document.getElementById("btn_download"); - t.btnCopyLink = document.getElementById("btn_copy"); - t.spanCopyLink = document.querySelector("#btn_copy > span"); - t.btnShare = document.getElementById("btn_share"); - t.divSharebar = document.getElementById("sharebar"); - - t.btnToggleToolbar.addEventListener("click", () => { t.toggle(); }); - t.btnDownload.addEventListener("click", () => { t.download(); }); - t.btnCopyLink.addEventListener("click", () => { t.copyUrl(); }); - t.btnShare.addEventListener("click", () => { t.toggleSharebar(); }); - } - - toggle() {let t = this; - if (t.visible) { - if (t.sharebarVisible) { t.toggleSharebar(); } - - t.divToolbar.style.left = "-8em"; - t.divFilePreview.style.left = "0px"; - t.btnToggleToolbar.classList.remove("button_highlight"); - t.visible = false; - } else { - t.divToolbar.style.left = "0px"; - t.divFilePreview.style.left = "8em"; - t.btnToggleToolbar.classList.add("button_highlight"); - t.visible = true; - } - } - - toggleSharebar(){let t = this; - if (navigator.share) { - navigator.share({ - title: t.viewer.title, - text: "Download " + t.viewer.title + " here", - url: window.location.href - }); - return; - } - - if(t.sharebarVisible){ - t.divSharebar.style.left = "-8em"; - t.btnShare.classList.remove("button_highlight") - t.sharebarVisible = false; - }else{ - t.divSharebar.style.left = "8em"; - t.btnShare.classList.add("button_highlight") - t.sharebarVisible = true; - } - } - - download() {let t = this; - let triggerDL = (captchaResp = "") => { - if (captchaResp === "") { - t.downloadFrame.src = apiEndpoint+"/file/"+ - t.viewer.currentFile+"?download"; - } else { - t.downloadFrame.src = apiEndpoint+"/file/"+ - t.viewer.currentFile+"?download&recaptcha_response="+captchaResp; - } - } - - if (captchaKey === "none"){ - // If the server doesn't support captcha there's no use in checking - // availability - triggerDL(); - return; - } - if (recaptchaResponse !== "") { - // Captcha already filled in. Use the saved captcha responsse to - // download the file - triggerDL(recaptchaResponse); - - // Reset the key - recaptchaResponse = ""; - return; - } - - fetch(apiEndpoint+"/file/"+t.viewer.currentFile+"/availability").then(resp => { - return resp.json(); - }).then(resp => { - let popupDiv = document.getElementById("captcha_popup"); - let popupTitle = document.getElementById("captcha_popup_title"); - let popupContent = document.getElementById("captcha_popup_content"); - - let showCaptcha = () => { - // Load the recaptcha script with a load function - let script = document.createElement("script"); - script.src = "https://www.google.com/recaptcha/api.js?onload=loadCaptcha&render=explicit"; - document.body.appendChild(script); - - // Show the popup - popupDiv.style.opacity = "1"; - popupDiv.style.visibility = "visible"; - } - - if (resp.value === "file_rate_limited_captcha_required") { - popupTitle.innerText = "Rate limiting enabled!"; - popupContent.innerText = "This file is using a suspicious "+ - "amount of bandwidth relative to its popularity. To "+ - "continue downloading this file you will have to "+ - "prove that you're a human first."; - showCaptcha(); - } else if (resp.value === "virus_detected_captcha_required") { - popupTitle.innerText = "Malware warning!"; - popupContent.innerText = "According to our scanning "+ - "systems this file may contain a virus of type '"+ - resp.extra+"'. You can continue downloading this file at "+ - "your own risk, but you will have to prove that you're a "+ - "human first."; - showCaptcha(); - } else { - console.warn("resp.value not valid: "+resp.value); - triggerDL(); - } - }).catch(e => { - console.warn("fetch availability failed: "+e); - triggerDL(); - }); - } - - copyUrl() {let t = this; - if(copyText(window.location.href)) { - console.log('Text copied'); - t.spanCopyLink.innerText = "Copied!"; - t.btnCopyLink.classList.add("button_highlight") - } else { - console.log('Copying not supported'); - t.spanCopyLink.innerText = "Error!"; - alert("Your browser does not support copying text."); - } - - // Return to normal - setTimeout(() => { - t.spanCopyLink.innerText = "Copy"; - t.btnCopyLink.classList.remove("button_highlight") - }, 60000); - } - - setStats(file) {let t = this; - t.spanViews.innerText = file.views - t.spanDownloads.innerText = Math.round((file.bandwidth_used/file.size)*10)/10; - t.spanSize.innerText = formatDataVolume(file.size, 3); + } else { + t.divToolbar.style.left = "0px"; + t.divFilePreview.style.left = "8em"; + t.btnToggleToolbar.classList.add("button_highlight"); + t.visible = true; } } +Toolbar.prototype.toggleSharebar = function() {let t = this; + if (navigator.share) { + navigator.share({ + title: t.viewer.title, + text: "Download " + t.viewer.title + " here", + url: window.location.href + }); + return; + } + + if(t.sharebarVisible){ + t.divSharebar.style.left = "-8em"; + t.btnShare.classList.remove("button_highlight") + t.sharebarVisible = false; + }else{ + t.divSharebar.style.left = "8em"; + t.btnShare.classList.add("button_highlight") + t.sharebarVisible = true; + } +} + +Toolbar.prototype.download = function() {let t = this; + let triggerDL = (captchaResp = "") => { + if (captchaResp === "") { + t.downloadFrame.src = apiEndpoint+"/file/"+ + t.viewer.currentFile+"?download"; + } else { + t.downloadFrame.src = apiEndpoint+"/file/"+ + t.viewer.currentFile+"?download&recaptcha_response="+captchaResp; + } + } + + if (captchaKey === "none"){ + // If the server doesn't support captcha there's no use in checking + // availability + triggerDL(); + return; + } + if (recaptchaResponse !== "") { + // Captcha already filled in. Use the saved captcha responsse to + // download the file + triggerDL(recaptchaResponse); + + // Reset the key + recaptchaResponse = ""; + return; + } + + fetch(apiEndpoint+"/file/"+t.viewer.currentFile+"/availability").then(resp => { + return resp.json(); + }).then(resp => { + let popupDiv = document.getElementById("captcha_popup"); + let popupTitle = document.getElementById("captcha_popup_title"); + let popupContent = document.getElementById("captcha_popup_content"); + + let showCaptcha = () => { + // Load the recaptcha script with a load function + let script = document.createElement("script"); + script.src = "https://www.google.com/recaptcha/api.js?onload=loadCaptcha&render=explicit"; + document.body.appendChild(script); + + // Show the popup + popupDiv.style.opacity = "1"; + popupDiv.style.visibility = "visible"; + } + + if (resp.value === "file_rate_limited_captcha_required") { + popupTitle.innerText = "Rate limiting enabled!"; + popupContent.innerText = "This file is using a suspicious "+ + "amount of bandwidth relative to its popularity. To "+ + "continue downloading this file you will have to "+ + "prove that you're a human first."; + showCaptcha(); + } else if (resp.value === "virus_detected_captcha_required") { + popupTitle.innerText = "Malware warning!"; + popupContent.innerText = "According to our scanning "+ + "systems this file may contain a virus of type '"+ + resp.extra+"'. You can continue downloading this file at "+ + "your own risk, but you will have to prove that you're a "+ + "human first."; + showCaptcha(); + } else { + console.warn("resp.value not valid: "+resp.value); + triggerDL(); + } + }).catch(e => { + console.warn("fetch availability failed: "+e); + triggerDL(); + }); +} + +Toolbar.prototype.copyUrl = function() {let t = this; + if(copyText(window.location.href)) { + console.log('Text copied'); + t.spanCopyLink.innerText = "Copied!"; + t.btnCopyLink.classList.add("button_highlight") + } else { + console.log('Copying not supported'); + t.spanCopyLink.innerText = "Error!"; + alert("Your browser does not support copying text."); + } + + // Return to normal + setTimeout(() => { + t.spanCopyLink.innerText = "Copy"; + t.btnCopyLink.classList.remove("button_highlight") + }, 60000); +} + +Toolbar.prototype.setStats = function(file) {let t = this; + t.spanViews.innerText = file.views + t.spanDownloads.innerText = Math.round((file.bandwidth_used/file.size)*10)/10; + t.spanSize.innerText = formatDataVolume(file.size, 3); +} + + // Called by the google recaptcha script let recaptchaResponse = ""; function loadCaptcha(){ diff --git a/res/include/script/file_viewer/Viewer.js b/res/include/script/file_viewer/Viewer.js index 6b20f41..00f7f31 100644 --- a/res/include/script/file_viewer/Viewer.js +++ b/res/include/script/file_viewer/Viewer.js @@ -1,200 +1,199 @@ -class Viewer { - constructor(type, viewToken, data) {let v = this; - // Set defaults - v.toolbar = null; - v.listNavigator = null; - v.detailsWindow = null; - v.divFilepreview = null; - v.currentFile = ""; - v.title = ""; // Contains either the file name or list title - v.listId = ""; - v.viewToken = ""; - v.isList = false; - v.isFile = false; - v.initialized = false; +function Viewer(type, viewToken, data) {let v = this; + // Set defaults + v.toolbar = null; + v.listNavigator = null; + v.detailsWindow = null; + v.divFilepreview = null; + v.currentFile = ""; + v.title = ""; // Contains either the file name or list title + v.listId = ""; + v.viewToken = ""; + v.isList = false; + v.isFile = false; + v.initialized = false; - v.viewToken = viewToken; - v.toolbar = new Toolbar(v); - v.detailsWindow = new DetailsWindow(v); + v.viewToken = viewToken; + v.toolbar = new Toolbar(v); + v.detailsWindow = new DetailsWindow(v); - v.divFilepreview = document.getElementById("filepreview"); + v.divFilepreview = document.getElementById("filepreview"); - // On small screens the toolbar takes too much space, so it collapses - // automatically - if (v.divFilepreview.clientWidth > 600 && !v.toolbar.visible) { - v.toolbar.toggle(); - } - - // The close button only works if the window has an opener. So we hide - // the button if it does not - if (window.opener === null && window.history.length !== 1) { - document.getElementById("button_close_file_viewer").remove() - } - - if (type === "file") { - v.isFile = true; - v.currentFile = data.id; - v.title = data.name; - v.setFile(data); - } else if (type === "list") { - v.isList = true; - v.listId = data.id; - v.title = data.title; - v.listNavigator = new ListNavigator(v, data.data); - } - - v.renderSponsors(); - window.addEventListener("resize", e => { v.renderSponsors(e); }); - - // Register keyboard shortcuts - document.addEventListener("keydown", e => { v.keyboardEvent(e); }); - - v.initialized = true; + // On small screens the toolbar takes too much space, so it collapses + // automatically + if (v.divFilepreview.clientWidth > 600 && !v.toolbar.visible) { + v.toolbar.toggle(); } - setFile(file) {let v = this; - v.currentFile = file.id; - if (v.isList) { - document.getElementById("file_viewer_headerbar_title").style.lineHeight = "1em"; - document.getElementById("file_viewer_list_title").innerText = this.title; - document.getElementById("file_viewer_file_title").innerText = file.name; - document.title = v.title + " ~ " + file.name + " ~ pixeldrain"; + // The close button only works if the window has an opener. So we hide + // the button if it does not + if (window.opener === null && window.history.length !== 1) { + document.getElementById("button_close_file_viewer").remove() + } + + if (type === "file") { + v.isFile = true; + v.currentFile = data.id; + v.title = data.name; + v.setFile(data); + } else if (type === "list") { + v.isList = true; + v.listId = data.id; + v.title = data.title; + v.listNavigator = new ListNavigator(v, data.data); + } + + v.renderSponsors(); + window.addEventListener("resize", e => { v.renderSponsors(e); }); + + // Register keyboard shortcuts + document.addEventListener("keydown", e => { v.keyboardEvent(e); }); + + v.initialized = true; +} + +Viewer.prototype.setFile = function(file) {let v = this; + v.currentFile = file.id; + if (v.isList) { + document.getElementById("file_viewer_headerbar_title").style.lineHeight = "1em"; + document.getElementById("file_viewer_list_title").innerText = this.title; + document.getElementById("file_viewer_file_title").innerText = file.name; + document.title = v.title + " ~ " + file.name + " ~ pixeldrain"; + } else { + document.getElementById("file_viewer_file_title").innerText = file.name; + document.title = file.name + " ~ pixeldrain"; + } + + // Update the file details + v.detailsWindow.setDetails(file); + v.toolbar.setStats(file); + + // Register a new view. We don't care what this returns becasue we can't + // do anything about it anyway + fetch(apiEndpoint+"/file/"+file.id+"/view", + { + method: "POST", + headers: {"Content-Type": "application/x-www-form-urlencoded"}, + body: "token="+v.viewToken + } + ); + + // Clear the canvas + v.divFilepreview.innerHTML = ""; + + let nextItem = () => { + if (v.listNavigator !== null) { + v.listNavigator.nextItem(); + } + }; + + if ( + file.mime_type.startsWith("image") + ) { + new ImageViewer(v, file).render(v.divFilepreview); + } else if ( + file.mime_type.startsWith("video") || + file.mime_type === "application/matroska" || + file.mime_type === "application/x-matroska" + ) { + new VideoViewer(v, file, nextItem).render(v.divFilepreview); + } else if ( + file.mime_type.startsWith("audio") || + file.mime_type === "application/ogg" || + file.name.endsWith(".mp3") + ) { + new AudioViewer(v, file, nextItem).render(v.divFilepreview); + } else if ( + file.mime_type === "application/pdf" || + file.mime_type === "application/x-pdf" + ) { + new PDFViewer(v, file).render(v.divFilepreview); + } else if ( + file.mime_type.startsWith("text") || + file.id === "demo" + ) { + new TextViewer(v, file).render(v.divFilepreview); + } else { + new FileViewer(v, file).render(v.divFilepreview); + } +} + +Viewer.prototype.renderSponsors = function() { + let scale = 1; + let scaleWidth = 1; + let scaleHeight = 1; + let minWidth = 728; + let minHeight = 800; + + if (window.innerWidth < minWidth) { + scaleWidth = window.innerWidth/minWidth; + } + if (window.innerHeight < minHeight) { + scaleHeight = window.innerHeight/minHeight; + } + scale = scaleWidth < scaleHeight ? scaleWidth : scaleHeight; + + // Because of the scale transformation the automatic margins don't work + // anymore. So we have to maunally calculate the margin. Where we take the + // width of the viewport - the width of the ad to calculate the amount of + // pixels around the ad. We multiply the ad size by the scale we calcualted + // to account for the smaller size. + let offset = (window.innerWidth - (minWidth*scale)) / 2 + if (offset < 0) { + offset = 0 + } + document.querySelector(".sponsors > iframe").style.marginLeft = offset+"px"; + + if (scale == 1) { + document.querySelector(".sponsors > iframe").style.transform = "none"; + document.querySelector(".sponsors").style.height = "90px"; + } else { + document.querySelector(".sponsors > iframe").style.transform = "scale("+scale+")"; + document.querySelector(".sponsors").style.height = (scale*90)+"px"; + } +} + +Viewer.prototype.keyboardEvent = function(evt) {let v = this; + if (evt.ctrlKey || evt.altKey) { + return // prevent custom shortcuts from interfering with system shortcuts + } + + switch (evt.keyCode) { + case 65: // A or left arrow key go to previous file + case 37: + if (v.listNavigator != null) { + v.listNavigator.previousItem(); + } + break; + case 68: // D or right arrow key go to next file + case 39: + if (v.listNavigator != null) { + v.listNavigator.nextItem(); + } + break; + case 83: + if (evt.shiftKey) { + v.listNavigator.downloadList(); // SHIFT + S downloads all files in list } else { - document.getElementById("file_viewer_file_title").innerText = file.name; - document.title = file.name + " ~ pixeldrain"; + v.toolbar.download(); // S to download the current file } - - // Update the file details - v.detailsWindow.setDetails(file); - v.toolbar.setStats(file); - - // Register a new view. We don't care what this returns becasue we can't - // do anything about it anyway - fetch(apiEndpoint+"/file/"+file.id+"/view", - { - method: "POST", - headers: {"Content-Type": "application/x-www-form-urlencoded"}, - body: "token="+v.viewToken - } - ); - - // Clear the canvas - v.divFilepreview.innerHTML = ""; - - let nextItem = () => { - if (v.listNavigator !== null) { - v.listNavigator.nextItem(); - } - }; - - if ( - file.mime_type.startsWith("image") - ) { - new ImageViewer(v, file).render(v.divFilepreview); - } else if ( - file.mime_type.startsWith("video") || - file.mime_type === "application/matroska" || - file.mime_type === "application/x-matroska" - ) { - new VideoViewer(v, file, nextItem).render(v.divFilepreview); - } else if ( - file.mime_type.startsWith("audio") || - file.mime_type === "application/ogg" || - file.name.endsWith(".mp3") - ) { - new AudioViewer(v, file, nextItem).render(v.divFilepreview); - } else if ( - file.mime_type === "application/pdf" || - file.mime_type === "application/x-pdf" - ) { - new PDFViewer(v, file).render(v.divFilepreview); - } else if ( - file.mime_type.startsWith("text") || - file.id === "demo" - ) { - new TextViewer(v, file).render(v.divFilepreview); - } else { - new FileViewer(v, file).render(v.divFilepreview); + break; + case 82: // R to toggle list shuffle + if (v.listNavigator != null) { + v.listNavigator.toggleShuffle(); } + break; + case 67: // C to copy to clipboard + v.toolbar.copyUrl(); + break; + case 73: // I to open the details window + v.detailsWindow.toggle(); + break; + case 81: // Q to close the window + window.close(); + break; } +} - renderSponsors() { - let scale = 1; - let scaleWidth = 1; - let scaleHeight = 1; - let minWidth = 728; - let minHeight = 800; - - if (window.innerWidth < minWidth) { - scaleWidth = window.innerWidth/minWidth; - } - if (window.innerHeight < minHeight) { - scaleHeight = window.innerHeight/minHeight; - } - scale = scaleWidth < scaleHeight ? scaleWidth : scaleHeight; - - // Because of the scale transformation the automatic margins don't work - // anymore. So we have to maunally calculate the margin. Where we take the - // width of the viewport - the width of the ad to calculate the amount of - // pixels around the ad. We multiply the ad size by the scale we calcualted - // to account for the smaller size. - let offset = (window.innerWidth - (minWidth*scale)) / 2 - if (offset < 0) { - offset = 0 - } - document.querySelector(".sponsors > iframe").style.marginLeft = offset+"px"; - - if (scale == 1) { - document.querySelector(".sponsors > iframe").style.transform = "none"; - document.querySelector(".sponsors").style.height = "90px"; - } else { - document.querySelector(".sponsors > iframe").style.transform = "scale("+scale+")"; - document.querySelector(".sponsors").style.height = (scale*90)+"px"; - } - } - - keyboardEvent(evt) {let v = this; - if (evt.ctrlKey || evt.altKey) { - return // prevent custom shortcuts from interfering with system shortcuts - } - - switch (evt.which) { - case 65: // A or left arrow key go to previous file - case 37: - if (v.listNavigator != null) { - v.listNavigator.previousItem(); - } - break; - case 68: // D or right arrow key go to next file - case 39: - if (v.listNavigator != null) { - v.listNavigator.nextItem(); - } - break; - case 83: - if (evt.shiftKey) { - v.listNavigator.downloadList(); // SHIFT + S downloads all files in list - } else { - v.toolbar.download(); // S to download the current file - } - break; - case 82: // R to toggle list shuffle - if (v.listNavigator != null) { - v.listNavigator.toggleShuffle(); - } - break; - case 67: // C to copy to clipboard - v.toolbar.copyUrl(); - break; - case 73: // I to open the details window - v.detailsWindow.toggle(); - break; - case 81: // Q to close the window - window.close(); - break; - } - } -}; // Against XSS attacks function escapeHTML(str) { diff --git a/res/include/script/file_viewer/viewer_scripts/AudioViewer.js b/res/include/script/file_viewer/viewer_scripts/AudioViewer.js index 371e74f..7e638ae 100644 --- a/res/include/script/file_viewer/viewer_scripts/AudioViewer.js +++ b/res/include/script/file_viewer/viewer_scripts/AudioViewer.js @@ -1,35 +1,33 @@ -class AudioViewer { - constructor(viewer, file, next) {let v = this; - v.viewer = viewer; - v.file = file; - v.next = next; +function AudioViewer(viewer, file, next) {let v = this; + v.viewer = viewer; + v.file = file; + v.next = next; - v.container = document.createElement("div"); - v.container.classList = "image-container"; - v.container.appendChild(document.createElement("br")); + v.container = document.createElement("div"); + v.container.classList = "image-container"; + v.container.appendChild(document.createElement("br")); - v.icon = document.createElement("img"); - v.icon.src = "/res/img/mime/audio.png"; - v.container.appendChild(v.icon); + v.icon = document.createElement("img"); + v.icon.src = "/res/img/mime/audio.png"; + v.container.appendChild(v.icon); - v.container.appendChild(document.createElement("br")); - v.container.appendChild(document.createTextNode(file.name)); - v.container.appendChild(document.createElement("br")); - v.container.appendChild(document.createElement("br")); + v.container.appendChild(document.createElement("br")); + v.container.appendChild(document.createTextNode(file.name)); + v.container.appendChild(document.createElement("br")); + v.container.appendChild(document.createElement("br")); - v.element = document.createElement("audio"); - v.element.autoplay = "autoplay"; - v.element.controls = "controls"; - v.element.style.width = "90%"; - v.element.addEventListener("ended", () => { v.next(); }, false); + v.element = document.createElement("audio"); + v.element.autoplay = "autoplay"; + v.element.controls = "controls"; + v.element.style.width = "90%"; + v.element.addEventListener("ended", () => { v.next(); }, false); - v.source = document.createElement("source"); - v.source.src = apiEndpoint+"/file/"+v.file.id; - v.element.appendChild(v.source); - v.container.appendChild(v.element); - } - - render(parent) {let v = this; - parent.appendChild(v.container); - } + v.source = document.createElement("source"); + v.source.src = apiEndpoint+"/file/"+v.file.id; + v.element.appendChild(v.source); + v.container.appendChild(v.element); +} + +AudioViewer.prototype.render = function(parent) {let v = this; + parent.appendChild(v.container); } diff --git a/res/include/script/file_viewer/viewer_scripts/FileViewer.js b/res/include/script/file_viewer/viewer_scripts/FileViewer.js index 46b22d9..bc5ae72 100644 --- a/res/include/script/file_viewer/viewer_scripts/FileViewer.js +++ b/res/include/script/file_viewer/viewer_scripts/FileViewer.js @@ -1,29 +1,27 @@ -class FileViewer { - constructor(viewer, file, next) {let v = this; - v.viewer = viewer; - v.file = file; - v.next = next; +function FileViewer(viewer, file, next) {let v = this; + v.viewer = viewer; + v.file = file; + v.next = next; - v.container = document.createElement("div"); - v.container.classList = "image-container"; - v.container.appendChild(document.createElement("br")); + v.container = document.createElement("div"); + v.container.classList = "image-container"; + v.container.appendChild(document.createElement("br")); - v.icon = document.createElement("img"); - v.icon.src = apiEndpoint+"/"+file.thumbnail_href; - v.container.appendChild(v.icon); + v.icon = document.createElement("img"); + v.icon.src = apiEndpoint+"/"+file.thumbnail_href; + v.container.appendChild(v.icon); - v.container.appendChild(document.createElement("br")); - v.container.appendChild(document.createTextNode(file.name)); - v.container.appendChild(document.createElement("br")); - v.container.appendChild(document.createTextNode("Type: "+file.mime_type)); - v.container.appendChild(document.createElement("br")); - v.container.appendChild(document.createElement("br")); - v.container.appendChild(document.createTextNode( - "Press the 'Download' button in the menu to download this file" - )); - } - - render(parent) {let v = this; - parent.appendChild(v.container); - } + v.container.appendChild(document.createElement("br")); + v.container.appendChild(document.createTextNode(file.name)); + v.container.appendChild(document.createElement("br")); + v.container.appendChild(document.createTextNode("Type: "+file.mime_type)); + v.container.appendChild(document.createElement("br")); + v.container.appendChild(document.createElement("br")); + v.container.appendChild(document.createTextNode( + "Press the 'Download' button in the menu to download this file" + )); +} + +FileViewer.prototype.render = function(parent) {let v = this; + parent.appendChild(v.container); } diff --git a/res/include/script/file_viewer/viewer_scripts/ImageViewer.js b/res/include/script/file_viewer/viewer_scripts/ImageViewer.js index 72f3893..50d3f4c 100644 --- a/res/include/script/file_viewer/viewer_scripts/ImageViewer.js +++ b/res/include/script/file_viewer/viewer_scripts/ImageViewer.js @@ -1,90 +1,88 @@ -class ImageViewer { - constructor(viewer, file) {let v = this; - v.viewer = viewer; - v.file = file; - v.zoomed = false; - v.x = 0; - v.y = 0; - v.dragging = false; +function ImageViewer(viewer, file) {let v = this; + v.viewer = viewer; + v.file = file; + v.zoomed = false; + v.x = 0; + v.y = 0; + v.dragging = false; - v.container = document.createElement("dv"); - v.container.classList = "image-container"; - // v.container.style.lineHeight = "0"; + v.container = document.createElement("dv"); + v.container.classList = "image-container"; + // v.container.style.lineHeight = "0"; - v.element = document.createElement("img"); - v.element.classList = "pannable center drop-shadow"; - v.element.src = apiEndpoint+"/file/"+v.file.id; - v.element.addEventListener("dblclick", (e) => { return v.doubleclick(e); }); - v.element.addEventListener("doubletap", (e) => { return v.doubleclick(e); }); - v.element.addEventListener("mousedown", (e) => { return v.mousedown(e); }); - document.addEventListener("mousemove", (e) => { return v.mousemove(e); }); - document.addEventListener("mouseup", (e) => { return v.mouseup(e); }); + v.element = document.createElement("img"); + v.element.classList = "pannable center drop-shadow"; + v.element.src = apiEndpoint+"/file/"+v.file.id; + v.element.addEventListener("dblclick", (e) => { return v.doubleclick(e); }); + v.element.addEventListener("doubletap", (e) => { return v.doubleclick(e); }); + v.element.addEventListener("mousedown", (e) => { return v.mousedown(e); }); + document.addEventListener("mousemove", (e) => { return v.mousemove(e); }); + document.addEventListener("mouseup", (e) => { return v.mouseup(e); }); - v.container.appendChild(v.element); + v.container.appendChild(v.element); +} + +ImageViewer.prototype.render = function(parent) {let v = this; + parent.appendChild(v.container); +} + +ImageViewer.prototype.doubleclick = function(e) {let v = this; + if (v.zoomed) { + v.element.style.maxWidth = "100%"; + v.element.style.maxHeight = "100%"; + v.element.style.top = "50%"; + v.element.style.left = "auto"; + v.element.style.transform = "translateY(-50%)"; + v.container.style.overflow = "hidden"; + v.zoomed = false; + } else { + v.element.style.maxWidth = "none"; + v.element.style.maxHeight = "none"; + v.element.style.top = "0"; + v.element.style.left = ""; + v.element.style.transform = "none"; + v.container.style.overflow = "scroll"; + v.zoomed = true; } - render(parent) {let v = this; - parent.appendChild(v.container); - } + e.preventDefault(); + e.stopPropagation(); + return false; +} - doubleclick(e) {let v = this; - if (v.zoomed) { - v.element.style.maxWidth = "100%"; - v.element.style.maxHeight = "100%"; - v.element.style.top = "50%"; - v.element.style.left = "auto"; - v.element.style.transform = "translateY(-50%)"; - v.container.style.overflow = "hidden"; - v.zoomed = false; - } else { - v.element.style.maxWidth = "none"; - v.element.style.maxHeight = "none"; - v.element.style.top = "0"; - v.element.style.left = ""; - v.element.style.transform = "none"; - v.container.style.overflow = "scroll"; - v.zoomed = true; - } +ImageViewer.prototype.mousedown = function(e) {let v = this; + if (!v.dragging && e.which === 1 && v.zoomed) { + v.x = e.pageX; + v.y = e.pageY; + v.dragging = true; + + e.preventDefault(); + e.stopPropagation(); + return false; + } +} + +ImageViewer.prototype.mousemove = function(e) {let v = this; + if (v.dragging) { + v.container.scrollLeft = v.container.scrollLeft - (e.pageX - v.x); + v.container.scrollTop = v.container.scrollTop - (e.pageY - v.y); + + v.x = e.pageX; + v.y = e.pageY; e.preventDefault(); e.stopPropagation(); return false; } - mousedown(e) {let v = this; - if (!v.dragging && e.which === 1 && v.zoomed) { - v.x = e.pageX; - v.y = e.pageY; - v.dragging = true; +} - e.preventDefault(); - e.stopPropagation(); - return false; - } - } +ImageViewer.prototype.mouseup = function(e) {let v = this; + if (v.dragging) { + v.dragging = false; - mousemove(e) {let v = this; - if (v.dragging) { - v.container.scrollLeft = v.container.scrollLeft - (e.pageX - v.x); - v.container.scrollTop = v.container.scrollTop - (e.pageY - v.y); - - v.x = e.pageX; - v.y = e.pageY; - - e.preventDefault(); - e.stopPropagation(); - return false; - } - - } - - mouseup(e) {let v = this; - if (v.dragging) { - v.dragging = false; - - e.preventDefault(); - e.stopPropagation(); - return false; - } + e.preventDefault(); + e.stopPropagation(); + return false; } } diff --git a/res/include/script/file_viewer/viewer_scripts/PDFViewer.js b/res/include/script/file_viewer/viewer_scripts/PDFViewer.js index 3fda0e0..17fb34a 100644 --- a/res/include/script/file_viewer/viewer_scripts/PDFViewer.js +++ b/res/include/script/file_viewer/viewer_scripts/PDFViewer.js @@ -1,15 +1,13 @@ -class PDFViewer { - constructor(viewer, file) {let v = this; - v.viewer = viewer; - v.file = file; +function PDFViewer(viewer, file) {let v = this; + v.viewer = viewer; + v.file = file; - v.container = document.createElement("iframe"); - v.container.classList = "image-container"; - v.container.style.border = "none"; - v.container.src = "/res/misc/pdf-viewer/web/viewer.html?file="+apiEndpoint+"/file/"+file.id; - } - - render(parent) {let v = this; - parent.appendChild(v.container); - } + v.container = document.createElement("iframe"); + v.container.classList = "image-container"; + v.container.style.border = "none"; + v.container.src = "/res/misc/pdf-viewer/web/viewer.html?file="+apiEndpoint+"/file/"+file.id; +} + +PDFViewer.prototype.render = function(parent) {let v = this; + parent.appendChild(v.container); } diff --git a/res/include/script/file_viewer/viewer_scripts/TextViewer.js b/res/include/script/file_viewer/viewer_scripts/TextViewer.js index f1d18f7..2843d12 100644 --- a/res/include/script/file_viewer/viewer_scripts/TextViewer.js +++ b/res/include/script/file_viewer/viewer_scripts/TextViewer.js @@ -1,58 +1,56 @@ -class TextViewer { - constructor(viewer, file) {let v = this; - v.viewer = viewer; - v.file = file; - v.pre = null; - v.prettyprint = null; +function TextViewer(viewer, file) {let v = this; + v.viewer = viewer; + v.file = file; + v.pre = null; + v.prettyprint = null; - v.container = document.createElement("div"); - v.container.classList = "text-container"; + v.container = document.createElement("div"); + v.container.classList = "text-container"; - if (file.name.endsWith(".md") || file.name.endsWith(".markdown") || file.id === "demo") { - v.getMarkdown(); - } else { - v.getText(); - } - } - - getText() {let v = this; - v.pre = document.createElement("pre"); - v.pre.classList = "pre-container prettyprint linenums"; - v.pre.innerText = "Loading..."; - v.container.appendChild(v.pre); - - if (v.file.size > 1<<22) { // File larger than 4 MiB - v.pre.innerText = "File is too large to view online.\nPlease download and view it locally."; - return; - } - - fetch(apiEndpoint+"/file/"+v.file.id).then(resp => { - if (!resp.ok) { return Promise.reject(resp.status); } - return resp.text(); - }).then(resp => { - v.pre.innerText = resp; - - // Load prettyprint script - v.prettyprint = document.createElement("script"); - v.prettyprint.src = "https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js?skin=desert"; - v.container.appendChild(v.prettyprint); - }).catch(err => { - v.pre.innerText = "Error loading file: "+err; - }); - } - - getMarkdown() {let v = this; - fetch("/u/"+v.file.id+"/preview").then(resp => { - if (!resp.ok) { return Promise.reject(resp.status); } - return resp.text(); - }).then(resp => { - v.container.innerHTML = resp; - }).catch(err => { - v.container.innerText = "Error loading file: "+err; - }); - } - - render(parent) {let v = this; - parent.appendChild(v.container); + if (file.name.endsWith(".md") || file.name.endsWith(".markdown") || file.id === "demo") { + v.getMarkdown(); + } else { + v.getText(); } } + +TextViewer.prototype.getText = function() {let v = this; + v.pre = document.createElement("pre"); + v.pre.classList = "pre-container prettyprint linenums"; + v.pre.innerText = "Loading..."; + v.container.appendChild(v.pre); + + if (v.file.size > 1<<22) { // File larger than 4 MiB + v.pre.innerText = "File is too large to view online.\nPlease download and view it locally."; + return; + } + + fetch(apiEndpoint+"/file/"+v.file.id).then(resp => { + if (!resp.ok) { return Promise.reject(resp.status); } + return resp.text(); + }).then(resp => { + v.pre.innerText = resp; + + // Load prettyprint script + v.prettyprint = document.createElement("script"); + v.prettyprint.src = "https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js?skin=desert"; + v.container.appendChild(v.prettyprint); + }).catch(err => { + v.pre.innerText = "Error loading file: "+err; + }); +} + +TextViewer.prototype.getMarkdown = function() {let v = this; + fetch("/u/"+v.file.id+"/preview").then(resp => { + if (!resp.ok) { return Promise.reject(resp.status); } + return resp.text(); + }).then(resp => { + v.container.innerHTML = resp; + }).catch(err => { + v.container.innerText = "Error loading file: "+err; + }); +} + +TextViewer.prototype.render = function(parent) {let v = this; + parent.appendChild(v.container); +} diff --git a/res/include/script/file_viewer/viewer_scripts/VideoViewer.js b/res/include/script/file_viewer/viewer_scripts/VideoViewer.js index 6ef4c28..ef164d3 100644 --- a/res/include/script/file_viewer/viewer_scripts/VideoViewer.js +++ b/res/include/script/file_viewer/viewer_scripts/VideoViewer.js @@ -1,26 +1,24 @@ -class VideoViewer { - constructor(viewer, file, next) {let v = this; - v.viewer = viewer; - v.file = file; - v.next = next; +function VideoViewer(viewer, file, next) {let v = this; + v.viewer = viewer; + v.file = file; + v.next = next; - v.vidContainer = document.createElement("div"); - v.vidContainer.classList = "image-container"; + v.vidContainer = document.createElement("div"); + v.vidContainer.classList = "image-container"; - v.vidElement = document.createElement("video"); - v.vidElement.autoplay = "autoplay"; - v.vidElement.controls = "controls"; - v.vidElement.classList = "center drop-shadow"; - v.vidElement.addEventListener("ended", () => { v.next(); }, false); + v.vidElement = document.createElement("video"); + v.vidElement.autoplay = "autoplay"; + v.vidElement.controls = "controls"; + v.vidElement.classList = "center drop-shadow"; + v.vidElement.addEventListener("ended", () => { v.next(); }, false); - v.videoSource = document.createElement("source"); - v.videoSource.src = apiEndpoint+"/file/"+v.file.id; + v.videoSource = document.createElement("source"); + v.videoSource.src = apiEndpoint+"/file/"+v.file.id; - v.vidElement.appendChild(v.videoSource); - v.vidContainer.appendChild(v.vidElement); - } - - render(parent) {let v = this; - parent.appendChild(v.vidContainer); - } + v.vidElement.appendChild(v.videoSource); + v.vidContainer.appendChild(v.vidElement); +} + +VideoViewer.prototype.render = function(parent) {let v = this; + parent.appendChild(v.vidContainer); } diff --git a/res/include/script/homepage.js b/res/include/script/homepage.js index df5d158..149866b 100644 --- a/res/include/script/homepage.js +++ b/res/include/script/homepage.js @@ -1,72 +1,70 @@ -class UploadProgressBar { - constructor(uploadManager, queueDiv, file){ - this.uploadManager = uploadManager; - this.file = file; - this.name = file.name; +function UploadProgressBar(uploadManager, queueDiv, file){let upb = this; + upb.uploadManager = uploadManager; + upb.file = file; + upb.name = file.name; - this.uploadDiv = document.createElement("a"); - this.uploadDiv.classList.add("file_button"); - this.uploadDiv.style.opacity = "0"; - this.uploadDiv.innerText = "Queued\n" + this.file.name; - queueDiv.appendChild(this.uploadDiv); + upb.uploadDiv = document.createElement("a"); + upb.uploadDiv.classList.add("file_button"); + upb.uploadDiv.style.opacity = "0"; + upb.uploadDiv.innerText = "Queued\n" + upb.file.name; + queueDiv.appendChild(upb.uploadDiv); - // Start uploading the file - let that = this; - this.uploadManager.addFile( - this.file, - this.name, - function(progress) { that.onProgress(progress); }, - function(id) { that.onFinished(id); }, - function(val, msg) { that.onFailure(val, msg); } - ); + // Start uploading the file + upb.uploadManager.addFile( + upb.file, + upb.name, + function(progress) { upb.onProgress(progress); }, + function(id) { upb.onFinished(id); }, + function(val, msg) { upb.onFailure(val, msg); } + ); - // Browsers don't render the transition if the opacity is set and - // updated in the same frame. So we have to wait a frame (or more) - // before changing the opacity to make sure the transition triggers - var d = this.uploadDiv // `this` stops working after constructor ends - window.setTimeout(function(){d.style.opacity = "1";}, 100) - } - - onProgress(progress){ - this.uploadDiv.innerText = "Uploading... " + Math.round(progress*1000)/10 + "%\n" + this.name - this.uploadDiv.style.background = 'linear-gradient(' - +'to right, ' - +'var(--file_background_color) 0%, ' - +'var(--highlight_color) '+ ((progress*100)) +'%, ' - +'var(--file_background_color) '+ ((progress*100)+1) +'%)' - } - onFinished(id){ - console.log("Upload finished: "+this.file.name+" "+id); - - this.uploadDiv.style.background = 'var(--file_background_color)' - this.uploadDiv.href = '/u/'+id - this.uploadDiv.target= "_blank" - - let fileImg = document.createElement("img") - fileImg.src = apiEndpoint+'/file/'+id+'/thumbnail' - fileImg.alt = this.file.name - - let linkSpan = document.createElement("span") - linkSpan.style.color = "var(--highlight_color)" - linkSpan.innerText = domainURL()+"/u/"+id - - this.uploadDiv.innerHTML = "" // Remove uploading progress - this.uploadDiv.appendChild(fileImg) - this.uploadDiv.appendChild(document.createTextNode(this.file.name)) - this.uploadDiv.appendChild(document.createElement("br")) - this.uploadDiv.appendChild(linkSpan) - } - onFailure(error) { - this.uploadDiv.innerHTML = "" // Remove uploading progress - this.uploadDiv.style.background = 'var(--danger_color)' - this.uploadDiv.appendChild(document.createTextNode(this.file.name)) - this.uploadDiv.appendChild(document.createElement("br")) - this.uploadDiv.appendChild(document.createTextNode("Upload failed after three tries:")) - this.uploadDiv.appendChild(document.createElement("br")) - this.uploadDiv.appendChild(document.createTextNode(error)) - } + // Browsers don't render the transition if the opacity is set and + // updated in the same frame. So we have to wait a frame (or more) + // before changing the opacity to make sure the transition triggers + var d = this.uploadDiv // `this` stops working after constructor ends + window.setTimeout(function(){d.style.opacity = "1";}, 100) } +UploadProgressBar.prototype.onProgress = function(progress){ + this.uploadDiv.innerText = "Uploading... " + Math.round(progress*1000)/10 + "%\n" + this.name + this.uploadDiv.style.background = 'linear-gradient(' + +'to right, ' + +'var(--file_background_color) 0%, ' + +'var(--highlight_color) '+ ((progress*100)) +'%, ' + +'var(--file_background_color) '+ ((progress*100)+1) +'%)' +} +UploadProgressBar.prototype.onFinished = function(id){ + console.log("Upload finished: "+this.file.name+" "+id); + + this.uploadDiv.style.background = 'var(--file_background_color)' + this.uploadDiv.href = '/u/'+id + this.uploadDiv.target= "_blank" + + let fileImg = document.createElement("img") + fileImg.src = apiEndpoint+'/file/'+id+'/thumbnail' + fileImg.alt = this.file.name + + let linkSpan = document.createElement("span") + linkSpan.style.color = "var(--highlight_color)" + linkSpan.innerText = domainURL()+"/u/"+id + + this.uploadDiv.innerHTML = "" // Remove uploading progress + this.uploadDiv.appendChild(fileImg) + this.uploadDiv.appendChild(document.createTextNode(this.file.name)) + this.uploadDiv.appendChild(document.createElement("br")) + this.uploadDiv.appendChild(linkSpan) +} +UploadProgressBar.prototype.onFailure = function(error) { + this.uploadDiv.innerHTML = "" // Remove uploading progress + this.uploadDiv.style.background = 'var(--danger_color)' + this.uploadDiv.appendChild(document.createTextNode(this.file.name)) + this.uploadDiv.appendChild(document.createElement("br")) + this.uploadDiv.appendChild(document.createTextNode("Upload failed after three tries:")) + this.uploadDiv.appendChild(document.createElement("br")) + this.uploadDiv.appendChild(document.createTextNode(error)) +} + + let uploader = null; let shareTitle = ""; let shareLink = ""; @@ -76,6 +74,10 @@ function handleUploads(files) { uploader = new UploadManager(apiEndpoint, uploadsFinished); } + if (files.length === 0) { + return; + } + for (let i = 0; i < files.length; i++) { new UploadProgressBar( uploader, @@ -143,13 +145,10 @@ function createList(title, anonymous) { } function hideShareButtons() { - document.getElementById("instruction_2").style.display = ""; - document.getElementById("instruction_3").style.display = "none"; document.getElementById("instruction_3_after").style.display = "none"; } function showShareButtons() { - document.getElementById("instruction_3").style.display = ""; document.getElementById("instruction_3_after").style.display = ""; if (window.navigator && window.navigator.share) { @@ -350,20 +349,19 @@ btnCopyMarkdown.addEventListener("click", function(){ /* * Keyboard shortcuts */ - document.addEventListener("keydown", function(event){ if (event.ctrlKey || event.altKey) { return // prevent custom shortcuts from interfering with system shortcuts } - if (event.which === 67 && !uploader.uploading()) { // c + if (event.keyCode === 67) { // c // Copy links to clipboard - copyLink(); - } else if (event.which === 85) { // u + document.getElementById("btn_copy_link").click(); + } else if (event.keyCode === 85) { // u // Click the upload button document.getElementById("file_input_field").click(); - } else if (event.which === 84) { // t + } else if (event.keyCode === 84) { // t // Click the text button document.getElementById("upload_text_button").click(); } - console.log(event.which) + console.log(event.keyCode) }); diff --git a/res/include/script/textupload.js b/res/include/script/textupload.js index 58f6e8f..e50cb4f 100644 --- a/res/include/script/textupload.js +++ b/res/include/script/textupload.js @@ -23,7 +23,7 @@ function uploadText() { // Upload the file when ctrl + s is pressed document.addEventListener("keydown", function(event) { - if (event.ctrlKey && (event.which === 83)) { + if (event.ctrlKey && (event.keyCode === 83)) { event.preventDefault(); uploadText(); return false; diff --git a/res/include/style/layout.css b/res/include/style/layout.css index 049b76d..761c255 100644 --- a/res/include/style/layout.css +++ b/res/include/style/layout.css @@ -245,23 +245,6 @@ hr{ margin: 16px 16px 16px 16px; } -::-webkit-scrollbar{ - width: 1em; /* for vertical scrollbars */ - height: 1em; /* for horizontal scrollbars */ -} -::-webkit-scrollbar-track { - background: var(--scrollbar_background_color); -} -::-webkit-scrollbar-thumb { - background-color: var(--scrollbar_foreground_color); - border-radius: 0.5em; - border: 0.22em solid var(--scrollbar_background_color); -} -::-webkit-scrollbar-thumb:hover { - background-color: var(--scrollbar_hover_color); -} -::-webkit-scrollbar-corner{background: var(--scrollbar_background_color);} - a {color: var(--highlight_color); text-decoration: none;} a:hover {color: var(--highlight_color); text-decoration: underline;} @@ -477,3 +460,66 @@ input[type=file]{ width: 0; height: 0; } + +/* Webkit Scrollbars */ + +::-webkit-scrollbar{ + width: 18px; /* for vertical scrollbars */ + height: 18px; /* for horizontal scrollbars */ +} +::-webkit-scrollbar-track { + background: var(--scrollbar_background_color); +} +::-webkit-scrollbar-thumb { + background-color: var(--scrollbar_foreground_color); + border-radius: 10px; + border: 5px solid var(--scrollbar_background_color); +} +::-webkit-scrollbar-thumb:hover { + background-color: var(--scrollbar_hover_color); +} +::-webkit-scrollbar-corner{ + background-color: var(--scrollbar_background_color); +} +::-webkit-scrollbar-button:single-button { + background-color: var(--scrollbar_background_color); + display: block; + border-style: solid; + height: 10px; + width: 10px; +} +::-webkit-scrollbar-button:single-button:vertical:decrement { + border-width: 0 8px 8px 8px; + border-color: transparent transparent var(--scrollbar_foreground_color) transparent; +} +::-webkit-scrollbar-button:single-button:vertical:decrement:hover { + border-color: transparent transparent var(--scrollbar_hover_color) transparent; +} +::-webkit-scrollbar-button:single-button:vertical:increment { + border-width: 8px 8px 0 8px; + border-color: var(--scrollbar_foreground_color) transparent transparent transparent; +} +::-webkit-scrollbar-button:vertical:single-button:increment:hover { + border-color: var(--scrollbar_hover_color) transparent transparent transparent; +} +::-webkit-scrollbar-button:single-button:horizontal:decrement { + border-width: 8px 8px 8px 0px; + border-color: transparent var(--scrollbar_foreground_color) transparent transparent; +} +::-webkit-scrollbar-button:single-button:horizontal:decrement:hover { + border-color: transparent var(--scrollbar_hover_color) transparent transparent; +} +::-webkit-scrollbar-button:single-button:horizontal:increment { + border-width: 8px 0px 8px 8px; + border-color: transparent transparent transparent var(--scrollbar_foreground_color); +} +::-webkit-scrollbar-button:horizontal:single-button:increment:hover { + border-color: transparent transparent transparent var(--scrollbar_hover_color); +} + +/* Firefox Scrollbar */ + +* { + /* scrollbar-color: var(--scrollbar_foreground_color) var(--scrollbar_background_color); */ + scrollbar-color: dark; +} diff --git a/res/include/style/viewer.css b/res/include/style/viewer.css index b5ce6eb..8c3b44f 100644 --- a/res/include/style/viewer.css +++ b/res/include/style/viewer.css @@ -48,6 +48,12 @@ .file_viewer > .file_viewer_headerbar > .button_home::after { content: "pixeldrain"; } +.file_viewer > .file_viewer_headerbar > .button_home > svg { + height: 1.7em; + width: 1.7em; + margin: -0.25em; + margin-right: 0.2em; +} @media (max-width: 500px) { .file_viewer > .file_viewer_headerbar > .button_home::after { content: "pd"; diff --git a/res/template/file_viewer.html b/res/template/file_viewer.html index c276be8..0503cfa 100644 --- a/res/template/file_viewer.html +++ b/res/template/file_viewer.html @@ -24,9 +24,7 @@
- Back to the Home page + {{template `pixeldrain.svg` .}}
@@ -153,8 +151,9 @@ {{template "analytics"}} diff --git a/webcontroller/viewer.go b/webcontroller/file_viewer.go similarity index 99% rename from webcontroller/viewer.go rename to webcontroller/file_viewer.go index d1d2e02..74248ef 100644 --- a/webcontroller/viewer.go +++ b/webcontroller/file_viewer.go @@ -35,7 +35,6 @@ func (wc *WebController) serveFileViewer(w http.ResponseWriter, r *http.Request, var list = strings.Contains(p.ByName("id"), ",") var ids []string - if list { ids = strings.Split(p.ByName("id"), ",") } else {