// ==UserScript==
// @name Flow Youtube Chat
// @version 1.15.8
// @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__ = {
142: (
__unused_webpack_module,
__unused_webpack___webpack_exports__,
__webpack_require__
) => {
"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) {
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
})
.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 constTrue = constant(!0),
constFalse = constant(!1),
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 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 = [],
Predicate_not =
(Object.prototype.hasOwnProperty,
function (predicate) {
return function (a) {
return !predicate(a)
}
}),
Separated_separated = function (left, right) {
return { left, right }
}
function Witherable_wiltDefault(T, C) {
return function (F) {
var traverseF = T.traverse(F)
return function (wa, f) {
return F.map(traverseF(wa, f), C.separate)
}
}
}
function Witherable_witherDefault(T, C) {
return function (F) {
var traverseF = T.traverse(F)
return function (wa, f) {
return F.map(traverseF(wa, f), C.compact)
}
}
}
var Option_none = none,
Option_some = some
function fromPredicate(predicate) {
return function (a) {
return predicate(a) ? Option_some(a) : Option_none
}
}
var getLeft = function (ma) {
return "Right" === ma._tag ? Option_none : Option_some(ma.left)
},
getRight = function (ma) {
return "Left" === ma._tag ? Option_none : Option_some(ma.right)
},
Option_map = function (fa, f) {
return function_pipe(fa, es6_Option_map(f))
},
_ap = function (fab, fa) {
return function_pipe(fab, ap(fa))
},
_reduce = function (fa, b, f) {
return function_pipe(fa, reduce(b, f))
},
_foldMap = function (M) {
var foldMapM = foldMap(M)
return function (fa, f) {
return function_pipe(fa, foldMapM(f))
}
},
_reduceRight = function (fa, b, f) {
return function_pipe(fa, reduceRight(b, f))
},
_traverse = function (F) {
var traverseF = traverse(F)
return function (ta, f) {
return function_pipe(ta, traverseF(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 },
of = Option_some,
ap = function (fa) {
return function (fab) {
return Option_isNone(fab) || Option_isNone(fa)
? Option_none
: Option_some(fab.value(fa.value))
}
},
Apply = { URI: "Option", map: Option_map, ap: _ap },
chain = function (f) {
return function (ma) {
return Option_isNone(ma) ? Option_none : f(ma.value)
}
},
reduce = function (b, f) {
return function (fa) {
return Option_isNone(fa) ? b : f(b, fa.value)
}
},
foldMap = function (M) {
return function (f) {
return function (fa) {
return Option_isNone(fa) ? M.empty : f(fa.value)
}
}
},
reduceRight = function (b, f) {
return function (fa) {
return Option_isNone(fa) ? b : f(fa.value, b)
}
},
alt = function (that) {
return function (fa) {
return Option_isNone(fa) ? that() : fa
}
},
extend = function (f) {
return function (wa) {
return Option_isNone(wa) ? Option_none : Option_some(f(wa))
}
},
compact = chain(function_identity),
defaultSeparated = Separated_separated(Option_none, Option_none),
separate = function (ma) {
return Option_isNone(ma)
? defaultSeparated
: Separated_separated(getLeft(ma.value), getRight(ma.value))
},
Compactable = { URI: "Option", compact, separate },
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), separate)
},
traverse = function (F) {
return function (f) {
return function (ta) {
return Option_isNone(ta)
? F.of(Option_none)
: F.map(f(ta.value), Option_some)
}
}
},
sequence = function (F) {
return function (ta) {
return Option_isNone(ta)
? F.of(Option_none)
: F.map(ta.value, Option_some)
}
},
Traversable = {
URI: "Option",
map: Option_map,
reduce: _reduce,
foldMap: _foldMap,
reduceRight: _reduceRight,
traverse: _traverse,
sequence,
},
_wither = Witherable_witherDefault(Traversable, Compactable),
_wilt = Witherable_wiltDefault(Traversable, Compactable),
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))
}
},
toUndefined = match(constUndefined, function_identity),
Option_option = {
URI: "Option",
map: Option_map,
of,
ap: _ap,
chain: function (ma, f) {
return function_pipe(ma, chain(f))
},
reduce: _reduce,
foldMap: _foldMap,
reduceRight: _reduceRight,
traverse: _traverse,
sequence,
zero: function () {
return Option_none
},
alt: function (fa, that) {
return function_pipe(fa, alt(that))
},
extend: function (wa, f) {
return function_pipe(wa, extend(f))
},
compact,
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))
},
wither: _wither,
wilt: _wilt,
throwError: function () {
return Option_none
},
}
function Apply_apSecond(A) {
return function (second) {
return function (first) {
return A.ap(
A.map(first, function () {
return function (b) {
return b
}
}),
second
)
}
}
}
function Apply_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 Functor_map(F, G) {
return function (f) {
return function (fa) {
return F.map(fa, function (ga) {
return G.map(ga, f)
})
}
}
}
function Functor_bindTo(F) {
return function (name) {
return function (fa) {
return F.map(fa, function (a) {
var _a
return ((_a = {})[name] = a), _a
})
}
}
}
function OptionT_some(F) {
return function_flow(Option_some, F.of)
}
function OptionT_zero(F) {
return constant(F.of(Option_none))
}
function Compactable_compact(F, G) {
return function (fga) {
return F.map(fga, G.compact)
}
}
function Filterable_filter(F, G) {
return function (predicate) {
return function (fga) {
return F.map(fga, function (ga) {
return G.filter(ga, predicate)
})
}
}
}
function Filterable_filterMap(F, G) {
return function (f) {
return function (fga) {
return F.map(fga, function (ga) {
return G.filterMap(ga, f)
})
}
}
}
function Chain_chainFirst(M) {
return function (f) {
return function (first) {
return M.chain(first, function (a) {
return M.map(f(a), function () {
return a
})
})
}
}
}
function Chain_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))
})
})
}
}
}
var M,
apM,
mapM,
chainM,
altM,
foldM,
getOrElseM,
zeroM,
IO_map = function (ma, f) {
return function () {
return f(ma())
}
},
IO_ap = function (mab, ma) {
return function () {
return mab()(ma())
}
},
IO_chain = function (ma, f) {
return function () {
return f(ma())()
}
},
es6_IO_map = function (f) {
return function (fa) {
return IO_map(fa, f)
}
},
IO_of = constant,
es6_IO_chain = function (f) {
return function (ma) {
return IO_chain(ma, f)
}
},
IO_Functor = { URI: "IO", map: IO_map },
IO_Apply = { URI: "IO", map: IO_map, ap: IO_ap },
IO_apSecond = Apply_apSecond(IO_Apply),
IO_Chain = { URI: "IO", map: IO_map, ap: IO_ap, chain: IO_chain },
IO_chainFirst = Chain_chainFirst(IO_Chain),
fromIO = function_identity,
IO_bindTo = Functor_bindTo(IO_Functor),
IO_bind = Chain_bind(IO_Chain),
IO_apS = Apply_apS(IO_Apply),
IO_ApT = IO_of(emptyReadonlyArray),
IO_sequenceArray = (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) : IO_ApT
}
})(function (_, a) {
return f(a)
})
})(function_identity),
IO_io = {
URI: "IO",
map: IO_map,
of: IO_of,
ap: IO_ap,
chain: IO_chain,
fromIO,
chainRec: function (a, f) {
return function () {
for (var e = f(a)(); "Left" === e._tag; ) e = f(e.left)()
return e.right
}
},
},
__assign = function () {
return (__assign =
Object.assign ||
function (t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i]
for (var p in s)
Object.prototype.hasOwnProperty.call(s, p) && (t[p] = s[p])
}
return t
}).apply(this, arguments)
},
T =
((apM = (function (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, Apply)
})((M = IO_io))),
(mapM = (function (F) {
return Functor_map(F, Option_Functor)
})(M)),
(chainM = (function (M) {
var zeroM = OptionT_zero(M)
return function (f) {
return function (ma) {
return M.chain(
ma,
match(function () {
return zeroM()
}, f)
)
}
}
})(M)),
(altM = (function (M) {
var _some = OptionT_some(M)
return function (second) {
return function (first) {
return M.chain(first, match(second, _some))
}
}
})(M)),
(foldM = (function (M) {
return function (onNone, onSome) {
return function (ma) {
return M.chain(ma, match(onNone, onSome))
}
}
})(M)),
(getOrElseM = (function (M) {
return function (onNone) {
return function (fa) {
return M.chain(fa, match(onNone, M.of))
}
}
})(M)),
(zeroM = OptionT_zero(M)),
{
map: function (fa, f) {
return function_pipe(fa, mapM(f))
},
ap: function (fab, fa) {
return function_pipe(fab, apM(fa))
},
of: OptionT_some(M),
chain: function (ma, f) {
return function_pipe(ma, chainM(f))
},
alt: function (fa, that) {
return function_pipe(fa, altM(that))
},
fold: function (fa, onNone, onSome) {
return function_pipe(fa, foldM(onNone, onSome))
},
getOrElse: function (fa, onNone) {
return function_pipe(fa, getOrElseM(onNone))
},
fromM: (function (F) {
return function (ma) {
return F.map(ma, Option_some)
}
})(M),
none: function () {
return zeroM()
},
}),
F = (function (F, G) {
var map = (function (F, G) {
var _map = Functor_map(F, G)
return {
map: function (fga, f) {
return function_pipe(fga, _map(f))
},
}
})(F, G).map,
_compact = Compactable_compact(F, G),
_separate = (function (F, C, G) {
var _compact = Compactable_compact(F, C),
_map = Functor_map(F, G)
return function (fge) {
return Separated_separated(
_compact(function_pipe(fge, _map(getLeft))),
_compact(function_pipe(fge, _map(getRight)))
)
}
})(F, G, G),
_filter = Filterable_filter(F, G),
_filterMap = Filterable_filterMap(F, G),
_partition = (function (F, G) {
var _filter = Filterable_filter(F, G)
return function (predicate) {
var left = _filter(Predicate_not(predicate)),
right = _filter(predicate)
return function (fgb) {
return Separated_separated(left(fgb), right(fgb))
}
}
})(F, G),
_partitionMap = (function (F, G) {
var _filterMap = Filterable_filterMap(F, G)
return function (f) {
return function (fga) {
return Separated_separated(
function_pipe(
fga,
_filterMap(function (a) {
return getLeft(f(a))
})
),
function_pipe(
fga,
_filterMap(function (a) {
return getRight(f(a))
})
)
)
}
}
})(F, G)
return {
map,
compact: _compact,
separate: _separate,
filter: function (fga, f) {
return function_pipe(fga, _filter(f))
},
filterMap: function (fga, f) {
return function_pipe(fga, _filterMap(f))
},
partition: function (fga, p) {
return function_pipe(fga, _partition(p))
},
partitionMap: function (fga, f) {
return function_pipe(fga, _partitionMap(f))
},
}
})(IO_io, Option_option),
IOOption_some = (T.none(), T.of),
IOOption_fromIO = T.fromM,
fromOption = IO_of,
IOOption_map = function (f) {
return function (fa) {
return T.map(fa, f)
}
},
IOOption_chain = function (f) {
return function (ma) {
return T.chain(ma, f)
}
},
IOOption_chainFirst = function (f) {
return function (ma) {
return T.chain(ma, function (a) {
return T.map(f(a), function () {
return a
})
})
}
},
IOOption_filter =
(F.compact,
F.separate,
function (predicate) {
return function (fa) {
return F.filter(fa, predicate)
}
}),
eqStrict =
(T.map,
T.map,
T.ap,
T.map,
T.ap,
T.map,
T.ap,
T.chain,
T.map,
T.alt,
T.map,
T.ap,
T.alt,
T.map,
F.filter,
F.filterMap,
F.partition,
F.partitionMap,
__assign(
{
URI: "IOOption",
of: IOOption_some,
ap: T.ap,
chain: T.chain,
alt: T.alt,
fromIO: IOOption_fromIO,
},
F
),
{
equals: function (a, b) {
return a === b
},
}),
es6_Reader_map = function (f) {
return function (fa) {
return function (r) {
return f(fa(r))
}
}
},
Reader_ApT = constant(emptyReadonlyArray),
Reader_sequenceArray = (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)
})
})(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()
},
ReadonlyArray_map = function (fa, f) {
return function_pipe(fa, es6_ReadonlyArray_map(f))
},
ReadonlyArray_reduce = function (fa, b, f) {
return function_pipe(fa, es6_ReadonlyArray_reduce(b, f))
},
ReadonlyArray_zero = function () {
return ReadonlyArray_empty
},
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)
}
},
ReadonlyArray_compact = (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)
})
})(function_identity),
es6_ReadonlyArray_reduce = function (b, f) {
return es6_ReadonlyArray_reduceWithIndex(b, function (_, b, a) {
return f(b, a)
})
},
es6_ReadonlyArray_foldMap = function (M) {
var foldMapWithIndexM = (function (M) {
return function (f) {
return function (fa) {
return fa.reduce(function (b, a, i) {
return M.concat(b, f(i, a))
}, M.empty)
}
}
})(M)
return function (f) {
return foldMapWithIndexM(function (_, a) {
return f(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
}
},
es6_ReadonlyArray_reduceRight = function (b, f) {
return es6_ReadonlyArray_reduceRightWithIndex(
b,
function (_, a, b) {
return f(a, b)
}
)
},
es6_ReadonlyArray_reduceRightWithIndex = function (b, f) {
return function (fa) {
return fa.reduceRight(function (b, a, i) {
return f(i, a, b)
}, b)
}
},
es6_ReadonlyArray_traverse = function (F) {
var traverseWithIndexF = es6_ReadonlyArray_traverseWithIndex(F)
return function (f) {
return traverseWithIndexF(function (_, a) {
return f(a)
})
}
},
es6_ReadonlyArray_traverseWithIndex = function (F) {
return function (f) {
return es6_ReadonlyArray_reduceWithIndex(
F.of(ReadonlyArray_zero()),
function (i, fbs, a) {
return F.ap(
F.map(fbs, function (bs) {
return function (b) {
return function_pipe(bs, ReadonlyArray_append(b))
}
}),
f(i, a)
)
}
)
}
},
ReadonlyArray_Functor = {
URI: "ReadonlyArray",
map: ReadonlyArray_map,
},
ReadonlyArray_Compactable = {
URI: "ReadonlyArray",
compact: ReadonlyArray_compact,
separate: function (fa) {
for (
var left = [], right = [], _i = 0, fa_1 = fa;
_i < fa_1.length;
_i++
) {
var e = fa_1[_i]
"Left" === e._tag ? left.push(e.left) : right.push(e.right)
}
return Separated_separated(left, right)
},
},
ReadonlyArray_Traversable = {
URI: "ReadonlyArray",
map: ReadonlyArray_map,
reduce: ReadonlyArray_reduce,
foldMap: function (M) {
var foldMapM = es6_ReadonlyArray_foldMap(M)
return function (fa, f) {
return function_pipe(fa, foldMapM(f))
}
},
reduceRight: function (fa, b, f) {
return function_pipe(fa, es6_ReadonlyArray_reduceRight(b, f))
},
traverse: function (F) {
var traverseF = es6_ReadonlyArray_traverse(F)
return function (ta, f) {
return function_pipe(ta, traverseF(f))
}
},
sequence: function (F) {
return function (ta) {
return ReadonlyArray_reduce(
ta,
F.of(ReadonlyArray_zero()),
function (fas, fa) {
return F.ap(
F.map(fas, function (as) {
return function (a) {
return function_pipe(as, ReadonlyArray_append(a))
}
}),
fa
)
}
)
}
},
},
toArray =
(Witherable_witherDefault(
ReadonlyArray_Traversable,
ReadonlyArray_Compactable
),
Witherable_wiltDefault(
ReadonlyArray_Traversable,
ReadonlyArray_Compactable
),
function (as) {
return as.slice()
}),
ReadonlyArray_empty = ReadonlyNonEmptyArray_empty,
ReadonlyArray_bindTo = Functor_bindTo(ReadonlyArray_Functor)
function chainFirstIOK(F, M) {
var chainFirstM = Chain_chainFirst(M)
return function (f) {
return chainFirstM(function_flow(f, F.fromIO))
}
}
var Task_fromIO = function (ma) {
return function () {
return Promise.resolve().then(ma)
}
},
Task_map = function (fa, f) {
return function_pipe(fa, es6_Task_map(f))
},
_apPar = function (fab, fa) {
return function_pipe(fab, Task_ap(fa))
},
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 = chainFirstIOK(
{ URI: "Task", fromIO: Task_fromIO },
Task_Chain
),
Task_bindTo = Functor_bindTo(Task_Functor),
Task_bind = Chain_bind(Task_Chain),
Task_apS = Apply_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")
element.style.pointerEvents = "none"
element.style.zIndex = "30"
element.style.position = "absolute"
element.style.overflow = "hidden"
element.style.height = "100%"
element.style.width = "100%"
return element
},
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 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 = 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),
toArray
)
),
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_chain(
(function (f) {
return function () {
for (var a = [], _i = 0; _i < arguments.length; _i++)
a[_i] = arguments[_i]
return fromOption(f.apply(void 0, a))
}
})(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) },
IO_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
})
),
es6_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))
),
],
IO_sequenceArray,
IOOption_fromIO
)
),
es6_IO_map(Option_isSome)
),
emptyElement = document.createElement("span")
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)
},
MonoidAny = {
concat: function (first, second) {
return first || second
},
empty: !1,
}
const operators = {
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(MonoidAny),
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)
}
},
},
allPreds: Monoid_concatAll({
concat: function (first, second) {
return function_pipe(
first,
(function (second) {
return function (first) {
return function (a) {
return first(a) && second(a)
}
}
})(second)
)
},
empty: constTrue,
}),
anyPreds: Monoid_concatAll({
concat: function (first, second) {
return function_pipe(
first,
(function (second) {
return function (first) {
return function (a) {
return first(a) || second(a)
}
}
})(second)
)
},
empty: constFalse,
}),
inText: text => x => text.content.includes(x),
eqText: text => x => text.content === x,
matchedByText: text => x =>
Boolean(text.content.match(RegExp(x, "u"))),
isVisible: x => x.visible,
},
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?.[authorPhotoMatches.length - 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, mainState, mainLog) =>
function_pipe(
data,
fromPredicate(() =>
function_pipe(
mainState.filterExp,
es6_Option_map(x =>
a(
x,
(data => ({
...operators,
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)
)
),
getOrElse(() => !1)
)
),
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([`Banned: ${x}`])),
match(
() => () => !1,
es6_IO_map(() => !0)
)
)())(data, mainState, 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,
IO_of,
IO_chainFirst(renderChat(flowChat)),
es6_IO_chain(
setChatAnimation(flowChat, flowChats)
),
es6_IO_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)
)
),
es6_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)"
}),
IO_sequenceArray
))(chat)
)
)
),
],
IO_sequenceArray
))()
}),
IO_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)
)
),
es6_IO_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 ("key" === key);
else 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 ||
("class" === key && !(newValue = createClass(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,
{ is: props.is }
)
: document.createElement(vdom.tag, { is: props.is })
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, props, children, type, node) => ({
tag,
props,
key: props.key,
children,
type,
node,
}),
hyperapp_text = (value, node) =>
createVNode(value, EMPTY_OBJ, EMPTY_ARR, 3, node),
h = (tag, props, children = EMPTY_ARR) =>
createVNode(tag, props, 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](dispatch, fx[1]),
update(action[0])
)
: update(action)
))(init),
dispatch
)
}
const src_defaultSettingText = {
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 = lang => key =>
src_defaultSettingText[key]["FYC_EN" === lang ? 0 : 1],
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)),
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))
),
panelBoxStyle = width => ({ flex: `0 0 ${width}px`, margin: "2px" }),
textRowStyle = { width: "70%", boxSizing: "border-box" },
langs = [
["FYC_EN", "English"],
["FYC_JA", "日本語"],
],
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 = (k, v) => [() => setConfig[k](v), void 0],
setState = {
flowY1: (s, v) =>
function_pipe(Math.max(s.flowY2, v + 0.05), flowY2 => [
{ ...s, flowY1: v, flowY2 },
configFx("flowY1", v),
configFx("flowY2", flowY2),
]),
flowY2: (s, v) =>
function_pipe(Math.min(s.flowY1, v - 0.05), flowY1 => [
{ ...s, flowY2: v, flowY1 },
configFx("flowY2", v),
configFx("flowY1", flowY1),
]),
flowX1: (s, v) =>
function_pipe(Math.max(s.flowX2, v + 0.05), flowX2 => [
{ ...s, flowX1: v, flowX2 },
configFx("flowX1", v),
configFx("flowX2", flowX2),
]),
flowX2: (s, v) =>
function_pipe(Math.min(s.flowX1, v - 0.05), flowX1 => [
{ ...s, flowX2: v, flowX1 },
configFx("flowX2", v),
configFx("flowX1", flowX1),
]),
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: { float: "right", margin: "3px 3px 0 0" } },
[
hyperapp_text("🌐"),
h(
"select",
{ onchange: updateString("lang") },
function_pipe(
langs,
es6_ReadonlyArray_map(x =>
ui_option(...x, x[0] === 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.05),
numberNode("flowY2", 0.05, 1, 0.05),
numberNode("flowX1", 0, 0.95, 0.05),
numberNode("flowX2", 0.05, 1, 0.05),
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://gf.qytechs.cn/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),
filterExp: Option_none,
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_fromIO(
() =>
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(IO_sequenceArray)
)
)
)
),
Task_chainFirstIOK(ctx =>
function_pipe(
[
["Version", "1.15.8"],
["User Agent", window.navigator.userAgent],
["UserConfig", JSON.stringify(ctx.userConfig)],
],
es6_ReadonlyArray_map(ctx.mainLog),
IO_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 }),
IO_of,
IO_chainFirst(
x => () => ctx.wrappedSetting.dispatch(x)
),
es6_IO_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.merge)(
function_pipe(
(0, external_rxjs_namespaceObject.merge)(
cs.bannedWordRegexs,
cs.bannedWords,
cs.bannedUsers
),
(0, external_rxjs_namespaceObject.startWith)(void 0),
(0, external_rxjs_namespaceObject.tap)(() => {
ctx.mainState.filterExp = Option_some(
((getConfig = ctx.getConfig),
external_jsep_default()(
`\nor([\nRA.some(anyPreds([\n flip(flow([matchedByText, RA.some]))(${JSON.stringify(
getConfig.bannedWordRegexs()
)}),\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`
))
)
var getConfig
})
),
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,
IO_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.mapTo)({
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.mapTo)({
render: !0,
})
),
function_pipe(
cs.flowSpeed,
(0, external_rxjs_namespaceObject.mapTo)({
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.mapTo)({
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)
),
IO_sequenceArray
)
)
),
IO_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_apS(
"documentMutationPair",
Task_fromIO(observePair(MutationObserver))
),
Task_apS(
"chatMutationPair",
Task_fromIO(observePair(MutationObserver))
),
Task_apS(
"playerResizePair",
Task_fromIO(observePair(ResizeObserver))
),
Task_bind("all$", ctx => {
return function_pipe(
{
css: mainCss(),
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,
},
IO_of,
IO_apS("chatScreen", createChatScreen),
IO_apS("documentMutationPair", observePair(MutationObserver)),
IO_apS("chatMutationPair", observePair(MutationObserver)),
IO_apS("playerResizePair", observePair(ResizeObserver)),
es6_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,
IO_sequenceArray,
es6_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)()
ctx.documentMutationPair.observer.disconnect()
ctx.documentMutationPair.observer.observe(document, {
childList: !0,
subtree: !0,
})
ctx.chatMutationPair.observer.disconnect()
ctx.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
ctx.chatMutationPair.observer.observe(x, {
childList: !0,
})
})
),
function_pipe(
ctx.live.chatTicker.ele,
es6_Option_map(
x => () =>
ctx.chatMutationPair.observer.observe(x, {
childList: !0,
})
)
),
function_pipe(
ctx.live.player.ele,
es6_Option_map(x => () => {
ctx.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
}
)
),
IO_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.mapTo)(
!0
)
),
function_pipe(
(0,
external_rxjs_namespaceObject.fromEvent)(
video,
"waiting"
),
(0, external_rxjs_namespaceObject.mapTo)(
!1
)
),
function_pipe(
(0,
external_rxjs_namespaceObject.fromEvent)(
video,
"pause"
),
(0, external_rxjs_namespaceObject.mapTo)(
!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(
ctx.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(
ctx.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(
ctx.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.retryWhen)(e =>
function_pipe(
e,
(0, external_rxjs_namespaceObject.tap)(
ctx.mixLog(["Errored", e])
),
(0, external_rxjs_namespaceObject.delay)(5e3),
(0, external_rxjs_namespaceObject.tap)(x =>
ctx.mixLog(x)()
),
(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)
}
})()
},
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)
__webpack_require__(142)
})()