Greasy Fork is available in English.

Kick.com Timestamp input

timestamp input on Kick.com

// ==UserScript==
// @name         Kick.com Timestamp input 
// @namespace    http://tampermonkey.net/
// @version      0.9
// @description  timestamp input on Kick.com
// @match        https://kick.com/*/videos/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    const styles = `
        #timestamp-container {
            display: flex;
            align-items: center;
            position: absolute;
            bottom: 5.5px;
            right: 240px;
            z-index: 9999;
        }
        #timestamp-toggle {
            background: none;
            border: none;
            width: 32px;
            height: 32px;
            padding: 0;
            cursor: pointer;
            opacity: 0;
            transition: opacity 0.3s ease;
            position: relative;
        }
        #timestamp-toggle svg {
            width: 90%;
            height: 90%;
            fill: white;
        }
        #timestamp-tooltip {
            position: absolute;
            bottom: calc(85% + 10px);
            left: 45%;
            transform: translateX(-50%);
            background-color: white;
            color: black;
            padding: 6px 10px;
            border-radius: 4px;
            font-size: 14px;
            font-weight: normal;
            white-space: nowrap;
            opacity: 0;
            pointer-events: none;
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
        }
        #timestamp-tooltip::after {
            content: '';
            position: absolute;
            top: 100%;
            left: 50%;
            margin-left: -5px;
            border-width: 5px;
            border-style: solid;
            border-color: white transparent transparent transparent;
        }
        #timestamp-toggle:hover #timestamp-tooltip {
            opacity: 1;
        }
        #timestamp-inputs {
            display: none;
            align-items: center;
            background-color: rgba(28, 28, 28, 0.9);
            border-radius: 4px;
            padding: 5px;
            position: absolute;
            bottom: 40px;
            right: 0;
        }
        #timestamp-inputs.visible {
            display: flex;
        }
        .timestamp-input {
            width: 30px;
            margin-right: 3px;
            background-color: rgba(255, 255, 255, 0.1);
            border: 1px solid rgba(255, 255, 255, 0.2);
            border-radius: 3px;
            color: white;
            padding: 3px;
            text-align: center;
        }
        #timestamp-go {
            background-color: rgba(255, 255, 255, 0.2);
            color: white;
            border: none;
            border-radius: 3px;
            padding: 3px 6px;
            cursor: pointer;
        }
        #timestamp-go:hover {
            background-color: rgba(255, 255, 255, 0.3);
        }
    `;

    function addTimestampInput() {
        const videoPlayer = document.querySelector('video');
        if (!videoPlayer) return;

        const styleElement = document.createElement('style');
        styleElement.textContent = styles;
        document.head.appendChild(styleElement);

        const container = document.createElement('div');
        container.innerHTML = `
            <div id="timestamp-container">
                <button id="timestamp-toggle">
                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                        <path d="M0 0h24v24H0z" fill="none"/>
                        <path d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z"/>
                    </svg>
                    <span id="timestamp-tooltip">Time Jump</span>
                </button>
                <div id="timestamp-inputs">
                    <input type="text" id="days" class="timestamp-input" placeholder="DD">
                    <input type="text" id="hours" class="timestamp-input" placeholder="HH">
                    <input type="text" id="minutes" class="timestamp-input" placeholder="MM">
                    <input type="text" id="seconds" class="timestamp-input" placeholder="SS">
                    <button id="timestamp-go">Go</button>
                </div>
            </div>
        `;
        const videoContainer = videoPlayer.closest('.relative.aspect-video.w-full');
        if (videoContainer) {
            videoContainer.appendChild(container.firstElementChild);

            const timestampContainer = document.getElementById('timestamp-container');
            const timestampToggle = document.getElementById('timestamp-toggle');
            const timestampInputs = document.getElementById('timestamp-inputs');
            const timestampGo = document.getElementById('timestamp-go');

            timestampToggle.addEventListener('click', (e) => {
                e.stopPropagation();
                timestampInputs.classList.toggle('visible');
            });

            timestampGo.addEventListener('click', (e) => {
                e.stopPropagation();
                const days = parseInt(document.getElementById('days').value) || 0;
                const hours = parseInt(document.getElementById('hours').value) || 0;
                const minutes = parseInt(document.getElementById('minutes').value) || 0;
                const seconds = parseInt(document.getElementById('seconds').value) || 0;

                const totalSeconds = (days * 24 * 3600) + (hours * 3600) + (minutes * 60) + seconds;
                if (totalSeconds >= 0) {
                    videoPlayer.currentTime = totalSeconds;
                    timestampInputs.classList.remove('visible');
                } else {
                    alert('Invalid timestamp. Please enter valid numbers.');
                }
            });

            // Hide inputs when clicking outside
            document.addEventListener('click', (e) => {
                if (!timestampContainer.contains(e.target)) {
                    timestampInputs.classList.remove('visible');
                }
            });

            // Show/hide timestamp toggle with other controls
            videoContainer.addEventListener('mouseover', () => {
                timestampToggle.style.opacity = '1';
            });
            videoContainer.addEventListener('mouseout', (e) => {
                if (!timestampContainer.contains(e.relatedTarget) && !timestampInputs.classList.contains('visible')) {
                    timestampToggle.style.opacity = '0';
                }
            });
        }
    }

    // Wait for the video player to be loaded
    const observer = new MutationObserver((mutations, obs) => {
        const videoPlayer = document.querySelector('video');
        if (videoPlayer) {
            addTimestampInput();
            obs.disconnect();
        }
    });

    observer.observe(document.body, {
        childList: true,
        subtree: true
    });
})();