Vinted Dark Mode

Global Dark Mode for Vinted (buttons, inputs, chips, navigation, stars, titles, footer, SPA support, app store badges)

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name         Vinted Dark Mode
// @namespace    https://greasyfork.org/en/users/1550823-nigel1992
// @version      0.30
// @description  Global Dark Mode for Vinted (buttons, inputs, chips, navigation, stars, titles, footer, SPA support, app store badges)
// @author       Nigel1992
// @match        *://*.vinted.at/*
// @match        *://*.vinted.be/*
// @match        *://*.vinted.co.uk/*
// @match        *://*.vinted.cz/*
// @match        *://*.vinted.de/*
// @match        *://*.vinted.dk/*
// @match        *://*.vinted.es/*
// @match        *://*.vinted.fr/*
// @match        *://*.vinted.hu/*
// @match        *://*.vinted.it/*
// @match        *://*.vinted.lt/*
// @match        *://*.vinted.lu/*
// @match        *://*.vinted.nl/*
// @match        *://*.vinted.pl/*
// @match        *://*.vinted.pt/*
// @match        *://*.vinted.ro/*
// @match        *://*.vinted.se/*
// @match        *://*.vinted.sk/*
// @grant        GM_addStyle
// @grant        GM_setValue
// @grant        GM_getValue
// @run-at      document-start
// @license MIT
// ==/UserScript==

