// ==UserScript==
// @name Flow Youtube Chat
// @version 1.14.10
// @description Youtubeのチャットをニコニコ風に画面上へ流すスクリプトです(再アップ,絵文字バグ修正済み)
// @match https://www.youtube.com/*
// @namespace FlowYoutubeChatScript
// @run-at document-end
// @grant GM.setValue
// @grant GM.getValue
// @grant GM.deleteValue
// @grant GM.listValues
// @noframes
// @license AGPL-3.0-or-later
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/sweetalert2.all.min.js#sha384-OCBhaEdUu7BFgaeRVey2PDeHof2MSQRFe/e6S8Q3XrmSV7wrKpLmhPj8FOldGiaF
// @require https://unpkg.com/[email protected]/dist/loglevel.min.js#sha384-7gGuWfek8Ql6j/uNDFrS0BCe4x2ZihD4B68w9Eu580OVHJBV+bl3rZmEWC7q5/Gj
// @require https://unpkg.com/[email protected]/dist/bundles/rxjs.umd.min.js#sha384-+BwV2u+ZJFwj586/3PlpsZdYS1U/+hT/zpjYSznHH4XzUJqgshDzZITJ+zGeWl//
// @require https://unpkg.com/[email protected]/mithril.min.js#sha384-vo9crXih40MlEv6JWHqS7SsPiFp+76csaWQFOF2UU0/xI58Jm/ZvK/1UtpaicJT9
// @require https://cdn.jsdelivr.net/npm/[email protected]/src/check-types.min.js#sha384-KGnImnhVjA5llfqKEbjBiY+1Mp6oa+NvW/TEY1XTPAKWNgrAwa3Qvn//MXL07wBM
// ==/UserScript==
/* jshint esversion: 6 */
;(() => {
var __webpack_modules__ = {
228: module => {
"use strict"
const createAbortError = () => {
const error = new Error("Delay aborted")
return (error.name = "AbortError"), error
},
createDelay = ({
clearTimeout: defaultClear,
setTimeout: set,
willResolve,
}) => (ms, { value, signal } = {}) => {
if (signal && signal.aborted)
return Promise.reject(createAbortError())
let timeoutId, settle, rejectFn
const clear = defaultClear || clearTimeout,
signalListener = () => {
clear(timeoutId), rejectFn(createAbortError())
},
delayPromise = new Promise((resolve, reject) => {
;(settle = () => {
signal && signal.removeEventListener("abort", signalListener),
willResolve ? resolve(value) : reject(value)
}),
(rejectFn = reject),
(timeoutId = (set || setTimeout)(settle, ms))
})
return (
signal &&
signal.addEventListener("abort", signalListener, { once: !0 }),
(delayPromise.clear = () => {
clear(timeoutId), (timeoutId = null), settle()
}),
delayPromise
)
},
delay = createDelay({ willResolve: !0 })
;(delay.reject = createDelay({ willResolve: !1 })),
(delay.range = (minimum, maximum, options) =>
delay(
((minimum, maximum) =>
Math.floor(Math.random() * (maximum - minimum + 1) + minimum))(
minimum,
maximum
),
options
)),
(delay.createWithTimers = ({ clearTimeout, setTimeout }) => {
const delay = createDelay({
clearTimeout,
setTimeout,
willResolve: !0,
})
return (
(delay.reject = createDelay({
clearTimeout,
setTimeout,
willResolve: !1,
})),
delay
)
}),
(module.exports = delay),
(module.exports.default = delay)
},
238: module => {
function monadic(fn, cache, serializer, arg) {
var value,
cacheKey =
null == (value = arg) ||
"number" == typeof value ||
"boolean" == typeof value
? arg
: serializer(arg),
computedValue = cache.get(cacheKey)
return (
void 0 === computedValue &&
((computedValue = fn.call(this, arg)),
cache.set(cacheKey, computedValue)),
computedValue
)
}
function variadic(fn, cache, serializer) {
var args = Array.prototype.slice.call(arguments, 3),
cacheKey = serializer(args),
computedValue = cache.get(cacheKey)
return (
void 0 === computedValue &&
((computedValue = fn.apply(this, args)),
cache.set(cacheKey, computedValue)),
computedValue
)
}
function assemble(fn, context, strategy, cache, serialize) {
return strategy.bind(context, fn, cache, serialize)
}
function strategyDefault(fn, options) {
return assemble(
fn,
this,
1 === fn.length ? monadic : variadic,
options.cache.create(),
options.serializer
)
}
function serializerDefault() {
return JSON.stringify(arguments)
}
function ObjectWithoutPrototypeCache() {
this.cache = Object.create(null)
}
;(ObjectWithoutPrototypeCache.prototype.has = function (key) {
return key in this.cache
}),
(ObjectWithoutPrototypeCache.prototype.get = function (key) {
return this.cache[key]
}),
(ObjectWithoutPrototypeCache.prototype.set = function (key, value) {
this.cache[key] = value
})
var cacheDefault = {
create: function () {
return new ObjectWithoutPrototypeCache()
},
}
;(module.exports = function (fn, options) {
var cache = options && options.cache ? options.cache : cacheDefault,
serializer =
options && options.serializer
? options.serializer
: serializerDefault
return (options && options.strategy
? options.strategy
: strategyDefault)(fn, { cache, serializer })
}),
(module.exports.strategies = {
variadic: function (fn, options) {
return assemble(
fn,
this,
variadic,
options.cache.create(),
options.serializer
)
},
monadic: function (fn, options) {
return assemble(
fn,
this,
monadic,
options.cache.create(),
options.serializer
)
},
})
},
},
__webpack_module_cache__ = {}
function __webpack_require__(moduleId) {
if (__webpack_module_cache__[moduleId])
return __webpack_module_cache__[moduleId].exports
var module = (__webpack_module_cache__[moduleId] = { exports: {} })
return (
__webpack_modules__[moduleId](
module,
module.exports,
__webpack_require__
),
module.exports
)
}
;(__webpack_require__.n = module => {
var getter =
module && module.__esModule ? () => module.default : () => module
return __webpack_require__.d(getter, { a: getter }), 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)
},
external_rxjs_namespaceObject = rxjs,
external_rxjs_operators_namespaceObject = rxjs.operators,
package_namespaceObject_i8 = "1.14.10",
addMainCss = () => {
let styleHtml = ""
;(styleHtml +=
".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 }"),
(styleHtml +=
".fyc_chat > img {\n vertical-align: text-top;\n }"),
(styleHtml +=
".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 }"),
external_log_default().debug("AppendCss")
const existedElement = document.querySelector(".fyc_style"),
styleElement =
null != existedElement
? existedElement
: document.createElement("style")
existedElement ||
(document.head.append(styleElement),
styleElement.classList.add(".fyc_style")),
(styleElement.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 }.fyc_chat > img {\n vertical-align: text-top;\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 }")
},
external_m_namespaceObject = m
var external_m_default = __webpack_require__.n(external_m_namespaceObject)
const external_Swal_namespaceObject = Swal
var external_Swal_default = __webpack_require__.n(
external_Swal_namespaceObject
)
const createBanButton = (chat, id, userConfig, mainLog) => {
var _a, _b
if (chat.children.namedItem("card")) return
const button = document.createElement("button")
button.classList.add(
"style-scope",
"yt-icon-button",
"fyc_button",
"fyc_ngbutton"
),
(button.style.padding = "0px"),
(button.style.width = "20px"),
(button.style.height = "20px"),
(button.style.fill = "#fff"),
button.setAttribute("aria-label", "NGに入れる"),
(button.innerHTML =
'<div style="width: 100%; height: 75%;fill: var(--yt-spec-text-secondary);"><svg class="style-scope yt-icon" width="100%" height="100%" version="1.1" viewBox="0 0 512 512" x="0px" y="0px"><path d="m437.02 74.977c-99.984-99.969-262.06-99.969-362.05 0-99.969 99.984-99.969 262.06 0 362.05 99.969 99.969 262.08 99.969 362.05 0s99.969-262.08 0-362.05zm-299.81 62.234c54.391-54.391 137.02-63.453 201.02-27.531l-228.55 228.55c-35.922-64-26.86-146.62 27.531-201.02zm237.59 237.58c-54.391 54.391-137.03 63.469-201.03 27.547l228.56-228.56c35.921 64 26.843 146.64-27.532 201.02z" fill-rule="evenodd"></path></svg></div>'),
(button.onclick = () => {
mainLog(`Added to Banned Users: ${id}`),
userConfig.bannedUsers.set([
...userConfig.bannedUsers.get().slice(),
id,
]),
external_m_default().redraw(),
(chat.style.display = "none"),
external_Swal_default()
.mixin({
toast: !0,
position: "bottom-left",
timer: 2500,
timerProgressBar: !0,
showConfirmButton: !1,
didOpen: toast => {
toast.addEventListener(
"mouseenter",
external_Swal_default().stopTimer
),
toast.addEventListener(
"mouseleave",
external_Swal_default().resumeTimer
)
},
})
.fire({ title: `Added Banned User: ${id}`, icon: "success" })
}),
external_log_default().debug("AppendNgButton"),
null ===
(_b =
null === (_a = chat.querySelector("#content")) || void 0 === _a
? void 0
: _a.querySelector("#message")) ||
void 0 === _b ||
_b.append(button)
}
var src = __webpack_require__(238),
src_default = __webpack_require__.n(src)
function function_pipe(
a,
ab,
bc,
cd,
de,
ef,
fg,
gh,
hi,
ij,
jk,
kl,
lm,
mn,
no,
op,
pq,
qr,
rs,
st
) {
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))))))))
case 10:
return ij(hi(gh(fg(ef(de(cd(bc(ab(a)))))))))
case 11:
return jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a))))))))))
case 12:
return kl(jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a)))))))))))
case 13:
return lm(kl(jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a))))))))))))
case 14:
return mn(lm(kl(jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a)))))))))))))
case 15:
return no(mn(lm(kl(jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a))))))))))))))
case 16:
return op(no(mn(lm(kl(jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a)))))))))))))))
case 17:
return pq(
op(no(mn(lm(kl(jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a)))))))))))))))
)
case 18:
return qr(
pq(op(no(mn(lm(kl(jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a))))))))))))))))
)
case 19:
return rs(
qr(
pq(
op(no(mn(lm(kl(jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a)))))))))))))))
)
)
)
case 20:
return st(
rs(
qr(
pq(
op(
no(mn(lm(kl(jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a))))))))))))))
)
)
)
)
)
}
}
var isNone = function (fa) {
return "None" === fa._tag
},
none = { _tag: "None" },
some = function (a) {
return { _tag: "Some", value: a }
}
var getOrElse = function (onNone) {
return function (ma) {
return isNone(ma) ? onNone() : ma.value
}
}
var empty = []
const getChatLane = (
flowChat,
progress,
flowChats,
mainState,
userConfig
) => {
const chatIndex = flowChats.indexOf(flowChat),
playerWidth = mainState.playerRect.width,
playerX = mainState.playerRect.x,
chatRect = flowChat.element.getBoundingClientRect(),
chatWidth = chatRect.width,
chatHeight = chatRect.height,
chatX = progress ? chatRect.x - playerX : playerWidth,
movingChats = (function (as) {
var l = as.length
if (0 === l) return empty
for (var ras = Array(l), i = 0; i < l; i++) ras[i] = as[i]
return ras
})(
flowChats
.slice(0, chatIndex >= 0 ? chatIndex : void 0)
.filter(chat => !chat.animationEnded)
.sort((a, b) => a.lane - b.lane)
),
tooCloseTo = src_default()(i => {
const otherRect = movingChats[i].element.getBoundingClientRect(),
otherWidth = otherRect.width,
otherX = otherRect.x - playerX,
gap =
(chatHeight * otherWidth * chatWidth) ** 0.333 *
userConfig.minSpacing.get()
return (
(playerWidth - otherX) / (playerWidth + otherWidth) - progress <
(chatWidth + gap) / (playerWidth + chatWidth) ||
otherX + otherWidth + gap > chatX
)
}),
occupyInfo = [
...movingChats.map((x, i) => ({
tooClose: () => tooCloseTo(i),
lane: x.lane,
})),
{ tooClose: () => !0, lane: userConfig.laneCount.get() },
],
index = occupyInfo.findIndex(x => x.lane >= flowChat.lane),
rightFreeLane = occupyInfo
.slice(index)
.findIndex(x => x.tooClose()),
leftFreeLane = function_pipe(
occupyInfo.slice(0, index),
((predicate = x => x.tooClose()),
function (as) {
for (var i = as.length - 1; i >= 0; i--)
if (predicate(as[i])) return some(i)
return none
}),
getOrElse(() => -1)
)
var predicate
let formerLaneInterval = 0
leftFreeLane < flowChat.lane &&
flowChat.lane < rightFreeLane &&
(formerLaneInterval = Math.min(
Math.max(
formerLaneInterval,
Math.min(
flowChat.lane - leftFreeLane,
rightFreeLane - flowChat.lane
)
),
1
))
let maxInterval = 0,
maxIntervalLane = 0,
lastLane = -1
for (let i = 0; i < occupyInfo.length; i += 1)
if (occupyInfo[i].tooClose()) {
const nextLane = occupyInfo[i].lane,
interLane = Math.min(
Math.max((lastLane + nextLane) / 2, 0),
userConfig.laneCount.get() - 1
),
newInterval = Math.min(
interLane - lastLane,
nextLane - interLane,
1
)
if (
newInterval - maxInterval > 0.001 &&
((maxIntervalLane = Math.max(lastLane + newInterval, 0)),
(maxInterval = newInterval),
maxInterval > 0.999)
)
break
lastLane = nextLane
}
return {
lane:
Math.abs(formerLaneInterval - maxInterval) < 0.001
? flowChat.lane
: maxIntervalLane,
interval: maxInterval,
}
},
setChatPlayState = (flowChat, mainState, userConfig) => {
!flowChat.animationEnded &&
flowChat.animation &&
(mainState.chatPlaying
? flowChat.animation.play()
: flowChat.animation.pause(),
(flowChat.animation.playbackRate = userConfig.flowSpeed.get() / 15))
},
setChatAnimation = (flowChat, flowChats, mainState, userConfig) => {
var _a, _b, _c
if (flowChat.animationEnded) return !1
const time =
null !==
(_b =
null === (_a = flowChat.animation) || void 0 === _a
? void 0
: _a.currentTime) && void 0 !== _b
? _b
: void 0,
progress = void 0 !== time ? time / flowChat.animationDuration : 0,
{ lane, interval } = getChatLane(
flowChat,
progress,
flowChats,
mainState,
userConfig
)
if (userConfig.noOverlap.get() && interval < 0.999)
return (
null === (_c = flowChat.animation) ||
void 0 === _c ||
_c.finish(),
(flowChat.animation = void 0),
!1
)
flowChat.lane = lane
const laneY = ((lane, mainState, userConfig) => {
const laneCount = userConfig.laneCount.get(),
laneR = lane % (2 * laneCount - 1),
playerHeight = mainState.playerRect.height
return (
Math.round(
100 *
(laneR < laneCount
? (playerHeight * (laneR % laneCount)) / laneCount + 4
: playerHeight *
((laneR % laneCount) / laneCount + 1 / (2 * laneCount)))
) / 100
)
})(flowChat.lane, mainState, userConfig)
flowChat.animation && flowChat.animation.cancel(),
(flowChat.animationDuration = 6400),
(flowChat.animation = flowChat.element.animate(
[
{
transform: `translate(${mainState.playerRect.width}px, ${laneY}px)`,
},
{
transform: `translate(${-flowChat.element.getBoundingClientRect()
.width}px, ${laneY}px)`,
},
],
{ duration: 6400, easing: userConfig.timingFunction.get() }
)),
(flowChat.animation.onfinish = () => {
flowChat.animationEnded = !0
})
const newTime = void 0 !== time ? 6400 * progress : 0
return (
(flowChat.animation.currentTime = newTime),
setChatPlayState(flowChat, mainState, userConfig),
!0
)
},
setChatStyle = (flowChat, mainState, userConfig) => {
const fontSize = ((mainState, userConfig) =>
Math.round(
Math.max(userConfig.fontSize.get() - 0.2, 0.01) *
(mainState.playerRect.height / userConfig.laneCount.get()) *
100
) / 100)(mainState, userConfig),
{ style } = flowChat.element
;(style.visibility = userConfig.displayChats.get()
? "visible"
: "hidden"),
(style.color =
"owner" === flowChat.authorType
? userConfig.ownerColor.get()
: "moderator" === flowChat.authorType
? userConfig.moderatorColor.get()
: "member" === flowChat.authorType
? userConfig.memberColor.get()
: userConfig.color.get()),
(style.fontSize = `${fontSize}px`),
(style.fontWeight = userConfig.fontWeight.get().toString()),
(style.fontFamily = userConfig.font.get()),
(style.opacity = userConfig.chatOpacity.get().toString())
const offset = userConfig.shadowFontWeight.get()
;(style.textShadow = `-${offset}px -${offset}px #0009, ${offset}px -${offset}px #0009, -${offset}px ${offset}px #0009, ${offset}px ${offset}px #0009`),
(style.transform = `translate(${mainState.playerRect.width}px)`)
},
assert_lib = check.assert,
tapNonNull = x => (assert_lib(null != x), x),
parseMessage = (lengthBefore, message, userConfig) => {
const maxChatLength = userConfig.maxChatLength.get(),
vnodes = []
let semantic = "",
length = lengthBefore
return (
message.innerHTML.split(/(?=<img )|">/g).some(part => {
if (part.match(/^<img /)) {
if (!userConfig.textOnly.get()) {
const srcMatch = part.match(
/<img\s.*?src=(?:'|")([^'">]+)(?:'|")/
),
altMatch = part.match(
/<img\s.*?alt=(?:'|")([^'">]+)(?:'|")/
),
src =
null == srcMatch ? void 0 : srcMatch[srcMatch.length - 1],
alt =
null == altMatch ? void 0 : altMatch[altMatch.length - 1]
vnodes.push(
external_m_default()("img", {
style: { height: "1em", width: "1em" },
src,
alt,
})
),
(semantic += `<img alt="${null != alt ? alt : ""}">`),
(length += 1)
}
} else {
const text =
part.length >= maxChatLength
? part.substr(0, maxChatLength)
: part
vnodes.push(external_m_default().fragment({}, text)),
(semantic += text),
(length += text.length)
}
return length >= maxChatLength
}),
{ vnodes, semantic, length }
)
},
chatFieldObserver = (
chatScrn,
flowChats,
mainState,
userConfig,
mainLog
) =>
new MutationObserver(mutations => {
mutations.forEach(e => {
Array.from(e.addedNodes)
.filter(x => x.children.length > 0)
.forEach(chat => {
var _a
const chatData = ((chat, userConfig) => {
let semantic = "",
length = 0
const vnodes = []
let authorID
const authorType = chat.querySelector(".owner")
? "owner"
: chat.querySelector(".moderator")
? "moderator"
: chat.querySelector(".member")
? "member"
: "normal"
return (
Array.from(chat.children).forEach(child => {
var _a, _b, _c, _d
const childID = child.id,
message = child.querySelector("#message"),
authorName = child.querySelector("#author-name")
if ("content" === childID) {
if (
(chat.querySelector(".moderator") &&
userConfig.displayModName.get() &&
vnodes.push(
external_m_default()(
"span",
{ style: { fontSize: "smaller" } },
`${
null !==
(_a =
null == authorName
? void 0
: authorName.innerText) &&
void 0 !== _a
? _a
: ""
}: `
)
),
message)
) {
const result = parseMessage(
length,
message,
userConfig
)
vnodes.push(...result.vnodes),
(semantic += result.semantic),
(length += result.length)
}
} else if ("author-photo" === childID) {
const matches = (null !==
(_c =
null === (_b = child.lastElementChild) ||
void 0 === _b
? void 0
: _b.getAttribute("src")) && void 0 !== _c
? _c
: ""
).match(/ytc\/(.*)=/)
authorID =
null == matches
? void 0
: matches[matches.length - 1]
} else if ("card" === childID) {
const normalChat = child.matches(
[
".style-scope",
".yt-live-chat-paid-message-renderer",
].join("")
),
stickerChat = child.matches(
[
".style-scope",
".yt-live-chat-paid-sticker-renderer",
].join("")
)
if (normalChat || stickerChat) {
const paidAmount = tapNonNull(
child.querySelector("#purchase-amount") ||
child.querySelector("#purchase-amount-chip")
)
authorID = void 0
const headerColor = normalChat
? window
.getComputedStyle(
tapNonNull(
child.querySelector("#header")
)
)
.getPropertyValue("background-color")
: window
.getComputedStyle(chat)
.getPropertyValue(
"--yt-live-chat-paid-sticker-chip-background-color"
),
paidColor = normalChat
? window
.getComputedStyle(
tapNonNull(
child.querySelector("#content")
)
)
.getPropertyValue("background-color")
: window
.getComputedStyle(chat)
.getPropertyValue(
"--yt-live-chat-paid-sticker-background-color"
)
if (
(userConfig.displaySuperChatAuthor.get() &&
vnodes.push(
external_m_default()(
"span",
{
style: {
color: headerColor,
fontSize: "smaller",
fontFamily: "inherit",
},
},
`${
null !==
(_d =
null == authorName
? void 0
: authorName.innerText) &&
void 0 !== _d
? _d
: ""
}: `
)
),
normalChat && message)
) {
const result = parseMessage(
length,
message,
userConfig
)
vnodes.push(
external_m_default()(
"span",
{
style: {
color: headerColor,
fontFamily: "inherit",
},
},
result.vnodes
)
),
(semantic += result.semantic),
(length += result.length)
}
;(length += paidAmount.innerText.length),
vnodes.push(
external_m_default()(
"span",
{
style: {
color: paidColor,
fontSize: "smaller",
fontFamily: "inherit",
},
},
external_m_default()(
"strong",
{ style: { fontFamily: "inherit" } },
paidAmount.innerText
)
)
)
}
}
}),
{ vnodes, semantic, authorType, authorID }
)
})(chat, userConfig),
semanticTextContent =
null !==
(_a = new DOMParser().parseFromString(
`<span>${chatData.semantic}<span>`,
"text/html"
).body.textContent) && void 0 !== _a
? _a
: ""
;((content, userConfig, mainLog) =>
userConfig.bannedWords
.get()
.some(
word =>
!!content.includes(word) &&
(mainLog(`Banned Word: "${word}" in "${content}"`),
!0)
))(semanticTextContent, userConfig, mainLog) ||
((content, userConfig, mainLog) =>
userConfig.bannedWordRegexs.get().some(word => {
const result = content.match(RegExp(word, "u"))
return (
!!result &&
(mainLog(
`Banned Word: "${result.toString()}" in "${content}"`
),
!0)
)
}))(semanticTextContent, userConfig, mainLog) ||
(void 0 !== chatData.authorID &&
((authorID, userConfig, mainLog) =>
userConfig.bannedUsers
.get()
.some(
user =>
!(
authorID !== user ||
(mainLog(`Banned User: "${authorID}"`), 0)
)
))(chatData.authorID, userConfig, mainLog))
? (chat.style.display = "none")
: (userConfig.createChats.get() &&
((
chatData,
flowChats,
chatScrn,
mainState,
userConfig
) => {
var _a
let element
const offScreenChatIndex = flowChats.findIndex(
chat =>
chat.animationEnded ||
flowChats.length >= userConfig.maxChatCount.get()
)
if (-1 !== offScreenChatIndex) {
element = flowChats[offScreenChatIndex].element
const [oldChat] = flowChats.splice(
offScreenChatIndex,
1
)
null === (_a = oldChat.animation) ||
void 0 === _a ||
_a.cancel()
} else
external_log_default().debug("CreateFlowChat"),
(element = document.createElement("span")),
chatScrn.append(element)
element.classList.add("fyc_chat")
const flowChat = {
element,
lane: -1,
animation: void 0,
animationDuration: 0,
animationEnded: !1,
authorType: chatData.authorType,
}
external_m_default().render(element, chatData.vnodes),
setChatStyle(flowChat, mainState, userConfig),
setChatAnimation(
flowChat,
flowChats,
mainState,
userConfig
)
? flowChats.push(flowChat)
: flowChat.element.remove()
})(
chatData,
flowChats,
chatScrn,
mainState,
userConfig
),
userConfig.createBanButton.get() &&
void 0 !== chatData.authorID &&
!chat.querySelector(".owner") &&
createBanButton(
chat,
chatData.authorID,
userConfig,
mainLog
),
userConfig.simplifyChatField.get() &&
(chat => {
if (
chat.querySelector(
".style-scope.yt-live-chat-paid-message-renderer"
) ||
chat.querySelector(".owner")
)
return
chat.style.borderBottom =
"1px solid var(--yt-spec-text-secondary)"
const authorPhoto = chat.querySelector(
"#author-photo"
)
authorPhoto && (authorPhoto.style.display = "none")
const authorChip = chat.querySelector(
"yt-live-chat-author-chip.style-scope.yt-live-chat-text-message-renderer"
)
authorChip && (authorChip.style.display = "none")
})(chat))
})
})
}),
componentMounter = (root, placeRoot) => component => {
root.style.display = "contents"
const success = placeRoot(root)
return success && external_m_default().mount(root, component), success
}
class IndirectConfigItem {
constructor(x) {
;(this.gmKey = x.gmKey),
(this.defaultVal = x.defaultVal),
(this.val = x.val),
(this.toGm = x.toGm)
}
get() {
return this.val
}
async set(val) {
return (this.val = val), GM.setValue(this.gmKey, this.toGm(val))
}
}
const makeConfigItem = async (gmKey, defaultVal, toItem, toGm) => {
const val = await GM.getValue(gmKey)
return new IndirectConfigItem({
gmKey,
val: void 0 !== val ? toItem(val) : defaultVal,
defaultVal,
toGm,
})
},
simpleConfigItem = async (gmKey, defaultVal) => {
var _a
return new IndirectConfigItem({
gmKey,
val:
null !== (_a = await GM.getValue(gmKey)) && void 0 !== _a
? _a
: defaultVal,
defaultVal,
toGm: x => x,
})
},
lineConfigArgs = [
[],
x => x.split(/\r\n|\n/).filter(s => "" !== s),
x => x.join("\n"),
],
livePage_getPlayer = () => {
var _a
return null !== (_a = document.querySelector("#movie_player")) &&
void 0 !== _a
? _a
: void 0
},
livePage_getMainVideo = () => {
var _a
return null !==
(_a = document.querySelector(
"video.video-stream.html5-main-video"
)) && void 0 !== _a
? _a
: void 0
},
livePage_getChatFrame = () => {
var _a
return null !== (_a = document.querySelector("#chatframe")) &&
void 0 !== _a
? _a
: void 0
},
livePage_getChatField = () => {
var _a, _b, _c
return null !==
(_c = (null !==
(_b =
null === (_a = document.querySelector("#chatframe")) ||
void 0 === _a
? void 0
: _a.contentDocument) && void 0 !== _b
? _b
: document
).querySelector(
"#items.style-scope.yt-live-chat-item-list-renderer"
)) && void 0 !== _c
? _c
: void 0
},
livePage_getOfflineSlate = () => {
var _a
return null !== (_a = document.querySelector(".ytp-offline-slate")) &&
void 0 !== _a
? _a
: void 0
},
removeOldChats = (flowChats, maxChatCount) => {
flowChats.sort((a, b) =>
a.animationEnded === b.animationEnded
? 0
: a.animationEnded
? -1
: 1
),
flowChats
.splice(0, Math.max(0, flowChats.length - maxChatCount))
.forEach(x => {
external_log_default().debug("RemoveChat"), x.element.remove()
})
}
var delay = __webpack_require__(228),
delay_default = __webpack_require__.n(delay)
const setChatFrameCss = async mainLog => (
await delay_default()(700),
(async (func, count, interval, mainLog) => {
let exception,
succeed = !1
for (let i = 0; i < count; i += 1) {
try {
await func(i), (succeed = !0)
break
} catch (e) {
exception = e
}
mainLog("Retry"), await delay_default()(interval)
}
if (!succeed) throw exception
})(
() => {
var _a, _b
const element =
null ===
(_b =
null === (_a = document.querySelector("#chatframe")) ||
void 0 === _a
? void 0
: _a.contentDocument) || void 0 === _b
? void 0
: _b.querySelector(
"#item-scroller.animated.yt-live-chat-item-list-renderer #item-offset.yt-live-chat-item-list-renderer"
)
element && (element.style.overflow = "unset")
},
5,
1e3,
mainLog
)
),
settingPanel_option = (value, label) =>
external_m_default()("option", { value }, label),
settingRow = (label, content) =>
external_m_default()("div", [
external_m_default()("span", label),
external_m_default()("div", content),
]),
rangeRow = (min, max, step, value, oninput) =>
external_m_default()("div", [
external_m_default()("input", {
style: { width: "150px", verticalAlign: "middle" },
type: "range",
min,
max,
step,
value,
oninput,
}),
external_m_default()("input", {
style: {
width: "30px",
backgroundColor: "transparent",
color: "inherit",
borderWidth: "1px",
verticalAlign: "middle",
},
inputmode: "decimal",
value,
onchange: oninput,
}),
]),
checkboxRow = (label, checked, onchange) =>
external_m_default()(
"div",
external_m_default()("label", [
label,
external_m_default()("input", {
type: "checkbox",
checked,
onchange,
}),
])
),
getInputValue = e => {
const target = e.currentTarget
if (
target instanceof HTMLSelectElement ||
target instanceof HTMLTextAreaElement ||
target instanceof HTMLInputElement
)
return target.value
throw Error(
"Event target isn't an Input or TextArea or Input element"
)
},
getInputChecked = e => {
return ((constructor = HTMLInputElement),
(x = e.currentTarget),
assert_lib(x instanceof constructor),
x).checked
var constructor, x
},
langOptions = [
["FYC_EN", "English"],
["FYC_JA", "日本語"],
],
fontOptions = [
["", "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", "游ゴシック体"],
],
settingPanel = (flowChats, mainState, state, userConfig, mainLog) => {
var _a, _b
const panelState = {
bannedWordRegexs: userConfig.bannedWordRegexs.get(),
bannedWordRegexsValid: !0,
bannedWordRegexsError: "",
currentTab: 0,
timingStepCount: parseInt(
null !==
(_b =
null ===
(_a = userConfig.timingFunction
.get()
.match(/^steps\((\d+),.+/)) || void 0 === _a
? void 0
: _a[1]) && void 0 !== _b
? _b
: "150",
10
),
},
stepTiming = stepCount => `steps(${stepCount}, jump-end)`,
useStepTiming = () =>
Boolean(userConfig.timingFunction.get().match(/^steps\(.+/)),
panelBoxStyle = width => ({
flex: `0 0 ${width}px`,
margin: "2px",
}),
textAreaStyle = {
resize: "horizontal",
boxSizing: "border-box",
width: "100%",
},
textRecord = {
FYC_EN: {
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",
bannedWordRegexs: "Banned Words(Regex)",
bannedUsers: "Banned Users",
simplifyChatField: "Simplify",
createBanButton: "Show ban button",
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",
},
FYC_JA: {
font: "フォント",
color: "色(通常)",
ownerColor: "色(オーナー)",
moderatorColor: "色(モデレーター)",
memberColor: "色(メンバー)",
feedback: "バグ報告と要望",
eventLog: "イベントログ",
giveFeedback:
"バグ報告、要望はこちら(バグの場合は、イベントログを添付してください)",
chatOpacity: "不透明度",
fontSize: "サイズ",
fontWeight: "太さ",
shadowFontWeight: "太さ(影)",
flowSpeed: "速度",
maxChatCount: "最大表示数",
maxChatLength: "最大文字数",
laneCount: "行数",
bannedWords: "NGワード",
bannedWordRegexs: "NGワード(正規表現)",
bannedUsers: "NGユーザー",
simplifyChatField: "簡略化する",
createBanButton: "NGボタンを表示する",
displayModName: "モデレータの名前を表示する",
displaySuperChatAuthor: "スパチャの作成者を表示する",
createChats: "チャットを流す",
textOnly: "文字のみ(絵文字を無視する)",
error: "エラー",
video: "画面",
chatField: "チャット欄",
useStepTiming: "チャットを段階的に動かす",
timingStepCount: "└段階数",
chatFilter: "チャットフィルター",
flowChat: "チャット流れ",
clearFlowChats: "流れるチャットをクリアする",
flowNewChatIf:
"新しいチャットは以下のすべてを満たす場合に流れます:",
noOverlap: "└他のチャットと重ならない",
minSpacing: "チャットの最小間隔",
},
},
getLang = () => textRecord[userConfig.lang.get()],
ss = {
str: {
lang: new external_rxjs_namespaceObject.Subject(),
font: new external_rxjs_namespaceObject.Subject(),
color: new external_rxjs_namespaceObject.Subject(),
ownerColor: new external_rxjs_namespaceObject.Subject(),
moderatorColor: new external_rxjs_namespaceObject.Subject(),
memberColor: new external_rxjs_namespaceObject.Subject(),
},
num: {
chatOpacity: new external_rxjs_namespaceObject.Subject(),
fontSize: new external_rxjs_namespaceObject.Subject(),
fontWeight: new external_rxjs_namespaceObject.Subject(),
shadowFontWeight: new external_rxjs_namespaceObject.Subject(),
flowSpeed: new external_rxjs_namespaceObject.Subject(),
minSpacing: new external_rxjs_namespaceObject.Subject(),
},
int: {
maxChatCount: new external_rxjs_namespaceObject.Subject(),
maxChatLength: new external_rxjs_namespaceObject.Subject(),
laneCount: new external_rxjs_namespaceObject.Subject(),
},
tabChange: new external_rxjs_namespaceObject.Subject(),
bannedWords: new external_rxjs_namespaceObject.Subject(),
bannedWordRegexs: new external_rxjs_namespaceObject.Subject(),
bannedUsers: new external_rxjs_namespaceObject.Subject(),
bl: {
createChats: new external_rxjs_namespaceObject.Subject(),
textOnly: new external_rxjs_namespaceObject.Subject(),
displayModName: new external_rxjs_namespaceObject.Subject(),
displaySuperChatAuthor: new external_rxjs_namespaceObject.Subject(),
noOverlap: new external_rxjs_namespaceObject.Subject(),
simplifyChatField: new external_rxjs_namespaceObject.Subject(),
createBanButton: new external_rxjs_namespaceObject.Subject(),
},
useStepTiming: new external_rxjs_namespaceObject.Subject(),
timingStepCount: new external_rxjs_namespaceObject.Subject(),
clearFlowChats: new external_rxjs_namespaceObject.Subject(),
},
checkboxNode = label =>
checkboxRow(
getLang()[label],
userConfig[label].get(),
lib(ss.bl[label])
),
textColorNode = label => {
return settingRow(getLang()[label], [
((color = userConfig[label].get()),
(textStyle = {
fontFamily: userConfig.font.get(),
fontWeight: userConfig.fontWeight.get().toString(),
}),
(oninput = lib(ss.str[label])),
external_m_default()("div", [
external_m_default()("input", {
style: { width: "36px", verticalAlign: "middle" },
type: "color",
value: color,
oninput,
}),
external_m_default()("input", {
style: { verticalAlign: "middle" },
type: "text",
size: 8,
maxlength: 20,
value: color,
oninput,
}),
external_m_default()(
"span",
{ style: { ...textStyle, color } },
"Aa1あア亜"
),
])),
])
var color, textStyle, oninput
},
rangeNode = (label, streams, min, max, step) =>
settingRow(getLang()[label], [
rangeRow(
min,
max,
step,
userConfig[label].get(),
lib(streams[label])
),
]),
updateStringMacro = key => {
return (
(stream = ss.str[key]),
(configKey = key),
stream.pipe(
(0, external_rxjs_operators_namespaceObject.map)(
getInputValue
),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
userConfig[configKey].set(x)
})
)
)
var stream, configKey
},
updateNumberMacro = key => {
return (
(stream = ss.num[key]),
(configKey = key),
stream.pipe(
(0, external_rxjs_operators_namespaceObject.map)(
getInputValue
),
(0, external_rxjs_operators_namespaceObject.map)(parseFloat),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
userConfig[configKey].set(x)
})
)
)
var stream, configKey
},
updateIntMacro = key => {
return (
(stream = ss.int[key]),
(configKey = key),
stream.pipe(
(0, external_rxjs_operators_namespaceObject.map)(
getInputValue
),
(0, external_rxjs_operators_namespaceObject.map)(x =>
parseInt(x, 10)
),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
userConfig[configKey].set(x)
})
)
)
var stream, configKey
},
updateBoolMacro = key => {
return (
(stream = ss.bl[key]),
(configKey = key),
stream.pipe(
(0, external_rxjs_operators_namespaceObject.map)(
getInputChecked
),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
userConfig[configKey].set(x)
})
)
)
var stream, configKey
}
return (
(0, external_rxjs_namespaceObject.merge)(
(0, external_rxjs_namespaceObject.merge)(
(0, external_rxjs_namespaceObject.merge)(
updateStringMacro("font"),
updateNumberMacro("fontSize"),
updateNumberMacro("fontWeight"),
updateIntMacro("laneCount"),
updateNumberMacro("minSpacing")
).pipe(
(0, external_rxjs_operators_namespaceObject.mapTo)({
setStyle: !0,
setAnimation: !0,
})
),
(0, external_rxjs_namespaceObject.merge)(
updateStringMacro("color"),
updateStringMacro("ownerColor"),
updateStringMacro("moderatorColor"),
updateStringMacro("memberColor"),
updateNumberMacro("chatOpacity"),
updateNumberMacro("shadowFontWeight")
).pipe(
(0, external_rxjs_operators_namespaceObject.mapTo)({
setStyle: !0,
})
),
(0, external_rxjs_namespaceObject.merge)(
updateNumberMacro("flowSpeed")
).pipe(
(0, external_rxjs_operators_namespaceObject.mapTo)({
setPlayState: !0,
})
),
(0, external_rxjs_namespaceObject.merge)(
updateIntMacro("maxChatCount").pipe(
(0, external_rxjs_operators_namespaceObject.tap)(x =>
removeOldChats(flowChats, x)
)
),
updateBoolMacro("noOverlap"),
ss.useStepTiming.pipe(
(0, external_rxjs_operators_namespaceObject.map)(
getInputChecked
),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
userConfig.timingFunction.set(
x ? stepTiming(panelState.timingStepCount) : "linear"
)
})
),
ss.timingStepCount.pipe(
(0, external_rxjs_operators_namespaceObject.map)(
getInputValue
),
(0, external_rxjs_operators_namespaceObject.map)(x =>
parseInt(x, 10)
),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
;(panelState.timingStepCount = x),
userConfig.timingFunction.set(stepTiming(x))
})
)
).pipe(
(0, external_rxjs_operators_namespaceObject.mapTo)({
setAnimation: !0,
})
)
).pipe(
(0, external_rxjs_operators_namespaceObject.throttleTime)(
180,
void 0,
{ leading: !0, trailing: !0 }
),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
flowChats
.filter(chat => !chat.animationEnded)
.forEach(chat => {
const config = {
setStyle: !1,
setAnimation: !1,
setPlayState: !1,
...x,
}
config.setStyle &&
setChatStyle(chat, mainState, userConfig),
config.setAnimation
? setChatAnimation(
chat,
flowChats,
mainState,
userConfig
)
: config.setPlayState &&
setChatPlayState(chat, mainState, userConfig)
})
})
),
updateStringMacro("lang"),
ss.tabChange.pipe(
(0, external_rxjs_operators_namespaceObject.tap)(x => {
panelState.currentTab = x
})
),
updateIntMacro("maxChatLength"),
updateBoolMacro("simplifyChatField"),
updateBoolMacro("createBanButton"),
updateBoolMacro("createChats"),
updateBoolMacro("displayModName"),
updateBoolMacro("displaySuperChatAuthor"),
updateBoolMacro("textOnly"),
ss.bannedWords.pipe(
(0, external_rxjs_operators_namespaceObject.map)(getInputValue),
(0, external_rxjs_operators_namespaceObject.map)(x =>
x.split(/\r\n|\n/).filter(word => "" !== word)
),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
userConfig.bannedWords.set(x)
})
),
ss.bannedWordRegexs.pipe(
(0, external_rxjs_operators_namespaceObject.map)(getInputValue),
(0, external_rxjs_operators_namespaceObject.map)(x =>
x.split(/\r\n|\n/).filter(regex => "" !== regex)
),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
panelState.bannedWordRegexs = x
let valid = !0
;(panelState.bannedWordRegexsError = ""),
panelState.bannedWordRegexs.forEach(regex => {
try {
RegExp(regex, "u")
} catch (error) {
mainLog("Invalid Regex", regex),
external_log_default().warn(error),
(panelState.bannedWordRegexsError += `${error} in ${regex};`),
(valid = !1)
}
}),
valid && userConfig.bannedWordRegexs.set(x),
(panelState.bannedWordRegexsValid = valid)
})
),
ss.bannedUsers.pipe(
(0, external_rxjs_operators_namespaceObject.map)(getInputValue),
(0, external_rxjs_operators_namespaceObject.map)(x =>
x.split(/\r\n|\n/).filter(user => "" !== user)
),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
userConfig.bannedUsers.set(x)
})
),
ss.clearFlowChats.pipe(
(0, external_rxjs_operators_namespaceObject.tap)(() =>
removeOldChats(flowChats, 0)
)
)
).subscribe(),
{
view: () => {
return external_m_default()(
"div",
{
className: "fyc_panel",
style: {
visibility: state.showPanel ? "visible" : "hidden",
backgroundColor: "rgba(30,30,30,0.9)",
zIndex: 5,
position: "absolute",
bottom: "40px",
right: "0px",
color: "#fff",
fontSize: "14px",
width: "660px",
border: "solid 1px #666",
fontFamily: "MS PGothic",
},
},
[
external_m_default()(
"div",
{ style: { float: "right", margin: "6px 6px 0 0" } },
[
"🌐",
external_m_default()(
"select",
{
selectedIndex: langOptions.findIndex(
x => x[0] === userConfig.lang.get()
),
onchange: lib(ss.str.lang),
},
langOptions.map(x => settingPanel_option(...x))
),
]
),
((style = {
container: { height: "364px" },
label: { padding: "6px" },
labelFocus: { background: "#666" },
tab: { display: "flex", padding: "6px" },
}),
(labels = [
getLang().flowChat,
getLang().chatFilter,
getLang().chatField,
getLang().feedback,
]),
(tabs = [
[
external_m_default()(
"div",
{ style: panelBoxStyle(212) },
[
settingRow(getLang().font, [
external_m_default()(
"select",
{
style: { width: "60%" },
selectedIndex: fontOptions.findIndex(
x => x[0] === userConfig.font.get()
),
onchange: lib(ss.str.font),
},
fontOptions.map(x =>
settingPanel_option(
x[0],
"FYC_JA" === userConfig.lang.get()
? x[2]
: x[1]
)
)
),
]),
textColorNode("color"),
textColorNode("ownerColor"),
textColorNode("moderatorColor"),
textColorNode("memberColor"),
]
),
external_m_default()(
"div",
{ style: panelBoxStyle(212) },
[
rangeNode("chatOpacity", ss.num, 0, 1, 0.05),
rangeNode("fontSize", ss.num, 0.3, 2, 0.05),
rangeNode("fontWeight", ss.num, 10, 1e3, 10),
rangeNode("shadowFontWeight", ss.num, 0, 3, 0.1),
rangeNode("flowSpeed", ss.num, 1, 50, 1),
rangeNode("maxChatCount", ss.int, 5, 200, 5),
rangeNode("maxChatLength", ss.int, 5, 200, 5),
rangeNode("laneCount", ss.int, 1, 25, 1),
]
),
external_m_default()(
"div",
{ style: panelBoxStyle(212) },
[
rangeNode("minSpacing", ss.num, 0, 2.5, 0.1),
checkboxRow(
getLang().useStepTiming,
useStepTiming(),
lib(ss.useStepTiming)
),
external_m_default()(
"div",
{
style: {
...(useStepTiming()
? {}
: { opacity: "0.5" }),
},
},
settingRow(getLang().timingStepCount, [
rangeRow(
1,
400,
1,
panelState.timingStepCount,
lib(ss.timingStepCount)
),
])
),
checkboxNode("createChats"),
checkboxNode("displayModName"),
checkboxNode("displaySuperChatAuthor"),
checkboxNode("textOnly"),
external_m_default()(
"span",
getLang().flowNewChatIf
),
checkboxNode("noOverlap"),
external_m_default()(
"button",
{
type: "button",
onclick: lib(ss.clearFlowChats),
},
getLang().clearFlowChats
),
]
),
],
[
external_m_default()(
"div",
{ style: panelBoxStyle(212) },
[
settingRow(getLang().bannedWords, [
external_m_default()(
"textarea",
{
rows: 18,
style: textAreaStyle,
onchange: lib(ss.bannedWords),
},
userConfig.bannedWords.get().join("\n")
),
]),
]
),
external_m_default()(
"div",
{ style: panelBoxStyle(212) },
[
settingRow(getLang().bannedWordRegexs, [
external_m_default()(
"span",
panelState.bannedWordRegexsValid
? ""
: `${getLang().error}: ${
panelState.bannedWordRegexsError
}`
),
external_m_default()(
"textarea",
{
rows: 18,
style: textAreaStyle,
onchange: lib(ss.bannedWordRegexs),
},
panelState.bannedWordRegexs.join("\n")
),
]),
]
),
external_m_default()(
"div",
{ style: panelBoxStyle(212) },
[
settingRow(getLang().bannedUsers, [
external_m_default()(
"textarea",
{
rows: 18,
style: textAreaStyle,
onchange: lib(ss.bannedUsers),
},
userConfig.bannedUsers.get().join("\n")
),
]),
]
),
],
[
external_m_default()(
"div",
{ style: panelBoxStyle(644) },
[
checkboxNode("simplifyChatField"),
checkboxNode("createBanButton"),
]
),
],
[
external_m_default()(
"div",
{ style: panelBoxStyle(644) },
[
external_m_default()(
"div",
{ style: { float: "right" } },
external_m_default()(
"a",
{
style: { color: "#f0f" },
href:
"https://gf.qytechs.cn/en/scripts/411442-flow-youtube-chat/feedback",
target: "_blank",
},
getLang().giveFeedback
)
),
settingRow(getLang().eventLog, [
external_m_default()(
"textarea",
{
rows: 18,
style: textAreaStyle,
readOnly: !0,
onclick: () => {},
},
mainState.log
),
]),
]
),
],
]),
(currentTab = panelState.currentTab),
(ontabSelect = lib(ss.tabChange)),
external_m_default()("div", [
external_m_default()(
"div",
...labels.map((x, i) =>
external_m_default()(
"span",
{
style: {
...style.label,
...(currentTab === i ? style.labelFocus : {}),
display: "inline-block",
},
onclick: () => ontabSelect(i),
},
x
)
)
),
external_m_default()(
"div",
{
style: {
...style.container,
overflow: "hidden auto",
},
},
...tabs.map((x, i) => {
var _a
return external_m_default()(
"div",
{
style: {
...style.tab,
display:
i === currentTab
? null !== (_a = style.tab.display) &&
void 0 !== _a
? _a
: "block"
: "none",
},
},
x
)
})
),
])),
]
)
var style, labels, tabs, currentTab, ontabSelect
},
}
)
},
settingComponent = (flowChats, mainState, userConfig, mainLog) => {
const state = { showPanel: !1 },
panel = settingPanel(
flowChats,
mainState,
state,
userConfig,
mainLog
),
toggleButton = ((state, userConfig) => {
const click$ = new external_rxjs_namespaceObject.Subject()
return (
click$
.pipe(
(0, external_rxjs_operators_namespaceObject.tap)(() => {
state.showPanel = !state.showPanel
})
)
.subscribe(),
{
view: () =>
external_m_default()(
"button",
{
className: "fyc_button",
style: {
background: "rgba(0,0,0,0)",
marginLeft: "10px",
whiteSpace: "nowrap",
},
onclick: lib(click$),
},
[
external_m_default()(
"svg",
{
preserveAspectRatio: "xMidYMid meet",
viewBox: "0 0 640 640",
width: "15",
height: "15",
style: { position: "relative", top: "1px" },
},
[
external_m_default()(
"defs",
external_m_default()("path", {
id: "d1TbzTC1zI",
d:
"m135.38 58.17 0.64 0.05 0.63 0.07 0.65 0.1 0.65 0.13 0.66 0.14 0.66 0.17 0.67 0.18 0.67 0.21 0.68 0.23 0.69 0.25 0.68 0.26 0.69 0.29 0.7 0.3 0.69 0.32 0.7 0.33 0.71 0.35 0.7 0.37 0.71 0.38 0.71 0.39 0.7 0.41 0.72 0.42 0.71 0.43 0.71 0.45 45.87 26.91 0.9-0.5 8.92-4.47 9.12-4.12 0.92-0.38v142.27l-2.42 2.55-3.53 4.01-3.38 4.15-3.22 4.28-3.06 4.41-2.9 4.53-2.73 4.65-2.55 4.76-2.37 4.87-2.19 4.97-2 5.07-1.82 5.17-1.61 5.26-1.41 5.35-1.21 5.43-1 5.51-0.78 5.57-0.57 5.65-0.34 5.71-0.12 5.77 0.12 5.78 0.34 5.71 0.57 5.64 0.78 5.58 1 5.51 1.21 5.43 1.41 5.34 1.61 5.27 1.82 5.16 2 5.08 2.19 4.97 2.37 4.87 2.55 4.76 2.73 4.65 2.9 4.53 3.06 4.41 3.22 4.28 3.38 4.14 3.53 4.02 3.68 3.87 3.82 3.73 3.96 3.57 4.09 3.43 4.23 3.26 4.34 3.1 4.47 2.94 4.59 2.76 4.7 2.59 4.8 2.4 4.91 2.22 5.01 2.03 5.1 1.84 5.19 1.63 5.28 1.44 5.36 1.22 5.43 1.01 5.51 0.8 5.57 0.57 5.63 0.35 5.7 0.11 5.69-0.11 5.64-0.35 5.57-0.57 5.51-0.8 5.43-1.01 5.36-1.22 5.28-1.44 5.19-1.63 5.1-1.84 5.01-2.03 4.91-2.22 4.8-2.4 4.7-2.59 4.59-2.76 4.46-2.94 4.35-3.1 4.23-3.26 4.09-3.43 3.96-3.57 3.82-3.73 3.68-3.87 3.53-4.02 3.38-4.14 3.22-4.28 3.06-4.41 2.9-4.53 2.72-4.65 2.56-4.76 2.37-4.87 2.19-4.97 2-5.08 1.81-5.16 1.62-5.27 1.41-5.34 1.21-5.43 1-5.51 0.78-5.58 0.57-5.64 0.34-5.71 0.12-5.78-0.12-5.77-0.06-1.06h33.29l140.27 63.64-0.02 0.01-0.48 0.4-0.51 0.38-0.52 0.37-0.55 0.36-0.57 0.36-0.58 0.34-0.6 0.34-0.63 0.33-0.63 0.32-0.66 0.31-0.67 0.31-0.69 0.3-0.7 0.29-0.71 0.3-0.73 0.28-0.74 0.28-1.52 0.56-0.78 0.27-0.78 0.28-1.6 0.54-0.82 0.26-51.23 13.84-1.32 4.34-3.37 9.6-3.71 9.43-4.07 9.24-4.41 9.04-0.5 0.91 26.56 46.48 0.44 0.72 0.84 1.44 0.4 0.72 0.39 0.72 0.38 0.72 0.36 0.71 0.34 0.71 0.33 0.71 0.32 0.71 0.3 0.7 0.28 0.7 0.26 0.7 0.24 0.69 0.23 0.69 0.2 0.68 0.19 0.67 0.16 0.68 0.14 0.66 0.12 0.66 0.1 0.66 0.08 0.65 0.05 0.64 0.02 0.63 0.01 0.62-0.03 0.62-0.05 0.61-0.08 0.6-0.1 0.59-0.13 0.59-0.16 0.57-0.2 0.57-0.22 0.55-0.25 0.54-0.28 0.54-0.31 0.52-0.35 0.51-0.37 0.5-0.41 0.48-0.45 0.48-66.99 67.88-0.47 0.45-0.47 0.41-0.49 0.38-0.49 0.34-0.51 0.31-0.51 0.27-0.53 0.24-0.53 0.21-0.54 0.18-0.55 0.14-0.56 0.12-0.56 0.09-0.58 0.06-0.58 0.03-0.59 0.01-0.6-0.02-0.61-0.04-0.62-0.07-0.62-0.09-0.63-0.12-0.64-0.13-0.65-0.16-0.65-0.17-0.66-0.2-0.67-0.21-0.68-0.23-0.68-0.25-0.69-0.26-0.69-0.28-0.71-0.3-0.7-0.3-0.72-0.32-0.72-0.33-0.73-0.34-0.73-0.36-0.74-0.36-0.75-0.37-0.75-0.38-1.52-0.78-45.87-26.91-0.9 0.5-8.92 4.47-9.12 4.12-9.3 3.77-9.47 3.41-4.29 1.34-13.65 51.91-0.27 0.83-0.26 0.81-0.27 0.81-0.27 0.8-0.54 1.56-0.28 0.76-0.28 0.75-0.28 0.74-0.29 0.73-0.29 0.71-0.3 0.69-0.3 0.68-0.31 0.67-0.32 0.64-0.32 0.63-0.33 0.61-0.34 0.6-0.35 0.57-0.36 0.55-0.36 0.54-0.38 0.51-0.39 0.49-0.4 0.46-0.41 0.45-0.42 0.42-0.44 0.39-0.45 0.37-0.46 0.34-0.48 0.32-0.49 0.29-0.5 0.26-0.52 0.24-0.54 0.2-0.56 0.18-0.57 0.14-0.59 0.12-0.6 0.08-0.63 0.05-0.64 0.01h-94.74l-0.64-0.01-0.64-0.05-0.61-0.08-0.6-0.12-0.59-0.14-0.57-0.18-0.55-0.2-0.54-0.24-0.53-0.26-0.52-0.29-0.5-0.32-0.49-0.34-0.47-0.37-0.46-0.39-0.45-0.42-0.43-0.45-0.43-0.46-0.41-0.49-0.4-0.51-0.38-0.54-0.38-0.55-0.36-0.57-0.36-0.6-0.34-0.61-0.33-0.63-0.32-0.64-0.31-0.67-0.3-0.68-0.29-0.69-0.28-0.71-0.27-0.73-0.26-0.74-0.25-0.75-0.25-0.76-0.46-1.56-0.21-0.8-0.42-1.62-0.19-0.83-13.65-51.91-4.29-1.34-9.47-3.41-9.3-3.77-9.12-4.12-8.92-4.47-1.08-0.59-45.69 26.81-1.42 0.88-0.72 0.42-0.7 0.4-0.71 0.4-0.71 0.38-0.7 0.37-0.71 0.35-0.7 0.33-0.69 0.32-0.7 0.3-0.69 0.29-0.68 0.26-0.69 0.25-0.68 0.23-0.67 0.2-0.67 0.19-0.66 0.17-0.66 0.14-0.65 0.12-0.65 0.1-0.63 0.08-0.64 0.05-0.62 0.03h-0.62l-0.61-0.03-0.6-0.05-0.59-0.08-0.59-0.1-0.57-0.14-0.57-0.16-0.56-0.19-0.54-0.23-0.54-0.25-0.52-0.28-0.52-0.32-0.5-0.35-0.49-0.38-0.48-0.42-0.47-0.45-66.99-67.88-0.45-0.48-0.4-0.48-0.37-0.49-0.34-0.5-0.3-0.52-0.27-0.52-0.24-0.53-0.21-0.54-0.17-0.54-0.15-0.56-0.11-0.57-0.09-0.57-0.06-0.58-0.03-0.6-0.01-0.6 0.02-0.6 0.04-0.62 0.07-0.62 0.09-0.64 0.11-0.64 0.14-0.64 0.15-0.66 0.17-0.66 0.19-0.67 0.44-1.36 0.25-0.69 0.26-0.7 0.27-0.71 0.29-0.71 0.3-0.72 0.32-0.72 0.33-0.73 0.33-0.74 0.35-0.74 0.36-0.75 0.74-1.52 0.38-0.77 0.39-0.77 26.5-46.38-0.44-0.82-4.41-9.04-4.07-9.24-3.72-9.43-3.36-9.6-1.33-4.34-51.22-13.84-0.82-0.26-1.6-0.54-0.78-0.28-0.78-0.27-1.52-0.56-0.74-0.28-0.73-0.28-0.71-0.3-0.7-0.29-0.69-0.3-0.67-0.31-0.66-0.31-0.64-0.32-0.62-0.33-0.6-0.34-0.58-0.34-0.57-0.36-0.55-0.36-0.52-0.37-0.51-0.38-0.48-0.4-0.46-0.4-0.44-0.42-0.41-0.43-0.39-0.44-0.37-0.45-0.33-0.47-0.32-0.48-0.28-0.5-0.26-0.51-0.23-0.53-0.21-0.55-0.17-0.56-0.14-0.58-0.11-0.6-0.08-0.61-0.05-0.63-0.02-0.66v-96l0.02-0.65 0.05-0.64 0.08-0.62 0.11-0.61 0.14-0.59 0.17-0.58 0.21-0.57 0.23-0.54 0.26-0.54 0.28-0.52 0.32-0.51 0.33-0.49 0.37-0.48 0.39-0.47 0.41-0.45 0.44-0.45 0.46-0.42 0.48-0.42 0.51-0.4 0.52-0.4 0.55-0.38 0.57-0.37 0.58-0.35 0.6-0.35 0.62-0.34 0.64-0.32 0.66-0.32 0.67-0.3 0.69-0.29 0.7-0.29 0.71-0.27 0.73-0.27 0.74-0.25 0.76-0.25 0.76-0.24 1.56-0.44 0.8-0.22 0.8-0.2 0.82-0.2 51.22-13.83 1.33-4.35 3.36-9.6 3.72-9.42 4.07-9.24 4.41-9.04 0.5-0.91-26.56-46.48-0.77-1.54-0.74-1.52-0.36-0.75-0.35-0.74-0.33-0.74-0.33-0.73-0.32-0.73-0.3-0.71-0.29-0.72-0.27-0.7-0.26-0.7-0.25-0.69-0.44-1.36-0.19-0.67-0.17-0.66-0.15-0.66-0.14-0.65-0.11-0.64-0.09-0.63-0.07-0.62-0.04-0.62-0.02-0.61 0.01-0.6 0.03-0.59 0.06-0.58 0.09-0.58 0.11-0.56 0.15-0.56 0.17-0.55 0.21-0.54 0.24-0.53 0.27-0.52 0.3-0.51 0.34-0.5 0.37-0.49 0.4-0.49 0.45-0.47 66.99-67.88 0.47-0.45 0.48-0.42 0.49-0.38 0.5-0.35 0.52-0.32 0.52-0.28 0.54-0.26 0.54-0.22 0.56-0.19 0.57-0.17 0.57-0.13 0.59-0.11 0.59-0.08 0.6-0.05 0.61-0.02h0.62l0.62 0.03zm441.37-56.16 2.78 0.28 2.75 0.4 2.71 0.49 2.67 0.61 2.63 0.7 2.59 0.81 2.54 0.9 2.5 1 2.45 1.09 2.39 1.18 2.35 1.28 2.28 1.36 2.23 1.44 2.17 1.53 2.11 1.6 2.04 1.69 1.97 1.76 1.91 1.83 1.83 1.91 1.76 1.97 1.69 2.05 1.61 2.1 1.52 2.17 1.45 2.23 1.36 2.29 1.27 2.34 1.18 2.4 1.1 2.44 0.99 2.5 0.91 2.55 0.8 2.58 0.71 2.64 0.6 2.67 0.5 2.71 0.39 2.74 0.28 2.78 0.17 2.81 0.06 2.84v137.8l-0.06 2.84-0.17 2.81-0.28 2.78-0.39 2.75-0.5 2.71-0.6 2.67-0.71 2.63-0.8 2.59-0.91 2.54-0.99 2.5-1.1 2.45-1.18 2.39-1.27 2.35-1.36 2.28-1.45 2.23-1.52 2.17-1.61 2.11-1.69 2.04-1.76 1.97-1.83 1.91-1.91 1.83-1.97 1.76-2.04 1.69-2.11 1.61-2.17 1.52-2.23 1.45-2.28 1.36-2.35 1.27-0.98 0.49 21.81 70.8-141.75-63.6h-155.05l-2.84-0.06-2.81-0.17-2.78-0.28-2.74-0.39-2.71-0.5-2.67-0.6-2.64-0.71-2.58-0.8-2.55-0.91-2.5-1-2.44-1.09-2.4-1.18-2.34-1.27-2.29-1.36-2.23-1.45-2.17-1.52-2.1-1.61-2.05-1.69-1.97-1.76-1.91-1.83-1.83-1.91-1.76-1.97-1.68-2.04-1.61-2.11-1.53-2.17-1.44-2.23-1.36-2.28-1.27-2.35-1.19-2.39-1.09-2.45-1-2.5-0.9-2.54-0.81-2.59-0.7-2.63-0.61-2.67-0.49-2.71-0.39-2.75-0.29-2.78-0.17-2.81-0.06-2.84v-137.8l0.06-2.84 0.17-2.81 0.29-2.78 0.39-2.74 0.49-2.71 0.61-2.67 0.7-2.64 0.81-2.58 0.9-2.55 1-2.5 1.09-2.44 1.19-2.4 1.27-2.34 1.36-2.29 1.44-2.23 1.53-2.17 1.61-2.1 1.68-2.05 1.76-1.97 1.83-1.91 1.91-1.83 1.97-1.76 2.05-1.69 2.1-1.6 2.17-1.53 2.23-1.44 2.29-1.36 2.34-1.28 2.4-1.18 2.44-1.09 2.5-1 2.55-0.9 2.58-0.81 2.64-0.7 2.67-0.61 2.71-0.49 2.74-0.4 2.78-0.28 2.81-0.17 2.84-0.06h244.31l2.84 0.06 2.81 0.17z",
})
),
external_m_default()("use", {
"xlink:href": "#d1TbzTC1zI",
opacity: "1",
fill: "var(--iron-icon-fill-color, currentcolor)",
"fill-opacity": "1",
}),
]
),
external_m_default()(
"span",
{
style: {
position: "relative",
top: "-2px",
marginLeft: "8px,",
},
},
"FYC_JA" === userConfig.lang.get()
? "設定"
: "Settings"
),
]
),
}
)
})(state, userConfig)
return {
view: () => [
external_m_default()(panel),
external_m_default()(toggleButton),
],
}
},
videoToggleStream = video =>
(0, external_rxjs_namespaceObject.merge)(
(0, external_rxjs_namespaceObject.fromEvent)(video, "playing").pipe(
(0, external_rxjs_operators_namespaceObject.mapTo)(!0)
),
(0, external_rxjs_namespaceObject.fromEvent)(video, "waiting").pipe(
(0, external_rxjs_operators_namespaceObject.mapTo)(!1)
),
(0, external_rxjs_namespaceObject.fromEvent)(video, "pause").pipe(
(0, external_rxjs_operators_namespaceObject.mapTo)(!1)
)
),
requirementMet = () =>
Boolean(
livePage_getChatFrame() &&
livePage_getChatField() &&
livePage_getPlayer()
),
initialize = async (mainState, mainLog) => {
const consoleLog = (a, ...b) => {
mainLog(a, ...b),
external_log_default().info(`【FYC】 ${a}`),
b.length > 0 && external_log_default().info(...b)
}
mainLog("Version", package_namespaceObject_i8),
mainLog("User Agent", window.navigator.userAgent)
const userConfig = await (async () => ({
lang: await simpleConfigItem("FYC_LANG", "FYC_EN"),
font: await simpleConfigItem("FYC_FONT", "MS PGothic"),
chatOpacity: await simpleConfigItem("FYC_OPACITY", 0.8),
color: await simpleConfigItem("FYC_COLOR", "#ffffff"),
ownerColor: await simpleConfigItem("FYC_COLOR_OWNER", "#ffd600"),
moderatorColor: await simpleConfigItem(
"FYC_COLOR_MODERATOR",
"#a74fff"
),
memberColor: await simpleConfigItem("FYC_COLOR_MEMBER", "#9fffff"),
fontSize: await simpleConfigItem("FYC_SIZE", 1),
fontWeight: await simpleConfigItem("FYC_WEIGHT", 730),
shadowFontWeight: await simpleConfigItem("FYC_WEIGHT_SHADOW", 1),
maxChatCount: await simpleConfigItem("FYC_LIMIT", 40),
flowSpeed: await simpleConfigItem("FYC_SPEED", 18),
maxChatLength: await simpleConfigItem("FYC_MAX", 100),
laneCount: await simpleConfigItem("FYC_LANE_DIV", 12),
bannedWords: await makeConfigItem(
"FYC_NG_WORDS",
...lineConfigArgs
),
bannedWordRegexs: await makeConfigItem(
"FYC_NG_REG_WORDS",
...lineConfigArgs
),
bannedUsers: await makeConfigItem(
"FYC_NG_USERS",
...lineConfigArgs
),
createChats: await simpleConfigItem(
"FYC_TOGGLE_CREATE_COMMENTS",
!0
),
noOverlap: await simpleConfigItem("FYC_NO_OVERLAP", !0),
createBanButton: await simpleConfigItem("FYC_NG_BUTTON", !0),
simplifyChatField: await simpleConfigItem(
"FYC_SIMPLE_CHAT_FIELD",
!1
),
displayModName: await simpleConfigItem(
"FYC_DISPLAY_MODERATOR_NAME",
!0
),
displaySuperChatAuthor: await simpleConfigItem(
"FYC_DISPLAY_SUPER_CHAT_AUTHOR",
!0
),
textOnly: await simpleConfigItem("FYC_TEXT_ONLY", !1),
timingFunction: await simpleConfigItem(
"FYC_TIMING_FUNCTION",
"linear"
),
displayChats: await simpleConfigItem("FYC_DISPLAY_COMMENTS", !0),
minSpacing: await simpleConfigItem("FYC_MIN_SPACING", 0.5),
}))()
mainLog("UserConfig", JSON.stringify(userConfig))
const reinitSubject = new external_rxjs_namespaceObject.Subject(),
reinitialize = lib(reinitSubject),
chatScrn = (() => {
const element = document.createElement("div")
return (
(element.style.pointerEvents = "none"),
(element.style.zIndex = "30"),
element
)
})(),
flowChats = []
let chatField,
video,
player,
storedHref = window.location.href
new MutationObserver(async () => {
storedHref !== window.location.href &&
((storedHref = window.location.href),
consoleLog("URL Changed", storedHref),
await reinitialize())
}).observe(document, { childList: !0, subtree: !0 })
const chatObserver = chatFieldObserver(
chatScrn,
flowChats,
mainState,
userConfig,
mainLog
),
playerResizeSubject = new external_rxjs_namespaceObject.Subject(),
playerResizeObserver = new ResizeObserver(lib(playerResizeSubject)),
toggleChatBtn = ((flowChats, userConfig) => {
const click$ = new external_rxjs_namespaceObject.Subject()
click$
.pipe(
(0, external_rxjs_operators_namespaceObject.tap)(() => {
const newDisplay = !userConfig.displayChats.get()
flowChats.forEach(x => {
x.element.style.visibility = newDisplay
? "visible"
: "hidden"
}),
userConfig.displayChats.set(newDisplay),
GM.setValue("FYC_DISPLAY_COMMENTS", newDisplay)
})
)
.subscribe()
const label = () =>
"チャット" + (userConfig.displayChats.get() ? "非表示" : "表示")
return {
view: () =>
external_m_default()(
"button",
{
className: ["ytp-button"].join(" "),
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: lib(click$),
},
[
external_m_default()(
"svg",
{ style: { width: "100%" }, viewBox: "0 0 36 36" },
[
external_m_default()("path", {
className: ["chat-button-path"].join(" "),
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": userConfig.displayChats.get()
? "1"
: "0",
stroke: "#fff",
"stroke-width": "2",
}),
]
),
]
),
}
})(flowChats, userConfig),
mountToggleChatBtn = componentMounter(
document.createElement("span"),
x => {
const parent = document.querySelector(".ytp-right-controls")
return parent && parent.append(x), Boolean(parent)
}
),
settingComp = settingComponent(
flowChats,
mainState,
userConfig,
mainLog
),
mountSettingComp = componentMounter(
document.createElement("span"),
x => {
const parent = document.querySelector(
"#menu-container .dropdown-trigger.style-scope.ytd-menu-renderer"
)
return (
parent && parent.insertAdjacentElement("beforebegin", x),
Boolean(parent)
)
}
)
external_log_default().debug("Append ToggleChatDisplayButton")
reinitSubject
.pipe(
(0, external_rxjs_operators_namespaceObject.observeOn)(
external_rxjs_namespaceObject.asyncScheduler
),
(0, external_rxjs_operators_namespaceObject.switchMap)(() =>
(0, external_rxjs_namespaceObject.interval)(800).pipe(
(0, external_rxjs_operators_namespaceObject.startWith)(0),
(0, external_rxjs_operators_namespaceObject.map)(
requirementMet
),
(0, external_rxjs_operators_namespaceObject.filter)(() => {
var _a, _b, _c, _d, _e, _f
const chatFieldDetached =
null !==
(_d =
chatField &&
!(
null !==
(_c =
null ===
(_b =
null === (_a = livePage_getChatFrame()) ||
void 0 === _a
? void 0
: _a.contentDocument) || void 0 === _b
? void 0
: _b.contains(chatField)) &&
void 0 !== _c &&
_c
) &&
!document.contains(chatField)) &&
void 0 !== _d &&
_d,
logDetached = x => consoleLog(`${x} detached...`)
chatFieldDetached &&
(logDetached("Chat field"), (chatField = void 0))
const videoDetached =
null !== (_e = video && !document.contains(video)) &&
void 0 !== _e &&
_e
videoDetached &&
(logDetached("Video"),
(video = void 0),
(mainState.chatPlaying = Boolean(
livePage_getOfflineSlate()
)))
const playerDetached =
null !== (_f = player && !document.contains(player)) &&
void 0 !== _f &&
_f
playerDetached && (logDetached("Player"), (player = void 0))
const detached =
chatFieldDetached || videoDetached || playerDetached
return detached && reinitialize(), !detached
}),
(0, external_rxjs_operators_namespaceObject.startWith)(!1),
(0,
external_rxjs_operators_namespaceObject.distinctUntilChanged)(),
(0, external_rxjs_operators_namespaceObject.tap)(x =>
consoleLog(
x
? "Found the chat container and the player"
: "Waiting to load..."
)
),
(0, external_rxjs_operators_namespaceObject.filter)(Boolean)
)
),
(0, external_rxjs_operators_namespaceObject.tap)(addMainCss),
(0, external_rxjs_operators_namespaceObject.tap)(() =>
mountSettingComp(settingComp)
),
(0, external_rxjs_operators_namespaceObject.tap)(() =>
consoleLog("Wait for 2200ms...")
),
(0, external_rxjs_operators_namespaceObject.delay)(2200),
(0, external_rxjs_operators_namespaceObject.tap)(() =>
consoleLog("Initializing...")
),
(0, external_rxjs_operators_namespaceObject.tap)(() => {
removeOldChats(flowChats, 0),
chatObserver.disconnect(),
(chatField = livePage_getChatField()),
chatField &&
chatObserver.observe(chatField, { childList: !0 }),
(video = livePage_getMainVideo()),
video &&
(mainState.chatPlaying =
!video.paused || Boolean(livePage_getOfflineSlate())),
playerResizeObserver.disconnect(),
(player = livePage_getPlayer()),
player &&
(external_log_default().debug("AppendChatScreen"),
playerResizeObserver.observe(player),
player.insertAdjacentElement("afterbegin", chatScrn)),
mountToggleChatBtn(toggleChatBtn),
(chatField && video && player) || reinitialize()
}),
(0, external_rxjs_operators_namespaceObject.switchMap)(() =>
setChatFrameCss(mainLog)
),
(0, external_rxjs_operators_namespaceObject.switchMap)(() =>
(0, external_rxjs_namespaceObject.merge)(
...(video
? [
videoToggleStream(video).pipe(
(0, external_rxjs_operators_namespaceObject.map)(
playing =>
playing || Boolean(livePage_getOfflineSlate())
),
(0, external_rxjs_operators_namespaceObject.tap)(
chatPlaying => {
;(mainState.chatPlaying = chatPlaying),
flowChats.forEach(chat => {
setChatPlayState(chat, mainState, userConfig)
})
}
)
),
]
: []),
playerResizeSubject.pipe(
(0,
external_rxjs_operators_namespaceObject.throttleTime)(
500,
void 0,
{ leading: !0, trailing: !0 }
),
(0, external_rxjs_operators_namespaceObject.startWith)([]),
(0, external_rxjs_operators_namespaceObject.tap)(() => {
var _a
consoleLog("Resize detected"),
(mainState.playerRect =
null !==
(_a =
null == player
? void 0
: player.getBoundingClientRect()) &&
void 0 !== _a
? _a
: new DOMRect()),
flowChats.forEach(chat => {
setChatStyle(chat, mainState, userConfig),
setChatAnimation(
chat,
flowChats,
mainState,
userConfig
)
})
})
)
)
),
(0, external_rxjs_operators_namespaceObject.retryWhen)(x =>
x.pipe(
(0, external_rxjs_operators_namespaceObject.tap)(y =>
consoleLog("Errored", y)
)
)
)
)
.subscribe(),
await reinitialize()
}
;(async () => {
external_log_namespaceObject.setLevel("info")
const mainState = {
chatPlaying: !0,
playerRect: new DOMRect(24, 80, 839, 472),
log: "",
},
mainLog = (mainState => (a, ...b) => {
;(mainState.log += `${a}${b.length > 0 ? ": " : ""}${b.join(
", "
)}\n`),
mainState.log.length > 22e3 &&
(mainState.log = `${mainState.log.slice(0, 6e3)}\n`)
})(mainState)
try {
await initialize(mainState, mainLog)
} catch (error) {
mainLog("Errored", error)
}
})()
})()
})()