Flow Youtube Chat

Youtubeのチャットをニコニコ風に画面上へ流す(再アップ) Make youtube chats move in danmaku-style.

Ajankohdalta 1.5.2022. Katso uusin versio.

// ==UserScript==
// @name        Flow Youtube Chat
// @version     1.15.9
// @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/[email protected]/dist/sweetalert2.all.min.js#sha384-EoPspU1QiQ0II6WaHKy5pERCBPBD1VqZByJ29O7fDUJxGXwWLyEREDpvym8c4v2S
// @require     https://unpkg.com/[email protected]/dist/loglevel.min.js#sha384-7gGuWfek8Ql6j/uNDFrS0BCe4x2ZihD4B68w9Eu580OVHJBV+bl3rZmEWC7q5/Gj
// @require     https://unpkg.com/[email protected]/dist/bundles/rxjs.umd.min.js#sha384-B2HMABdZA26zJ9QwbG/c5zrcdr6+Zs8J4MgKs7udycjXgvRDA5nZKLzJ1vXWzJyH
// @require     https://unpkg.com/[email protected]/mithril.min.js#sha384-vo9crXih40MlEv6JWHqS7SsPiFp+76csaWQFOF2UU0/xI58Jm/ZvK/1UtpaicJT9
// @require     https://cdn.jsdelivr.net/npm/[email protected]/src/check-types.min.js#sha384-KGnImnhVjA5llfqKEbjBiY+1Mp6oa+NvW/TEY1XTPAKWNgrAwa3Qvn//MXL07wBM
// @require     https://cdn.jsdelivr.net/npm/[email protected]/index.min.js#sha384-Q/uiWfFlwn9XjOpL49VpFKn01EkScmaC3hh1prAn7S++WoZgXRrrjQvZ7cI7C7Zn
// @require     https://cdn.jsdelivr.net/npm/[email protected]/dist/astring.min.js#sha384-mGnfE+xZkK7mo04MqU0t7DI1ZTFZSKwfPNjrLFeibz94N4lJgdHXh5+kI6rf5x10
// @require     https://cdn.jsdelivr.net/npm/[email protected]/build/jsep.min.js#sha384-89PRdfFVlT2bC9VxvLdvlByyVGml9l14DjpPqZYVI9umfvV24KPZ5dY6qBOeKf2z
// @require     https://cdn.jsdelivr.net/npm/[email protected]/dist/hash-it.min.js#sha384-biRMep0zr/5fw/hIdnBIb56UHRgiIyhAagZrngd9dSxxQ9aDFMP0hbYR8PEj5lVu
// @require     https://cdn.jsdelivr.net/npm/[email protected]/dist/micro-memoize.min.js#sha384-aGxbSIH2oMTKxZ93i+/iQKx5xefR8mHJW3mkbRaiSZizVoCvKS6wzndlLeQzMv9B
// ==/UserScript==

/* jshint esversion: 6 */

