// ==UserScript== // @name pixeldrain improved (sort by size, markers and modal) // @namespace Violentmonkey Scripts // @icon data:image/png;base64,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 // @match https://pixeldrain.com/l/* // @version 1.1.8 // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @author dummy_mole // @license GNU GPLv3 // @description Improves the user experience on pixeldrain by adding a sort by size button, markers on viewed files and file playback in a modal window. // @downloadURL none // ==/UserScript== (() => { 'use strict'; //===================================script config panel part==================================== const defaultConfig = { "auto_sort_file": false, "show_file_size": true, "seen_file": false, "viewing_file_method": "2" }; function createConfigPanel() { // DOM creation const configPanel = `

Pixeldrain configuration

`; document.body.insertAdjacentHTML('afterbegin', configPanel); //--------------------------------------------------------------------------------------------- function slideOutAndRemove(element, classOut, classIn) { element.classList.remove(classOut); element.classList.add(classIn); setTimeout(() => element.remove(), 1000); } const configPanelContainer = document.querySelector('.config-panel-container'); const autoSortCheckbox = document.querySelector('#auto-sort'); const showFileSizeCheckbox = document.querySelector('#show-filesize'); const seenFileCheckbox = document.querySelector('#seen-file'); const viewedFileMethodSelect = document.querySelector('#file-viewing-method'); const saveBtn = document.querySelector('.save-btn'); const resetBtn = document.querySelector('.reset-btn'); const cancelBtn = document.querySelector('.cancel-btn'); // Load configuration values from script's local storage or use default values let config = JSON.parse(GM_getValue("pixeldrain_cfg", defaultConfig)); // Updates user interface elements with current configuration values autoSortCheckbox.checked = config.auto_sort_file; showFileSizeCheckbox.checked = config.show_file_size; seenFileCheckbox.checked = config.seen_file; viewedFileMethodSelect.value = config.viewing_file_method; // Updates configuration when user interface elements change autoSortCheckbox.onchange = function () { config.auto_sort_file = this.checked; }; showFileSizeCheckbox.onchange = function () { config.show_file_size = this.checked; }; seenFileCheckbox.onchange = function () { config.seen_file = this.checked; }; viewedFileMethodSelect.onchange = function () { config.viewing_file_method = this.value; }; // Saves configuration to script's local storage when user clicks "Save" saveBtn.onclick = function () { GM_setValue("pixeldrain_cfg", JSON.stringify(config)); location.reload(); }; // Resets the configuration to default values when the user clicks on "Reset". resetBtn.onclick = function () { config = defaultConfig; autoSortCheckbox.checked = defaultConfig.auto_sort_file; showFileSizeCheckbox.checked = defaultConfig.show_file_size; seenFileCheckbox.checked = defaultConfig.seen_file; viewedFileMethodSelect.value = defaultConfig.viewing_file_method; GM_setValue("pixeldrain_cfg", JSON.stringify(defaultConfig)); location.reload(); }; // Cancels changes made to the configuration when the user clicks on "Cancel". cancelBtn.onclick = function () { slideOutAndRemove(configPanelContainer, "slide-in-top", "slide-out-top"); }; //------------------------------------config panel css style----------------------------------- const configPanelStyle = `.config-panel-container{position:fixed!important;top:10px;right:10px;z-index:10001;display:flex;flex-direction:column;min-width:250px!important;max-width:320px!important;background:linear-gradient(0deg,#141617 0,rgba(27,27,28,.9) 50%,rgba(33,34,36,.9) 100%)!important;box-shadow:6px 6px 5px #00000069!important;padding:5px 15px!important;border:1px solid #282828!important;border-radius:5px!important;font-family:inherit;backdrop-filter:blur(15px);width:265px}.config-panel-title{margin:10px auto;padding-bottom:5px;color:#159cff!important;font-size:20px!important;font-weight:600}#file-viewing-method,.panel{color:#aaa!important}.auto-sort-container,.seen-file-container,.show-filesize-container,.watch-file-method{margin:10px auto}.separator{display:block;width:98%;height:1px;background:#fdfdfd0d}.validation-buton-container{display:flex;justify-content:space-evenly;margin:10px auto}.validation-buton-container>button{display:block;font-size:16px!important;color:#f5f5f5!important;background:#0087ff;border:transparent!important;border-radius:3px!important;height:30px!important;padding:0 10px!important;width:66px;box-shadow:unset!important}#file-viewing-method{background:#2d2d2d!important;border-radius:5px!important;border:1px solid #424242!important;width:70px!important;height:25px!important;text-align:center!important;padding:unset!important;box-shadow:unset!important}#file-viewing-method>option{background:#2d2d2d!important;color:#aaa!important}.cancel-btn{background:#4a4949!important}.slide-in-top{-webkit-animation:.9s cubic-bezier(.25,.46,.45,.94) both slide-in-top;animation:.9s cubic-bezier(.25,.46,.45,.94) both slide-in-top}.slide-out-top{-webkit-animation:.9s cubic-bezier(.55,.085,.68,.53) both slide-out-top;animation:.9s cubic-bezier(.55,.085,.68,.53) both slide-out-top}@-webkit-keyframes slide-in-top{0%{-webkit-transform:translateY(-1000px);transform:translateY(-1000px);opacity:0}75%{-webkit-transform:translateY(20px);transform:translateY(20px)}100%{-webkit-transform:translateY(0);transform:translateY(0);opacity:1}}@keyframes slide-in-top{0%{-webkit-transform:translateY(-1000px);transform:translateY(-1000px);opacity:0}75%{-webkit-transform:translateY(20px);transform:translateY(20px)}100%{-webkit-transform:translateY(0);transform:translateY(0);opacity:1}}@-webkit-keyframes slide-out-top{0%{-webkit-transform:translateY(0);transform:translateY(0);opacity:1}25%{-webkit-transform:translateY(20px);transform:translateY(20px)}100%{-webkit-transform:translateY(-1000px);transform:translateY(-1000px);opacity:0}}@keyframes slide-out-top{0%{-webkit-transform:translateY(0);transform:translateY(0)}25%{-webkit-transform:translateY(20px);transform:translateY(20px)}100%{-webkit-transform:translateY(-1000px);transform:translateY(-1000px)}}`; GM_addStyle(configPanelStyle); } //======================================Pixeldrain Part========================================== const URL = location.href; const API = 'https://pixeldrain.com/api/list/'; const descendingIcon = ``; const ascendingIcon = ``; const downloadIcon = ``; //===================================Only active on album pages=================================== if (/\/l\/(?![^\/]*item).*$/.test(URL)) { GM_registerMenuCommand("Pixeldrain configuration", createConfigPanel); if (!GM_getValue("pixeldrain_cfg")) GM_setValue("pixeldrain_cfg", JSON.stringify(defaultConfig)); const { auto_sort_file, show_file_size, seen_file, viewing_file_method } = JSON.parse(GM_getValue("pixeldrain_cfg")); const markers = []; //------------------------------Check if element exists function-------------------------------- const waitForElm = (selector, all = false) => { const elementDirect = all ? document.querySelectorAll(selector) : document.querySelector(selector); return new Promise(resolve => { if (elementDirect) { return resolve(elementDirect); } const observer = new MutationObserver(mutations => { const elementObserved = all ? document.querySelectorAll(selector) : document.querySelector(selector); if (elementObserved) { resolve(elementObserved); observer.disconnect(); } }); observer.observe(document.body, { childList: true, subtree: true }); }); }; //----------------------------------Bytes formatting function----------------------------------- const formatFileSize = bytes => { const units = ['o', 'Ko', 'Mo', 'Go', 'To', 'Po', 'Eo', 'Zo', 'Yo']; const exponent = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1); const size = (bytes / Math.pow(1024, exponent)).toFixed(2); return `${size} ${units[exponent]}`; }; //---------------------------------sorting function (by size)------------------------------------ let ascending = true; let filesNodelist; const sortByFileSize = (nodeList) => { const arrayFromNodeList = [...nodeList]; arrayFromNodeList.sort((a, b) => +a.dataset.size - +b.dataset.size); if (ascending) arrayFromNodeList.reverse(); const parentNode = nodeList[0].parentNode; parentNode.innerHTML = ''; arrayFromNodeList.forEach(element => parentNode.appendChild(element)); ascending = !ascending; }; //----------------------------------create sort button function--------------------------------- const createSortButton = (targetContainer, eventHandler) => { const sortButton = document.createElement('button'); sortButton.className = "toolbar_button sort-button"; sortButton.innerText = "Sort files"; const sortIconContainer = document.createElement('div'); sortIconContainer.className = "sort-icon-container"; sortIconContainer.insertAdjacentHTML("afterbegin", ascending ? ascendingIcon : descendingIcon); sortButton.prepend(sortIconContainer); sortButton.addEventListener('click', () => { eventHandler(filesNodelist); sortIconContainer.innerHTML = ""; sortIconContainer.insertAdjacentHTML("afterbegin", ascending ? ascendingIcon : descendingIcon); }); targetContainer.appendChild(sortButton); }; //----------------------------------------modal function---------------------------------------- const modal = (url, file) => { const fileLink = url + file.dataset.id; const fileType = file.dataset.type; const fileTypeShort = fileType.split("/")[0]; if (!["video", "audio", "image"].includes(fileTypeShort)) { const directDL = document.createElement('a'); directDL.href = fileLink; directDL.download = ""; directDL.click(); return; } const modalContainer = document.createElement('div'); modalContainer.className = "modal-container"; const modalFileContainer = document.createElement('div'); modalFileContainer.className = "modal-file-container"; let tag; if (fileTypeShort === "video") { const tagType = document.createElement('video'); tagType.controls = true; tagType.autoplay = true; tagType.src = fileLink; tag = tagType; } if (fileTypeShort === "audio") { const tagType = document.createElement('audio'); tagType.controls = true; tagType.autoplay = true; tagType.setAttribute('playsinline', ""); const source = document.createElement('source'); source.src = fileLink; source.type = fileType; tagType.appendChild(source); tag = tagType; } if (fileTypeShort === "image") { const tagType = document.createElement('img'); tagType.src = fileLink; tag = tagType; } const dlContainer = document.createElement('div'); dlContainer.className = "dl-container"; const downloadBtn = document.createElement('a'); downloadBtn.className = "download-file-btn"; downloadBtn.download = ""; downloadBtn.innerText = "Download"; downloadBtn.href = fileLink; downloadBtn.onclick = () => { const dlIcon = document.querySelector('.dl-container > #my-dl-icon'); dlIcon.classList.remove('backOutDown'); setTimeout(() => { dlIcon.classList.add('backOutDown'); }, 50); }; downloadBtn.insertAdjacentHTML('afterbegin', downloadIcon); modalContainer.addEventListener('click', e => { const clickedElement = e.target; if (clickedElement.matches('.modal-file-container')) modalContainer.remove(); if (clickedElement.matches('.download-file-btn')) setTimeout(() => modalContainer.remove(), 500); }); dlContainer.appendChild(downloadBtn); dlContainer.insertAdjacentHTML("beforeend", downloadIcon); modalFileContainer.appendChild(tag); modalContainer.appendChild(modalFileContainer); modalFileContainer.appendChild(dlContainer); body.appendChild(modalContainer); }; //--------------------------------fetching file details function-------------------------------- const fetchFileDetails = async () => { const albumID = URL.split('/').pop(); // fectch the API to get the file size, type, detail and identifier, allowing us to sort files by size and view them directly in the modal window if the option is selected try { const res = await fetch(`${API}${albumID}`); const { files: filesInfosArrayFromAPI } = await res.json(); const files = document.querySelectorAll('.gallery > .file'); //console.log(filesInfosArrayFromAPI) files.forEach((file, i) => { const { size: fileSize, id: fileID, mime_type: fileType, detail_href: fileDetail } = filesInfosArrayFromAPI[i]; file.setAttribute("data-size", fileSize); file.setAttribute("data-id", fileID); file.setAttribute("data-type", fileType); file.setAttribute("data-detail", `https://pixeldrain.com/api${fileDetail}`); if (viewing_file_method === "2") file.setAttribute("target", "_blank"); if (show_file_size) file.insertAdjacentHTML('beforeend', `

${formatFileSize(fileSize)}

`); }); filesNodelist = files; return filesNodelist; } catch (error) { console.error(error.message); throw error; } }; //==================================window load event listener=================================== window.addEventListener("load", () => { const body = document.body; const fileAPIUrl = 'https://pixeldrain.com/api/file/'; //----------------------------------------event handling---------------------------------------- // event delegation to manage actions on clicked files const gallery = document.querySelector('.gallery'); gallery.addEventListener('click', e => { const file = e.target.closest('a.file'); if (!file) return; if (seen_file && viewing_file_method !== "1") file.classList.add('seen'); if (viewing_file_method === "3") { e.preventDefault(); const unsupportedMimeTypes = [ // Audio "audio/3gpp", "audio/ac3", "audio/amr", "audio/flac", "audio/midi", "audio/mp2", "audio/mpegurl", "audio/x-aiff", "audio/x-ms-wax", "audio/x-ms-wma", "audio/x-pn-realaudio", "audio/x-realaudio", "audio/x-scpls", "audio/x-wav", // Video "video/3gpp", "video/3gpp2", "video/dv", "video/mpeg", "video/msvideo", "video/quicktime", "video/vnd.dlna.mpeg-tts", "video/vnd.rn-realvideo", "video/vnd.vivo", "video/x-f4v", "video/x-matroska", "video/x-mng", "video/x-ms-asf", "video/x-ms-wm", "video/x-ms-wmv", "video/x-ms-wvx", "video/x-msvideo", "video/x-sgi-movie", // Image "image/cgm", "image/fits", "image/g3fax", "image/ief", "image/jpm", "image/pcx", "image/pict", "image/x-cmu-raster", "image/x-cmx", "image/x-freehand", "image/x-icon", "image/x-jg", "image/x-portable-anymap", "image/x-portable-bitmap", "image/x-portable-graymap", "image/x-portable-pixmap", "image/x-rgb", "image/x-tga", "image/x-xbitmap", "image/x-xpixmap", "image/x-xwindowdump" ]; // Determine if the current file is suitable for modal playback based on its fetched mime-type and a predefined array of allowed mime-types. const detail = file.dataset.detail; const type = file.dataset.type; fetch(detail) .then(res => res.json()) .then(data => { const { allow_video_player, availability, availability_message } = data; if (allow_video_player && !unsupportedMimeTypes.includes(type) && (!availability.length || !availability_message.length)) { modal(fileAPIUrl, file); } else { window.open(file.href, "_blank"); } }) .catch(error => { console.error(error.message); }); } }); //---------------------------------------Details fetching--------------------------------------- // Execute once DOM and its ressources are fully loaded fetchFileDetails() .then(() => { if (auto_sort_file) sortByFileSize(filesNodelist); createSortButton(document.querySelector('.toolbar'), sortByFileSize); }); }); //--------Monitoring Hash Changes to re-run some script's funtionnalities on Gallery Return--------- window.addEventListener("hashchange", () => { if (window.location.href.split('#').at(-1) === "") { // wait for the files before executing function waitForElm(".gallery > a.file", true) .then(() => { return fetchFileDetails(); }) .then(files => { if (auto_sort_file) { ascending = true; sortByFileSize(files); } if (markers.length === 0) return; if (seen_file) { for (const file of files) { if (markers.includes(file.hash)) file.classList.add('seen'); } } }) .catch(error => { console.error(error); }); } else { const newItem = `#${window.location.href.split('#').at(-1)}`; if (markers.indexOf(newItem) === -1 ) markers.push(newItem); } }); //============================================CSS Style============================================= const pixeldrainStyle = `.sort-button{width:calc(100% - 4px);padding:6px 7px}.sort-icon-container{display:flex}.modal-container,a.file{display:flex!important;flex-direction:column}.sort-button svg{margin-right:2px;filter:invert(.18);pointer-events:none}a.file{position:relative;height:unset!important;justify-content:space-between;padding:0 10px}.seen{border:3px solid #1e90ff}.modal-container{justify-content:center!important;align-items:center!important;position:fixed!important;top:0!important;left:0!important;z-index:9999!important;width:100%!important;height:100%!important;background:rgb(0 0 0 / 90%)!important;animation:.3s ease-in fadeIn!important;backdrop-filter:blur(5px)!important;font-family:system-ui!important;overflow:hidden}.modal-file-container{position:absolute;width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;-webkit-animation:1s both scale-up-center!important;animation:1s both scale-up-center!important}.modal-file-container audio,.modal-file-container img,.modal-file-container video{max-width:80%;max-height:80%;box-shadow:8px 8px 3px rgba(0 0 0 / .2);border-radius:5px}.modal-file-container audio{max-width:unset!important;max-height:unset!important;width:80%}.dl-container{position:relative;display:flex;flex-direction:column}.dl-container>#my-dl-icon{position:absolute;top:20px;left:50%;width:80px;height:80px;translate:-50% 0;z-index:0;filter:invert(42%) sepia(90%) saturate(1352%) hue-rotate(190deg) brightness(85%) contrast(110%);opacity:0;pointer-events:none}.download-file-btn{position:relative;z-index:10000;background:#0f0f0f;text-decoration:none;color:#595959;font-size:18px;font-weight:600;padding:2px 15px;box-shadow:0 3px 3px rgba(0,0,0,.6);border:1px solid #131313;border-radius:3px;transition:background .2s;margin-top:15px}.download-file-btn:hover{background:#151515;color:#8c8c8c}.backOutDown{animation-name:backOutDown;animation-duration:0.5s;animation-fill-mode:both}.download-file-btn:active{background:#0f0f0f}.download-file-btn svg{pointer-events:none;filter:invert(.35)}.download-file-btn:hover svg{filter:invert(42%) sepia(90%) saturate(1352%) hue-rotate(190deg) brightness(85%) contrast(110%)}.download-file-btn:after{content:"";display:block;position:absolute;border-radius:1px;left:0;top:0;width:100%;height:100%;opacity:0;transition:.5s;box-shadow:0 0 10px 20px #157ce2}.download-file-btn:active:after{box-shadow:0 0 0 0 #157ce2;position:absolute;border-radius:1px;left:0;top:0;opacity:1;transition:none}@keyframes scale-up-center{0%{-webkit-transform:scale(0);transform:scale(0)}100%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes fadeIn{0%{-webkit-opacity:0;opacity:0}100%{-webkit-opacity:1;opacity:1}}@keyframes backOutDown{0%{transform:scale(1);opacity:1}100%{transform:translateY(700px) scale(0.7);opacity:0}}`; GM_addStyle(pixeldrainStyle); } })();