Vinted Dark Mode

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

คุณจะต้องติดตั้งส่วนขยาย เช่น Tampermonkey, Greasemonkey หรือ Violentmonkey เพื่อติดตั้งสคริปต์นี้

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

คุณจะต้องติดตั้งส่วนขยาย เช่น Tampermonkey หรือ Violentmonkey เพื่อติดตั้งสคริปต์นี้

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         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 });

})();