Mega.nz File Sorter (Size & Type)

Add buttons to sort by size and file type on mega.nz

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name:vi Mega.nz File Sorter (Size & Type)
// @name:en Mega.nz File Sorter (Size & Type)
// @name Mega.nz File Sorter (Size & Type)
// @namespace    https://greasyfork.org/vi/users/1195312-renji-yuusei
// @version 0.6
// @description:vi Thêm nút sắp xếp theo kích thước và loại tệp trên mega.nz
// @description:en Add buttons to sort by size and file type on mega.nz
// @description Add buttons to sort by size and file type on mega.nz
// @author JethaLal_420 (modified by RenjiYuusei)
// @match https://mega.nz/folder/*
// @icon https://www.google.com/s2/favicons?domain=mega.nz
// @grant none
// @license MIT
// ==/UserScript==

(function() {
'use strict';

// Global variable declarations
let listViewBtn, blockViewBtn, sortBySizeBtn, sortByTypeBtn;

// Function to create button with enhanced properties
const createBtn = (text, id, onClick) => {
    const button = document.createElement('button');
    Object.assign(button, {
        innerHTML: text,
        id: id,
        className: 'mega-sort-btn',
        style: `
            padding: 8px 12px;
            margin: 0 5px;
            border-radius: 4px;
            background: #ff0000;
            color: white;
            border: none;
            cursor: pointer;
            transition: all 0.3s ease;
        `
    });
    button.addEventListener('click', onClick);
    button.addEventListener('mouseover', () => button.style.opacity = '0.8');
    button.addEventListener('mouseout', () => button.style.opacity = '1');
    return button;
};

// Function to sort by size with better error handling
const sortBySize = async () => {
    try {
        listViewBtn.click();
        const sizeBtn = await waitForElement('.size', 5000); // Wait up to 5 seconds
        if (sizeBtn) {
            sizeBtn.click();
            setTimeout(() => sizeBtn.click(), 100); // Second click for descending order
        }
        blockViewBtn.click();
    } catch (error) {
        console.error('Error sorting by size:', error);
        alert('Unable to sort by size. Please try again.');
    }
};

// Function to sort by type with better error handling
const sortByType = async () => {
    try {
        listViewBtn.click();
        const typeBtn = await waitForElement('.type', 5000);
        if (typeBtn) {
            typeBtn.click();
        }
        blockViewBtn.click();
    } catch (error) {
        console.error('Error sorting by type:', error);
        alert('Unable to sort by type. Please try again.');
    }
};

// Utility function to wait for element to appear in DOM
const waitForElement = (selector, timeout = 5000) => {
    return new Promise((resolve, reject) => {
        const element = document.querySelector(selector);
        if (element) return resolve(element);

        const observer = new MutationObserver(() => {
            const element = document.querySelector(selector);
            if (element) {
                observer.disconnect();
                resolve(element);
            }
        });

        observer.observe(document.body, {
            childList: true,
            subtree: true
        });

        setTimeout(() => {
            observer.disconnect();
            reject(new Error(`Element ${selector} not found after ${timeout}ms`));
        }, timeout);
    });
};

// Function to check and insert buttons with better error handling
const checkAndInsertBtns = async () => {
    try {
        listViewBtn = document.querySelector('.listing-view');
        blockViewBtn = document.querySelector('.block-view');

        if (listViewBtn && blockViewBtn && !sortBySizeBtn) {
            const parentNode = document.querySelector('.fm-breadcrumbs-wrapper');
            const childNode = document.querySelector('.fm-breadcrumbs-block');

            if (!parentNode || !childNode) {
                throw new Error('Button insertion location not found');
            }

            sortBySizeBtn = createBtn('Sort by Size', 'sortbysize', sortBySize);
            sortByTypeBtn = createBtn('Sort by Type', 'sortbytype', sortByType);

            parentNode.insertBefore(sortBySizeBtn, childNode);
            parentNode.insertBefore(sortByTypeBtn, childNode);
        }
    } catch (error) {
        console.error('Error initializing buttons:', error);
    }
};

// Create observer and initialize
try {
    const observer = new MutationObserver(checkAndInsertBtns);
    observer.observe(document.body, { 
        childList: true, 
        subtree: true 
    });
    checkAndInsertBtns();
} catch (error) {
    console.error('Error initializing observer:', error);
}

})();