(function () {
    'use strict';

    const darkCSS = `
    /* ===== Base Dark Mode Colors ===== */
    html.dark-mode {
        --color-background-primary: #121212 !important;
        --color-background-secondary: #1a1a1a !important;
        --color-text-primary: #e0e0e0 !important;
        --color-text-secondary: #aaaaaa !important;
        --color-border-primary: #333333 !important;
        --color-button-primary-background: #007782 !important;
        --color-button-primary-text: #ffffff !important;
    }
    html.dark-mode, html.dark-mode body, html.dark-mode #content, html.dark-mode .viewport, html.dark-mode .web_ui__Page__page, html.dark-mode [class*="u-background-white"] {
        background-color: #121212 !important;
        color: #e0e0e0 !important;
        transition: background 0.3s ease, color 0.3s ease;
    }

    /* ===== Headers, Tabs ===== */
    html.dark-mode .l-header, html.dark-mode .l-header__main, html.dark-mode .l-header__navigation, html.dark-mode .web_ui__Tabs__tabs {
        background-color: #121212 !important;
        border-bottom: 1px solid #333 !important;
    }

    /* ===== Text, feeds ===== */
    html.dark-mode svg { fill: #ffffff !important; stroke: #ffffff !important; }
    html.dark-mode .feed-grid, html.dark-mode .catalog-container, html.dark-mode .u-bg-white { background-color: #121212 !important; }
    html.dark-mode .web_ui__Text__text, html.dark-mode p, html.dark-mode span, html.dark-mode h1, html.dark-mode h2, html.dark-mode h3 { color: #e0e0e0 !important; }

    /* ===== Inbox / Thread ===== */
    html.dark-mode .inbox-page__container, html.dark-mode .inbox-page__block, html.dark-mode .thread__wrapper, html.dark-mode .thread__messages-container, html.dark-mode .thread__content { background-color: #121212 !important; }
    html.dark-mode .inbox-page__block--sidebar, html.dark-mode .conversation-list-toolbar, html.dark-mode .u-fill-height.u-overflow-auto { background-color: #121212 !important; }
    html.dark-mode [data-testid^="inbox-list-item"], html.dark-mode .web_ui__Cell__cell { background-color: #121212 !important; border-bottom: 1px solid #2a2a2a !important; }
    html.dark-mode .u-background-gray { background-color: #1a1a1a !important; }
    html.dark-mode .web_ui__Cell__navigating:hover { background-color: #1e1e1e !important; }
    html.dark-mode .web_ui__Card__card, html.dark-mode .web_ui__Card__lifted { background-color: #1a1a1a !important; border: 1px solid #2a2a2a !important; }
    html.dark-mode .conversation-header { background-color: #121212 !important; border-bottom: 1px solid #333 !important; }
    html.dark-mode .web_ui__Bubble__bubble { background-color: #1e1e1e !important; color: #e0e0e0 !important; }
    html.dark-mode .web_ui__Bubble__inverse { background-color: #007782 !important; color: #ffffff !important; }
    html.dark-mode .web_ui__Text__caption { color: #999 !important; }
    html.dark-mode .web_ui__Divider__divider { background-color: #2a2a2a !important; }

    /* ===== Dark Mode Buttons: Toggle & Bug ===== */
    #vinted-dark-toggle, #vinted-bug-report {
        position: fixed;
        right: 20px;
        z-index: 9999;
        padding: 10px 18px;
        border-radius: 50px;
        font-weight: bold;
        cursor: pointer;
        box-shadow: 0 4px 15px rgba(0,0,0,0.6);
        text-align: center;
        font-family: sans-serif;
    }
    #vinted-dark-toggle { bottom: 70px; background: #2a2a2a; color: #ffffff; border: 1px solid #555; }
    #vinted-bug-report { bottom: 20px; background: #ff5555; color: #fff; border: 1px solid #cc0000; }
    #vinted-dark-toggle:hover { background: #3a3a3a; }
    #vinted-bug-report:hover { background: #ff3333; }

    @media (max-width: 600px) {
        #vinted-dark-toggle, #vinted-bug-report { right: 10px; padding: 8px 14px; font-size: 14px; }
        #vinted-dark-toggle { bottom: 60px; }
        #vinted-bug-report { bottom: 10px; }
    }

    /* ===== Chips ===== */
    html.dark-mode .web_ui__Chip__chip {
        background-color: #007782 !important;
        color: #ffffff !important;
        border-color: #005f63 !important;
    }
    html.dark-mode .web_ui__Chip__chip .web_ui__Text__text { color: #ffffff !important; }
    html.dark-mode .web_ui__Chip__chip svg { fill: #ffffff !important; stroke: #ffffff !important; }
    html.dark-mode .web_ui__Chip__chip.web_ui__Chip__outlined { border-color: #ffffff !important; }

    /* ===== Inputs ===== */
    html.dark-mode .web_ui__Input__input { background-color: #1a1a1a !important; border: 1px solid #333 !important; color: #e0e0e0 !important; }
    html.dark-mode .web_ui__Input__title { color: #e0e0e0 !important; }
    html.dark-mode .web_ui__Input__value { background-color: #222 !important; color: #ffffff !important; border: none !important; caret-color: #ffffff !important; }

    /* ===== Navigation & Buttons ===== */
    html.dark-mode .web_ui__Button__button {
        background-color: #007782 !important;
        color: #ffffff !important;
        border: 1px solid #005f63 !important;
    }
    html.dark-mode .web_ui__Button__button .web_ui__Button__content,
    html.dark-mode .web_ui__Button__button .web_ui__Button__icon,
    html.dark-mode .web_ui__Button__button svg {
        color: #ffffff !important;
        fill: #ffffff !important;
        stroke: #ffffff !important;
    }

    /* ===== Star Ratings ===== */
    html.dark-mode .web_ui__Rating__star .web_ui__Icon__icon svg path {
        fill: #007782 !important;
    }

    /* ===== Cell Titles ===== */
    html.dark-mode .web_ui__Cell__title {
        color: #007782 !important;
    }

    /* ===== Footer Dark Mode ===== */
    html.dark-mode .main-footer__content {
        background-color: #121212 !important;
        color: #e0e0e0 !important;
    }
    html.dark-mode .main-footer__links-section-label {
        color: #007782 !important;
    }
    html.dark-mode .main-footer__links-section-link,
    html.dark-mode .main-footer__privacy-section-link,
    html.dark-mode .main-footer__privacy-section-link button {
        color: #007782 !important;
    }
    html.dark-mode .web_ui__Divider__divider {
        background-color: #2a2a2a !important;
    }

    /* ===== Footer Social Icons ===== */
    html.dark-mode .main-footer__social-media-link img {
        filter: brightness(0) invert(1);
    }

    /* ===== Footer App Store Badges ===== */
    html.dark-mode .main-footer__social-section-app-store {
        background-color: #121212 !important;
        padding: 10px 0;
    }
    html.dark-mode .main-footer__social-app-store-item {
        margin-right: 10px;
    }
    html.dark-mode .main-footer__social-app-store-item a {
        display: inline-block;
    }
    html.dark-mode .main-footer__social-app-store-item img {
        filter: none !important;
        background-color: #121212;
        border-radius: 5px;
        padding: 2px;
    }
    `;

    GM_addStyle(darkCSS);

    const htmlEl = document.documentElement;

    // Dark mode preference
    let isDark = GM_getValue('darkMode', null);
    if (isDark === null) {
        isDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
        GM_setValue('darkMode', isDark);
    }
    if (isDark) htmlEl.classList.add('dark-mode');

    function onBodyReady(callback) {
        if (document.body) return callback();
        new MutationObserver((obs) => {
            if (document.body) {
                obs.disconnect();
                callback();
            }
        }).observe(document.documentElement, { childList: true, subtree: true });
    }

    onBodyReady(() => {
        // ===== Create Toggle & Bug Buttons =====
        const darkBtn = document.createElement('button');
        darkBtn.id = 'vinted-dark-toggle';
        darkBtn.textContent = isDark ? '☀️ Light' : '🌙 Dark';
        document.body.appendChild(darkBtn);

        const bugBtn = document.createElement('button');
        bugBtn.id = 'vinted-bug-report';
        bugBtn.textContent = '🐞 Report Issue';
        document.body.appendChild(bugBtn);

        bugBtn.addEventListener('click', () => {
            if (document.getElementById('vinted-bug-modal')) return;
            const overlay = document.createElement('div');
            overlay.id = 'vinted-bug-modal';
            Object.assign(overlay.style, {
                position: 'fixed', top: 0, left: 0, width: '100%', height: '100%',
                background: 'rgba(0,0,0,0.6)', display: 'flex', alignItems: 'center',
                justifyContent: 'center', zIndex: 9999
            });

            const modal = document.createElement('div');
            Object.assign(modal.style, {
                background: '#1a1a1a', color: '#e0e0e0', padding: '20px 25px', borderRadius: '10px',
                maxWidth: '400px', textAlign: 'center', fontFamily: 'sans-serif',
                boxShadow: '0 4px 15px rgba(0,0,0,0.5)'
            });

            modal.innerHTML = `
                <p>⚠️ Please check the known issues first:</p>
                <p><a href="https://greasyfork.org/en/scripts/560002-vinted-dark-mode-toggle" target="_blank" style="color:#00bcd4; text-decoration:underline;">Vinted Dark Mode Known Issues</a></p>
                <button id="vinted-bug-ok" style="
                    margin-top: 15px;
                    padding: 8px 16px;
                    border:none;
                    border-radius:5px;
                    background:#007782;
                    color:#fff;
                    font-weight:bold;
                    cursor:pointer;
                ">Unknown issue? Click here to report</button>
            `;
            overlay.appendChild(modal);
            document.body.appendChild(overlay);

            document.getElementById('vinted-bug-ok').addEventListener('click', () => {
                document.body.removeChild(overlay);
                window.open('https://greasyfork.org/en/scripts/560002-vinted-dark-mode-toggle/feedback', '_blank');
            });
        });

        // ===== Dark Mode Toggle Event =====
        darkBtn.addEventListener('click', () => {
            isDark = !isDark;
            htmlEl.classList.toggle('dark-mode', isDark);
            darkBtn.textContent = isDark ? '☀️ Light' : '🌙 Dark';
            GM_setValue('darkMode', isDark);
        });
    });

    // ===== SPA & URL Observer (throttled) =====
    let lastUrl = location.href;
    let throttleTimeout = null;
    new MutationObserver(() => {
        if (throttleTimeout) return;
        throttleTimeout = setTimeout(() => {
            throttleTimeout = null;
            const currentUrl = location.href;
            if (currentUrl !== lastUrl) {
                lastUrl = currentUrl;
                if (GM_getValue('darkMode', false)) htmlEl.classList.add('dark-mode');
            }
        }, 200);
    }).observe(document.body || document.documentElement, { childList: true, subtree: true });

})();