// ==UserScript== // @name plex.tv UI fixes and features // @namespace http://tampermonkey.net/ // @updateURL https://gist.githubusercontent.com/mroosen/8ef2e69c1d753c4d4ed802572f857886/raw/ // @downloadURL https://gist.githubusercontent.com/mroosen/8ef2e69c1d753c4d4ed802572f857886/raw/ // @version 0.91 // @description Bigger volume bar, close button to top right, set playback speed, frame skip with SHIFT-, and SHIFT-. // @author @PostHum4n // @match https://app.plex.tv/* // @grant none // @require http://code.jquery.com/jquery-3.2.1.slim.min.js // ==/UserScript== (function() { 'use strict'; let divSpeed, divFrameForward; function insertAfter(newNode, referenceNode) { referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling); } // FPS fixed to 24fps; could make options for selecting framerate, can't read it from the VIDEO object :( let fps = 23.976; let frameByFrameSpeed = 100; let frameByFrameLast = Date.now(); document.addEventListener("keydown", function(e){ if (e.keyCode === 190 && e.shiftKey === true){ frameByFrame(1); } if (e.keyCode === 188 && e.shiftKey === true){ frameByFrame(-1); } }); function frameByFrame(d){ if (Date.now() - frameByFrameLast < frameByFrameSpeed){ return false; } frameByFrameLast = Date.now(); var video2 = document.getElementsByTagName("video")[0]; video2.pause(); video2.currentTime = video2.currentTime + (1/fps) * d; } (function initSpeedButtons(){ divFrameForward = document.createElement("div"); divFrameForward.innerHTML = ">>>"; divFrameForward.style.color = "white"; divFrameForward.style.border = "0px solid red"; divFrameForward.style.cursor = "pointer"; divFrameForward.style.marginLeft = "10px"; divFrameForward.style.zIndex = "100"; divFrameForward.addEventListener("mousedown", function(e){ //frameForward(e) }); //divFrameForward.style.cssFloat ="right"; //divFrameForward.style.margin = "13px 11px 0px 10px"; divSpeed = document.createElement("div"); divSpeed.innerHTML = ""; divSpeed.style.color = "white"; divSpeed.style.border = "0px solid red"; divSpeed.style.cssFloat ="right"; divSpeed.style.margin = "13px 11px 0px 10px"; [2, 1.5, 1.25, 1, 0.75, 0.5, 0.25, 0.1].forEach( function(v, k){ let newSpeedBtn = document.createElement("div"); newSpeedBtn.innerHTML = v; newSpeedBtn.style.color = "#CCC"; newSpeedBtn.style.border = "0px solid red"; newSpeedBtn.style.cssFloat ="right"; newSpeedBtn.style.fontSize = "13px"; newSpeedBtn.style.minWidth = "35px"; newSpeedBtn.style.textAlign = "center"; newSpeedBtn.style.marginLeft = "0px" ; newSpeedBtn.style.marginRight = "0px"; newSpeedBtn.style.marginTop = "0px"; newSpeedBtn.style.marginBottom = "0px"; newSpeedBtn.style.margin = "0px"; newSpeedBtn.style.cursor = "pointer"; newSpeedBtn.onclick = function(e){ e.preventDefault(); document.getElementsByTagName("video")[0].playbackRate = v; localStorage.setItem("plexVideoSpeed", v); }; $(newSpeedBtn).hover(function(){ $(this).css("background-color", "rgba(255,255,255,0.3)"); $(this).css("color", "white"); }, function(){ $(this).css("background-color", ""); $(this).css("color", "#CCC"); }); newSpeedBtn.style.margin ="0px 5px 5px 5px"; divSpeed.appendChild(newSpeedBtn); }); })(); let lastBtnExpandPlayer, lastTopControls; function initVideoControlsFix(){ // Find some common HTML elements let btnFullscreen = document.querySelectorAll('[aria-label="Enter Fullscreen"]')[0]; let btnFullscreenExit = document.querySelectorAll('[aria-label="Exit Fullscreen"]')[0]; let btnClosePlayer = document.querySelectorAll('[aria-label="Close Player"]')[0]; let bottomControls = document.getElementsByClassName("AudioVideoPlayerControls-buttonGroupRight-17650")[0]; let topControls = $("div[class*='FullPlayerTopControls-topControls']")[0]; let btnExpandPlayer = document.querySelectorAll('[aria-label="Expand Player"]')[0]; let bottomControlsCenter = $("div[class*='AudioVideoPlayerControls-buttonGroupCenter-Vok98']")[0]; let btnPlayBig = $("div[class*='PlayPauseOverlay-playCircle-3ydPY']")[0]; if (btnPlayBig){ btnPlayBig.style.opacity = "0.1"; } if (bottomControlsCenter){ //bottomControlsCenter.append(divFrameForward) } let video = document.getElementsByTagName("video")[0]; // Set video speed let getSpeed = localStorage.getItem("plexVideoSpeed"); if (getSpeed && video){ video.playbackRate = getSpeed; } let volumeSlider = document.getElementsByClassName("VolumeSlider-fill-3XkYy")[0]; let volumeSliderTrack = document.getElementsByClassName("VolumeSlider-track-2WJDz")[0]; if (volumeSlider){ volumeSlider.style.height = "40px"; volumeSliderTrack.style.height = "40px"; } if (btnExpandPlayer != lastBtnExpandPlayer || topControls != lastTopControls){ if (btnExpandPlayer){ btnClosePlayer.style.position = "absolute"; btnClosePlayer.style.left = "65px"; btnClosePlayer.style.top = "-10px"; btnClosePlayer.style.zIndex = "100"; } let volumeSlider = $("div[class*='VolumeSlider-slider-1QXdT ']")[0]; if (volumeSlider){ volumeSlider.style.marginRight = "10px"; } /* let seekBarTrack = $("div[class*='SeekBar-seekBarTrack-3Gu5R']")[0]; seekBarTrack.style.height = "8px"; seekBarTrack.style.marginTop = "0px"; seekBarTrack.pseudoStyle("before","height","10px"); //let seekBarTrack2 = $("div[class*='SeekBar-seekBarTrack-3Gu5R']")[0] //seekBarTrack2.style.height = "10px" //seekBarTrack.style.marginTop = "0px" let seekBar = $("div[class*='SeekBar-seekBarFill-1Lcu0']")[0]; seekBar.style.height = "10px"; seekBar.style.opacity = "1"; seekBar.style.background = "linear-gradient(to top, rgba(255,155,67,0.65) 0%,rgba(255,155,67,0) 50%)"; let seekBarAnchor = $("div[class*='Slider-thumb-2QGiU']")[0]; if (seekBarAnchor){ seekBarAnchor.style.border = "100px solid red"; seekBarAnchor.style.boxShadow = "5px 5px 20px black"; } else { console.log("seekBarAnchor?????"); } */ if (bottomControls !== undefined){ let btnAuxSettings = document.getElementsByClassName("AudioVideoPlayerControls-auxButtons-2YhIh")[0]; if (btnAuxSettings !== undefined){ btnAuxSettings.append(divSpeed); } } if (btnClosePlayer !== undefined && topControls !== undefined){ topControls.appendChild(btnClosePlayer); } } lastBtnExpandPlayer = btnExpandPlayer; lastTopControls = topControls; } let hasFullVideo = false; setInterval(function(){ let video = document.getElementsByTagName("video")[0]; let fullControls = document.getElementsByClassName("AudioVideoFullPlayer-fullPlayer-3bJyO")[0]; let bottomControls = document.getElementsByClassName("AudioVideoPlayerControls-buttonGroupRight-17650")[0]; if (bottomControls){ initVideoControlsFix(); hasFullVideo = true; } else { hasFullVideo = false; try { divSpeed.parentNode.remove(); } catch(e){} } }, 500); var UID = { _current: 0, getNew: function(){ this._current++; return this._current; } }; HTMLElement.prototype.pseudoStyle = function(element,prop,value){ var _this = this; var _sheetId = "pseudoStyles"; var _head = document.head || document.getElementsByTagName('head')[0]; var _sheet = document.getElementById(_sheetId) || document.createElement('style'); _sheet.id = _sheetId; var className = "pseudoStyle" + UID.getNew(); _this.className += " "+className; _sheet.innerHTML += " ."+className+":"+element+"{"+prop+":"+value+"}"; _head.appendChild(_sheet); return this; }; })();