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