kociolekt / MaxTVGo better video list

// ==UserScript==
// @name         MaxTVGo better video list
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Show viewed list of videos on maxtvgo.com
// @author       kociolekt
// @match        https://maxtvgo.com/video.php*
// @grant        none
// @require      https://player.vimeo.com/api/player.js
// @license MIT
// @copyright 2019, kociolekt (https://openuserjs.org//users/kociolekt)
// ==/UserScript==

/* globals $, Vimeo */

(function() {
    'use strict';

    // jQuery unveil
    !function(t){t.fn.unveil=function(i,e){var n,r=t(window),o=i||0,u=window.devicePixelRatio>1?"data-src-retina":"data-src",s=this;function l(){var i=s.filter(function(){var i=t(this);if(!i.is(":hidden")){var e=r.scrollTop(),n=e+r.height(),u=i.offset().top;return u+i.height()>=e-o&&u<=n+o}});n=i.trigger("unveil"),s=s.not(n)}return this.one("unveil",function(){var t=this.getAttribute(u);(t=t||this.getAttribute("data-src"))&&(this.setAttribute("src",t),"function"==typeof e&&e.call(this))}),r.on("scroll.unveil resize.unveil lookup.unveil",l),l(),this}}(window.jQuery||window.Zepto);
    // throttle
    function throttle(t,n){var e,o;return function(){var a=this,i=arguments;o?(clearTimeout(e),e=setTimeout(function(){Date.now()-o>=n&&(t.apply(a,i),o=Date.now())},n-(Date.now()-o))):(t.apply(a,i),o=Date.now())}}

    const defaults = {
        videosUrl: 'https://maxtvgo.com/api/videos.php?action=find'
    };

    class MaxTVGoVideoList {
        constructor(options) {
            this.settings = Object.assign({}, defaults, options);
            this.videos = [];

            this.init();
        }

        async init() {
            await this.initVideos();
            this.initDOM();
            this.initWatchEvents();
        }

        async initVideos() {
            let newList = await this.requestVideoList();

            this.loadVideos();

            for (let i = 0, nLen = newList.length; i < nLen; i++) {
                let newVideo = newList[i];
                let currentVideo = this.findVideo(newVideo.id);

                if (currentVideo) {
                    Object.assign(currentVideo, newVideo);
                } else {
                    this.videos.push(newVideo);
                }
            }

            this.videos = this.videos.sort(MaxTVGoVideoList.compareVideos);

            this.saveVideos();
        }

        requestVideoList() {
            return new Promise((resolve, reject) => {
                let retval = [];

                $.get(this.settings.videosUrl, (response) => {
                    let lists = response.data;

                    for (let i = 0, lLen = lists.length; i < lLen; i++) {
                        let list = lists[i];
                        let category = list.name;

                        for (let j = 0, vLen = list.videos.length; j < vLen; j++) {
                            let video = list.videos[j];
                            video.category = category;
                            retval.push(video);
                        }
                    }

                    retval = retval.sort(MaxTVGoVideoList.compareVideos);

                    resolve(retval);
                });
            });
        }

        findVideo(videoId) {
            return this.videos.find(video => video.id === videoId);
        }

        findVideoByVimeoVideoId(vimeoVideoId) {
            return this.videos.find(video => video.vimeoVideoId === vimeoVideoId);
        }

        initDOM() {
           let videoListDOM = this.videos.map((video) => {
               let titleColor = '#6895E3';
               let viewed = '';

               if(video.percent) {
                   viewed = `<br/>Obejrzany (${video.percent}%)`;
                   titleColor = '#ccc';
               }

               return `
                 <div style="position: relative; border-radius: 7px;background-color: rgba(0, 0, 0, 0.75);padding: 10px;float: right;margin: 10px 11px 0 0px !important;width: 95%;height: 100%;">
                    <div class="row">
                       <div class="col-xl-3 col-lg-3 col-md-3 col-sm-3 col-xs-3">
                          <img data-src="https://i.vimeocdn.com/video/${video.vimeoPosterId}.jpg?mw=300" style="max-width: 100%;"/>
                       </div>
                       <div class="col-xl-9 col-lg-9 col-md-9 col-sm-9 col-xs-9" style="font-family: 'Open Sans', sans-serif;font-size: 14px; color: ${titleColor}; font-weight: 400;">
                          [${video.category}] ${video.title} ${viewed}
                       </div>
                    </div>
                    <a href="https://maxtvgo.com/video.php?film=${video.code}" style="position: absolute; left: 0; top: 0; bottom: 0; right: 0;">&nbsp;</a>
                 </div>
               `;
           });


           $('#counter-div').after(`
             <div class="row">
               <div class="col-xl-12 col-lg-12 col-md-12 col-sm-12 col-xs-12">
               ${videoListDOM};
               </div>
             </div>
           `);

           $('img').unveil();
        }

        initWatchEvents() {
            let vimeoPlayer = document.getElementById('vimeoPlayer');

            if(vimeoPlayer) {

                let player = new Vimeo.Player(vimeoPlayer);

                player.getVideoId().then((id) => {
                    let video = this.findVideoByVimeoVideoId(id);

                    if (video) {
                        player.on('timeupdate', throttle((event) => {
                            video.percent = Math.round(event.percent * 100);
                            if(video.percent >= 1) {
                                this.saveVideos();
                            }
                        }, 2000));

                        player.on('ended', (event) => {
                            video.percent = 1;
                            this.saveVideos();
                        });
                    }
                }).catch(function(error) {
                    console.error('cannot get video id :(');
                    console.error(error);
                });
            }
        }

        loadVideos() {
            if(window.localStorage.getItem('videos')) {
                this.videos = JSON.parse(window.localStorage.getItem('videos'));
            } else {
                this.videos = [];
            }
        }

        saveVideos() {
            window.localStorage.setItem('videos', JSON.stringify(this.videos));
        }

        static compareVideos(a, b) {
            return b.id - a.id;
        }
    }

    // Start
    $(document).ready(() => {
        new MaxTVGoVideoList();
    });
})();