Greasy Fork

Greasy Fork is available in English.

片頭自動跳轉 用AI寫的

重點強化文字顏色自定義,支援分:秒顯示與拖動開關

当前为 2025-12-30 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         片頭自動跳轉 用AI寫的
// @namespace    http://tampermonkey.net/
// @version      1.0
// @license MIT
// @description  重點強化文字顏色自定義,支援分:秒顯示與拖動開關
// @match        *://www.ntdm8.com/play/*
// @match        *://www.agedm.io/play/*
// @match        *://www.857fans.com/play/*
// @match        *://*.ntdm8.com/*
// @match        *://*.agefans.*/*
// @match        *://*.agemys.*/*
// @match        *://*.agedm.*/*
// @match        *://*.agefans.tv/*
// @match        *://*.sp-flv.com/*
// @match        *://*.ejtsyc.com/*
// @match        *://*.yhdmjx.com/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @run-at       document-end
// @allFrames    true
// ==/UserScript==

(function() {
    'use strict';

    // 核心數據讀取
    const getTargetSeconds = () => Math.round(GM_getValue('skip_seconds', 90));
    const isEnabled = () => GM_getValue('auto_skip_enabled', true);
    const getTextColor = () => GM_getValue('text_color', '#000000'); // 預設文字為黑色

    const formatTime = (seconds) => {
        const m = Math.floor(seconds / 60);
        const s = seconds % 60;
        return `${m}:${s < 10 ? '0' : ''}${s}`;
    };

    // 註冊選單命令
    GM_registerMenuCommand("🎨 更改文字顏色", setTextColor);
    GM_registerMenuCommand("⚙️ 設定跳轉時間", setSkipTime);

    function setTextColor() {
        const currentCol = getTextColor();
        const newCol = prompt(`請輸入文字顏色 (名稱或代碼)\n例如: blue, red, #00ff00, orange`, currentCol);
        if (newCol) {
            GM_setValue('text_color', newCol);
            location.reload();
        }
    }

    function setSkipTime() {
        const currentSec = getTargetSeconds();
        const input = prompt(`請輸入要跳過的總秒數:`, currentSec);
        if (input !== null && !isNaN(input)) updateSkipTime(parseInt(input));
    }

    function updateSkipTime(newSeconds) {
        if (newSeconds < 0) newSeconds = 0;
        GM_setValue('skip_seconds', newSeconds);
        const textBtn = document.getElementById('skip-text-btn');
        if (textBtn) textBtn.innerText = `跳轉: ${formatTime(newSeconds)}`;
    }

    // --- UI 繪製 ---
    const createUI = () => {
        if (window.self !== window.top) return;
        if (document.getElementById('skip-config-container')) return;

        const color = getTextColor();
        const container = document.createElement('div');
        container.id = 'skip-config-container';
        const savedPos = GM_getValue('btn_pos', { right: '20px', bottom: '100px' });
        const active = isEnabled();

        container.style = `
            position: fixed;
            right: ${savedPos.right}; bottom: ${savedPos.bottom};
            left: ${savedPos.left}; top: ${savedPos.top};
            z-index: 999999;
            background: rgba(255, 255, 255, 0.9);
            padding: 8px 15px;
            border-radius: 50px;
            cursor: move;
            box-shadow: 0 4px 15px rgba(0,0,0,0.2);
            font-size: 15px;
            font-family: "Microsoft JhengHei", sans-serif;
            font-weight: 900;
            display: flex;
            align-items: center;
            border: 2px solid ${color};
            gap: 12px;
            user-select: none;
        `;

        // 內部組件全部套用 color 變數
        container.innerHTML = `
            <div id="skip-toggle-btn" style="width: 36px; height: 20px; background: ${active ? '#28a745' : '#888'}; border-radius: 12px; position: relative; cursor: pointer; border: 1px solid ${color};">
                <div style="width: 14px; height: 14px; background: white; border-radius: 50%; position: absolute; top: 2px; left: ${active ? '19px' : '2px'}; transition: left 0.3s;"></div>
            </div>
            <div id="skip-minus-btn" style="cursor: pointer; color: ${color}; border: 1px solid ${color}; padding: 1px 6px; border-radius: 5px;">-5s</div>
            <span id="skip-text-btn" style="cursor: pointer; color: ${color}; min-width: 85px; text-align: center;">跳轉: ${formatTime(getTargetSeconds())}</span>
            <div id="skip-plus-btn" style="cursor: pointer; color: ${color}; border: 1px solid ${color}; padding: 1px 6px; border-radius: 5px;">+5s</div>
            <div id="skip-color-btn" style="cursor: pointer; font-size: 18px;">🎨</div>
        `;

        document.body.appendChild(container);

        // 事件綁定
        const bind = (id, fn) => document.getElementById(id).onclick = (e) => { e.stopPropagation(); fn(e); };

        bind('skip-toggle-btn', () => {
            const newState = !isEnabled();
            GM_setValue('auto_skip_enabled', newState);
            document.getElementById('skip-toggle-btn').style.background = newState ? '#28a745' : '#888';
            document.getElementById('skip-toggle-btn').firstElementChild.style.left = newState ? '19px' : '2px';
        });

        bind('skip-minus-btn', () => updateSkipTime(getTargetSeconds() - 5));
        bind('skip-plus-btn', () => updateSkipTime(getTargetSeconds() + 5));
        bind('skip-color-btn', () => setTextColor());
        bind('skip-text-btn', (e) => { if (container.dataset.dragging !== 'true') setSkipTime(); });

        // 拖動邏輯
        let isDragging = false, offsetX, offsetY;
        container.onmousedown = function(e) {
            if (e.target.id === 'skip-config-container' || e.target.id === 'skip-text-btn') {
                isDragging = false; container.dataset.dragging = 'false';
                offsetX = e.clientX - container.getBoundingClientRect().left;
                offsetY = e.clientY - container.getBoundingClientRect().top;
                const move = (ev) => {
                    isDragging = true; container.dataset.dragging = 'true';
                    container.style.left = (ev.clientX - offsetX) + 'px';
                    container.style.top = (ev.clientY - offsetY) + 'px';
                    container.style.right = 'auto'; container.style.bottom = 'auto';
                };
                document.addEventListener('mousemove', move);
                document.onmouseup = () => {
                    document.removeEventListener('mousemove', move);
                    if (isDragging) GM_setValue('btn_pos', { left: container.style.left, top: container.style.top, right: 'auto', bottom: 'auto' });
                    document.onmouseup = null;
                };
            }
        };
    };

    // --- 跳轉邏輯 ---
    let jumpSuccess = false;
    function forceSeek() {
        if (!isEnabled()) return;
        const video = document.querySelector('video');
        const SKIP_SEC = getTargetSeconds();
        if (video && !jumpSuccess) {
            if (video.currentTime < SKIP_SEC && video.duration > SKIP_SEC) {
                video.currentTime = SKIP_SEC;
                if (video.paused) video.play().catch(() => {});
            }
            jumpSuccess = true;
        }
    }

    setTimeout(createUI, 1500);
    setInterval(forceSeek, 1000);
    document.addEventListener('click', forceSeek);
})();