X.com/Twitter Original Images by default (Cromite)

Replace X.com/Twitter images with original size. Compatible with Cromite browser (no @grant).

// ==UserScript==
// @name         X.com/Twitter Original Images by default (Cromite)
// @namespace    http://cromite.local
// @version      1.0
// @description  Replace X.com/Twitter images with original size. Compatible with Cromite browser (no @grant).
// @match        https://x.com/*
// @match        https://twitter.com/*
// @run-at       document-end
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    const lang = navigator.language.toLowerCase();
    const isZh = lang.startsWith('zh');

    // ---------- Settings / 设置 ----------
    let REPLACE_BIG_ON_START = localStorage.getItem('REPLACE_BIG_ON_START') === 'true';
    
    function toggleReplaceSetting() {
        REPLACE_BIG_ON_START = !REPLACE_BIG_ON_START;
        localStorage.setItem('REPLACE_BIG_ON_START', REPLACE_BIG_ON_START);
        alert(isZh
            ? `默认替换原图已设置为: ${REPLACE_BIG_ON_START ? '开' : '关'},请刷新页面生效`
            : `Default replacement with original images is now: ${REPLACE_BIG_ON_START ? 'ON' : 'OFF'}. Please refresh the page to apply.`);
        replaceAllImages(); // 切换时立即生效
    }

    // ---------- Utility / 工具 ----------
    function toOrigUrl(url) {
        if (!url) return url;
        try {
            const u = new URL(url);
            if (u.hostname.includes("twimg.com") && u.searchParams.has("name")) {
                u.searchParams.set("name", "orig");
                return u.toString();
            }
        } catch (e) {}
        return url;
    }

    function replaceAllImages() {
        // img 标签
        document.querySelectorAll('img[src*="twimg.com/media/"]').forEach(img => {
            if (!img.dataset.origProcessed) {
                if (REPLACE_BIG_ON_START) img.src = toOrigUrl(img.src);
                img.dataset.origProcessed = "true";
            }
        });
        // background-image
        document.querySelectorAll('div[style*="background-image"]').forEach(div => {
            if (!div.dataset.origProcessed) {
                const match = div.style.backgroundImage.match(/url\("(.*?)"\)/);
                if (match) {
                    const newUrl = toOrigUrl(match[1]);
                    if (REPLACE_BIG_ON_START && newUrl !== match[1]) div.style.backgroundImage = `url("${newUrl}")`;
                }
                div.dataset.origProcessed = "true";
            }
        });
    }

    // ---------- Right-click save ---------- 
    document.body.addEventListener('contextmenu', function(event) {
        const img = event.target.closest('img[src*="twimg.com/media/"]');
        if (img) img.src = toOrigUrl(img.src);
    }, true);

    // ---------- Shortcut key / 快捷键 Shift+O 切换默认替换 ----------
    document.addEventListener('keydown', function(e) {
        if (e.shiftKey && e.code === 'KeyO') toggleReplaceSetting();
    });

    // ---------- Initial execution / 首次执行 ----------
    replaceAllImages();

    // ---------- MutationObserver / 懒加载 ----------
    const observer = new MutationObserver(() => replaceAllImages());
    observer.observe(document.body, { childList: true, subtree: true });

})();