[Wallhaven] Subscription Tools

Adds a useful "tool box" to the top of the side bar on the subscriptions page (Filter Subs by name, sort them by amount, toggle on/off visibility of subs with 0 new wallpapers)

Bu betiği kurabilmeniz için Tampermonkey, Greasemonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği yüklemek için Tampermonkey gibi bir uzantı yüklemeniz gerekir.

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Userscripts gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği indirebilmeniz için ayrıca Tampermonkey gibi bir eklenti kurmanız gerekmektedir.

Bu komut dosyasını yüklemek için bir kullanıcı komut dosyası yöneticisi uzantısı yüklemeniz gerekecek.

(Zaten bir kullanıcı komut dosyası yöneticim var, kurmama izin verin!)

Bu stili yüklemek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için Stylus gibi bir uzantı kurmanız gerekir.

Bu stili yükleyebilmek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı kurmanız gerekir.

Bu stili yükleyebilmek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

(Zateb bir user-style yöneticim var, yükleyeyim!)

// ==UserScript==
// @name         [Wallhaven] Subscription Tools
// @namespace    NooScripts
// @author       NooScripts
// @version      1.6
// @description  Adds a useful "tool box" to the top of the side bar on the subscriptions page (Filter Subs by name, sort them by amount, toggle on/off visibility of subs with 0 new wallpapers)
// @license MIT
// @match        https://wallhaven.cc/subscription*
// @grant        none
// ==/UserScript==

window.addEventListener('load', () => {
    'use strict';

    // Create container for search tools
    const container = document.createElement('div');
    container.id = 'custom-tag-filter';
    container.style.display = 'flex';
    container.style.flexDirection = 'column';
    container.style.alignItems = 'center';
    container.style.gap = '8px';
    container.style.padding = '10px';
    container.style.background = '#111';
    container.style.zIndex = '9999';

    // Search input
    const input = document.createElement('input');
    input.type = 'text';
    input.placeholder = 'Filter tags...';
    input.style.padding = '6px';
    input.style.width = '100%';
    input.style.background = '#222';
    input.style.color = '#fff';
    input.style.border = '1px solid #555';
    input.style.borderRadius = '4px';

    // Create a container for buttons
    const buttonsContainer = document.createElement('div');
    buttonsContainer.style.display = 'flex';
    buttonsContainer.style.gap = '8px';
    buttonsContainer.style.width = '100%';
    buttonsContainer.style.margin = 'auto';

    // Reset button
    const resetBtn = document.createElement('button');
    resetBtn.textContent = 'Reset';
    resetBtn.style.padding = '6px 10px';
    resetBtn.style.background = '#333';
    resetBtn.style.color = '#fff';
    resetBtn.style.border = '1px solid #555';
    resetBtn.style.borderRadius = '4px';
    resetBtn.style.cursor = 'pointer';
    resetBtn.style.flex = '1';

    // Toggle style button
    const toggleBtn = document.createElement('button');
    toggleBtn.style.padding = '6px 10px';
    toggleBtn.style.background = '#333';
    toggleBtn.style.color = '#fff';
    toggleBtn.style.border = '1px solid #555';
    toggleBtn.style.borderRadius = '4px';
    toggleBtn.style.cursor = 'pointer';
    toggleBtn.style.flex = '1';

    // Append buttons to the buttons container
    buttonsContainer.appendChild(resetBtn);
    buttonsContainer.appendChild(toggleBtn);

    // Append input and buttons container to the main container
    container.appendChild(input);
    container.appendChild(buttonsContainer);

    // Insert above .sidebar-background
    const sidebarBg = document.querySelector('.sidebar-background');
    if (sidebarBg && sidebarBg.parentNode) {
        sidebarBg.parentNode.insertBefore(container, sidebarBg);
    } else {
        console.warn('⚠️ Could not find sidebar');
    }

    // Initialize styleEnabled from localStorage or default to true
    let styleEnabled = localStorage.getItem('styleEnabled') !== null
        ? JSON.parse(localStorage.getItem('styleEnabled'))
        : true;

    const styleSheet = document.createElement('style');
    document.head.appendChild(styleSheet);

    // Set initial button text and stylesheet based on styleEnabled
    toggleBtn.textContent = styleEnabled ? 'Show Empty' : 'Hide Empty';
    styleSheet.textContent = styleEnabled ? `
        .blocklist.subscription-list li:is([class=""]) {
            display: none !important;
        }
    ` : '';

    // Load saved input text from localStorage
    input.value = localStorage.getItem('filterText') || '';
    if (input.value) performFiltering(); // Apply filter if there's saved text

    // Add or remove the CSS to hide empty <li> elements
    function toggleStyle() {
        styleEnabled = !styleEnabled;
        localStorage.setItem('styleEnabled', JSON.stringify(styleEnabled)); // Save to localStorage

        if (styleEnabled) {
            styleSheet.textContent = `
                .blocklist.subscription-list li:is([class=""]) {
                    display: none !important;
                }
            `;
            toggleBtn.textContent = 'Show Empty';
        } else {
            styleSheet.textContent = '';
            toggleBtn.textContent = 'Hide Empty';
        }
    }

    // Function to get all li elements in blocklist
    function getTagItems() {
        return Array.from(document.querySelectorAll('ul.blocklist.subscription-list li'));
    }

    // Perform filtering based on input
    function performFiltering() {
        const term = input.value.toLowerCase().trim();
        localStorage.setItem('filterText', input.value); // Save input text to localStorage
        const items = getTagItems();
        items.forEach(li => {
            const tag = li.querySelector('.tagname');
            if (!tag) return;
            const tagText = tag.textContent.toLowerCase();
            li.style.display = tagText.includes(term) ? '' : 'none';
        });
    }

    // Reset the filter
    function resetFilter() {
        const items = getTagItems();
        items.forEach(li => li.style.display = '');
        input.value = '';
        localStorage.setItem('filterText', ''); // Clear saved input text
    }

    // Add event listeners
    input.addEventListener('input', performFiltering);
    resetBtn.addEventListener('click', resetFilter);
    toggleBtn.addEventListener('click', toggleStyle);
});



