diff --git a/build/assets/fonts/youtube-sans-bold.ttf b/build/assets/fonts/youtube-sans-bold.ttf new file mode 100644 index 0000000..3ebd568 Binary files /dev/null and b/build/assets/fonts/youtube-sans-bold.ttf differ diff --git a/build/assets/gif/clickUserNamesToAtThem.gif b/build/assets/gif/clickUserNamesToAtThem.gif new file mode 100644 index 0000000..77639a6 Binary files /dev/null and b/build/assets/gif/clickUserNamesToAtThem.gif differ diff --git a/build/assets/gif/emotesMenu.gif b/build/assets/gif/emotesMenu.gif new file mode 100644 index 0000000..02e6848 Binary files /dev/null and b/build/assets/gif/emotesMenu.gif differ diff --git a/build/assets/gif/optionsMenu.gif b/build/assets/gif/optionsMenu.gif new file mode 100644 index 0000000..e5896ff Binary files /dev/null and b/build/assets/gif/optionsMenu.gif differ diff --git a/build/assets/gif/pinYourExtension.gif b/build/assets/gif/pinYourExtension.gif new file mode 100644 index 0000000..5521371 Binary files /dev/null and b/build/assets/gif/pinYourExtension.gif differ diff --git a/build/assets/gif/theaterMode.gif b/build/assets/gif/theaterMode.gif new file mode 100644 index 0000000..49ffced Binary files /dev/null and b/build/assets/gif/theaterMode.gif differ diff --git a/build/assets/icons/3x.png b/build/assets/icons/3x.png new file mode 100644 index 0000000..e906c9d Binary files /dev/null and b/build/assets/icons/3x.png differ diff --git a/build/assets/icons/MonkaSSS.jpg b/build/assets/icons/MonkaSSS.jpg new file mode 100644 index 0000000..a5e96e0 Binary files /dev/null and b/build/assets/icons/MonkaSSS.jpg differ diff --git a/build/assets/icons/blob.gif b/build/assets/icons/blob.gif new file mode 100644 index 0000000..150ec22 Binary files /dev/null and b/build/assets/icons/blob.gif differ diff --git a/build/assets/icons/icon128.png b/build/assets/icons/icon128.png new file mode 100644 index 0000000..006b7cf Binary files /dev/null and b/build/assets/icons/icon128.png differ diff --git a/build/assets/icons/icon48.png b/build/assets/icons/icon48.png new file mode 100644 index 0000000..41627ce Binary files /dev/null and b/build/assets/icons/icon48.png differ diff --git a/build/assets/icons/icon512.png b/build/assets/icons/icon512.png new file mode 100644 index 0000000..539922b Binary files /dev/null and b/build/assets/icons/icon512.png differ diff --git a/build/assets/icons/omegalul.png b/build/assets/icons/omegalul.png new file mode 100644 index 0000000..6e565a3 Binary files /dev/null and b/build/assets/icons/omegalul.png differ diff --git a/build/assets/icons/pepepls.gif b/build/assets/icons/pepepls.gif new file mode 100644 index 0000000..303ea84 Binary files /dev/null and b/build/assets/icons/pepepls.gif differ diff --git a/build/assets/screenShots/arrow.png b/build/assets/screenShots/arrow.png new file mode 100644 index 0000000..e272dee Binary files /dev/null and b/build/assets/screenShots/arrow.png differ diff --git a/build/assets/screenShots/screen1.png b/build/assets/screenShots/screen1.png new file mode 100644 index 0000000..05fb3e6 Binary files /dev/null and b/build/assets/screenShots/screen1.png differ diff --git a/build/assets/screenShots/screen2.png b/build/assets/screenShots/screen2.png new file mode 100644 index 0000000..bc8915a Binary files /dev/null and b/build/assets/screenShots/screen2.png differ diff --git a/build/assets/screenShots/screen3.png b/build/assets/screenShots/screen3.png new file mode 100644 index 0000000..1f6ea86 Binary files /dev/null and b/build/assets/screenShots/screen3.png differ diff --git a/build/assets/screenShots/screen4.png b/build/assets/screenShots/screen4.png new file mode 100644 index 0000000..8a774cd Binary files /dev/null and b/build/assets/screenShots/screen4.png differ diff --git a/build/assets/screenShots/screenShot1.jpg b/build/assets/screenShots/screenShot1.jpg new file mode 100644 index 0000000..7d50d1a Binary files /dev/null and b/build/assets/screenShots/screenShot1.jpg differ diff --git a/build/assets/screenShots/screenShot2.jpg b/build/assets/screenShots/screenShot2.jpg new file mode 100644 index 0000000..30efed5 Binary files /dev/null and b/build/assets/screenShots/screenShot2.jpg differ diff --git a/build/assets/screenShots/screenShot3.jpg b/build/assets/screenShots/screenShot3.jpg new file mode 100644 index 0000000..6978c1f Binary files /dev/null and b/build/assets/screenShots/screenShot3.jpg differ diff --git a/build/assets/screenShots/screenShot4.jpg b/build/assets/screenShots/screenShot4.jpg new file mode 100644 index 0000000..63e6589 Binary files /dev/null and b/build/assets/screenShots/screenShot4.jpg differ diff --git a/build/assets/screenShots/screenShot5.jpg b/build/assets/screenShots/screenShot5.jpg new file mode 100644 index 0000000..e4f3206 Binary files /dev/null and b/build/assets/screenShots/screenShot5.jpg differ diff --git a/build/background.js b/build/background.js new file mode 100644 index 0000000..8cd7b6f --- /dev/null +++ b/build/background.js @@ -0,0 +1 @@ +!function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=35)}({0:function(e,t,n){"use strict";var r=class{get(e=null){return new Promise((t,n)=>{const r="string"==typeof e||"number"==typeof e;chrome.storage[this.store].get(e,n=>{t(r?n[e]:n)})})}getBytesInUse(e=null){return new Promise((t,n)=>{chrome.storage[this.store].getBytesInUse(e,t)})}set(e){return new Promise((t,n)=>{chrome.storage[this.store].set(e,t)})}remove(e){return new Promise((t,n)=>{chrome.storage[this.store].remove(e,t)})}clear(){return new Promise((e,t)=>{chrome.storage[this.store].clear(e)})}listen(e,t){"function"==typeof e&&(t=e,e=null),chrome.storage.onChanged.addListener((n,r)=>{if(r===this.store)if(null!==e){if(n.hasOwnProperty(e)){const r=n[e].oldValue||null,i=n[e].newValue||null;t(r,i)}}else t(n)})}};new class extends r{constructor(){super(),this.store="local"}};const i=new class extends r{constructor(){super(),this.store="sync"}};new class{create(e=null,t){return"object"==typeof e&&(t=e,e=null),new Promise((n,r)=>{chrome.notifications.create(e,t,n)})}update(e,t){return new Promise((n,r)=>{chrome.notifications.update(e,t,n)})}clear(e){return new Promise((t,n)=>{chrome.notifications.clear(e,t)})}getAll(){return new Promise((e,t)=>{chrome.notifications.getAll(e)})}getPermissionLevel(){return new Promise((e,t)=>{chrome.notifications.getPermissionLevel(e)})}listen(e,t=null,n){if("function"==typeof t&&(n=t,t=null),"onPermissionLevelChanged"===e||"onShowSettings"===e)return this._nonNotificationIdListen(e,n);const r=null!==t?(e,...r)=>{t===e&&n(e,...r)}:n;chrome.notifications[e].addListener(r)}_nonNotificationIdListen(e,t){chrome.notifications[e].addListener(t)}};var o=n(1);t.a=new class extends o.EventEmitter{constructor(){super(),this._data=null,this.state="initiating",this._init()}async _init(){const e=await i.get();this._initListener(),this._data=e,this.state="ready",this.emit(this.state)}_initListener(){i.listen(e=>{Object.keys(e).forEach(t=>{e[t].hasOwnProperty("newValue")?this._data[t]=e[t].newValue:console.error("No newValue in sync storge change")}),this.emit("change",this.data,e)})}set(e){return i.set(e)}get data(){return this._data}has(e){return this.data.hasOwnProperty(e)}}},1:function(e,t,n){"use strict";var r,i="object"==typeof Reflect?Reflect:null,o=i&&"function"==typeof i.apply?i.apply:function(e,t,n){return Function.prototype.apply.call(e,t,n)};r=i&&"function"==typeof i.ownKeys?i.ownKeys:Object.getOwnPropertySymbols?function(e){return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))}:function(e){return Object.getOwnPropertyNames(e)};var s=Number.isNaN||function(e){return e!=e};function u(){u.init.call(this)}e.exports=u,e.exports.once=function(e,t){return new Promise((function(n,r){function i(){void 0!==o&&e.removeListener("error",o),n([].slice.call(arguments))}var o;"error"!==t&&(o=function(n){e.removeListener(t,i),r(n)},e.once("error",o)),e.once(t,i)}))},u.EventEmitter=u,u.prototype._events=void 0,u.prototype._eventsCount=0,u.prototype._maxListeners=void 0;var a=10;function l(e){if("function"!=typeof e)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof e)}function c(e){return void 0===e._maxListeners?u.defaultMaxListeners:e._maxListeners}function f(e,t,n,r){var i,o,s;if(l(n),void 0===(o=e._events)?(o=e._events=Object.create(null),e._eventsCount=0):(void 0!==o.newListener&&(e.emit("newListener",t,n.listener?n.listener:n),o=e._events),s=o[t]),void 0===s)s=o[t]=n,++e._eventsCount;else if("function"==typeof s?s=o[t]=r?[n,s]:[s,n]:r?s.unshift(n):s.push(n),(i=c(e))>0&&s.length>i&&!s.warned){s.warned=!0;var u=new Error("Possible EventEmitter memory leak detected. "+s.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");u.name="MaxListenersExceededWarning",u.emitter=e,u.type=t,u.count=s.length,function(e){console&&console.warn&&console.warn(e)}(u)}return e}function h(e,t,n){var r={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},i=function(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,0===arguments.length?this.listener.call(this.target):this.listener.apply(this.target,arguments)}.bind(r);return i.listener=n,r.wrapFn=i,i}function p(e,t,n){var r=e._events;if(void 0===r)return[];var i=r[t];return void 0===i?[]:"function"==typeof i?n?[i.listener||i]:[i]:n?function(e){for(var t=new Array(e.length),n=0;n0&&(s=t[0]),s instanceof Error)throw s;var u=new Error("Unhandled error."+(s?" ("+s.message+")":""));throw u.context=s,u}var a=i[e];if(void 0===a)return!1;if("function"==typeof a)o(a,this,t);else{var l=a.length,c=m(a,l);for(n=0;n=0;o--)if(n[o]===t||n[o].listener===t){s=n[o].listener,i=o;break}if(i<0)return this;0===i?n.shift():function(e,t){for(;t+1=0;r--)this.removeListener(e,t[r]);return this},u.prototype.listeners=function(e){return p(this,e,!0)},u.prototype.rawListeners=function(e){return p(this,e,!1)},u.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):v.call(e,t)},u.prototype.listenerCount=v,u.prototype.eventNames=function(){return this._eventsCount>0?r(this._events):[]}},35:function(e,t,n){"use strict";n.r(t);var r=n(0),i={defaultOptions:{enableBTTVEmotes:!0,enableFrankerEmotes:!0,enableTwitchEmotes:!0,kappaFix:!0,theaterModeFix:!1,setAuthorColor:!1,showTimeStamp:!1,alternateLineColor:!1,hideAuthorIcons:!1,hideWelcomBanner:!1,setTwitchColors:!1,textSizeSlider:"inherit",setLiveChat:!0,allowTextSlider:!1}},o=()=>new Promise((e,t)=>{if(r.a.data.setupComplete)return r.a.set({options:Object.assign({},i.defaultOptions,r.a.data.options)}),e();const n=(t,i,o)=>("setupComplete"===t.name&&(chrome.runtime.onMessage.removeListener(n),r.a.set({setupComplete:!0}),e()),!0);chrome.tabs.create({url:"./html/welcome.html"}),chrome.runtime.onMessage.addListener(n),console.log("Setup Complete")});new class{constructor(){this.init=this.init.bind(this),r.a.on("ready",()=>{this.setupOptions(),o().then(this.init)})}init(){}setupOptions(){r.a.has("options")||r.a.set({options:i.defaultOptions})}}}}); \ No newline at end of file diff --git a/build/content.js b/build/content.js new file mode 100644 index 0000000..08f22e8 --- /dev/null +++ b/build/content.js @@ -0,0 +1 @@ +!function(t){var e={};function n(o){if(e[o])return e[o].exports;var r=e[o]={i:o,l:!1,exports:{}};return t[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=t,n.c=e,n.d=function(t,e,o){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:o})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)n.d(o,r,function(e){return t[e]}.bind(null,r));return o},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=34)}({0:function(t,e,n){"use strict";var o=class{get(t=null){return new Promise((e,n)=>{const o="string"==typeof t||"number"==typeof t;chrome.storage[this.store].get(t,n=>{e(o?n[t]:n)})})}getBytesInUse(t=null){return new Promise((e,n)=>{chrome.storage[this.store].getBytesInUse(t,e)})}set(t){return new Promise((e,n)=>{chrome.storage[this.store].set(t,e)})}remove(t){return new Promise((e,n)=>{chrome.storage[this.store].remove(t,e)})}clear(){return new Promise((t,e)=>{chrome.storage[this.store].clear(t)})}listen(t,e){"function"==typeof t&&(e=t,t=null),chrome.storage.onChanged.addListener((n,o)=>{if(o===this.store)if(null!==t){if(n.hasOwnProperty(t)){const o=n[t].oldValue||null,r=n[t].newValue||null;e(o,r)}}else e(n)})}};new class extends o{constructor(){super(),this.store="local"}};const r=new class extends o{constructor(){super(),this.store="sync"}};new class{create(t=null,e){return"object"==typeof t&&(e=t,t=null),new Promise((n,o)=>{chrome.notifications.create(t,e,n)})}update(t,e){return new Promise((n,o)=>{chrome.notifications.update(t,e,n)})}clear(t){return new Promise((e,n)=>{chrome.notifications.clear(t,e)})}getAll(){return new Promise((t,e)=>{chrome.notifications.getAll(t)})}getPermissionLevel(){return new Promise((t,e)=>{chrome.notifications.getPermissionLevel(t)})}listen(t,e=null,n){if("function"==typeof e&&(n=e,e=null),"onPermissionLevelChanged"===t||"onShowSettings"===t)return this._nonNotificationIdListen(t,n);const o=null!==e?(t,...o)=>{e===t&&n(t,...o)}:n;chrome.notifications[t].addListener(o)}_nonNotificationIdListen(t,e){chrome.notifications[t].addListener(e)}};var i=n(1);e.a=new class extends i.EventEmitter{constructor(){super(),this._data=null,this.state="initiating",this._init()}async _init(){const t=await r.get();this._initListener(),this._data=t,this.state="ready",this.emit(this.state)}_initListener(){r.listen(t=>{Object.keys(t).forEach(e=>{t[e].hasOwnProperty("newValue")?this._data[e]=t[e].newValue:console.error("No newValue in sync storge change")}),this.emit("change",this.data,t)})}set(t){return r.set(t)}get data(){return this._data}has(t){return this.data.hasOwnProperty(t)}}},1:function(t,e,n){"use strict";var o,r="object"==typeof Reflect?Reflect:null,i=r&&"function"==typeof r.apply?r.apply:function(t,e,n){return Function.prototype.apply.call(t,e,n)};o=r&&"function"==typeof r.ownKeys?r.ownKeys:Object.getOwnPropertySymbols?function(t){return Object.getOwnPropertyNames(t).concat(Object.getOwnPropertySymbols(t))}:function(t){return Object.getOwnPropertyNames(t)};var a=Number.isNaN||function(t){return t!=t};function s(){s.init.call(this)}t.exports=s,t.exports.once=function(t,e){return new Promise((function(n,o){function r(){void 0!==i&&t.removeListener("error",i),n([].slice.call(arguments))}var i;"error"!==e&&(i=function(n){t.removeListener(e,r),o(n)},t.once("error",i)),t.once(e,r)}))},s.EventEmitter=s,s.prototype._events=void 0,s.prototype._eventsCount=0,s.prototype._maxListeners=void 0;var c=10;function l(t){if("function"!=typeof t)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof t)}function h(t){return void 0===t._maxListeners?s.defaultMaxListeners:t._maxListeners}function d(t,e,n,o){var r,i,a;if(l(n),void 0===(i=t._events)?(i=t._events=Object.create(null),t._eventsCount=0):(void 0!==i.newListener&&(t.emit("newListener",e,n.listener?n.listener:n),i=t._events),a=i[e]),void 0===a)a=i[e]=n,++t._eventsCount;else if("function"==typeof a?a=i[e]=o?[n,a]:[a,n]:o?a.unshift(n):a.push(n),(r=h(t))>0&&a.length>r&&!a.warned){a.warned=!0;var s=new Error("Possible EventEmitter memory leak detected. "+a.length+" "+String(e)+" listeners added. Use emitter.setMaxListeners() to increase limit");s.name="MaxListenersExceededWarning",s.emitter=t,s.type=e,s.count=a.length,function(t){console&&console.warn&&console.warn(t)}(s)}return t}function u(t,e,n){var o={fired:!1,wrapFn:void 0,target:t,type:e,listener:n},r=function(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,0===arguments.length?this.listener.call(this.target):this.listener.apply(this.target,arguments)}.bind(o);return r.listener=n,o.wrapFn=r,r}function m(t,e,n){var o=t._events;if(void 0===o)return[];var r=o[e];return void 0===r?[]:"function"==typeof r?n?[r.listener||r]:[r]:n?function(t){for(var e=new Array(t.length),n=0;n0&&(a=e[0]),a instanceof Error)throw a;var s=new Error("Unhandled error."+(a?" ("+a.message+")":""));throw s.context=a,s}var c=r[t];if(void 0===c)return!1;if("function"==typeof c)i(c,this,e);else{var l=c.length,h=f(c,l);for(n=0;n=0;i--)if(n[i]===e||n[i].listener===e){a=n[i].listener,r=i;break}if(r<0)return this;0===r?n.shift():function(t,e){for(;e+1=0;o--)this.removeListener(t,e[o]);return this},s.prototype.listeners=function(t){return m(this,t,!0)},s.prototype.rawListeners=function(t){return m(this,t,!1)},s.listenerCount=function(t,e){return"function"==typeof t.listenerCount?t.listenerCount(e):p.call(t,e)},s.prototype.listenerCount=p,s.prototype.eventNames=function(){return this._eventsCount>0?o(this._events):[]}},10:function(t,e,n){var o=n(11);"string"==typeof o&&(o=[[t.i,o,""]]);n(4)(o,{hmr:!0,transform:void 0,insertInto:void 0}),o.locals&&(t.exports=o.locals)},11:function(t,e,n){(t.exports=n(3)(!1)).push([t.i,".chat-color-0 #content #author-name {\n color: #536dfe !important;\n}\n.chat-color-1 #content #author-name {\n color: #2196f3 !important;\n}\n.chat-color-2 #content #author-name {\n color: #03a9f4 !important;\n}\n.chat-color-3 #content #author-name {\n color: #00bcd4 !important;\n}\n.chat-color-4 #content #author-name {\n color: #009688 !important;\n}\n.chat-color-5 #content #author-name {\n color: #4caf50 !important;\n}\n.chat-color-6 #content #author-name {\n color: #8bc34a !important;\n}\n.chat-color-7 #content #author-name {\n color: #cddc39 !important;\n}\n.chat-color-8 #content #author-name {\n color: #ffeb3b !important;\n}\n.chat-color-9 #content #author-name {\n color: #ffc107 !important;\n}\n.chat-color-A #content #author-name {\n color: #f44336 !important;\n}\n.chat-color-B #content #author-name {\n color: #e91e63 !important;\n}\n.chat-color-C #content #author-name {\n color: #9c27b0 !important;\n}\n.chat-color-D #content #author-name {\n color: #673ab7 !important;\n}\n.chat-color-E #content #author-name {\n color: #536dfe !important;\n}\n.chat-color-F #content #author-name {\n color: #2196f3 !important;\n}\n.chat-color-G #content #author-name {\n color: #03a9f4 !important;\n}\n.chat-color-H #content #author-name {\n color: #00bcd4 !important;\n}\n.chat-color-I #content #author-name {\n color: #009688 !important;\n}\n.chat-color-J #content #author-name {\n color: #4caf50 !important;\n}\n.chat-color-K #content #author-name {\n color: #8bc34a !important;\n}\n.chat-color-L #content #author-name {\n color: #cddc39 !important;\n}\n.chat-color-M #content #author-name {\n color: #ffeb3b !important;\n}\n.chat-color-N #content #author-name {\n color: #ffc107 !important;\n}\n.chat-color-O #content #author-name {\n color: #ff9800 !important;\n}\n.chat-color-P #content #author-name {\n color: #ff5722 !important;\n}\n.chat-color-Q #content #author-name {\n color: #f44336 !important;\n}\n.chat-color-R #content #author-name {\n color: #e91e63 !important;\n}\n.chat-color-S #content #author-name {\n color: #9c27b0 !important;\n}\n.chat-color-T #content #author-name {\n color: #673ab7 !important;\n}\n.chat-color-U #content #author-name {\n color: #536dfe !important;\n}\n.chat-color-V #content #author-name {\n color: #2196f3 !important;\n}\n.chat-color-W #content #author-name {\n color: #03a9f4 !important;\n}\n.chat-color-X #content #author-name {\n color: #00bcd4 !important;\n}\n.chat-color-Y #content #author-name {\n color: #009688 !important;\n}\n.chat-color-Z #content #author-name {\n color: #4caf50 !important;\n}\n.chat-color-a #content #author-name {\n color: #8bc34a !important;\n}\n.chat-color-b #content #author-name {\n color: #cddc39 !important;\n}\n.chat-color-c #content #author-name {\n color: #ffeb3b !important;\n}\n.chat-color-d #content #author-name {\n color: #ffc107 !important;\n}\n.chat-color-e #content #author-name {\n color: #ff9800 !important;\n}\n.chat-color-f #content #author-name {\n color: #ff5722 !important;\n}\n.chat-color-g #content #author-name {\n color: #f44336 !important;\n}\n.chat-color-h #content #author-name {\n color: #e91e63 !important;\n}\n.chat-color-i #content #author-name {\n color: #9c27b0 !important;\n}\n.chat-color-j #content #author-name {\n color: #673ab7 !important;\n}\n.chat-color-k #content #author-name {\n color: #536dfe !important;\n}\n.chat-color-l #content #author-name {\n color: #2196f3 !important;\n}\n.chat-color-m #content #author-name {\n color: #03a9f4 !important;\n}\n.chat-color-n #content #author-name {\n color: #00bcd4 !important;\n}\n.chat-color-o #content #author-name {\n color: #009688 !important;\n}\n.chat-color-p #content #author-name {\n color: #4caf50 !important;\n}\n.chat-color-q #content #author-name {\n color: #8bc34a !important;\n}\n.chat-color-r #content #author-name {\n color: #cddc39 !important;\n}\n.chat-color-s #content #author-name {\n color: #ffeb3b !important;\n}\n.chat-color-t #content #author-name {\n color: #ffc107 !important;\n}\n.chat-color-u #content #author-name {\n color: #ff9800 !important;\n}\n.chat-color-v #content #author-name {\n color: #ff5722 !important;\n}\n.chat-color-w #content #author-name {\n color: #f44336 !important;\n}\n.chat-color-x #content #author-name {\n color: #e91e63 !important;\n}\n.chat-color-y #content #author-name {\n color: #9c27b0 !important;\n}\n.chat-color-z #content #author-name {\n color: #673ab7 !important;\n}\n.chat-color-- #content #author-name {\n color: #ff9800 !important;\n}\n.chat-color-_ #content #author-name {\n color: #ff5722 !important;\n}\n.AuthorFix #author-photo.yt-live-chat-text-message-renderer img.yt-img-shadow {\n display: inline-block;\n vertical-align: middle;\n border-radius: 50%;\n height: 1.5em;\n width: 1.5em;\n vertical-align: sub;\n}\n.AuthorFix #content {\n display: inline-block;\n vertical-align: middle;\n}\n.AuthorFix #timestamp.yt-live-chat-text-message-renderer {\n font-size: 1em;\n display: inline-block;\n vertical-align: middle;\n}\n.showTimeStamp #timestamp.yt-live-chat-text-message-renderer {\n display: inline-block;\n}\n.Emote img {\n height: 1.75em;\n align-self: center;\n vertical-align: sub;\n display: inline-block;\n vertical-align: middle;\n}\nemote_div:hover {\n background-size: 100%;\n background-color: rgba(255,255,255,0.6);\n}\n.hideElement {\n display: none !important;\n}\n.set-background-color-one {\n background-color: #303030 !important;\n}\n.set-background-color-two {\n background-color: transparent !important;\n}\n.setTwitchColors {\n text-shadow: 0 0 1px #000, 0 0 2px #000 !important;\n background: #18181b !important;\n font-family: 'Roboto' !important;\n font-size: 1.3rem !important;\n line-height: 1.5em !important;\n color: #fafafa !important;\n}\n.setTwitchColors #timestamp.yt-live-chat-text-message-renderer {\n display: none;\n}\n.setTwitchColors yt-live-chat-author-chip[is-highlighted] #author-name.owner.yt-live-chat-author-chip,\n.setTwitchColors #author-name.owner.yt-live-chat-author-chip {\n background-color: transparent;\n color: #008000;\n}\n.setTwitchColors yt-live-chat-author-chip[is-highlighted] #author-name.yt-live-chat-author-chip {\n background-color: transparent;\n}\n.emoteDivider {\n width: 60vw;\n border: 2px solid #d3d3d3;\n border-radius: 5px;\n margin-top: 2%;\n margin-bottom: 2%;\n margin-left: auto;\n margin-right: auto;\n}\n.emotePopUpText {\n margin-bottom: 2%;\n}\n.popup {\n background-color: #202020;\n position: absolute;\n top: 15%;\n left: 0;\n right: 0;\n margin-left: auto;\n margin-right: auto;\n height: 70%;\n width: 75%;\n z-index: 999;\n text-align: center;\n border-radius: 5px;\n border: #303030 1px solid;\n font-size: 1em;\n overflow: hidden;\n overflow-y: scroll;\n padding: 1%;\n padding-top: 2%;\n}\n.emoteButton {\n background-color: rgba(255,255,255,0.1);\n background-image: url(\"https://cdn.frankerfacez.com/emoticon/447885/4\");\n background-repeat: no-repeat;\n background-position: center;\n background-size: 80% 80%;\n width: var(--yt-live-chat-32px-icon-button_-_width);\n height: var(--yt-live-chat-32px-icon-button_-_height);\n padding: var(--yt-live-chat-32px-icon-button_-_padding);\n border-radius: 10px;\n border: none;\n cursor: pointer;\n}\n.emoteButton:hover {\n background-color: rgba(255,255,255,0.8);\n}\n.emoteButton:focus {\n outline: 0;\n}\n.body_Fix {\n height: 100% !important;\n margin: 0 !important;\n overflow: hidden !important;\n}\n.theater_wrapper_fix {\n padding: 2px;\n background-color: #1e1e1e;\n position: fixed;\n z-index: 900 !important;\n height: 100vh !important;\n width: 100vw !important;\n}\n.movie_player_fix {\n height: 100vh;\n position: absolute;\n width: calc(100vw - 25vw);\n}\n.movie_player_fix video {\n left: 0 !important;\n top: 0 !important;\n height: 100vh !important;\n width: calc(100vw - 25vw) !important;\n}\n.movie_player_fix #html5-video-player {\n top: 0 !important;\n width: calc(100vw - 25vw) !important;\n}\n.movie_player_fix .ytp-title {\n color: rgba(255,255,255,0.8) !important;\n}\n.movie_player_fix .ytp-title-channel {\n all: unset;\n}\n.movie_player_fix .ytp-gradient-top {\n max-width: calc(100vw - 25vw) !important;\n}\n.movie_player_fix .ytp-chrome-bottom {\n width: calc(100vw - 25vw) !important;\n left: 0 !important;\n}\n.movie_player_fix .html5-endscreen {\n width: calc(100vw - 25vw) !important;\n}\n.movie_player_fix .ytp-chapter-hover-container {\n width: calc(100vw - 25vw) !important;\n}\n.movie_player_fix .ytp-gradient-bottom {\n width: calc(100vw - 25vw) !important;\n}\n.movie_player_fix .ytp-iv-video-content {\n width: calc(100vw - 25vw) !important;\n left: 0 !important;\n}\n.movie_player_fix .ytp-player-content.ytp-iv-player-content {\n width: calc(100vw - 25vw) !important;\n left: -12px !important;\n bottom: 10vh !important;\n}\n.movie_player_fix .ytp-upnext.ytp-player-content.ytp-upnext-autoplay-paused.ytp-suggestion-set {\n width: calc(100vw - 25vw) !important;\n left: 0 !important;\n}\n.movie_player_fix .ytp-bezel-text-hide {\n width: calc(100vw - 25vw) !important;\n left: 0 !important;\n}\n.movie_player_fix .ytp-spinner {\n left: 40% !important;\n}\n.movie_player_fix .ytp-cued-thumbnail-overlay {\n width: calc(100vw - 25vw) !important;\n}\n.info_contents_fix {\n z-index: 901 !important;\n height: 80px;\n top: 0;\n position: absolute !important;\n width: calc(100vw - 25vw) !important;\n}\n.info_contents_fix ytd-video-primary-info-renderer {\n padding: 1rem;\n border-bottom: none;\n}\n.chat_frame_fix {\n height: 100vh !important;\n width: calc(calc(100vw - 75vw) - 1px) !important;\n position: absolute !important;\n right: 0px !important;\n top: 0px !important;\n border: 1px solid #4e4e4e;\n}\n",""])},3:function(t,e){t.exports=function(t){var e=[];return e.toString=function(){return this.map((function(e){var n=function(t,e){var n=t[1]||"",o=t[3];if(!o)return n;if(e&&"function"==typeof btoa){var r=function(t){return"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(t))))+" */"}(o),i=o.sources.map((function(t){return"/*# sourceURL="+o.sourceRoot+t+" */"}));return[n].concat(i).concat([r]).join("\n")}return[n].join("\n")}(e,t);return e[2]?"@media "+e[2]+"{"+n+"}":n})).join("")},e.i=function(t,n){"string"==typeof t&&(t=[[null,t,""]]);for(var o={},r=0;r\n ${this.code}\n \n `.trim()}},i=new class{constructor(){this.dictionary=new Map,this.twitch_Dictionary=new Map,this.bttv_Dictionary=new Map,this.franker_Dictionary=new Map,this.specialEmotesDictionary=new Map,this.init=this.init.bind(this)}init(){return Promise.all([o.a.data.options.enableBTTVEmotes&&this.loadBTTVEmote(),o.a.data.options.enableFrankerEmotes&&this.loadFrankerEmotes(),o.a.data.options.enableTwitchEmotes&&this.loadTwitchEmotes(),this.specialEmotes()])}get(t){return this.dictionary.get(t)}set(t,e){return this.dictionary.set(t,new r(e))}has(t){return this.dictionary.has(t)}bbtv_ToDict(t){for(let e=0;e{let e=!1;t.forEach(t=>{if(void 0!==t.removedNodes&&!(t.removedNodes.length<=0))for(let n=0,o=t.removedNodes.length;n',n.parentNode.replaceChild(t,n)}}}o.a.data.options.setAuthorColor&&"owner"!==this.node.getAttribute("author-type")&&this.setAuthorColor();var n=this.node.querySelector("#author-photo");o.a.data.options.hideAuthorIcons&&n.classList.add("hideElement"),this.node.querySelector("#timestamp"),o.a.data.options.showTimeStamp&&this.node.classList.add("showTimeStamp"),this.node.querySelector("#author-name").addEventListener("click",(function(){var t=document.querySelector("#input.yt-live-chat-text-input-field-renderer"),e=document.querySelector("#label.yt-live-chat-text-input-field-renderer");t.innerText="@"+this.innerText,t.innerText.length,t.focus(),e.innerText=""}));var r=o.a.data.options.textSizeSlider;o.a.data.options.allowTextSlider&&(this.node.setAttribute("style","font-size:"+r+"px!important"),this.node.classList.add("AuthorFix")),o.a.data.options.setTwitchColors&&(this.node.classList.add("setTwitchColors"),n.classList.add("hideElement")),o.a.data.options.alternateLineColor&&this.alternateLineColor()}setAuthorColor(){let t=null;if(this.node.hasChildNodes&&this.node.contains(this.node.querySelector("#author-photo"))&&null!=this.node.querySelector("#author-photo").querySelector("img").src){t=this.node.querySelector("#author-photo").querySelector("img").src;const e=/\/-([A-Za-z-_\d])/;try{if(null!==e.exec(t)){const n=e.exec(t)[1];this.node.classList.add("chat-color-"+n)}}catch(e){console.log(e),console.log(t)}}}alternateLineColor(){a%2==0&&this.node.classList.add("set-background-color-one"),a%2!=0&&this.node.classList.add("set-background-color-two"),a++}removelternateLineColor(){this.node.classList.remove("set-background-color-one"),this.node.classList.remove("set-background-color-two")}},c=n(1),l=n.n(c),h=class extends l.a{constructor(){super(),this.target=document.querySelector("head > title"),this.observer=null,this.init()}init(){this.observer=new MutationObserver(t=>{t.forEach(t=>{"YouTube Gaming"===t.target.innerText?this.emit("main"):this.emit("change")})}),null!==this.target&&this.observer.observe(this.target,{childList:!0,attributes:!1,characterData:!0,subtree:!0})}};const d=()=>{const t=document.querySelector(".ytp-time-display"),e=document.querySelector("yt-live-chat-app"),n=document.querySelector(".yt-live-chat-renderer-0"),o=t&&t.classList.contains("ytp-live"),r=document.body.contains(e)||document.body.contains(n);return o||r};let u=null;const m=document.createElement("theater_wrapper");document.body.appendChild(m);var p=!1;function f(){p?(console.log("enterTheater"),p=!1,v()):document.getElementById("player-theater-container").contains(document.getElementById("player-container"))?(console.log("exitTheater"),function(){const t=document.getElementById("movie_player"),e=document.getElementById("chatframe"),n=document.getElementById("info-contents"),o=document.getElementById("player-container"),r=document.getElementById("player-container-inner"),i=document.getElementById("chat"),a=document.getElementById("meta");document.getElementById("masthead-container").hidden=!1,m.classList.remove("theater_wrapper_fix"),t.classList.remove("movie_player_fix"),e.classList.remove("chat_frame_fix"),n.classList.remove("info_contents_fix"),o.prepend(t),r.prepend(o),i.prepend(e),a.before(n),document.body.classList.remove("body_Fix")}()):(console.log("enterTheater"),v())}function v(){const t=document.getElementById("movie_player"),e=document.getElementById("chatframe"),n=document.getElementById("info-contents");document.getElementById("masthead-container").hidden=!0,m.classList.add("theater_wrapper_fix"),t.classList.add("movie_player_fix"),e.classList.add("chat_frame_fix"),n.classList.add("info_contents_fix"),m.append(n),m.append(t),m.append(e),document.body.classList.add("body_Fix")}o.a.on("ready",()=>{u=new class{constructor(){this.chatWatcher=null,this.chatScroller=null,this.routeWatcher=null,this.onRouteChange=this.onRouteChange.bind(this),this.load()}load(){this.routeWatcher=new h,this.routeWatcher.on("change",this.onRouteChange),this.onRouteChange()}onRouteChange(){d()&&(!!document.querySelector("ytg-app")||!!window.frameElement||!window.frameElement&&window.location!=window.parent.location||!window.frameElement&&!!window.location.href.includes("is_popout=1")&&!!window.location.href.includes("popout=1"))&&this.init(),d()&&o.a.data.options.theaterModeFix&&null!=document.getElementById("player-container")&&null!=document.getElementById("player-theater-container")&&function(){var t=document.querySelector("button.ytp-size-button.ytp-button");t&&(document.getElementById("player-theater-container").contains(document.getElementById("player-container"))&&(p=!0,f()),t.addEventListener("click",f,!1))}()}init(){this.chatWatcher=new class{constructor(){this.watchChat=this.watchChat.bind(this),this._chatContainer=null,this._observer=null,this.messages=new Map}init(){return new Promise((t,e)=>{this.getChatContainer().then(i.init).then(()=>{this.addEmotePopup(),this.watchChat(),this.parsePreloadedMessages()})})}getChatContainer(){const t=(e,n)=>{this._chatContainer=document.querySelector("#items.style-scope.yt-live-chat-item-list-renderer"),null!==this._chatContainer?e():setTimeout(t.bind(this,e,n),250)};return new Promise(t)}parsePreloadedMessages(){const t=this._chatContainer.children;for(let e=t.length-1;e>=0;e--){const n=t[e];this.isMessageNode(n)&&new s(n)}}watchChat(){console.log("Chat observer started"),this._observer=new MutationObserver(t=>{t.forEach(t=>{const{addedNodes:e,removedNodes:n}=t;if(void 0!==e&&e.length>0)for(let t=0,n=e.length-1;t<=n;t++){const n=e[t];this.isMessageNode(n)&&this.onNewMessage(n)}if(void 0!==n&&n.length>0)for(let t=0,e=n.length-1;t<=e;t++){const e=n[t];this.isMessageNode(e)&&this.isObservedMessage(e)&&this.onObservedMessageRemoved(e)}})}),this._observer.observe(this._chatContainer,{childList:!0,attributes:!1,characterData:!1,subtree:!1})}onNewMessage(t){const e=new s(t);e.hasEmotes&&this.messages.set(e.id,e)}onObservedMessageRemoved(t){const e=t.getAttribute("message-id"),n=this.messages.get(e);null!=n&&n.destroy(),this.messages.delete(e)}isMessageNode(t){return"YT-LIVE-CHAT-TEXT-MESSAGE-RENDERER"===t.tagName}isObservedMessage(t){return null!==t.getAttribute("message-id")}addEmotePopup(){const t=document.createElement("button");t.classList.add("emoteButton"),t.textContent="";const e=document.getElementById("action-buttons");e.parentNode.insertBefore(t,e);const n=document.createElement("div");function r(t){var e=document.createElement("hr");e.classList.add("emoteDivider");for(let e=0;e{this.scroller.addEventListener("mouseenter",this.stop),this.start()})}start(){this.interval=setInterval(this.scroll,250)}stop(){clearInterval(this.interval)}scroll(){this.scroller.scrollTop=9999}getScroller(){const t=(e,n)=>{this.scroller=document.getElementById("item-scroller"),null!==this.scroller?e():setTimeout(t.bind(this,e,n),250)};return new Promise(t)}},this.chatScroller.init(),o.a.data.options.setLiveChat&&document.getElementsByClassName("yt-simple-endpoint style-scope yt-dropdown-menu").item(1).click(),console.log("INIT")}}})},4:function(t,e,n){var o={},r=function(t){var e;return function(){return void 0===e&&(e=t.apply(this,arguments)),e}}((function(){return window&&document&&document.all&&!window.atob})),i=function(t){var e={};return function(t,n){if("function"==typeof t)return t();if(void 0===e[t]){var o=function(t,e){return e?e.querySelector(t):document.querySelector(t)}.call(this,t,n);if(window.HTMLIFrameElement&&o instanceof window.HTMLIFrameElement)try{o=o.contentDocument.head}catch(t){o=null}e[t]=o}return e[t]}}(),a=null,s=0,c=[],l=n(5);function h(t,e){for(var n=0;n=0&&c.splice(e,1)}function p(t){var e=document.createElement("style");if(void 0===t.attrs.type&&(t.attrs.type="text/css"),void 0===t.attrs.nonce){var o=n.nc;o&&(t.attrs.nonce=o)}return f(e,t.attrs),u(t,e),e}function f(t,e){Object.keys(e).forEach((function(n){t.setAttribute(n,e[n])}))}function v(t,e){var n,o,r,i;if(e.transform&&t.css){if(!(i=e.transform(t.css)))return function(){};t.css=i}if(e.singleton){var c=s++;n=a||(a=p(e)),o=g.bind(null,n,c,!1),r=g.bind(null,n,c,!0)}else t.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=function(t){var e=document.createElement("link");return void 0===t.attrs.type&&(t.attrs.type="text/css"),t.attrs.rel="stylesheet",f(e,t.attrs),u(t,e),e}(e),o=function(t,e,n){var o=n.css,r=n.sourceMap,i=void 0===e.convertToAbsoluteUrls&&r;(e.convertToAbsoluteUrls||i)&&(o=l(o)),r&&(o+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(r))))+" */");var a=new Blob([o],{type:"text/css"}),s=t.href;t.href=URL.createObjectURL(a),s&&URL.revokeObjectURL(s)}.bind(null,n,e),r=function(){m(n),n.href&&URL.revokeObjectURL(n.href)}):(n=p(e),o=function(t,e){var n=e.css,o=e.media;if(o&&t.setAttribute("media",o),t.styleSheet)t.styleSheet.cssText=n;else{for(;t.firstChild;)t.removeChild(t.firstChild);t.appendChild(document.createTextNode(n))}}.bind(null,n),r=function(){m(n)});return o(t),function(e){if(e){if(e.css===t.css&&e.media===t.media&&e.sourceMap===t.sourceMap)return;o(t=e)}else r()}}t.exports=function(t,e){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");(e=e||{}).attrs="object"==typeof e.attrs?e.attrs:{},e.singleton||"boolean"==typeof e.singleton||(e.singleton=r()),e.insertInto||(e.insertInto="head"),e.insertAt||(e.insertAt="bottom");var n=d(t,e);return h(n,e),function(t){for(var r=[],i=0;i + + + + + Options + + + + + 🔴 + + +

Live Chat Options

+
+ + + + +
+
+ +
+
+

Emote Options

+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+ +
+
+
+
+
+
+ +
+ + +
+ +
+

Chat Options

+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+ +
+

Font Size

+ + + + + +
+
+
+ +
+
+ +
+
+ +
+
+
+
+
 
+ +
+ +
+ + + + + \ No newline at end of file diff --git a/build/html/welcome.html b/build/html/welcome.html new file mode 100644 index 0000000..e1564a7 --- /dev/null +++ b/build/html/welcome.html @@ -0,0 +1,96 @@ + + + + + + + Welcome Page + + + +
+ +
+ done +
+ +
+ +
+ + +

Welcome to the Chat

+ +

This is still very beta

+ +
+ + + +
+ +

+ Soon to come: +

+ +
    +
  • Specific channel Emotes
  • +
  • Search for Emote Panel
  • +
  • Autocomplete for emote Selection
  • +
  • Theater Mode Fix for that quality Stream and Chat time
  • +
  • Moderation Options
  • +
  • User Profile Info
  • +
  • Other Styling Options
  • +
+ +
+ +

How To:

+ +

+ There is still a lot of stuff I am working on. This is very Beta at the moment so +

+

Use At Your Own Risk

+

+ This is a Chrome Extension for Youtube Live Streams, adding some Quality of Life improvements for the Chat. + Adds Top, Trending and Global (500ish) Emotes from popular sites. These Update with what is Trending. +

+

+ Don't forget to pin this extension for easy access. +

+ pinYourExtension.gif +

+ Youtube Live is slow to load its pages currently. + Give the extension a moment while the page's iframes are loading. + Once you see the Emote Panel Icon you can open the Emote Selection Panel. +

+ emotesMenu.gif +

+ Enhanced Theater Mode Is Now Available. Just click the check in the option panel and refresh your page. +

+ theaterMode.gif +

+ Over around 500 Top and Trending Emotes are loaded from popular sites. + You can Enable/Disable them in the Options Menu. +

+ optionsMenu.gif +

+ Can Also Click on UserNames To Autofill an @ Notification +

+ clickUserNamesToAtThem.gif + +

Use At Your Own Risk

+ +

Enjoy!

+
+ + + + \ No newline at end of file diff --git a/build/manifest.json b/build/manifest.json new file mode 100644 index 0000000..6d74a33 --- /dev/null +++ b/build/manifest.json @@ -0,0 +1,48 @@ +{ + "manifest_version": 2, + + "name": "🔴 LIVE CHAT", + "version": "1.0.1", + "description": "Enhances the YouTube Live Streaming experience with Emotes, Custom Styling and quality of life improvements.", + "icons": { + "48": "assets/icons/icon48.png", + "128": "assets/icons/icon128.png", + "512": "assets/icons/icon512.png" + }, + + "permissions": [ + "storage", + "background" + ], + + "options_ui": { + "page": "html/options.html", + "chrome_style": true + }, + + "browser_action": { + "default_popup": "html/options.html", + "chrome_style": true + }, + + "background": { + "scripts": [ + "background.js" + ] + }, + + "content_scripts": [ + { + "matches": [ + "*://*.youtube.com/*" + ], + "js": [ "content.js" ], + "run_at": "document_end", + "all_frames": true + } + ], + + "web_accessible_resources": [ + "assets/*" + ] +} diff --git a/build/options.js b/build/options.js new file mode 100644 index 0000000..fdd66d1 --- /dev/null +++ b/build/options.js @@ -0,0 +1 @@ +!function(n){var t={};function e(r){if(t[r])return t[r].exports;var u=t[r]={i:r,l:!1,exports:{}};return n[r].call(u.exports,u,u.exports,e),u.l=!0,u.exports}e.m=n,e.c=t,e.d=function(n,t,r){e.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:r})},e.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},e.t=function(n,t){if(1&t&&(n=e(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var r=Object.create(null);if(e.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var u in n)e.d(r,u,function(t){return n[t]}.bind(null,u));return r},e.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return e.d(t,"a",t),t},e.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},e.p="",e(e.s=12)}([function(n,t,e){"use strict";var r=class{get(n=null){return new Promise((t,e)=>{const r="string"==typeof n||"number"==typeof n;chrome.storage[this.store].get(n,e=>{t(r?e[n]:e)})})}getBytesInUse(n=null){return new Promise((t,e)=>{chrome.storage[this.store].getBytesInUse(n,t)})}set(n){return new Promise((t,e)=>{chrome.storage[this.store].set(n,t)})}remove(n){return new Promise((t,e)=>{chrome.storage[this.store].remove(n,t)})}clear(){return new Promise((n,t)=>{chrome.storage[this.store].clear(n)})}listen(n,t){"function"==typeof n&&(t=n,n=null),chrome.storage.onChanged.addListener((e,r)=>{if(r===this.store)if(null!==n){if(e.hasOwnProperty(n)){const r=e[n].oldValue||null,u=e[n].newValue||null;t(r,u)}}else t(e)})}};new class extends r{constructor(){super(),this.store="local"}};const u=new class extends r{constructor(){super(),this.store="sync"}};new class{create(n=null,t){return"object"==typeof n&&(t=n,n=null),new Promise((e,r)=>{chrome.notifications.create(n,t,e)})}update(n,t){return new Promise((e,r)=>{chrome.notifications.update(n,t,e)})}clear(n){return new Promise((t,e)=>{chrome.notifications.clear(n,t)})}getAll(){return new Promise((n,t)=>{chrome.notifications.getAll(n)})}getPermissionLevel(){return new Promise((n,t)=>{chrome.notifications.getPermissionLevel(n)})}listen(n,t=null,e){if("function"==typeof t&&(e=t,t=null),"onPermissionLevelChanged"===n||"onShowSettings"===n)return this._nonNotificationIdListen(n,e);const r=null!==t?(n,...r)=>{t===n&&e(n,...r)}:e;chrome.notifications[n].addListener(r)}_nonNotificationIdListen(n,t){chrome.notifications[n].addListener(t)}};var i=e(1);t.a=new class extends i.EventEmitter{constructor(){super(),this._data=null,this.state="initiating",this._init()}async _init(){const n=await u.get();this._initListener(),this._data=n,this.state="ready",this.emit(this.state)}_initListener(){u.listen(n=>{Object.keys(n).forEach(t=>{n[t].hasOwnProperty("newValue")?this._data[t]=n[t].newValue:console.error("No newValue in sync storge change")}),this.emit("change",this.data,n)})}set(n){return u.set(n)}get data(){return this._data}has(n){return this.data.hasOwnProperty(n)}}},function(n,t,e){"use strict";var r,u="object"==typeof Reflect?Reflect:null,i=u&&"function"==typeof u.apply?u.apply:function(n,t,e){return Function.prototype.apply.call(n,t,e)};r=u&&"function"==typeof u.ownKeys?u.ownKeys:Object.getOwnPropertySymbols?function(n){return Object.getOwnPropertyNames(n).concat(Object.getOwnPropertySymbols(n))}:function(n){return Object.getOwnPropertyNames(n)};var o=Number.isNaN||function(n){return n!=n};function a(){a.init.call(this)}n.exports=a,n.exports.once=function(n,t){return new Promise((function(e,r){function u(){void 0!==i&&n.removeListener("error",i),e([].slice.call(arguments))}var i;"error"!==t&&(i=function(e){n.removeListener(t,u),r(e)},n.once("error",i)),n.once(t,u)}))},a.EventEmitter=a,a.prototype._events=void 0,a.prototype._eventsCount=0,a.prototype._maxListeners=void 0;var f=10;function c(n){if("function"!=typeof n)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof n)}function s(n){return void 0===n._maxListeners?a.defaultMaxListeners:n._maxListeners}function l(n,t,e,r){var u,i,o;if(c(e),void 0===(i=n._events)?(i=n._events=Object.create(null),n._eventsCount=0):(void 0!==i.newListener&&(n.emit("newListener",t,e.listener?e.listener:e),i=n._events),o=i[t]),void 0===o)o=i[t]=e,++n._eventsCount;else if("function"==typeof o?o=i[t]=r?[e,o]:[o,e]:r?o.unshift(e):o.push(e),(u=s(n))>0&&o.length>u&&!o.warned){o.warned=!0;var a=new Error("Possible EventEmitter memory leak detected. "+o.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");a.name="MaxListenersExceededWarning",a.emitter=n,a.type=t,a.count=o.length,function(n){console&&console.warn&&console.warn(n)}(a)}return n}function h(n,t,e){var r={fired:!1,wrapFn:void 0,target:n,type:t,listener:e},u=function(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,0===arguments.length?this.listener.call(this.target):this.listener.apply(this.target,arguments)}.bind(r);return u.listener=e,r.wrapFn=u,u}function p(n,t,e){var r=n._events;if(void 0===r)return[];var u=r[t];return void 0===u?[]:"function"==typeof u?e?[u.listener||u]:[u]:e?function(n){for(var t=new Array(n.length),e=0;e0&&(o=t[0]),o instanceof Error)throw o;var a=new Error("Unhandled error."+(o?" ("+o.message+")":""));throw a.context=o,a}var f=u[n];if(void 0===f)return!1;if("function"==typeof f)i(f,this,t);else{var c=f.length,s=d(f,c);for(e=0;e=0;i--)if(e[i]===t||e[i].listener===t){o=e[i].listener,u=i;break}if(u<0)return this;0===u?e.shift():function(n,t){for(;t+1=0;r--)this.removeListener(n,t[r]);return this},a.prototype.listeners=function(n){return p(this,n,!0)},a.prototype.rawListeners=function(n){return p(this,n,!1)},a.listenerCount=function(n,t){return"function"==typeof n.listenerCount?n.listenerCount(t):v.call(n,t)},a.prototype.listenerCount=v,a.prototype.eventNames=function(){return this._eventsCount>0?r(this._events):[]}},function(n,t,e){var r=e(17),u=e(7),i=36e5,o=6e4,a=/[T ]/,f=/:/,c=/^(\d{2})$/,s=[/^([+-]\d{2})$/,/^([+-]\d{3})$/,/^([+-]\d{4})$/],l=/^(\d{4})/,h=[/^([+-]\d{4})/,/^([+-]\d{5})/,/^([+-]\d{6})/],p=/^-(\d{2})$/,v=/^-?(\d{3})$/,d=/^-?(\d{2})-?(\d{2})$/,g=/^-?W(\d{2})$/,_=/^-?W(\d{2})-?(\d{1})$/,y=/^(\d{2}([.,]\d*)?)$/,m=/^(\d{2}):?(\d{2}([.,]\d*)?)$/,b=/^(\d{2}):?(\d{2}):?(\d{2}([.,]\d*)?)$/,w=/([Z+-].*)$/,x=/^(Z)$/,j=/^([+-])(\d{2})$/,S=/^([+-])(\d{2}):?(\d{2})$/;function O(n,t,e){t=t||0,e=e||0;var r=new Date(0);r.setUTCFullYear(n,0,4);var u=7*t+e+1-(r.getUTCDay()||7);return r.setUTCDate(r.getUTCDate()+u),r}n.exports=function(n,t){if(u(n))return new Date(n.getTime());if("string"!=typeof n)return new Date(n);var e=(t||{}).additionalDigits;e=null==e?2:Number(e);var L=function(n){var t,e={},r=n.split(a);if(f.test(r[0])?(e.date=null,t=r[0]):(e.date=r[0],t=r[1]),t){var u=w.exec(t);u?(e.time=t.replace(u[1],""),e.timezone=u[1]):e.time=t}return e}(n),A=function(n,t){var e,r=s[t],u=h[t];if(e=l.exec(n)||u.exec(n)){var i=e[1];return{year:parseInt(i,10),restDateString:n.slice(i.length)}}if(e=c.exec(n)||r.exec(n)){var o=e[1];return{year:100*parseInt(o,10),restDateString:n.slice(o.length)}}return{year:null}}(L.date,e),D=A.year,M=function(n,t){if(null===t)return null;var e,r,u;if(0===n.length)return(r=new Date(0)).setUTCFullYear(t),r;if(e=p.exec(n))return r=new Date(0),u=parseInt(e[1],10)-1,r.setUTCFullYear(t,u),r;if(e=v.exec(n)){r=new Date(0);var i=parseInt(e[1],10);return r.setUTCFullYear(t,0,i),r}if(e=d.exec(n)){r=new Date(0),u=parseInt(e[1],10)-1;var o=parseInt(e[2],10);return r.setUTCFullYear(t,u,o),r}return(e=g.exec(n))?O(t,parseInt(e[1],10)-1):(e=_.exec(n))?O(t,parseInt(e[1],10)-1,parseInt(e[2],10)-1):null}(A.restDateString,D);if(M){var T,E=M.getTime(),I=0;if(L.time&&(I=function(n){var t,e,r;if(t=y.exec(n))return(e=parseFloat(t[1].replace(",",".")))%24*i;if(t=m.exec(n))return e=parseInt(t[1],10),r=parseFloat(t[2].replace(",",".")),e%24*i+r*o;if(t=b.exec(n)){e=parseInt(t[1],10),r=parseInt(t[2],10);var u=parseFloat(t[3].replace(",","."));return e%24*i+r*o+1e3*u}return null}(L.time)),L.timezone)T=function(n){var t,e;return(t=x.exec(n))?0:(t=j.exec(n))?(e=60*parseInt(t[2],10),"+"===t[1]?-e:e):(t=S.exec(n))?(e=60*parseInt(t[2],10)+parseInt(t[3],10),"+"===t[1]?-e:e):0}(L.timezone)*o;else{var k=E+I,R=new Date(k);T=r(R);var C=new Date(k);C.setDate(R.getDate()+1);var z=r(C)-r(R);z>0&&(T+=z)}return new Date(E+I+T)}return new Date(n)}},function(n,t){n.exports=function(n){var t=[];return t.toString=function(){return this.map((function(t){var e=function(n,t){var e=n[1]||"",r=n[3];if(!r)return e;if(t&&"function"==typeof btoa){var u=function(n){return"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(n))))+" */"}(r),i=r.sources.map((function(n){return"/*# sourceURL="+r.sourceRoot+n+" */"}));return[e].concat(i).concat([u]).join("\n")}return[e].join("\n")}(t,n);return t[2]?"@media "+t[2]+"{"+e+"}":e})).join("")},t.i=function(n,e){"string"==typeof n&&(n=[[null,n,""]]);for(var r={},u=0;u=0&&f.splice(t,1)}function v(n){var t=document.createElement("style");if(void 0===n.attrs.type&&(n.attrs.type="text/css"),void 0===n.attrs.nonce){var r=e.nc;r&&(n.attrs.nonce=r)}return d(t,n.attrs),h(n,t),t}function d(n,t){Object.keys(t).forEach((function(e){n.setAttribute(e,t[e])}))}function g(n,t){var e,r,u,i;if(t.transform&&n.css){if(!(i=t.transform(n.css)))return function(){};n.css=i}if(t.singleton){var f=a++;e=o||(o=v(t)),r=y.bind(null,e,f,!1),u=y.bind(null,e,f,!0)}else n.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(e=function(n){var t=document.createElement("link");return void 0===n.attrs.type&&(n.attrs.type="text/css"),n.attrs.rel="stylesheet",d(t,n.attrs),h(n,t),t}(t),r=function(n,t,e){var r=e.css,u=e.sourceMap,i=void 0===t.convertToAbsoluteUrls&&u;(t.convertToAbsoluteUrls||i)&&(r=c(r)),u&&(r+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(u))))+" */");var o=new Blob([r],{type:"text/css"}),a=n.href;n.href=URL.createObjectURL(o),a&&URL.revokeObjectURL(a)}.bind(null,e,t),u=function(){p(e),e.href&&URL.revokeObjectURL(e.href)}):(e=v(t),r=function(n,t){var e=t.css,r=t.media;if(r&&n.setAttribute("media",r),n.styleSheet)n.styleSheet.cssText=e;else{for(;n.firstChild;)n.removeChild(n.firstChild);n.appendChild(document.createTextNode(e))}}.bind(null,e),u=function(){p(e)});return r(n),function(t){if(t){if(t.css===n.css&&t.media===n.media&&t.sourceMap===n.sourceMap)return;r(n=t)}else u()}}n.exports=function(n,t){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");(t=t||{}).attrs="object"==typeof t.attrs?t.attrs:{},t.singleton||"boolean"==typeof t.singleton||(t.singleton=u()),t.insertInto||(t.insertInto="head"),t.insertAt||(t.insertAt="bottom");var e=l(n,t);return s(e,t),function(n){for(var u=[],i=0;i=o.getTime()?e+1:t.getTime()>=f.getTime()?e:e-1}},function(n,t,e){(function(n,r){var u;(function(){var i,o="Expected a function",a="__lodash_hash_undefined__",f="__lodash_placeholder__",c=16,s=32,l=64,h=128,p=256,v=1/0,d=9007199254740991,g=NaN,_=4294967295,y=[["ary",h],["bind",1],["bindKey",2],["curry",8],["curryRight",c],["flip",512],["partial",s],["partialRight",l],["rearg",p]],m="[object Arguments]",b="[object Array]",w="[object Boolean]",x="[object Date]",j="[object Error]",S="[object Function]",O="[object GeneratorFunction]",L="[object Map]",A="[object Number]",D="[object Object]",M="[object RegExp]",T="[object Set]",E="[object String]",I="[object Symbol]",k="[object WeakMap]",R="[object ArrayBuffer]",C="[object DataView]",z="[object Float32Array]",U="[object Float64Array]",P="[object Int8Array]",W="[object Int16Array]",F="[object Int32Array]",$="[object Uint8Array]",B="[object Uint8ClampedArray]",N="[object Uint16Array]",Y="[object Uint32Array]",H=/\b__p \+= '';/g,Z=/\b(__p \+=) '' \+/g,q=/(__e\(.*?\)|\b__t\)) \+\n'';/g,G=/&(?:amp|lt|gt|quot|#39);/g,J=/[&<>"']/g,V=RegExp(G.source),K=RegExp(J.source),X=/<%-([\s\S]+?)%>/g,Q=/<%([\s\S]+?)%>/g,nn=/<%=([\s\S]+?)%>/g,tn=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,en=/^\w*$/,rn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,un=/[\\^$.*+?()[\]{}|]/g,on=RegExp(un.source),an=/^\s+|\s+$/g,fn=/^\s+/,cn=/\s+$/,sn=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,ln=/\{\n\/\* \[wrapped with (.+)\] \*/,hn=/,? & /,pn=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,vn=/\\(\\)?/g,dn=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,gn=/\w*$/,_n=/^[-+]0x[0-9a-f]+$/i,yn=/^0b[01]+$/i,mn=/^\[object .+?Constructor\]$/,bn=/^0o[0-7]+$/i,wn=/^(?:0|[1-9]\d*)$/,xn=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,jn=/($^)/,Sn=/['\n\r\u2028\u2029\\]/g,On="\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff",Ln="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",An="["+Ln+"]",Dn="["+On+"]",Mn="\\d+",Tn="[a-z\\xdf-\\xf6\\xf8-\\xff]",En="[^\\ud800-\\udfff"+Ln+Mn+"\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde]",In="\\ud83c[\\udffb-\\udfff]",kn="[^\\ud800-\\udfff]",Rn="(?:\\ud83c[\\udde6-\\uddff]){2}",Cn="[\\ud800-\\udbff][\\udc00-\\udfff]",zn="[A-Z\\xc0-\\xd6\\xd8-\\xde]",Un="(?:"+Tn+"|"+En+")",Pn="(?:"+zn+"|"+En+")",Wn="(?:"+Dn+"|"+In+")?",Fn="[\\ufe0e\\ufe0f]?"+Wn+"(?:\\u200d(?:"+[kn,Rn,Cn].join("|")+")[\\ufe0e\\ufe0f]?"+Wn+")*",$n="(?:"+["[\\u2700-\\u27bf]",Rn,Cn].join("|")+")"+Fn,Bn="(?:"+[kn+Dn+"?",Dn,Rn,Cn,"[\\ud800-\\udfff]"].join("|")+")",Nn=RegExp("['’]","g"),Yn=RegExp(Dn,"g"),Hn=RegExp(In+"(?="+In+")|"+Bn+Fn,"g"),Zn=RegExp([zn+"?"+Tn+"+(?:['’](?:d|ll|m|re|s|t|ve))?(?="+[An,zn,"$"].join("|")+")",Pn+"+(?:['’](?:D|LL|M|RE|S|T|VE))?(?="+[An,zn+Un,"$"].join("|")+")",zn+"?"+Un+"+(?:['’](?:d|ll|m|re|s|t|ve))?",zn+"+(?:['’](?:D|LL|M|RE|S|T|VE))?","\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",Mn,$n].join("|"),"g"),qn=RegExp("[\\u200d\\ud800-\\udfff"+On+"\\ufe0e\\ufe0f]"),Gn=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Jn=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],Vn=-1,Kn={};Kn[z]=Kn[U]=Kn[P]=Kn[W]=Kn[F]=Kn[$]=Kn[B]=Kn[N]=Kn[Y]=!0,Kn[m]=Kn[b]=Kn[R]=Kn[w]=Kn[C]=Kn[x]=Kn[j]=Kn[S]=Kn[L]=Kn[A]=Kn[D]=Kn[M]=Kn[T]=Kn[E]=Kn[k]=!1;var Xn={};Xn[m]=Xn[b]=Xn[R]=Xn[C]=Xn[w]=Xn[x]=Xn[z]=Xn[U]=Xn[P]=Xn[W]=Xn[F]=Xn[L]=Xn[A]=Xn[D]=Xn[M]=Xn[T]=Xn[E]=Xn[I]=Xn[$]=Xn[B]=Xn[N]=Xn[Y]=!0,Xn[j]=Xn[S]=Xn[k]=!1;var Qn={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},nt=parseFloat,tt=parseInt,et="object"==typeof n&&n&&n.Object===Object&&n,rt="object"==typeof self&&self&&self.Object===Object&&self,ut=et||rt||Function("return this")(),it=t&&!t.nodeType&&t,ot=it&&"object"==typeof r&&r&&!r.nodeType&&r,at=ot&&ot.exports===it,ft=at&&et.process,ct=function(){try{return ot&&ot.require&&ot.require("util").types||ft&&ft.binding&&ft.binding("util")}catch(n){}}(),st=ct&&ct.isArrayBuffer,lt=ct&&ct.isDate,ht=ct&&ct.isMap,pt=ct&&ct.isRegExp,vt=ct&&ct.isSet,dt=ct&&ct.isTypedArray;function gt(n,t,e){switch(e.length){case 0:return n.call(t);case 1:return n.call(t,e[0]);case 2:return n.call(t,e[0],e[1]);case 3:return n.call(t,e[0],e[1],e[2])}return n.apply(t,e)}function _t(n,t,e,r){for(var u=-1,i=null==n?0:n.length;++u-1}function jt(n,t,e){for(var r=-1,u=null==n?0:n.length;++r-1;);return e}function Ht(n,t){for(var e=n.length;e--&&It(t,n[e],0)>-1;);return e}var Zt=Ut({"À":"A","Á":"A","Â":"A","Ã":"A","Ä":"A","Å":"A","à":"a","á":"a","â":"a","ã":"a","ä":"a","å":"a","Ç":"C","ç":"c","Ð":"D","ð":"d","È":"E","É":"E","Ê":"E","Ë":"E","è":"e","é":"e","ê":"e","ë":"e","Ì":"I","Í":"I","Î":"I","Ï":"I","ì":"i","í":"i","î":"i","ï":"i","Ñ":"N","ñ":"n","Ò":"O","Ó":"O","Ô":"O","Õ":"O","Ö":"O","Ø":"O","ò":"o","ó":"o","ô":"o","õ":"o","ö":"o","ø":"o","Ù":"U","Ú":"U","Û":"U","Ü":"U","ù":"u","ú":"u","û":"u","ü":"u","Ý":"Y","ý":"y","ÿ":"y","Æ":"Ae","æ":"ae","Þ":"Th","þ":"th","ß":"ss","Ā":"A","Ă":"A","Ą":"A","ā":"a","ă":"a","ą":"a","Ć":"C","Ĉ":"C","Ċ":"C","Č":"C","ć":"c","ĉ":"c","ċ":"c","č":"c","Ď":"D","Đ":"D","ď":"d","đ":"d","Ē":"E","Ĕ":"E","Ė":"E","Ę":"E","Ě":"E","ē":"e","ĕ":"e","ė":"e","ę":"e","ě":"e","Ĝ":"G","Ğ":"G","Ġ":"G","Ģ":"G","ĝ":"g","ğ":"g","ġ":"g","ģ":"g","Ĥ":"H","Ħ":"H","ĥ":"h","ħ":"h","Ĩ":"I","Ī":"I","Ĭ":"I","Į":"I","İ":"I","ĩ":"i","ī":"i","ĭ":"i","į":"i","ı":"i","Ĵ":"J","ĵ":"j","Ķ":"K","ķ":"k","ĸ":"k","Ĺ":"L","Ļ":"L","Ľ":"L","Ŀ":"L","Ł":"L","ĺ":"l","ļ":"l","ľ":"l","ŀ":"l","ł":"l","Ń":"N","Ņ":"N","Ň":"N","Ŋ":"N","ń":"n","ņ":"n","ň":"n","ŋ":"n","Ō":"O","Ŏ":"O","Ő":"O","ō":"o","ŏ":"o","ő":"o","Ŕ":"R","Ŗ":"R","Ř":"R","ŕ":"r","ŗ":"r","ř":"r","Ś":"S","Ŝ":"S","Ş":"S","Š":"S","ś":"s","ŝ":"s","ş":"s","š":"s","Ţ":"T","Ť":"T","Ŧ":"T","ţ":"t","ť":"t","ŧ":"t","Ũ":"U","Ū":"U","Ŭ":"U","Ů":"U","Ű":"U","Ų":"U","ũ":"u","ū":"u","ŭ":"u","ů":"u","ű":"u","ų":"u","Ŵ":"W","ŵ":"w","Ŷ":"Y","ŷ":"y","Ÿ":"Y","Ź":"Z","Ż":"Z","Ž":"Z","ź":"z","ż":"z","ž":"z","IJ":"IJ","ij":"ij","Œ":"Oe","œ":"oe","ʼn":"'n","ſ":"s"}),qt=Ut({"&":"&","<":"<",">":">",'"':""","'":"'"});function Gt(n){return"\\"+Qn[n]}function Jt(n){return qn.test(n)}function Vt(n){var t=-1,e=Array(n.size);return n.forEach((function(n,r){e[++t]=[r,n]})),e}function Kt(n,t){return function(e){return n(t(e))}}function Xt(n,t){for(var e=-1,r=n.length,u=0,i=[];++e",""":'"',"'":"'"}),re=function n(t){var e=(t=null==t?ut:re.defaults(ut.Object(),t,re.pick(ut,Jn))).Array,r=t.Date,u=t.Error,On=t.Function,Ln=t.Math,An=t.Object,Dn=t.RegExp,Mn=t.String,Tn=t.TypeError,En=e.prototype,In=On.prototype,kn=An.prototype,Rn=t["__core-js_shared__"],Cn=In.toString,zn=kn.hasOwnProperty,Un=0,Pn=function(){var n=/[^.]+$/.exec(Rn&&Rn.keys&&Rn.keys.IE_PROTO||"");return n?"Symbol(src)_1."+n:""}(),Wn=kn.toString,Fn=Cn.call(An),$n=ut._,Bn=Dn("^"+Cn.call(zn).replace(un,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Hn=at?t.Buffer:i,qn=t.Symbol,Qn=t.Uint8Array,et=Hn?Hn.allocUnsafe:i,rt=Kt(An.getPrototypeOf,An),it=An.create,ot=kn.propertyIsEnumerable,ft=En.splice,ct=qn?qn.isConcatSpreadable:i,Mt=qn?qn.iterator:i,Ut=qn?qn.toStringTag:i,ue=function(){try{var n=ai(An,"defineProperty");return n({},"",{}),n}catch(n){}}(),ie=t.clearTimeout!==ut.clearTimeout&&t.clearTimeout,oe=r&&r.now!==ut.Date.now&&r.now,ae=t.setTimeout!==ut.setTimeout&&t.setTimeout,fe=Ln.ceil,ce=Ln.floor,se=An.getOwnPropertySymbols,le=Hn?Hn.isBuffer:i,he=t.isFinite,pe=En.join,ve=Kt(An.keys,An),de=Ln.max,ge=Ln.min,_e=r.now,ye=t.parseInt,me=Ln.random,be=En.reverse,we=ai(t,"DataView"),xe=ai(t,"Map"),je=ai(t,"Promise"),Se=ai(t,"Set"),Oe=ai(t,"WeakMap"),Le=ai(An,"create"),Ae=Oe&&new Oe,De={},Me=ki(we),Te=ki(xe),Ee=ki(je),Ie=ki(Se),ke=ki(Oe),Re=qn?qn.prototype:i,Ce=Re?Re.valueOf:i,ze=Re?Re.toString:i;function Ue(n){if(Ko(n)&&!Fo(n)&&!(n instanceof $e)){if(n instanceof Fe)return n;if(zn.call(n,"__wrapped__"))return Ri(n)}return new Fe(n)}var Pe=function(){function n(){}return function(t){if(!Vo(t))return{};if(it)return it(t);n.prototype=t;var e=new n;return n.prototype=i,e}}();function We(){}function Fe(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=i}function $e(n){this.__wrapped__=n,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=_,this.__views__=[]}function Be(n){var t=-1,e=null==n?0:n.length;for(this.clear();++t=t?n:t)),n}function ir(n,t,e,r,u,o){var a,f=1&t,c=2&t,s=4&t;if(e&&(a=u?e(n,r,u,o):e(n)),a!==i)return a;if(!Vo(n))return n;var l=Fo(n);if(l){if(a=function(n){var t=n.length,e=new n.constructor(t);return t&&"string"==typeof n[0]&&zn.call(n,"index")&&(e.index=n.index,e.input=n.input),e}(n),!f)return Ou(n,a)}else{var h=si(n),p=h==S||h==O;if(Yo(n))return mu(n,f);if(h==D||h==m||p&&!u){if(a=c||p?{}:hi(n),!f)return c?function(n,t){return Lu(n,ci(n),t)}(n,function(n,t){return n&&Lu(t,Da(t),n)}(a,n)):function(n,t){return Lu(n,fi(n),t)}(n,tr(a,n))}else{if(!Xn[h])return u?n:{};a=function(n,t,e){var r=n.constructor;switch(t){case R:return bu(n);case w:case x:return new r(+n);case C:return function(n,t){var e=t?bu(n.buffer):n.buffer;return new n.constructor(e,n.byteOffset,n.byteLength)}(n,e);case z:case U:case P:case W:case F:case $:case B:case N:case Y:return wu(n,e);case L:return new r;case A:case E:return new r(n);case M:return function(n){var t=new n.constructor(n.source,gn.exec(n));return t.lastIndex=n.lastIndex,t}(n);case T:return new r;case I:return function(n){return Ce?An(Ce.call(n)):{}}(n)}}(n,h,f)}}o||(o=new Ze);var v=o.get(n);if(v)return v;o.set(n,a),ea(n)?n.forEach((function(r){a.add(ir(r,t,e,r,n,o))})):Xo(n)&&n.forEach((function(r,u){a.set(u,ir(r,t,e,u,n,o))}));var d=l?i:(s?c?ni:Qu:c?Da:Aa)(n);return yt(d||n,(function(r,u){d&&(r=n[u=r]),Xe(a,u,ir(r,t,e,u,n,o))})),a}function or(n,t,e){var r=e.length;if(null==n)return!r;for(n=An(n);r--;){var u=e[r],o=t[u],a=n[u];if(a===i&&!(u in n)||!o(a))return!1}return!0}function ar(n,t,e){if("function"!=typeof n)throw new Tn(o);return Li((function(){n.apply(i,e)}),t)}function fr(n,t,e,r){var u=-1,i=xt,o=!0,a=n.length,f=[],c=t.length;if(!a)return f;e&&(t=St(t,$t(e))),r?(i=jt,o=!1):t.length>=200&&(i=Nt,o=!1,t=new He(t));n:for(;++u-1},Ne.prototype.set=function(n,t){var e=this.__data__,r=Qe(e,n);return r<0?(++this.size,e.push([n,t])):e[r][1]=t,this},Ye.prototype.clear=function(){this.size=0,this.__data__={hash:new Be,map:new(xe||Ne),string:new Be}},Ye.prototype.delete=function(n){var t=ii(this,n).delete(n);return this.size-=t?1:0,t},Ye.prototype.get=function(n){return ii(this,n).get(n)},Ye.prototype.has=function(n){return ii(this,n).has(n)},Ye.prototype.set=function(n,t){var e=ii(this,n),r=e.size;return e.set(n,t),this.size+=e.size==r?0:1,this},He.prototype.add=He.prototype.push=function(n){return this.__data__.set(n,a),this},He.prototype.has=function(n){return this.__data__.has(n)},Ze.prototype.clear=function(){this.__data__=new Ne,this.size=0},Ze.prototype.delete=function(n){var t=this.__data__,e=t.delete(n);return this.size=t.size,e},Ze.prototype.get=function(n){return this.__data__.get(n)},Ze.prototype.has=function(n){return this.__data__.has(n)},Ze.prototype.set=function(n,t){var e=this.__data__;if(e instanceof Ne){var r=e.__data__;if(!xe||r.length<199)return r.push([n,t]),this.size=++e.size,this;e=this.__data__=new Ye(r)}return e.set(n,t),this.size=e.size,this};var cr=Mu(_r),sr=Mu(yr,!0);function lr(n,t){var e=!0;return cr(n,(function(n,r,u){return e=!!t(n,r,u)})),e}function hr(n,t,e){for(var r=-1,u=n.length;++r0&&e(a)?t>1?vr(a,t-1,e,r,u):Ot(u,a):r||(u[u.length]=a)}return u}var dr=Tu(),gr=Tu(!0);function _r(n,t){return n&&dr(n,t,Aa)}function yr(n,t){return n&&gr(n,t,Aa)}function mr(n,t){return wt(t,(function(t){return qo(n[t])}))}function br(n,t){for(var e=0,r=(t=du(t,n)).length;null!=n&&et}function Sr(n,t){return null!=n&&zn.call(n,t)}function Or(n,t){return null!=n&&t in An(n)}function Lr(n,t,r){for(var u=r?jt:xt,o=n[0].length,a=n.length,f=a,c=e(a),s=1/0,l=[];f--;){var h=n[f];f&&t&&(h=St(h,$t(t))),s=ge(h.length,s),c[f]=!r&&(t||o>=120&&h.length>=120)?new He(f&&h):i}h=n[0];var p=-1,v=c[0];n:for(;++p=a?f:f*("desc"==e[r]?-1:1)}return n.index-t.index}(n,t,e)}))}function $r(n,t,e){for(var r=-1,u=t.length,i={};++r-1;)a!==n&&ft.call(a,f,1),ft.call(n,f,1);return n}function Nr(n,t){for(var e=n?t.length:0,r=e-1;e--;){var u=t[e];if(e==r||u!==i){var i=u;vi(u)?ft.call(n,u,1):au(n,u)}}return n}function Yr(n,t){return n+ce(me()*(t-n+1))}function Hr(n,t){var e="";if(!n||t<1||t>d)return e;do{t%2&&(e+=n),(t=ce(t/2))&&(n+=n)}while(t);return e}function Zr(n,t){return Ai(xi(n,t,Qa),n+"")}function qr(n){return Ge(za(n))}function Gr(n,t){var e=za(n);return Ti(e,ur(t,0,e.length))}function Jr(n,t,e,r){if(!Vo(n))return n;for(var u=-1,o=(t=du(t,n)).length,a=o-1,f=n;null!=f&&++ui?0:i+t),(r=r>i?i:r)<0&&(r+=i),i=t>r?0:r-t>>>0,t>>>=0;for(var o=e(i);++u>>1,o=n[i];null!==o&&!ua(o)&&(e?o<=t:o=200){var c=t?null:Hu(n);if(c)return Qt(c);o=!1,u=Nt,f=new He}else f=t?[]:a;n:for(;++r=r?n:Qr(n,t,e)}var yu=ie||function(n){return ut.clearTimeout(n)};function mu(n,t){if(t)return n.slice();var e=n.length,r=et?et(e):new n.constructor(e);return n.copy(r),r}function bu(n){var t=new n.constructor(n.byteLength);return new Qn(t).set(new Qn(n)),t}function wu(n,t){var e=t?bu(n.buffer):n.buffer;return new n.constructor(e,n.byteOffset,n.length)}function xu(n,t){if(n!==t){var e=n!==i,r=null===n,u=n==n,o=ua(n),a=t!==i,f=null===t,c=t==t,s=ua(t);if(!f&&!s&&!o&&n>t||o&&a&&c&&!f&&!s||r&&a&&c||!e&&c||!u)return 1;if(!r&&!o&&!s&&n1?e[u-1]:i,a=u>2?e[2]:i;for(o=n.length>3&&"function"==typeof o?(u--,o):i,a&&di(e[0],e[1],a)&&(o=u<3?i:o,u=1),t=An(t);++r-1?u[o?t[a]:a]:i}}function Cu(n){return Xu((function(t){var e=t.length,r=e,u=Fe.prototype.thru;for(n&&t.reverse();r--;){var a=t[r];if("function"!=typeof a)throw new Tn(o);if(u&&!f&&"wrapper"==ei(a))var f=new Fe([],!0)}for(r=f?r:e;++r1&&b.reverse(),p&&sf))return!1;var s=o.get(n),l=o.get(t);if(s&&l)return s==t&&l==n;var h=-1,p=!0,v=2&e?new He:i;for(o.set(n,t),o.set(t,n);++h-1&&n%1==0&&n1?"& ":"")+t[r],t=t.join(e>2?", ":" "),n.replace(sn,"{\n/* [wrapped with "+t+"] */\n")}(r,function(n,t){return yt(y,(function(e){var r="_."+e[0];t&e[1]&&!xt(n,r)&&n.push(r)})),n.sort()}(function(n){var t=n.match(ln);return t?t[1].split(hn):[]}(r),e)))}function Mi(n){var t=0,e=0;return function(){var r=_e(),u=16-(r-e);if(e=r,u>0){if(++t>=800)return arguments[0]}else t=0;return n.apply(i,arguments)}}function Ti(n,t){var e=-1,r=n.length,u=r-1;for(t=t===i?r:t;++e1?n[t-1]:i;return no(n,e="function"==typeof e?(n.pop(),e):i)}));function ao(n){var t=Ue(n);return t.__chain__=!0,t}function fo(n,t){return t(n)}var co=Xu((function(n){var t=n.length,e=t?n[0]:0,r=this.__wrapped__,u=function(t){return rr(t,n)};return!(t>1||this.__actions__.length)&&r instanceof $e&&vi(e)?((r=r.slice(e,+e+(t?1:0))).__actions__.push({func:fo,args:[u],thisArg:i}),new Fe(r,this.__chain__).thru((function(n){return t&&!n.length&&n.push(i),n}))):this.thru(u)})),so=Au((function(n,t,e){zn.call(n,e)?++n[e]:er(n,e,1)})),lo=Ru(Pi),ho=Ru(Wi);function po(n,t){return(Fo(n)?yt:cr)(n,ui(t,3))}function vo(n,t){return(Fo(n)?mt:sr)(n,ui(t,3))}var go=Au((function(n,t,e){zn.call(n,e)?n[e].push(t):er(n,e,[t])})),_o=Zr((function(n,t,r){var u=-1,i="function"==typeof t,o=Bo(n)?e(n.length):[];return cr(n,(function(n){o[++u]=i?gt(t,n,r):Ar(n,t,r)})),o})),yo=Au((function(n,t,e){er(n,e,t)}));function mo(n,t){return(Fo(n)?St:Cr)(n,ui(t,3))}var bo=Au((function(n,t,e){n[e?0:1].push(t)}),(function(){return[[],[]]})),wo=Zr((function(n,t){if(null==n)return[];var e=t.length;return e>1&&di(n,t[0],t[1])?t=[]:e>2&&di(t[0],t[1],t[2])&&(t=[t[0]]),Fr(n,vr(t,1),[])})),xo=oe||function(){return ut.Date.now()};function jo(n,t,e){return t=e?i:t,t=n&&null==t?n.length:t,qu(n,h,i,i,i,i,t)}function So(n,t){var e;if("function"!=typeof t)throw new Tn(o);return n=sa(n),function(){return--n>0&&(e=t.apply(this,arguments)),n<=1&&(t=i),e}}var Oo=Zr((function(n,t,e){var r=1;if(e.length){var u=Xt(e,ri(Oo));r|=s}return qu(n,r,t,e,u)})),Lo=Zr((function(n,t,e){var r=3;if(e.length){var u=Xt(e,ri(Lo));r|=s}return qu(t,r,n,e,u)}));function Ao(n,t,e){var r,u,a,f,c,s,l=0,h=!1,p=!1,v=!0;if("function"!=typeof n)throw new Tn(o);function d(t){var e=r,o=u;return r=u=i,l=t,f=n.apply(o,e)}function g(n){var e=n-s;return s===i||e>=t||e<0||p&&n-l>=a}function _(){var n=xo();if(g(n))return y(n);c=Li(_,function(n){var e=t-(n-s);return p?ge(e,a-(n-l)):e}(n))}function y(n){return c=i,v&&r?d(n):(r=u=i,f)}function m(){var n=xo(),e=g(n);if(r=arguments,u=this,s=n,e){if(c===i)return function(n){return l=n,c=Li(_,t),h?d(n):f}(s);if(p)return yu(c),c=Li(_,t),d(s)}return c===i&&(c=Li(_,t)),f}return t=ha(t)||0,Vo(e)&&(h=!!e.leading,a=(p="maxWait"in e)?de(ha(e.maxWait)||0,t):a,v="trailing"in e?!!e.trailing:v),m.cancel=function(){c!==i&&yu(c),l=0,r=s=u=c=i},m.flush=function(){return c===i?f:y(xo())},m}var Do=Zr((function(n,t){return ar(n,1,t)})),Mo=Zr((function(n,t,e){return ar(n,ha(t)||0,e)}));function To(n,t){if("function"!=typeof n||null!=t&&"function"!=typeof t)throw new Tn(o);var e=function(){var r=arguments,u=t?t.apply(this,r):r[0],i=e.cache;if(i.has(u))return i.get(u);var o=n.apply(this,r);return e.cache=i.set(u,o)||i,o};return e.cache=new(To.Cache||Ye),e}function Eo(n){if("function"!=typeof n)throw new Tn(o);return function(){var t=arguments;switch(t.length){case 0:return!n.call(this);case 1:return!n.call(this,t[0]);case 2:return!n.call(this,t[0],t[1]);case 3:return!n.call(this,t[0],t[1],t[2])}return!n.apply(this,t)}}To.Cache=Ye;var Io=gu((function(n,t){var e=(t=1==t.length&&Fo(t[0])?St(t[0],$t(ui())):St(vr(t,1),$t(ui()))).length;return Zr((function(r){for(var u=-1,i=ge(r.length,e);++u=t})),Wo=Dr(function(){return arguments}())?Dr:function(n){return Ko(n)&&zn.call(n,"callee")&&!ot.call(n,"callee")},Fo=e.isArray,$o=st?$t(st):function(n){return Ko(n)&&xr(n)==R};function Bo(n){return null!=n&&Jo(n.length)&&!qo(n)}function No(n){return Ko(n)&&Bo(n)}var Yo=le||pf,Ho=lt?$t(lt):function(n){return Ko(n)&&xr(n)==x};function Zo(n){if(!Ko(n))return!1;var t=xr(n);return t==j||"[object DOMException]"==t||"string"==typeof n.message&&"string"==typeof n.name&&!na(n)}function qo(n){if(!Vo(n))return!1;var t=xr(n);return t==S||t==O||"[object AsyncFunction]"==t||"[object Proxy]"==t}function Go(n){return"number"==typeof n&&n==sa(n)}function Jo(n){return"number"==typeof n&&n>-1&&n%1==0&&n<=d}function Vo(n){var t=typeof n;return null!=n&&("object"==t||"function"==t)}function Ko(n){return null!=n&&"object"==typeof n}var Xo=ht?$t(ht):function(n){return Ko(n)&&si(n)==L};function Qo(n){return"number"==typeof n||Ko(n)&&xr(n)==A}function na(n){if(!Ko(n)||xr(n)!=D)return!1;var t=rt(n);if(null===t)return!0;var e=zn.call(t,"constructor")&&t.constructor;return"function"==typeof e&&e instanceof e&&Cn.call(e)==Fn}var ta=pt?$t(pt):function(n){return Ko(n)&&xr(n)==M},ea=vt?$t(vt):function(n){return Ko(n)&&si(n)==T};function ra(n){return"string"==typeof n||!Fo(n)&&Ko(n)&&xr(n)==E}function ua(n){return"symbol"==typeof n||Ko(n)&&xr(n)==I}var ia=dt?$t(dt):function(n){return Ko(n)&&Jo(n.length)&&!!Kn[xr(n)]},oa=Bu(Rr),aa=Bu((function(n,t){return n<=t}));function fa(n){if(!n)return[];if(Bo(n))return ra(n)?te(n):Ou(n);if(Mt&&n[Mt])return function(n){for(var t,e=[];!(t=n.next()).done;)e.push(t.value);return e}(n[Mt]());var t=si(n);return(t==L?Vt:t==T?Qt:za)(n)}function ca(n){return n?(n=ha(n))===v||n===-v?17976931348623157e292*(n<0?-1:1):n==n?n:0:0===n?n:0}function sa(n){var t=ca(n),e=t%1;return t==t?e?t-e:t:0}function la(n){return n?ur(sa(n),0,_):0}function ha(n){if("number"==typeof n)return n;if(ua(n))return g;if(Vo(n)){var t="function"==typeof n.valueOf?n.valueOf():n;n=Vo(t)?t+"":t}if("string"!=typeof n)return 0===n?n:+n;n=n.replace(an,"");var e=yn.test(n);return e||bn.test(n)?tt(n.slice(2),e?2:8):_n.test(n)?g:+n}function pa(n){return Lu(n,Da(n))}function va(n){return null==n?"":iu(n)}var da=Du((function(n,t){if(mi(t)||Bo(t))Lu(t,Aa(t),n);else for(var e in t)zn.call(t,e)&&Xe(n,e,t[e])})),ga=Du((function(n,t){Lu(t,Da(t),n)})),_a=Du((function(n,t,e,r){Lu(t,Da(t),n,r)})),ya=Du((function(n,t,e,r){Lu(t,Aa(t),n,r)})),ma=Xu(rr),ba=Zr((function(n,t){n=An(n);var e=-1,r=t.length,u=r>2?t[2]:i;for(u&&di(t[0],t[1],u)&&(r=1);++e1),t})),Lu(n,ni(n),e),r&&(e=ir(e,7,Vu));for(var u=t.length;u--;)au(e,t[u]);return e})),Ia=Xu((function(n,t){return null==n?{}:function(n,t){return $r(n,t,(function(t,e){return ja(n,e)}))}(n,t)}));function ka(n,t){if(null==n)return{};var e=St(ni(n),(function(n){return[n]}));return t=ui(t),$r(n,e,(function(n,e){return t(n,e[0])}))}var Ra=Zu(Aa),Ca=Zu(Da);function za(n){return null==n?[]:Bt(n,Aa(n))}var Ua=Iu((function(n,t,e){return t=t.toLowerCase(),n+(e?Pa(t):t)}));function Pa(n){return Za(va(n).toLowerCase())}function Wa(n){return(n=va(n))&&n.replace(xn,Zt).replace(Yn,"")}var Fa=Iu((function(n,t,e){return n+(e?"-":"")+t.toLowerCase()})),$a=Iu((function(n,t,e){return n+(e?" ":"")+t.toLowerCase()})),Ba=Eu("toLowerCase"),Na=Iu((function(n,t,e){return n+(e?"_":"")+t.toLowerCase()})),Ya=Iu((function(n,t,e){return n+(e?" ":"")+Za(t)})),Ha=Iu((function(n,t,e){return n+(e?" ":"")+t.toUpperCase()})),Za=Eu("toUpperCase");function qa(n,t,e){return n=va(n),(t=e?i:t)===i?function(n){return Gn.test(n)}(n)?function(n){return n.match(Zn)||[]}(n):function(n){return n.match(pn)||[]}(n):n.match(t)||[]}var Ga=Zr((function(n,t){try{return gt(n,i,t)}catch(n){return Zo(n)?n:new u(n)}})),Ja=Xu((function(n,t){return yt(t,(function(t){t=Ii(t),er(n,t,Oo(n[t],n))})),n}));function Va(n){return function(){return n}}var Ka=Cu(),Xa=Cu(!0);function Qa(n){return n}function nf(n){return Ir("function"==typeof n?n:ir(n,1))}var tf=Zr((function(n,t){return function(e){return Ar(e,n,t)}})),ef=Zr((function(n,t){return function(e){return Ar(n,e,t)}}));function rf(n,t,e){var r=Aa(t),u=mr(t,r);null!=e||Vo(t)&&(u.length||!r.length)||(e=t,t=n,n=this,u=mr(t,Aa(t)));var i=!(Vo(e)&&"chain"in e&&!e.chain),o=qo(n);return yt(u,(function(e){var r=t[e];n[e]=r,o&&(n.prototype[e]=function(){var t=this.__chain__;if(i||t){var e=n(this.__wrapped__);return(e.__actions__=Ou(this.__actions__)).push({func:r,args:arguments,thisArg:n}),e.__chain__=t,e}return r.apply(n,Ot([this.value()],arguments))})})),n}function uf(){}var of=Wu(St),af=Wu(bt),ff=Wu(Dt);function cf(n){return gi(n)?zt(Ii(n)):function(n){return function(t){return br(t,n)}}(n)}var sf=$u(),lf=$u(!0);function hf(){return[]}function pf(){return!1}var vf=Pu((function(n,t){return n+t}),0),df=Yu("ceil"),gf=Pu((function(n,t){return n/t}),1),_f=Yu("floor"),yf=Pu((function(n,t){return n*t}),1),mf=Yu("round"),bf=Pu((function(n,t){return n-t}),0);return Ue.after=function(n,t){if("function"!=typeof t)throw new Tn(o);return n=sa(n),function(){if(--n<1)return t.apply(this,arguments)}},Ue.ary=jo,Ue.assign=da,Ue.assignIn=ga,Ue.assignInWith=_a,Ue.assignWith=ya,Ue.at=ma,Ue.before=So,Ue.bind=Oo,Ue.bindAll=Ja,Ue.bindKey=Lo,Ue.castArray=function(){if(!arguments.length)return[];var n=arguments[0];return Fo(n)?n:[n]},Ue.chain=ao,Ue.chunk=function(n,t,r){t=(r?di(n,t,r):t===i)?1:de(sa(t),0);var u=null==n?0:n.length;if(!u||t<1)return[];for(var o=0,a=0,f=e(fe(u/t));ou?0:u+e),(r=r===i||r>u?u:sa(r))<0&&(r+=u),r=e>r?0:la(r);e>>0)?(n=va(n))&&("string"==typeof t||null!=t&&!ta(t))&&!(t=iu(t))&&Jt(n)?_u(te(n),0,e):n.split(t,e):[]},Ue.spread=function(n,t){if("function"!=typeof n)throw new Tn(o);return t=null==t?0:de(sa(t),0),Zr((function(e){var r=e[t],u=_u(e,0,t);return r&&Ot(u,r),gt(n,this,u)}))},Ue.tail=function(n){var t=null==n?0:n.length;return t?Qr(n,1,t):[]},Ue.take=function(n,t,e){return n&&n.length?Qr(n,0,(t=e||t===i?1:sa(t))<0?0:t):[]},Ue.takeRight=function(n,t,e){var r=null==n?0:n.length;return r?Qr(n,(t=r-(t=e||t===i?1:sa(t)))<0?0:t,r):[]},Ue.takeRightWhile=function(n,t){return n&&n.length?cu(n,ui(t,3),!1,!0):[]},Ue.takeWhile=function(n,t){return n&&n.length?cu(n,ui(t,3)):[]},Ue.tap=function(n,t){return t(n),n},Ue.throttle=function(n,t,e){var r=!0,u=!0;if("function"!=typeof n)throw new Tn(o);return Vo(e)&&(r="leading"in e?!!e.leading:r,u="trailing"in e?!!e.trailing:u),Ao(n,t,{leading:r,maxWait:t,trailing:u})},Ue.thru=fo,Ue.toArray=fa,Ue.toPairs=Ra,Ue.toPairsIn=Ca,Ue.toPath=function(n){return Fo(n)?St(n,Ii):ua(n)?[n]:Ou(Ei(va(n)))},Ue.toPlainObject=pa,Ue.transform=function(n,t,e){var r=Fo(n),u=r||Yo(n)||ia(n);if(t=ui(t,4),null==e){var i=n&&n.constructor;e=u?r?new i:[]:Vo(n)&&qo(i)?Pe(rt(n)):{}}return(u?yt:_r)(n,(function(n,r,u){return t(e,n,r,u)})),e},Ue.unary=function(n){return jo(n,1)},Ue.union=Vi,Ue.unionBy=Ki,Ue.unionWith=Xi,Ue.uniq=function(n){return n&&n.length?ou(n):[]},Ue.uniqBy=function(n,t){return n&&n.length?ou(n,ui(t,2)):[]},Ue.uniqWith=function(n,t){return t="function"==typeof t?t:i,n&&n.length?ou(n,i,t):[]},Ue.unset=function(n,t){return null==n||au(n,t)},Ue.unzip=Qi,Ue.unzipWith=no,Ue.update=function(n,t,e){return null==n?n:fu(n,t,vu(e))},Ue.updateWith=function(n,t,e,r){return r="function"==typeof r?r:i,null==n?n:fu(n,t,vu(e),r)},Ue.values=za,Ue.valuesIn=function(n){return null==n?[]:Bt(n,Da(n))},Ue.without=to,Ue.words=qa,Ue.wrap=function(n,t){return ko(vu(t),n)},Ue.xor=eo,Ue.xorBy=ro,Ue.xorWith=uo,Ue.zip=io,Ue.zipObject=function(n,t){return hu(n||[],t||[],Xe)},Ue.zipObjectDeep=function(n,t){return hu(n||[],t||[],Jr)},Ue.zipWith=oo,Ue.entries=Ra,Ue.entriesIn=Ca,Ue.extend=ga,Ue.extendWith=_a,rf(Ue,Ue),Ue.add=vf,Ue.attempt=Ga,Ue.camelCase=Ua,Ue.capitalize=Pa,Ue.ceil=df,Ue.clamp=function(n,t,e){return e===i&&(e=t,t=i),e!==i&&(e=(e=ha(e))==e?e:0),t!==i&&(t=(t=ha(t))==t?t:0),ur(ha(n),t,e)},Ue.clone=function(n){return ir(n,4)},Ue.cloneDeep=function(n){return ir(n,5)},Ue.cloneDeepWith=function(n,t){return ir(n,5,t="function"==typeof t?t:i)},Ue.cloneWith=function(n,t){return ir(n,4,t="function"==typeof t?t:i)},Ue.conformsTo=function(n,t){return null==t||or(n,t,Aa(t))},Ue.deburr=Wa,Ue.defaultTo=function(n,t){return null==n||n!=n?t:n},Ue.divide=gf,Ue.endsWith=function(n,t,e){n=va(n),t=iu(t);var r=n.length,u=e=e===i?r:ur(sa(e),0,r);return(e-=t.length)>=0&&n.slice(e,u)==t},Ue.eq=zo,Ue.escape=function(n){return(n=va(n))&&K.test(n)?n.replace(J,qt):n},Ue.escapeRegExp=function(n){return(n=va(n))&&on.test(n)?n.replace(un,"\\$&"):n},Ue.every=function(n,t,e){var r=Fo(n)?bt:lr;return e&&di(n,t,e)&&(t=i),r(n,ui(t,3))},Ue.find=lo,Ue.findIndex=Pi,Ue.findKey=function(n,t){return Tt(n,ui(t,3),_r)},Ue.findLast=ho,Ue.findLastIndex=Wi,Ue.findLastKey=function(n,t){return Tt(n,ui(t,3),yr)},Ue.floor=_f,Ue.forEach=po,Ue.forEachRight=vo,Ue.forIn=function(n,t){return null==n?n:dr(n,ui(t,3),Da)},Ue.forInRight=function(n,t){return null==n?n:gr(n,ui(t,3),Da)},Ue.forOwn=function(n,t){return n&&_r(n,ui(t,3))},Ue.forOwnRight=function(n,t){return n&&yr(n,ui(t,3))},Ue.get=xa,Ue.gt=Uo,Ue.gte=Po,Ue.has=function(n,t){return null!=n&&li(n,t,Sr)},Ue.hasIn=ja,Ue.head=$i,Ue.identity=Qa,Ue.includes=function(n,t,e,r){n=Bo(n)?n:za(n),e=e&&!r?sa(e):0;var u=n.length;return e<0&&(e=de(u+e,0)),ra(n)?e<=u&&n.indexOf(t,e)>-1:!!u&&It(n,t,e)>-1},Ue.indexOf=function(n,t,e){var r=null==n?0:n.length;if(!r)return-1;var u=null==e?0:sa(e);return u<0&&(u=de(r+u,0)),It(n,t,u)},Ue.inRange=function(n,t,e){return t=ca(t),e===i?(e=t,t=0):e=ca(e),function(n,t,e){return n>=ge(t,e)&&n=-d&&n<=d},Ue.isSet=ea,Ue.isString=ra,Ue.isSymbol=ua,Ue.isTypedArray=ia,Ue.isUndefined=function(n){return n===i},Ue.isWeakMap=function(n){return Ko(n)&&si(n)==k},Ue.isWeakSet=function(n){return Ko(n)&&"[object WeakSet]"==xr(n)},Ue.join=function(n,t){return null==n?"":pe.call(n,t)},Ue.kebabCase=Fa,Ue.last=Hi,Ue.lastIndexOf=function(n,t,e){var r=null==n?0:n.length;if(!r)return-1;var u=r;return e!==i&&(u=(u=sa(e))<0?de(r+u,0):ge(u,r-1)),t==t?function(n,t,e){for(var r=e+1;r--;)if(n[r]===t)return r;return r}(n,t,u):Et(n,Rt,u,!0)},Ue.lowerCase=$a,Ue.lowerFirst=Ba,Ue.lt=oa,Ue.lte=aa,Ue.max=function(n){return n&&n.length?hr(n,Qa,jr):i},Ue.maxBy=function(n,t){return n&&n.length?hr(n,ui(t,2),jr):i},Ue.mean=function(n){return Ct(n,Qa)},Ue.meanBy=function(n,t){return Ct(n,ui(t,2))},Ue.min=function(n){return n&&n.length?hr(n,Qa,Rr):i},Ue.minBy=function(n,t){return n&&n.length?hr(n,ui(t,2),Rr):i},Ue.stubArray=hf,Ue.stubFalse=pf,Ue.stubObject=function(){return{}},Ue.stubString=function(){return""},Ue.stubTrue=function(){return!0},Ue.multiply=yf,Ue.nth=function(n,t){return n&&n.length?Wr(n,sa(t)):i},Ue.noConflict=function(){return ut._===this&&(ut._=$n),this},Ue.noop=uf,Ue.now=xo,Ue.pad=function(n,t,e){n=va(n);var r=(t=sa(t))?ne(n):0;if(!t||r>=t)return n;var u=(t-r)/2;return Fu(ce(u),e)+n+Fu(fe(u),e)},Ue.padEnd=function(n,t,e){n=va(n);var r=(t=sa(t))?ne(n):0;return t&&rt){var r=n;n=t,t=r}if(e||n%1||t%1){var u=me();return ge(n+u*(t-n+nt("1e-"+((u+"").length-1))),t)}return Yr(n,t)},Ue.reduce=function(n,t,e){var r=Fo(n)?Lt:Pt,u=arguments.length<3;return r(n,ui(t,4),e,u,cr)},Ue.reduceRight=function(n,t,e){var r=Fo(n)?At:Pt,u=arguments.length<3;return r(n,ui(t,4),e,u,sr)},Ue.repeat=function(n,t,e){return t=(e?di(n,t,e):t===i)?1:sa(t),Hr(va(n),t)},Ue.replace=function(){var n=arguments,t=va(n[0]);return n.length<3?t:t.replace(n[1],n[2])},Ue.result=function(n,t,e){var r=-1,u=(t=du(t,n)).length;for(u||(u=1,n=i);++rd)return[];var e=_,r=ge(n,_);t=ui(t),n-=_;for(var u=Ft(r,t);++e=o)return n;var f=e-ne(r);if(f<1)return r;var c=a?_u(a,0,f).join(""):n.slice(0,f);if(u===i)return c+r;if(a&&(f+=c.length-f),ta(u)){if(n.slice(f).search(u)){var s,l=c;for(u.global||(u=Dn(u.source,va(gn.exec(u))+"g")),u.lastIndex=0;s=u.exec(l);)var h=s.index;c=c.slice(0,h===i?f:h)}}else if(n.indexOf(iu(u),f)!=f){var p=c.lastIndexOf(u);p>-1&&(c=c.slice(0,p))}return c+r},Ue.unescape=function(n){return(n=va(n))&&V.test(n)?n.replace(G,ee):n},Ue.uniqueId=function(n){var t=++Un;return va(n)+t},Ue.upperCase=Ha,Ue.upperFirst=Za,Ue.each=po,Ue.eachRight=vo,Ue.first=$i,rf(Ue,function(){var n={};return _r(Ue,(function(t,e){zn.call(Ue.prototype,e)||(n[e]=t)})),n}(),{chain:!1}),Ue.VERSION="4.17.20",yt(["bind","bindKey","curry","curryRight","partial","partialRight"],(function(n){Ue[n].placeholder=Ue})),yt(["drop","take"],(function(n,t){$e.prototype[n]=function(e){e=e===i?1:de(sa(e),0);var r=this.__filtered__&&!t?new $e(this):this.clone();return r.__filtered__?r.__takeCount__=ge(e,r.__takeCount__):r.__views__.push({size:ge(e,_),type:n+(r.__dir__<0?"Right":"")}),r},$e.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()}})),yt(["filter","map","takeWhile"],(function(n,t){var e=t+1,r=1==e||3==e;$e.prototype[n]=function(n){var t=this.clone();return t.__iteratees__.push({iteratee:ui(n,3),type:e}),t.__filtered__=t.__filtered__||r,t}})),yt(["head","last"],(function(n,t){var e="take"+(t?"Right":"");$e.prototype[n]=function(){return this[e](1).value()[0]}})),yt(["initial","tail"],(function(n,t){var e="drop"+(t?"":"Right");$e.prototype[n]=function(){return this.__filtered__?new $e(this):this[e](1)}})),$e.prototype.compact=function(){return this.filter(Qa)},$e.prototype.find=function(n){return this.filter(n).head()},$e.prototype.findLast=function(n){return this.reverse().find(n)},$e.prototype.invokeMap=Zr((function(n,t){return"function"==typeof n?new $e(this):this.map((function(e){return Ar(e,n,t)}))})),$e.prototype.reject=function(n){return this.filter(Eo(ui(n)))},$e.prototype.slice=function(n,t){n=sa(n);var e=this;return e.__filtered__&&(n>0||t<0)?new $e(e):(n<0?e=e.takeRight(-n):n&&(e=e.drop(n)),t!==i&&(e=(t=sa(t))<0?e.dropRight(-t):e.take(t-n)),e)},$e.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},$e.prototype.toArray=function(){return this.take(_)},_r($e.prototype,(function(n,t){var e=/^(?:filter|find|map|reject)|While$/.test(t),r=/^(?:head|last)$/.test(t),u=Ue[r?"take"+("last"==t?"Right":""):t],o=r||/^find/.test(t);u&&(Ue.prototype[t]=function(){var t=this.__wrapped__,a=r?[1]:arguments,f=t instanceof $e,c=a[0],s=f||Fo(t),l=function(n){var t=u.apply(Ue,Ot([n],a));return r&&h?t[0]:t};s&&e&&"function"==typeof c&&1!=c.length&&(f=s=!1);var h=this.__chain__,p=!!this.__actions__.length,v=o&&!h,d=f&&!p;if(!o&&s){t=d?t:new $e(this);var g=n.apply(t,a);return g.__actions__.push({func:fo,args:[l],thisArg:i}),new Fe(g,h)}return v&&d?n.apply(this,a):(g=this.thru(l),v?r?g.value()[0]:g.value():g)})})),yt(["pop","push","shift","sort","splice","unshift"],(function(n){var t=En[n],e=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",r=/^(?:pop|shift)$/.test(n);Ue.prototype[n]=function(){var n=arguments;if(r&&!this.__chain__){var u=this.value();return t.apply(Fo(u)?u:[],n)}return this[e]((function(e){return t.apply(Fo(e)?e:[],n)}))}})),_r($e.prototype,(function(n,t){var e=Ue[t];if(e){var r=e.name+"";zn.call(De,r)||(De[r]=[]),De[r].push({name:t,func:e})}})),De[zu(i,2).name]=[{name:"wrapper",func:i}],$e.prototype.clone=function(){var n=new $e(this.__wrapped__);return n.__actions__=Ou(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=Ou(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=Ou(this.__views__),n},$e.prototype.reverse=function(){if(this.__filtered__){var n=new $e(this);n.__dir__=-1,n.__filtered__=!0}else(n=this.clone()).__dir__*=-1;return n},$e.prototype.value=function(){var n=this.__wrapped__.value(),t=this.__dir__,e=Fo(n),r=t<0,u=e?n.length:0,i=function(n,t,e){for(var r=-1,u=e.length;++r=this.__values__.length;return{done:n,value:n?i:this.__values__[this.__index__++]}},Ue.prototype.plant=function(n){for(var t,e=this;e instanceof We;){var r=Ri(e);r.__index__=0,r.__values__=i,t?u.__wrapped__=r:t=r;var u=r;e=e.__wrapped__}return u.__wrapped__=n,t},Ue.prototype.reverse=function(){var n=this.__wrapped__;if(n instanceof $e){var t=n;return this.__actions__.length&&(t=new $e(this)),(t=t.reverse()).__actions__.push({func:fo,args:[Ji],thisArg:i}),new Fe(t,this.__chain__)}return this.thru(Ji)},Ue.prototype.toJSON=Ue.prototype.valueOf=Ue.prototype.value=function(){return su(this.__wrapped__,this.__actions__)},Ue.prototype.first=Ue.prototype.head,Mt&&(Ue.prototype[Mt]=function(){return this}),Ue}();ut._=re,(u=function(){return re}.call(t,e,t,r))===i||(r.exports=u)}).call(this)}).call(this,e(29),e(30)(n))},,,function(n,t,e){"use strict";e.r(t),e(13),e(15);var r=e(9),u=e(0);const i=Object(r.debounce)(n=>{n.classList.remove("show")},1e3),o=n=>{const t=document.getElementById("save-status");switch(n){case"saving":t.innerHTML="Saving ...";break;case"saved":t.innerHTML="Saved",i(t);break;default:t.innerHTML=" "}t.classList.add("show")};var a,f=document.getElementById("textSizeSlider"),c=document.getElementById("allowTextSlider");f.oninput=function(){a=f.value},c.oninput=function(){1==c.checked?f.disabled=!1:f.disabled=!0};const s=document.querySelectorAll(".option-input");u.a.on("ready",()=>{s.forEach(n=>{const t=(n=>{var t;return"textSizeSlider"===n.id?(t=n.value,u.a.data.options.hasOwnProperty(n.id)&&(t=u.a.data.options[n.id],f.value=t)):(t="checked",u.a.data.options.hasOwnProperty(n.id)&&(n[t]=u.a.data.options[n.id])),()=>{if(o("saving"),"textSizeSlider"===n.id){t=a;const e=Object.assign({},u.a.data.options,{[n.id]:t});u.a.set({options:e}).then(()=>{o("saved")})}else{const e=Object.assign({},u.a.data.options,{[n.id]:n[t]});u.a.set({options:e}).then(()=>{o("saved")})}}})(n);switch(n.addEventListener("change",t),n.id){case"allowTextSlider":n.removeAttribute("disabled"),1==u.a.data.options.allowTextSlider?f.disabled=!1:f.disabled=!0;break;case"theaterModeFix":n.removeAttribute("disabled");break;case"textSizeSlider":break;default:n.removeAttribute("disabled")}})}),document.getElementById("infoButton").addEventListener("click",(function(){chrome.tabs.create({url:"./html/welcome.html"})}))},function(n,t,e){var r=e(14);"string"==typeof r&&(r=[[n.i,r,""]]);e(4)(r,{hmr:!0,transform:void 0,insertInto:void 0}),r.locals&&(n.exports=r.locals)},function(n,t,e){(n.exports=e(3)(!1)).push([n.i,"body {\n background-color: #1e1e1e;\n color: #fff;\n}\n.section:nth-child(1) .options-heading {\n margin: 0;\n}\n.options-heading {\n margin: 10px 0 0 0;\n}\n.options-description {\n margin: 0 0 10px 0;\n opacity: 0.8;\n}\ntable {\n border: none;\n border-spacing: 0;\n width: 100%;\n}\ntable tr td {\n padding: 0;\n}\ntable tr td:nth-child(1) {\n width: 80%;\n}\ntable tr td:nth-child(2) {\n width: 20%;\n text-align: right;\n}\n.hr {\n background-color: #d1d1d1;\n height: 1px;\n margin: 10px 0;\n}\n#save-status {\n text-align: center;\n opacity: 0;\n transition: all 1s linear;\n}\n#save-status.show {\n opacity: 1;\n transition: none;\n}\n.options-table .option-row {\n display: flex;\n flex-direction: row;\n align-items: space-between;\n justify-content: space-between;\n}\n.options-table .option-cell {\n padding-right: 5px;\n}\n.options-table .option-cell:last-child {\n padding-right: 0px;\n}\n.light-text {\n color: rgba(0,0,0,0.6);\n}\ninput[type=checkbox][disabled] {\n outline: 1px solid #f00;\n cursor: not-allowed;\n opacity: 0.9;\n}\n.info_button {\n display: inline-block;\n padding: 0.3em 1.2em;\n margin: 0 0.3em 0.3em 0;\n border-radius: 2em;\n box-sizing: border-box;\n text-decoration: none;\n font-weight: 300;\n color: #1e1e1e;\n text-align: center;\n margin-left: 150px;\n transition: all 0.2s;\n}\n.info_button:hover {\n color: #f00;\n}\n",""])},function(n,t,e){var r=e(16),u=e(21),i=e(8),o=e(2),a=e(24),f=e(25),c={M:function(n){return n.getMonth()+1},MM:function(n){return h(n.getMonth()+1,2)},Q:function(n){return Math.ceil((n.getMonth()+1)/3)},D:function(n){return n.getDate()},DD:function(n){return h(n.getDate(),2)},DDD:function(n){return r(n)},DDDD:function(n){return h(r(n),3)},d:function(n){return n.getDay()},E:function(n){return n.getDay()||7},W:function(n){return u(n)},WW:function(n){return h(u(n),2)},YY:function(n){return h(n.getFullYear(),4).substr(2)},YYYY:function(n){return h(n.getFullYear(),4)},GG:function(n){return String(i(n)).substr(2)},GGGG:function(n){return i(n)},H:function(n){return n.getHours()},HH:function(n){return h(n.getHours(),2)},h:function(n){var t=n.getHours();return 0===t?12:t>12?t%12:t},hh:function(n){return h(c.h(n),2)},m:function(n){return n.getMinutes()},mm:function(n){return h(n.getMinutes(),2)},s:function(n){return n.getSeconds()},ss:function(n){return h(n.getSeconds(),2)},S:function(n){return Math.floor(n.getMilliseconds()/100)},SS:function(n){return h(Math.floor(n.getMilliseconds()/10),2)},SSS:function(n){return h(n.getMilliseconds(),3)},Z:function(n){return l(n.getTimezoneOffset(),":")},ZZ:function(n){return l(n.getTimezoneOffset())},X:function(n){return Math.floor(n.getTime()/1e3)},x:function(n){return n.getTime()}};function s(n){return n.match(/\[[\s\S]/)?n.replace(/^\[|]$/g,""):n.replace(/\\/g,"")}function l(n,t){t=t||"";var e=n>0?"-":"+",r=Math.abs(n),u=r%60;return e+h(Math.floor(r/60),2)+t+h(u,2)}function h(n,t){for(var e=Math.abs(n).toString();e.length0?"in "+u:u+" ago":u}}}},function(n,t,e){var r=e(28);n.exports=function(){var n=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],t=["January","February","March","April","May","June","July","August","September","October","November","December"],e=["Su","Mo","Tu","We","Th","Fr","Sa"],u=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],i=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],o=["AM","PM"],a=["am","pm"],f=["a.m.","p.m."],c={MMM:function(t){return n[t.getMonth()]},MMMM:function(n){return t[n.getMonth()]},dd:function(n){return e[n.getDay()]},ddd:function(n){return u[n.getDay()]},dddd:function(n){return i[n.getDay()]},A:function(n){return n.getHours()/12>=1?o[1]:o[0]},a:function(n){return n.getHours()/12>=1?a[1]:a[0]},aa:function(n){return n.getHours()/12>=1?f[1]:f[0]}};return["M","D","DDD","d","Q","W"].forEach((function(n){c[n+"o"]=function(t,e){return function(n){var t=n%100;if(t>20||t<10)switch(t%10){case 1:return n+"st";case 2:return n+"nd";case 3:return n+"rd"}return n+"th"}(e[n](t))}})),{formatters:c,formattingTokensRegExp:r(c)}}},function(n,t){var e=["M","MM","Q","D","DD","DDD","DDDD","d","E","W","WW","YY","YYYY","GG","GGGG","H","HH","h","hh","m","mm","s","ss","S","SS","SSS","Z","ZZ","X","x"];n.exports=function(n){var t=[];for(var r in n)n.hasOwnProperty(r)&&t.push(r);var u=e.concat(t).sort().reverse();return new RegExp("(\\[[^\\[]*\\])|(\\\\)?("+u.join("|")+"|.)","g")}},function(n,t){var e;e=function(){return this}();try{e=e||new Function("return this")()}catch(n){"object"==typeof window&&(e=window)}n.exports=e},function(n,t){n.exports=function(n){return n.webpackPolyfill||(n.deprecate=function(){},n.paths=[],n.children||(n.children=[]),Object.defineProperty(n,"loaded",{enumerable:!0,get:function(){return n.l}}),Object.defineProperty(n,"id",{enumerable:!0,get:function(){return n.i}}),n.webpackPolyfill=1),n}}]); \ No newline at end of file diff --git a/build/welcomePage.js b/build/welcomePage.js new file mode 100644 index 0000000..76f08ad --- /dev/null +++ b/build/welcomePage.js @@ -0,0 +1 @@ +!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=31)}({0:function(e,t,n){"use strict";var r=class{get(e=null){return new Promise((t,n)=>{const r="string"==typeof e||"number"==typeof e;chrome.storage[this.store].get(e,n=>{t(r?n[e]:n)})})}getBytesInUse(e=null){return new Promise((t,n)=>{chrome.storage[this.store].getBytesInUse(e,t)})}set(e){return new Promise((t,n)=>{chrome.storage[this.store].set(e,t)})}remove(e){return new Promise((t,n)=>{chrome.storage[this.store].remove(e,t)})}clear(){return new Promise((e,t)=>{chrome.storage[this.store].clear(e)})}listen(e,t){"function"==typeof e&&(t=e,e=null),chrome.storage.onChanged.addListener((n,r)=>{if(r===this.store)if(null!==e){if(n.hasOwnProperty(e)){const r=n[e].oldValue||null,o=n[e].newValue||null;t(r,o)}}else t(n)})}};new class extends r{constructor(){super(),this.store="local"}};const o=new class extends r{constructor(){super(),this.store="sync"}};new class{create(e=null,t){return"object"==typeof e&&(t=e,e=null),new Promise((n,r)=>{chrome.notifications.create(e,t,n)})}update(e,t){return new Promise((n,r)=>{chrome.notifications.update(e,t,n)})}clear(e){return new Promise((t,n)=>{chrome.notifications.clear(e,t)})}getAll(){return new Promise((e,t)=>{chrome.notifications.getAll(e)})}getPermissionLevel(){return new Promise((e,t)=>{chrome.notifications.getPermissionLevel(e)})}listen(e,t=null,n){if("function"==typeof t&&(n=t,t=null),"onPermissionLevelChanged"===e||"onShowSettings"===e)return this._nonNotificationIdListen(e,n);const r=null!==t?(e,...r)=>{t===e&&n(e,...r)}:n;chrome.notifications[e].addListener(r)}_nonNotificationIdListen(e,t){chrome.notifications[e].addListener(t)}};var i=n(1);t.a=new class extends i.EventEmitter{constructor(){super(),this._data=null,this.state="initiating",this._init()}async _init(){const e=await o.get();this._initListener(),this._data=e,this.state="ready",this.emit(this.state)}_initListener(){o.listen(e=>{Object.keys(e).forEach(t=>{e[t].hasOwnProperty("newValue")?this._data[t]=e[t].newValue:console.error("No newValue in sync storge change")}),this.emit("change",this.data,e)})}set(e){return o.set(e)}get data(){return this._data}has(e){return this.data.hasOwnProperty(e)}}},1:function(e,t,n){"use strict";var r,o="object"==typeof Reflect?Reflect:null,i=o&&"function"==typeof o.apply?o.apply:function(e,t,n){return Function.prototype.apply.call(e,t,n)};r=o&&"function"==typeof o.ownKeys?o.ownKeys:Object.getOwnPropertySymbols?function(e){return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))}:function(e){return Object.getOwnPropertyNames(e)};var s=Number.isNaN||function(e){return e!=e};function a(){a.init.call(this)}e.exports=a,e.exports.once=function(e,t){return new Promise((function(n,r){function o(){void 0!==i&&e.removeListener("error",i),n([].slice.call(arguments))}var i;"error"!==t&&(i=function(n){e.removeListener(t,o),r(n)},e.once("error",i)),e.once(t,o)}))},a.EventEmitter=a,a.prototype._events=void 0,a.prototype._eventsCount=0,a.prototype._maxListeners=void 0;var c=10;function u(e){if("function"!=typeof e)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof e)}function l(e){return void 0===e._maxListeners?a.defaultMaxListeners:e._maxListeners}function f(e,t,n,r){var o,i,s;if(u(n),void 0===(i=e._events)?(i=e._events=Object.create(null),e._eventsCount=0):(void 0!==i.newListener&&(e.emit("newListener",t,n.listener?n.listener:n),i=e._events),s=i[t]),void 0===s)s=i[t]=n,++e._eventsCount;else if("function"==typeof s?s=i[t]=r?[n,s]:[s,n]:r?s.unshift(n):s.push(n),(o=l(e))>0&&s.length>o&&!s.warned){s.warned=!0;var a=new Error("Possible EventEmitter memory leak detected. "+s.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");a.name="MaxListenersExceededWarning",a.emitter=e,a.type=t,a.count=s.length,function(e){console&&console.warn&&console.warn(e)}(a)}return e}function p(e,t,n){var r={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},o=function(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,0===arguments.length?this.listener.call(this.target):this.listener.apply(this.target,arguments)}.bind(r);return o.listener=n,r.wrapFn=o,o}function d(e,t,n){var r=e._events;if(void 0===r)return[];var o=r[t];return void 0===o?[]:"function"==typeof o?n?[o.listener||o]:[o]:n?function(e){for(var t=new Array(e.length),n=0;n0&&(s=t[0]),s instanceof Error)throw s;var a=new Error("Unhandled error."+(s?" ("+s.message+")":""));throw a.context=s,a}var c=o[e];if(void 0===c)return!1;if("function"==typeof c)i(c,this,t);else{var u=c.length,l=m(c,u);for(n=0;n=0;i--)if(n[i]===t||n[i].listener===t){s=n[i].listener,o=i;break}if(o<0)return this;0===o?n.shift():function(e,t){for(;t+1=0;r--)this.removeListener(e,t[r]);return this},a.prototype.listeners=function(e){return d(this,e,!0)},a.prototype.rawListeners=function(e){return d(this,e,!1)},a.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):h.call(e,t)},a.prototype.listenerCount=h,a.prototype.eventNames=function(){return this._eventsCount>0?r(this._events):[]}},3:function(e,t){e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=function(e,t){var n=e[1]||"",r=e[3];if(!r)return n;if(t&&"function"==typeof btoa){var o=function(e){return"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(e))))+" */"}(r),i=r.sources.map((function(e){return"/*# sourceURL="+r.sourceRoot+e+" */"}));return[n].concat(i).concat([o]).join("\n")}return[n].join("\n")}(t,e);return t[2]?"@media "+t[2]+"{"+n+"}":n})).join("")},t.i=function(e,n){"string"==typeof e&&(e=[[null,e,""]]);for(var r={},o=0;o{});r.a.on("ready",()=>{if(1==!!r.a.data.setupComplete)return console.log("Setup is already complete, Should not be here"),!0;chrome.runtime.sendMessage({name:"setupComplete",data:{}},i),console.log("Competed setup, sent message")})},32:function(e,t,n){var r=n(33);"string"==typeof r&&(r=[[e.i,r,""]]);n(4)(r,{hmr:!0,transform:void 0,insertInto:void 0}),r.locals&&(e.exports=r.locals)},33:function(e,t,n){(t=e.exports=n(3)(!1)).push([e.i,"@import url(https://fonts.googleapis.com/css?family=Roboto:300,400,700|Material+Icons);",""]),t.push([e.i,"body {\n font-family: 'Roboto', Arial, sans-serif;\n font-size: 16px;\n background: #222;\n color: #fff;\n margin: 25px;\n}\n.fw-light {\n font-weight: 300;\n}\n.fw-regular {\n font-weight: 400;\n}\n.fw-bold {\n font-weight: 700;\n}\n.success-overlay {\n visibility: hidden;\n opacity: 0;\n position: fixed;\n top: 0;\n left: 0;\n z-index: 10;\n background: rgba(25,25,25,0.95);\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n width: 100%;\n transition: visibility 0s, opacity 200ms ease;\n}\n.success-overlay.show {\n visibility: visible;\n opacity: 1;\n}\n.success-overlay .material-icons {\n font-size: 20em;\n opacity: 0;\n}\n.success-overlay .material-icons.show {\n opacity: 1;\n animation: jackInTheBox 700ms 1;\n}\n.success-overlay .success-message {\n font-size: 3em;\n}\n.success-overlay .close-message {\n font-size: 0.7em;\n opacity: 0.7;\n}\n.container {\n display: flex;\n flex-direction: column;\n align-items: center;\n}\n.container h1 {\n margin: 0;\n font-size: 3em;\n letter-spacing: 3px;\n}\n.container .heading-note {\n font-size: 18px;\n color: #bbb;\n}\n.container .option {\n text-align: center;\n}\n.container .option .option-note {\n font-size: 12px;\n font-style: italic;\n color: #999;\n}\n.container .complete-setup-button {\n background: #333;\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 10px;\n cursor: pointer;\n text-transform: uppercase;\n border-radius: 3px;\n box-shadow: 0 2px 5px 0 rgba(0,0,0,0.7);\n transition: background 50ms ease;\n}\n.container .complete-setup-button:hover {\n background: #404040;\n}\n.container .complete-setup-button .material-icons {\n margin-right: 7px;\n}\n.links_bottom {\n display: inline-block;\n margin: 1%;\n}\na {\n background-color: #252526;\n color: #fff;\n padding-top: 1em;\n padding-bottom: 1em;\n text-decoration: none;\n text-transform: uppercase;\n width: 100%;\n table-layout: fixed;\n border-collapse: collapse;\n text-align: center;\n border: 1px solid #4e4e4e;\n}\na:hover {\n background-color: #d3d3d3;\n color: #000;\n}\na:active {\n box-shadow: none;\n top: 5px;\n}\n.links_div {\n width: 20vw;\n}\np {\n margin: 2%;\n max-width: 30vw;\n}\nh2 {\n margin: 2%;\n}\nhr {\n margin: 2%;\n width: 60vw;\n border: 3px solid #d3d3d3;\n border-radius: 5px;\n}\n@-moz-keyframes jackInTheBox {\n from {\n opacity: 0;\n transform: scale(0.1) rotate(60deg);\n transform-origin: center center;\n }\n 50% {\n transform: rotate(-20deg);\n }\n 70% {\n opacity: 1;\n transform: rotate(6deg);\n }\n to {\n transform: scale(1);\n }\n}\n@-webkit-keyframes jackInTheBox {\n from {\n opacity: 0;\n transform: scale(0.1) rotate(60deg);\n transform-origin: center center;\n }\n 50% {\n transform: rotate(-20deg);\n }\n 70% {\n opacity: 1;\n transform: rotate(6deg);\n }\n to {\n transform: scale(1);\n }\n}\n@-o-keyframes jackInTheBox {\n from {\n opacity: 0;\n transform: scale(0.1) rotate(60deg);\n transform-origin: center center;\n }\n 50% {\n transform: rotate(-20deg);\n }\n 70% {\n opacity: 1;\n transform: rotate(6deg);\n }\n to {\n transform: scale(1);\n }\n}\n@keyframes jackInTheBox {\n from {\n opacity: 0;\n transform: scale(0.1) rotate(60deg);\n transform-origin: center center;\n }\n 50% {\n transform: rotate(-20deg);\n }\n 70% {\n opacity: 1;\n transform: rotate(6deg);\n }\n to {\n transform: scale(1);\n }\n}\n",""])},4:function(e,t,n){var r={},o=function(e){var t;return function(){return void 0===t&&(t=e.apply(this,arguments)),t}}((function(){return window&&document&&document.all&&!window.atob})),i=function(e){var t={};return function(e,n){if("function"==typeof e)return e();if(void 0===t[e]){var r=function(e,t){return t?t.querySelector(e):document.querySelector(e)}.call(this,e,n);if(window.HTMLIFrameElement&&r instanceof window.HTMLIFrameElement)try{r=r.contentDocument.head}catch(e){r=null}t[e]=r}return t[e]}}(),s=null,a=0,c=[],u=n(5);function l(e,t){for(var n=0;n=0&&c.splice(t,1)}function h(e){var t=document.createElement("style");if(void 0===e.attrs.type&&(e.attrs.type="text/css"),void 0===e.attrs.nonce){var r=n.nc;r&&(e.attrs.nonce=r)}return m(t,e.attrs),p(e,t),t}function m(e,t){Object.keys(t).forEach((function(n){e.setAttribute(n,t[n])}))}function v(e,t){var n,r,o,i;if(t.transform&&e.css){if(!(i=t.transform(e.css)))return function(){};e.css=i}if(t.singleton){var c=a++;n=s||(s=h(t)),r=g.bind(null,n,c,!1),o=g.bind(null,n,c,!0)}else e.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=function(e){var t=document.createElement("link");return void 0===e.attrs.type&&(e.attrs.type="text/css"),e.attrs.rel="stylesheet",m(t,e.attrs),p(e,t),t}(t),r=function(e,t,n){var r=n.css,o=n.sourceMap,i=void 0===t.convertToAbsoluteUrls&&o;(t.convertToAbsoluteUrls||i)&&(r=u(r)),o&&(r+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(o))))+" */");var s=new Blob([r],{type:"text/css"}),a=e.href;e.href=URL.createObjectURL(s),a&&URL.revokeObjectURL(a)}.bind(null,n,t),o=function(){d(n),n.href&&URL.revokeObjectURL(n.href)}):(n=h(t),r=function(e,t){var n=t.css,r=t.media;if(r&&e.setAttribute("media",r),e.styleSheet)e.styleSheet.cssText=n;else{for(;e.firstChild;)e.removeChild(e.firstChild);e.appendChild(document.createTextNode(n))}}.bind(null,n),o=function(){d(n)});return r(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;r(e=t)}else o()}}e.exports=function(e,t){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");(t=t||{}).attrs="object"==typeof t.attrs?t.attrs:{},t.singleton||"boolean"==typeof t.singleton||(t.singleton=o()),t.insertInto||(t.insertInto="head"),t.insertAt||(t.insertAt="bottom");var n=f(e,t);return l(n,t),function(e){for(var o=[],i=0;i { + return new Promise((res, rej) => { + + // Resolves if setup is complete + if(PersistentSyncStorage.data.setupComplete) { + // Ensure new options (on extension update) are added to options object + PersistentSyncStorage.set({ + options: Object.assign({}, CONFIG.defaultOptions, PersistentSyncStorage.data.options) + }); + + return res(); + } + + // Otherwise inits setup + const onSetupComplete = (request, sender, sendResponse) => { + if(request.name === 'setupComplete') { + chrome.runtime.onMessage.removeListener(onSetupComplete); + + PersistentSyncStorage.set({ + setupComplete: true + }); + + res(); + } + + return true; + }; + + chrome.tabs.create({ url: './html/welcome.html' }); + chrome.runtime.onMessage.addListener(onSetupComplete); + console.log('Setup Complete'); + }); +}; + +export default {ensure}; \ No newline at end of file diff --git a/src/background/index.js b/src/background/index.js new file mode 100644 index 0000000..544e848 --- /dev/null +++ b/src/background/index.js @@ -0,0 +1,27 @@ +import PersistentSyncStorage from 'src/helpers/PersistentSyncStorage'; + +import Setup from './Setup'; + +import CONFIG from 'src/config'; + +class Main { + constructor() { + this.init = this.init.bind(this); + + PersistentSyncStorage.on('ready', () => { + this.setupOptions(); + Setup.ensure().then(this.init); + }); + } + + init() {} + + setupOptions() { + // Ensure options store is setup + if(!PersistentSyncStorage.has('options')) { + PersistentSyncStorage.set({ options: CONFIG.defaultOptions }); + } + } +} + +const main = new Main(); \ No newline at end of file diff --git a/src/config.js b/src/config.js new file mode 100644 index 0000000..ed5fffd --- /dev/null +++ b/src/config.js @@ -0,0 +1,26 @@ + +const CONFIG = { + defaultOptions: { + + // Emote Options + enableBTTVEmotes: true, + enableFrankerEmotes: true, + enableTwitchEmotes: true, + kappaFix: true, + + // Chat Options + theaterModeFix: false, + setAuthorColor: false, + showTimeStamp: false, + alternateLineColor: false, + hideAuthorIcons: false, + hideWelcomBanner: false, + setTwitchColors: false, + textSizeSlider: 'inherit', + setLiveChat: true, + allowTextSlider: false, + } +}; + +export default CONFIG; + diff --git a/src/content/ChatScroller.js b/src/content/ChatScroller.js new file mode 100644 index 0000000..f6708d8 --- /dev/null +++ b/src/content/ChatScroller.js @@ -0,0 +1,48 @@ +class ChatScroller { + constructor() { + this.scroll = this.scroll.bind(this); + this.start = this.start.bind(this); + this.stop = this.stop.bind(this); + + this.scroller = null; + this.interval = null; + } + + init() { + this.getScroller() + .then(() => { + //this.scroller.addEventListener('mouseleave', this.start); + this.scroller.addEventListener('mouseenter', this.stop); + this.start(); + }); + } + + start() { + this.interval = setInterval( + this.scroll, + 250 + ); + } + + stop() { + clearInterval(this.interval); + } + + scroll() { + this.scroller.scrollTop = 9999; + } + + getScroller() { + const checkForScroller = (res, rej) => { + this.scroller = document.getElementById('item-scroller'); + if(this.scroller !== null) { + res(); + } else { + setTimeout(checkForScroller.bind(this, res, rej), 250); + } + }; + return new Promise(checkForScroller); + } +} + +export default ChatScroller; \ No newline at end of file diff --git a/src/content/ChatWatcher.js b/src/content/ChatWatcher.js new file mode 100644 index 0000000..1cba59b --- /dev/null +++ b/src/content/ChatWatcher.js @@ -0,0 +1,230 @@ +import Emotes from './Emotes'; +import Message from './Message'; +import PersistentSyncStorage from 'src/helpers/PersistentSyncStorage'; + + + +class ChatWatcher { + + + + constructor() { + this.watchChat = this.watchChat.bind(this); + this._chatContainer = null; + this._observer = null; + this.messages = new Map(); + } + + init() { + + return new Promise((res, rej) => { + this.getChatContainer().then(Emotes.init).then(() => { + this.addEmotePopup(); + this.watchChat(); + this.parsePreloadedMessages(); + }); + }); + } + + + getChatContainer() { + // Parent of actual chat (children are messages) + const checkForContainer = (res, rej) => { + this._chatContainer = document.querySelector('#items.style-scope.yt-live-chat-item-list-renderer'); + if(this._chatContainer !== null) { + res(); + } else { + setTimeout(checkForContainer.bind(this, res, rej), 250); + } + }; + return new Promise(checkForContainer); + } + + parsePreloadedMessages() { + const messages = this._chatContainer.children; + + for(let i = messages.length-1; i >= 0; i--) { + const node = messages[i]; + if(this.isMessageNode(node)) { + const message = new Message(node); + } + } + } + + watchChat() { + console.log('Chat observer started'); + this._observer = new MutationObserver(mutations => { + + mutations.forEach(mutation => { + + + + const { addedNodes, removedNodes } = mutation; + + // Added nodes + if(typeof addedNodes !== 'undefined' && addedNodes.length > 0) { + for(let i = 0, length = addedNodes.length-1; i <= length; i++) { + const node = addedNodes[i]; + if(this.isMessageNode(node)) { + this.onNewMessage(node); + } + } + } + + // Removed nodes + if(typeof removedNodes !== 'undefined' && removedNodes.length > 0) { + for(let i = 0, length = removedNodes.length-1; i <= length; i++) { + const node = removedNodes[i]; + if(this.isMessageNode(node) && this.isObservedMessage(node)) { + this.onObservedMessageRemoved(node); + } + } + } + }); + }); + + this._observer.observe(this._chatContainer, { + childList: true, + attributes: false, + characterData: false, + subtree: false + }); + } + + onNewMessage(node) { + const message = new Message(node); + + // Don't store message if has 0 emotes + if(message.hasEmotes) { + this.messages.set(message.id, message); + } + } + + onObservedMessageRemoved(node) { + const messageId = node.getAttribute('message-id'); + const message = this.messages.get(messageId); + if(message != undefined){ + message.destroy(); + } + + this.messages.delete(messageId); + } + + isMessageNode(node) { + return node.tagName === 'YT-LIVE-CHAT-TEXT-MESSAGE-RENDERER'; + } + + isObservedMessage(node) { + return node.getAttribute('message-id') !== null; + } + + + /////////////////////////////////////////////////////////////////// + + addEmotePopup(){ + + // create emote button + const emoteButton = document.createElement('button'); + emoteButton.classList.add('emoteButton'); + emoteButton.textContent = ''; + + // append button to action-buttons list + const chatButtonSelectionList = document.getElementById('action-buttons'); + chatButtonSelectionList.parentNode.insertBefore(emoteButton, chatButtonSelectionList); + + // create popupDiv + const popUpDiv = document.createElement('div'); + popUpDiv.classList.add('popup'); + popUpDiv.classList.add('hideElement'); + + function emoteAppend(keysITer){ + + // create divider + var hr = document.createElement('hr'); + hr.classList.add('emoteDivider'); + + for (let index = 0; index < keysITer.length; index++) { + const element = keysITer[index]; + var emote_div = document.createElement('emote_div'); + emote_div.innerHTML = (Emotes.get(element).html); + popUpDiv.appendChild(emote_div); + } + popUpDiv.appendChild(hr); + } + + // create text + var bttv_text = document.createElement('h2'); + bttv_text.textContent = "BTTV"; + bttv_text.classList.add('emotePopUpText'); + var franker_text = document.createElement('h2'); + franker_text.textContent = "FrankerFacez"; + franker_text.classList.add('emotePopUpText'); + var twitch_text = document.createElement('h2'); + twitch_text.textContent = "Twitch"; + twitch_text.classList.add('emotePopUpText'); + + + + // need ittr to search each dict and append to dom + let keysITer = null; + + keysITer = Array.from(Emotes.specialEmotesDictionary.keys()); + emoteAppend(keysITer); + + if(PersistentSyncStorage.data.options.enableBTTVEmotes){ + popUpDiv.appendChild(bttv_text); + keysITer = Array.from(Emotes.bttv_Dictionary.keys()); + emoteAppend(keysITer); + } + + if(PersistentSyncStorage.data.options.enableFrankerEmotes){ + popUpDiv.appendChild(franker_text); + keysITer = Array.from(Emotes.franker_Dictionary.keys()); + emoteAppend(keysITer); + } + + if(PersistentSyncStorage.data.options.enableTwitchEmotes){ + popUpDiv.appendChild(twitch_text); + keysITer = Array.from(Emotes.twitch_Dictionary.keys()); + emoteAppend(keysITer); + } + + + + // add div to doc + chatButtonSelectionList.appendChild(popUpDiv); + + // listen for popup button + emoteButton.addEventListener('click', function(){ + popUpDiv.classList.toggle('hideElement'); + console.log('emote popup button clicked'); + }); + + // get input area + var inputArea = document.querySelector('#input.yt-live-chat-text-input-field-renderer'); + var inputAreaLabel = document.querySelector('#label.yt-live-chat-text-input-field-renderer'); + + // add alt tag to chat + function emoteToTextArea(){ + inputArea.textContent += this.alt + " "; + inputArea.focus(); + inputAreaLabel.textContent = ""; + popUpDiv.classList.toggle('hideElement'); + console.log(this.alt + " emote button selected"); + } + + // listener button for emotes + var EMOTICONS = document.getElementsByTagName('img'); + for (let index = 0; index < EMOTICONS.length; index++) { + const element = EMOTICONS[index]; + element.addEventListener('click', emoteToTextArea, false); + } + + console.log((keysITer.length+1) + " Emotes Added"); + }// end addEmotePopup + + /////////////////////////////////////////////////////////////////// + +}// end chat watcher + +export default ChatWatcher; diff --git a/src/content/Emotes/Emote.js b/src/content/Emotes/Emote.js new file mode 100644 index 0000000..b66ab0b --- /dev/null +++ b/src/content/Emotes/Emote.js @@ -0,0 +1,16 @@ +class Emote { + constructor({ code, url }) { + this.code = code; + this.url = url; + } + + get html() { + return (` + + ${this.code} + + `).trim(); + } +} + +export default Emote; \ No newline at end of file diff --git a/src/content/Emotes/index.js b/src/content/Emotes/index.js new file mode 100644 index 0000000..894e853 --- /dev/null +++ b/src/content/Emotes/index.js @@ -0,0 +1,194 @@ +import PersistentSyncStorage from 'src/helpers/PersistentSyncStorage'; +import Emote from './Emote'; + + +class Emotes { + constructor() { + this.dictionary = new Map(); + + // identification for popup + this.twitch_Dictionary = new Map(); + this.bttv_Dictionary = new Map(); + this.franker_Dictionary = new Map(); + this.specialEmotesDictionary = new Map(); + + + this.init = this.init.bind(this); + } + + init() { + return Promise.all([ + (PersistentSyncStorage.data.options.enableBTTVEmotes && this.loadBTTVEmote()), + (PersistentSyncStorage.data.options.enableFrankerEmotes && this.loadFrankerEmotes()), + (PersistentSyncStorage.data.options.enableTwitchEmotes && this.loadTwitchEmotes()), + (this.specialEmotes()) + ]); + } + + ///////////////////////////////////////////////////////////////////////////////// + + get(key) { + return this.dictionary.get(key); + } + + set(key, value) { + return this.dictionary.set(key, new Emote(value)); + } + + has(key) { + return this.dictionary.has(key); + } + + + ////////////////////////////////////////////////////////////////// + + bbtv_ToDict(json){ + for (let index = 0; index < json.length; index++) { + + const { emote, total } = json[index]; + + const url = `https://cdn.betterttv.net/emote/${emote.id}/3x`; + + this.dictionary.set(emote.code, new Emote({ code: emote.code, url })); + this.bttv_Dictionary.set(emote.code, new Emote({ code: emote.code, url })); + } + } + + bbtv_cached_ToDict(json){ + for (let index = 0; index < json.length; index++) { + + const { id, code } = json[index]; + + const url = `https://cdn.betterttv.net/emote/${id}/3x`; + + this.dictionary.set(code, new Emote({ code: code, url })); + this.bttv_Dictionary.set(code, new Emote({ code: code, url })); + } + } + + // loadEmote is where we collect an object array of emotes from bttv api + async loadBTTVEmote(){ + + // top 100 emotes query = ?limit=100&offset=100 + const bttv_top_api_url = "https://api.betterttv.net/3/emotes/shared/top?limit=100"; + const bttv_top_api_response = await fetch(bttv_top_api_url); + var top_Json = await bttv_top_api_response.json(); + + // tredning emotes + const bttv_trending_api_url = "https://api.betterttv.net/3/emotes/shared/trending?limit=100"; + const bttv_trending_api_response = await fetch(bttv_trending_api_url); + var trending_Json = await bttv_trending_api_response.json(); + + // global emotes are weird, stored in seperate cache and do not give all the normal attributes + const bttv_global_api_url = "https://api.betterttv.net/3/cached/emotes/global"; + const bttv_global_api_response = await fetch(bttv_global_api_url); + var global_Json = await bttv_global_api_response.json(); + + this.bbtv_ToDict(top_Json); + this.bbtv_ToDict(trending_Json); + this.bbtv_cached_ToDict(global_Json); + } + + //////////////////////////////////////////////////////////////// + + frankerToDict(json){ + for (let index = 0; index < json.emoticons.length; index++) { + + const { name, urls } = json.emoticons[index]; + + var url = ""; + if(urls[4] != undefined){ + url = urls[4]; + }else if(urls[2] != undefined){ + url = urls[2]; + }else{ + url = urls[1]; + } + + this.dictionary.set(name, new Emote({ code: name, url })); + this.franker_Dictionary.set(name, new Emote({ code: name, url })); + } + } + + // loadFrankerEmotes is where we collect an object array of emotes from franker api + async loadFrankerEmotes(){ + + const franker_top_api_url = "https://api.frankerfacez.com/v1/emoticons?sort=count-desc"; + + const first50Response = await fetch(franker_top_api_url); + var first50json = await first50Response.json(); + var next50Link = first50json._links.next; + const second50Response = await fetch(next50Link); + var second50json = await second50Response.json(); + + // Top 100 + this.frankerToDict(first50json); + this.frankerToDict(second50json); + } + + //////////////////////////////////////////////////////////////// + + twitchToDict(json){ + for (let index = 0; index < json.emotes.length; index++) { + + const { code, id } = json.emotes[index]; + + const url = `https://static-cdn.jtvnw.net/emoticons/v1/${id}/3.0`; + + this.dictionary.set(code, new Emote({ code: code, url })); + this.twitch_Dictionary.set(code, new Emote({ code: code, url })); + } + } + + // loadTwitchEmotes is where we collect an object array of emotes from twitch api + async loadTwitchEmotes(){ + + // https://api.twitchemotes.com/api/v4/channels/0 - twitch globals - 232 items + // https://static-cdn.jtvnw.net/emoticons/v1/25/1.0 - cdn + + // Global + const twitch_global_api_url = "https://api.twitchemotes.com/api/v4/channels/0"; + const twitch_global_api_response = await fetch(twitch_global_api_url); + var twitch_global_Json = await twitch_global_api_response.json(); + + this.twitchToDict(twitch_global_Json); + } + + // ♥ + specialEmotes(){ + + var emoteObj = { + "emotes": [ + { + "code": "wompWTF", + "url": "https://static-cdn.jtvnw.net/emoticons/v1/301653066/3.0" + }, + { + "code": "wompISeeYou", + "url": "https://static-cdn.jtvnw.net/emoticons/v1/301506153/3.0" + }, + { + "code": "wompCry", + "url": "https://static-cdn.jtvnw.net/emoticons/v1/301506193/3.0" + }, + { + "code": "BabyCorona", + "url": "https://static-cdn.jtvnw.net/emoticons/v1/301629296/3.0" + }, + { + "code": "LEL", + "url": "https://static-cdn.jtvnw.net/emoticons/v1/431249/3.0" + } + ] + }; + + for (let index = 0; index < emoteObj.emotes.length; index++) { + const element = emoteObj[index]; + const { code, url } = emoteObj.emotes[index]; + this.dictionary.set(code, new Emote({ code: code, url})); + this.specialEmotesDictionary.set(code, new Emote({ code: code, url})); + } + } +}// End Emotes + +export default new Emotes; \ No newline at end of file diff --git a/src/content/Message.js b/src/content/Message.js new file mode 100644 index 0000000..5d7a612 --- /dev/null +++ b/src/content/Message.js @@ -0,0 +1,255 @@ +import Emotes from './Emotes'; +import PersistentSyncStorage from 'src/helpers/PersistentSyncStorage'; + +var colorNumberIndex = 0; + +class Message { + constructor(messageNode) { + this.node = messageNode; + this.id = this.node.id; // this.id should not be used to reference the node, dom id changes due to optimisitc updates + this.hasEmotes = null; + this.observer = null; + this.parsedText = ''; // This should be fine since you can't edit/change messages + + this.parseText(); + + + + // Set Defaults + this.setDefaultSelections(); + + + if(this.hasEmotes) { + this.node.setAttribute('message-id', this.id); + this.setHtml(); + this.watch(); + } + } + + get textNode() { + const node = this.node.querySelector('#message'); + return { + node, + text: node.innerText + }; + } + + parseText() { + const rawWords = this.textNode.text.split(' '); + + for(let i = 0, length = rawWords.length; i < length; i++) { + const word = this.parseIllegalCharcters(rawWords[i]); + const emote = Emotes.get(word); + + //console.log(Emotes.get(word)); + + + if(typeof emote === 'undefined') { + this.parsedText += word + ' '; + } else { + this.hasEmotes = true; + this.parsedText += emote.html + ' '; + } + } + } + + watch() { + this.observer = new MutationObserver(mutations => { + let emoteRemoved = false; + + mutations.forEach(mutation => { + if(typeof mutation.removedNodes === 'undefined') return; + if(mutation.removedNodes.length <= 0) return; // This must be after undefined check + + for(let i = 0, length = mutation.removedNodes.length; i < length; i++) { + const removedNode = mutation.removedNodes[i]; + if(typeof removedNode.className === 'string' && // check if className exists, is 'SVGAnimatedString' when window resized and removed + ~removedNode.className.indexOf('Emote') !== 0) { + emoteRemoved = true; + } + } + + }); + + if(emoteRemoved && document.body.contains(this.node)) { + this.setHtml(); + } + }); + + this.observer.observe(this.node, { + childList: true, + attributes: false, + characterData: false, + subtree: true + }); + } + + setHtml() { + this.textNode.node.innerHTML = this.parsedText; + } + + parseIllegalCharcters(word) { + //  === 'ZERO WIDTH NO-BREAK SPACE' + return word.replace('', '').trim(); + } + + destroy() { + if(this.observer !== null) { + this.observer.disconnect(); + this.observer = null; + } + } + + /////////////////////////////////////////////////////////////////// + + // Setting Options for Each Message + setDefaultSelections(){ + + /////////////////////////////////////////////////////////////////// + + // Welcome Banner + var welcomBanner = document.querySelector("yt-live-chat-viewer-engagement-message-renderer"); + + // Set Hide Welcome Banner + if (PersistentSyncStorage.data.options.hideWelcomBanner) { + welcomBanner.classList.add("hideElement"); + } + + /////////////////////////////////////////////////////////////////// + + // Checks for kappa and replaces emoji element with kappa + if(PersistentSyncStorage.data.options.kappaFix) { + + var stupidKappa = document.querySelectorAll('#message.yt-live-chat-text-message-renderer .emoji.yt-live-chat-text-message-renderer'); + + for (let index = 0; index < stupidKappa.length; index++) { + const stupidElement = stupidKappa[index]; + var stupidToolTip = stupidElement.getAttribute('shared-tooltip-text'); + + if(stupidToolTip == ':full_moon_face:'){ + const newSpan = document.createElement('span'); + newSpan.classList.add('Emote'); + newSpan.innerHTML = 'kappa'; + + stupidElement.parentNode.replaceChild(newSpan, stupidElement); + } + } + } + /////////////////////////////////////////////////////////////////// + + //Set Author Colors + if(PersistentSyncStorage.data.options.setAuthorColor && this.node.getAttribute('author-type') !== 'owner') { + this.setAuthorColor(); + } + + /////////////////////////////////////////////////////////////////// + + // Author Icons + var author_photo = this.node.querySelector('#author-photo'); + + // Set Hide Author Icons + if (PersistentSyncStorage.data.options.hideAuthorIcons) { + author_photo.classList.add("hideElement"); + } + + // TimeStamp + var timestamp = this.node.querySelector('#timestamp'); + + // Set Show TimeStamp + if (PersistentSyncStorage.data.options.showTimeStamp) { + this.node.classList.add("showTimeStamp"); + } + + + /////////////////////////////////////////////////////////////////// + + // Author Name @ auto paste in text area + this.node.querySelector('#author-name').addEventListener("click", function(){ + var inputArea = document.querySelector('#input.yt-live-chat-text-input-field-renderer'); + var inputAreaLabel = document.querySelector('#label.yt-live-chat-text-input-field-renderer'); + inputArea.innerText = "@" + this.innerText; + const textLength = inputArea.innerText.length; + inputArea.focus(); + inputAreaLabel.innerText = ""; + }); + + + /////////////////////////////////////////////////////////////////// + + // Set Font Size + var textSizeSlider = PersistentSyncStorage.data.options.textSizeSlider; + + if (PersistentSyncStorage.data.options.allowTextSlider) { + this.node.setAttribute('style', 'font-size:' + textSizeSlider + 'px' + '!important'); + this.node.classList.add("AuthorFix"); + } + + /////////////////////////////////////////////////////////////////// + + // Set Twitch Styling + if (PersistentSyncStorage.data.options.setTwitchColors) { + this.node.classList.add("setTwitchColors"); + author_photo.classList.add("hideElement"); + } + + /////////////////////////////////////////////////////////////////// + + // Set Alternate message Colors + if (PersistentSyncStorage.data.options.alternateLineColor) { + this.alternateLineColor(); + } + + }// end setDefaultSelections + + setAuthorColor() { + + let imageSrc = null; + + if(this.node.hasChildNodes && this.node.contains(this.node.querySelector('#author-photo'))){ + + if(this.node.querySelector('#author-photo').querySelector('img').src != null){ + imageSrc = this.node.querySelector('#author-photo').querySelector('img').src; + + const idRegexp = /\/-([A-Za-z-_\d])/; + + try { + if(idRegexp.exec(imageSrc) !== null){ + const parsedSRC = idRegexp.exec(imageSrc)[1]; + this.node.classList.add(`chat-color-${parsedSRC}`); + } + } catch (error) { + // for some reason nodes from user img.src are getting weird link on occasion + console.log(error); + console.log(imageSrc); + } + } + } + } + + /////////////////////////////////////////////////////////////////// + + // changes color every line + alternateLineColor(){ + + if(colorNumberIndex % 2 == 0){ + this.node.classList.add("set-background-color-one"); + } + if(colorNumberIndex % 2 !== 0){ + this.node.classList.add("set-background-color-two"); + } + colorNumberIndex++; + } + + /////////////////////////////////////////////////////////////////// + + // removes color attr + removelternateLineColor(){ + this.node.classList.remove("set-background-color-one"); + this.node.classList.remove("set-background-color-two"); + } + +}// end Message + + + +export default Message; \ No newline at end of file diff --git a/src/content/RouteWatcher.js b/src/content/RouteWatcher.js new file mode 100644 index 0000000..355f4b5 --- /dev/null +++ b/src/content/RouteWatcher.js @@ -0,0 +1,39 @@ +import EventEmitter from 'events'; + +class RouteWatcher extends EventEmitter { + constructor() { + super(); + + this.target = document.querySelector('head > title'); + this.observer = null; + + this.init(); + } + + init() { + this.observer = new MutationObserver(mutations => { + mutations.forEach((m) => { + /** + * Title is set to 'YouTube Gaming' on main routes + * and between routes. + */ + if(m.target.innerText === 'YouTube Gaming') { + this.emit('main'); + } else { + this.emit('change'); + } + }); + }); + + if(this.target !== null) { // Popout chat does not have title tag + this.observer.observe(this.target, { + childList: true, + attributes: false, + characterData: true, + subtree: true + }); + } + } +} + +export default RouteWatcher; diff --git a/src/content/index.js b/src/content/index.js new file mode 100644 index 0000000..755258c --- /dev/null +++ b/src/content/index.js @@ -0,0 +1,188 @@ +import "src/stylus/content.styl"; +import ChatScroller from "./ChatScroller"; +import ChatWatcher from "./ChatWatcher"; +import RouteWatcher from "./RouteWatcher"; + + +import { + isLivestream, isYoutubeGaming, + isYoutubeEmbed, isYoutubeVanilla, + isPopOut +} from "src/helpers/Identification"; + +import PersistentSyncStorage from "src/helpers/PersistentSyncStorage"; + +let MAIN = null; +const theater_wrapper = document.createElement('theater_wrapper'); +document.body.appendChild(theater_wrapper); +var alreadyTheater = false; + +// --- + +class Main { + constructor() { + this.chatWatcher = null; + this.chatScroller = null; + this.routeWatcher = null; + this.onRouteChange = this.onRouteChange.bind(this); + this.load(); + + + // button class - ytp-size-button ytp-button + // right player controls - ytp-right-controls + // player div id - ytd-player + // chatframe id - chatframe + // movieframe id - movie_player_fix + // dono ticker id - ticker + + // player-theater-container + } + + load() { + this.routeWatcher = new RouteWatcher(); + this.routeWatcher.on("change", this.onRouteChange); + this.onRouteChange(); + } + + onRouteChange() { + if(isLivestream() && ((isYoutubeGaming()) || (isYoutubeVanilla()) || (isYoutubeEmbed()) || isPopOut())) { + this.init(); + } + + if(isLivestream()) { + if (PersistentSyncStorage.data.options.theaterModeFix) { + if(document.getElementById('player-container') != null && document.getElementById('player-theater-container') != null){ + theaterMode(); + } + } + } + }// end onRouteChange + + init() { + + this.chatWatcher = new ChatWatcher(); + this.chatWatcher.init(); + this.chatScroller = new ChatScroller(); + this.chatScroller.init(); + + setDefaults(); + console.log("INIT"); + + }// end init + +}// end main + + + function setDefaults() { + + /////////////////////////////////////////////////////////////////// + + //Live Chat Default Option + if (PersistentSyncStorage.data.options.setLiveChat) { + document.getElementsByClassName("yt-simple-endpoint style-scope yt-dropdown-menu").item(1).click(); + } else { + // do nothing, let user pick option if not set as default in options menu + } + + /////////////////////////////////////////////////////////////////// + + } + +// --- Every Frame Loaded +PersistentSyncStorage.on("ready", () => { + MAIN = new Main(); +}); + + +function checkMode(){ + + if(alreadyTheater){ + console.log('enterTheater'); + alreadyTheater = false; + enterTheaterMode(); + }else{ + // is reverse because at the time of check dom elements havent moved yet + if(document.getElementById('player-theater-container').contains(document.getElementById('player-container'))){ + console.log('exitTheater'); + exitTheaterMode(); + }else{ + console.log('enterTheater'); + enterTheaterMode(); + } + } +} + +function enterTheaterMode() { + + const movie_player = document.getElementById('movie_player'); + const chat_frame = document.getElementById('chatframe'); + const info_frame = document.getElementById('info-contents'); + + const masthead_container = document.getElementById('masthead-container'); + + + masthead_container.hidden = true; + + theater_wrapper.classList.add('theater_wrapper_fix'); + movie_player.classList.add('movie_player_fix'); + chat_frame.classList.add('chat_frame_fix'); + info_frame.classList.add('info_contents_fix'); + + + theater_wrapper.append(info_frame); + theater_wrapper.append(movie_player); + theater_wrapper.append(chat_frame); + + document.body.classList.add('body_Fix'); + + +}// end enterTheaterMode + +function exitTheaterMode(){ + + const movie_player = document.getElementById('movie_player'); + const chat_frame = document.getElementById('chatframe'); + const info_frame = document.getElementById('info-contents'); + + const movie_player_container = document.getElementById('player-container'); + const player_container_parent = document.getElementById('player-container-inner'); + + const chat_frame_parent = document.getElementById('chat'); + const info_frame_before = document.getElementById('meta'); + + const masthead_container = document.getElementById('masthead-container'); + + + masthead_container.hidden = false; + + theater_wrapper.classList.remove('theater_wrapper_fix'); + movie_player.classList.remove('movie_player_fix'); + chat_frame.classList.remove('chat_frame_fix'); + info_frame.classList.remove('info_contents_fix'); + + movie_player_container.prepend(movie_player); + player_container_parent.prepend(movie_player_container); + chat_frame_parent.prepend(chat_frame); + info_frame_before.before(info_frame); + + document.body.classList.remove('body_Fix'); +} + +function theaterMode(){ + + var theaterButton = document.querySelector('button.ytp-size-button.ytp-button'); + + if(theaterButton){ + + + if(document.getElementById('player-theater-container').contains(document.getElementById('player-container'))){ + + // for when page loads first time - check is reversed after this + alreadyTheater = true; + checkMode(); + } + + // add button + theaterButton.addEventListener('click', checkMode, false); + } +} diff --git a/src/helpers/Identification.js b/src/helpers/Identification.js new file mode 100644 index 0000000..ecf54b9 --- /dev/null +++ b/src/helpers/Identification.js @@ -0,0 +1,48 @@ +export const isLivestream = () => { + const timeDisplay = document.querySelector('.ytp-time-display'); + const chatApp = document.querySelector('yt-live-chat-app'); + const chatHeader = document.querySelector('.yt-live-chat-renderer-0'); + const timeDisplayCheck = timeDisplay && timeDisplay.classList.contains('ytp-live'); + const chatCheck = (document.body.contains(chatApp) || document.body.contains(chatHeader)); + + return (timeDisplayCheck || chatCheck); +}; + +// isYoutubeGaming checks for the presence of ytg-app, the top level element for YT Gaming +export const isYoutubeGaming = () => { + return !!document.querySelector('ytg-app'); +}; + +// isYoutubeEmbed checks that this is an iframe, and it is being used on youtube.com +export const isYoutubeVanilla = () => { + // window.frameElement is only available from youtube.com sites from within iframe per CORS + return !!window.frameElement; +}; + +// isYoutubeEmbed checks that this is an iframe, and it is **not** loaded from youtube.com (main site uses embed too) +export const isYoutubeEmbed = () => { + + // If the frameElement is available, then CORS means that we must be on youtube.com. + if (window.frameElement) { + return false; + } + + // If the window location isn't the parent location, then we are in an iframe. + return (window.location != window.parent.location); +}; + +// isPopOut fix for popout page +export const isPopOut = () => { + + // If the frameElement is available, then CORS means that we must be on youtube.com. + if (window.frameElement) { + return false; + } + + // Checks href for page + if(window.location.href.includes('is_popout=1')){ + return !!window.location.href.includes('popout=1'); + } + + return false; +}; \ No newline at end of file diff --git a/src/helpers/OpenActiveTab.js b/src/helpers/OpenActiveTab.js new file mode 100644 index 0000000..b22d1dd --- /dev/null +++ b/src/helpers/OpenActiveTab.js @@ -0,0 +1,20 @@ + + +/* Open new tab if tab is not already open, otherwise focus that tab */ +export default url => { + const matchUrl = url.replace(/^(https|http)/i, '*'); + chrome.tabs.query({ url: matchUrl }, tabs => { // url must be valid match pattern - https://developer.chrome.com/extensions/match_patterns + if(tabs && tabs.length) { + // tab.id is not present in some rare cases, so if error around here, that could be the cause. + chrome.tabs.update(tabs[0].id, { active: true }); + } else { + chrome.tabs.create({ url }); + } + }); + + // for(let i = 0, tab; tab = tabs[i]; i++) { + // if(tab.url && tab.url === url) { + // return; + // } + // } +}; diff --git a/src/helpers/PersistentSyncStorage.js b/src/helpers/PersistentSyncStorage.js new file mode 100644 index 0000000..aeae526 --- /dev/null +++ b/src/helpers/PersistentSyncStorage.js @@ -0,0 +1,51 @@ +import { SyncStorage } from '../utils/chrome'; +import { EventEmitter } from 'events'; + +class PersistentSyncStorage extends EventEmitter { + constructor() { + super(); + + this._data = null; + this.state = 'initiating'; + + this._init(); + } + + async _init() { + const fetchedData = await SyncStorage.get(); + this._initListener(); + this._data = fetchedData; + this.state = 'ready'; + this.emit(this.state); + } + + _initListener() { + SyncStorage.listen((changes) => { + + Object.keys(changes).forEach((changeKey) => { + if(changes[changeKey].hasOwnProperty('newValue')) { + this._data[changeKey] = changes[changeKey].newValue; + } else { + console.error('No newValue in sync storge change'); + } + }); + + this.emit('change', this.data, changes); + }); + } + + set(items) { + return SyncStorage.set(items); + } + + get data() { + return this._data; + } + + + has(item) { + return this.data.hasOwnProperty(item); + } +} + +export default new PersistentSyncStorage(); \ No newline at end of file diff --git a/src/html/options.html b/src/html/options.html new file mode 100644 index 0000000..91e5475 --- /dev/null +++ b/src/html/options.html @@ -0,0 +1,165 @@ + + + + + + Options + + + + + 🔴 + + +

Live Chat Options

+
+ + + + +
+
+ +
+
+

Emote Options

+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+ +
+
+
+
+
+
+ +
+ + +
+ +
+

Chat Options

+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+ +
+

Font Size

+ + + + + +
+
+
+ +
+
+ +
+
+ +
+
+
+
+
 
+ +
+ +
+ + + + + \ No newline at end of file diff --git a/src/html/welcome.html b/src/html/welcome.html new file mode 100644 index 0000000..e1564a7 --- /dev/null +++ b/src/html/welcome.html @@ -0,0 +1,96 @@ + + + + + + + Welcome Page + + + +
+ +
+ done +
+ +
+ +
+ + +

Welcome to the Chat

+ +

This is still very beta

+ +
+ + + +
+ +

+ Soon to come: +

+ +
    +
  • Specific channel Emotes
  • +
  • Search for Emote Panel
  • +
  • Autocomplete for emote Selection
  • +
  • Theater Mode Fix for that quality Stream and Chat time
  • +
  • Moderation Options
  • +
  • User Profile Info
  • +
  • Other Styling Options
  • +
+ +
+ +

How To:

+ +

+ There is still a lot of stuff I am working on. This is very Beta at the moment so +

+

Use At Your Own Risk

+

+ This is a Chrome Extension for Youtube Live Streams, adding some Quality of Life improvements for the Chat. + Adds Top, Trending and Global (500ish) Emotes from popular sites. These Update with what is Trending. +

+

+ Don't forget to pin this extension for easy access. +

+ pinYourExtension.gif +

+ Youtube Live is slow to load its pages currently. + Give the extension a moment while the page's iframes are loading. + Once you see the Emote Panel Icon you can open the Emote Selection Panel. +

+ emotesMenu.gif +

+ Enhanced Theater Mode Is Now Available. Just click the check in the option panel and refresh your page. +

+ theaterMode.gif +

+ Over around 500 Top and Trending Emotes are loaded from popular sites. + You can Enable/Disable them in the Options Menu. +

+ optionsMenu.gif +

+ Can Also Click on UserNames To Autofill an @ Notification +

+ clickUserNamesToAtThem.gif + +

Use At Your Own Risk

+ +

Enjoy!

+
+ + + + \ No newline at end of file diff --git a/src/manifest.json b/src/manifest.json new file mode 100644 index 0000000..6d74a33 --- /dev/null +++ b/src/manifest.json @@ -0,0 +1,48 @@ +{ + "manifest_version": 2, + + "name": "🔴 LIVE CHAT", + "version": "1.0.1", + "description": "Enhances the YouTube Live Streaming experience with Emotes, Custom Styling and quality of life improvements.", + "icons": { + "48": "assets/icons/icon48.png", + "128": "assets/icons/icon128.png", + "512": "assets/icons/icon512.png" + }, + + "permissions": [ + "storage", + "background" + ], + + "options_ui": { + "page": "html/options.html", + "chrome_style": true + }, + + "browser_action": { + "default_popup": "html/options.html", + "chrome_style": true + }, + + "background": { + "scripts": [ + "background.js" + ] + }, + + "content_scripts": [ + { + "matches": [ + "*://*.youtube.com/*" + ], + "js": [ "content.js" ], + "run_at": "document_end", + "all_frames": true + } + ], + + "web_accessible_resources": [ + "assets/*" + ] +} diff --git a/src/options.js b/src/options.js new file mode 100644 index 0000000..8f7648f --- /dev/null +++ b/src/options.js @@ -0,0 +1,155 @@ + +import './stylus/options.styl'; +import dateFormat from 'date-fns/format'; +import { debounce } from 'lodash'; +import PersistentSyncStorage from './helpers/PersistentSyncStorage'; + + + +// hides element after short timeout +const hideDebounce = debounce(ele => { + ele.classList.remove('show'); +}, 1000); + +// little popup/fade save status message +const setSavingStatus = (status) => { +const SaveStatusEle = document.getElementById('save-status'); + + switch(status) { + case 'saving': + SaveStatusEle.innerHTML = 'Saving ...'; + break; + case 'saved': + SaveStatusEle.innerHTML = 'Saved'; + hideDebounce(SaveStatusEle); + break; + default: + SaveStatusEle.innerHTML = ' '; + } + + SaveStatusEle.classList.add('show'); +}; + + +/////////////////////////////////////////////////////////////////////////////// + +var textSizeSlider = document.getElementById("textSizeSlider"); +var allowTextSlider = document.getElementById("allowTextSlider"); + +var sliderValue; +textSizeSlider.oninput = function(){ + sliderValue = textSizeSlider.value; +}; + +allowTextSlider.oninput = function(){ + + if(allowTextSlider.checked == true){ + textSizeSlider.disabled = false; + }else { + textSizeSlider.disabled = true; + } + +}; + + +const optionOnChange = (input) => { + + var inputValueKey; + + if(input.id === 'textSizeSlider'){ + inputValueKey = input.value; + if(PersistentSyncStorage.data.options.hasOwnProperty(input.id)) { + inputValueKey = PersistentSyncStorage.data.options[input.id]; + textSizeSlider.value = inputValueKey; + } + }else{ + inputValueKey = 'checked'; + if(PersistentSyncStorage.data.options.hasOwnProperty(input.id)) { + input[inputValueKey] = PersistentSyncStorage.data.options[input.id]; + } + } + + const eventType = 'change'; + + const onChange = (() => { + const saveOption = () => { + + setSavingStatus('saving'); + + // [input.id]: inputValueKey | number vs true or false statement| [input.id]: input[inputValueKey] + if(input.id === 'textSizeSlider'){ + + inputValueKey = sliderValue; + + const updatedOptions = Object.assign({}, PersistentSyncStorage.data.options, { + [input.id]: inputValueKey + }); + + PersistentSyncStorage.set({ options: updatedOptions }) + .then(() => { + setSavingStatus('saved'); + }); + + }else{ + const updatedOptions = Object.assign({}, PersistentSyncStorage.data.options, { + [input.id]: input[inputValueKey] + }); + + PersistentSyncStorage.set({ options: updatedOptions }) + .then(() => { + setSavingStatus('saved'); + }); + } + }; + + return saveOption; + })(); + + return onChange; +}; + + +// Executed code +const OptionInputs = document.querySelectorAll('.option-input'); + +PersistentSyncStorage.on('ready', () => { + + OptionInputs.forEach((input) => { + const inputOnChange = optionOnChange(input); + input.addEventListener('change', inputOnChange); + + + switch (input.id) { + case 'allowTextSlider': + input.removeAttribute('disabled'); + + + if(PersistentSyncStorage.data.options.allowTextSlider == true){ + textSizeSlider.disabled = false; + }else{ + textSizeSlider.disabled = true; + } + break; + + case 'theaterModeFix': + // do nothing, stay disabled + input.removeAttribute('disabled'); + break; + + case 'textSizeSlider' : + // do nothing + break; + + default: + input.removeAttribute('disabled'); + break; + } + }); +}); + +var infoButton = document.getElementById('infoButton'); +infoButton.addEventListener('click', function(){ + chrome.tabs.create({ url: './html/welcome.html' }); +}); + + diff --git a/src/stylus/_chatColors.styl b/src/stylus/_chatColors.styl new file mode 100644 index 0000000..14e27d2 --- /dev/null +++ b/src/stylus/_chatColors.styl @@ -0,0 +1,73 @@ +colors = { + 'A': #f44336, + 'B': #e91e63, + 'C': #9c27b0, + 'D': #673ab7, + 'E': #536dfe, + 'F': #2196f3, + 'G': #03a9f4, + 'H': #00bcd4, + 'I': #009688, + 'J': #4caf50, + 'K': #8bc34a, + 'L': #cddc39, + 'M': #ffeb3b, + 'N': #ffc107, + 'O': #ff9800, + 'P': #ff5722, + 'Q': #f44336, + 'R': #e91e63, + 'S': #9c27b0, + 'T': #673ab7, + 'U': #536dfe, + 'V': #2196f3, + 'W': #03a9f4, + 'X': #00bcd4, + 'Y': #009688, + 'Z': #4caf50, + + 'a': #8bc34a, + 'b': #cddc39, + 'c': #ffeb3b, + 'd': #ffc107, + 'e': #ff9800, + 'f': #ff5722, + 'g': #f44336, + 'h': #e91e63, + 'i': #9c27b0, + 'j': #673ab7, + 'k': #536dfe, + 'l': #2196f3, + 'm': #03a9f4, + 'n': #00bcd4, + 'o': #009688, + 'p': #4caf50, + 'q': #8bc34a, + 'r': #cddc39, + 's': #ffeb3b, + 't': #ffc107, + 'u': #ff9800, + 'v': #ff5722, + 'w': #f44336, + 'x': #e91e63, + 'y': #9c27b0, + 'z': #673ab7, + + '0': #536dfe, + '1': #2196f3, + '2': #03a9f4, + '3': #00bcd4, + '4': #009688, + '5': #4caf50, + '6': #8bc34a, + '7': #cddc39, + '8': #ffeb3b, + '9': #ffc107, + '-': #ff9800, + '_': #ff5722, +} + +for id, col in colors + .chat-color-{id} #content #author-name + color: col !important + diff --git a/src/stylus/content.styl b/src/stylus/content.styl new file mode 100644 index 0000000..5fc8fc6 --- /dev/null +++ b/src/stylus/content.styl @@ -0,0 +1,223 @@ +@import '_chatColors.styl' + +.item-offset + //height: 100% + +#items + // Chat user avatar + img.yt-img-shadow + //height: inherit; + //width: inherit; + //align-content: center; + //display: initial; + //border-radius: inherit; + + + + // Owner chat messages + .yt-live-chat-item-list-renderer[author-type="owner"] + //background: rgba(#fff, 0.1); + #content #author-name + //text-shadow: #ffd600 0px 0px 10px + + // Chat user menu button (3 dot menu) + #menu #menu-button.yt-live-chat-text-message-renderer + //padding: 5px !important + //width: 28px !important + //height: 28px !important + + + // Chat user name + #author-name.yt-live-chat-text-message-renderer + &:after + //content: ' :' + //color: #fff + + +.AuthorFix + #author-photo.yt-live-chat-text-message-renderer + img.yt-img-shadow + display: inline-block + vertical-align: middle + border-radius: 50%; + height: 1.5em; + width: 1.5em; + vertical-align: sub; + #content + display: inline-block + vertical-align: middle + #timestamp.yt-live-chat-text-message-renderer + font-size: 1em + display: inline-block + vertical-align: middle + +.showTimeStamp + #timestamp.yt-live-chat-text-message-renderer + display: inline-block + + +.Emote + img + height: 1.75em + align-self: center + vertical-align: sub; + display:inline-block + vertical-align: middle + +emote_div:hover + background-size: 100% //100% + background-color: rgba(255, 255, 255, .6) + +.hideElement + display: none !important + +.set-background-color-one + background-color: #303030 !important + +.set-background-color-two + background-color: transparent !important + +.setTwitchColors + text-shadow: 0 0 1px #000, 0 0 2px #000 !important + background: #18181b !important + font-family: 'Roboto' !important + font-size: 1.3rem !important + line-height: 1.5em !important + color: #FAFAFA !important + #timestamp.yt-live-chat-text-message-renderer + display: none + yt-live-chat-author-chip[is-highlighted] #author-name.owner.yt-live-chat-author-chip, #author-name.owner.yt-live-chat-author-chip + background-color: transparent + color: green + yt-live-chat-author-chip[is-highlighted] #author-name.yt-live-chat-author-chip + background-color: transparent + +.emoteDivider + width: 60vw + border: 2px solid #d3d3d3; + border-radius: 5px; + margin-top: 2%; + margin-bottom: 2%; + margin-left: auto + margin-right: auto + +.emotePopUpText + margin-bottom: 2%; + + +.popup + background-color: #202020 + position: absolute; + top: 15% + left: 0 + right: 0 + margin-left: auto + margin-right: auto + height 70% + width: 75% + z-index: 999 + text-align: center + border-radius: 5px + border: #303030 1px solid + font-size: 1em + overflow: hidden + overflow-y: scroll + padding: 1%; + padding-top: 2%; + +.emoteButton + background-color:rgba(255, 255, 255, .1); + background-image: url("https://cdn.frankerfacez.com/emoticon/447885/4") + background-repeat: no-repeat + background-position: center + background-size: 80% 80%; + width: var(--yt-live-chat-32px-icon-button_-_width) + height: var(--yt-live-chat-32px-icon-button_-_height) + padding: var(--yt-live-chat-32px-icon-button_-_padding) + border-radius: 10px; + border: none + cursor: pointer + +.emoteButton:hover + background-color:rgba(255, 255, 255, .8) + +.emoteButton:focus + outline:0 + +.body_Fix + height: 100% !important + margin: 0 !important + overflow: hidden !important + +.theater_wrapper_fix + padding: 2px; + background-color: #1e1e1e; + position: fixed + z-index: 900 !important + height: 100vh !important + width: 100vw !important + +.movie_player_fix + height: 100vh; + position: absolute; + width: calc(100vw - 25vw); + video + left: 0 !important + top: 0 !important + height: 100vh !important + width: calc(100vw - 25vw) !important + #html5-video-player + top: 0 !important + width: calc(100vw - 25vw) !important + .ytp-title + color: rgba(255, 255, 255, .8) !important + .ytp-title-channel + all: unset + .ytp-gradient-top + max-width: calc(100vw - 25vw) !important + .ytp-chrome-bottom + width: calc(100vw - 25vw) !important + left: 0 !important + .html5-endscreen + width: calc(100vw - 25vw) !important + .ytp-chapter-hover-container + width: calc(100vw - 25vw) !important + .ytp-gradient-bottom + width: calc(100vw - 25vw) !important + .ytp-iv-video-content + width: calc(100vw - 25vw) !important + left: 0 !important + .ytp-player-content.ytp-iv-player-content + width: calc(100vw - 25vw) !important + left: -12px !important + bottom: 10vh !important; + .ytp-upnext.ytp-player-content.ytp-upnext-autoplay-paused.ytp-suggestion-set + width: calc(100vw - 25vw) !important + left: 0 !important + .ytp-bezel-text-hide + width: calc(100vw - 25vw) !important + left: 0 !important + .ytp-spinner + left: 40% !important + .ytp-cued-thumbnail-overlay + width: calc(100vw - 25vw) !important + +.info_contents_fix + z-index: 901 !important + height: 80px + top: 0 + position: absolute !important + width: calc(100vw - 25vw) !important + + ytd-video-primary-info-renderer + padding: 1rem + border-bottom: none + +.chat_frame_fix + height: 100vh !important + width: calc(calc(100vw - 75vw) - 1px) !important; + position: absolute !important + right: 0px !important + top: 0px !important + border: 1px solid #4e4e4e + \ No newline at end of file diff --git a/src/stylus/options.styl b/src/stylus/options.styl new file mode 100644 index 0000000..3a07092 --- /dev/null +++ b/src/stylus/options.styl @@ -0,0 +1,76 @@ +body + background-color: #1e1e1e + color: #ffffff + +.section + &:nth-child(1) + .options-heading + margin: 0 + +.options-heading + margin: 10px 0 0 0 + +.options-description + margin: 0 0 10px 0 + opacity: 0.8 + +table + border: none + border-spacing: 0 + width: 100% + tr td + padding: 0 + &:nth-child(1) + width: 80% + &:nth-child(2) + width: 20% + text-align: right + +.hr + background-color: #d1d1d1 + height: 1px + margin: 10px 0 + +#save-status + text-align: center + opacity: 0 + transition: all 1s linear + &.show + opacity: 1 + transition: none + +.options-table + .option-row + display:flex + flex-direction: row + align-items: space-between + justify-content: space-between + .option-cell + padding-right: 5px + &:last-child + padding-right: 0px + +.light-text + color: rgba(#000, 0.6) + +input[type=checkbox][disabled] + outline: 1px solid red + cursor: not-allowed + opacity: .9 + +.info_button + display:inline-block + padding:0.3em 1.2em + margin:0 0.3em 0.3em 0 + border-radius:2em + box-sizing: border-box + text-decoration:none + font-weight:300 + color:#1e1e1e + text-align:center + margin-left: 150px + transition: all 0.2s + +.info_button:hover + color: red + diff --git a/src/stylus/setupPage.styl b/src/stylus/setupPage.styl new file mode 100644 index 0000000..c24375e --- /dev/null +++ b/src/stylus/setupPage.styl @@ -0,0 +1,146 @@ +@import url("https://fonts.googleapis.com/css?family=Roboto:300,400,700|Material+Icons") + +body + font-family: 'Roboto', Arial, sans-serif + font-size: 16px + background: #222 + color: #fff + margin: 25px + +font-weights = { + light: 300, + regular: 400, + bold: 700 +} +for fw, w in font-weights + .fw-{fw} + font-weight: w + +.success-overlay + visibility: hidden + opacity: 0 + position: fixed + top: 0 + left: 0 + z-index: 10 + background: rgba(#191919, 0.95) + display: flex + flex-direction: column + align-items: center + justify-content: center + height: 100% + width: 100% + transition: visibility 0s, opacity 200ms ease + &.show + visibility: visible + opacity: 1 + .material-icons + font-size: 20em + opacity: 0 + &.show + opacity: 1 + animation: jackInTheBox 700ms 1 + .success-message + font-size: 3em + .close-message + font-size: 0.7em + opacity: 0.7 + +.container + display: flex + flex-direction: column + align-items: center + h1 + margin: 0 + font-size: 3em + letter-spacing: 3px + .heading-note + font-size: 18px + color: #bbb + .option + text-align: center + .option-note + font-size: 12px + font-style: italic + color: #999 + .complete-setup-button + background: #333 + display: flex + justify-content: center + align-items: center + padding: 10px + cursor: pointer + text-transform: uppercase + border-radius: 3px + box-shadow: 0 2px 5px 0 rgba(#000, 0.7) + transition: background 50ms ease + &:hover + background: #404040 + .material-icons + margin-right: 7px + + +.links_bottom + display: inline-block; + margin: 1% + + +a + background-color: #252526; + color: white; + padding-top: 1em; + padding-bottom: 1em; + text-decoration: none; + text-transform: uppercase; + width: 100%; + table-layout: fixed; + border-collapse: collapse; + text-align: center + border: 1px solid #4e4e4e + +a:hover + background-color: #d3d3d3; + color: black + + +a:active + box-shadow: none; + top: 5px; + +.links_div + width: 20vw + +p + margin: 2% + max-width: 30vw + +h2 + margin: 2% + +hr { + margin: 2% + width: 60vw + border: 3px solid #d3d3d3; + border-radius: 5px; +} + + + + +// jackInTheBox from animate.css https://github.com/daneden/animate.css +@keyframes jackInTheBox + from + opacity: 0 + transform: scale(0.1) rotate(60deg) + transform-origin: center center + + 50% + transform: rotate(-20deg) + + 70% + opacity: 1 + transform: rotate(6deg) + + to + transform: scale(1) + diff --git a/src/utils/chrome/LocalStorage.js b/src/utils/chrome/LocalStorage.js new file mode 100644 index 0000000..e73ffff --- /dev/null +++ b/src/utils/chrome/LocalStorage.js @@ -0,0 +1,35 @@ +/** +* MIT License +* +* Copyright (c) 2020 wompmacho +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +*/ + + +import Storage from './Storage'; + +class LocalStorage extends Storage { + constructor() { + super(); + this.store = 'local'; + } +} + +export default LocalStorage; diff --git a/src/utils/chrome/Notifications.js b/src/utils/chrome/Notifications.js new file mode 100644 index 0000000..4501fe1 --- /dev/null +++ b/src/utils/chrome/Notifications.js @@ -0,0 +1,115 @@ +/** +* MIT License +* +* Copyright (c) 2020 wompmacho +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +*/ + + +class Notifications { + + create(notificationId = null, options) { + // notificationId is optional + if(typeof notificationId === 'object') { + options = notificationId; + notificationId = null; + } + + return new Promise((res, rej) => { + // resolve args = notificationId:string + chrome.notifications.create(notificationId, options, res); + }); + } + + update(notificationId, options) { + return new Promise((res, rej) => { + // resolve args = wasUpdated:boolean + chrome.notifications.update(notificationId, options, res); + }); + } + + clear(notificationId) { + return new Promise((res, rej) => { + // resolve args = wasCleared:boolean + chrome.notifications.clear(notificationId, res); + }); + } + + getAll() { + return new Promise((res, rej) => { + // resolve args = notifications:object + chrome.notifications.getAll(res); + }); + } + + getPermissionLevel() { + return new Promise((res, rej) => { + // resolve args = level:PermissionLevel (https://developer.chrome.com/apps/notifications#type-PermissionLevel) + chrome.notifications.getPermissionLevel(res); + }); + } + + listen(event, notificationId = null, callback) { + // event = 'onClosed' | 'onClicked' | 'onButtonClicked' | 'onPermissionLevelChanged' | 'onShowSettings' + // notificationId is optional + if(typeof notificationId === 'function') { + callback = notificationId; + notificationId = null; + } + + if(event === 'onPermissionLevelChanged' || event === 'onShowSettings') { + return this._nonNotificationIdListen(event, callback); + } + + /** + * https://developer.chrome.com/apps/notifications#events + * + * Resolve args (by event): + * onClosed = notificationId:string, byUser:boolean + * onClicked = notificationId:string + * onButtonClicked = notificationId:string, buttonIndex:integer + * + * onPermissionLevelChanged = level:PermissionLevel (https://developer.chrome.com/apps/notifications#type-PermissionLevel) + * onShowSettings = (none) + */ + + // This callback relates only to those events that have notificationId arg + const ListenerCallback = (() => { + if(notificationId !== null) { + return (passedNotificationId, ...args) => { + if(notificationId === passedNotificationId) { + callback(passedNotificationId, ...args); + } + }; + } else { + return callback; + } + })(); + + + chrome.notifications[event].addListener(ListenerCallback); + } + + _nonNotificationIdListen(event, callback) { + chrome.notifications[event].addListener(callback); + } +} + +export default Notifications; diff --git a/src/utils/chrome/Storage.js b/src/utils/chrome/Storage.js new file mode 100644 index 0000000..b1e390d --- /dev/null +++ b/src/utils/chrome/Storage.js @@ -0,0 +1,92 @@ +/** +* MIT License +* +* Copyright (c) 2020 wompmacho +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +*/ + + +class Storage { + + get(keys = null) { + return new Promise((res, rej) => { + const returnSingle = typeof keys === 'string' || typeof keys === 'number'; + // resolve args = items:object + chrome.storage[this.store].get(keys, (items) => { + if(returnSingle) { + res(items[keys]); + } else { + res(items); + } + }); + }); + } + + getBytesInUse(keys = null) { + return new Promise((res, rej) => { + // resolve args = bytesInUse:integer + chrome.storage[this.store].getBytesInUse(keys, res); + }); + } + + set(items) { + return new Promise((res, rej) => { + // resolve args = (none) + chrome.storage[this.store].set(items, res); + }); + } + + remove(keys) { + // resolve args = (none) + return new Promise((res, rej) => { + chrome.storage[this.store].remove(keys, res); + }); + } + + clear() { + // resolve args = (none) + return new Promise((res, rej) => { + chrome.storage[this.store].clear(res); + }); + } + + listen(item, onChange) { + if(typeof item === 'function') { + onChange = item; + item = null; + } + + chrome.storage.onChanged.addListener((changes, areaName) => { + if(areaName === this.store) { + if(item !== null) { + if(changes.hasOwnProperty(item)) { + const oldValue = changes[item].oldValue || null; + const newValue = changes[item].newValue || null; + onChange(oldValue, newValue); + } + } else { + onChange(changes); + } + } + }); + } +} + +export default Storage; diff --git a/src/utils/chrome/SyncStorage.js b/src/utils/chrome/SyncStorage.js new file mode 100644 index 0000000..33292b9 --- /dev/null +++ b/src/utils/chrome/SyncStorage.js @@ -0,0 +1,35 @@ +/** +* MIT License +* +* Copyright (c) 2020 wompmacho +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +*/ + + +import Storage from './Storage'; + +class SyncStorage extends Storage { + constructor() { + super(); + this.store = 'sync'; + } +} + +export default SyncStorage; diff --git a/src/utils/chrome/index.js b/src/utils/chrome/index.js new file mode 100644 index 0000000..abf1499 --- /dev/null +++ b/src/utils/chrome/index.js @@ -0,0 +1,37 @@ +/** +* MIT License +* +* Copyright (c) 2020 wompmacho +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +*/ + +import _LocalStorage from './LocalStorage'; +import _SyncStorage from './SyncStorage'; +import _Notifications from './Notifications'; + +// export default { +// LocalStorage: new _LocalStorage, +// SyncStorage: new _SyncStorage, +// Notifications: new _Notifications +// } + +export const LocalStorage = new _LocalStorage; +export const SyncStorage = new _SyncStorage; +export const Notifications = new _Notifications; \ No newline at end of file diff --git a/src/welcomePage.js b/src/welcomePage.js new file mode 100644 index 0000000..744e748 --- /dev/null +++ b/src/welcomePage.js @@ -0,0 +1,71 @@ + +import './stylus/setupPage.styl'; +import PersistentSyncStorage from './helpers/PersistentSyncStorage'; + + +// THIS IS A JS PAGE FOR SETUP.HTML + + +// --- Definitions --- +const completeButton = document.querySelector('.complete-setup-button'); +const successOverlay = document.querySelector('.success-overlay'); +const successIcon = successOverlay.querySelector('.material-icons'); +const successCloseMessageCountdown = successOverlay.querySelector('.countdown'); + +const setupComplete = () => { + + // successOverlay.classList.add('show'); + + // setTimeout(() => { + // successIcon.classList.add('show'); + // }, 100); + + + //////////////////////////////////// Neat if I ever want to close a window + // let closeCountdown = 5; // seconds + // const closeTimeout = () => { + // successCloseMessageCountdown.innerHTML = closeCountdown; + // setTimeout(() => { + // if(closeCountdown > 1) { + // closeCountdown -= 1; + // closeTimeout(); + // } else { + // chrome.tabs.getCurrent((tab) => { + // chrome.tabs.remove(tab.id); + // }); + // } + // }, 1000); + // } + + // successCloseMessageCountdown.innerHTML = closeCountdown; + // closeTimeout(); +}; + +// --- Main --- + +const main = () => { + + PersistentSyncStorage.on('ready', () => { + if(!!PersistentSyncStorage.data.setupComplete === true) { + console.log('Setup is already complete, Should not be here'); + return true; + } + + let setupOutput = {}; + chrome.runtime.sendMessage({ + name: 'setupComplete', + data: setupOutput + }, setupComplete); + + console.log('Competed setup, sent message'); + + }); + + +}; + +// --- Executed --- + +main(); + + diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..28f48f3 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,53 @@ +// Packages +const webpack = require('webpack'), + path = require('path'); + +// Webpack Plugins +const CopyPlugin = require('copy-webpack-plugin'); + +// Paths +const srcPath = path.join(__dirname, 'src'), + distPath = path.join(__dirname, 'dev-build'), + node_modulesPath = path.join(__dirname, 'node_modules'); + +module.exports = { + mode: 'development', + + resolve: { + alias: { + src: srcPath + } + }, + context: srcPath, + entry: { + content: './content/', + background: './background/', + options: './options.js', + welcomePage: './welcomePage.js' + + }, + output: { + path: distPath, + filename: './[name].js' + }, + + module: { + rules: [ + { test: /\.styl$/, use: ['style-loader', 'css-loader', 'stylus-loader'], exclude: /node_modules/ } + ] + }, + + plugins: [ + new CopyPlugin([ + 'manifest.json', + 'html/**/*', + 'assets/**/*' + ], { + ignore: [ + '**/*.psd' + ] + }) + ], + + devtool: '#inline-cheap-source-map' +}; diff --git a/webpack.prod.js b/webpack.prod.js new file mode 100644 index 0000000..50b47c2 --- /dev/null +++ b/webpack.prod.js @@ -0,0 +1,62 @@ +// Packages +const webpack = require('webpack'), + path = require('path'); + +// Webpack Plugins +const CopyPlugin = require('copy-webpack-plugin'), + UglifyJsPlugin = require('uglifyjs-webpack-plugin'); + +// Paths +const srcPath = path.join(__dirname, 'src'), + distPath = path.join(__dirname, 'build'), + node_modulesPath = path.join(__dirname, 'node_modules'); + +module.exports = { + mode: 'production', + + resolve: { + alias: { + src: srcPath + } + }, + context: srcPath, + entry: { + content: './content/', + background: './background/', + options: './options.js', + welcomePage: './welcomePage.js' + }, + output: { + path: distPath, + filename: './[name].js' + }, + + module: { + rules: [ + { test: /\.styl$/, use: ['style-loader', 'css-loader', 'stylus-loader'], exclude: /node_modules/ } + ] + }, + + plugins: [ + new CopyPlugin([ + 'manifest.json', + 'html/**/*', + 'assets/**/*', + ], { + ignore: [ + '**/*.psd' + ] + }), + + new UglifyJsPlugin({ + uglifyOptions: { + output: { + beautify: false, + comments: false + } + } + }) + ], + + devtool: '#inline-cheap-source-map' +};