Tab Media Focus (Smart Filter)

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

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

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

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// ==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();
        }
    });

})();