NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name miyoushe video mod // @namespace https://www.miyoushe.com/ // @version 20250330 // @description 米游社视频快捷键mod // @author Hentai // @match https://www.miyoushe.com/* // @icon https://img-static.mihoyo.com/favicon.ico // @grant none // @license MIT // ==/UserScript== let init = false; let initTimer = 0; let videoLs = []; function load() { initTimer = setInterval(() => { const ls = document.querySelectorAll('.mhy-layout__main video'); if (!ls.length) return; init = true; videoLs = ls; // console.info(videoLs); clearInterval(initTimer); initTimer = 0; }, 100); } load(); document.addEventListener("keydown", keymap); document.addEventListener("keyup", keymap_up); window.navigation.addEventListener("navigate", (event) => { if (initTimer) return; init = false; load(); }); function pickVideoDOM() { // 如果有多个的话就要考虑选择当前的video了,可以根据窗口位置什么的判断 // 但是按照道理讲只有一个video,所以现在直接返回0 // console.info(videoLs[0]); return videoLs[0]; } function togglePlay() { const dom = pickVideoDOM(); if (!dom) return; if (dom.paused) { dom.play(); } else { dom.pause(); } } function wheelListener(e) { const dom = pickVideoDOM(); if (!dom) return; let volume = dom.volume * 100 + (e.deltaY < 0 ? 5 : -5); if (volume < 0) volume = 0; if (volume > 100) volume = 100; dom.volume = volume / 100; } let keyTimer = new Map(); function keymap(e) { //console.info(mayTyping(e.target)); if (mayTyping(e.target)) return; // console.info(e); const dom = pickVideoDOM(); if (!dom) return; switch (e.key) { case " ": e.preventDefault(); e.stopPropagation(); togglePlay(); break; case "ArrowUp": e.preventDefault(); e.stopPropagation(); wheelListener({deltaY: -1}); break; case "ArrowDown": e.preventDefault(); e.stopPropagation(); wheelListener({deltaY: 1}); break; case "ArrowLeft": case "ArrowRight": e.preventDefault(); e.stopPropagation(); // dom.playbackRate = e.ctrlKey ? 5 : 2; // if (!keyTimer.get(e.key)) keyTimer.set(e.key, new Date().valueOf()); break; case "Enter": e.preventDefault(); e.stopPropagation(); if (e.ctrlKey) dom.requestFullscreen(); else { const ifFixed = document.querySelector('#videoPlayer').style.position === 'fixed'; if (ifFixed) { document.querySelector('#videoPlayer').style.position = null; document.querySelector('#videoPlayer').style.zIndex = null; document.querySelector('#videoPlayer').style.left = null; document.querySelector('#videoPlayer').style.top = null; document.querySelector('#videoPlayer').style.width = null; document.querySelector('#videoPlayer').style.height = null; } else { document.querySelector('#videoPlayer').style.position = 'fixed'; document.querySelector('#videoPlayer').style.zIndex = 999; document.querySelector('#videoPlayer').style.left = 0; document.querySelector('#videoPlayer').style.top = 0; document.querySelector('#videoPlayer').style.width = '100vw'; document.querySelector('#videoPlayer').style.height = '100vh'; } } break; } } function keymap_up(e) { //console.info(mayTyping(e.target)); if (mayTyping(e.target)) return; let now = new Date().valueOf(); // console.info(e); const dom = pickVideoDOM(); if (!dom) return; switch (e.key) { case "ArrowLeft": case "ArrowRight": e.preventDefault(); e.stopPropagation(); // dom.playbackRate = 1; // if (now - keyTimer.get(e.key) < 500) { dom.currentTime += e.key === "ArrowLeft" ? -5 : 5; } // keyTimer.delete(e.key); break; } } function mayTyping(target) { if (!target) return false; let dom = target; while (true) { if (dom.tagName === 'BODY') return false; else if (dom.tagName === 'HTML') return false; else if (dom.tagName === 'TEXTAREA') return true; else if (dom.tagName === 'INPUT') { switch (dom.type) { case 'input': case 'date': case 'datetime': case 'datetime-local': case 'file': case 'number': case 'password': // case 'radio': case 'search': case 'text': case 'time': case 'tel': case 'url': return true; break; } } else if (dom.contentEditable && dom.contentEditable.toLowerCase() === 'true') return true; else if (!dom.parentElement) return false; dom = dom.parentElement; } return false; }