Skip to content

Instantly share code, notes, and snippets.

@nimatrueway
Created November 17, 2022 04:09
Show Gist options
  • Save nimatrueway/73f37989e38a34b018106cd1b98e402f to your computer and use it in GitHub Desktop.
Save nimatrueway/73f37989e38a34b018106cd1b98e402f to your computer and use it in GitHub Desktop.

Revisions

  1. nimatrueway created this gist Nov 17, 2022.
    107 changes: 107 additions & 0 deletions add-instagram-video-progressbar.user.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,107 @@
    // ==UserScript==
    // @name Add Instagram Video Progressbar
    // @namespace https://greasyfork.org/en/users/85671-jcunews
    // @version 1.0.4
    // @license GNU AGPLv3
    // @author jcunews
    // @description Add a video playback progressbar at bottom of an Instagram video. This script also disables video looping. Both are configurable.
    // @match *://www.instagram.com/*
    // @exclude *://www.instagram.com/stories/*
    // @grant none
    // @run-at document-start
    // ==/UserScript==

    (function(vael, ie, ee, be, wm) {

    //===== CONFIGURATION BEGIN =====

    var ProgressbarHeight = 3; //in pixels. set to zero to hide
    var ProgressbarColor = "#fff"; //e.g. "#fff" or "#e0e0e0" or "cyan"
    var ProgressbarElapsedColor = "#f00";

    var disableVideoLoop = true;

    //===== CONFIGURATION END =====

    function findTopContainer(elem, sizeDiff) {
    var parent = elem
    while (parent.parentNode &&
    (parent.parentNode.clientWidth < (elem.clientWidth + sizeDiff)) &&
    (parent.parentNode.clientHeight < (elem.clientHeight + sizeDiff))) {
    parent = parent.parentNode
    }
    return parent
    }

    function moveMuteUp(containerElem) {
    findTopContainer(containerElem.querySelector('svg'), 40).style.marginBottom = '20px';
    }

    function addSeek(videoElem, bar) {
    const containerElem = findTopContainer(videoElem, 20)
    function act(e) {
    const fractionX = e.offsetX / containerElem.clientWidth
    const fractionY = e.offsetY / containerElem.clientHeight
    if (e.altKey == true || fractionY > 0.97) {
    e.stopPropagation();
    bar.style.width = e.offsetX + "px";
    videoElem.currentTime = fractionX * videoElem.duration
    }
    }

    containerElem.addEventListener('click', (e) => act(e))
    containerElem.addEventListener('mousedown', (e) => act(e))
    containerElem.addEventListener('mousemove', (e) => (e.buttons == 1) && act(e))
    moveMuteUp(containerElem)
    }

    function addBar(a, b) {
    if (disableVideoLoop) ie = this.parentNode.parentNode.parentNode.parentNode.lastElementChild;
    a = "aivp" + (new Date()).getTime();
    b = a + "bar";
    ee = document.createElement("DIV");
    ee.id = a;
    ee.innerHTML = `<style>
    #${a} { position: absolute; opacity: .66; left: 0; right: 0; bottom: 0; height: ${ProgressbarHeight}px; background: ${ProgressbarColor} }
    #${b} { width: 0; height: 100%; background: ${ProgressbarElapsedColor} }
    </style><div id="${b}"></div>`;
    wm.set(this, be = ee.lastElementChild);
    this.parentNode.insertBefore(ee, this);
    addSeek(this, this.parentNode.querySelector("#"+b));
    this.removeEventListener("canplay", addBar);
    }
    wm = new WeakMap;
    vael = HTMLVideoElement.prototype.addEventListener;
    HTMLVideoElement.prototype.addEventListener = function() {
    var res;
    ((ve, tm, be) => {
    function updBar() {
    be.style.width = Math.ceil((ve.currentTime / ve.duration) * ee.offsetWidth) + "px";
    }
    function startTimer(ev) {
    if (!be) be = wm.get(this);
    if (disableVideoLoop) ve.loop = false;
    if (!tm) tm = setInterval(updBar, 100);
    }
    function stopTimer(ev) {
    if (ev.type === "ended") {
    be.style.width = "100%";
    if (disableVideoLoop) ie.click();
    }
    clearInterval(tm);
    tm = 0;
    }
    res = vael.apply(ve, arguments);
    if (!ve.attributes["aivp_done"]) {
    ve.setAttribute("aivp_done", "1");
    vael.call(ve, "canplay", addBar);
    vael.call(ve, "play", startTimer);
    vael.call(ve, "playing", startTimer);
    vael.call(ve, "waiting", stopTimer);
    vael.call(ve, "pause", stopTimer);
    vael.call(ve, "ended", stopTimer);
    }
    })(this);
    return res;
    };
    })();