OnlyFans - Hide Video Controls Overlay

Hide the controls overlay on Onlyfans video player

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

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

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         OnlyFans - Hide Video Controls Overlay
// @version      0.6.3
// @description  Hide the controls overlay on Onlyfans video player
// @author       pipstar
// @match        https://onlyfans.com/*
// @run-at       document-start
// @grant        GM_registerMenuCommand
// @grant        GM_unregisterMenuCommand
// @grant        GM_getValue
// @grant        GM_setValue
// @icon         data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiI+PHJlY3QgeD0iMiIgeT0iMTAuNSIgd2lkdGg9IjI4IiBoZWlnaHQ9IjExIiByeD0iMy4yIiBmaWxsPSIjMDBBRkYwIi8+PHBhdGggZD0iTTcgMTMuNCBMNyAxOC42IEwxMS40IDE2IFoiIGZpbGw9IiNmZmYiLz48cmVjdCB4PSIxMy41IiB5PSIxNS4xIiB3aWR0aD0iMTQiIGhlaWdodD0iMS44IiByeD0iMC45IiBmaWxsPSIjZmZmIiBvcGFjaXR5PSIwLjQ1Ii8+PHJlY3QgeD0iMTMuNSIgeT0iMTUuMSIgd2lkdGg9IjYiIGhlaWdodD0iMS44IiByeD0iMC45IiBmaWxsPSIjZmZmIi8+PGNpcmNsZSBjeD0iMTkuNSIgY3k9IjE2IiByPSIyLjQiIGZpbGw9IiNmZmYiLz48bGluZSB4MT0iNCIgeTE9IjI4IiB4Mj0iMjgiIHkyPSI0IiBzdHJva2U9IiNmZmYiIHN0cm9rZS13aWR0aD0iNiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+PGxpbmUgeDE9IjQiIHkxPSIyOCIgeDI9IjI4IiB5Mj0iNCIgc3Ryb2tlPSIjZmYyZDU1IiBzdHJva2Utd2lkdGg9IjMuNCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+PC9zdmc+
// @license      MIT
// @namespace https://greasyfork.org/users/1275465
// ==/UserScript==

(function () {
    'use strict';

    /* ------------------------------------------------------------------ *
     * CONFIG - which elements count as "the controls" the toggle governs.
     * ------------------------------------------------------------------ */
    const HIDE_CONTROL_BAR     = true;  // bottom bar: play, scrubber, volume, quality, fullscreen, "record"
    const HIDE_BIG_PLAY_BUTTON = true;  // large centered play button overlay

    const selectors = [];
    if (HIDE_CONTROL_BAR)     selectors.push('.video-js .vjs-control-bar');
    if (HIDE_BIG_PLAY_BUTTON) selectors.push('.video-js .vjs-big-play-button');

    const HIDE_CSS = `${selectors.join(',\n')} {
        display: none !important;
        opacity: 0 !important;
        pointer-events: none !important;
    }`;

    /* ------------------------------------------------------------------ *
     * STATE - persisted across page loads. Defaults to hidden.
     * ------------------------------------------------------------------ */
    const STORAGE_KEY = 'of_controls_hidden';
    let hidden = GM_getValue(STORAGE_KEY, true);

    // Single <style> element we flip on/off. Injected at document-start so
    // the bar never flashes when controls are meant to be hidden.
    const style = document.createElement('style');
    style.id = 'of-hide-controls-style';
    (document.head || document.documentElement).appendChild(style);

    function applyState() {
        // When hidden, inject the rules; when shown, clear them so video.js
        // resumes its normal hover/autohide behavior. Updates live.
        style.textContent = (hidden && selectors.length) ? HIDE_CSS : '';
    }

    /* ------------------------------------------------------------------ *
     * MENU TOGGLE - appears in the Tampermonkey popup under this script.
     * Re-registered on each toggle so its label reflects the current state.
     * ------------------------------------------------------------------ */
    let menuId;
    function registerMenu() {
        if (menuId !== undefined && typeof GM_unregisterMenuCommand === 'function') {
            try { GM_unregisterMenuCommand(menuId); } catch (e) { /* older TM */ }
        }
        const label = hidden
            ? 'Video controls: HIDDEN  \u2014  click to show  (Ctrl+Alt+V)'
            : 'Video controls: SHOWN  \u2014  click to hide  (Ctrl+Alt+V)';
        menuId = GM_registerMenuCommand(label, toggle);
    }

    function toggle() {
        hidden = !hidden;
        GM_setValue(STORAGE_KEY, hidden);
        applyState();
        registerMenu(); // refresh the menu label
    }

    /* ------------------------------------------------------------------ *
     * FULLSCREEN HELPERS - target the .video-js container, not the raw
     * <video>, so the browser doesn't draw its own native controls.
     * ------------------------------------------------------------------ */
    function pickPlayer() {
        const players = [...document.querySelectorAll('.video-js')];
        if (!players.length) return null;
        // Prefer a player that's actually playing.
        const playing = players.find(p => {
            const v = p.querySelector('video');
            return v && !v.paused && !v.ended && v.readyState > 2;
        });
        if (playing) return playing;
        // Otherwise, the one with the largest visible area in the viewport.
        let best = null, bestArea = -1;
        for (const p of players) {
            const r = p.getBoundingClientRect();
            const w = Math.max(0, Math.min(r.right, innerWidth) - Math.max(r.left, 0));
            const h = Math.max(0, Math.min(r.bottom, innerHeight) - Math.max(r.top, 0));
            const area = w * h;
            if (area > bestArea) { bestArea = area; best = p; }
        }
        return best || players[0];
    }

    function toggleFullscreen() {
        const fsEl = document.fullscreenElement || document.webkitFullscreenElement;
        if (fsEl) {
            (document.exitFullscreen || document.webkitExitFullscreen || function () {}).call(document);
            return;
        }
        const el = pickPlayer();
        if (!el) return;
        const req = el.requestFullscreen || el.webkitRequestFullscreen;
        if (req) req.call(el);
    }

    /* ------------------------------------------------------------------ *
     * KEYBOARD SHORTCUTS
     *   Ctrl+Alt+V : toggle controls (works regardless of state)
     *   F          : fullscreen the video, ONLY while controls are hidden
     *                and only when not typing in a field. Press again (or
     *                Esc) to exit.
     * Uses e.code (physical key) so it's layout-independent.
     * ------------------------------------------------------------------ */
    function isTyping(e) {
        const t = e.target;
        if (!t) return false;
        return t.isContentEditable ||
            t.tagName === 'INPUT' || t.tagName === 'TEXTAREA' || t.tagName === 'SELECT';
    }

    document.addEventListener('keydown', e => {
        // Ctrl+Alt+V -> toggle controls
        if (e.ctrlKey && e.altKey && !e.shiftKey && !e.metaKey &&
            (e.code === 'KeyV' || (e.key && e.key.toLowerCase() === 'v'))) {
            e.preventDefault();
            e.stopPropagation();
            toggle();
            return;
        }
        // F (no modifiers) -> fullscreen, only while controls are hidden
        if (!e.ctrlKey && !e.altKey && !e.metaKey && !e.shiftKey &&
            (e.code === 'KeyF' || (e.key && e.key.toLowerCase() === 'f'))) {
            if (hidden && !isTyping(e)) {
                e.preventDefault();
                e.stopPropagation();
                toggleFullscreen();
            }
        }
    }, true); // capture phase so we act before the page's own handlers

    /* ------------------------------------------------------------------ *
     * BOOT
     * ------------------------------------------------------------------ */
    applyState();
    registerMenu();
})();