ykh5p

改善优酷官方html5播放器播放体验

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

'use strict';

var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

// ==UserScript==
// @name         ykh5p
// @namespace    https://github.com/gooyie/ykh5p
// @homepageURL  https://github.com/gooyie/ykh5p
// @supportURL   https://github.com/gooyie/ykh5p/issues
// @version      0.12.5
// @description  改善优酷官方html5播放器播放体验
// @author       gooyie
// @license      MIT License
//
// @include      *://v.youku.com/*
// @include      *://player.youku.com/embed/*
// @grant        GM_info
// @grant        GM_addStyle
// @grant        unsafeWindow
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict';

    /* eslint-disable no-console */

    var Logger = function () {
        function Logger() {
            _classCallCheck(this, Logger);
        }

        _createClass(Logger, null, [{
            key: 'log',
            value: function log() {
                var _console;

                for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
                    args[_key] = arguments[_key];
                }

                (_console = console).log.apply(_console, ['%c' + this.tag + '%c' + args.shift(), 'color: #fff; background: #2FB3FF', ''].concat(args));
            }
        }, {
            key: 'info',
            value: function info() {
                var _console2;

                for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
                    args[_key2] = arguments[_key2];
                }

                (_console2 = console).info.apply(_console2, [this.tag + args.shift()].concat(args));
            }
        }, {
            key: 'debug',
            value: function debug() {
                var _console3;

                for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
                    args[_key3] = arguments[_key3];
                }

                (_console3 = console).debug.apply(_console3, [this.tag + args.shift()].concat(args));
            }
        }, {
            key: 'warn',
            value: function warn() {
                var _console4;

                for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
                    args[_key4] = arguments[_key4];
                }

                (_console4 = console).warn.apply(_console4, [this.tag + args.shift()].concat(args));
            }
        }, {
            key: 'error',
            value: function error() {
                var _console5;

                for (var _len5 = arguments.length, args = Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
                    args[_key5] = arguments[_key5];
                }

                (_console5 = console).error.apply(_console5, [this.tag + args.shift()].concat(args));
            }
        }, {
            key: 'tag',
            get: function get() {
                return '[' + GM_info.script.name + ']';
            }
        }]);

        return Logger;
    }();
    /* eslint-enable no-console */

    var Hooker = function () {
        function Hooker() {
            _classCallCheck(this, Hooker);
        }

        _createClass(Hooker, null, [{
            key: '_hookCall',
            value: function _hookCall(cb) {
                var call = Function.prototype.call;
                Function.prototype.call = function () {
                    for (var _len6 = arguments.length, args = Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {
                        args[_key6] = arguments[_key6];
                    }

                    var ret = call.apply(this, args);
                    try {
                        if (args && cb(args)) {
                            Function.prototype.call = call;
                            cb = function cb() {};
                            Logger.log('restored call');
                        }
                    } catch (err) {
                        Logger.error(err.stack);
                    }
                    return ret;
                };
                this._hookCall = null;
            }
        }, {
            key: '_isEsModule',
            value: function _isEsModule(obj) {
                return obj.__esModule;
            }
        }, {
            key: '_isFuction',
            value: function _isFuction(arg) {
                return 'function' === typeof arg;
            }
        }, {
            key: '_isModuleCall',
            value: function _isModuleCall(args) {
                // module.exports, module, module.exports, require
                return args.length === 4 && args[1] && Object.getPrototypeOf(args[1]) === Object.prototype && args[1].hasOwnProperty('exports');
            }
        }, {
            key: '_hookModuleCall',
            value: function _hookModuleCall(cb, pred) {
                var _this = this;

                var callbacksMap = new Map([[pred, [cb]]]);
                this._hookCall(function (args) {
                    if (!_this._isModuleCall(args)) return;
                    var exports = args[1].exports;
                    var _iteratorNormalCompletion = true;
                    var _didIteratorError = false;
                    var _iteratorError = undefined;

                    try {
                        for (var _iterator = callbacksMap[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
                            var _step$value = _slicedToArray(_step.value, 2),
                                _pred = _step$value[0],
                                callbacks = _step$value[1];

                            if (!_pred.apply(_this, [exports])) continue;
                            callbacks.forEach(function (cb) {
                                return cb(exports, args);
                            });
                            callbacksMap.delete(_pred);
                            !callbacksMap.size && (_this._hookModuleCall = null);
                            break;
                        }
                    } catch (err) {
                        _didIteratorError = true;
                        _iteratorError = err;
                    } finally {
                        try {
                            if (!_iteratorNormalCompletion && _iterator.return) {
                                _iterator.return();
                            }
                        } finally {
                            if (_didIteratorError) {
                                throw _iteratorError;
                            }
                        }
                    }

                    return !callbacksMap.size;
                });

                this._hookModuleCall = function (cb, pred) {
                    if (callbacksMap.has(pred)) {
                        callbacksMap.get(pred).push(cb);
                    } else {
                        callbacksMap.set(pred, [cb]);
                    }
                };
            }
        }, {
            key: '_isUpsModuleCall',
            value: function _isUpsModuleCall(exports) {
                return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('getServieceUrl') && /\.id\s*=\s*"ups"/.test(exports.default.toString());
            }
        }, {
            key: 'hookUps',
            value: function hookUps(cb) {
                this._hookModuleCall(cb, this._isUpsModuleCall);
            }
        }, {
            key: 'hookUpsOnComplete',
            value: function hookUpsOnComplete(cb) {
                this.hookUps(function (exports) {
                    var onComplete = exports.default.prototype.onComplete;
                    exports.default.prototype.onComplete = function (res) {
                        cb(res);
                        onComplete.apply(this, [res]);
                    };
                });
            }
        }, {
            key: '_isLogoModuleCall',
            value: function _isLogoModuleCall(exports) {
                return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('reset') && /logo\.style\.display/.test(exports.default.prototype.reset.toString());
            }
        }, {
            key: 'hookLogo',
            value: function hookLogo(cb) {
                this._hookModuleCall(cb, this._isLogoModuleCall);
            }
        }, {
            key: '_isQualityIconComponentModuleCall',
            value: function _isQualityIconComponentModuleCall(exports) {
                return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('renderQuality');
            }
        }, {
            key: 'hookQualityIcon',
            value: function hookQualityIcon(cb) {
                this._hookModuleCall(cb, this._isQualityIconComponentModuleCall);
            }
        }, {
            key: 'hookRenderQuality',
            value: function hookRenderQuality(cb) {
                Hooker.hookQualityIcon(function (exports) {
                    var renderQuality = exports.default.prototype.renderQuality;
                    exports.default.prototype.renderQuality = function (langCode) {
                        cb(langCode, this);
                        renderQuality.apply(this, [langCode]);
                    };
                });
            }
        }, {
            key: 'hookSetQuality',
            value: function hookSetQuality(cb) {
                Hooker.hookQualityIcon(function (exports) {
                    var setQuality = exports.default.prototype.setQuality;
                    exports.default.prototype.setQuality = function () {
                        for (var _len7 = arguments.length, args = Array(_len7), _key7 = 0; _key7 < _len7; _key7++) {
                            args[_key7] = arguments[_key7];
                        }

                        // quality, innerText
                        cb(args, this);
                        setQuality.apply(this, args);
                    };
                });
            }
        }, {
            key: '_isManageModuleCall',
            value: function _isManageModuleCall(exports) {
                return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('_resetPlayer');
            }
        }, {
            key: 'hookManage',
            value: function hookManage(cb) {
                this._hookModuleCall(cb, this._isManageModuleCall);
            }
        }, {
            key: 'hookInitPlayerEvent',
            value: function hookInitPlayerEvent(cb) {
                Hooker.hookManage(function (exports) {
                    var _initPlayerEvent = exports.default.prototype._initPlayerEvent;
                    exports.default.prototype._initPlayerEvent = function () {
                        cb(this);
                        _initPlayerEvent.apply(this);
                    };
                });
            }
        }, {
            key: 'hookResetPlayerAfter',
            value: function hookResetPlayerAfter(cb) {
                Hooker.hookManage(function (exports) {
                    var _resetPlayer = exports.default.prototype._resetPlayer;
                    exports.default.prototype._resetPlayer = function () {
                        try {
                            _resetPlayer.apply(this);
                        } catch (err) {
                            // 忽略 ykSDK.destroyAd 异常
                            if (!err.stack.includes('destroyAd')) throw err;
                        }
                        cb(this);
                    };
                });
            }
        }, {
            key: '_isKeyShortcutsModuleCall',
            value: function _isKeyShortcutsModuleCall(exports) {
                return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('registerEvents');
            }
        }, {
            key: 'hookKeyShortcuts',
            value: function hookKeyShortcuts(cb) {
                this._hookModuleCall(cb, this._isKeyShortcutsModuleCall);
            }
        }, {
            key: '_isTipsModuleCall',
            value: function _isTipsModuleCall(exports) {
                return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('showHintTips');
            }
        }, {
            key: 'hookTips',
            value: function hookTips(cb) {
                this._hookModuleCall(cb, this._isTipsModuleCall);
            }
        }, {
            key: '_isAdServiceModuleCall',
            value: function _isAdServiceModuleCall(exports) {
                return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('requestAdData');
            }
        }, {
            key: 'hookAdService',
            value: function hookAdService(cb) {
                this._hookModuleCall(cb, this._isAdServiceModuleCall);
            }
        }, {
            key: '_isTopAreaModuleCall',
            value: function _isTopAreaModuleCall(exports) {
                return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('_timerHandler');
            }
        }, {
            key: 'hookTopArea',
            value: function hookTopArea(cb) {
                this._hookModuleCall(cb, this._isTopAreaModuleCall);
            }
        }, {
            key: 'hookTopAreaAddEvent',
            value: function hookTopAreaAddEvent(cb) {
                Hooker.hookTopArea(function (exports) {
                    var _addEvent = exports.default.prototype._addEvent;
                    exports.default.prototype._addEvent = function () {
                        cb(this);
                        _addEvent.apply(this);
                    };
                });
            }
        }, {
            key: '_isPreviewLayerModuleCall',
            value: function _isPreviewLayerModuleCall(exports) {
                return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('setPreviewShow');
            }
        }, {
            key: 'hookPreviewLayer',
            value: function hookPreviewLayer(cb) {
                this._hookModuleCall(cb, this._isPreviewLayerModuleCall);
            }
        }, {
            key: 'hookPreviewLayerBind',
            value: function hookPreviewLayerBind(cb) {
                Hooker.hookPreviewLayer(function (exports) {
                    var bind = exports.default.prototype.bind;
                    exports.default.prototype.bind = function () {
                        cb(this);
                        bind.apply(this);
                    };
                });
            }
        }, {
            key: '_isSettingSeriesComponentModuleCall',
            value: function _isSettingSeriesComponentModuleCall(exports) {
                return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('_addEvent') && exports.default.prototype._addEvent.toString().includes('seriesliseLayer');
            }
        }, {
            key: 'hookSettingSeries',
            value: function hookSettingSeries(cb) {
                this._hookModuleCall(cb, this._isSettingSeriesComponentModuleCall);
            }
        }, {
            key: '_isSettingsIconComponentModuleCall',
            value: function _isSettingsIconComponentModuleCall(exports) {
                return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('setConfig');
            }
        }, {
            key: 'hookSettingsIcon',
            value: function hookSettingsIcon(cb) {
                this._hookModuleCall(cb, this._isSettingsIconComponentModuleCall);
            }
        }, {
            key: '_isTriggerLayerComponentModuleCall',
            value: function _isTriggerLayerComponentModuleCall(exports) {
                return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('showMenu');
            }
        }, {
            key: 'hookTriggerLayer',
            value: function hookTriggerLayer(cb) {
                this._hookModuleCall(cb, this._isTriggerLayerComponentModuleCall);
            }
        }, {
            key: '_isUtilModuleCall',
            value: function _isUtilModuleCall(exports) {
                return exports.setLocalData && exports.getLocalData;
            }
        }, {
            key: 'hookUtil',
            value: function hookUtil(cb) {
                this._hookModuleCall(cb, this._isUtilModuleCall);
            }
        }, {
            key: '_isGlobalModuleCall',
            value: function _isGlobalModuleCall(exports) {
                return this._isEsModule(exports) && this._isFuction(exports.default) && exports.default.prototype && exports.default.prototype.hasOwnProperty('resetConfig');
            }
        }, {
            key: 'hookGlobal',
            value: function hookGlobal(cb) {
                this._hookModuleCall(cb, this._isGlobalModuleCall);
            }
        }, {
            key: 'hookGlobalConstructorAfter',
            value: function hookGlobalConstructorAfter(cb) {
                Hooker.hookGlobal(function (exports) {
                    var constructor = exports.default;
                    exports.default = function () {
                        for (var _len8 = arguments.length, args = Array(_len8), _key8 = 0; _key8 < _len8; _key8++) {
                            args[_key8] = arguments[_key8];
                        }

                        constructor.apply(this, args);
                        cb(this);
                    };
                    exports.default.prototype = constructor.prototype;
                });
            }
        }, {
            key: 'hookGlobalInit',
            value: function hookGlobalInit(cb) {
                Hooker.hookGlobal(function (exports) {
                    var init = exports.default.prototype.init;
                    exports.default.prototype.init = function (config) {
                        cb(config, this);
                        init.apply(this, [config]);
                    };
                });
            }
        }, {
            key: 'hookGlobalDeal',
            value: function hookGlobalDeal(cb) {
                Hooker.hookGlobal(function (exports) {
                    var deal = exports.default.prototype.deal;
                    exports.default.prototype.deal = function () {
                        cb(this);
                        deal.apply(this);
                    };
                });
            }
        }, {
            key: 'hookGlobalResetAfter',
            value: function hookGlobalResetAfter(cb) {
                Hooker.hookGlobal(function (exports) {
                    var reset = exports.default.prototype.reset;
                    exports.default.prototype.reset = function () {
                        reset.apply(this);
                        cb(this);
                    };
                });
            }
        }, {
            key: '_extractArgsName',
            value: function _extractArgsName(code) {
                return code.slice(code.indexOf('(') + 1, code.indexOf(')')).split(/\s*,\s*/);
            }
        }, {
            key: '_extractFunctionBody',
            value: function _extractFunctionBody(code) {
                return code.slice(code.indexOf('{') + 1, code.lastIndexOf('}'));
            }
        }, {
            key: '_isBaseModuleCall',
            value: function _isBaseModuleCall(exports) {
                return exports.SingleVideoControl && exports.MultiVideoControl;
            }
        }, {
            key: 'hookBase',
            value: function hookBase(cb, mode) {
                var _this2 = this;

                var callbacks = [];
                var codeCallbacks = [];
                (mode === 'code' ? codeCallbacks : callbacks).push(cb);

                this._hookModuleCall(function (exports, args) {
                    if (codeCallbacks.length > 0) {
                        var code = args[3].m[args[1].i].toString();
                        code = codeCallbacks.reduce(function (c, cb) {
                            return cb(c);
                        }, code);
                        var fn = new (Function.prototype.bind.apply(Function, [null].concat(_toConsumableArray(_this2._extractArgsName(code)), [_this2._extractFunctionBody(code)])))();
                        fn.apply(args[0], args.slice(1));
                    }
                    callbacks.forEach(function (cb) {
                        return cb(args[1].exports);
                    });
                    _this2.hookBase = null;
                }, this._isBaseModuleCall);

                this.hookBase = function (cb, mode) {
                    return (mode === 'code' ? codeCallbacks : callbacks).push(cb);
                };
            }
        }, {
            key: 'hookGlobalVariable',
            value: function hookGlobalVariable(name, cb) {
                var window = unsafeWindow;

                var value = window[name];
                Object.defineProperty(window, name, {
                    get: function get() {
                        return value;
                    },
                    set: function set(v) {
                        try {
                            var ret = cb(v);
                            value = ret === undefined ? v : ret;
                        } catch (err) {
                            Logger.error(err.stack);
                        }
                    }
                });
                if (value) window[name] = value;
            }
        }, {
            key: 'hookOz',
            value: function hookOz(cb) {
                var callbacks = [cb];
                this.hookGlobalVariable('oz', function (oz) {
                    callbacks.forEach(function (cb) {
                        return cb(oz);
                    });
                });
                this.hookOz = function (cb) {
                    return callbacks.push(cb);
                };
            }
        }, {
            key: 'hookDefine',
            value: function hookDefine(name, cb) {
                var _this3 = this;

                var callbacksMap = new Map([[name, [cb]]]);
                this.hookOz(function (oz) {
                    var self = _this3;
                    var define = oz.define;
                    oz.define = function (name, deps, block) {
                        if (callbacksMap.has(name)) {
                            var code = block.toString();
                            code = callbacksMap.get(name).reduce(function (c, cb) {
                                return cb(c);
                            }, code);
                            block = new (Function.prototype.bind.apply(Function, [null].concat(_toConsumableArray(self._extractArgsName(code)), [self._extractFunctionBody(code)])))();
                        }
                        define(name, deps, block);
                    };
                });

                this.hookDefine = function (name, cb) {
                    if (callbacksMap.has(name)) {
                        callbacksMap.get(name).push(cb);
                    } else {
                        callbacksMap.set(name, [cb]);
                    }
                };
            }
        }]);

        return Hooker;
    }();

    var Patch = function () {
        function Patch() {
            _classCallCheck(this, Patch);

            this._installed = false;
        }

        _createClass(Patch, [{
            key: 'install',
            value: function install() {
                if (!this._installed) {
                    this._installed = true;
                    this._apply();
                }
            }
        }, {
            key: '_apply',
            value: function _apply() {}
        }]);

        return Patch;
    }();

    var MockAdsPatch = function (_Patch) {
        _inherits(MockAdsPatch, _Patch);

        function MockAdsPatch() {
            _classCallCheck(this, MockAdsPatch);

            return _possibleConstructorReturn(this, (MockAdsPatch.__proto__ || Object.getPrototypeOf(MockAdsPatch)).call(this));
        }

        _createClass(MockAdsPatch, [{
            key: '_apply',
            value: function _apply() {
                var self = this;
                Hooker.hookAdService(function (exports) {
                    exports.default.prototype.requestAdData = function (obj /* , params */) {
                        var _this5 = this;

                        setTimeout(function () {
                            if ('frontad' === obj.adtype) {
                                _this5.success(obj, self._fakeFrontAdData());
                            } else {
                                _this5.fail(obj, { code: '404', message: 'error' });
                            }
                        }, 0);
                    };
                });
                this._hideOppoAds();
            }
        }, {
            key: '_fakeFrontAdData',
            value: function _fakeFrontAdData() {
                var data = {
                    VAL: []
                };
                return data;
            }
        }, {
            key: '_hideOppoAds',
            value: function _hideOppoAds() {
                GM_addStyle('\n                .oppo-ads, .oppinfo {\n                    display: none !important;\n                }\n            ');
            }
        }]);

        return MockAdsPatch;
    }(Patch);

    var WatermarksPatch = function (_Patch2) {
        _inherits(WatermarksPatch, _Patch2);

        function WatermarksPatch() {
            _classCallCheck(this, WatermarksPatch);

            return _possibleConstructorReturn(this, (WatermarksPatch.__proto__ || Object.getPrototypeOf(WatermarksPatch)).call(this));
        }

        _createClass(WatermarksPatch, [{
            key: '_apply',
            value: function _apply() {
                Hooker.hookLogo(function (exports) {
                    exports.default.prototype.reset = function () {};
                });
            }
        }]);

        return WatermarksPatch;
    }(Patch);

    var VipPatch = function (_Patch3) {
        _inherits(VipPatch, _Patch3);

        function VipPatch() {
            _classCallCheck(this, VipPatch);

            return _possibleConstructorReturn(this, (VipPatch.__proto__ || Object.getPrototypeOf(VipPatch)).call(this));
        }

        _createClass(VipPatch, [{
            key: '_apply',
            value: function _apply() {
                Hooker.hookUpsOnComplete(function (res) {
                    var data = res.data;
                    data.user = Object.assign(data.user || {}, { vip: true });
                    data.vip = Object.assign(data.vip || {}, { hd3: true });
                });
            }
        }]);

        return VipPatch;
    }(Patch);

    var QualityPatch = function (_Patch4) {
        _inherits(QualityPatch, _Patch4);

        function QualityPatch() {
            _classCallCheck(this, QualityPatch);

            return _possibleConstructorReturn(this, (QualityPatch.__proto__ || Object.getPrototypeOf(QualityPatch)).call(this));
        }

        _createClass(QualityPatch, [{
            key: '_apply',
            value: function _apply() {
                this._improveAdaptQuality();
            }
        }, {
            key: '_findBestQuality',
            value: function _findBestQuality(qualityList) {
                return ['1080p', '720p', '480p', '320p'].find(function (q) {
                    return qualityList.some(function (v) {
                        return v === q;
                    });
                });
            }
        }, {
            key: '_improveAdaptQuality',
            value: function _improveAdaptQuality() {
                var self = this;
                Hooker.hookGlobal(function (exports) {
                    var adaptQuality = exports.default.prototype.adaptQuality;
                    exports.default.prototype.adaptQuality = function (lang) {
                        var cfg = this._config;
                        var quality = cfg.quality;
                        adaptQuality.apply(this, [lang]);
                        if (!this.qualityList.includes(quality)) {
                            cfg.quality = self._findBestQuality(this.qualityList);
                        }
                    };
                });
            }
        }]);

        return QualityPatch;
    }(Patch);

    var DashboardPatch = function (_Patch5) {
        _inherits(DashboardPatch, _Patch5);

        function DashboardPatch() {
            _classCallCheck(this, DashboardPatch);

            return _possibleConstructorReturn(this, (DashboardPatch.__proto__ || Object.getPrototypeOf(DashboardPatch)).call(this));
        }

        _createClass(DashboardPatch, [{
            key: '_apply',
            value: function _apply() {
                this._prepare();
                this._patch();
            }
        }, {
            key: '_prepare',
            value: function _prepare() {
                this._exposeDashboard();
                Hooker.hookPreviewLayerBind(function (that) {
                    that._el.addEventListener('mouseover', function () {
                        return that.emit('mouseoverpreview');
                    });
                    that._el.addEventListener('mouseleave', function () {
                        return that.emit('mouseleavepreview');
                    });
                });
            }
        }, {
            key: '_findVarName',
            value: function _findVarName(code) {
                return (/"dashboard"\s*,\s*(\w+)/.exec(code)[1]
                );
            }
        }, {
            key: '_exposeDashboard',
            value: function _exposeDashboard() {
                var _this10 = this;

                Hooker.hookBase(function (code) {
                    var varName = _this10._findVarName(code);
                    return code.replace(/\.exports\s*=\s*(\w+)/, '$&;$1.__Dashboard=' + varName + ';');
                }, 'code');
            }
        }, {
            key: '_patch',
            value: function _patch() {
                Hooker.hookBase(function (exports) {
                    var proto = exports.__Dashboard.prototype;

                    proto.bindAutoHide = function () {
                        var _this11 = this;

                        this._args.show = 'function' === typeof this._args.show ? this._args.show : function () {};
                        this._args.hide = 'function' === typeof this._args.hide ? this._args.show : function () {};

                        this._el.addEventListener('mouseover', function () {
                            return _this11._mouseover = true;
                        });
                        this._el.addEventListener('mouseleave', function () {
                            return _this11._mouseover = false;
                        });
                        this.on('mouseoverpreview', function () {
                            return _this11._mouseoverpreview = true;
                        });
                        this.on('mouseleavepreview', function () {
                            return _this11._mouseoverpreview = false;
                        });
                        this._video.on('play', function () {
                            if (!_this11._mouseover && !_this11._mouseoverpreview) _this11._hideTimeout = setTimeout(_this11.hide.bind(_this11), _this11._args.autoHide);
                        });
                        this._video.on('pause', function () {
                            _this11._hideTimeout && clearTimeout(_this11._hideTimeout);
                            _this11.isShow() || _this11.show();
                        });
                        this._parent.addEventListener('mousemove', function () {
                            _this11._hideTimeout && clearTimeout(_this11._hideTimeout);
                            _this11.isShow() || _this11.show();
                            if (!_this11._isPaused() && !_this11._mouseover && !_this11._mouseoverpreview) _this11._hideTimeout = setTimeout(_this11.hide.bind(_this11), _this11._args.autoHide);
                        });
                        this._parent.addEventListener('mouseleave', function () {
                            _this11._hideTimeout && clearTimeout(_this11._hideTimeout);
                            if (!_this11._isPaused()) _this11.hide();
                        });
                    };

                    proto._isPaused = function () {
                        return this._video._videoCore.video.paused;
                    };

                    proto.isShow = function () {
                        return this._el.style.display !== 'none';
                    };

                    proto.show = function () {
                        this.emit('dashboardshow');
                        this._parent.style.cursor = '';
                        this._el.style.display = '';
                        this._args.show();
                    };

                    proto.hide = function () {
                        this.emit('dashboardhide');
                        this._parent.style.cursor = 'none'; // 隐藏鼠标
                        this._el.style.display = 'none';
                        this._args.show();
                    };
                });
            }
        }]);

        return DashboardPatch;
    }(Patch);

    var TopAreaPatch = function (_Patch6) {
        _inherits(TopAreaPatch, _Patch6);

        function TopAreaPatch() {
            _classCallCheck(this, TopAreaPatch);

            return _possibleConstructorReturn(this, (TopAreaPatch.__proto__ || Object.getPrototypeOf(TopAreaPatch)).call(this));
        }

        _createClass(TopAreaPatch, [{
            key: '_apply',
            value: function _apply() {
                Hooker.hookTopAreaAddEvent(function (that) {
                    that.on('webfullscreen', function (isWebFullscreen) {
                        isWebFullscreen ? that._showHideTop(true) : that._hideHideTop();
                    });
                    that.on('dashboardshow', function () {
                        var playerState = that._video.global.playerState;
                        if (playerState.fullscreen || playerState.webfullscreen) {
                            that._showHideTop(true);
                        }
                    });
                    that.on('dashboardhide', function () {
                        var playerState = that._video.global.playerState;
                        if (playerState.fullscreen || playerState.webfullscreen) {
                            that._hideHideTop();
                        }
                    });
                });
                Hooker.hookResetPlayerAfter(function (that) {
                    // 网页全屏播放上下集重置播放器后显示顶部控件
                    if (!that.global.playerState.fullscreen) that._player.control.emit('webfullscreen', that.global.playerState.webfullscreen);
                });
            }
        }]);

        return TopAreaPatch;
    }(Patch);

    var SettingSeriesPatch = function (_Patch7) {
        _inherits(SettingSeriesPatch, _Patch7);

        function SettingSeriesPatch() {
            _classCallCheck(this, SettingSeriesPatch);

            return _possibleConstructorReturn(this, (SettingSeriesPatch.__proto__ || Object.getPrototypeOf(SettingSeriesPatch)).call(this));
        }

        _createClass(SettingSeriesPatch, [{
            key: '_apply',
            value: function _apply() {
                Hooker.hookSettingSeries(function (exports) {
                    // 网页全屏显示选集
                    var _addEvent = exports.default.prototype._addEvent;
                    exports.default.prototype._addEvent = function () {
                        var _this14 = this;

                        _addEvent.apply(this);
                        this.on('webfullscreen', function (isWebFullscreen) {
                            if (isWebFullscreen) {
                                if (_this14.seriesList.length > 1) _this14._el.style.display = 'inline-block';
                            } else {
                                _this14._el.style.display = 'none';
                                _this14._el.classList.remove('cliced');
                                _this14.emit('seriesliseLayer', false);
                            }
                        });
                    };
                });
            }
        }]);

        return SettingSeriesPatch;
    }(Patch);

    var ContinuePlayPatch = function (_Patch8) {
        _inherits(ContinuePlayPatch, _Patch8);

        function ContinuePlayPatch() {
            _classCallCheck(this, ContinuePlayPatch);

            return _possibleConstructorReturn(this, (ContinuePlayPatch.__proto__ || Object.getPrototypeOf(ContinuePlayPatch)).call(this));
        }

        _createClass(ContinuePlayPatch, [{
            key: '_apply',
            value: function _apply() {
                var _this16 = this;

                Hooker.hookInitPlayerEvent(function (that) {
                    // 视频播放结束处理
                    that._player.control.on('ended', that._onEnd.bind(that));
                    that._player.control.on('ended', function () {
                        return _this16._onEnd(that);
                    });
                });
            }
        }, {
            key: '_onEnd',
            value: function _onEnd(that) {
                var config = that.global.config;
                var playerState = that.global.playerState;
                if (config.continuePlay && config.nextVid && !playerState.fullscreen) {
                    if (playerState.webfullscreen) {
                        that.playByVid({ vid: that.global.config.nextVid });
                    } else {
                        that.gotoVideo(that.global.config.nextVid);
                    }
                }
            }
        }]);

        return ContinuePlayPatch;
    }(Patch);

    var FullscreenPatch = function (_Patch9) {
        _inherits(FullscreenPatch, _Patch9);

        function FullscreenPatch() {
            _classCallCheck(this, FullscreenPatch);

            return _possibleConstructorReturn(this, (FullscreenPatch.__proto__ || Object.getPrototypeOf(FullscreenPatch)).call(this));
        }

        _createClass(FullscreenPatch, [{
            key: '_apply',
            value: function _apply() {
                Object.defineProperty(document, 'fullscreen', {});
            }
        }]);

        return FullscreenPatch;
    }(Patch);

    var WebFullscreen = function () {
        function WebFullscreen(elem) {
            _classCallCheck(this, WebFullscreen);

            this._elem = elem;
        }

        _createClass(WebFullscreen, [{
            key: 'isWebFullscreen',
            value: function isWebFullscreen() {
                return this._elem.classList.contains('webfullscreen');
            }
        }, {
            key: 'enter',
            value: function enter() {
                this._elem.classList.add('webfullscreen');
                var body = document.body;
                body.style.overflow = 'hidden';

                var parentElement = this._elem.parentElement;
                while (parentElement && parentElement !== body) {
                    parentElement.classList.add('z-top');
                    parentElement = parentElement.parentElement;
                }
            }
        }, {
            key: 'exit',
            value: function exit() {
                this._elem.classList.remove('webfullscreen');
                var body = document.body;
                body.style.overflow = '';

                var parentElement = this._elem.parentElement;
                while (parentElement && parentElement !== body) {
                    parentElement.classList.remove('z-top');
                    parentElement = parentElement.parentElement;
                }
            }
        }, {
            key: 'toggle',
            value: function toggle() {
                this.isWebFullscreen() ? this.exit() : this.enter();
            }
        }], [{
            key: 'addStyle',
            value: function addStyle() {
                GM_addStyle('\n                .z-top {\n                    position: relative !important;\n                    z-index: 23333333 !important;\n                }\n                .webfullscreen {\n                    display: block !important;\n                    position: fixed !important;\n                    width: 100% !important;\n                    height: 100% !important;\n                    top: 0 !important;\n                    left: 0 !important;\n                    background: #000 !important;\n                    z-index: 23333333 !important;\n                }\n            ');
            }
        }]);

        return WebFullscreen;
    }();

    var ManagePatch = function (_Patch10) {
        _inherits(ManagePatch, _Patch10);

        function ManagePatch() {
            _classCallCheck(this, ManagePatch);

            return _possibleConstructorReturn(this, (ManagePatch.__proto__ || Object.getPrototypeOf(ManagePatch)).call(this));
        }

        _createClass(ManagePatch, [{
            key: '_apply',
            value: function _apply() {
                this._prepare();
                this._hookManage();
            }
        }, {
            key: '_prepare',
            value: function _prepare() {
                this._customTip();
                this._disablePlayAfterSeek();
                this._addPrevInfo();
                this._playAfterPlayerReset();
                this._keepPlaybackRate();
                this._playbackRatePersistence();
                new ContinuePlayPatch().install();
                new FullscreenPatch().install();
            }
        }, {
            key: '_customTip',
            value: function _customTip() {
                Hooker.hookTips(function (exports) {
                    var showHintTips = exports.default.prototype.showHintTips;
                    exports.default.prototype.showHintTips = function (code, info) {
                        if (info.msg) {
                            this._hintLayer.setHintShow(info.msg);
                        } else {
                            showHintTips.apply(this, [code, info]);
                        }
                    };
                });
            }
        }, {
            key: '_disablePlayAfterSeek',
            value: function _disablePlayAfterSeek() {
                // SingleVideoControl seek 后不自动播放
                Hooker.hookBase(function (exports) {
                    var _setCurrentTime = exports.SingleVideoControl.prototype._setCurrentTime;
                    exports.SingleVideoControl.prototype._setCurrentTime = function (time) {
                        var play = this.video.play;
                        this.video.play = function () {};
                        _setCurrentTime.apply(this, [time]);
                        this.video.play = play;
                    };
                });
            }
        }, {
            key: '_keepPlaybackRate',
            value: function _keepPlaybackRate() {
                Hooker.hookBase(function (exports) {
                    var proto = exports.MultiVideoControl.prototype;
                    var _setVideo = proto._setVideo;
                    proto._setVideo = function () {
                        var rate = this.video.playbackRate;

                        for (var _len9 = arguments.length, args = Array(_len9), _key9 = 0; _key9 < _len9; _key9++) {
                            args[_key9] = arguments[_key9];
                        }

                        _setVideo.apply(this, args);
                        this.video.playbackRate = rate;
                    };
                });
            }
        }, {
            key: '_playbackRatePersistence',
            value: function _playbackRatePersistence() {
                var util = void 0;
                Hooker.hookUtil(function (exports) {
                    return util = exports;
                });
                Hooker.hookSettingsIcon(function (exports) {
                    var proto = exports.default.prototype;
                    var setDataUI = proto.setDataUI;
                    proto.setDataUI = function (data) {
                        var _this19 = this;

                        setDataUI.apply(this, [data]);
                        this._video.global.playerState = { playbackRate: data.playbackRate || 1 };
                        this.on('playbackratechange', function (rate) {
                            _this19.data.playbackRate = rate;
                            util.setLocalData('YK_PSL_SETTINGS', _this19.data);
                        });
                    };
                });
            }
        }, {
            key: '_addPrevInfo',
            value: function _addPrevInfo() {
                Hooker.hookGlobalDeal(function (that) {
                    if (that.ups && that.ups.videoData && that.ups.programList && that.ups.programList.videoList) {
                        var list = that.ups.programList.videoList;
                        var currVid = that.ups.videoData.id;
                        var currIdx = list.findIndex(function (item) {
                            return parseInt(item.vid) === currVid;
                        });
                        if (currIdx > 0) {
                            var prevVideo = list[currIdx - 1];
                            that.ups.programList.prevVideo = prevVideo;
                            prevVideo && (that._config.prevVid = prevVideo.encodevid);
                        }
                    }
                });
            }
        }, {
            key: '_playAfterPlayerReset',
            value: function _playAfterPlayerReset() {
                Hooker.hookResetPlayerAfter(function (that) {
                    if (that.global.playerState.state === 'playerreset') that.play();
                });
            }
        }, {
            key: '_hookManage',
            value: function _hookManage() {
                Hooker.hookManage(this._hookManageCallback.bind(this));
            }
        }, {
            key: '_hookManageCallback',
            value: function _hookManageCallback(exports) {
                var proto = exports.default.prototype;

                var _init = proto._init;
                proto._init = function () {
                    _init.apply(this);
                    WebFullscreen.addStyle();
                    this._webfullscreen = new WebFullscreen(this.container);
                };

                proto._showTip = function (msg) {
                    this._emitter.emit('player.showinfo', { type: 'hint', msg: msg });
                };

                proto.play = function () {
                    this._player && this._player.control.play();
                    this._showTip('播放');
                };

                proto._pause = proto.pause;
                proto.pause = function () {
                    this._pause();
                    this._showTip('暂停');
                };

                proto.adjustVolume = function (value) {
                    var volume = this.global.playerState.volume + value;
                    volume = Math.max(0, Math.min(1, volume.toFixed(2)));
                    this._player.control.setVolume(volume);
                    if (volume === 0) {
                        this._emitter.emit('player.showinfo', { type: 'hint', code: 'H0003', volume: volume + '%' });
                    }
                };

                proto.toggleMute = function () {
                    if (this.global.playerState.muted) this._showTip('取消静音');
                    this.setMuted(!this.global.playerState.muted);
                };

                proto.stepSeek = function (stepTime) {
                    var duration = this._player.control.getDuration();
                    var currentTime = this.global.currentTime;
                    var seekTime = Math.max(0, Math.min(duration, currentTime + stepTime));
                    this.seek(seekTime);

                    var msg = void 0;
                    if (Math.abs(stepTime) < 60) {
                        msg = stepTime > 0 ? '\u6B65\u8FDB\uFF1A' + stepTime + '\u79D2' : '\u6B65\u9000\uFF1A' + Math.abs(stepTime) + '\u79D2';
                    } else {
                        msg = stepTime > 0 ? '\u6B65\u8FDB\uFF1A' + stepTime / 60 + '\u5206\u949F' : '\u6B65\u9000\uFF1A' + Math.abs(stepTime) / 60 + '\u5206\u949F';
                    }
                    this._showTip(msg);
                };

                proto.rangeSeek = function (range) {
                    var duration = this._player.control.getDuration();
                    var seekTime = Math.max(0, Math.min(duration, duration * range));
                    this.seek(seekTime);
                    this._showTip('定位:' + (range * 100).toFixed(0) + '%');
                };

                proto.isFullscreen = function () {
                    return this.global.playerState.fullscreen;
                };

                proto.toggleFullscreen = function () {
                    if (this.isFullscreen()) {
                        this.exitFullscreen();
                    } else {
                        this.fullScreen();
                    }
                };

                proto.isWebFullscreen = function () {
                    return this._webfullscreen.isWebFullscreen();
                };

                proto.enterWebFullscreen = function () {
                    this._webfullscreen.enter();
                    this.global.playerState = { webfullscreen: true };
                    this._player.control.emit('webfullscreen', true);
                };

                proto.exitWebFullscreen = function () {
                    this._webfullscreen.exit();
                    this.global.playerState = { webfullscreen: false };
                    this._player.control.emit('webfullscreen', false);
                };

                proto.toggleWebFullscreen = function () {
                    this.isWebFullscreen() ? this.exitWebFullscreen() : this.enterWebFullscreen();
                };

                proto.setRate = function (rate) {
                    var videoCore = this._player.control._videoCore;
                    var video = videoCore.video;
                    if (this._player.config.controlType === 'multi') {
                        videoCore._videoElments.forEach(function (v) {
                            return v.playbackRate = rate;
                        });
                    } else {
                        video.playbackRate = rate;
                    }
                };

                proto.adjustPlaybackRate = function (value) {
                    var video = this._player.control._videoCore.video;
                    var rate = Math.max(0.2, Math.min(5, parseFloat((video.playbackRate + value).toFixed(1))));
                    this.setRate(rate);
                    this.global.playerState = { playbackRate: rate };
                    this._player.control.emit('playbackratechange', rate);
                    this._showTip('\u64AD\u653E\u901F\u7387\uFF1A' + rate);
                };

                proto.turnPlaybackRate = function () {
                    var video = this._player.control._videoCore.video;
                    var rate = video.playbackRate !== 1 ? 1 : this.global.playerState.playbackRate;
                    this.setRate(rate);
                    this._showTip('\u64AD\u653E\u901F\u7387\uFF1A' + rate);
                };

                proto.getFps = function () {
                    return 25; // 标清fps为15,标清以上fps为25。
                };

                proto.prevFrame = function () {
                    var state = this.global.playerState.state;
                    if (state === 'playing') this.pause();
                    var duration = this._player.control.getDuration();
                    var currentTime = this.global.currentTime;
                    var seekTime = Math.max(0, Math.min(duration, currentTime - 1 / this.getFps()));
                    this.seek(seekTime);
                    this._showTip('上一帧');
                };

                proto.nextFrame = function () {
                    var state = this.global.playerState.state;
                    if (state === 'playing') this.pause();
                    var duration = this._player.control.getDuration();
                    var currentTime = this.global.currentTime;
                    var seekTime = Math.max(0, Math.min(duration, currentTime + 1 / this.getFps()));
                    this.seek(seekTime);
                    this._showTip('下一帧');
                };

                proto.playPrev = function () {
                    var prevVid = this.global.config.prevVid;
                    if (prevVid) {
                        if (this.isFullscreen() || this.isWebFullscreen()) {
                            this.playByVid({ vid: prevVid });
                        } else {
                            this.gotoVideo(prevVid);
                        }
                        this._showTip('播放上一集');
                    } else {
                        this._showTip('没有上一集哦');
                    }
                };

                var playNext = proto.playNext;
                proto.playNext = function (data) {
                    if (data) return playNext.apply(this, [data]);
                    var nextVid = this.global.config.nextVid;
                    if (nextVid) {
                        if (this.isFullscreen() || this.isWebFullscreen()) {
                            this.playByVid({ vid: nextVid });
                        } else {
                            this.gotoVideo(nextVid);
                        }
                        this._showTip('播放下一集');
                    } else {
                        this._showTip('没有下一集哦');
                    }
                };

                proto.gotoVideo = function (vid) {
                    location.href = '//v.youku.com/v_show/id_' + vid + '.html';
                };
            }
        }]);

        return ManagePatch;
    }(Patch);

    var managePatch = new ManagePatch();

    var KeyShortcutsPatch = function (_Patch11) {
        _inherits(KeyShortcutsPatch, _Patch11);

        function KeyShortcutsPatch() {
            _classCallCheck(this, KeyShortcutsPatch);

            return _possibleConstructorReturn(this, (KeyShortcutsPatch.__proto__ || Object.getPrototypeOf(KeyShortcutsPatch)).call(this));
        }

        _createClass(KeyShortcutsPatch, [{
            key: '_apply',
            value: function _apply() {
                this._prepare();
                this._addListener();
            }
        }, {
            key: '_prepare',
            value: function _prepare() {
                managePatch.install();
                this._obtainPlayer();
            }
        }, {
            key: '_obtainPlayer',
            value: function _obtainPlayer() {
                var self = this;
                Hooker.hookKeyShortcuts(function (exports) {
                    exports.default.prototype.registerEvents = function () {
                        self._player = this._player;
                    };
                });
            }
        }, {
            key: '_addListener',
            value: function _addListener() {
                document.addEventListener('keydown', this._handler.bind(this));
            }
        }, {
            key: '_handler',
            value: function _handler(event) {
                if (event.target.nodeName !== 'BODY') return;

                switch (event.keyCode) {
                    case 32:
                        // Spacebar
                        if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
                            var state = this._player.global.playerState.state;
                            if (state === 'paused') {
                                this._player.play();
                            } else if (state === 'ended') {
                                this._player.replay();
                            } else {
                                this._player.pause();
                            }
                        } else {
                            return;
                        }
                        break;
                    case 39: // → Arrow Right
                    case 37:
                        {
                            // ← Arrow Left
                            var stepTime = void 0;
                            if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
                                stepTime = 39 === event.keyCode ? 5 : -5;
                            } else if (event.ctrlKey && !event.shiftKey && !event.altKey) {
                                stepTime = 39 === event.keyCode ? 30 : -30;
                            } else if (!event.ctrlKey && event.shiftKey && !event.altKey) {
                                stepTime = 39 === event.keyCode ? 60 : -60;
                            } else if (event.ctrlKey && !event.shiftKey && event.altKey) {
                                stepTime = 39 === event.keyCode ? 3e2 : -3e2; // 5分钟
                            } else {
                                return;
                            }
                            this._player.stepSeek(stepTime);
                            break;
                        }
                    case 38: // ↑ Arrow Up
                    case 40:
                        // ↓ Arrow Down
                        if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
                            this._player.adjustVolume(38 === event.keyCode ? 0.05 : -0.05);
                        } else {
                            return;
                        }
                        break;
                    case 77:
                        // M
                        if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
                            this._player.toggleMute();
                        } else {
                            return;
                        }
                        break;
                    case 13:
                        // Enter
                        if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
                            this._player.toggleFullscreen();
                        } else if (event.ctrlKey && !event.shiftKey && !event.altKey) {
                            this._player.toggleWebFullscreen();
                        } else {
                            return;
                        }
                        break;
                    case 67: // C
                    case 88:
                        // X
                        if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
                            this._player.adjustPlaybackRate(67 === event.keyCode ? 0.1 : -0.1);
                        } else {
                            return;
                        }
                        break;
                    case 90:
                        // Z
                        if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
                            this._player.turnPlaybackRate();
                        } else {
                            return;
                        }
                        break;
                    case 68: // D
                    case 70:
                        // F
                        if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
                            if (event.keyCode === 68) {
                                this._player.prevFrame();
                            } else {
                                this._player.nextFrame();
                            }
                        } else {
                            return;
                        }
                        break;
                    case 80: // P
                    case 78:
                        // N
                        if (!event.ctrlKey && event.shiftKey && !event.altKey) {
                            if (event.keyCode === 78) {
                                this._player.playNext();
                            } else {
                                this._player.playPrev();
                            }
                        } else {
                            return;
                        }
                        break;
                    case 27:
                        // ESC
                        if (!event.ctrlKey && !event.shiftKey && !event.altKey) this._player.isWebFullscreen() && this._player.exitWebFullscreen();
                        return;
                    default:
                        if (event.keyCode >= 48 && event.keyCode <= 57) {
                            // 0 ~ 9
                            if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
                                this._player.rangeSeek((event.keyCode - 48) * 0.1);
                            } else {
                                return;
                            }
                        } else {
                            return;
                        }
                }

                event.preventDefault();
                event.stopPropagation();
            }
        }]);

        return KeyShortcutsPatch;
    }(Patch);

    var MouseShortcutsPatch = function (_Patch12) {
        _inherits(MouseShortcutsPatch, _Patch12);

        function MouseShortcutsPatch() {
            _classCallCheck(this, MouseShortcutsPatch);

            return _possibleConstructorReturn(this, (MouseShortcutsPatch.__proto__ || Object.getPrototypeOf(MouseShortcutsPatch)).call(this));
        }

        _createClass(MouseShortcutsPatch, [{
            key: '_apply',
            value: function _apply() {
                this._prepare();
                this._initEvents();
            }
        }, {
            key: '_prepare',
            value: function _prepare() {
                managePatch.install();
            }
        }, {
            key: '_initEvents',
            value: function _initEvents() {
                Hooker.hookTriggerLayer(function (exports) {
                    var proto = exports.default.prototype;
                    var initEvents = proto.initEvents;
                    proto.initEvents = function () {
                        var _this22 = this;

                        var player = this._video.ykplayer;

                        this._el.addEventListener('dblclick', function (event) {
                            if (event.ctrlKey) {
                                player.toggleWebFullscreen();
                                event.stopImmediatePropagation();
                                _this22._clickTimer.clear();
                            }
                        });
                        this._el.addEventListener('wheel', function (event) {
                            if (player.isFullscreen() || player.isWebFullscreen()) {
                                var delta = event.wheelDelta || event.detail || event.deltaY && -event.deltaY;
                                player.adjustVolume(delta > 0 ? 0.05 : -0.05);
                            }
                        });

                        initEvents.apply(this);
                    };
                });
            }
        }]);

        return MouseShortcutsPatch;
    }(Patch);

    var ShortcutsPatch = function (_Patch13) {
        _inherits(ShortcutsPatch, _Patch13);

        function ShortcutsPatch() {
            _classCallCheck(this, ShortcutsPatch);

            return _possibleConstructorReturn(this, (ShortcutsPatch.__proto__ || Object.getPrototypeOf(ShortcutsPatch)).call(this));
        }

        _createClass(ShortcutsPatch, [{
            key: '_apply',
            value: function _apply() {
                new KeyShortcutsPatch().install();
                Logger.log('添加键盘快捷键');
                new MouseShortcutsPatch().install();
                Logger.log('添加鼠标快捷键');
            }
        }]);

        return ShortcutsPatch;
    }(Patch);

    var TVBH5Patch = function (_Patch14) {
        _inherits(TVBH5Patch, _Patch14);

        function TVBH5Patch() {
            _classCallCheck(this, TVBH5Patch);

            return _possibleConstructorReturn(this, (TVBH5Patch.__proto__ || Object.getPrototypeOf(TVBH5Patch)).call(this));
        }

        _createClass(TVBH5Patch, [{
            key: '_apply',
            value: function _apply() {
                Hooker.hookGlobalVariable('PageConfig', function (cfg) {
                    Object.defineProperty(cfg, 'production', { get: function get() {
                            return '';
                        } });
                });
                Logger.log('H5-player has been enabled at TVB\'s videos.');
            }
        }]);

        return TVBH5Patch;
    }(Patch);

    // class H5Patch extends Patch {

    // constructor() {
    // super();
    // }

    // _apply() {
    // Hooker.hookDefine('page/find/play/player/load', this._forceH5.bind(this));
    // }

    // _forceH5(code) {
    // return code.replace(/(if\s*\().*?(\)\s*\{)/, '$1true$2').replace('window.sessionStorage', 'null');
    // }

    // }

    function ensureH5PlayerEnabled() {
        // (new H5Patch()).install();
        Object.defineProperty(unsafeWindow.navigator, 'plugins', { get: function get() {
                return {};
            } });
        Logger.log('启用html5播放器');
    }

    function mockAds() {
        new MockAdsPatch().install();
        Logger.log('和谐广告');
    }

    function invalidateWatermarks() {
        new WatermarksPatch().install();
        Logger.log('和谐水印');
    }

    function invalidateQualityLimitation() {
        new VipPatch().install();
        Logger.log('解除会员画质限制');
    }

    function improveQualityLogic() {
        new QualityPatch().install();
        Logger.log('改善画质逻辑');
    }

    function improveAutoHide() {
        new DashboardPatch().install();
        new TopAreaPatch().install();
        new SettingSeriesPatch().install();
        Logger.log('改善控件与光标自动隐藏');
    }

    function improveShortcuts() {
        new ShortcutsPatch().install();
    }

    function enableH5ForTVB() {
        new TVBH5Patch().install();
    }

    //=============================================================================

    ensureH5PlayerEnabled();
    mockAds();
    invalidateWatermarks();
    invalidateQualityLimitation();
    improveQualityLogic();
    improveAutoHide();
    improveShortcuts();
    enableH5ForTVB();
})();