// ==UserScript== // @name Flow Youtube Chat // @version 1.15.18 // @description Youtubeのチャットをニコニコ風に画面上へ流す(再アップ) Make youtube chats move in danmaku-style. // @match https://www.youtube.com/* // @namespace FlowYoutubeChatScript // @run-at document-end // @grant GM.setValue // @grant GM.getValue // @grant GM.deleteValue // @grant GM.listValues // @grant GM.setClipboard // @noframes // @license AGPL-3.0-or-later // @require https://cdn.jsdelivr.net/npm/sweetalert2@11.4.29/dist/sweetalert2.all.min.js#sha384-oOcVIFjLmJbkImF/OMv4gZHmkUcQAiX1EJZt7C9siwnS9yGghuo22mPgX7a623rc // @require https://unpkg.com/loglevel@1.8.0/dist/loglevel.min.js#sha384-xnEzWQtTztbu/yV2BtSvqqZGP52iLXbnb4NJ59OYT0ZDo1fGaKCR6QBxjyRuNFJ8 // @require https://unpkg.com/rxjs@7.5.6/dist/bundles/rxjs.umd.min.js#sha384-loWwI45AmzSZ93ze6KW4+6eZVsQT8PriLOVCZGZstdycw5uylV3xKkHLQh53ui6b // @require https://unpkg.com/mithril@2.2.2/mithril.min.js#sha384-60kek02kUAH+DNSgj7HCtrpcirTroG3uWnDpsdvoAl2Z9Xe3GdpXDSy4ouNMHoBZ // @require https://cdn.jsdelivr.net/npm/check-types@11.1.2/src/check-types.min.js#sha384-KGnImnhVjA5llfqKEbjBiY+1Mp6oa+NvW/TEY1XTPAKWNgrAwa3Qvn//MXL07wBM // @require https://cdn.jsdelivr.net/npm/deep-diff@1.0.2/index.min.js#sha384-Q/uiWfFlwn9XjOpL49VpFKn01EkScmaC3hh1prAn7S++WoZgXRrrjQvZ7cI7C7Zn // @require https://cdn.jsdelivr.net/npm/astring@1.8.3/dist/astring.min.js#sha384-5Ucbdr4B4nO60a/3Lv4z9adjzcDkpVPH19acFTr320dXMe+cKE5y5zV+gycjJO8N // @require https://cdn.jsdelivr.net/npm/jsep@1.3.6/dist/iife/jsep.iife.min.js#sha384-6PGvkKayYZDccXp2sQ43aTf44oUNudO3L940VBGQYHfhg3YZEgSEbuannHJk7NBe // @require https://cdn.jsdelivr.net/npm/hash-it@5.0.2/dist/hash-it.min.js#sha384-biRMep0zr/5fw/hIdnBIb56UHRgiIyhAagZrngd9dSxxQ9aDFMP0hbYR8PEj5lVu // @require https://cdn.jsdelivr.net/npm/micro-memoize@4.0.11/dist/micro-memoize.min.js#sha384-3VwqC1DvF4pyT2nI/Y2hvIoGqAwEYFLImjifWlsBHhIuISG0a28JYU7K9g3c7wI9 // @downloadURL none // ==/UserScript== /* jshint esversion: 6 */ ;(() => { var __webpack_modules__ = { 661: module => { module.exports = !1 }, 204: module => { "use strict" module.exports = function equal(a, b) { if (a === b) return !0 if (a && b && "object" == typeof a && "object" == typeof b) { if (a.constructor !== b.constructor) return !1 var length, i, keys if (Array.isArray(a)) { if ((length = a.length) != b.length) return !1 for (i = length; 0 != i--; ) if (!equal(a[i], b[i])) return !1 return !0 } if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf() if (a.toString !== Object.prototype.toString) return a.toString() === b.toString() if ( (length = (keys = Object.keys(a)).length) !== Object.keys(b).length ) return !1 for (i = length; 0 != i--; ) if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return !1 for (i = length; 0 != i--; ) { var key = keys[i] if (!equal(a[key], b[key])) return !1 } return !0 } return a != a && b != b } }, 90: module => { module.exports = (function (e) { var r = {} function n(t) { if (r[t]) return r[t].exports var a = (r[t] = { i: t, l: !1, exports: {} }) return e[t].call(a.exports, a, a.exports, n), (a.l = !0), a.exports } return ( (n.m = e), (n.c = r), (n.d = function (e, r, t) { n.o(e, r) || Object.defineProperty(e, r, { enumerable: !0, get: t }) }), (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, r) { if ((1 & r && (e = n(e)), 8 & r)) return e if (4 & r && "object" == typeof e && e && e.__esModule) return e var t = Object.create(null) if ( (n.r(t), Object.defineProperty(t, "default", { enumerable: !0, value: e, }), 2 & r && "string" != typeof e) ) for (var a in e) n.d( t, a, function (r) { return e[r] }.bind(null, a) ) return t }), (n.n = function (e) { var r = e && e.__esModule ? function () { return e.default } : function () { return e } return n.d(r, "a", r), r }), (n.o = function (e, r) { return Object.prototype.hasOwnProperty.call(e, r) }), (n.p = ""), n((n.s = 0)) ) })([ function (e, r, n) { "use strict" n.r(r), n.d(r, "validateHTMLColorName", function () { return l }), n.d(r, "validateHTMLColorSpecialName", function () { return i }), n.d(r, "validateHTMLColorHex", function () { return u }), n.d(r, "validateHTMLColorRgb", function () { return d }), n.d(r, "validateHTMLColorHsl", function () { return f }), n.d(r, "validateHTMLColorHwb", function () { return h }), n.d(r, "validateHTMLColorLab", function () { return g }), n.d(r, "validateHTMLColor", function () { return m }) const t = e => e && "string" == typeof e, a = [ "AliceBlue", "AntiqueWhite", "Aqua", "Aquamarine", "Azure", "Beige", "Bisque", "Black", "BlanchedAlmond", "Blue", "BlueViolet", "Brown", "BurlyWood", "CadetBlue", "Chartreuse", "Chocolate", "Coral", "CornflowerBlue", "Cornsilk", "Crimson", "Cyan", "DarkBlue", "DarkCyan", "DarkGoldenrod", "DarkGray", "DarkGreen", "DarkKhaki", "DarkMagenta", "DarkOliveGreen", "DarkOrange", "DarkOrchid", "DarkRed", "DarkSalmon", "DarkSeaGreen", "DarkSlateBlue", "DarkSlateGray", "DarkTurquoise", "DarkViolet", "DeepPink", "DeepSkyBlue", "DimGray", "DodgerBlue", "FireBrick", "FloralWhite", "ForestGreen", "Fuchsia", "Gainsboro", "GhostWhite", "Gold", "Goldenrod", "Gray", "Green", "GreenYellow", "HoneyDew", "HotPink", "IndianRed", "Indigo", "Ivory", "Khaki", "Lavender", "LavenderBlush", "LawnGreen", "LemonChiffon", "LightBlue", "LightCoral", "LightCyan", "LightGoldenrodYellow", "LightGray", "LightGreen", "LightPink", "LightSalmon", "LightSalmon", "LightSeaGreen", "LightSkyBlue", "LightSlateGray", "LightSteelBlue", "LightYellow", "Lime", "LimeGreen", "Linen", "Magenta", "Maroon", "MediumAquamarine", "MediumBlue", "MediumOrchid", "MediumPurple", "MediumSeaGreen", "MediumSlateBlue", "MediumSlateBlue", "MediumSpringGreen", "MediumTurquoise", "MediumVioletRed", "MidnightBlue", "MintCream", "MistyRose", "Moccasin", "NavajoWhite", "Navy", "OldLace", "Olive", "OliveDrab", "Orange", "OrangeRed", "Orchid", "PaleGoldenrod", "PaleGreen", "PaleTurquoise", "PaleVioletRed", "PapayaWhip", "PeachPuff", "Peru", "Pink", "Plum", "PowderBlue", "Purple", "RebeccaPurple", "Red", "RosyBrown", "RoyalBlue", "SaddleBrown", "Salmon", "SandyBrown", "SeaGreen", "SeaShell", "Sienna", "Silver", "SkyBlue", "SlateBlue", "SlateGray", "Snow", "SpringGreen", "SteelBlue", "Tan", "Teal", "Thistle", "Tomato", "Turquoise", "Violet", "Wheat", "White", "WhiteSmoke", "Yellow", "YellowGreen", ], o = ["currentColor", "inherit", "transparent"], l = e => { let r = !1 return ( t(e) && a.map( n => ( e.toLowerCase() === n.toLowerCase() && (r = !0), null ) ), r ) }, i = e => { let r = !1 return ( t(e) && o.map( n => ( e.toLowerCase() === n.toLowerCase() && (r = !0), null ) ), r ) }, u = e => { if (t(e)) { const r = /^#([\da-f]{3}){1,2}$|^#([\da-f]{4}){1,2}$/i return e && r.test(e) } }, d = e => { if (t(e)) { const r = /(rgb)a?\((\s*\d+%?\s*?,?\s*){2}(\s*\d+%?\s*?,?\s*\)?)(\s*,?\s*\/?\s*(0?\.?\d+%?\s*)?|1|0)?\)$/i return e && r.test(e) } }, s = "(([0-9]|[1-9][0-9]|100)%)", c = `\\s*?\\)?)(\\s*?(\\/?)\\s+(((${s}))|(0?(\\.\\d+)?)|1))?\\s*?\\)$`, f = e => { if (t(e)) { const r = new RegExp( `(hsl)a?\\((\\s*?((-?([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9]|3[0-5][0-9]|360)(deg)?)|(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9]|3[0-9][0-9]|400)gra)|((([0-5])?\\.\\d+|6\\.([0-9]|1[0-9]|2[0-8])|[0-6])rad)|((0?(\\.\\d+)?|1)turn))((\\s*,\\s*)|(\\s+)))(\\s*?(0|${s})((\\s*,\\s*)|(\\s+)))(\\s*?(0|${s})\\s*?\\)?)(\\s*?(\\/?|,?)\\s*?(((${s}))|(0?(\\.\\d+)?)|1))?\\)$` ) return e && r.test(e) } }, h = e => { if (t(e)) { const r = new RegExp( `(hwb\\(\\s*?(-?([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9]|3[0-5][0-9]|360)(deg)?)\\s+)((0|${s})\\s+)((0|${s})${c}` ) return e && r.test(e) } }, g = e => { if (t(e)) { const r = "(-?(([0-9]|[1-9][0-9]|1[0-5][0-9])(\\.\\d+)??|160))", n = new RegExp( `(lab\\(\\s*?((\\d*(\\.\\d+)?)%)\\s+${r}\\s+${r}${c}` ) return e && n.test(e) } }, m = e => !!((e && u(e)) || d(e) || f(e) || h(e) || g(e)) r.default = e => !!((e && u(e)) || l(e) || i(e) || d(e) || f(e) || h(e) || g(e)) }, ]) }, 938: () => {}, }, __webpack_module_cache__ = {} function __webpack_require__(moduleId) { var cachedModule = __webpack_module_cache__[moduleId] if (void 0 !== cachedModule) return cachedModule.exports var module = (__webpack_module_cache__[moduleId] = { exports: {} }) __webpack_modules__[moduleId](module, module.exports, __webpack_require__) return module.exports } __webpack_require__.n = module => { var getter = module && module.__esModule ? () => module.default : () => module __webpack_require__.d(getter, { a: getter }) return getter } __webpack_require__.d = (exports, definition) => { for (var key in definition) __webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key) && Object.defineProperty(exports, key, { enumerable: !0, get: definition[key], }) } __webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop) ;(() => { "use strict" const external_log_namespaceObject = log var external_log_default = __webpack_require__.n( external_log_namespaceObject ) const lib = observer => value => { observer.next(value) } Promise.resolve(!1) Promise.resolve(!0) var PROMISE_RESOLVED_VOID = Promise.resolve() function sleep(time, resolveWith) { time || (time = 0) return new Promise(function (res) { return setTimeout(function () { return res(resolveWith) }, time) }) } function randomToken() { return Math.random().toString(36).substring(2) } var lastMs = 0, additional = 0 function microSeconds() { var ms = new Date().getTime() if (ms === lastMs) return 1e3 * ms + ++additional lastMs = ms additional = 0 return 1e3 * ms } var isNode = "[object process]" === Object.prototype.toString.call( "undefined" != typeof process ? process : 0 ) const methods_native = { create: function (channelName) { var state = { messagesCallback: null, bc: new BroadcastChannel(channelName), subFns: [], } state.bc.onmessage = function (msg) { state.messagesCallback && state.messagesCallback(msg.data) } return state }, close: function (channelState) { channelState.bc.close() channelState.subFns = [] }, onMessage: function (channelState, fn) { channelState.messagesCallback = fn }, postMessage: function (channelState, messageJson) { try { channelState.bc.postMessage(messageJson, !1) return PROMISE_RESOLVED_VOID } catch (err) { return Promise.reject(err) } }, canBeUsed: function () { if (isNode && "undefined" == typeof window) return !1 if ("function" == typeof BroadcastChannel) { if (BroadcastChannel._pubkey) throw new Error( "BroadcastChannel: Do not overwrite window.BroadcastChannel with this module, this is not a polyfill" ) return !0 } return !1 }, type: "native", averageResponseTime: function () { return 150 }, microSeconds, } var ObliviousSet = (function () { function ObliviousSet(ttl) { this.ttl = ttl this.map = new Map() this._to = !1 } ObliviousSet.prototype.has = function (value) { return this.map.has(value) } ObliviousSet.prototype.add = function (value) { var _this = this this.map.set(value, now()) if (!this._to) { this._to = !0 setTimeout(function () { _this._to = !1 !(function (obliviousSet) { for ( var olderThen = now() - obliviousSet.ttl, iterator = obliviousSet.map[Symbol.iterator](); ; ) { var next = iterator.next().value if (!next) return var value = next[0] if (!(next[1] < olderThen)) return obliviousSet.map.delete(value) } })(_this) }, 0) } } ObliviousSet.prototype.clear = function () { this.map.clear() } return ObliviousSet })() function now() { return new Date().getTime() } function options_fillOptionsWithDefaults() { var originalOptions = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, options = JSON.parse(JSON.stringify(originalOptions)) void 0 === options.webWorkerSupport && (options.webWorkerSupport = !0) options.idb || (options.idb = {}) options.idb.ttl || (options.idb.ttl = 45e3) options.idb.fallbackInterval || (options.idb.fallbackInterval = 150) originalOptions.idb && "function" == typeof originalOptions.idb.onclose && (options.idb.onclose = originalOptions.idb.onclose) options.localstorage || (options.localstorage = {}) options.localstorage.removeTimeout || (options.localstorage.removeTimeout = 6e4) originalOptions.methods && (options.methods = originalOptions.methods) options.node || (options.node = {}) options.node.ttl || (options.node.ttl = 12e4) options.node.maxParallelWrites || (options.node.maxParallelWrites = 2048) void 0 === options.node.useFastPath && (options.node.useFastPath = !0) return options } var TRANSACTION_SETTINGS = { durability: "relaxed" } function getIdb() { if ("undefined" != typeof indexedDB) return indexedDB if ("undefined" != typeof window) { if (void 0 !== window.mozIndexedDB) return window.mozIndexedDB if (void 0 !== window.webkitIndexedDB) return window.webkitIndexedDB if (void 0 !== window.msIndexedDB) return window.msIndexedDB } return !1 } function commitIndexedDBTransaction(tx) { tx.commit && tx.commit() } function _readLoop(state) { state.closed || readNewMessages(state) .then(function () { return sleep(state.options.idb.fallbackInterval) }) .then(function () { return _readLoop(state) }) } function readNewMessages(state) { return state.closed ? PROMISE_RESOLVED_VOID : state.messagesCallback ? (function (db, lastCursorId) { var tx = db.transaction( "messages", "readonly", TRANSACTION_SETTINGS ), objectStore = tx.objectStore("messages"), ret = [], keyRangeValue = IDBKeyRange.bound(lastCursorId + 1, 1 / 0) if (objectStore.getAll) { var getAllRequest = objectStore.getAll(keyRangeValue) return new Promise(function (res, rej) { getAllRequest.onerror = function (err) { return rej(err) } getAllRequest.onsuccess = function (e) { res(e.target.result) } }) } return new Promise(function (res, rej) { var openCursorRequest = (function () { try { keyRangeValue = IDBKeyRange.bound(lastCursorId + 1, 1 / 0) return objectStore.openCursor(keyRangeValue) } catch (e) { return objectStore.openCursor() } })() openCursorRequest.onerror = function (err) { return rej(err) } openCursorRequest.onsuccess = function (ev) { var cursor = ev.target.result if (cursor) if (cursor.value.id < lastCursorId + 1) cursor.continue(lastCursorId + 1) else { ret.push(cursor.value) cursor.continue() } else { commitIndexedDBTransaction(tx) res(ret) } } }) })(state.db, state.lastCursorId).then(function (newerMessages) { var useMessages = newerMessages .filter(function (msgObj) { return !!msgObj }) .map(function (msgObj) { msgObj.id > state.lastCursorId && (state.lastCursorId = msgObj.id) return msgObj }) .filter(function (msgObj) { return (function (msgObj, state) { return !( msgObj.uuid === state.uuid || state.eMIs.has(msgObj.id) || msgObj.data.time < state.messagesCallbackTime ) })(msgObj, state) }) .sort(function (msgObjA, msgObjB) { return msgObjA.time - msgObjB.time }) useMessages.forEach(function (msgObj) { if (state.messagesCallback) { state.eMIs.add(msgObj.id) state.messagesCallback(msgObj.data) } }) return PROMISE_RESOLVED_VOID }) : PROMISE_RESOLVED_VOID } const indexed_db = { create: function (channelName, options) { options = options_fillOptionsWithDefaults(options) return (function (channelName) { var dbName = "pubkey.broadcast-channel-0-" + channelName, openRequest = getIdb().open(dbName) openRequest.onupgradeneeded = function (ev) { ev.target.result.createObjectStore("messages", { keyPath: "id", autoIncrement: !0, }) } return new Promise(function (res, rej) { openRequest.onerror = function (ev) { return rej(ev) } openRequest.onsuccess = function () { res(openRequest.result) } }) })(channelName).then(function (db) { var state = { closed: !1, lastCursorId: 0, channelName, options, uuid: randomToken(), eMIs: new ObliviousSet(2 * options.idb.ttl), writeBlockPromise: PROMISE_RESOLVED_VOID, messagesCallback: null, readQueuePromises: [], db, } db.onclose = function () { state.closed = !0 options.idb.onclose && options.idb.onclose() } _readLoop(state) return state }) }, close: function (channelState) { channelState.closed = !0 channelState.db.close() }, onMessage: function (channelState, fn, time) { channelState.messagesCallbackTime = time channelState.messagesCallback = fn readNewMessages(channelState) }, postMessage: function (channelState, messageJson) { channelState.writeBlockPromise = channelState.writeBlockPromise .then(function () { return (function (db, readerUuid, messageJson) { var writeObject = { uuid: readerUuid, time: new Date().getTime(), data: messageJson, }, tx = db.transaction( ["messages"], "readwrite", TRANSACTION_SETTINGS ) return new Promise(function (res, rej) { tx.oncomplete = function () { return res() } tx.onerror = function (ev) { return rej(ev) } tx.objectStore("messages").add(writeObject) commitIndexedDBTransaction(tx) }) })(channelState.db, channelState.uuid, messageJson) }) .then(function () { 0 === Math.floor(11 * Math.random() + 0) && ((db = channelState.db), (ttl = channelState.options.idb.ttl), (function (db, ttl) { var olderThen = new Date().getTime() - ttl, tx = db.transaction( "messages", "readonly", TRANSACTION_SETTINGS ), objectStore = tx.objectStore("messages"), ret = [] return new Promise(function (res) { objectStore.openCursor().onsuccess = function (ev) { var cursor = ev.target.result if (cursor) { var msgObk = cursor.value if (!(msgObk.time < olderThen)) { commitIndexedDBTransaction(tx) res(ret) return } ret.push(msgObk) cursor.continue() } else res(ret) } }) })(db, ttl).then(function (tooOld) { return (function (db, ids) { var objectStore = db .transaction( ["messages"], "readwrite", TRANSACTION_SETTINGS ) .objectStore("messages") return Promise.all( ids.map(function (id) { var deleteRequest = objectStore.delete(id) return new Promise(function (res) { deleteRequest.onsuccess = function () { return res() } }) }) ) })( db, tooOld.map(function (msg) { return msg.id }) ) })) var db, ttl }) return channelState.writeBlockPromise }, canBeUsed: function () { return !isNode && !!getIdb() }, type: "idb", averageResponseTime: function (options) { return 2 * options.idb.fallbackInterval }, microSeconds, } function getLocalStorage() { var localStorage if ("undefined" == typeof window) return null try { localStorage = window.localStorage localStorage = window["ie8-eventlistener/storage"] || window.localStorage } catch (e) {} return localStorage } function storageKey(channelName) { return "pubkey.broadcastChannel-" + channelName } function localstorage_canBeUsed() { if (isNode) return !1 var ls = getLocalStorage() if (!ls) return !1 try { var key = "__broadcastchannel_check" ls.setItem(key, "works") ls.removeItem(key) } catch (e) { return !1 } return !0 } const localstorage = { create: function (channelName, options) { options = options_fillOptionsWithDefaults(options) if (!localstorage_canBeUsed()) throw new Error("BroadcastChannel: localstorage cannot be used") var uuid = randomToken(), eMIs = new ObliviousSet(options.localstorage.removeTimeout), state = { channelName, uuid, eMIs } state.listener = (function (channelName, fn) { var key = storageKey(channelName), listener = function (ev) { ev.key === key && (function (msgObj) { if ( state.messagesCallback && msgObj.uuid !== uuid && msgObj.token && !eMIs.has(msgObj.token) && !( msgObj.data.time && msgObj.data.time < state.messagesCallbackTime ) ) { eMIs.add(msgObj.token) state.messagesCallback(msgObj.data) } })(JSON.parse(ev.newValue)) } window.addEventListener("storage", listener) return listener })(channelName) return state }, close: function (channelState) { ;(listener = channelState.listener), window.removeEventListener("storage", listener) var listener }, onMessage: function (channelState, fn, time) { channelState.messagesCallbackTime = time channelState.messagesCallback = fn }, postMessage: function (channelState, messageJson) { return new Promise(function (res) { sleep().then(function () { var key = storageKey(channelState.channelName), writeObj = { token: randomToken(), time: new Date().getTime(), data: messageJson, uuid: channelState.uuid, }, value = JSON.stringify(writeObj) getLocalStorage().setItem(key, value) var ev = document.createEvent("Event") ev.initEvent("storage", !0, !0) ev.key = key ev.newValue = value window.dispatchEvent(ev) res() }) }) }, canBeUsed: localstorage_canBeUsed, type: "localstorage", averageResponseTime: function () { var userAgent = navigator.userAgent.toLowerCase() return userAgent.includes("safari") && !userAgent.includes("chrome") ? 240 : 120 }, microSeconds, } var simulate_microSeconds = microSeconds, SIMULATE_CHANNELS = new Set() const simulate = { create: function (channelName) { var state = { name: channelName, messagesCallback: null } SIMULATE_CHANNELS.add(state) return state }, close: function (channelState) { SIMULATE_CHANNELS.delete(channelState) }, onMessage: function (channelState, fn) { channelState.messagesCallback = fn }, postMessage: function (channelState, messageJson) { return new Promise(function (res) { return setTimeout(function () { Array.from(SIMULATE_CHANNELS) .filter(function (channel) { return channel.name === channelState.name }) .filter(function (channel) { return channel !== channelState }) .filter(function (channel) { return !!channel.messagesCallback }) .forEach(function (channel) { return channel.messagesCallback(messageJson) }) res() }, 5) }) }, canBeUsed: function () { return !0 }, type: "simulate", averageResponseTime: function () { return 5 }, microSeconds: simulate_microSeconds, } var METHODS = [methods_native, indexed_db, localstorage], OPEN_BROADCAST_CHANNELS = new Set(), lastId = 0, broadcast_channel_BroadcastChannel = function (name, options) { this.id = lastId++ OPEN_BROADCAST_CHANNELS.add(this) this.name = name this.options = options_fillOptionsWithDefaults(options) this.method = (function (options) { var chooseMethods = [] .concat(options.methods, METHODS) .filter(Boolean) if (options.type) { if ("simulate" === options.type) return simulate var ret = chooseMethods.find(function (m) { return m.type === options.type }) if (ret) return ret throw new Error("method-type " + options.type + " not found") } options.webWorkerSupport || isNode || (chooseMethods = chooseMethods.filter(function (m) { return "idb" !== m.type })) var useMethod = chooseMethods.find(function (method) { return method.canBeUsed() }) if (useMethod) return useMethod throw new Error( "No useable method found in " + JSON.stringify( METHODS.map(function (m) { return m.type }) ) ) })(this.options) this._iL = !1 this._onML = null this._addEL = { message: [], internal: [] } this._uMP = new Set() this._befC = [] this._prepP = null !(function (channel) { var obj, maybePromise = channel.method.create(channel.name, channel.options) if ((obj = maybePromise) && "function" == typeof obj.then) { channel._prepP = maybePromise maybePromise.then(function (s) { channel._state = s }) } else channel._state = maybePromise })(this) } broadcast_channel_BroadcastChannel._pubkey = !0 broadcast_channel_BroadcastChannel.prototype = { postMessage: function (msg) { if (this.closed) throw new Error( "BroadcastChannel.postMessage(): Cannot post message after channel has closed " + JSON.stringify(msg) ) return _post(this, "message", msg) }, postInternal: function (msg) { return _post(this, "internal", msg) }, set onmessage(fn) { var listenObj = { time: this.method.microSeconds(), fn } _removeListenerObject(this, "message", this._onML) if (fn && "function" == typeof fn) { this._onML = listenObj _addListenerObject(this, "message", listenObj) } else this._onML = null }, addEventListener: function (type, fn) { _addListenerObject(this, type, { time: this.method.microSeconds(), fn }) }, removeEventListener: function (type, fn) { _removeListenerObject( this, type, this._addEL[type].find(function (obj) { return obj.fn === fn }) ) }, close: function () { var _this = this if (!this.closed) { OPEN_BROADCAST_CHANNELS.delete(this) this.closed = !0 var awaitPrepare = this._prepP ? this._prepP : PROMISE_RESOLVED_VOID this._onML = null this._addEL.message = [] return awaitPrepare .then(function () { return Promise.all(Array.from(_this._uMP)) }) .then(function () { return Promise.all( _this._befC.map(function (fn) { return fn() }) ) }) .then(function () { return _this.method.close(_this._state) }) } }, get type() { return this.method.type }, get isClosed() { return this.closed }, } function _post(broadcastChannel, type, msg) { var msgObj = { time: broadcastChannel.method.microSeconds(), type, data: msg, } return ( broadcastChannel._prepP ? broadcastChannel._prepP : PROMISE_RESOLVED_VOID ).then(function () { var sendPromise = broadcastChannel.method.postMessage( broadcastChannel._state, msgObj ) broadcastChannel._uMP.add(sendPromise) sendPromise.catch().then(function () { return broadcastChannel._uMP.delete(sendPromise) }) return sendPromise }) } function _hasMessageListeners(channel) { return ( channel._addEL.message.length > 0 || channel._addEL.internal.length > 0 ) } function _addListenerObject(channel, type, obj) { channel._addEL[type].push(obj) !(function (channel) { if (!channel._iL && _hasMessageListeners(channel)) { var listenerFn = function (msgObj) { channel._addEL[msgObj.type].forEach(function (listenerObject) { var minMessageTime = listenerObject.time - 1e5 msgObj.time >= minMessageTime && listenerObject.fn(msgObj.data) }) }, time = channel.method.microSeconds() if (channel._prepP) channel._prepP.then(function () { channel._iL = !0 channel.method.onMessage(channel._state, listenerFn, time) }) else { channel._iL = !0 channel.method.onMessage(channel._state, listenerFn, time) } } })(channel) } function _removeListenerObject(channel, type, obj) { channel._addEL[type] = channel._addEL[type].filter(function (o) { return o !== obj }) !(function (channel) { if (channel._iL && !_hasMessageListeners(channel)) { channel._iL = !1 var time = channel.method.microSeconds() channel.method.onMessage(channel._state, null, time) } })(channel) } var browser = __webpack_require__(661), browser_default = __webpack_require__.n(browser) const es_browser = { add: function (fn) { if ( "function" == typeof WorkerGlobalScope && self instanceof WorkerGlobalScope ); else { if ("function" != typeof window.addEventListener) return window.addEventListener( "beforeunload", function () { fn() }, !0 ) window.addEventListener( "unload", function () { fn() }, !0 ) } }, } var node_ignored_ = __webpack_require__(938), node_ignored_default = __webpack_require__.n(node_ignored_) browser_default() && node_ignored_default(), new Set() const external_DeepDiff_namespaceObject = DeepDiff var fast_deep_equal = __webpack_require__(204), fast_deep_equal_default = __webpack_require__.n(fast_deep_equal), apply = function (a) { return function (f) { return f(a) } } function function_identity(a) { return a } function constant(a) { return function () { return a } } var constNull = constant(null), constUndefined = constant(void 0) function flip(f) { return function () { for (var args = [], _i = 0; _i < arguments.length; _i++) args[_i] = arguments[_i] return args.length > 1 ? f(args[1], args[0]) : function (a) { return f(a)(args[0]) } } } function function_flow(ab, bc, cd, de, ef, fg, gh, hi, ij) { switch (arguments.length) { case 1: return ab case 2: return function () { return bc(ab.apply(this, arguments)) } case 3: return function () { return cd(bc(ab.apply(this, arguments))) } case 4: return function () { return de(cd(bc(ab.apply(this, arguments)))) } case 5: return function () { return ef(de(cd(bc(ab.apply(this, arguments))))) } case 6: return function () { return fg(ef(de(cd(bc(ab.apply(this, arguments)))))) } case 7: return function () { return gh(fg(ef(de(cd(bc(ab.apply(this, arguments))))))) } case 8: return function () { return hi(gh(fg(ef(de(cd(bc(ab.apply(this, arguments)))))))) } case 9: return function () { return ij(hi(gh(fg(ef(de(cd(bc(ab.apply(this, arguments))))))))) } } } function function_pipe(a, ab, bc, cd, de, ef, fg, gh, hi) { switch (arguments.length) { case 1: return a case 2: return ab(a) case 3: return bc(ab(a)) case 4: return cd(bc(ab(a))) case 5: return de(cd(bc(ab(a)))) case 6: return ef(de(cd(bc(ab(a))))) case 7: return fg(ef(de(cd(bc(ab(a)))))) case 8: return gh(fg(ef(de(cd(bc(ab(a))))))) case 9: return hi(gh(fg(ef(de(cd(bc(ab(a)))))))) default: for (var ret = arguments[0], i = 1; i < arguments.length; i++) ret = arguments[i](ret) return ret } } var eqStrict = { equals: function (a, b) { return a === b }, } function apFirst(A) { return function (second) { return function (first) { return A.ap( A.map(first, function (a) { return function () { return a } }), second ) } } } function apSecond(A) { return function (second) { return function (first) { return A.ap( A.map(first, function () { return function (b) { return b } }), second ) } } } function apS(F) { return function (name, fb) { return function (fa) { return F.ap( F.map(fa, function (a) { return function (b) { var _a return Object.assign({}, a, (((_a = {})[name] = b), _a)) } }), fb ) } } } function Chain_chainFirst(M) { return function (f) { return function (first) { return M.chain(first, function (a) { return M.map(f(a), function () { return a }) }) } } } function bind(M) { return function (name, f) { return function (ma) { return M.chain(ma, function (a) { return M.map(f(a), function (b) { var _a return Object.assign({}, a, (((_a = {})[name] = b), _a)) }) }) } } } function bindTo(F) { return function (name) { return function (fa) { return F.map(fa, function (a) { var _a return ((_a = {})[name] = a), _a }) } } } function let_(F) { return function (name, f) { return function (fa) { return F.map(fa, function (a) { var _a return Object.assign({}, a, (((_a = {})[name] = f(a)), _a)) }) } } } var isSome = function (fa) { return "Some" === fa._tag }, none = { _tag: "None" }, some = function (a) { return { _tag: "Some", value: a } }, isNonEmpty = function (as) { return as.length > 0 }, head = function (as) { return as[0] }, emptyReadonlyArray = [], _map = (Object.prototype.hasOwnProperty, function (ma, f) { return function () { return f(ma()) } }), _ap = function (mab, ma) { return function () { return mab()(ma()) } }, _chain = function (ma, f) { return function () { return f(ma())() } }, IO_map = function (f) { return function (fa) { return _map(fa, f) } }, of = constant, chain = function (f) { return function (ma) { return _chain(ma, f) } }, Functor = { URI: "IO", map: _map }, Pointed = { URI: "IO", of }, Apply = { URI: "IO", map: _map, ap: _ap }, IO_apFirst = apFirst(Apply), IO_apSecond = apSecond(Apply), Chain = { URI: "IO", map: _map, ap: _ap, chain: _chain }, Monad = { URI: "IO", map: _map, ap: _ap, of, chain: _chain }, IO_chainFirst = Chain_chainFirst(Chain), IO_bindTo = bindTo(Functor), IO_bind = bind(Chain), IO_apS = apS(Apply), ApT = of(emptyReadonlyArray), traverseArray = function (f) { return (function (f) { var g = (function (f) { return function (as) { return function () { for (var out = [f(0, head(as))()], i = 1; i < as.length; i++) out.push(f(i, as[i])()) return out } } })(f) return function (as) { return isNonEmpty(as) ? g(as) : ApT } })(function (_, a) { return f(a) }) }, sequenceArray = traverseArray(function_identity), Predicate_not = function (predicate) { return function (a) { return !predicate(a) } }, Separated_separated = function (left, right) { return { left, right } }, Option_none = none, Option_some = some function fromPredicate(predicate) { return function (a) { return predicate(a) ? Option_some(a) : Option_none } } var Option_map = function (fa, f) { return function_pipe(fa, es6_Option_map(f)) }, Option_ap = function (fab, fa) { return function_pipe(fab, es6_Option_ap(fa)) }, _filter = function (fa, predicate) { return function_pipe(fa, filter(predicate)) }, es6_Option_map = function (f) { return function (fa) { return Option_isNone(fa) ? Option_none : Option_some(f(fa.value)) } }, Option_Functor = { URI: "Option", map: Option_map }, Option_of = Option_some, es6_Option_ap = function (fa) { return function (fab) { return Option_isNone(fab) || Option_isNone(fa) ? Option_none : Option_some(fab.value(fa.value)) } }, Option_Apply = { URI: "Option", map: Option_map, ap: Option_ap }, es6_Option_chain = function (f) { return function (ma) { return Option_isNone(ma) ? Option_none : f(ma.value) } }, Option_Chain = { URI: "Option", map: Option_map, ap: Option_ap, chain: function (ma, f) { return function_pipe(ma, es6_Option_chain(f)) }, }, alt = function (that) { return function (fa) { return Option_isNone(fa) ? that() : fa } }, Option_compact = es6_Option_chain(function_identity), defaultSeparated = Separated_separated(Option_none, Option_none), Option_separate = function (ma) { return Option_isNone(ma) ? defaultSeparated : Separated_separated( (function (ma) { return "Right" === ma._tag ? Option_none : Option_some(ma.left) })(ma.value), (function (ma) { return "Left" === ma._tag ? Option_none : Option_some(ma.right) })(ma.value) ) }, filter = function (predicate) { return function (fa) { return Option_isNone(fa) ? Option_none : predicate(fa.value) ? fa : Option_none } }, filterMap = function (f) { return function (fa) { return Option_isNone(fa) ? Option_none : f(fa.value) } }, partition = function (predicate) { return function (fa) { return Separated_separated( _filter(fa, Predicate_not(predicate)), _filter(fa, predicate) ) } }, partitionMap = function (f) { return function_flow(es6_Option_map(f), Option_separate) }, Filterable = { URI: "Option", map: Option_map, compact: Option_compact, separate: Option_separate, filter: _filter, filterMap: function (fa, f) { return function_pipe(fa, filterMap(f)) }, partition: function (fa, predicate) { return function_pipe(fa, partition(predicate)) }, partitionMap: function (fa, f) { return function_pipe(fa, partitionMap(f)) }, }, Option_isSome = isSome, Option_isNone = function (fa) { return "None" === fa._tag }, match = function (onNone, onSome) { return function (ma) { return Option_isNone(ma) ? onNone() : onSome(ma.value) } }, getOrElseW = function (onNone) { return function (ma) { return Option_isNone(ma) ? onNone() : ma.value } }, getOrElse = getOrElseW, fromNullable = function (a) { return null == a ? Option_none : Option_some(a) }, chainNullableK = function (f) { return function (ma) { return Option_isNone(ma) ? Option_none : fromNullable(f(ma.value)) } }, toNullable = match(constNull, function_identity), toUndefined = match(constUndefined, function_identity), Option_bind = bind(Option_Chain), Option_ApT = Option_of(emptyReadonlyArray), Option_traverseArray = function (f) { return (function (f) { var g = (function (f) { return function (as) { var o = f(0, head(as)) if (Option_isNone(o)) return Option_none for (var out = [o.value], i = 1; i < as.length; i++) { var o_1 = f(i, as[i]) if (Option_isNone(o_1)) return Option_none out.push(o_1.value) } return Option_some(out) } })(f) return function (as) { return isNonEmpty(as) ? g(as) : Option_ApT } })(function (_, a) { return f(a) }) }, Option_sequenceArray = Option_traverseArray(function_identity), es6_Reader_map = function (f) { return function (fa) { return function (r) { return f(fa(r)) } } }, es6_Reader_chain = function (f) { return function (fa) { return function (r) { return f(fa(r))(r) } } }, Reader_ApT = constant(emptyReadonlyArray), Reader_traverseArray = function (f) { return (function (f) { var g = (function (f) { return function (as) { return function (r) { for (var out = [f(0, head(as))(r)], i = 1; i < as.length; i++) out.push(f(i, as[i])(r)) return out } } })(f) return function (as) { return isNonEmpty(as) ? g(as) : Reader_ApT } })(function (_, a) { return f(a) }) }, Reader_sequenceArray = Reader_traverseArray(function_identity), ReadonlyNonEmptyArray_spreadArray = function (to, from, pack) { if (pack || 2 === arguments.length) for (var ar, i = 0, l = from.length; i < l; i++) if (ar || !(i in from)) { ar || (ar = Array.prototype.slice.call(from, 0, i)) ar[i] = from[i] } return to.concat(ar || Array.prototype.slice.call(from)) }, ReadonlyNonEmptyArray_empty = emptyReadonlyArray, ReadonlyNonEmptyArray_isNonEmpty = isNonEmpty, fromReadonlyArray = function (as) { return ReadonlyNonEmptyArray_isNonEmpty(as) ? some(as) : none }, ReadonlyNonEmptyArray_head = head, ReadonlyNonEmptyArray_tail = function (as) { return as.slice(1) }, ReadonlyArray_isNonEmpty = ReadonlyNonEmptyArray_isNonEmpty, ReadonlyArray_append = function (end) { return function (init) { return ReadonlyNonEmptyArray_spreadArray( ReadonlyNonEmptyArray_spreadArray([], init, !0), [end], !1 ) } }, ReadonlyArray_makeBy = function (n, f) { return n <= 0 ? ReadonlyArray_empty : (function (f) { return function (n) { for ( var j = Math.max(0, Math.floor(n)), out = [f(0)], i = 1; i < j; i++ ) out.push(f(i)) return out } })(f)(n) }, ReadonlyArray_isOutOfBound = function (i, as) { return i < 0 || i >= as.length }, ReadonlyArray_head = function (as) { return ReadonlyArray_isNonEmpty(as) ? some(ReadonlyNonEmptyArray_head(as)) : none }, findIndex = function (predicate) { return function (as) { for (var i = 0; i < as.length; i++) if (predicate(as[i])) return some(i) return none } }, ReadonlyArray_reverse = function (as) { return as.length <= 1 ? as : as.slice().reverse() }, ReadonlyArray_of = function (a) { return [a] }, es6_ReadonlyArray_chain = function (f) { return function (ma) { return function_pipe( ma, (function (f) { return function (as) { if ( (function (as) { return 0 === as.length })(as) ) return ReadonlyArray_empty for (var out = [], i = 0; i < as.length; i++) out.push.apply(out, f(0, as[i])) return out } })(function (_, a) { return f(a) }) ) } }, es6_ReadonlyArray_map = function (f) { return function (fa) { return fa.map(function (a) { return f(a) }) } }, es6_ReadonlyArray_mapWithIndex = function (f) { return function (fa) { return fa.map(function (a, i) { return f(i, a) }) } }, es6_ReadonlyArray_filter = function (predicate) { return function (as) { return as.filter(predicate) } }, es6_ReadonlyArray_filterMap = function (f) { return (function (f) { return function (fa) { for (var out = [], i = 0; i < fa.length; i++) { var optionB = f(i, fa[i]) isSome(optionB) && out.push(optionB.value) } return out } })(function (_, a) { return f(a) }) }, ReadonlyArray_compact = es6_ReadonlyArray_filterMap(function_identity), es6_ReadonlyArray_reduce = function (b, f) { return es6_ReadonlyArray_reduceWithIndex(b, function (_, b, a) { return f(b, a) }) }, es6_ReadonlyArray_reduceWithIndex = function (b, f) { return function (fa) { for (var len = fa.length, out = b, i = 0; i < len; i++) out = f(i, out, fa[i]) return out } }, toArray = function (as) { return as.slice() }, ReadonlyArray_empty = ReadonlyNonEmptyArray_empty function every(predicate) { return function (as) { return as.every(predicate) } } var ReadonlyArray_some = function (predicate) { return function (as) { return as.some(predicate) } }, ReadonlyArray_bindTo = bindTo({ URI: "ReadonlyArray", map: function (fa, f) { return function_pipe(fa, es6_ReadonlyArray_map(f)) }, }) function chainIOK(F, M) { return function (f) { var g = function_flow(f, F.fromIO) return function (first) { return M.chain(first, g) } } } function chainFirstIOK(F, M) { var chainFirstM = Chain_chainFirst(M) return function (f) { return chainFirstM(function_flow(f, F.fromIO)) } } var Task_fromIO = function (ma) { return function () { return Promise.resolve().then(ma) } }, Task_map = function (fa, f) { return function_pipe(fa, es6_Task_map(f)) }, _apPar = function (fab, fa) { return function_pipe(fab, Task_ap(fa)) }, Task_chain = function (ma, f) { return function_pipe(ma, es6_Task_chain(f)) }, es6_Task_map = function (f) { return function (fa) { return function () { return Promise.resolve().then(fa).then(f) } } }, Task_ap = function (fa) { return function (fab) { return function () { return Promise.all([ Promise.resolve().then(fab), Promise.resolve().then(fa), ]).then(function (_a) { return (0, _a[0])(_a[1]) }) } } }, Task_of = function (a) { return function () { return Promise.resolve(a) } }, es6_Task_chain = function (f) { return function (ma) { return function () { return Promise.resolve() .then(ma) .then(function (a) { return f(a)() }) } } }, Task_Functor = { URI: "Task", map: Task_map }, ApplyPar = { URI: "Task", map: Task_map, ap: _apPar }, Task_Chain = { URI: "Task", map: Task_map, ap: _apPar, chain: Task_chain, }, Task_Monad = { URI: "Task", map: Task_map, of: Task_of, ap: _apPar, chain: Task_chain, }, Task_chainFirst = Chain_chainFirst(Task_Chain), Task_chainFirstIOK = chainFirstIOK( { URI: "Task", fromIO: Task_fromIO }, Task_Chain ), Task_let_ = let_(Task_Functor), Task_bind = bind(Task_Chain), Task_apS = apS(ApplyPar), Task_ApT = Task_of(emptyReadonlyArray), Task_traverseArray = function (f) { return (function (f) { var g = (function (f) { return function (as) { return function () { return Promise.all( as.map(function (a, i) { return Promise.resolve().then(function () { return f(i, a)() }) }) ) } } })(f) return function (as) { return isNonEmpty(as) ? g(as) : Task_ApT } })(function (_, a) { return f(a) }) }, Task_sequenceArray = Task_traverseArray(function_identity) function Filterable_filter(F, G) { return function (predicate) { return function (fga) { return F.map(fga, function (ga) { return G.filter(ga, predicate) }) } } } function chainTaskK(F, M) { return function (f) { var g = function_flow(f, F.fromTask) return function (first) { return M.chain(first, g) } } } function OptionT_some(F) { return function_flow(Option_some, F.of) } function fromF(F) { return function (ma) { return F.map(ma, Option_some) } } function OptionT_chainOptionK(M) { var F, chainM = OptionT_chain(M), fromOptionKM = ((F = M), function (f) { return function_flow(f, F.of) }) return function (f) { return chainM(fromOptionKM(f)) } } function OptionT_fromPredicate(F) { return function (predicate) { return function (a) { return F.of(fromPredicate(predicate)(a)) } } } function OptionT_map(F) { return (function (F, G) { return function (f) { return function (fa) { return F.map(fa, function (ga) { return G.map(ga, f) }) } } })(F, Option_Functor) } function OptionT_ap(F) { return (function (F, G) { return function (fa) { return function (fab) { return F.ap( F.map(fab, function (gab) { return function (ga) { return G.ap(gab, ga) } }), fa ) } } })(F, Option_Apply) } function OptionT_chain(M) { var zeroM = constant(M.of(Option_none)) return function (f) { return function (ma) { return M.chain( ma, match(function () { return zeroM() }, f) ) } } } function OptionT_alt(M) { var _some = OptionT_some(M) return function (second) { return function (first) { return M.chain(first, match(second, _some)) } } } var TaskOption_fromTask = fromF(Task_Functor), TaskOption_map = OptionT_map(Task_Functor), TaskOption_ap = OptionT_ap(ApplyPar), TaskOption_chain = OptionT_chain(Task_Monad), TaskOption_chainTaskK = chainTaskK( { URI: "TaskOption", fromIO: function (ma) { return TaskOption_fromTask(Task_fromIO(ma)) }, fromTask: TaskOption_fromTask, }, { URI: "TaskOption", map: function (fa, f) { return function_pipe(fa, TaskOption_map(f)) }, ap: function (fab, fa) { return function_pipe(fab, TaskOption_ap(fa)) }, chain: function (ma, f) { return function_pipe(ma, TaskOption_chain(f)) }, } ) const external_rxjs_namespaceObject = rxjs, mapObject = f => o => function_pipe( Object.entries(o), es6_ReadonlyArray_map(f), Object.fromEntries ), makePageState = mapObject(([k, v]) => [k, { ele: Option_none, read: v }]), appendLog = log => ([a, ...b]) => function_pipe( [...log, `${a}${b.length > 0 ? ": " : ""}${b.join(", ")}`], x => (x.length > 1e3 ? x.slice(0, 100) : x) ), consoleLog = (...[[a, ...b]]) => function_pipe( () => external_log_default().info( ...("string" == typeof a ? [`【FYC】 ${a}`] : ["【FYC】", a]) ), IO_apSecond( b.length > 0 ? () => external_log_default().info(...b) : () => {} ) ), createChatScreen = function_pipe( () => document.createElement("div"), IO_chainFirst( x => () => Object.assign(x.style, { pointerEvents: "none", zIndex: "30", position: "absolute", overflow: "hidden", height: "100%", width: "100%", }) ) ), external_jsep_namespaceObject = jsep var external_jsep_default = __webpack_require__.n( external_jsep_namespaceObject ), u = { "||": function (r, e) { return r || e }, "&&": function (r, e) { return r && e }, "|": function (r, e) { return r | e }, "^": function (r, e) { return r ^ e }, "&": function (r, e) { return r & e }, "==": function (r, e) { return r == e }, "!=": function (r, e) { return r != e }, "===": function (r, e) { return r === e }, "!==": function (r, e) { return r !== e }, "<": function (r, e) { return r < e }, ">": function (r, e) { return r > e }, "<=": function (r, e) { return r <= e }, ">=": function (r, e) { return r >= e }, "<<": function (r, e) { return r << e }, ">>": function (r, e) { return r >> e }, ">>>": function (r, e) { return r >>> e }, "+": function (r, e) { return r + e }, "-": function (r, e) { return r - e }, "*": function (r, e) { return r * e }, "/": function (r, e) { return r / e }, "%": function (r, e) { return r % e }, }, i = { "-": function (r) { return -r }, "+": function (r) { return +r }, "~": function (r) { return ~r }, "!": function (r) { return !r }, } function s(r, e) { return r.map(function (r) { return a(r, e) }) } function c(r, e) { var n, t = a(r.object, e) if ( ((n = r.computed ? a(r.property, e) : r.property.name), /^__proto__|prototype|constructor$/.test(n)) ) throw Error('Access to member "' + n + '" disallowed.') return [t, t[n]] } function a(r, e) { var n = r switch (n.type) { case "ArrayExpression": return s(n.elements, e) case "BinaryExpression": return u[n.operator](a(n.left, e), a(n.right, e)) case "CallExpression": var t, o, l if ( ("MemberExpression" === n.callee.type ? ((t = (l = c(n.callee, e))[0]), (o = l[1])) : (o = a(n.callee, e)), "function" != typeof o) ) return return o.apply(t, s(n.arguments, e)) case "ConditionalExpression": return a(n.test, e) ? a(n.consequent, e) : a(n.alternate, e) case "Identifier": return e[n.name] case "Literal": return n.value case "LogicalExpression": return "||" === n.operator ? a(n.left, e) || a(n.right, e) : "&&" === n.operator ? a(n.left, e) && a(n.right, e) : u[n.operator](a(n.left, e), a(n.right, e)) case "MemberExpression": return c(n, e)[1] case "ThisExpression": return e case "UnaryExpression": return i[n.operator](a(n.argument, e)) default: return } } const defaultFilter = config => external_jsep_default()( `\nor([\nRA.some(\n flip(flow([inText, RA.some]))(${JSON.stringify( config.bannedWords )})\n)(RA.compact([\n messageText,\n paymentInfo\n])),\nRA.some(\n flip(flow([matchedByText, RA.some]))(${JSON.stringify( config.bannedWordRegexs )})\n)(RA.compact([\n messageText,\n paymentInfo\n])),\nO.exists(\n flip(flow([eqText, RA.some]))(${JSON.stringify( config.bannedUsers )})\n)(authorID)\n])\n` ), external_astring_namespaceObject = astring var Identity_map = function (fa, f) { return function_pipe(fa, es6_Identity_map(f)) }, Identity_ap = function (fab, fa) { return function_pipe(fab, es6_Identity_ap(fa)) }, es6_Identity_map = function (f) { return function (fa) { return f(fa) } }, es6_Identity_ap = function (fa) { return function (fab) { return fab(fa) } }, es6_Identity_chain = function (f) { return function (ma) { return f(ma) } }, Identity_Functor = { URI: "Identity", map: Identity_map }, Identity_Apply = { URI: "Identity", map: Identity_map, ap: Identity_ap }, Identity_Chain = { URI: "Identity", map: Identity_map, ap: Identity_ap, chain: function (ma, f) { return function_pipe(ma, es6_Identity_chain(f)) }, }, Identity_bindTo = bindTo(Identity_Functor), Identity_let_ = let_(Identity_Functor), Identity_bind = bind(Identity_Chain), Identity_apS = apS(Identity_Apply), Eq = { equals: function (first, second) { return first === second }, }, string_isEmpty = function (s) { return 0 === s.length }, split = function (separator) { return function (s) { var out = s.split(separator) return ReadonlyNonEmptyArray_isNonEmpty(out) ? out : [s] } } const fycKey = key => `FYC_${key}`, languages = ["FYC_EN", "FYC_JA"], stringsArgs = [ [], function_flow( split(/\r\n|\n/), es6_ReadonlyArray_filter(Predicate_not(string_isEmpty)) ), x => x.join("\n"), ], sc = (k, d) => { return { gmKey: (key = fycKey(k)), getValue: async () => (await GM.getValue(key)) ?? defaultValue, defaultValue: (defaultValue = d), toGm: function_identity, } var key, defaultValue }, ic = (k, d, c, g) => { return ( (key = fycKey(k)), (toConfig = c), function_pipe( { gmKey: key, defaultValue: (defaultValue = d), toGm: g }, Identity_apS( "getValue", function_pipe( () => GM.getValue(key), es6_Task_map(x => (void 0 !== x ? toConfig(x) : defaultValue)) ) ) ) ) var key, defaultValue, toConfig }, src_defaultGMConfig = function_pipe( { lang: ic( "LANG", "FYC_EN", x => (languages.includes(x) ? x : "FYC_EN"), x => x ), font: sc("FONT", "MS PGothic"), chatOpacity: sc("OPACITY", 0.8), color: sc("COLOR", "#ffffff"), ownerColor: sc("COLOR_OWNER", "#ffd600"), moderatorColor: sc("COLOR_MODERATOR", "#c564ff"), memberColor: sc("COLOR_MEMBER", "#9fffff"), fontSize: sc("SIZE", 1), fontWeight: sc("WEIGHT", 730), shadowFontWeight: sc("WEIGHT_SHADOW", 1), maxChatCount: sc("LIMIT", 40), flowSpeed: sc("SPEED", 18), maxChatLength: sc("MAX", 100), laneCount: sc("LANE_DIV", 12), bannedWords: ic("NG_WORDS", ...stringsArgs), bannedWordRegexs: ic("NG_REG_WORDS", ...stringsArgs), bannedUsers: ic("NG_USERS", ...stringsArgs), createChats: sc("TOGGLE_CREATE_COMMENTS", !0), noOverlap: sc("NO_OVERLAP", !0), createBanButton: sc("NG_BUTTON", !0), simplifyChatField: sc("SIMPLE_CHAT_FIELD", !1), displayModName: sc("DISPLAY_MODERATOR_NAME", !0), displaySuperChatAuthor: sc("DISPLAY_SUPER_CHAT_AUTHOR", !0), textOnly: sc("TEXT_ONLY", !1), timingFunction: sc("TIMING_FUNCTION", "linear"), displayChats: sc("DISPLAY_COMMENTS", !0), minSpacing: sc("MIN_SPACING", 0.5), fieldScale: sc("FIELD_SCALE", 1), flowY1: sc("flowY1", 0), flowY2: sc("flowY2", 1), flowX1: sc("flowX1", 0), flowX2: sc("flowX2", 1), shadowColor: sc("shadowColor", "#000000"), }, Identity_bind("filterExp", x => ic( "filterExp", external_jsep_default()( `\n or([\n RA.some(\n flip(flow([inText, RA.some]))(${JSON.stringify( x.bannedWords.defaultValue )})\n )(RA.compact([\n messageText,\n paymentInfo\n ])),\n RA.some(\n flip(flow([matchedByText, RA.some]))(${JSON.stringify( x.bannedWordRegexs.defaultValue )})\n )(RA.compact([\n messageText,\n paymentInfo\n ])),\n O.exists(\n flip(flow([eqText, RA.some]))(${JSON.stringify( x.bannedUsers.defaultValue )})\n )(authorID)\n ])\n ` ), external_jsep_default(), external_astring_namespaceObject.generate ) ) ), ioFromLogState = log => function_flow(apply([]), ([io, logs]) => function_pipe( io, IO_apFirst( function_pipe( logs, es6_ReadonlyArray_map( function_flow( fromReadonlyArray, es6_Option_map(log), getOrElse(() => () => {}) ) ), sequenceArray ) ) ) ), src_listeningBroadcastConfigKeys = [ "lang", "bannedWords", "bannedWordRegexs", "bannedUsers", "filterExp", "simplifyChatField", "createBanButton", "fieldScale", ], chatApp = () => function_pipe( fromNullable(document.querySelector("#chatframe")), filter( function_flow( x => x.contentDocument?.readyState, x => "loading" === x || "complete" === x ) ), chainNullableK(x => x.contentDocument), alt(() => Option_of(document)), chainNullableK(x => x.querySelector("yt-live-chat-app")) ), livePageYt = { toggleChatBtnParent: () => fromNullable(document.querySelector(".ytp-right-controls")), settingsToggleNextElement: () => function_pipe( document.querySelector("#menu-container"), fromNullable, filter(x => null !== x.offsetParent), chainNullableK(x => x.querySelector(".dropdown-trigger.ytd-menu-renderer") ), alt(() => fromNullable( document.querySelector( "#top-row .dropdown-trigger.ytd-menu-renderer" ) ) ) ), settingsContainer: () => fromNullable(document.body), player: () => fromNullable(document.querySelector("#movie_player")), video: () => fromNullable( document.querySelector("video.video-stream.html5-main-video") ), chatField: () => function_pipe( chatApp(), chainNullableK(x => x.querySelector("#items.yt-live-chat-item-list-renderer") ) ), chatTicker: () => function_pipe( chatApp(), chainNullableK(x => x.querySelector("#items.yt-live-chat-ticker-renderer") ) ), chatScroller: () => function_pipe( chatApp(), chainNullableK(x => x.querySelector("#item-scroller.yt-live-chat-item-list-renderer") ) ), offlineSlate: () => fromNullable(document.querySelector(".ytp-offline-slate")), }, mainCss = function_pipe( () => document.createElement("style"), IO_chainFirst(x => () => { x.innerHTML = ".fyc_chat {\n line-height: 1;\n z-index: 30;\n position: absolute;\n user-select: none;\n white-space: nowrap;\n will-change: transform;\n}\n.fyc_button {\n display: inline-block;\n border-style: none;\n z-index: 4;\n font-weight: 500;\n color: var(--yt-spec-text-secondary);\n}" }) ), observePair = con => function_pipe( () => new external_rxjs_namespaceObject.Subject(), IO_bindTo("subject"), IO_bind("observer", x => () => new con(lib(x.subject))) ) var IOOption_some = OptionT_some(Pointed), IOOption_fromPredicate = OptionT_fromPredicate(Pointed), IOOption_fromOption = of, IOOption_fromIO = fromF(Functor), IOOption_chainOptionK = (IO_map(toUndefined), IO_map(toNullable), OptionT_chainOptionK(Monad)), IOOption_map = OptionT_map(Functor), IOOption_ap = OptionT_ap(Apply), IOOption_of = IOOption_some, IOOption_chain = OptionT_chain(Monad), IOOption_alt = OptionT_alt(Monad), IOOption_filter = Filterable_filter(Functor, Filterable), IOOption_Chain = { URI: "IOOption", map: function (fa, f) { return function_pipe(fa, IOOption_map(f)) }, ap: function (fab, fa) { return function_pipe(fab, IOOption_ap(fa)) }, chain: function (ma, f) { return function_pipe(ma, IOOption_chain(f)) }, }, IOOption_FromIO = { URI: "IOOption", fromIO: IOOption_fromIO }, IOOption_chainIOK = chainIOK(IOOption_FromIO, IOOption_Chain), IOOption_chainFirstIOK = chainFirstIOK(IOOption_FromIO, IOOption_Chain), es6_State_map = function (f) { return function (fa) { return function (s1) { var _a = fa(s1), a = _a[0], s2 = _a[1] return [f(a), s2] } } }, es6_State_ap = function (fa) { return function (fab) { return function (s1) { var _a = fab(s1), f = _a[0], s2 = _a[1], _b = fa(s2), a = _b[0], s3 = _b[1] return [f(a), s3] } } }, State_of = function (a) { return function (s) { return [a, s] } }, es6_State_chain = function (f) { return function (ma) { return function (s1) { var _a = ma(s1), a = _a[0], s2 = _a[1] return f(a)(s2) } } }, State_bind = bind({ URI: "State", map: function (fa, f) { return function_pipe(fa, es6_State_map(f)) }, ap: function (fab, fa) { return function_pipe(fab, es6_State_ap(fa)) }, chain: function (ma, f) { return function_pipe(ma, es6_State_chain(f)) }, }), State_traverseArray = function (f) { return (function (f) { var g = (function (f) { return function (as) { return function (s) { for ( var _a = f(0, head(as))(s), bs = [_a[0]], out = _a[1], i = 1; i < as.length; i++ ) { var _b = f(i, as[i])(out), b_1 = _b[0], s2_1 = _b[1] bs.push(b_1) out = s2_1 } return [bs, out] } } })(f) return function (as) { return isNonEmpty(as) ? g(as) : State_of(emptyReadonlyArray) } })(function (_, a) { return f(a) }) }, State_sequenceArray = State_traverseArray(function_identity) const getChatFontSize = mainState => Math.round( ((Math.max(mainState.config.fontSize - 0.2, 0.01) * mainState.playerRect.height) / mainState.config.laneCount) * (mainState.config.flowY2 - mainState.config.flowY1) * 100 ) / 100 var equalsDefault = function (compare) { return function (first, second) { return first === second || 0 === compare(first, second) } }, Ord_contramap = function (f) { return function (fa) { return { equals: equalsDefault( (compare = function (first, second) { return fa.compare(f(first), f(second)) }) ), compare: function (first, second) { return first === second ? 0 : compare(first, second) }, } var compare } }, number_Ord = { equals: function (first, second) { return first === second }, compare: function (first, second) { return first < second ? -1 : first > second ? 1 : 0 }, }, number_Show_show = function (n) { return JSON.stringify(n) } const external_window_micro_memoize_namespaceObject = window["micro-memoize"] var external_window_micro_memoize_default = __webpack_require__.n( external_window_micro_memoize_namespaceObject ) const getFlowChatProgress = chat => function_pipe( chat.animation, chainNullableK(x => x.currentTime), getOrElse(() => 0), x => x / chat.animationDuration ), getFlowChatRect = (chat, mainState) => function_pipe( mainState.config, x => mainState.playerRect.width * x.flowX2 - (chat.width + mainState.playerRect.width * (x.flowX2 - x.flowX1)) * getFlowChatProgress(chat), x => new DOMRect(x, chat.y, chat.width, chat.height) ), getChatLane = (flowChat, progress, flowChats) => mainState => { const flowWidth = mainState.playerRect.width * (mainState.config.flowX2 - mainState.config.flowX1), chatRect = getFlowChatRect(flowChat, mainState), chatWidth = chatRect.width, chatHeight = chatRect.height, chatX = chatRect.x, chatIndex = flowChats.indexOf(flowChat), movingChats = function_pipe( flowChats, ((n = chatIndex >= 0 ? chatIndex : -1), function (as) { return ReadonlyArray_isOutOfBound(n, as) ? as : 0 === n ? ReadonlyArray_empty : as.slice(0, n) }), es6_ReadonlyArray_filter( chat => !chat.animationEnded && chat.width > 0 ), ((O = Ord_contramap(x => x.lane)(number_Ord)), function (as) { return as.length <= 1 ? as : as.slice().sort(O.compare) }) ), tooCloseTo = external_window_micro_memoize_default()( i => { const otherRect = getFlowChatRect(movingChats[i], mainState), otherWidth = otherRect.width, otherX = otherRect.x, gap = (chatHeight * otherWidth * chatWidth) ** 0.333 * mainState.config.minSpacing return ( (flowWidth - otherX) / (flowWidth + otherWidth) - progress < (chatWidth + gap) / (flowWidth + chatWidth) || otherX + otherWidth + gap > chatX ) }, { maxSize: 1e3 } ), occupyInfo = function_pipe( movingChats, es6_ReadonlyArray_mapWithIndex((i, x) => ({ tooClose: () => tooCloseTo(i), lane: x.lane, })), ReadonlyArray_append({ tooClose: () => !0, lane: mainState.config.laneCount, }) ), index = occupyInfo.findIndex(x => x.lane >= flowChat.lane), rightFreeLane = function_pipe( occupyInfo.slice(index), ((predicate = x => x.tooClose()), function (as) { for (var i = 0; i < as.length; i++) if (predicate(as[i])) return some(as[i]) return none }), es6_Option_map(x => x.lane), getOrElse(() => mainState.config.laneCount) ) var O, n, predicate const leftFreeLane = function_pipe( occupyInfo.slice(0, index), function (as) { for (var i = as.length - 1; i >= 0; i--) if (as[i].tooClose()) return some(as[i]) return none }, es6_Option_map(x => x.lane), getOrElse(() => -1) ), formerLaneInterval = Math.min( flowChat.lane - leftFreeLane, rightFreeLane - flowChat.lane, 1 ) return function_pipe( occupyInfo, es6_ReadonlyArray_reduce( { maxInterval: 0, maxIntervalLane: 0, lastLane: -1 }, ({ maxInterval, maxIntervalLane, lastLane }, info) => maxInterval > 0.999 || !info.tooClose() ? { maxInterval, maxIntervalLane, lastLane } : (() => { const nextLane = info.lane, interLane = Math.min( Math.max((lastLane + nextLane) / 2, 0), mainState.config.laneCount - 1 ), newInterval = Math.min( interLane - lastLane, nextLane - interLane, 1 ) return newInterval - maxInterval > 0.001 ? { maxInterval: newInterval, maxIntervalLane: Math.max(lastLane + newInterval, 0), lastLane: nextLane, } : { maxInterval, maxIntervalLane, lastLane: nextLane } })() ), x => ({ lane: Math.abs(formerLaneInterval - x.maxInterval) < 0.001 ? flowChat.lane : x.maxIntervalLane, interval: x.maxInterval, }) ) }, intervalTooSmall = interval => config => config.noOverlap && interval < 0.999, external_m_namespaceObject = m var external_m_default = __webpack_require__.n(external_m_namespaceObject) const textShadow = shadowColor => function_flow( x => `${x}px`, x => (a, b) => `${a}${x} ${b}${x} ${shadowColor}99`, x => [x("-", "-"), x("", "-"), x("-", ""), x("", "")].join(", ") ), textStyle = { fontFamily: "inherit" }, renderChat = chat => mainState => () => external_m_default().render( chat.element, ((chat, mainState) => function_pipe( mainState.config, config => ({ data: chat.getData(config), config }), ({ data, config }) => external_m_default()( "span", { style: { fontSize: `${getChatFontSize(mainState)}px`, visibility: config.displayChats ? "visible" : "hidden", color: "owner" === data.authorType ? config.ownerColor : "moderator" === data.authorType ? config.moderatorColor : "member" === data.authorType ? config.memberColor : config.color, fontWeight: config.fontWeight.toString(), fontFamily: config.font, opacity: config.chatOpacity.toString(), textShadow: textShadow(config.shadowColor)( config.shadowFontWeight ), }, }, function_pipe( [ function_pipe( data.authorName, filter(x => x.visible), es6_Option_map(x => external_m_default()( "span", { style: { color: toUndefined(data.textColor), fontSize: "0.84em", ...textStyle, }, }, `${x.content}: ` ) ) ), function_pipe( data.messageElement, es6_Option_map(x => ((message, config) => { const eleWin = message.ownerDocument.defaultView ?? window, { maxChatLength } = config return function_pipe( Array.from(message.childNodes), es6_ReadonlyArray_reduce( { vnodes: [], length: 0 }, ({ vnodes, length }, node) => { return length >= maxChatLength ? { vnodes, length } : !config.textOnly && node instanceof eleWin.HTMLImageElement ? { vnodes: [ ...vnodes, external_m_default()("img", { style: { height: "1em", width: "1em", verticalAlign: "text-top", }, src: node.src.replace( /=w\d+-h\d+-c-k-nd$/, "" ), alt: node.alt, }), ], length: length + 1, } : function_pipe( node.textContent ?? "", ((end = maxChatLength), function (s) { return s.slice(0, end) }), x => node instanceof eleWin.HTMLAnchorElement ? { vnodes: [ ...vnodes, external_m_default()( "span", { style: { fontSize: "0.84em", textDecoration: "underline", ...textStyle, }, }, x ), ], length: length + x.length, } : { vnodes: [ ...vnodes, external_m_default().fragment( {}, x ), ], length: length + x.length, } ) var end } ) ) })(x, config) ), es6_Option_map(x => external_m_default()( "span", { style: { color: toUndefined(data.textColor), ...textStyle, }, }, x.vnodes ) ) ), function_pipe( data.paymentInfo, filter(x => x.visible), es6_Option_map(x => external_m_default()( "span", { style: { color: toUndefined(data.paidColor), fontSize: "0.84em", ...textStyle, }, }, external_m_default()( "strong", { style: textStyle }, x.content ) ) ) ), ], ReadonlyArray_compact, toArray ) ) ))(chat, mainState) ), external_window_hash_it_namespaceObject = window["hash-it"] var external_window_hash_it_default = __webpack_require__.n( external_window_hash_it_namespaceObject ) const getLaneY = (lane, mainState) => mainState.playerRect.height * ((lane / mainState.config.laneCount + 0.005) * (mainState.config.flowY2 - mainState.config.flowY1) + mainState.config.flowY1), setChatPlayState = chat => mainState => function_pipe( chat, fromPredicate(x => !x.animationEnded), IOOption_fromOption, IOOption_chainOptionK(x => x.animation), IOOption_chainFirstIOK(x => mainState.chatPlaying ? () => x.play() : () => x.pause() ), IOOption_chainIOK(x => () => { x.playbackRate = mainState.config.flowSpeed / 15 }) ), getWidth = external_window_micro_memoize_default()( ele => ele?.getBoundingClientRect().width ?? 0, { maxSize: 2e3, transformKey: function_flow( es6_ReadonlyArray_map(external_window_hash_it_default()), toArray ), } ), setChatAnimation = (chat, chats) => mainState => function_pipe( { fontSize: getChatFontSize(mainState) }, of, IO_chainFirst(x => () => { chat.element.style.transform = `translate(${ mainState.playerRect.width * (mainState.config.flowX2 - mainState.config.flowX1) }px, -${2 * x.fontSize}px)` }), IOOption_fromIO, IOOption_filter(() => !chat.animationEnded), IOOption_chainFirstIOK(x => () => { chat.animationDuration = 6400 chat.width = getWidth(chat.element.firstElementChild) chat.height = x.fontSize }), IOOption_map(() => ({ progress: getFlowChatProgress(chat) })), IOOption_map(x => ({ ...x, ...getChatLane(chat, x.progress, chats)(mainState), })), IOOption_chain(ctx => intervalTooSmall(ctx.interval)(mainState.config) ? function_pipe( chat.animation, IOOption_fromOption, IOOption_chainIOK(x => () => { x.finish() chat.animation = Option_none }), IO_map(() => Option_none) ) : IOOption_of(ctx) ), IOOption_chainFirstIOK(x => () => { chat.lane = x.lane }), IOOption_map(x => ({ ...x, laneY: getLaneY(chat.lane, mainState) })), IOOption_chain(ctx => function_pipe( [ function_pipe( chat.animation, IOOption_fromOption, IOOption_chainIOK(x => () => x.cancel()) ), function_pipe( [ [ mainState.playerRect.width * (mainState.config.flowX2 - mainState.config.flowX1), ctx.laneY, ], [-chat.width, ctx.laneY], ], es6_ReadonlyArray_map(es6_ReadonlyArray_map(x => `${x}px`)), es6_ReadonlyArray_map(([x, y]) => `translate(${x}, ${y})`), ReadonlyArray_bindTo("transform"), toArray, x => chat.element.animate(x, { duration: 6400, easing: mainState.config.timingFunction, }), x => { x.onfinish = () => { chat.animationEnded = !0 } chat.y = ctx.laneY const newTime = 6400 * ctx.progress x.currentTime = newTime return x }, Option_of, x => () => { chat.animation = x }, IO_apSecond(setChatPlayState(chat)(mainState)) ), ], sequenceArray, IOOption_fromIO ) ), IO_map(Option_isSome) ), emptyElement = document.createElement("span"), appendChatMessage = flip(chat => chain(x => () => chat.querySelector("#content #message")?.append(x)) ), external_Swal_namespaceObject = Swal var external_Swal_default = __webpack_require__.n( external_Swal_namespaceObject ) const defaultToast = external_Swal_default().mixin({ toast: !0, position: "bottom-left", timer: 2500, timerProgressBar: !0, showConfirmButton: !1, didOpen: toast => { toast.addEventListener( "pointerenter", external_Swal_default().stopTimer ) toast.addEventListener( "pointerleave", external_Swal_default().resumeTimer ) }, }), template = function_pipe( document.createElement("button"), of, IO_chainFirst( x => () => x.classList.add("style-scope", "yt-icon-button", "fyc_button") ), IO_chainFirst( x => () => Object.assign(x.style, { padding: "0px", width: "20px", height: "20px", fill: "#fff", }) ), IO_chainFirst( x => () => x.setAttribute("aria-label", "NGに入れる(Ban this user)") ), IO_chainFirst(x => () => { x.innerHTML = '' }) )(), banButton = id => getConfig => setConfig => chat => { return function_pipe( getConfig.bannedUsers, IOOption_fromIO, IOOption_filter(x => !x.includes(id)), IOOption_map( function_flow( ((f = (function (E) { return function (as) { if (1 === as.length) return as for ( var out = [ReadonlyNonEmptyArray_head(as)], _loop_1 = function (a) { out.every(function (o) { return !E.equals(o, a) }) && out.push(a) }, _i = 0, rest_1 = ReadonlyNonEmptyArray_tail(as); _i < rest_1.length; _i++ ) _loop_1(rest_1[_i]) return out } })(Eq)), function (as) { return ReadonlyArray_isNonEmpty(as) ? f(as) : as }), ReadonlyArray_append(id) ) ), IOOption_chainIOK(x => function_pipe( setConfig.bannedUsers(x), IO_apSecond(() => defaultToast.fire({ title: `Added Banned User: ${id}`, icon: "success", }) ) ) ), IO_apSecond(() => { chat.style.display = "none" }), onclick => function_pipe( () => template.cloneNode(!0), IO_chainFirst(x => () => { x.onclick = onclick }) ) ) var f } var Monoid_concatAll = function (M) { return (function (M) { return function (startWith) { return function (as) { return as.reduce(function (a, acc) { return M.concat(a, acc) }, startWith) } } })(M)(M.empty) } const filterOperators = { flip, flow: fns => function_flow(...fns), and: Monoid_concatAll({ concat: function (first, second) { return first && second }, empty: !0, }), or: Monoid_concatAll({ concat: function (first, second) { return first || second }, empty: !1, }), RA: { some: ReadonlyArray_some, compact: ReadonlyArray_compact }, O: { exists: function (predicate) { return function (ma) { return !Option_isNone(ma) && predicate(ma.value) } }, }, inText: text => x => { return ((searchString = x), function (s) { return s.includes(searchString, undefined) })(text.content) var searchString }, eqText: text => x => text.content === x, matchedByText: text => x => Boolean(text.content.match(RegExp(x, "u"))), isVisible: x => x.visible, }, filter_filterOperators = filterOperators, assert_lib = check.assert, tapNonNull = x => { assert_lib(null != x) return x }, parseChat = chat => { const chatType = chat.querySelector( ".yt-live-chat-ticker-paid-message-item-renderer" ) ? "ticker" : chat.querySelector(".yt-live-chat-membership-item-renderer") ? "membership" : chat.querySelector( ".yt-live-chat-viewer-engagement-message-renderer" ) ? "engagement" : "normal", isPaid = "ticker" === chatType || Boolean(chat.querySelector("#card")), paymentInfo = function_pipe( fromNullable( isPaid ? chat.querySelector( [ "#purchase-amount", "#purchase-amount-chip", "#content>#text", ].join(",") )?.textContent : void 0 ), es6_Option_map(x => ({ visible: !0, content: x })) ), authorType = chat.querySelector(".owner") ? "owner" : chat.querySelector(".moderator") ? "moderator" : chat.querySelector(".member") ? "member" : "normal", messageElement = fromNullable(chat.querySelector("#message")), isPaidNormal = !!Option_isSome(paymentInfo) && Boolean(chat.querySelector(".yt-live-chat-paid-message-renderer")), isPaidSticker = !(!Option_isSome(paymentInfo) || isPaidNormal) && Boolean(chat.querySelector(".yt-live-chat-paid-sticker-renderer")), textColor = fromNullable( isPaidNormal ? window .getComputedStyle(tapNonNull(chat.querySelector("#header"))) .getPropertyValue("background-color") : isPaidSticker ? window .getComputedStyle(chat) .getPropertyValue( "--yt-live-chat-paid-sticker-chip-background-color" ) : void 0 ), paidColor = fromNullable( isPaidNormal ? window .getComputedStyle(tapNonNull(chat.querySelector("#content"))) .getPropertyValue("background-color") : isPaidSticker ? window .getComputedStyle(chat) .getPropertyValue( "--yt-live-chat-paid-sticker-background-color" ) : void 0 ), authorPhotoMatches = chat .querySelector(["#author-photo", "img"].join(" ")) ?.src.match(/ggpht\.com\/(ytc\/)?(.*)=/), authorID = fromNullable(authorPhotoMatches?.at(-1)), authorName = fromNullable( chat.querySelector("#author-name")?.textContent ), message = function_pipe( messageElement, es6_Option_map(x => ({ visible: !0, content: x.innerHTML })) ), messageText = function_pipe( messageElement, es6_Option_map(x => ({ visible: !0, content: x.textContent ?? "" })) ) return config => ({ chatType, authorType, authorID, authorName: function_pipe( authorName, es6_Option_map(x => ({ visible: ("moderator" === authorType && config.displayModName) || (Option_isSome(paymentInfo) && config.displaySuperChatAuthor), content: x, })) ), messageElement, message, messageText, paymentInfo, textColor, paidColor, }) }, onChatFieldMutate = ( chatScrn, flowChats, mainState, getConfig, setConfig ) => function_flow( es6_ReadonlyArray_chain(e => Array.from(e.addedNodes)), es6_ReadonlyArray_filter(x => x.children.length > 0), ReadonlyArray_reverse, es6_ReadonlyArray_map(chat => function_pipe( { getData: parseChat(chat), config: mainState.config }, Identity_let_("data", x => x.getData(x.config)), State_of, State_bind("banned", x => { return function_pipe( ((data = x.data), (config = x.config), function_pipe( data, fromPredicate(() => function_pipe(config.filterExp, x => a( x, (data => ({ ...filter_filterOperators, authorName: data.authorName, message: data.message, messageText: data.messageText, paymentInfo: data.paymentInfo, authorID: function_pipe( data.authorID, es6_Option_map(x => ({ visible: !1, content: x })) ), }))(data) ) ) ), es6_Option_map(x => [ function_pipe( x.message, es6_Option_map(m => m.content) ), function_pipe( x.paymentInfo, es6_Option_map(p => p.content) ), ]), es6_Option_map(es6_ReadonlyArray_map(getOrElse(() => ""))), es6_Option_map(JSON.stringify), es6_Option_map(x => [`Filtered: ${x}`]), match( () => State_of(!1), x => s => [!0, [...s, x]] ) )) ) var data, config }), es6_State_map(ctx => ctx.banned ? () => { chat.style.display = "none" } : sequenceArray([ function_pipe( ctx.config.createChats && "normal" === ctx.data.chatType, IOOption_fromPredicate(function_identity), IOOption_chainIOK(() => ((getData, flowChats, chatScrn, mainState) => function_pipe( { getData, element: emptyElement, lane: -1, animation: Option_none, animationDuration: 0, animationEnded: !1, width: 2, height: getChatFontSize(mainState), y: 0, }, x => getChatLane(x, 0, flowChats)(mainState) .interval, intervalTooSmall, x => x(mainState.config) ) ? () => {} : () => { const offScreenIndex = function_pipe( flowChats, findIndex( chat => chat.animationEnded || flowChats.length >= mainState.config.maxChatCount ) ), element = function_pipe( offScreenIndex, es6_Option_map(x => flowChats[x].element), getOrElseW(() => document.createElement("span") ) ) function_pipe( offScreenIndex, match( () => () => { external_log_default().debug( "CreateFlowChat" ) chatScrn.append(element) }, i => function_pipe( () => flowChats.splice(i, 1)[0].animation, IOOption_chainIOK( oldAnimation => () => oldAnimation.cancel() ) ) ) )() const flowChat = { getData, element, lane: -1, animation: Option_none, animationDuration: 0, animationEnded: !1, width: 2, height: getChatFontSize(mainState), y: 0, } element.classList.add("fyc_chat") function_pipe( mainState, of, IO_chainFirst(renderChat(flowChat)), chain( setChatAnimation(flowChat, flowChats) ), chain(x => x ? () => flowChats.push(flowChat) : () => flowChat.element.remove() ) )() })(ctx.getData, flowChats, chatScrn, mainState) ) ), function_pipe( ctx.data.authorID, filter(() => ctx.config.createBanButton), IOOption_fromOption, IOOption_filter(() => !chat.children.namedItem("card")), IOOption_chainIOK(x => es6_Reader_chain(appendChatMessage)( banButton(x)(getConfig)(setConfig) )(chat) ) ), function_pipe( ctx.config.simplifyChatField, IOOption_fromPredicate(function_identity), IOOption_chainIOK(() => (chat => chat.querySelector( ".style-scope.yt-live-chat-paid-message-renderer" ) ? () => {} : function_pipe( [ "#author-photo", "yt-live-chat-author-chip.style-scope.yt-live-chat-text-message-renderer", ], es6_ReadonlyArray_map(x => fromNullable(chat.querySelector(x)) ), ReadonlyArray_compact, es6_ReadonlyArray_map(x => () => { x.style.display = "none" }), ReadonlyArray_append(() => { chat.style.borderBottom = "1px solid var(--yt-spec-text-secondary)" }), sequenceArray ))(chat) ) ), ]) ) ) ), State_sequenceArray, es6_State_map(sequenceArray) ), removeOldChats = flowChats => maxChatCount => function_pipe( () => flowChats.sort((a, b) => a.animationEnded === b.animationEnded ? 0 : a.animationEnded ? -1 : 1 ), IO_apSecond(() => flowChats.splice(0, Math.max(0, flowChats.length - maxChatCount)) ), chain( removed => () => removed.forEach(x => { external_log_default().debug("RemoveChat") x.element.remove() }) ) ), setChatAppCss = chatField => () => function_pipe( fromNullable(chatField.parentElement), es6_Option_map(x => () => { x.style.overflow = "unset" }) ), exceptions = ["timingFunction", "lang"], isEditable = k => v => ("number" == typeof v || "string" == typeof v || (Array.isArray(v) && ("string" == typeof v[0] || 0 === v.length))) && !ReadonlyArray_some(x => x === k)(exceptions) function fst(ea) { return ea[0] } function snd(ea) { return ea[1] } var mapFst = function (f) { return function (fa) { return [f(fst(fa)), snd(fa)] } }, mapSnd = function (f) { return function (fa) { return [fst(fa), f(snd(fa))] } } const Editable_of = x => [x, Option_none], fromValueText = v => t => [v, Option_of([t, Option_none])], Editable_value = fst, Editable_text = function_flow(snd, es6_Option_map(fst)), error = function_flow(snd, es6_Option_chain(snd)), setValue = function_flow(constant, mapFst), setText = x => mapSnd( function_flow( es6_Option_map(mapFst(constant(x))), alt(constant(Option_of([x, Option_none]))) ) ), hasError = function_flow(error, Option_isSome), identifier = function_identity, isExpType = type => x => x.type === type, fromJsepExp = x => { return isExpType("Identifier")(x) ? Option_of(identifier(x)) : isExpType("MemberExpression")(x) ? ((f = fromJsepExp), exp => function_pipe( { type: exp.type, computed: exp.computed }, Option_of, Option_bind("object", () => f(exp.object)), Option_bind("property", () => f(exp.property)) ))(x) : isExpType("CallExpression")(x) ? ( f => exp => function_pipe( { type: exp.type }, Option_of, Option_bind("argument", () => function_pipe( exp.arguments, ReadonlyArray_head, es6_Option_map(f) ) ), Option_bind("callee", () => f(exp.callee)) ) )(fromJsepExp)(x) : isExpType("Literal")(x) ? "string" == typeof (exp = x).value ? Option_of({ type: "Literal", value: Editable_of(exp.value) }) : Option_none : isExpType("ArrayExpression")(x) ? ( f => exp => function_pipe(exp.elements, elements => function_pipe( elements, fromPredicate(every(x => "Literal" === x.type)), filter(every(x => "string" == typeof x.value)), es6_Option_map(es => ({ type: "LiteralArray", value: Editable_of( function_pipe( es, es6_ReadonlyArray_map(x => x.value) ) ), })), x => Option_isSome(x) ? x : function_pipe( { type: exp.type }, Option_of, Option_bind("elements", () => function_pipe( elements, es6_ReadonlyArray_map(f), Option_sequenceArray ) ) ) ) ) )(fromJsepExp)(x) : isExpType("Compound")(x) ? ( f => exp => function_pipe( { type: exp.type }, Option_of, Option_bind("body", () => function_pipe( exp.body, es6_ReadonlyArray_map(f), Option_sequenceArray ) ) ) )(fromJsepExp)(x) : Option_none var f, exp }, EditableExpression_fromJsepExp = fromJsepExp, settingStateInit = config => function_pipe( config, mapObject(([k, v]) => [ k, isEditable(k)(v) ? Editable_of(v) : "filterExp" === k ? function_pipe( EditableExpression_fromJsepExp(v), getOrElseW(() => ({ type: "Compound", body: [] })) ) : v, ]), x => ({ ...x, showPanel: !1, mainTab: 0, logTab: 0, timingStepCount: Editable_of( parseInt( config.timingFunction.match(/^steps\((\d+),.+/)?.[1] ?? "150", 10 ) ), eventLog: [], panelRect: new DOMRectReadOnly(0, 0, 660, 395), }) ) var EMPTY_OBJ = {}, EMPTY_ARR = [], hyperapp_id = a => a, hyperapp_map = EMPTY_ARR.map, isArray = Array.isArray, enqueue = "undefined" != typeof requestAnimationFrame ? requestAnimationFrame : setTimeout, createClass = obj => { var out = "" if ("string" == typeof obj) return obj if (isArray(obj)) for (var tmp, k = 0; k < obj.length; k++) (tmp = createClass(obj[k])) && (out += (out && " ") + tmp) else for (var k in obj) obj[k] && (out += (out && " ") + k) return out }, shouldRestart = (a, b) => { for (var k in { ...a, ...b }) if ("function" == typeof (isArray(a[k]) ? a[k][0] : a[k])) b[k] = a[k] else if (a[k] !== b[k]) return !0 }, getKey = vdom => (null == vdom ? vdom : vdom.key), patchProperty = (node, key, oldValue, newValue, listener, isSvg) => { if ("style" === key) for (var k in { ...oldValue, ...newValue }) { oldValue = null == newValue || null == newValue[k] ? "" : newValue[k] "-" === k[0] ? node[key].setProperty(k, oldValue) : (node[key][k] = oldValue) } else "o" === key[0] && "n" === key[1] ? ((node.events || (node.events = {}))[(key = key.slice(2))] = newValue) ? oldValue || node.addEventListener(key, listener) : node.removeEventListener(key, listener) : !isSvg && "list" !== key && "form" !== key && key in node ? (node[key] = newValue ?? "") : null == newValue || !1 === newValue ? node.removeAttribute(key) : node.setAttribute(key, newValue) }, createNode = (vdom, listener, isSvg) => { var props = vdom.props, node = 3 === vdom.type ? document.createTextNode(vdom.tag) : (isSvg = isSvg || "svg" === vdom.tag) ? document.createElementNS( "http://www.w3.org/2000/svg", vdom.tag, props.is && props ) : document.createElement(vdom.tag, props.is && props) for (var k in props) patchProperty(node, k, null, props[k], listener, isSvg) for (var i = 0; i < vdom.children.length; i++) node.appendChild( createNode( (vdom.children[i] = maybeVNode(vdom.children[i])), listener, isSvg ) ) return (vdom.node = node) }, patch = (parent, node, oldVNode, newVNode, listener, isSvg) => { if (oldVNode === newVNode); else if (null != oldVNode && 3 === oldVNode.type && 3 === newVNode.type) oldVNode.tag !== newVNode.tag && (node.nodeValue = newVNode.tag) else if (null == oldVNode || oldVNode.tag !== newVNode.tag) { node = parent.insertBefore( createNode((newVNode = maybeVNode(newVNode)), listener, isSvg), node ) null != oldVNode && parent.removeChild(oldVNode.node) } else { var tmpVKid, oldVKid, oldKey, newKey, oldProps = oldVNode.props, newProps = newVNode.props, oldVKids = oldVNode.children, newVKids = newVNode.children, oldHead = 0, newHead = 0, oldTail = oldVKids.length - 1, newTail = newVKids.length - 1 isSvg = isSvg || "svg" === newVNode.tag for (var i in { ...oldProps, ...newProps }) ("value" === i || "selected" === i || "checked" === i ? node[i] : oldProps[i]) !== newProps[i] && patchProperty(node, i, oldProps[i], newProps[i], listener, isSvg) for ( ; newHead <= newTail && oldHead <= oldTail && null != (oldKey = getKey(oldVKids[oldHead])) && oldKey === getKey(newVKids[newHead]); ) patch( node, oldVKids[oldHead].node, oldVKids[oldHead], (newVKids[newHead] = maybeVNode( newVKids[newHead++], oldVKids[oldHead++] )), listener, isSvg ) for ( ; newHead <= newTail && oldHead <= oldTail && null != (oldKey = getKey(oldVKids[oldTail])) && oldKey === getKey(newVKids[newTail]); ) patch( node, oldVKids[oldTail].node, oldVKids[oldTail], (newVKids[newTail] = maybeVNode( newVKids[newTail--], oldVKids[oldTail--] )), listener, isSvg ) if (oldHead > oldTail) for (; newHead <= newTail; ) node.insertBefore( createNode( (newVKids[newHead] = maybeVNode(newVKids[newHead++])), listener, isSvg ), (oldVKid = oldVKids[oldHead]) && oldVKid.node ) else if (newHead > newTail) for (; oldHead <= oldTail; ) node.removeChild(oldVKids[oldHead++].node) else { var keyed = {}, newKeyed = {} for (i = oldHead; i <= oldTail; i++) null != (oldKey = oldVKids[i].key) && (keyed[oldKey] = oldVKids[i]) for (; newHead <= newTail; ) { oldKey = getKey((oldVKid = oldVKids[oldHead])) newKey = getKey( (newVKids[newHead] = maybeVNode(newVKids[newHead], oldVKid)) ) if ( newKeyed[oldKey] || (null != newKey && newKey === getKey(oldVKids[oldHead + 1])) ) { null == oldKey && node.removeChild(oldVKid.node) oldHead++ } else if (null == newKey || 1 === oldVNode.type) { if (null == oldKey) { patch( node, oldVKid && oldVKid.node, oldVKid, newVKids[newHead], listener, isSvg ) newHead++ } oldHead++ } else { if (oldKey === newKey) { patch( node, oldVKid.node, oldVKid, newVKids[newHead], listener, isSvg ) newKeyed[newKey] = !0 oldHead++ } else if (null != (tmpVKid = keyed[newKey])) { patch( node, node.insertBefore(tmpVKid.node, oldVKid && oldVKid.node), tmpVKid, newVKids[newHead], listener, isSvg ) newKeyed[newKey] = !0 } else patch( node, oldVKid && oldVKid.node, null, newVKids[newHead], listener, isSvg ) newHead++ } } for (; oldHead <= oldTail; ) null == getKey((oldVKid = oldVKids[oldHead++])) && node.removeChild(oldVKid.node) for (var i in keyed) null == newKeyed[i] && node.removeChild(keyed[i].node) } } return (newVNode.node = node) }, maybeVNode = (newVNode, oldVNode) => !0 !== newVNode && !1 !== newVNode && newVNode ? "function" == typeof newVNode.tag ? ((!oldVNode || null == oldVNode.memo || ((a, b) => { for (var k in a) if (a[k] !== b[k]) return !0 for (var k in b) if (a[k] !== b[k]) return !0 })(oldVNode.memo, newVNode.memo)) && ((oldVNode = newVNode.tag(newVNode.memo)).memo = newVNode.memo), oldVNode) : newVNode : hyperapp_text(""), recycleNode = node => 3 === node.nodeType ? hyperapp_text(node.nodeValue, node) : createVNode( node.nodeName.toLowerCase(), EMPTY_OBJ, hyperapp_map.call(node.childNodes, recycleNode), 1, node ), createVNode = (tag, { key, ...props }, children, type, node) => ({ tag, props, key, children, type, node, }), hyperapp_text = (value, node) => createVNode(value, EMPTY_OBJ, EMPTY_ARR, 3, node), h = (tag, { class: c, ...props }, children = EMPTY_ARR) => createVNode( tag, { ...props, ...(c ? { class: createClass(c) } : EMPTY_OBJ) }, isArray(children) ? children : [children] ), app = ({ node, view, subscriptions, dispatch = hyperapp_id, init = EMPTY_OBJ, }) => { var state, busy, vdom = node && recycleNode(node), subs = [], update = newState => { if (state !== newState) { null == (state = newState) && (dispatch = subscriptions = render = hyperapp_id) subscriptions && (subs = ((oldSubs, newSubs = EMPTY_ARR, dispatch) => { for ( var oldSub, newSub, subs = [], i = 0; i < oldSubs.length || i < newSubs.length; i++ ) { oldSub = oldSubs[i] newSub = newSubs[i] subs.push( newSub && !0 !== newSub ? !oldSub || newSub[0] !== oldSub[0] || shouldRestart(newSub[1], oldSub[1]) ? [ newSub[0], newSub[1], (oldSub && oldSub[2](), newSub[0](dispatch, newSub[1])), ] : oldSub : oldSub && oldSub[2]() ) } return subs })(subs, subscriptions(state), dispatch)) view && !busy && enqueue(render, (busy = !0)) } }, render = () => (node = patch( node.parentNode, node, vdom, (vdom = view(state)), listener, (busy = !1) )), listener = function (event) { dispatch(this.events[event.type], event) } return ( (dispatch = dispatch((action, props) => "function" == typeof action ? dispatch(action(state, props)) : isArray(action) ? "function" == typeof action[0] ? dispatch(action[0], action[1]) : action .slice(1) .map( fx => fx && !0 !== fx && (fx[0] || fx)(dispatch, fx[1]), update(action[0]) ) : update(action) ))(init), dispatch ) } const makeComponent = x => tag => ({ tag, view: x(tag) }), src_flip = x => (...b) => (...a) => x(...a)(...b), defaultText = { setting: ["Settings", "設定"], font: ["Font", "フォント"], color: ["Color(Normal)", "色(通常)"], ownerColor: ["Color(Owner)", "色(オーナー)"], moderatorColor: ["Color(Moderator)", "色(モデレーター)"], memberColor: ["Color(Member)", "色(メンバー)"], feedback: ["Feedback", "バグ報告と要望"], eventLog: ["Event log", "イベントログ"], giveFeedback: [ "Give your feedbacks here(Please attach the event log if they're bug related)", "バグ報告、要望はこちら(バグの場合は、イベントログを添付してください)", ], chatOpacity: ["Opacity", "不透明度"], fontSize: ["Size", "サイズ"], fontWeight: ["Weight", "太さ"], shadowFontWeight: ["Weight(Shadow)", "太さ(影)"], flowSpeed: ["Speed", "速度"], maxChatCount: ["Max number of chats", "最大表示数"], maxChatLength: ["Max number of characters", "最大文字数"], laneCount: ["Number of rows", "行数"], bannedWords: ["Banned Words", "NGワード"], bannedWordRegexs: ["Banned Words(Regex)", "NGワード(正規表現)"], bannedUsers: ["Banned Users", "NGユーザー"], simplifyChatField: ["Simplify", "簡略化する"], createBanButton: ["Show ban button", "NGボタンを表示する"], displayModName: [ "Show moderator's name", "モデレーターの名前を表示する", ], displaySuperChatAuthor: [ "Show super chat author", "スパチャの作成者を表示する", ], createChats: ["Display flowing chats", "チャットを流す"], textOnly: ["Text only(ignore emojis)", "文字のみ(絵文字を無視する)"], error: ["Error", "エラー"], video: ["Video", "画面"], chatField: ["Chat Window", "チャット欄"], useStepTiming: ["Move chat in steps", "チャットを段階的に動かす"], timingStepCount: ["└Step Count", "└段階数"], chatFilter: ["Chat Filter", "チャットフィルター"], flowChat: ["Flow Chat", "チャット流れ"], clearFlowChats: ["Clear Flowing Chats", "流れるチャットをクリアする"], flowNewChatIf: [ "A new chat will appear if all of the followings are met:", "新しいチャットは以下のすべてを満たす場合に流れます:", ], noOverlap: ["└Chats won't overlap", "└他のチャットと重ならない"], minSpacing: ["Min spacing between chats", "チャットの最小間隔"], fieldScale: ["Scale", "拡大率"], copy: ["Copy", "コピーする"], showChat: ["Show chats", "チャットを表示する"], hideChat: ["Hide chats", "チャットを非表示にする"], flowY1: ["Flow area top edge", "流れ範囲の上端"], flowY2: ["Flow area bottom edge", "流れ範囲の下端"], flowX1: ["Flow area left edge", "流れ範囲の左端"], flowX2: ["Flow area right edge", "流れ範囲の右端"], shadowColor: ["Color(Shadow)", "色(影)"], invalidColor: ["Invalid color", "無効な色"], inputNonNumberic: ["Input isn't a number", "入力値が数字でない"], invalidSetting: ["Invalid setting", "無効な設定値"], }, getText = key => language => defaultText[key]["FYC_EN" === language ? 0 : 1], languageLabels = ["English", "日本語"], computed = { useStepTiming: s => Boolean(s.timingFunction.match(/^steps\(.+/)), }, getState = k => (k in computed ? computed[k] : s => s[k]), toJsepExp_identifier = function_identity, toJsepExp = x => { return "Identifier" === x.type ? toJsepExp_identifier(x) : "ArrayExpression" === x.type ? ((f = toJsepExp), exp => function_pipe({ type: exp.type, elements: function_pipe( es6_ReadonlyArray_map(f)(exp.elements), toArray ), }))(x) : "MemberExpression" === x.type ? (f => exp => ({ ...exp, object: f(exp.object), property: f(exp.property), }))(toJsepExp)(x) : "CallExpression" === x.type ? (f => exp => ({ ...exp, arguments: function_pipe( exp.argument, es6_Option_map(f), es6_Option_map(ReadonlyArray_of), es6_Option_map(toArray), getOrElse(constant([])) ), callee: f(exp.callee), }))(toJsepExp)(x) : "Literal" === x.type ? function_pipe(x.value, Editable_value, x => ({ type: "Literal", value: x, raw: JSON.stringify(x), })) : "LiteralArray" === x.type ? { type: "ArrayExpression", elements: function_pipe( x.value, Editable_value, es6_ReadonlyArray_map( function_flow(x => ({ type: "Literal", value: x, raw: JSON.stringify(x), })) ), toArray ), } : ( f => exp => function_pipe({ type: exp.type, body: function_pipe( es6_ReadonlyArray_map(f)(exp.body), toArray ), }) )(toJsepExp)(x) var f }, EditableExpression_toJsepExp = toJsepExp, configEffect = (k, v) => setConfig => setConfig[k](v), stepTiming = stepCount => `steps(${stepCount}, jump-end)`, setComputed = { useStepTiming: v => c => s => function_pipe( v ? stepTiming(Editable_value(s.timingStepCount)) : "linear", timingFunction => [ { ...s, timingFunction }, configEffect("timingFunction", timingFunction)(c.setConfig), ] ), }, settingUI_setComputed = setComputed, setRange = keyA => keyB => bFn => vA => c => s => function_pipe( { a: Editable_value(vA) }, Identity_let_("b", ({ a }) => bFn(a)(Editable_value(s[keyB]))), ({ a, b }) => function_pipe( [configEffect(keyA, a), configEffect(keyB, b)], Reader_sequenceArray, es6_Reader_map(effects => [ { ...s, [keyA]: vA, [keyB]: setValue(b)(s[keyB]) }, ...effects, ]) )(c.setConfig) ), setState = { flowY1: setRange("flowY1")("flowY2")(a => b => Math.max(b, a + 0.05)), flowY2: setRange("flowY2")("flowY1")(a => b => Math.min(b, a - 0.05)), flowX1: setRange("flowX1")("flowX2")(a => b => Math.max(b, a + 0.05)), flowX2: setRange("flowX2")("flowX1")(a => b => Math.min(b, a - 0.05)), timingStepCount: v => c => s => function_pipe(stepTiming(Editable_value(v)), timingFunction => [ { ...s, timingStepCount: v, timingFunction }, configEffect("timingFunction", timingFunction)(c.setConfig), ]), }, settingUI_setState = setState, settingUI_updateAt = k => v => function_pipe( k in settingUI_setComputed ? settingUI_setComputed[k](v) : k in settingUI_setState ? settingUI_setState[k](v) : c => s => [ { ...s, [k]: v }, ...(k in c.setConfig ? [ configEffect( k, Array.isArray(v) && 2 === v.length && isEditable(k)(v[0]) ? Editable_value(v) : "filterExp" === k ? EditableExpression_toJsepExp(v) : v )(c.setConfig), ] : []), ] ), tapIs = constructor => x => { assert_lib(x instanceof constructor) return x }, checkboxNode = label => c => s => { return ((label, checked, onchange) => h( "div", {}, h("label", {}, [ hyperapp_text(label), h("input", { type: "checkbox", checked, onchange }), ]) ))( getText(label)(s.lang), getState(label)(s), ((key = label), src_flip((s, e) => function_pipe( (e => tapIs(HTMLInputElement)(e.currentTarget).checked)(e), settingUI_updateAt(key), src_flip, apply(s) ) ))(c) ) var key }, updateInput = setter => key => src_flip((s, e) => function_pipe( (e => { const target = e.currentTarget ?? e.__target if ( target instanceof HTMLSelectElement || target instanceof HTMLTextAreaElement || target instanceof HTMLInputElement ) return target.value throw Error("Event target type isn't acceptable.") })(e), setter, apply(getState(key)(s)), settingUI_updateAt(key), src_flip, apply(s) ) ), editAction = (key, setter) => c => ({ oninput: (s, e) => updateInput(setter(!0))(key)(c)(s, e), onchange: (s, e) => updateInput(setter(!1))(key)(c)(s, e), }), setEditNumber = editing => value => state => function_pipe( value, Number.parseFloat, editing ? x => Number.isNaN(x) || "." === value.at(-1) ? function_pipe(state, setText(value)) : fromValueText(x)(value) : x => Number.isNaN(x) ? function_pipe( state, mapSnd(constant(Option_of([value, Option_of("")]))) ) : Editable_of(x) ), errorText = subject => edit => function_pipe( edit, error, es6_Option_map(x => `${subject}${"" === x ? "" : ": "}${x}`), getOrElse(constant("")) ), rangeRow = (min, max, step, action) => value => h("div", {}, [ h("input", { style: { width: "150px", verticalAlign: "middle" }, type: "range", min, max, step, value: Editable_value(value).toString(), oninput: action.onchange, }), h("input", { style: { width: "30px", backgroundColor: "transparent", color: "inherit", borderWidth: "1px", verticalAlign: "middle", borderColor: hasError(value) ? "#f55" : void 0, }, inputmode: "decimal", value: function_pipe( value, Editable_text, getOrElse( constant( Editable_value(value) .toFixed(4) .replace(/\.?0+$/, "") ) ) ), ...action, }), ]), settingRow = (label, error, content) => h("div", {}, [ h("span", {}, hyperapp_text(label)), h( "span", { style: { color: "#f55", marginLeft: "5px", whiteSpace: "pre-wrap", }, }, hyperapp_text(error) ), h("div", {}, content), ]), numberNode = (label, min, max, step) => c => s => settingRow( getText(label)(s.lang), errorText(getText("inputNonNumberic")(s.lang))(s[label]), [ rangeRow( min, max, step, editAction(label, setEditNumber)(c) )(getState(label)(s)), ] ), panelBoxStyle = width => ({ flex: `0 0 ${width}px`, margin: "2px" }), settingUI_chatFieldPanel = function_pipe( [ function_pipe( [ numberNode("fieldScale", 0.7, 1.5, 0.05), checkboxNode("simplifyChatField"), checkboxNode("createBanButton"), ], Reader_sequenceArray, es6_Reader_map(Reader_sequenceArray), es6_Reader_map( es6_Reader_map(x => h("div", { style: panelBoxStyle(644) }, x)) ) ), ], Reader_sequenceArray, es6_Reader_map(Reader_sequenceArray) ), action = { copy: () => s => async () => { GM.setClipboard(s.eventLog.join("\n")) }, clearFlowChats: c => s => async () => { c.act.clearFlowChats() }, }, buttonNode = label => c => state => h( "button", { type: "button", onclick: s => [s, action[label](c)(s)] }, hyperapp_text(getText(label)(state.lang)) ), tabContainer = style => ontabSelect => labels => tabs => mainTab => h("div", {}, [ h( "div", {}, function_pipe( labels, es6_ReadonlyArray_mapWithIndex((i, x) => h( "span", { style: { ...style.label, ...(mainTab === i ? style.labelFocus : {}), display: "inline-block", }, onpointerdown: [ontabSelect, i], }, hyperapp_text(x) ) ) ) ), h( "div", { style: { ...style.container, overflow: "auto" } }, h( "div", { style: { ...style.tab } }, tabs.find((_, i) => i === mainTab)?.() ) ), ]), feedbackPanel = c => s => function_pipe( Math.trunc(getState("eventLog")(s).length / 100) + 1, logPageLength => [ h("div", { style: panelBoxStyle(644) }, [ h( "div", { style: { float: "right" } }, h( "a", { style: { color: "#f0f" }, href: "https://greasyfork.org/en/scripts/411442-flow-youtube-chat/feedback", target: "_blank", }, hyperapp_text(getText("giveFeedback")(s.lang)) ) ), h("div", {}, [ h("span", {}, hyperapp_text(getText("eventLog")(s.lang))), buttonNode("copy")(c)(s), tabContainer({ container: { height: "276px" }, label: { padding: "4px", width: "2em", textAlign: "center" }, labelFocus: { background: "#666" }, tab: { display: "flex", flexDirection: "column", padding: "6px", }, })((_, n) => settingUI_updateAt("logTab")(n)(c))( function_pipe( ReadonlyArray_makeBy(logPageLength, number_Show_show) ) )( function_pipe( ReadonlyArray_makeBy( logPageLength, i => () => function_pipe( getState("eventLog")(s).slice(100 * i, 100 * (i + 1)), es6_ReadonlyArray_mapWithIndex((j, x) => h("div", { style: { display: "flex" } }, [ h( "div", { style: { userSelect: "none", flex: "0 0 2em", }, }, hyperapp_text(100 * i + j) ), h( "div", { style: { background: j % 2 == 0 ? "#fff" : "#ddd", color: "#000", flex: "auto", wordBreak: "break-all", padding: "0 2px", }, }, hyperapp_text(x) ), ]) ) ) ) ) )(getState("logTab")(s)), ]), ]), ] ), setEditRegexs = editing => value => function_pipe( value, split(/\r\n|\n/), es6_ReadonlyArray_filter(Predicate_not(string_isEmpty)), Identity_bindTo("regexs"), Identity_let_("errors", ({ regexs }) => { return function_pipe( regexs, es6_ReadonlyArray_mapWithIndex((i, x) => { try { RegExp(x, "u") return Option_none } catch (e) { return Option_of(`${e} in regex number ${i}`) } }), Monoid_concatAll( ((S = { concat: (x, y) => `${x}\n${y}` }), { concat: function (x, y) { return Option_isNone(x) ? y : Option_isNone(y) ? x : Option_some(S.concat(x.value, y.value)) }, empty: Option_none, }) ) ) var S }), ctx => editing ? setText(value) : function_pipe( ctx.errors, es6_Option_map(x => mapSnd(() => Option_of([value, Option_of(x)])) ), getOrElse(constant(constant(Editable_of(ctx.regexs)))) ) ), setEditStrings = editing => value => function_pipe( value, split(/\r\n|\n/), es6_ReadonlyArray_filter(Predicate_not(string_isEmpty)), x => constant( editing ? [x, Option_of([value, Option_none])] : Editable_of(x) ) ), textAreaRow = (rows, action) => value => h("textarea", { rows, style: { resize: "horizontal", boxSizing: "border-box", width: "100%", borderColor: hasError(value) ? "#f55" : void 0, }, value: function_pipe( value, Editable_text, getOrElse( function_pipe(Editable_value(value), x => x.join("\n"), constant) ) ), ...action, }), textAreaNode = (label, rows, setter) => c => s => settingRow( getText(label)(s.lang), errorText(getText("invalidSetting")(s.lang))(s[label]), [textAreaRow(rows, editAction(label, setter)(c))(getState(label)(s))] ), filterPanelOld = c => s => [ h( "div", { style: panelBoxStyle(212) }, textAreaNode("bannedWords", 18, setEditStrings)(c)(s) ), h( "div", { style: panelBoxStyle(212) }, textAreaNode("bannedWordRegexs", 18, setEditRegexs)(c)(s) ), h( "div", { style: panelBoxStyle(212) }, textAreaNode("bannedUsers", 18, setEditStrings)(c)(s) ), ] var validate_color_lib = __webpack_require__(90), lib_default = __webpack_require__.n(validate_color_lib) const validColor = x => lib_default()(x.replace(/grey/gi, "gray")), setEditColor = editing => value => editing ? validColor(value) ? constant(fromValueText(value)(value)) : setText(value) : validColor(value) ? constant(Editable_of(value)) : mapSnd(constant(Option_of([value, Option_of("")]))), colorPicker = action => color => h("input", { style: { width: "36px", verticalAlign: "middle" }, type: "color", value: color, oninput: action.onchange, }), textInput = action => value => h("input", { style: { verticalAlign: "middle", width: "5.5em", borderColor: hasError(value) ? "#f55" : void 0, }, maxlength: 20, value: function_pipe( value, Editable_text, getOrElse(constant(Editable_value(value))) ), ...action, }), setEditInt = editing => value => state => function_pipe( value, Number.parseInt, editing ? x => Number.isNaN(x) || "." === value.at(-1) ? function_pipe(state, setText(value)) : fromValueText(x)(value) : x => Number.isNaN(x) ? function_pipe( state, mapSnd(constant(Option_of([value, Option_of("")]))) ) : Editable_of(x) ), intNode = (label, min, max, step) => c => s => settingRow( getText(label)(s.lang), errorText(getText("inputNonNumberic")(s.lang))(s[label]), [ rangeRow( min, max, step, editAction(label, setEditInt)(c) )(getState(label)(s)), ] ), fonts = currentFont => [ ["", "Default", "デフォルト"], ["arial", "Arial", "Arial"], ["arial black", "Arial Black", "Arial Black"], ["arial narrow", "Arial Narrow", "Arial Narrow"], ["Century", "Century", "Century"], ["Comic Sans MS", "Comic Sans MS", "Comic Sans MS"], ["Courier", "Courier", "Courier"], ["cursive", "cursive", "cursive"], ["fantasy", "fantasy", "fantasy"], ["Impact", "Impact", "Impact"], ["Meiryo", "Meiryo", "メイリオ"], ["Meiryo UI", "Meiryo UI", "メイリオ UI"], ["monospace", "monospace", "monospace"], ["Monotype Corsiva", "Monotype Corsiva", "Monotype Corsiva"], ["MS PGothic", "MS PGothic", "MS Pゴシック"], ["MS Gothic", "MS Gothic", "MS ゴシック"], ["MS Sans Serif", "MS Sans Serif", "MS Sans Serif"], ["MS Serif", "MS Serif", "MS Serif"], ["MS UI Gothic", "MS UI Gothic", "MS UI Gothic"], ["sans-serif", "Sans-serif", "Sans-serif"], ["serif", "Serif", "Serif"], ["Times New Roman", "Times New Roman", "Times New Roman"], ["Yu Gothic", "Yu Gothic", "遊ゴシック"], ["YuGothic", "YuGothic", "游ゴシック体"], [currentFont, "Custom", "カスタム"], ], setEditString = editing => function_flow(x => constant(editing ? fromValueText(x)(x) : Editable_of(x)) ), settingUI_textRowStyle = { width: "70%", boxSizing: "border-box" }, ui_option = (value, label, selected) => h("option", { value, selected }, hyperapp_text(label)), exampleTextStyle = s => ({ fontFamily: Editable_value(s.font), fontWeight: Editable_value(s.fontWeight).toString(), textShadow: textShadow(Editable_value(s.shadowColor))( Editable_value(s.shadowFontWeight) ), }), colorTextOutput = textStyle => color => h( "span", { style: { ...textStyle, color } }, hyperapp_text("Aa1あア亜") ), textColorNode = label => c => s => settingRow( getText(label)(s.lang), errorText(getText("invalidColor")(s.lang))(s[label]), function_pipe( { a: editAction(label, setEditColor)(c), v: Editable_value(s[label]), }, ({ a, v }) => [ colorPicker(a)(v), textInput(a)(s[label]), colorTextOutput(exampleTextStyle(s))(v), ] ) ), flowChatPanel = function_pipe( [ function_pipe( [ c => s => function_pipe(Editable_value(s.font), font => settingRow(getText("font")(s.lang), "", [ h( "select", { style: settingUI_textRowStyle, onchange: updateInput(setEditString(!1))("font")(c), }, function_pipe( fonts(font), findIndex(x => x[0] === font), getOrElse(() => 0), index => function_pipe( fonts(font), es6_ReadonlyArray_mapWithIndex((i, f) => ui_option( f[0], function_pipe( languages, findIndex(x => x === s.lang), es6_Option_map(x => f[x + 1]), getOrElse(() => "Error") ), i === index ) ) ) ) ), h("input", { style: settingUI_textRowStyle, maxlength: 20, value: font, ...editAction("font", setEditString), }), ]) ), textColorNode("color"), textColorNode("ownerColor"), textColorNode("moderatorColor"), textColorNode("memberColor"), ((label = "shadowColor"), c => s => settingRow( getText(label)(s.lang), errorText(getText("invalidColor")(s.lang))(s[label]), function_pipe(editAction(label, setEditColor)(c), x => [ colorPicker(x)(Editable_value(s[label])), textInput(x)(s[label]), ]) )), ], Reader_sequenceArray, es6_Reader_map(Reader_sequenceArray), es6_Reader_map( es6_Reader_map(x => h("div", { style: panelBoxStyle(212) }, x)) ) ), function_pipe( [ numberNode("chatOpacity", 0, 1, 0.05), numberNode("fontSize", 0.3, 2, 0.05), numberNode("fontWeight", 10, 1e3, 10), numberNode("shadowFontWeight", 0, 3, 0.1), numberNode("flowSpeed", 1, 50, 1), intNode("maxChatCount", 5, 200, 5), intNode("maxChatLength", 5, 200, 5), intNode("laneCount", 1, 25, 1), ], Reader_sequenceArray, es6_Reader_map(Reader_sequenceArray), es6_Reader_map( es6_Reader_map(x => h("div", { style: panelBoxStyle(212) }, x)) ) ), function_pipe( [ numberNode("flowY1", 0, 0.95, 0.01), numberNode("flowY2", 0.05, 1, 0.01), numberNode("flowX1", 0, 0.95, 0.01), numberNode("flowX2", 0.05, 1, 0.01), numberNode("minSpacing", 0, 2.5, 0.1), c => s => h("div", {}, [ checkboxNode("useStepTiming")(c)(s), h( "div", { style: { opacity: getState("useStepTiming")(s) ? void 0 : "0.5", }, }, intNode("timingStepCount", 1, 400, 1)(c)(s) ), ]), checkboxNode("createChats"), checkboxNode("displayModName"), checkboxNode("displaySuperChatAuthor"), checkboxNode("textOnly"), () => s => hyperapp_text(getText("flowNewChatIf")(s.lang)), checkboxNode("noOverlap"), buttonNode("clearFlowChats"), ], Reader_sequenceArray, es6_Reader_map(Reader_sequenceArray), es6_Reader_map( es6_Reader_map(x => h("div", { style: panelBoxStyle(212) }, x)) ) ), ], Reader_sequenceArray, es6_Reader_map(Reader_sequenceArray) ) var label const settingUI_flowChatPanel = flowChatPanel, setString = function_flow(function_identity, constant), simpleWrap = (comp, init) => function_pipe( () => document.createElement(comp.tag), chain(node => () => ({ node, dispatch: app({ init, view: comp.view, node }), })) ), toggleSettingsPanelComponent = function_flow( syncState => (x, e) => function_pipe({ ...x, showPanel: !x.showPanel }, newState => [ newState, x.showPanel ? () => tapIs(HTMLElement)(e.currentTarget).blur() : () => {}, syncState(oldState => ({ ...oldState, ...newState })), ]), toggle => state => h( "button", { class: "fyc_button", style: { background: "rgba(0,0,0,0)", marginLeft: "10px", whiteSpace: "nowrap", }, onclick: toggle, }, [ h( "svg", { preserveAspectRatio: "xMidYMid meet", viewBox: "0 0 640 640", width: "15", height: "15", style: { position: "relative", top: "1px" }, }, [ h( "defs", {}, h("path", { id: "d1TbzTC1zI", d: "M135 58c25 14 67 30 82 35-7 49 16 109-15 149-50 71-19 184 64 213 74 31 165-18 183-95-3-38 23-62 58-36l120 55c-39 10-106 35-72 85 40 38 1 71-29 98-29 53-70-17-109-5-46 22-25 109-96 85h-55c-24-31-21-103-80-84-32 32-70 31-93-9l-35-36c4-40 57-96-6-120-45 5-58-32-52-68 2-19-4-41 3-59 35-15 100-22 77-79-48-43 1-84 35-115 5-6 12-12 20-14zM577 2c52 3 72 62 62 106-5 51 19 117-27 155-18 24 8 49 11 74-39-8-98-46-146-60-55-1-111 2-167-2-52-15-57-76-52-121S242 52 282 18c38-30 88-11 132-16h163z", }) ), h("use", { href: "#d1TbzTC1zI", opacity: "1", fill: "var(--iron-icon-fill-color, currentcolor)", "fill-opacity": "1", }), ] ), h( "span", { style: { position: "relative", top: "-2px", marginLeft: "8px,", }, }, hyperapp_text(getText("setting")(state.lang)) ), ] ), button => makeComponent( tag => s => h(tag, { style: { display: "flex" } }, button(s)) )("span") ), videoToggleStream = video => function_pipe( [["playing"], ["waiting", "pause"]], es6_ReadonlyArray_mapWithIndex((i, x) => [x, 0 === i]), es6_ReadonlyArray_chain(([xs, b]) => function_pipe( xs, es6_ReadonlyArray_map(x => [x, b]) ) ), es6_ReadonlyArray_map(([x, b]) => function_pipe( (0, external_rxjs_namespaceObject.fromEvent)(video, x), (0, external_rxjs_namespaceObject.map)(() => b) ) ), x => (0, external_rxjs_namespaceObject.merge)(...x) ), initialize = () => function_pipe( src_defaultGMConfig, x => ({ gmConfig: x, configKeys: Object.keys(x) }), Task_of, Task_bind("config", ctx => { return ( (config = ctx.gmConfig), function_pipe( Object.entries(config), es6_ReadonlyArray_map(([x, c]) => async () => [ x, await c.getValue(), ]), Task_sequenceArray, es6_Task_map(Object.fromEntries) ) ) var config }), Task_let_("getConfig", ctx => (c => function_pipe( c, mapObject(([x]) => [x, () => c[x]]) ))(ctx.config) ), Task_let_("mainState", x => ({ chatPlaying: !0, playerRect: new DOMRectReadOnly(0, 0, 600, 400), config: x.config, })), Task_let_("configSubject", ctx => function_pipe( ctx.configKeys, es6_ReadonlyArray_map(x => [ x, new external_rxjs_namespaceObject.Subject(), ]), Object.fromEntries ) ), Task_let_("setterFromKeysMap", ctx => { return ( (keys = ctx.configKeys), f => function_pipe( keys, es6_ReadonlyArray_map(x => [x, f(x)]), Object.fromEntries ) ) var keys }), Task_let_("setConfigPlain", ctx => ctx.setterFromKeysMap(key => val => async () => { Object.assign(ctx.mainState.config, { [key]: val }) ctx.configSubject[key].next(val) }) ), function_flow( Task_let_( "changedConfigMap", ctx => key => val => function_pipe( async () => ctx.config[key], es6_Task_map( fromPredicate(x => !fast_deep_equal_default()(x, val)) ), TaskOption_chainTaskK(() => ctx.setConfigPlain[key](val)) ) ), Task_let_("setChangedConfig", ctx => ctx.setterFromKeysMap(ctx.changedConfigMap) ), Task_apS( "channel", Task_of( new broadcast_channel_BroadcastChannel("fyc-0615654655528523") ) ), Task_let_("setConfig", ctx => ctx.setterFromKeysMap( key => val => function_pipe( ctx.changedConfigMap(key)(val), TaskOption_chainTaskK(() => async () => { ctx.channel.postMessage([key, val]) const item = ctx.gmConfig[key] GM.setValue(item.gmKey, item.toGm(val)) }) ) ) ), Task_apS( "reinitSubject", Task_fromIO(() => new external_rxjs_namespaceObject.Subject()) ), Task_let_("reinitialize", ctx => () => { requestAnimationFrame(() => lib(ctx.reinitSubject)()) }) ), function_flow( Task_chainFirst(ctx => ctx.setConfigPlain.filterExp(defaultFilter(ctx.config)) ), Task_let_("toggleChatButtonInit", ctx => ({ lang: ctx.config.lang, displayChats: ctx.config.displayChats, })), Task_let_("wrappedToggleChat", ctx => { return simpleWrap( ((setConfig = ctx.setConfig), function_pipe( "button", makeComponent( tag => state => function_pipe( getText(state.displayChats ? "hideChat" : "showChat")( state.lang ), label => h( tag, { class: "ytp-button", style: { background: "none", border: "none", cursor: "pointer", float: "left", fontSize: "1em", height: "4em", outline: "none", overflow: "visible", padding: "0 0 0em", position: "relative", width: "3em", }, type: "button", "aria-label": label, title: label, onclick: s => function_pipe(!s.displayChats, displayChats => [ { ...s, displayChats }, setConfig.displayChats(displayChats), ]), }, [ h( "svg", { style: { width: "100%" }, viewBox: "0 0 36 36", }, [ h("path", { class: "chat-button-path", d: "m11 12h17q1 0 1 1v9q0 1-1 1h-1v2l-4-2h-12q-1 0-1-1v-9q0-1 1-1z", fill: "#fff", "fill-opacity": state.displayChats ? "1" : "0", stroke: "#fff", "stroke-width": "2", }), ] ), ] ) ) ) )), ctx.toggleChatButtonInit )() var setConfig }), Task_apS("flowChats", Task_of([])), Task_apS("settingUpdateApps", Task_of([])), Task_let_( "updateSettingState", ctx => dispatchable => function_pipe( ctx.settingUpdateApps, es6_ReadonlyArray_map(x => () => x(dispatchable)), sequenceArray ) ), Task_let_("wrappedSettings", ctx => simpleWrap( function_pipe( (c => function_flow(state => state.showPanel ? h( "div", { class: "fyc_panel", style: { backgroundColor: "rgba(30,30,30,0.9)", position: "absolute", zIndex: "10000", color: "#fff", fontSize: "14px", overflow: "auto", left: `${state.panelRect.x}px`, top: `${state.panelRect.y}px`, width: `${state.panelRect.width}px`, height: `${state.panelRect.height}px`, border: "solid 1px #666", fontFamily: "MS PGothic", lineHeight: "1.2", colorScheme: "dark", }, }, [ h( "div", { style: { position: "absolute", inset: "3px 3px auto auto", }, }, [ hyperapp_text("🌐"), h( "select", { onchange: updateInput(setString)("lang")(c), }, function_pipe( languages, es6_ReadonlyArray_mapWithIndex( (i, lang) => ui_option( lang, languageLabels[i], lang === state.lang ) ) ) ), ] ), tabContainer({ container: { height: "364px" }, label: { padding: "6px" }, labelFocus: { background: "#666" }, tab: { display: "flex", padding: "6px" }, })((s, n) => settingUI_updateAt("mainTab")(n)(c)(s) )( function_pipe( [ "flowChat", "chatFilter", "chatField", "feedback", ], es6_ReadonlyArray_map(getText), es6_ReadonlyArray_map(apply(state.lang)) ) )( function_pipe( [ settingUI_flowChatPanel, filterPanelOld, settingUI_chatFieldPanel, feedbackPanel, ], es6_ReadonlyArray_map(apply(c)), es6_ReadonlyArray_map(constant), es6_ReadonlyArray_map(src_flip), es6_ReadonlyArray_map(apply(state)) ) )(getState("mainTab")(state)), ] ) : h("div", {}) ))({ setConfig: ctx.setConfig, act: { clearFlowChats: Task_fromIO( removeOldChats(ctx.flowChats)(0) ), }, }), panel => makeComponent( tag => s => h(tag, { style: { display: "contents" } }, panel(s)) )("span") ), settingStateInit(ctx.config) )() ), Task_let_("wrappedToggleSettings", ctx => simpleWrap( toggleSettingsPanelComponent(ctx.updateSettingState), settingStateInit(ctx.config) )() ) ), function_flow( Task_chainFirstIOK( ctx => () => ctx.settingUpdateApps.push( ctx.wrappedSettings.dispatch, ctx.wrappedToggleSettings.dispatch ) ), Task_apS( "settingsRectSubject", Task_of( new external_rxjs_namespaceObject.BehaviorSubject( new DOMRectReadOnly(0, 0, 660, 395) ) ) ), Task_let_( "settingLog", ctx => x => ctx.updateSettingState(s => ({ ...s, eventLog: appendLog(s.eventLog)(x), })) ), Task_let_("mixLog", ctx => function_pipe( [ctx.settingLog, consoleLog], Reader_sequenceArray, es6_Reader_map(sequenceArray) ) ), Task_chainFirstIOK(ctx => function_pipe( [ ["Version", "1.15.18"], ["User Agent", window.navigator.userAgent], ["GMConfig", JSON.stringify(ctx.gmConfig)], ], es6_ReadonlyArray_map(ctx.settingLog), sequenceArray ) ), Task_let_("co", ctx => function_pipe( ctx.configSubject, mapObject(([k, value]) => [ k, function_pipe( value, (0, external_rxjs_namespaceObject.tap)(v => function_pipe( v, x => s => ({ ...s, [k]: x }), of, IO_chainFirst(() => { return ctx.updateSettingState( ((key = k), value => state => ({ ...state, [key]: isEditable(key)(value) ? setValue(value)(state[key]) : "filterExp" === key ? function_pipe( EditableExpression_fromJsepExp(value), getOrElseW(() => ({ type: "Compound", body: [], })) ) : value, }))(v) ) var key }), chain(x => k in ctx.toggleChatButtonInit ? () => ctx.wrappedToggleChat.dispatch(x) : () => {} ), x => () => requestAnimationFrame(x) )() ) ), ]) ) ), Task_apS("livePage", Task_of(livePageYt)), Task_let_("live", ctx => makePageState(ctx.livePage)), Task_apS("chatScreen", Task_fromIO(createChatScreen)) ), Task_bind("all$", ctx => { return function_pipe( { eq: ((E = eqStrict), { equals: function (x, y) { return ( x === y || (Option_isNone(x) ? Option_isNone(y) : !Option_isNone(y) && E.equals(x.value, y.value)) ) }, }).equals, initDelay: 100, urlDelay: 1700, changeDetectInterval: 700, bodyResizeDetectInterval: 300, errorRetryInterval: 5e3, liveElementKeys: Object.keys(ctx.livePage), tapUpdateSettingsRect: ob => (0, external_rxjs_namespaceObject.switchMap)(value => { return function_pipe( ctx.settingsRectSubject, (0, external_rxjs_namespaceObject.first)(), (0, external_rxjs_namespaceObject.map)( ((toggleSettingsElement = ctx.wrappedToggleSettings.node), nextSettingsRect => last => function_pipe( () => toggleSettingsElement, IO_map(fromPredicate(x => null !== x.offsetParent)), IOOption_map(x => x.getBoundingClientRect()), IOOption_map( x => new DOMRectReadOnly( Math.max(0, x.right + window.scrollX - 660), Math.max(0, x.y + window.scrollY - 395), 660, Math.min(x.y + window.scrollY, 395) ) ), IOOption_alt(() => IOOption_of( new DOMRectReadOnly(-660, -395, 660, 395) ) ), IOOption_filter( x => x.x !== last.x || x.y !== last.y || x.width !== last.width || x.height !== last.height ), IOOption_chainFirstIOK(nextSettingsRect), IO_apSecond(() => {}) ))(rect => () => ctx.settingsRectSubject.next(rect)) ), (0, external_rxjs_namespaceObject.tap)(x => x()), (0, external_rxjs_namespaceObject.map)(() => value) ) var toggleSettingsElement })(ob), config$: function_pipe(ctx.co, co => (0, external_rxjs_namespaceObject.defer)(() => { return (0, external_rxjs_namespaceObject.merge)( (0, external_rxjs_namespaceObject.merge)( co.bannedWordRegexs, co.bannedWords, co.bannedUsers ), function_pipe( co.fieldScale, (0, external_rxjs_namespaceObject.startWith)( ctx.config.fieldScale ), (0, external_rxjs_namespaceObject.map)( ((live = ctx.live), scale => function_pipe( live.chatField.ele, IOOption_fromOption, IOOption_chainIOK(field => function_pipe( [ function_pipe( fromNullable(field.parentElement), es6_Option_map( x => () => Object.assign(x.style, { transformOrigin: (scale >= 1 ? "top" : "bottom") + " left", transform: `scale(${scale})`, width: 100 / scale + "%", height: 100 / scale + "%", }) ) ), function_pipe( live.chatScroller.ele, es6_Option_map(scroller => () => { scroller.scrollTop = scroller.scrollHeight }) ), ], ReadonlyArray_compact, sequenceArray ) ) )) ), (0, external_rxjs_namespaceObject.tap)(x => x()) ), function_pipe( (0, external_rxjs_namespaceObject.merge)( function_pipe( (0, external_rxjs_namespaceObject.merge)( co.font, co.fontSize, co.fontWeight, co.laneCount, co.minSpacing, co.flowY1, co.flowY2, function_pipe( co.flowX1, (0, external_rxjs_namespaceObject.startWith)( ctx.config.flowX1 ), (0, external_rxjs_namespaceObject.tap)(x => Object.assign(ctx.chatScreen.style, { left: 100 * x + "%", width: 100 * (ctx.config.flowX2 - x) + "%", }) ) ), function_pipe( co.flowX2, (0, external_rxjs_namespaceObject.tap)(x => Object.assign(ctx.chatScreen.style, { left: 100 * ctx.config.flowX1 + "%", width: 100 * (x - ctx.config.flowX1) + "%", }) ) ), co.textOnly ), (0, external_rxjs_namespaceObject.map)(() => ({ render: !0, setAnimation: !0, })) ), function_pipe( (0, external_rxjs_namespaceObject.merge)( co.color, co.ownerColor, co.moderatorColor, co.memberColor, co.shadowColor, co.chatOpacity, co.shadowFontWeight, co.displayChats ), (0, external_rxjs_namespaceObject.map)(() => ({ render: !0, })) ), function_pipe( co.flowSpeed, (0, external_rxjs_namespaceObject.map)(() => ({ setPlayState: !0, })) ), function_pipe( (0, external_rxjs_namespaceObject.merge)( function_pipe( co.maxChatCount, (0, external_rxjs_namespaceObject.map)( removeOldChats(ctx.flowChats) ), (0, external_rxjs_namespaceObject.tap)(x => x()) ), co.noOverlap, co.timingFunction ), (0, external_rxjs_namespaceObject.map)(() => ({ setAnimation: !0, })) ) ), (0, external_rxjs_namespaceObject.throttleTime)( 180, void 0, { leading: !0, trailing: !0 } ), (0, external_rxjs_namespaceObject.tap)(config => function_pipe( ctx.flowChats, es6_ReadonlyArray_filter(x => !x.animationEnded), es6_ReadonlyArray_map(chat => function_pipe( { render: !1, setAnimation: !1, setPlayState: !1, ...config, }, x => function_pipe( [ function_pipe( renderChat(chat), fromPredicate(() => x.render) ), function_pipe( setChatAnimation(chat, ctx.flowChats), fromPredicate(() => x.setAnimation), alt(() => function_pipe( setChatPlayState(chat), fromPredicate(() => x.setPlayState) ) ) ), ], ReadonlyArray_compact, es6_ReadonlyArray_map(apply(ctx.mainState)), sequenceArray ) ) ), sequenceArray )() ) ), function_pipe( co.lang, (0, external_rxjs_namespaceObject.tap)(lang => ctx.updateSettingState(x => ({ ...x, lang }))() ) ), co.maxChatLength, co.simplifyChatField, co.createBanButton, co.createChats, co.displayModName, co.displaySuperChatAuthor, co.fieldScale, function_pipe( (0, external_rxjs_namespaceObject.merge)( co.bannedWords, co.bannedWordRegexs, co.bannedUsers ), (0, external_rxjs_namespaceObject.tap)(() => ctx.setConfig.filterExp(defaultFilter(ctx.config))() ) ) ) var live }) ), }, of, IO_apS("cos", mainCss), IO_apS("documentMutationPair", observePair(MutationObserver)), IO_apS("chatMutationPair", observePair(MutationObserver)), IO_apS("playerResizePair", observePair(ResizeObserver)), IO_apS("bodyResizePair", observePair(ResizeObserver)), IO_map(c => function_pipe( ctx.reinitSubject, (0, external_rxjs_namespaceObject.observeOn)( external_rxjs_namespaceObject.asyncScheduler ), (0, external_rxjs_namespaceObject.delay)(c.initDelay), (0, external_rxjs_namespaceObject.tap)(ctx.mixLog(["Init"])), (0, external_rxjs_namespaceObject.switchMap)(() => function_pipe( (0, external_rxjs_namespaceObject.interval)( c.changeDetectInterval ), c.tapUpdateSettingsRect, (0, external_rxjs_namespaceObject.filter)(() => function_pipe( c.liveElementKeys, es6_ReadonlyArray_map(key => function_pipe( ctx.live[key].read(), fromPredicate( newEle => !c.eq(ctx.live[key].ele, newEle) ), es6_Option_map( function_flow( of, IO_chainFirst(x => () => { ctx.live[key].ele = x }), IO_map(Option_isSome), IO_map(x => `${key} ${x ? "found" : "lost"}`), chain(x => ctx.mixLog([x])) ) ) ) ), ReadonlyArray_compact, sequenceArray, IO_map(ReadonlyArray_isNonEmpty) )() ), (0, external_rxjs_namespaceObject.startWith)(0) ) ), (0, external_rxjs_namespaceObject.tap)( ctx.mixLog(["Loading..."]) ), (0, external_rxjs_namespaceObject.tap)(() => { removeOldChats(ctx.flowChats)(0)() c.documentMutationPair.observer.disconnect() c.documentMutationPair.observer.observe(document, { childList: !0, subtree: !0, }) c.chatMutationPair.observer.disconnect() c.playerResizePair.observer.disconnect() c.bodyResizePair.observer.disconnect() document.head.append(c.cos) function_pipe( [ function_pipe( ctx.live.chatField.ele, es6_Option_map( function_flow( of, IO_chainFirst(setChatAppCss), chain( x => () => c.chatMutationPair.observer.observe(x, { childList: !0, }) ) ) ) ), function_pipe( ctx.live.chatTicker.ele, es6_Option_map( x => () => c.chatMutationPair.observer.observe(x, { childList: !0, }) ) ), function_pipe( ctx.live.player.ele, es6_Option_map( function_flow( of, IO_chainFirst( x => () => c.playerResizePair.observer.observe(x) ), chain(x => () => x.prepend(ctx.chatScreen)) ) ) ), function_pipe( ctx.live.toggleChatBtnParent.ele, es6_Option_map( x => () => x.prepend(ctx.wrappedToggleChat.node) ) ), function_pipe( ctx.live.settingsToggleNextElement.ele, es6_Option_map( x => () => x.before(ctx.wrappedToggleSettings.node) ) ), function_pipe( ctx.live.settingsContainer.ele, es6_Option_map( function_flow( of, IO_chainFirst( x => () => x.append(ctx.wrappedSettings.node) ) ) ) ), function_pipe( document.body, fromNullable, es6_Option_map( x => () => c.bodyResizePair.observer.observe(x) ) ), ], ReadonlyArray_compact, ReadonlyArray_append( function_pipe( ctx.live.video.ele, filter(x => !x.paused), alt(() => ctx.live.offlineSlate.ele), Option_isSome, x => () => { Object.assign(ctx.mainState, { chatPlaying: x }) } ) ), sequenceArray )() }), (0, external_rxjs_namespaceObject.switchMap)(() => (0, external_rxjs_namespaceObject.merge)( function_pipe( (0, external_rxjs_namespaceObject.fromEvent)( ctx.channel, "message" ), (0, external_rxjs_namespaceObject.tap)(([key, val]) => function_pipe( src_listeningBroadcastConfigKeys.includes(key), x => (x ? ctx.setChangedConfig[key](val) : () => {}) )() ) ), ...function_pipe( ctx.configKeys, es6_ReadonlyArray_map(key => function_pipe( ctx.co[key], (0, external_rxjs_namespaceObject.startWith)( ctx.config[key] ), (0, external_rxjs_namespaceObject.bufferCount)( 2, 1 ), (0, external_rxjs_namespaceObject.map)(([x, y]) => (0, external_DeepDiff_namespaceObject.diff)(x, y) ), (0, external_rxjs_namespaceObject.tap)(x => ctx.settingLog([ `Config ${key}`, JSON.stringify(x, void 0, 2), ])() ) ) ) ), c.config$, function_pipe( ctx.live.video.ele, match( () => external_rxjs_namespaceObject.EMPTY, function_flow( videoToggleStream, (0, external_rxjs_namespaceObject.map)( playing => playing || Option_isSome(ctx.live.offlineSlate.ele) ), (0, external_rxjs_namespaceObject.tap)( chatPlaying => function_pipe(() => { ctx.mainState.chatPlaying = chatPlaying }, IO_apSecond(function_pipe(ctx.flowChats, es6_ReadonlyArray_map(setChatPlayState), es6_ReadonlyArray_map(apply(ctx.mainState)), sequenceArray)))() ) ) ) ), function_pipe( c.chatMutationPair.subject, (0, external_rxjs_namespaceObject.map)( onChatFieldMutate( ctx.chatScreen, ctx.flowChats, ctx.mainState, ctx.getConfig, ctx.setConfig ) ), (0, external_rxjs_namespaceObject.map)( ioFromLogState(ctx.settingLog) ), (0, external_rxjs_namespaceObject.tap)(x => x()) ), function_pipe( c.documentMutationPair.subject, (0, external_rxjs_namespaceObject.map)( () => window.location.href ), (0, external_rxjs_namespaceObject.distinctUntilChanged)(), (0, external_rxjs_namespaceObject.skip)(1), c.tapUpdateSettingsRect, (0, external_rxjs_namespaceObject.tap)(x => sequenceArray([ ctx.mixLog(["URL Changed", x]), removeOldChats(ctx.flowChats)(0), ctx.mixLog([`Wait for ${c.urlDelay}ms...`]), ])() ), (0, external_rxjs_namespaceObject.delay)(c.urlDelay), (0, external_rxjs_namespaceObject.tap)(ctx.reinitialize) ), function_pipe( c.playerResizePair.subject, (0, external_rxjs_namespaceObject.throttleTime)( 500, void 0, { leading: !0, trailing: !0 } ), (0, external_rxjs_namespaceObject.startWith)([]), (0, external_rxjs_namespaceObject.map)( () => ctx.live.player.ele ), (0, external_rxjs_namespaceObject.map)( es6_Option_map(x => x.getBoundingClientRect()) ), (0, external_rxjs_namespaceObject.tap)(x => { return ioFromLogState(ctx.settingLog)( ((rect = x), (flowChats = ctx.flowChats), (mainState = ctx.mainState), function_pipe( rect, match( () => State_of(() => {}), function_flow( x => () => Object.assign(mainState, { playerRect: x }), IO_map(() => flowChats), IO_map( es6_ReadonlyArray_chain(x => [ renderChat(x)(mainState), setChatAnimation(x, flowChats)(mainState), ]) ), chain(sequenceArray), io => s => [io, [...s, ["Resize detected"]]] ) ) )) )() var rect, flowChats, mainState }) ), function_pipe( c.bodyResizePair.subject, (0, external_rxjs_namespaceObject.throttleTime)( c.bodyResizeDetectInterval, void 0, { leading: !0, trailing: !0 } ), (0, external_rxjs_namespaceObject.startWith)([]), c.tapUpdateSettingsRect ), function_pipe( ctx.settingsRectSubject, (0, external_rxjs_namespaceObject.tap)(panelRect => ctx.updateSettingState(s => ({ ...s, panelRect }))() ) ) ) ), (0, external_rxjs_namespaceObject.retry)({ delay: e => function_pipe( e, external_rxjs_namespaceObject.of, (0, external_rxjs_namespaceObject.tap)( ctx.mixLog(["Errored", e]) ), (0, external_rxjs_namespaceObject.delay)( c.errorRetryInterval ), (0, external_rxjs_namespaceObject.tap)(ctx.reinitialize) ), }) ) ), Task_fromIO ) var E }), Task_chainFirstIOK( ctx => () => ctx.all$.subscribe({ error: x => ctx.mixLog(["Stream error", x])(), complete: ctx.mixLog(["Stream complete"]), }) ), Task_chainFirstIOK(ctx => ctx.reinitialize) )() ;(async () => { external_log_namespaceObject.setLevel("info") try { await initialize() } catch (error) { external_log_namespaceObject.info("【FYC】 Error", error) } })() })() })()