;(() => {
	var __webpack_modules__ = { 633: () => {} },
		__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)
		}
		function sleep(time) {
			time || (time = 0)
			return new Promise(function (res) {
				return setTimeout(res, 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.resolve()
				} 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.set = new Set()
				this.timeMap = new Map()
			}
			ObliviousSet.prototype.has = function (value) {
				return this.set.has(value)
			}
			ObliviousSet.prototype.add = function (value) {
				var _this = this
				this.timeMap.set(value, now())
				this.set.add(value)
				setTimeout(function () {
					!(function (obliviousSet) {
						for (
							var olderThen = now() - obliviousSet.ttl,
								iterator = obliviousSet.set[Symbol.iterator]();
							;

						) {
							var value = iterator.next().value
							if (!value) return
							if (!(obliviousSet.timeMap.get(value) < olderThen)) return
							obliviousSet.timeMap.delete(value)
							obliviousSet.set.delete(value)
						}
					})(_this)
				}, 0)
			}
			ObliviousSet.prototype.clear = function () {
				this.set.clear()
				this.timeMap.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)
			void 0 === options.node.useFastPath && (options.node.useFastPath = !0)
			return options
		}
		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 _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.resolve()
				: state.messagesCallback
				? ((db = state.db),
				  (lastCursorId = state.lastCursorId),
				  (objectStore = db.transaction("messages").objectStore("messages")),
				  (ret = []),
				  new Promise(function (res) {
						;(function () {
							try {
								var keyRangeValue = IDBKeyRange.bound(lastCursorId + 1, 1 / 0)
								return objectStore.openCursor(keyRangeValue)
							} catch (e) {
								return objectStore.openCursor()
							}
						})().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 res(ret)
						}
				  })).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.resolve()
				  })
				: Promise.resolve()
			var db, lastCursorId, objectStore, ret
		}
		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, 1)
					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.resolve(),
						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,
								},
								transaction = db.transaction(["messages"], "readwrite")
							return new Promise(function (res, rej) {
								transaction.oncomplete = function () {
									return res()
								}
								transaction.onerror = function (ev) {
									return rej(ev)
								}
								transaction.objectStore("messages").add(writeObject)
							})
						})(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,
									objectStore = db
										.transaction("messages")
										.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)) {
												res(ret)
												return
											}
											ret.push(msgObk)
											cursor.continue()
										} else res(ret)
									}
								})
							})(db, ttl).then(function (tooOld) {
								return Promise.all(
									tooOld.map(function (msgObj) {
										return (function (db, id) {
											var request = db
												.transaction(["messages"], "readwrite")
												.objectStore("messages")
												.delete(id)
											return new Promise(function (res) {
												request.onsuccess = function () {
													return res()
												}
											})
										})(db, msgObj.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]
		if (isNode) {
			var NodeMethod = __webpack_require__(633)
			"function" == typeof NodeMethod.canBeUsed && METHODS.push(NodeMethod)
		}
		var broadcast_channel_BroadcastChannel = function (name, options) {
			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 methode found:" +
						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"
					)
				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) {
					this.closed = !0
					var awaitPrepare = this._prepP ? this._prepP : Promise.resolve()
					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.resolve()
			).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 (obj) {
								msgObj.time >= obj.time && obj.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)
		}
		const external_DeepDiff_namespaceObject = DeepDiff
		function function_identity(a) {
			return a
		}
		function constant(a) {
			return function () {
				return a
			}
		}
		var constNull = constant(null),
			constUndefined = constant(void 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 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 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
					})
				}
			}
		}
		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_apSecond = apSecond(Apply),
			Chain = { URI: "IO", map: _map, ap: _ap, chain: _chain },
			Monad = { URI: "IO", map: _map, ap: _ap, of, chain: _chain },
			IO_chainFirst = 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))
			},
			_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 },
			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: function (fab, fa) {
					return function_pipe(fab, es6_Option_ap(fa))
				},
			},
			alt = function (that) {
				return function (fa) {
					return Option_isNone(fa) ? that() : fa
				}
			},
			Option_compact = (function (f) {
				return function (ma) {
					return Option_isNone(ma) ? Option_none : f(ma.value)
				}
			})(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)
		function Filterable_filter(F, G) {
			return function (predicate) {
				return function (fga) {
					return F.map(fga, function (ga) {
						return G.filter(ga, predicate)
					})
				}
			}
		}
		function OptionT_some(F) {
			return function_flow(Option_some, F.of)
		}
		function fromF(F) {
			return function (ma) {
				return F.map(ma, Option_some)
			}
		}
		function 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_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)
					)
				}
			}
		}
		var IOOption_some = OptionT_some(Pointed),
			fromOption = of,
			IOOption_fromIO = fromF(Functor),
			IOOption_chainOptionK =
				(IO_map(toUndefined), IO_map(toNullable), chainOptionK(Monad)),
			IOOption_map = OptionT_map(Functor),
			IOOption_ap = OptionT_ap(Apply),
			IOOption_chain = OptionT_chain(Monad),
			IOOption_filter = Filterable_filter(Functor, Filterable),
			IOOption_chainFirst = chainFirst({
				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))
				},
			}),
			es6_Reader_map = function (f) {
				return function (fa) {
					return function (r) {
						return f(fa(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) {
				for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
					to[j] = from[i]
				return to
			},
			ReadonlyNonEmptyArray_empty = emptyReadonlyArray,
			ReadonlyNonEmptyArray_isNonEmpty = isNonEmpty,
			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),
						[end]
					)
				}
			},
			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
			},
			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()
			},
			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,
			ReadonlyArray_bindTo = bindTo({
				URI: "ReadonlyArray",
				map: function (fa, f) {
					return function_pipe(fa, es6_ReadonlyArray_map(f))
				},
			})
		function FromIO_chainFirstIOK(F, M) {
			var chainFirstM = 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))
			},
			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: function (ma, f) {
					return function_pipe(ma, es6_Task_chain(f))
				},
			},
			Task_chainFirstIOK = FromIO_chainFirstIOK(
				{ URI: "Task", fromIO: Task_fromIO },
				Task_Chain
			),
			Task_bindTo = bindTo(Task_Functor),
			Task_bind = bind(Task_Chain),
			Task_apS = apS(ApplyPar)
		const external_rxjs_namespaceObject = rxjs,
			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 = () => {
				const element = document.createElement("div")
				Object.assign(element.style, {
					pointerEvents: "none",
					zIndex: "30",
					position: "absolute",
					overflow: "hidden",
					height: "100%",
					width: "100%",
				})
				return element
			}
		var 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}`,
			stringsArgs = [
				[],
				function_flow(
					split(/\r\n|\n/),
					es6_ReadonlyArray_filter(Predicate_not(string_isEmpty))
				),
				x => x.join("\n"),
			],
			sc = (k, d) =>
				(async (key, defaultVal) => ({
					gmKey: key,
					val: (await GM.getValue(key)) ?? defaultVal,
					defaultVal,
					toGm: function_identity,
				}))(fycKey(k), d),
			ic = (k, d, i, g) =>
				(async (key, defaultVal, toItem, toGm) => {
					const val = await GM.getValue(key)
					return {
						gmKey: key,
						val: void 0 !== val ? toItem(val) : defaultVal,
						defaultVal,
						toGm,
					}
				})(fycKey(k), d, i, g),
			defaultUserConfig = () =>
				function_pipe(async () => ({
					lang: await sc("LANG", "FYC_EN"),
					font: await sc("FONT", "MS PGothic"),
					chatOpacity: await sc("OPACITY", 0.8),
					color: await sc("COLOR", "#ffffff"),
					ownerColor: await sc("COLOR_OWNER", "#ffd600"),
					moderatorColor: await sc("COLOR_MODERATOR", "#c564ff"),
					memberColor: await sc("COLOR_MEMBER", "#9fffff"),
					fontSize: await sc("SIZE", 1),
					fontWeight: await sc("WEIGHT", 730),
					shadowFontWeight: await sc("WEIGHT_SHADOW", 1),
					maxChatCount: await sc("LIMIT", 40),
					flowSpeed: await sc("SPEED", 18),
					maxChatLength: await sc("MAX", 100),
					laneCount: await sc("LANE_DIV", 12),
					bannedWords: await ic("NG_WORDS", ...stringsArgs),
					bannedWordRegexs: await ic("NG_REG_WORDS", ...stringsArgs),
					bannedUsers: await ic("NG_USERS", ...stringsArgs),
					createChats: await sc("TOGGLE_CREATE_COMMENTS", !0),
					noOverlap: await sc("NO_OVERLAP", !0),
					createBanButton: await sc("NG_BUTTON", !0),
					simplifyChatField: await sc("SIMPLE_CHAT_FIELD", !1),
					displayModName: await sc("DISPLAY_MODERATOR_NAME", !0),
					displaySuperChatAuthor: await sc("DISPLAY_SUPER_CHAT_AUTHOR", !0),
					textOnly: await sc("TEXT_ONLY", !1),
					timingFunction: await sc("TIMING_FUNCTION", "linear"),
					displayChats: await sc("DISPLAY_COMMENTS", !0),
					minSpacing: await sc("MIN_SPACING", 0.5),
					fieldScale: await sc("FIELD_SCALE", 1),
					flowY1: await sc("flowY1", 0),
					flowY2: await sc("flowY2", 1),
					flowX1: await sc("flowX1", 0),
					flowX2: await sc("flowX2", 1),
					shadowColor: await sc("shadowColor", "#000000"),
				}))(),
			chatApp = () =>
				function_pipe(
					fromNullable(document.querySelector("#chatframe")),
					filter(x => {
						const state = x.contentDocument?.readyState
						return "loading" === state || "complete" === state
					}),
					chainNullableK(x => x.contentDocument),
					alt(() => Option_some(document)),
					chainNullableK(x => x.querySelector("yt-live-chat-app"))
				),
			livePageYt = () => ({
				toggleChatBtnParent: () =>
					fromNullable(document.querySelector(".ytp-right-controls")),
				settingNextElement: () =>
					fromNullable(
						document.querySelector(
							"#menu-container .dropdown-trigger.ytd-menu-renderer"
						)
					),
				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 = () => {
				const element = document.createElement("style")
				element.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  }"
				return element
			},
			observePair = con =>
				function_pipe(
					() => new external_rxjs_namespaceObject.Subject(),
					IO_bindTo("subject"),
					IO_bind("observer", x => () => new con(lib(x.subject)))
				),
			external_Swal_namespaceObject = Swal
		var external_Swal_default = __webpack_require__.n(
			external_Swal_namespaceObject
		)
		const addBanButton_button = document.createElement("button")
		addBanButton_button.classList.add(
			"style-scope",
			"yt-icon-button",
			"fyc_button"
		)
		Object.assign(addBanButton_button.style, {
			padding: "0px",
			width: "20px",
			height: "20px",
			fill: "#fff",
		})
		addBanButton_button.setAttribute("aria-label", "NGに入れる(Ban this user)")
		addBanButton_button.innerHTML =
			'<svg class="style-scope yt-icon" style="width: 100%; height: 75%; fill: var(--yt-spec-text-secondary);" viewBox="0 0 512 512"><path d="M440 78A256 256 0 1 0 73 435 256 256 0 0 0 440 78zm-99 35L113 341C37 179 212 44 341 113zM177 405l228-228c76 162-99 297-228 228z" fill-rule="evenodd"/></svg>'
		const addBanButton = (chat, id, getConfig, setConfig) =>
				chat.children.namedItem("card")
					? () => {}
					: () => {
							const clone = addBanButton_button.cloneNode(!0)
							clone.onclick = 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_chain(x =>
									IOOption_fromIO(() => {
										setConfig.bannedUsers(x)
										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
													)
												},
											})
											.fire({
												title: `Added Banned User: ${id}`,
												icon: "success",
											})
									})
								),
								IO_apSecond(() => {
									chat.style.display = "none"
								})
							)
							var f
							chat.querySelector("#content #message")?.append(clone)
					  },
			getChatFontSize = mainState =>
				Math.round(
					((Math.max(mainState.getConfig.fontSize() - 0.2, 0.01) *
						mainState.playerRect.height) /
						mainState.getConfig.laneCount()) *
						(mainState.getConfig.flowY2() - mainState.getConfig.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)
				) / chat.animationDuration,
			getFlowChatRect = (chat, mainState) => {
				const { getConfig } = mainState,
					x =
						mainState.playerRect.width * getConfig.flowX2() -
						(chat.width +
							mainState.playerRect.width *
								(getConfig.flowX2() - getConfig.flowX1())) *
							getFlowChatProgress(chat)
				return new DOMRect(x, chat.y, chat.width, chat.height)
			},
			getChatLane = (flowChat, progress, flowChats) => mainState => {
				const flowWidth =
						mainState.playerRect.width *
						(mainState.getConfig.flowX2() - mainState.getConfig.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.getConfig.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.getConfig.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.getConfig.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.getConfig.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 => getConfig =>
				getConfig.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) => {
						const { getConfig } = mainState,
							data = chat.getData(getConfig)
						return external_m_default()(
							"span",
							{
								style: {
									fontSize: `${getChatFontSize(mainState)}px`,
									visibility: getConfig.displayChats() ? "visible" : "hidden",
									color:
										"owner" === data.authorType
											? getConfig.ownerColor()
											: "moderator" === data.authorType
											? getConfig.moderatorColor()
											: "member" === data.authorType
											? getConfig.memberColor()
											: getConfig.color(),
									fontWeight: getConfig.fontWeight().toString(),
									fontFamily: getConfig.font(),
									opacity: getConfig.chatOpacity().toString(),
									textShadow: textShadow(getConfig.shadowColor())(
										getConfig.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, getConfig) => {
												const eleWin =
														message.ownerDocument.defaultView ?? window,
													maxChatLength = getConfig.maxChatLength()
												return function_pipe(
													Array.from(message.childNodes),
													es6_ReadonlyArray_reduce(
														{ vnodes: [], length: 0 },
														({ vnodes, length }, node) => {
															return length >= maxChatLength
																? { vnodes, length }
																: !getConfig.textOnly() &&
																  node instanceof eleWin.HTMLImageElement
																? {
																		vnodes: [
																			...vnodes,
																			external_m_default()("img", {
																				style: {
																					height: "1em",
																					width: "1em",
																					verticalAlign: "text-top",
																				},
																				src: node.src,
																				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, getConfig)
										),
										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.getConfig.laneCount() + 0.005) *
					(mainState.getConfig.flowY2() - mainState.getConfig.flowY1()) +
					mainState.getConfig.flowY1()),
			setChatPlayState = chat => mainState =>
				function_pipe(
					chat,
					fromPredicate(x => !x.animationEnded),
					fromOption,
					IOOption_chainOptionK(x => x.animation),
					IOOption_chainFirst(x =>
						IOOption_fromIO(
							mainState.chatPlaying ? () => x.play() : () => x.pause()
						)
					),
					IOOption_chain(x =>
						IOOption_fromIO(() => {
							x.playbackRate = mainState.getConfig.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.getConfig.flowX2() - mainState.getConfig.flowX1())
						}px, -${2 * x.fontSize}px)`
					}),
					IOOption_fromIO,
					IOOption_filter(() => !chat.animationEnded),
					IOOption_chainFirst(x =>
						IOOption_fromIO(() => {
							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.getConfig)
							? function_pipe(
									chat.animation,
									fromOption,
									IOOption_chain(x =>
										IOOption_fromIO(() => {
											x.finish()
											chat.animation = Option_none
										})
									),
									IO_map(() => Option_none)
							  )
							: IOOption_some(ctx)
					),
					IOOption_chainFirst(x =>
						IOOption_fromIO(() => {
							chat.lane = x.lane
						})
					),
					IOOption_map(x => ({ ...x, laneY: getLaneY(chat.lane, mainState) })),
					IOOption_chain(ctx =>
						function_pipe(
							[
								function_pipe(
									chat.animation,
									fromOption,
									IOOption_chain(x => IOOption_fromIO(() => x.cancel()))
								),
								function_pipe(
									[
										[
											mainState.playerRect.width *
												(mainState.getConfig.flowX2() -
													mainState.getConfig.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.getConfig.timingFunction(),
										}),
									x => {
										x.onfinish = () => {
											chat.animationEnded = !0
										}
										chat.y = ctx.laneY
										const newTime = 6400 * ctx.progress
										x.currentTime = newTime
										return x
									},
									Option_some,
									x => () => {
										chat.animation = x
									},
									IO_apSecond(setChatPlayState(chat)(mainState))
								),
							],
							sequenceArray,
							IOOption_fromIO
						)
					),
					IO_map(Option_isSome)
				),
			emptyElement = document.createElement("span"),
			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
			}
		}
		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: x => b => a => x(a)(b),
				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: function (predicate) {
						return function (as) {
							return as.some(predicate)
						}
					},
					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,
			},
			src_filterOperators = filterOperators,
			assert_lib = check.assert,
			tapNonNull = x => {
				assert_lib(null != x)
				return x
			},
			onChatFieldMutate = (
				chatScrn,
				flowChats,
				mainState,
				setConfig,
				mainLog
			) => {
				return function_flow(
					((f = e => Array.from(e.addedNodes)),
					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_filter(x => x.children.length > 0),
					ReadonlyArray_reverse,
					es6_ReadonlyArray_map(chat => () => {
						const getData = (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(/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 getConfig => ({
									chatType,
									authorType,
									authorID,
									authorName: function_pipe(
										authorName,
										es6_Option_map(x => ({
											visible:
												("moderator" === authorType &&
													getConfig.displayModName()) ||
												(Option_isSome(paymentInfo) &&
													getConfig.displaySuperChatAuthor()),
											content: x,
										}))
									),
									messageElement,
									message,
									messageText,
									paymentInfo,
									textColor,
									paidColor,
								})
							})(chat),
							{ getConfig } = mainState,
							data = getData(getConfig)
						;(((data, getConfig, mainLog) =>
							function_pipe(
								data,
								fromPredicate(() =>
									function_pipe(
										(getConfig =>
											external_jsep_default()(
												`\nor([\nRA.some(\n  flip(flow([matchedByText, RA.some]))(${JSON.stringify(
													getConfig.bannedWordRegexs()
												)})\n)(RA.compact([\n  messageText,\n  paymentInfo\n])),\nRA.some(\n  flip(flow([inText, RA.some]))(${JSON.stringify(
													getConfig.bannedWords()
												)})\n)(RA.compact([\n  messageText,\n  paymentInfo\n])),\nO.exists(\n  flip(flow([eqText, RA.some]))(${JSON.stringify(
													getConfig.bannedUsers()
												)})\n)(authorID)\n])\n`
											))(getConfig),
										x =>
											a(
												x,
												(data => ({
													...src_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 => mainLog([`Filtered: ${x}`])),
								match(
									() => () => !1,
									IO_map(() => !0)
								)
							)())(data, getConfig, mainLog)
							? () => {
									chat.style.display = "none"
							  }
							: function_pipe(
									[
										function_pipe(
											void 0,
											fromPredicate(getConfig.createChats),
											filter(() => "normal" === data.chatType),
											fromOption,
											IOOption_chain(() =>
												IOOption_fromIO(
													((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.getConfig)
														)
															? () => {}
															: () => {
																	const offScreenIndex = function_pipe(
																			flowChats,
																			findIndex(
																				chat =>
																					chat.animationEnded ||
																					flowChats.length >=
																						mainState.getConfig.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_chain(oldAnimation =>
																						IOOption_fromIO(() =>
																							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()
																		)
																	)()
															  })(getData, flowChats, chatScrn, mainState)
												)
											)
										),
										function_pipe(
											data.authorID,
											fromOption,
											IOOption_filter(getConfig.createBanButton),
											IOOption_chain(x =>
												IOOption_fromIO(
													addBanButton(chat, x, getConfig, setConfig)
												)
											),
											IO_map(() => Option_some(void 0)),
											IOOption_filter(getConfig.simplifyChatField),
											IOOption_chain(() =>
												IOOption_fromIO(
													(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)
												)
											)
										),
									],
									sequenceArray
							  ))()
					}),
					sequenceArray
				)
				var f
			},
			removeOldChats = maxChatCount => flowChats =>
				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()
							})
					)
				)
		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 src_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)", "色(影)"],
			},
			getLang = language => key =>
				src_defaultText[key]["FYC_EN" === language ? 0 : 1],
			src_languages = [
				["FYC_EN", "English"],
				["FYC_JA", "日本語"],
			],
			colorInput = action => color =>
				h("input", {
					style: { verticalAlign: "middle", width: "5.5em" },
					maxlength: 20,
					value: color,
					...action,
				}),
			colorPicker = action => color =>
				h("input", {
					style: { width: "36px", verticalAlign: "middle" },
					type: "color",
					value: color,
					oninput: action.onchange,
				}),
			colorTextOutput = textStyle => color =>
				h(
					"span",
					{ style: { ...textStyle, color } },
					hyperapp_text("Aa1あア亜")
				),
			tapIs = constructor => x => {
				assert_lib(x instanceof constructor)
				return x
			},
			getValue = 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.")
			},
			ui_option = (value, label, selected) =>
				h("option", { value, selected }, hyperapp_text(label)),
			panelBoxStyle = width => ({ flex: `0 0 ${width}px`, margin: "2px" }),
			rangeRow = (min, max, step, value, editing, action) =>
				h("div", {}, [
					h("input", {
						style: { width: "150px", verticalAlign: "middle" },
						type: "range",
						min,
						max,
						step,
						value,
						oninput: action.onchange,
					}),
					h("input", {
						style: {
							width: "30px",
							backgroundColor: "transparent",
							color: "inherit",
							borderWidth: "1px",
							verticalAlign: "middle",
						},
						inputmode: "decimal",
						value: editing
							? value
							: Number.parseFloat(value)
									.toFixed(4)
									.replace(/\.?0+$/, ""),
						...action,
					}),
				]),
			settingRow = (label, content) =>
				h("div", {}, [
					h("span", {}, hyperapp_text(label)),
					h("div", {}, content),
				]),
			tabContainer = (style, labels, tabs, mainTab, ontabSelect) =>
				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: "hidden auto" } },
						h(
							"div",
							{ style: { ...style.tab } },
							tabs.find((_, i) => i === mainTab)?.()
						)
					),
				]),
			style = { resize: "horizontal", boxSizing: "border-box", width: "100%" },
			textAreaRow = (rows, value, action) =>
				h("textarea", { rows, value, style, ...action }),
			textColorRow = colorNodes =>
				function_pipe(
					colorNodes,
					Reader_sequenceArray,
					es6_Reader_map(x => h("div", {}, x))
				),
			textRowStyle = { width: "70%", boxSizing: "border-box" },
			exampleTextStyle = s => ({
				fontFamily: s.font,
				fontWeight: s.fontWeight.toString(),
				textShadow: textShadow(s.shadowColor)(s.shadowFontWeight),
			}),
			computed = {
				useStepTiming: s => Boolean(s.timingFunction.match(/^steps\(.+/)),
			},
			stepTiming = stepCount => `steps(${stepCount}, jump-end)`,
			settingPanel = command => {
				const { setConfig, act } = command,
					configFx = (
						setConfig => (k, v) =>
							[() => setConfig[k](v), void 0]
					)(setConfig),
					setRange = keyA => keyB => bFn => (s, vA) =>
						function_pipe(bFn(vA)(s[keyB]), newB => [
							{ ...s, [keyA]: vA, [keyB]: newB },
							configFx(keyA, vA),
							configFx(keyB, newB),
						]),
					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: (s, v) =>
							function_pipe(stepTiming(v), timingFunction => [
								{ ...s, timingStepCount: v, timingFunction },
								configFx("timingFunction", timingFunction),
							]),
						bannedWordRegexs: (s, v) =>
							function_pipe(
								v,
								es6_ReadonlyArray_reduce(
									{ valid: !0, error: "" },
									(acc, cur) => {
										try {
											RegExp(cur, "u")
											return acc
										} catch (e) {
											return { valid: !1, error: `${acc.error}${e} in ${cur};` }
										}
									}
								),
								x => [
									{
										...s,
										bannedWordRegexs: v,
										bannedWordRegexsError: x.error,
										bannedWordRegexsValid: x.valid,
									},
									...(x.valid ? [configFx("bannedWordRegexs", v)] : []),
								]
							),
					},
					setComputed = {
						useStepTiming: (s, v) => {
							const timingFunction = v
								? stepTiming(s.timingStepCount)
								: "linear"
							return [
								{ ...s, timingFunction },
								configFx("timingFunction", timingFunction),
							]
						},
					},
					doAct = {
						copy: async s => {
							GM.setClipboard(s.eventLog.join("\n"))
						},
						clearFlowChats: async s => {
							act.clearFlowChats()
						},
					},
					getTrueState = (k, s) => (k in computed ? computed[k](s) : s[k]),
					getState = (k, s) =>
						s.editingInput.id === k
							? s.editingInput.committedState
							: getTrueState(k, s),
					updateAt = (k, v, s) =>
						k in setComputed
							? setComputed[k](s, v)
							: k in setState
							? setState[k](s, v)
							: [{ ...s, [k]: v }, ...(k in setConfig ? [configFx(k, v)] : [])],
					updateString = key => (s, e) =>
						function_pipe(getValue(e), x => updateAt(key, x, s)),
					updateNumber = key => (s, e) =>
						function_pipe(getValue(e), parseFloat, x => updateAt(key, x, s)),
					updateInt = key => (s, e) =>
						function_pipe(
							getValue(e),
							x => parseInt(x, 10),
							x => updateAt(key, x, s)
						),
					updateStrings = key => (s, e) =>
						function_pipe(
							getValue(e),
							function_flow(
								split(/\r\n|\n/),
								es6_ReadonlyArray_filter(Predicate_not(string_isEmpty))
							),
							x => updateAt(key, x, s)
						),
					editAction = (key, onchange) => ({
						onfocus: (s, e) =>
							updateAt(
								"editingInput",
								{
									id: key,
									committedState: getTrueState(key, s),
									value: getValue(e),
								},
								s
							),
						onblur: s =>
							updateAt(
								"editingInput",
								{ id: "", committedState: "", value: "" },
								s
							),
						oninput: (s, e) =>
							updateAt(
								"editingInput",
								{
									id: key,
									committedState: s.editingInput.committedState,
									value: getValue(e),
								},
								s
							),
						onchange: (s, e) => {
							const [s1, ...es1] = onchange(key)(s, e),
								x =
									s1.editingInput.id === key
										? {
												id: key,
												committedState: getTrueState(key, s1),
												value: getValue(e),
										  }
										: s1.editingInput,
								[s2, ...es2] = updateAt("editingInput", x, s1)
							return [s2, ...es1, ...es2]
						},
					}),
					getEditValue = (s, k, t) =>
						s.editingInput.id === k ? s.editingInput.value : t(getState(k, s))
				return state => {
					const getText = getLang(state.lang),
						checkboxNode = label => {
							return ((label, checked, onchange) =>
								h(
									"div",
									{},
									h("label", {}, [
										hyperapp_text(label),
										h("input", { type: "checkbox", checked, onchange }),
									])
								))(
								getText(label),
								getState(label, state),
								((key = label),
								(s, e) =>
									function_pipe(
										(e => tapIs(HTMLInputElement)(e.currentTarget).checked)(e),
										x => updateAt(key, x, s)
									))
							)
							var key
						},
						textColorNode = label =>
							settingRow(getText(label), [
								textColorRow(
									function_pipe(editAction(label, updateString), x => [
										colorPicker(x),
										colorInput(x),
										colorTextOutput(exampleTextStyle(state)),
									])
								)(getEditValue(state, label, function_identity)),
							]),
						intNode = (label, min, max, step) =>
							settingRow(getText(label), [
								rangeRow(
									min,
									max,
									step,
									getEditValue(state, label, number_Show_show),
									state.editingInput.id === label,
									editAction(label, updateInt)
								),
							]),
						numberNode = (label, min, max, step) =>
							settingRow(getText(label), [
								rangeRow(
									min,
									max,
									step,
									getEditValue(state, label, number_Show_show),
									state.editingInput.id === label,
									editAction(label, updateNumber)
								),
							]),
						buttonNode = label =>
							h(
								"button",
								{
									type: "button",
									onclick: s => [s, [() => doAct[label](s), void 0]],
								},
								hyperapp_text(getText(label))
							),
						textAreaNode = (label, rows) =>
							settingRow(getText(label), [
								textAreaRow(
									rows,
									getEditValue(state, label, x => x.join("\n")),
									editAction(label, updateStrings)
								),
							]),
						currentFonts = [
							["", "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", "游ゴシック体"],
							[state.font, "Custom", "カスタム"],
						],
						logPageLength =
							Math.trunc(getState("eventLog", state).length / 100) + 1
					return state.showPanel
						? h(
								"div",
								{
									class: "fyc_panel",
									style: {
										backgroundColor: "rgba(30,30,30,0.9)",
										zIndex: "10000",
										position: "absolute",
										bottom: "40px",
										right: "0px",
										color: "#fff",
										fontSize: "14px",
										width: "660px",
										border: "solid 1px #666",
										fontFamily: "MS PGothic",
										lineHeight: "1.2",
									},
								},
								[
									h(
										"div",
										{
											style: {
												position: "absolute",
												inset: "3px 3px auto auto",
											},
										},
										[
											hyperapp_text("🌐"),
											h(
												"select",
												{ onchange: updateString("lang") },
												function_pipe(
													src_languages,
													es6_ReadonlyArray_map(([lang, label]) =>
														ui_option(lang, label, lang === state.lang)
													)
												)
											),
										]
									),
									tabContainer(
										{
											container: { height: "364px" },
											label: { padding: "6px" },
											labelFocus: { background: "#666" },
											tab: { display: "flex", padding: "6px" },
										},
										[
											getText("flowChat"),
											getText("chatFilter"),
											getText("chatField"),
											getText("feedback"),
										],
										[
											() => {
												return [
													h("div", { style: panelBoxStyle(212) }, [
														settingRow(getText("font"), [
															h(
																"select",
																{
																	style: textRowStyle,
																	onchange: updateString("font"),
																},
																function_pipe(
																	currentFonts,
																	findIndex(x => x[0] === state.font),
																	getOrElse(() => 0),
																	index =>
																		function_pipe(
																			currentFonts,
																			es6_ReadonlyArray_mapWithIndex((i, x) =>
																				ui_option(
																					x[0],
																					"FYC_JA" === state.lang ? x[2] : x[1],
																					i === index
																				)
																			)
																		)
																)
															),
														]),
														h("input", {
															style: textRowStyle,
															maxlength: 20,
															value: state.font,
															oninput: updateString("font"),
														}),
														textColorNode("color"),
														textColorNode("ownerColor"),
														textColorNode("moderatorColor"),
														textColorNode("memberColor"),
														((label = "shadowColor"),
														settingRow(getText(label), [
															textColorRow(
																function_pipe(
																	[colorPicker, colorInput],
																	es6_ReadonlyArray_map(f =>
																		f(editAction(label, updateString))
																	)
																)
															)(getEditValue(state, label, function_identity)),
														])),
													]),
													h("div", { style: panelBoxStyle(212) }, [
														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),
													]),
													h("div", { style: panelBoxStyle(212) }, [
														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),
														checkboxNode("useStepTiming"),
														h(
															"div",
															{
																style: {
																	...(getState("useStepTiming", state)
																		? {}
																		: { opacity: "0.5" }),
																},
															},
															intNode("timingStepCount", 1, 400, 1)
														),
														checkboxNode("createChats"),
														checkboxNode("displayModName"),
														checkboxNode("displaySuperChatAuthor"),
														checkboxNode("textOnly"),
														hyperapp_text(getText("flowNewChatIf")),
														checkboxNode("noOverlap"),
														buttonNode("clearFlowChats"),
													]),
												]
												var label
											},
											() => [
												h(
													"div",
													{ style: panelBoxStyle(212) },
													textAreaNode("bannedWords", 18)
												),
												h(
													"div",
													{ style: panelBoxStyle(212) },
													settingRow(getText("bannedWordRegexs"), [
														h(
															"span",
															{},
															hyperapp_text(
																state.bannedWordRegexsValid
																	? ""
																	: `${getText("error")}: ${
																			state.bannedWordRegexsError
																	  }`
															)
														),
														textAreaRow(
															18,
															getEditValue(state, "bannedWordRegexs", x =>
																x.join("\n")
															),
															editAction("bannedWordRegexs", updateStrings)
														),
													])
												),
												h(
													"div",
													{ style: panelBoxStyle(212) },
													textAreaNode("bannedUsers", 18)
												),
											],
											() => [
												h("div", { style: panelBoxStyle(644) }, [
													numberNode("fieldScale", 0.7, 1.5, 0.05),
													checkboxNode("simplifyChatField"),
													checkboxNode("createBanButton"),
												]),
											],
											() => [
												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"))
														)
													),
													h("div", {}, [
														h("span", {}, hyperapp_text(getText("eventLog"))),
														buttonNode("copy"),
														tabContainer(
															{
																container: { height: "276px" },
																label: {
																	padding: "4px",
																	width: "2em",
																	textAlign: "center",
																},
																labelFocus: { background: "#666" },
																tab: {
																	display: "flex",
																	flexDirection: "column",
																	padding: "6px",
																},
															},
															function_pipe(
																ReadonlyArray_makeBy(
																	logPageLength,
																	number_Show_show
																)
															),
															function_pipe(
																ReadonlyArray_makeBy(
																	logPageLength,
																	i => () =>
																		function_pipe(
																			getState("eventLog", state).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", state),
															(s, n) => updateAt("logTab", n, s)
														),
													]),
												]),
											],
										],
										getState("mainTab", state),
										(s, n) => updateAt("mainTab", n, s)
									),
								]
						  )
						: h("div", {})
				}
			},
			togglePanel = (x, e) => [
				{ ...x, showPanel: !x.showPanel },
				[
					x.showPanel
						? () => tapIs(HTMLElement)(e.currentTarget).blur()
						: () => {},
					void 0,
				],
			],
			simpleWrap = (comp, init) => {
				const node = document.createElement(comp.tag)
				return { node, dispatch: app({ init, view: comp.view, node }) }
			}
		;(async () => {
			external_log_namespaceObject.setLevel("info")
			try {
				await function_pipe(
					defaultUserConfig,
					function_flow(
						Task_bindTo("userConfig"),
						Task_bind("configKeys", x => Task_of(Object.keys(x.userConfig))),
						Task_bind("getConfig", ctx =>
							Task_of(
								function_pipe(
									ctx.configKeys,
									es6_ReadonlyArray_map(x => [x, () => ctx.userConfig[x].val]),
									Object.fromEntries
								)
							)
						),
						Task_bind("mainState", x =>
							Task_of({
								chatPlaying: !0,
								playerRect: new DOMRect(0, 0, 600, 400),
								getConfig: x.getConfig,
							})
						),
						Task_bind("configSubject", ctx =>
							Task_of(
								function_pipe(
									ctx.configKeys,
									es6_ReadonlyArray_map(x => [
										x,
										new external_rxjs_namespaceObject.Subject(),
									]),
									Object.fromEntries
								)
							)
						),
						Task_bind("setConfigPlain", ctx =>
							Task_of(
								function_pipe(
									ctx.configKeys,
									es6_ReadonlyArray_map(x => [
										x,
										async val => {
											ctx.userConfig[x].val = val
											ctx.configSubject[x].next(val)
										},
									]),
									Object.fromEntries
								)
							)
						),
						Task_apS(
							"channel",
							Task_of(
								new broadcast_channel_BroadcastChannel("fyc-0615654655528523")
							)
						),
						Task_bind("setConfig", ctx =>
							Task_of(
								function_pipe(
									ctx.configKeys,
									es6_ReadonlyArray_map(x => [
										x,
										async val => {
											ctx.setConfigPlain[x](val)
											const item = ctx.userConfig[x]
											ctx.channel.postMessage([x, val])
											GM.setValue(item.gmKey, item.toGm(val))
										},
									]),
									Object.fromEntries
								)
							)
						)
					),
					function_flow(
						Task_apS(
							"reinitSubject",
							Task_fromIO(() => new external_rxjs_namespaceObject.Subject())
						),
						Task_bind("reinitialize", ctx =>
							Task_of(() => {
								requestAnimationFrame(() => lib(ctx.reinitSubject)())
							})
						),
						Task_bind("toggleChatButtonInit", ctx =>
							Task_of({
								lang: ctx.getConfig.lang(),
								displayChats: ctx.getConfig.displayChats(),
							})
						),
						Task_bind("wrappedToggleChatBtn", ctx => {
							return Task_of(
								simpleWrap(
									((setConfig = ctx.setConfig),
									{
										tag: "button",
										view: state => {
											const label = getLang(state.lang)(
												state.displayChats ? "hideChat" : "showChat"
											)
											return h(
												"button",
												{
													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 => {
														const displayChats = !s.displayChats
														return [
															{ ...s, displayChats },
															[
																() => setConfig.displayChats(displayChats),
																void 0,
															],
														]
													},
												},
												[
													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_bind("wrappedSetting", ctx => {
							return Task_of(
								simpleWrap(
									(command => {
										const panel = settingPanel(command)
										return {
											tag: "span",
											view: s => {
												return h("span", { style: { display: "contents" } }, [
													panel(s),
													((state = s),
													h(
														"button",
														{
															class: "fyc_button",
															style: {
																background: "rgba(0,0,0,0)",
																marginLeft: "10px",
																whiteSpace: "nowrap",
															},
															onclick: togglePanel,
														},
														[
															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(getLang(state.lang)("setting"))
															),
														]
													)),
												])
												var state
											},
										}
									})({
										setConfig: ctx.setConfig,
										act: {
											clearFlowChats: async () =>
												removeOldChats(0)(ctx.flowChats)(),
										},
									}),
									((getConfig = ctx.getConfig),
									{
										...function_pipe(
											Object.entries(getConfig),
											es6_ReadonlyArray_map(([k, v]) => [k, v()]),
											Object.fromEntries
										),
										showPanel: !1,
										bannedWordRegexsValid: !0,
										bannedWordRegexsError: "",
										mainTab: 0,
										logTab: 0,
										timingStepCount: parseInt(
											getConfig
												.timingFunction()
												.match(/^steps\((\d+),.+/)?.[1] ?? "150",
											10
										),
										eventLog: [],
										editingInput: { id: "", committedState: void 0, value: "" },
									})
								)
							)
							var getConfig
						}),
						Task_bind("mainLog", ctx =>
							Task_of(
								x => () =>
									ctx.wrappedSetting.dispatch(s => ({
										...s,
										eventLog: appendLog(s.eventLog)(x),
									}))
							)
						),
						Task_bind("mixLog", ctx =>
							Task_of(
								function_pipe(
									[ctx.mainLog, consoleLog],
									Reader_sequenceArray,
									es6_Reader_map(sequenceArray)
								)
							)
						)
					),
					Task_chainFirstIOK(ctx =>
						function_pipe(
							[
								["Version", "1.15.9"],
								["User Agent", window.navigator.userAgent],
								["UserConfig", JSON.stringify(ctx.userConfig)],
							],
							es6_ReadonlyArray_map(ctx.mainLog),
							sequenceArray
						)
					),
					Task_bind("cs", ctx =>
						Task_of(
							function_pipe(
								ctx.configSubject,
								Object.entries,
								es6_ReadonlyArray_map(([k, value]) => [
									k,
									function_pipe(
										value,
										(0, external_rxjs_namespaceObject.tap)(v =>
											function_pipe(
												v,
												x => s => ({ ...s, [k]: x }),
												of,
												IO_chainFirst(
													x => () => ctx.wrappedSetting.dispatch(x)
												),
												chain(x =>
													k in ctx.toggleChatButtonInit
														? () => ctx.wrappedToggleChatBtn.dispatch(x)
														: () => {}
												),
												x => () => requestAnimationFrame(x)
											)()
										)
									),
								]),
								Object.fromEntries
							)
						)
					),
					Task_apS("livePage", Task_fromIO(livePageYt)),
					Task_bind("liveElementKeys", ctx =>
						Task_of(Object.keys(ctx.livePage))
					),
					Task_bind("live", ctx =>
						Task_of(
							function_pipe(
								key => ({ ele: Option_none, read: ctx.livePage[key] }),
								initState =>
									function_pipe(
										ctx.liveElementKeys,
										es6_ReadonlyArray_map(x => [x, initState(x)]),
										Object.fromEntries
									)
							)
						)
					),
					Task_apS("chatScreen", Task_fromIO(createChatScreen)),
					Task_bind("config$", ctx =>
						function_pipe(
							ctx.cs,
							cs =>
								(0, external_rxjs_namespaceObject.defer)(() =>
									(0, external_rxjs_namespaceObject.merge)(
										(0, external_rxjs_namespaceObject.merge)(
											cs.bannedWordRegexs,
											cs.bannedWords,
											cs.bannedUsers
										),
										function_pipe(
											cs.fieldScale,
											(0, external_rxjs_namespaceObject.startWith)(
												ctx.getConfig.fieldScale()
											),
											(0, external_rxjs_namespaceObject.tap)(scale =>
												function_pipe(
													ctx.live.chatField.ele,
													fromOption,
													IOOption_chain(field =>
														IOOption_fromIO(() =>
															function_pipe(
																[
																	function_pipe(
																		fromNullable(field.parentElement),
																		es6_Option_map(x => () => {
																			x.style.transformOrigin =
																				(scale >= 1 ? "top" : "bottom") +
																				" left"
																			x.style.transform = `scale(${scale})`
																			x.style.width = 100 / scale + "%"
																			x.style.height = `${field.offsetHeight}px`
																		})
																	),
																	function_pipe(
																		ctx.live.chatScroller.ele,
																		es6_Option_map(scroller => () => {
																			scroller.scrollTop = scroller.scrollHeight
																		})
																	),
																],
																ReadonlyArray_compact,
																sequenceArray
															)
														)
													)
												)()
											)
										),
										function_pipe(
											(0, external_rxjs_namespaceObject.merge)(
												function_pipe(
													(0, external_rxjs_namespaceObject.merge)(
														cs.font,
														cs.fontSize,
														cs.fontWeight,
														cs.laneCount,
														cs.minSpacing,
														cs.flowY1,
														cs.flowY2,
														function_pipe(
															cs.flowX1,
															(0, external_rxjs_namespaceObject.startWith)(
																ctx.getConfig.flowX1()
															),
															(0, external_rxjs_namespaceObject.tap)(x => {
																ctx.chatScreen.style.left = 100 * x + "%"
																ctx.chatScreen.style.width =
																	100 * (ctx.getConfig.flowX2() - x) + "%"
															})
														),
														function_pipe(
															cs.flowX2,
															(0, external_rxjs_namespaceObject.tap)(x => {
																ctx.chatScreen.style.left =
																	100 * ctx.getConfig.flowX1() + "%"
																ctx.chatScreen.style.width =
																	100 * (x - ctx.getConfig.flowX1()) + "%"
															})
														),
														cs.textOnly
													),
													(0, external_rxjs_namespaceObject.map)(() => ({
														render: !0,
														setAnimation: !0,
													}))
												),
												function_pipe(
													(0, external_rxjs_namespaceObject.merge)(
														cs.color,
														cs.ownerColor,
														cs.moderatorColor,
														cs.memberColor,
														cs.shadowColor,
														cs.chatOpacity,
														cs.shadowFontWeight,
														cs.displayChats
													),
													(0, external_rxjs_namespaceObject.map)(() => ({
														render: !0,
													}))
												),
												function_pipe(
													cs.flowSpeed,
													(0, external_rxjs_namespaceObject.map)(() => ({
														setPlayState: !0,
													}))
												),
												function_pipe(
													(0, external_rxjs_namespaceObject.merge)(
														function_pipe(
															cs.maxChatCount,
															(0, external_rxjs_namespaceObject.tap)(x =>
																removeOldChats(x)(ctx.flowChats)()
															)
														),
														cs.noOverlap,
														cs.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(
																		(function (a) {
																			return function (f) {
																				return f(a)
																			}
																		})(ctx.mainState)
																	),
																	sequenceArray
																)
														)
													),
													sequenceArray
												)()
											)
										),
										cs.lang,
										cs.maxChatLength,
										cs.simplifyChatField,
										cs.createBanButton,
										cs.createChats,
										cs.displayModName,
										cs.displaySuperChatAuthor,
										cs.fieldScale,
										cs.bannedWords,
										cs.bannedWordRegexs,
										cs.bannedUsers
									)
								),
							Task_of
						)
					),
					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,
							},
							of,
							IO_apS("css", mainCss),
							IO_apS("documentMutationPair", observePair(MutationObserver)),
							IO_apS("chatMutationPair", observePair(MutationObserver)),
							IO_apS("playerResizePair", 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
											),
											(0, external_rxjs_namespaceObject.filter)(() =>
												function_pipe(
													ctx.liveElementKeys,
													es6_ReadonlyArray_map(key =>
														function_pipe(
															ctx.live[key].read(),
															fromPredicate(
																newEle => !c.eq(ctx.live[key].ele, newEle)
															),
															es6_Option_map(x => () => {
																ctx.live[key].ele = x
															}),
															es6_Option_map(
																IO_apSecond(ctx.mixLog([`${key} changed`]))
															)
														)
													),
													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(0)(ctx.flowChats)()
										c.documentMutationPair.observer.disconnect()
										c.documentMutationPair.observer.observe(document, {
											childList: !0,
											subtree: !0,
										})
										c.chatMutationPair.observer.disconnect()
										c.playerResizePair.observer.disconnect()
										document.head.append(c.css)
										function_pipe(
											[
												function_pipe(
													ctx.live.chatField.ele,
													es6_Option_map(x => () => {
														;((chatField = x),
														() =>
															function_pipe(
																fromNullable(chatField.parentElement),
																es6_Option_map(x => () => {
																	x.style.overflow = "unset"
																})
															))()
														var chatField
														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(x => () => {
														c.playerResizePair.observer.observe(x)
														x.insertAdjacentElement(
															"afterbegin",
															ctx.chatScreen
														)
													})
												),
												function_pipe(
													ctx.live.toggleChatBtnParent.ele,
													es6_Option_map(
														x => () => x.append(ctx.wrappedToggleChatBtn.node)
													)
												),
												function_pipe(
													ctx.live.settingNextElement.ele,
													es6_Option_map(x => () => {
														x.insertAdjacentElement(
															"beforebegin",
															ctx.wrappedSetting.node
														)
													})
												),
											],
											ReadonlyArray_compact,
											ReadonlyArray_append(
												function_pipe(
													ctx.live.video.ele,
													filter(x => !x.paused),
													alt(() => ctx.live.offlineSlate.ele),
													Option_isSome,
													x => () => {
														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(
														[
															"lang",
															"bannedWords",
															"bannedWordRegexs",
															"bannedUsers",
															"simplifyChatField",
															"createBanButton",
															"fieldScale",
														].includes(key),
														x =>
															x ? () => ctx.setConfigPlain[key](val) : () => {}
													)()
												)
											),
											...function_pipe(
												ctx.configKeys,
												es6_ReadonlyArray_map(key =>
													function_pipe(
														ctx.cs[key],
														(0, external_rxjs_namespaceObject.startWith)(
															ctx.getConfig[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.mainLog([
																`Config ${key}`,
																JSON.stringify(x, void 0, 2),
															])()
														)
													)
												)
											),
											ctx.config$,
											function_pipe(
												ctx.live.video.ele,
												match(
													() => external_rxjs_namespaceObject.EMPTY,
													x => {
														return function_pipe(
															((video = x),
															(0, external_rxjs_namespaceObject.merge)(
																function_pipe(
																	(0, external_rxjs_namespaceObject.fromEvent)(
																		video,
																		"playing"
																	),
																	(0, external_rxjs_namespaceObject.map)(
																		() => !0
																	)
																),
																function_pipe(
																	(0, external_rxjs_namespaceObject.fromEvent)(
																		video,
																		"waiting"
																	),
																	(0, external_rxjs_namespaceObject.map)(
																		() => !1
																	)
																),
																function_pipe(
																	(0, external_rxjs_namespaceObject.fromEvent)(
																		video,
																		"pause"
																	),
																	(0, external_rxjs_namespaceObject.map)(
																		() => !1
																	)
																)
															)),
															(0, external_rxjs_namespaceObject.map)(
																playing =>
																	playing ||
																	Option_isSome(ctx.live.offlineSlate.ele)
															),
															(0, external_rxjs_namespaceObject.tap)(
																chatPlaying => {
																	ctx.mainState.chatPlaying = chatPlaying
																	ctx.flowChats.forEach(chat =>
																		setChatPlayState(chat)(ctx.mainState)()
																	)
																}
															)
														)
														var video
													}
												)
											),
											function_pipe(
												c.chatMutationPair.subject,
												(0, external_rxjs_namespaceObject.map)(
													onChatFieldMutate(
														ctx.chatScreen,
														ctx.flowChats,
														ctx.mainState,
														ctx.setConfig,
														ctx.mainLog
													)
												),
												(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),
												(0, external_rxjs_namespaceObject.tap)(x => {
													ctx.mixLog(["URL Changed", x])()
													removeOldChats(0)(ctx.flowChats)()
													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 (
														(rect = x),
														(flowChats = ctx.flowChats),
														(mainState = ctx.mainState),
														(mainLog = ctx.mainLog),
														function_pipe(
															rect,
															match(
																() => () => {},
																x => () => {
																	mainLog(["Resize detected"])()
																	mainState.playerRect = x
																	flowChats.forEach(chat => {
																		renderChat(chat)(mainState)()
																		setChatAnimation(
																			chat,
																			flowChats
																		)(mainState)()
																	})
																}
															)
														)()
													)
													var rect, flowChats, mainState, mainLog
												})
											)
										)
									),
									(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)(5e3),
												(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)
				)()
			} catch (error) {
				external_log_namespaceObject.info("【FYC】 Error", error)
			}
		})()
	})()
})()