class Viewer { // Child components toolbar = null; listNavigator = null; detailsWindow = null; divFilepreview = null; currentFile = ""; title = ""; // Contains either the file name or list title listId = ""; isList = false; isFile = false; initialized = false; constructor(type, data) {let v = this; if(v.initialized){ return; } v.toolbar = new Toolbar(v); v.detailsWindow = new DetailsWindow(v); 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; } 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"; } else { document.getElementById("file_viewer_file_title").innerText = file.name; document.title = file.name + " ~ pixeldrain"; } // Update the file details v.detailsWindow.setDetails(file); // Clear the canvas v.divFilepreview.innerHTML = ""; if (file.mime_type.startsWith("image")) { new ImageViewer(v, file).render(v.divFilepreview); } else if (file.mime_type.startsWith("video")) { new VideoViewer(v, file, () => { if (v.listNavigator !== null) { v.listNavigator.nextItem(); } }).render(v.divFilepreview); } else if (file.mime_type.startsWith("audio") || file.mime_type === "application/ogg") { new AudioViewer(v, file, () => { if (v.listNavigator !== null) { v.listNavigator.nextItem(); } }).render(v.divFilepreview); } else { fetch("/u/"+file.id+"/preview").then(resp => { if (!resp.ok) { return Promise.reject(resp.status); } return resp.text(); }).then(resp => { v.divFilepreview.innerHTML = resp; }).catch(err => { v.divFilepreview.innerText = "Error loading file: "+err; }); } } 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.toolbar.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) { return String(str) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"'); }