Tab Media Focus (Smart Filter)

Pause media in other tabs when playing media in current tab (mobile-like behavior)

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na inštaláciu tohto skriptu budete musieť nainštalovať rozšírenie, ako je napríklad Tampermonkey alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==UserScript==
// @name         Tab Media Focus (Smart Filter)
// @namespace    https://greasyfork.org/en/scripts/589569/
// @version      1.2
// @description  Pause media in other tabs when playing media in current tab (mobile-like behavior)
// @author       TechComet
// @match        *://*/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addValueChangeListener
// @run-at       document-idle
// @license      MIT
// ==/UserScript==

// Written using Qwen Ai from the first attempt

(function() {
    'use strict';

    // 1. Generate a unique ID for this tab
    const MY_TAB_ID = 'tab_' + Math.random().toString(36).substr(2, 9);
    const STORAGE_KEY = 'active_media_focus_id';

    // 2. Configuration for Smart Filtering
    const CONFIG = {
        ignoreMuted: true,             // Ignore muted videos (common in previews)
        ignoreShortDuration: true,     // Ignore very short videos (previews)
        minDurationSeconds: 5,         // Minimum duration to be considered "real" media
        previewKeywords: [             // Keywords in class names indicating previews
            'preview', 'thumbnail', 'mini', 'hover', 'feed', 'shorts',
            'ytd-thumbnail', 'video-preview', 'autoplay-preview'
        ]
    };

    console.log(`[MediaFocus] Initialized: ${MY_TAB_ID}`);

    // 3. Check if video is a preview/thumbnail based on multiple criteria
    function isPreviewVideo(media) {
        // A. Check Mute Status (Fastest & Most Reliable)
        if (CONFIG.ignoreMuted && (media.muted || media.volume === 0)) {
            return true;
        }

        // B. Check Class Names (Fast)
        if (media.classList) {
            for (let i = 0; i < media.classList.length; i++) {
                const cls = media.classList[i].toLowerCase();
                for (const keyword of CONFIG.previewKeywords) {
                    if (cls.includes(keyword)) {
                        return true;
                    }
                }
            }
        }

        // C. Check Duration (Reliable if metadata loaded)
        if (CONFIG.ignoreShortDuration && media.duration) {
            if (isFinite(media.duration) && media.duration < CONFIG.minDurationSeconds) {
                return true;
            }
        }

        return false;
    }

    // 4. Pause all media elements in this tab
    function pauseAllMedia() {
        const mediaElements = document.querySelectorAll('video, audio');
        let pausedCount = 0;
        mediaElements.forEach(media => {
            if (!media.paused) {
                media.pause();
                pausedCount++;
            }
        });
        if (pausedCount > 0) console.log(`[MediaFocus] Paused ${pausedCount} media element(s)`);
    }

    // 5. Claim focus when valid media starts playing
    function claimFocus() {
        GM_setValue(STORAGE_KEY, MY_TAB_ID);
    }

    // 6. Listen for 'play' events on the window (Capture Phase)
    // This avoids MutationObserver for better performance
    window.addEventListener('play', (event) => {
        const target = event.target;

        // Ensure it's a valid media element
        if (target instanceof HTMLMediaElement) {
            // Apply smart filters
            if (isPreviewVideo(target)) {
                return; // Ignore preview/thumbnail videos
            }

            // Valid media detected, claim focus
            console.log(`[MediaFocus] Valid media play detected`);
            claimFocus();
        }
    }, true); // 'true' enables capture phase

    // 7. Listen for changes from other tabs via shared storage
    GM_addValueChangeListener(STORAGE_KEY, function(key, oldVal, newVal, remote) {
        // If change came from a remote tab and it's not us, pause local media
        if (remote && newVal && newVal !== MY_TAB_ID) {
            console.log(`[MediaFocus] Tab ${newVal} is playing, pausing local media`);
            pauseAllMedia();
        }
    });

})();