//Script 2: Sort Subscriptions By Number

function sortListItems(descending) {
    const container = document.querySelector('[data-storage-id="tagsubscriptions"]');
    if (!container) {
        console.error('Tag subscriptions container not found.');
        return;
    }

    const listItems = Array.from(container.querySelectorAll('.blocklist[class*="subscription-list"] [class*="has-"]'));

    listItems.sort((a, b) => {
        const valueA = parseInt(a.querySelector('small').textContent);
        const valueB = parseInt(b.querySelector('small').textContent);

        return descending ? valueB - valueA : valueA - valueB;
    });

    listItems.forEach((item) => {
        const parent = item.parentNode;
        parent.appendChild(item);
    });
}

function createDropdown(labelText, options, onChange) {
    const dropdown = document.createElement('select');

    options.forEach(option => {
        const optionElement = document.createElement('option');
        optionElement.value = option.value;
        optionElement.text = option.text;
        dropdown.appendChild(optionElement);
    });

    dropdown.addEventListener('change', onChange);

    const label = document.createElement('label');
    label.style.marginRight = '10px';
    label.appendChild(document.createTextNode(labelText + ': '));
    label.appendChild(dropdown);

    return label;
}

function handleSortDropdownChange() {
    if (this.value === 'default') {
        localStorage.removeItem('subscriptionSortOrder');
        location.reload();
        return;
    }

    const descending = this.value === 'desc';
    sortListItems(descending);
    localStorage.setItem('subscriptionSortOrder', descending ? 'desc' : 'asc');
}

function handleDisplayDropdownChange() {
    const existingStyle = document.getElementById('display-filter-style');
    if (existingStyle) {
        existingStyle.remove();
    }

    let css = '';
    switch (this.value) {
        case 'sfw':
            css = `
                [class="has-new "]:has([class="tagname sketchy"]) {display: none!important;}
                [class="has-new "]:has([class="tagname nsfw"]) {display: none!important;}
            `;
            break;
        case 'sketch':
            css = `
                [class="has-new "]:has([class="tagname sfw"]) {display: none!important;}
                [class="has-new "]:has([class="tagname nsfw"]) {display: none!important;}
            `;
            break;
        case 'nsfw':
            css = `
                [class="has-new "]:has([class="tagname sfw"]) {display: none!important;}
                [class="has-new "]:has([class="tagname sketchy"]) {display: none!important;}
            `;
            break;
    }

    if (css) {
        const style = document.createElement('style');
        style.id = 'display-filter-style';
        style.textContent = css;
        document.head.appendChild(style);
    }

    localStorage.setItem('subscriptionDisplayFilter', this.value);
}

function initializeDropdown() {
    const sortDropdownOptions = [
        { value: 'default', text: 'Default' },
        { value: 'desc', text: 'Most to Least' },
        { value: 'asc', text: 'Least To Most' }
    ];

    const displayDropdownOptions = [
        { value: 'all', text: 'All' },
        { value: 'sfw', text: 'Only SFW' },
        { value: 'sketch', text: 'Only Sketch' },
        { value: 'nsfw', text: 'Only NSFW' }
    ];

    const sortDropdown = createDropdown('Sort Order', sortDropdownOptions, handleSortDropdownChange);
    const displayDropdown = createDropdown('Display', displayDropdownOptions, handleDisplayDropdownChange);

    const container = document.createElement('div');
    container.id = 'sort-dropdown-container';
    container.style.padding = '0px 0px 8px 0px';
    container.style.marginBottom = '10px';
    container.style.backgroundColor = '#111111';
    container.style.borderBottom = '1px solid #4a4a4a';
    container.style.fontSize = '12px';
    container.style.display = 'flex';
    container.style.alignItems = 'center';
    container.style.gap = '10px';

    container.appendChild(sortDropdown);
    container.appendChild(displayDropdown);

    const sidebarBackground = document.querySelector('.sidebar-background');
    if (sidebarBackground) {
        sidebarBackground.insertBefore(container, sidebarBackground.firstChild);
    } else {
        console.error('.sidebar-background element not found.');
    }

    const sortOrder = localStorage.getItem('subscriptionSortOrder');
    if (sortOrder === 'desc') {
        sortDropdown.querySelector('select').value = 'desc';
        sortListItems(true);
    } else if (sortOrder === 'asc') {
        sortDropdown.querySelector('select').value = 'asc';
        sortListItems(false);
    }

    const displayFilter = localStorage.getItem('subscriptionDisplayFilter');
    if (displayFilter) {
        displayDropdown.querySelector('select').value = displayFilter;
        handleDisplayDropdownChange.call(displayDropdown.querySelector('select'));
    }
}

initializeDropdown();