// ==UserScript==
// @name Flow Youtube Chat
// @version 1.13.8
// @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
// ==/UserScript==
/* jshint esversion: 6 */
;(() => {
var __webpack_modules__ = {
494: function (module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_RESULT__
!(function (globals) {
"use strict"
var messages,
predicates,
functions,
assert,
not,
maybe,
collections,
hasOwnProperty,
toString,
keys,
slice,
isArray,
neginf,
posinf,
haveSymbols,
haveMaps,
haveSets
function assigned(data) {
return null != data
}
function number(data) {
return "number" == typeof data && data > neginf && data < posinf
}
function integer(data) {
return "number" == typeof data && data % 1 == 0
}
function greater(lhs, rhs) {
return number(lhs) && lhs > rhs
}
function less(lhs, rhs) {
return number(lhs) && lhs < rhs
}
function greaterOrEqual(lhs, rhs) {
return number(lhs) && lhs >= rhs
}
function lessOrEqual(lhs, rhs) {
return number(lhs) && lhs <= rhs
}
function string(data) {
return "string" == typeof data
}
function nonEmptyString(data) {
return string(data) && "" !== data
}
function object(data) {
return "[object Object]" === toString.call(data)
}
function some(data, predicate) {
for (var key in data)
if (hasOwnProperty.call(data, key) && predicate(key, data[key]))
return !0
return !1
}
function instanceStrict(data, prototype) {
try {
return data instanceof prototype
} catch (error) {
return !1
}
}
function like(data, archetype) {
var name
for (name in archetype)
if (hasOwnProperty.call(archetype, name)) {
if (
!1 === hasOwnProperty.call(data, name) ||
typeof data[name] != typeof archetype[name]
)
return !1
if (
object(data[name]) &&
!1 === like(data[name], archetype[name])
)
return !1
}
return !0
}
function arrayLike(data) {
return assigned(data) && data.length >= 0
}
function iterable(data) {
return haveSymbols
? assigned(data) && isFunction(data[Symbol.iterator])
: arrayLike(data)
}
function contains(data, value) {
var iterator, iteration
if (!assigned(data)) return !1
if (haveSets && instanceStrict(data, Set)) return data.has(value)
if (string(data)) return -1 !== data.indexOf(value)
if (
haveSymbols &&
data[Symbol.iterator] &&
isFunction(data.values)
) {
iterator = data.values()
do {
if ((iteration = iterator.next()).value === value) return !0
} while (!iteration.done)
return !1
}
return some(data, function (key, dataValue) {
return dataValue === value
})
}
function containsKey(data, key) {
return (
!!assigned(data) &&
(haveMaps && instanceStrict(data, Map)
? data.has(key)
: !(iterable(data) && !number(+key)) && !!data[key])
)
}
function isFunction(data) {
return "function" == typeof data
}
function forEach(object, action) {
for (var key in object)
hasOwnProperty.call(object, key) && action(key, object[key])
}
function testArray(data, result) {
var i
for (i = 0; i < data.length; i += 1)
if (data[i] === result) return result
return !result
}
function testObject(data, result) {
var key, value
for (key in data)
if (hasOwnProperty.call(data, key)) {
if (
object((value = data[key])) &&
testObject(value, result) === result
)
return result
if (value === result) return result
}
return !result
}
function mixin(target, source) {
return (
forEach(source, function (key, value) {
target[key] = value
}),
target
)
}
function assertModifier(predicate, defaultMessage) {
return function () {
var args = arguments,
argCount = predicate.l || predicate.length,
message = args[argCount],
ErrorType = args[argCount + 1]
return (
assertImpl(
predicate.apply(null, args),
nonEmptyString(message)
? message
: defaultMessage
.replace("{a}", messageFormatter(args[0]))
.replace("{e}", messageFormatter(args[1]))
.replace("{e2}", messageFormatter(args[2]))
.replace("{t}", function () {
var arg = args[1]
return arg && arg.name ? arg.name : arg
}),
isFunction(ErrorType) ? ErrorType : TypeError
),
args[0]
)
}
}
function messageFormatter(arg) {
return function () {
return string(arg)
? '"' + arg.replace(/\\/g, "\\\\").replace(/"/g, '\\"') + '"'
: arg &&
!0 !== arg &&
arg.constructor &&
!instanceStrict(arg, RegExp) &&
"number" != typeof arg
? arg.constructor.name
: arg
}
}
function assertImpl(value, message, ErrorType) {
if (value) return value
throw new (ErrorType || Error)(message || "assert failed")
}
function notModifier(predicate) {
var modifiedPredicate = function () {
return notImpl(predicate.apply(null, arguments))
}
return (modifiedPredicate.l = predicate.length), modifiedPredicate
}
function notImpl(value) {
return !value
}
function ofModifier(target, type, predicate) {
var modifiedPredicate = function () {
var collection, args
if (
((collection = arguments[0]),
"maybe" === target && not.assigned(collection))
)
return !0
if (!type(collection)) return !1
;(collection = coerceCollection(type, collection)),
(args = slice.call(arguments, 1))
try {
collection.forEach(function (item) {
if (
("maybe" !== target || assigned(item)) &&
!predicate.apply(null, [item].concat(args))
)
throw 0
})
} catch (ignore) {
return !1
}
return !0
}
return (modifiedPredicate.l = predicate.length), modifiedPredicate
}
function coerceCollection(type, collection) {
switch (type) {
case arrayLike:
return slice.call(collection)
case object:
return keys(collection).map(function (key) {
return collection[key]
})
default:
return collection
}
}
function createModifiedPredicates(modifier, object) {
return createModifiedFunctions([modifier, predicates, object, ""])
}
function createModifiedFunctions(args) {
var modifier, messageModifier, object
return (
(modifier = args.shift()),
(messageModifier = args.pop()),
(object = args.pop()),
forEach(args.pop(), function (key, fn) {
var message = messages[key]
message &&
messageModifier &&
(message = message.replace("to", messageModifier + "to")),
Object.defineProperty(object, key, {
configurable: !1,
enumerable: !0,
writable: !1,
value: modifier.apply(null, args.concat(fn, message)),
})
}),
object
)
}
function createModifiedModifier(modifier, modified, messageModifier) {
return createModifiedFunctions([
modifier,
modified,
{},
messageModifier,
])
}
function createOfModifiers(base, modifier) {
collections.forEach(function (key) {
base[key].of = createModifiedModifier(
modifier,
predicates[key].of
)
})
}
;(messages = {}),
(predicates = {}),
[
{
n: "equal",
f: function (lhs, rhs) {
return lhs === rhs
},
s: "equal {e}",
},
{
n: "undefined",
f: function (data) {
return void 0 === data
},
s: "be undefined",
},
{
n: "null",
f: function (data) {
return null === data
},
s: "be null",
},
{ n: "assigned", f: assigned, s: "be assigned" },
{
n: "primitive",
f: function (data) {
var type
switch (data) {
case null:
case void 0:
case !1:
case !0:
return !0
}
return (
"string" === (type = typeof data) ||
"number" === type ||
(haveSymbols && "symbol" === type)
)
},
s: "be primitive type",
},
{ n: "contains", f: contains, s: "contain {e}" },
{
n: "in",
f: function (value, data) {
return contains(data, value)
},
s: "be in {e}",
},
{ n: "containsKey", f: containsKey, s: "contain key {e}" },
{
n: "keyIn",
f: function (key, data) {
return containsKey(data, key)
},
s: "be key in {e}",
},
{
n: "zero",
f: function (data) {
return 0 === data
},
s: "be 0",
},
{
n: "one",
f: function (data) {
return 1 === data
},
s: "be 1",
},
{
n: "infinity",
f: function (data) {
return data === neginf || data === posinf
},
s: "be infinity",
},
{ n: "number", f: number, s: "be Number" },
{ n: "integer", f: integer, s: "be integer" },
{
n: "float",
f: function (data) {
return number(data) && data % 1 != 0
},
s: "be non-integer number",
},
{
n: "even",
f: function (data) {
return "number" == typeof data && data % 2 == 0
},
s: "be even number",
},
{
n: "odd",
f: function (data) {
return integer(data) && data % 2 != 0
},
s: "be odd number",
},
{ n: "greater", f: greater, s: "be greater than {e}" },
{ n: "less", f: less, s: "be less than {e}" },
{
n: "between",
f: function (data, x, y) {
if (x < y) return greater(data, x) && data < y
return less(data, x) && data > y
},
s: "be between {e} and {e2}",
},
{
n: "greaterOrEqual",
f: greaterOrEqual,
s: "be greater than or equal to {e}",
},
{
n: "lessOrEqual",
f: lessOrEqual,
s: "be less than or equal to {e}",
},
{
n: "inRange",
f: function (data, x, y) {
if (x < y) return greaterOrEqual(data, x) && data <= y
return lessOrEqual(data, x) && data >= y
},
s: "be in the range {e} to {e2}",
},
{
n: "positive",
f: function (data) {
return greater(data, 0)
},
s: "be positive number",
},
{
n: "negative",
f: function (data) {
return less(data, 0)
},
s: "be negative number",
},
{ n: "string", f: string, s: "be String" },
{
n: "emptyString",
f: function (data) {
return "" === data
},
s: "be empty string",
},
{
n: "nonEmptyString",
f: nonEmptyString,
s: "be non-empty string",
},
{
n: "match",
f: function (data, regex) {
return string(data) && !!data.match(regex)
},
s: "match {e}",
},
{
n: "boolean",
f: function (data) {
return !1 === data || !0 === data
},
s: "be Boolean",
},
{ n: "object", f: object, s: "be Object" },
{
n: "emptyObject",
f: function (data) {
return (
object(data) &&
!some(data, function () {
return !0
})
)
},
s: "be empty object",
},
{
n: "nonEmptyObject",
f: function (data) {
return (
object(data) &&
some(data, function () {
return !0
})
)
},
s: "be non-empty object",
},
{
n: "instanceStrict",
f: instanceStrict,
s: "be instanceof {t}",
},
{
n: "thenable",
f: function (data) {
return assigned(data) && isFunction(data.then)
},
s: "be promise-like",
},
{
n: "instance",
f: function (data, prototype) {
try {
return (
instanceStrict(data, prototype) ||
data.constructor.name === prototype.name ||
toString.call(data) === "[object " + prototype.name + "]"
)
} catch (error) {
return !1
}
},
s: "be {t}",
},
{ n: "like", f: like, s: "be like {e}" },
{
n: "array",
f: function (data) {
return isArray(data)
},
s: "be Array",
},
{
n: "emptyArray",
f: function (data) {
return isArray(data) && 0 === data.length
},
s: "be empty array",
},
{
n: "nonEmptyArray",
f: function (data) {
return isArray(data) && data.length > 0
},
s: "be non-empty array",
},
{ n: "arrayLike", f: arrayLike, s: "be array-like" },
{ n: "iterable", f: iterable, s: "be iterable" },
{
n: "date",
f: function (data) {
return instanceStrict(data, Date) && integer(data.getTime())
},
s: "be valid Date",
},
{ n: "function", f: isFunction, s: "be Function" },
{
n: "hasLength",
f: function (data, length) {
return assigned(data) && data.length === length
},
s: "have length {e}",
},
{
n: "throws",
f: function (data) {
if (!isFunction(data)) return !1
try {
data()
} catch (error) {
return !0
}
return !1
},
s: "throw",
},
].map(function (data) {
var n = data.n
;(messages[n] = "assert failed: expected {a} to " + data.s),
(predicates[n] = data.f)
}),
(functions = {
map: function map(data, predicates) {
var result
result = isArray(data) ? [] : {}
if (isFunction(predicates))
forEach(data, function (key, value) {
result[key] = predicates(value)
})
else {
isArray(predicates) || assert.object(predicates)
var dataKeys = keys(data || {})
forEach(predicates, function (key, predicate) {
dataKeys.some(function (dataKey, index) {
return dataKey === key && (dataKeys.splice(index, 1), !0)
}),
isFunction(predicate)
? not.assigned(data)
? (result[key] = !!predicate.m)
: (result[key] = predicate(data[key]))
: (result[key] = map(data[key], predicate))
})
}
return result
},
all: function (data) {
if (isArray(data)) return testArray(data, !1)
return assert.object(data), testObject(data, !1)
},
any: function (data) {
if (isArray(data)) return testArray(data, !0)
return assert.object(data), testObject(data, !0)
},
}),
(collections = ["array", "arrayLike", "iterable", "object"]),
(hasOwnProperty = Object.prototype.hasOwnProperty),
(toString = Object.prototype.toString),
(keys = Object.keys),
(slice = Array.prototype.slice),
(isArray = Array.isArray),
(neginf = Number.NEGATIVE_INFINITY),
(posinf = Number.POSITIVE_INFINITY),
(haveSymbols = "function" == typeof Symbol),
(haveMaps = "function" == typeof Map),
(haveSets = "function" == typeof Set),
(functions = mixin(functions, predicates)),
(assert = createModifiedPredicates(assertModifier, assertImpl)),
(not = createModifiedPredicates(notModifier, notImpl)),
(maybe = createModifiedPredicates(
function (predicate) {
var modifiedPredicate = function () {
return (
!!not.assigned(arguments[0]) ||
predicate.apply(null, arguments)
)
}
return (
(modifiedPredicate.l = predicate.length),
(modifiedPredicate.m = !0),
modifiedPredicate
)
},
function (value) {
if (!1 === assigned(value)) return !0
return value
}
)),
(assert.not = createModifiedModifier(assertModifier, not, "not ")),
(assert.maybe = createModifiedModifier(
assertModifier,
maybe,
"maybe "
)),
collections.forEach(function (key) {
predicates[key].of = createModifiedFunctions([
ofModifier.bind(null, null),
predicates[key],
predicates,
{},
"",
])
}),
createOfModifiers(assert, assertModifier),
createOfModifiers(not, notModifier),
collections.forEach(function (key) {
;(maybe[key].of = createModifiedFunctions([
ofModifier.bind(null, "maybe"),
predicates[key],
predicates,
{},
"",
])),
(assert.maybe[key].of = createModifiedModifier(
assertModifier,
maybe[key].of
)),
(assert.not[key].of = createModifiedModifier(
assertModifier,
not[key].of
))
}),
(function (functions) {
void 0 ===
(__WEBPACK_AMD_DEFINE_RESULT__ = function () {
return functions
}.call(exports, __webpack_require__, exports, module)) ||
(module.exports = __WEBPACK_AMD_DEFINE_RESULT__)
})(mixin(functions, { assert, not, maybe }))
})()
},
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)
},
},
__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].call(
module.exports,
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,
animateChat = (flowChat, flowChats, mainState, userConfig) => {
var _a
if (flowChat.animationEnded) return
const duration = (userConfig => 96e3 / userConfig.flowSpeed)(
userConfig
),
time =
null === (_a = flowChat.animation) || void 0 === _a
? void 0
: _a.currentTime,
progress = time ? time / flowChat.animationDuration : 0,
newTime = time ? progress * duration : 0
flowChat.lane = ((
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,
chatX = progress ? chatRect.x - playerX : playerWidth,
chatsByLane = Array.from({
length: 2 * userConfig.laneCount - 1,
}).map(() => [])
flowChats
.slice(0, chatIndex >= 0 ? chatIndex : void 0)
.filter(chat => !chat.animationEnded)
.forEach(chat => chatsByLane[chat.lane].push(chat))
const occupiedChatCount = chats =>
chats.filter(chat => {
const otherRect = chat.element.getBoundingClientRect(),
otherWidth = otherRect.width,
otherX = otherRect.x - playerX,
gap = (otherWidth * chatWidth) ** 0.5 / 3
return (
(playerWidth - otherX) / (playerWidth + otherWidth) -
(null != progress ? progress : 0) <
(chatWidth + gap) / (playerWidth + chatWidth) ||
otherX + otherWidth + gap > chatX
)
}).length,
occupiedChatCountByLane = Array.from({
length: 2 * userConfig.laneCount - 1,
}).map(() => 0)
let laneNum =
flowChat.lane < chatsByLane.length &&
0 === occupiedChatCount(chatsByLane[flowChat.lane])
? flowChat.lane
: chatsByLane.findIndex((chats, i) => {
const count = occupiedChatCount(chats)
return (occupiedChatCountByLane[i] = count), 0 === count
})
return (
-1 === laneNum &&
([[laneNum]] = [...occupiedChatCountByLane.entries()].sort(
(a, b) => a[1] - b[1]
)),
laneNum
)
})(flowChat, progress, flowChats, mainState, userConfig)
const laneY = ((lane, mainState, userConfig) => {
const { laneCount } = userConfig,
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 = duration),
(flowChat.animation = flowChat.element.animate(
[
{
transform: `translate(${mainState.playerRect.width}px, ${laneY}px)`,
},
{ transform: `translate(-100%, ${laneY}px)` },
],
{ duration, easing: userConfig.timingFunction }
)),
(flowChat.animation.currentTime = newTime),
mainState.videoPlaying
? flowChat.animation.play()
: flowChat.animation.pause(),
(flowChat.animation.onfinish = () => {
flowChat.animationEnded = !0
})
}
const assert_lib = __webpack_require__(494).assert,
tapNonNull = x => (assert_lib(null != x), x),
parseMessage = (lengthBefore, message, userConfig) => {
const { maxChatLength } = userConfig
let html = "",
length = lengthBefore
return (
message.innerHTML.split(/(?=<img)|">/g).some(part => {
if (part.match(/^<img/)) {
if (!userConfig.textOnly) {
const src = part.match(/src="(\\.|[^"\\])*"/g)
;(html += `<img ${src} style="height: 1em">`), (length += 1)
}
} else
(html +=
part.length >= maxChatLength
? part.substr(0, maxChatLength)
: part),
(length += part.length)
return length >= maxChatLength
}),
{ html, length }
)
},
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 logFyc = (...x) => external_log_default().info(`【FYC】 ${x}`),
createBanButton = (chat, id, userConfig) => {
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.023,74.977c-99.984-99.969-262.063-99.969-362.047,0c-99.969,99.984-99.969,262.063,0,362.047c99.969,99.969,262.078,99.969,362.047,0S536.992,174.945,437.023,74.977z M137.211,137.211c54.391-54.391,137.016-63.453,201.016-27.531L109.68,338.227C73.758,274.227,82.82,191.602,137.211,137.211z M374.805,374.789c-54.391,54.391-137.031,63.469-201.031,27.547l228.563-228.563C438.258,237.773,429.18,320.414,374.805,374.789z" fill-rule="evenodd"></path></svg></div>'),
(button.onclick = () => {
logFyc(`Added to Banned Users: ${id}`),
userConfig.bannedUsers.push(id),
GM.setValue("FYC_NG_USERS", userConfig.bannedUsers.join("\n")),
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)
},
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
},
stylizeChat = (flowChat, userConfig) => {
const fontSize = (userConfig => {
var _a, _b
return (
Math.round(
(userConfig.fontSize - 0.2) *
((null !==
(_b =
null === (_a = livePage_getMainVideo()) || void 0 === _a
? void 0
: _a.clientHeight) && void 0 !== _b
? _b
: 0) /
userConfig.laneCount) *
100
) / 100
)
})(userConfig),
offset = userConfig.shadowFontWeight,
{ style } = flowChat.element
;(style.visibility = userConfig.displayChats ? "visible" : "hidden"),
(style.color = flowChat.color),
(style.fontSize = `${fontSize}px`),
(style.fontWeight = userConfig.fontWeight.toString()),
(style.fontFamily = userConfig.font),
(style.opacity = userConfig.chatOpacity.toString()),
(style.textShadow = `-${offset}px -${offset}px #000, ${offset}px -${offset}px #000, -${offset}px ${offset}px #000, ${offset}px ${offset}px #000`)
},
chatFieldObserver = (chatScrn, flowChats, mainState, userConfig) =>
new MutationObserver(mutations => {
mutations.forEach(e => {
Array.from(e.addedNodes)
.filter(x => x.children.length > 0)
.forEach(chat => {
const chatData = ((chat, userConfig) => {
let html = "",
length = 0
const isMember = Boolean(chat.querySelector(".member"))
let authorID
const color = chat.querySelector(".owner")
? userConfig.ownerColor
: chat.querySelector(".moderator")
? userConfig.moderatorColor
: isMember
? userConfig.memberColor
: userConfig.color
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 &&
(chat.querySelector(".moderator") &&
!0 === userConfig.displayModeratorName &&
(html += `<span style="font-size: smaller;">${
null == authorName ? void 0 : authorName.innerText
}: </span>`),
message)
) {
const result = parseMessage(
length,
message,
userConfig
)
;(html += result.html), (length += result.length)
}
if ("author-photo" === childID) {
const matches = (
(null === (_a = child.lastElementChild) ||
void 0 === _a
? void 0
: _a.getAttribute("src")) || ""
).match(/ytc\/(.*)=/)
authorID =
null == matches
? void 0
: matches[matches.length - 1]
}
if ("card" === childID) {
const paidAmount =
child.querySelector("#purchase-amount") ||
child.querySelector("#purchase-amount-chip")
if (
child.matches(
[
".style-scope",
".yt-live-chat-paid-message-renderer",
].join("")
)
) {
const header = tapNonNull(
child.querySelector("#header")
),
content = child.querySelector("#content"),
headerColor = window
.getComputedStyle(header)
.getPropertyValue("background-color"),
paidColor = window
.getComputedStyle(content)
.getPropertyValue("background-color")
if (message) {
const result = parseMessage(
length,
message,
userConfig
)
;(html += `<span style="color: ${headerColor}; font-size: smaller;">${
null == authorName
? void 0
: authorName.innerText
}: </span><span style="color: ${headerColor};">${
result.html
}</span><span style="color: ${paidColor}; font-size: smaller;"><strong>${
null == paidAmount
? void 0
: paidAmount.innerText
}</strong></span>`),
(length +=
result.length +
(null !==
(_b =
null == paidAmount
? void 0
: paidAmount.innerText.length) &&
void 0 !== _b
? _b
: 0))
}
authorID = void 0
}
if (
child.matches(
[
".style-scope",
".yt-live-chat-paid-sticker-renderer",
].join("")
)
) {
const headerColor = window
.getComputedStyle(chat)
.getPropertyValue(
"--yt-live-chat-paid-sticker-chip-background-color"
),
amountColor = window
.getComputedStyle(chat)
.getPropertyValue(
"--yt-live-chat-paid-sticker-background-color"
)
;(html += `<span style="color: ${headerColor};">${
null == authorName ? void 0 : authorName.innerText
}: </span>`),
(html += `<span style="color: ${amountColor}; font-size: smaller;"><strong>${
null == paidAmount
? void 0
: paidAmount.innerText
}</strong></span>`),
(length +=
null !==
(_d =
null ===
(_c =
null == paidAmount
? void 0
: paidAmount.innerText) ||
void 0 === _c
? void 0
: _c.length) && void 0 !== _d
? _d
: 0),
(authorID = void 0)
}
}
}),
{ html, length, color, authorID }
)
})(chat, userConfig)
;((chatData, userConfig) =>
userConfig.bannedWords.some(
word =>
!!chatData.html.includes(word) &&
(external_log_default().debug(
`Banned Word: "${word}" in "${chatData.html}"`
),
!0)
))(chatData, userConfig) ||
((chatData, userConfig) =>
userConfig.bannedWordRegexs.some(word => {
const result = chatData.html.match(word)
return (
!!result &&
(external_log_default().debug(
`Banned Word: "${result}" in "${chatData.html}"`
),
!0)
)
}))(chatData, userConfig) ||
((chatData, userConfig) =>
Boolean(chatData.authorID) &&
userConfig.bannedUsers.some(user => {
var _a
const result =
null === (_a = chatData.authorID) || void 0 === _a
? void 0
: _a.match(user)
return (
!!result &&
(external_log_default().debug(
`Banned User: "${result}" in "${chatData.html}"`
),
!0)
)
}))(chatData, userConfig)
? (chat.style.display = "none")
: ((chat.style.display =
chat.querySelectorAll(
".style-scope.yt-live-chat-paid-message-renderer"
).length > 0
? "block"
: "flex"),
userConfig.createChats &&
((
chatData,
flowChats,
chatScrn,
mainState,
userConfig
) => {
let element
const offScreenChatIndex = flowChats.findIndex(
chat =>
chat.animationEnded ||
flowChats.length >= userConfig.maxChatCount
)
;-1 !== offScreenChatIndex
? ((element =
flowChats[offScreenChatIndex].element),
flowChats.splice(offScreenChatIndex, 1))
: (external_log_default().debug("CreateFlowChat"),
(element = document.createElement("span")),
chatScrn.append(element)),
element.classList.add("fyc_chat")
const flowChat = {
element,
lane: 0,
animation: void 0,
animationDuration: 0,
animationEnded: !1,
length: chatData.length,
color: chatData.color,
}
;(element.innerHTML = chatData.html),
stylizeChat(flowChat, userConfig),
animateChat(
flowChat,
flowChats,
mainState,
userConfig
),
flowChats.push(flowChat)
})(
chatData,
flowChats,
chatScrn,
mainState,
userConfig
),
userConfig.createBanButtons &&
chatData.authorID &&
!chat.querySelector(".owner") &&
createBanButton(chat, chatData.authorID, userConfig),
((chat, simplify) => {
if (
((chat.style.borderBottom = simplify
? "1px solid var(--yt-spec-text-secondary)"
: "none"),
chat.querySelector(
".style-scope.yt-live-chat-paid-message-renderer"
) || chat.querySelector(".owner"))
)
return
const authorPhoto = chat.querySelector("#author-photo")
authorPhoto &&
(authorPhoto.style.display = simplify
? "none"
: "block")
const authorChip = chat.querySelector(
"yt-live-chat-author-chip.style-scope.yt-live-chat-text-message-renderer"
)
authorChip &&
(authorChip.style.display = simplify
? "none"
: "inline-flex")
})(chat, userConfig.simplifyChatField))
})
})
}),
componentMounter = (root, placeRoot) => component => {
const success = placeRoot(root)
return success && external_m_default().mount(root, component), success
},
createScriptCss = () => {
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 animation-fill-mode: none;\n will-change: transform;\n transform: translate(-100%);\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 animation-fill-mode: none;\n will-change: transform;\n transform: translate(-100%);\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 }")
}
var delay = __webpack_require__(228),
delay_default = __webpack_require__.n(delay)
const setChatFrameCss = async () => (
await delay_default()(700),
(async (func, count, interval) => {
let exception,
succeed = !1
for (let i = 0; i < count; i += 1) {
try {
await func(i), (succeed = !0)
break
} catch (e) {
exception = e
}
external_log_default().debug("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
)
),
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),
]),
textColorRow = (color, textStyle, oninput) =>
external_m_default()("div", [
external_m_default()("input", {
type: "text",
size: 10,
maxlength: 30,
value: color,
oninput,
}),
external_m_default()(
"span",
{ style: { ...textStyle, color } },
"Aa1あア亜"
),
]),
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
},
langRecord = {
FYC_EN: {
language: "Language",
font: "Font",
color: "Color(Normal)",
ownerColor: "Color(Owner)",
moderatorColor: "Color(Moderator)",
memberColor: "Color(Member)",
feedback: "Give your feedbacks here",
chatOpacity: "Opacity",
fontSize: "Size",
fontWeight: "Weight",
shadowFontWeight: "Weight(Shadow)",
flowSpeed: "Speed",
maxChatCount: "Max number of chats",
maxChatLength: "Max number of characters",
laneCount: "Number of Line",
bannedWords: "Banned Words",
bannedWordRegexs: "Banned Words(Regex)",
bannedUsers: "Banned Users",
simplifyChatField: "Simplify",
createBanButton: "Show ban button",
displayModeratorName: "Show moderator's name",
createChats: "Display flowing chats",
textOnly: "Text only(ignore emojis)",
reload: "Reload",
save: "Save",
error: "Error",
video: "Video",
chatField: "Chat Window",
useStepTiming: "Move chat in steps",
timingStepCount: "└Step Count",
},
FYC_JA: {
language: "言語",
font: "フォント",
color: "色(通常)",
ownerColor: "色(オーナー)",
moderatorColor: "色(モデレーター)",
memberColor: "色(メンバー)",
feedback: "バグ報告、要望はこちら",
chatOpacity: "透明度",
fontSize: "サイズ",
fontWeight: "太さ",
shadowFontWeight: "太さ(影)",
flowSpeed: "速度",
maxChatCount: "最大表示数",
maxChatLength: "最大文字数",
laneCount: "行数",
bannedWords: "NGワード",
bannedWordRegexs: "NGワード(正規表現)",
bannedUsers: "NGユーザー",
simplifyChatField: "簡略化する",
createBanButton: "NGボタンを表示する",
displayModeratorName: "モデレータの名前を表示する",
createChats: "チャットを流す",
textOnly: "文字のみ(絵文字を無視する)",
reload: "再読み込み",
save: "保存",
error: "エラー",
video: "画面",
chatField: "チャット欄",
useStepTiming: "チャットを段階的に動かす",
timingStepCount: "└段階数",
},
},
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,
recreateCss,
mainState,
state,
userConfig
) => {
var _a, _b
const exampleTextStyle = () => ({
fontFamily: userConfig.font,
fontWeight: userConfig.fontWeight.toString(),
}),
panelState = {
bannedWordRegexs: userConfig.bannedWordRegexs,
bannedWordRegexsValid: !0,
bannedWordRegexsError: "",
currentBanTab: 0,
timingStepCount: parseInt(
null !==
(_b =
null ===
(_a = userConfig.timingFunction.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.match(/^steps\(.+/)),
panelBoxStyle = { flex: "0 0 212px", margin: "2px" },
textAreaStyle = {
resize: "horizontal",
boxSizing: "border-box",
width: "100%",
},
fieldSetStyle = { border: "solid 1px", padding: "3px" },
getLang = () => langRecord[userConfig.lang],
langSelectChange$ = new external_rxjs_namespaceObject.Subject(),
fontSelectChange$ = new external_rxjs_namespaceObject.Subject(),
colorInputInput$ = new external_rxjs_namespaceObject.Subject(),
colorOwnerInputInput$ = new external_rxjs_namespaceObject.Subject(),
colorModeratorInputInput$ = new external_rxjs_namespaceObject.Subject(),
colorMemberInputInput$ = new external_rxjs_namespaceObject.Subject(),
chatOpacityInputInput$ = new external_rxjs_namespaceObject.Subject(),
fontSizeInputInput$ = new external_rxjs_namespaceObject.Subject(),
fontWeightInputInput$ = new external_rxjs_namespaceObject.Subject(),
shadowFontWeightInputInput$ = new external_rxjs_namespaceObject.Subject(),
flowSpeedInputInput$ = new external_rxjs_namespaceObject.Subject(),
maxChatCountInputInput$ = new external_rxjs_namespaceObject.Subject(),
maxChatLengthInputInput$ = new external_rxjs_namespaceObject.Subject(),
laneCountInputInput$ = new external_rxjs_namespaceObject.Subject(),
banTabChange$ = new external_rxjs_namespaceObject.Subject(),
bannedWordsTextAreaChange$ = new external_rxjs_namespaceObject.Subject(),
bannedWordRegexsTextAreaChange$ = new external_rxjs_namespaceObject.Subject(),
bannedUsersTextAreaChange$ = new external_rxjs_namespaceObject.Subject(),
simplifyChatFieldInputChange$ = new external_rxjs_namespaceObject.Subject(),
createBanButtonInputChange$ = new external_rxjs_namespaceObject.Subject(),
displayModeratorNameInputChange$ = new external_rxjs_namespaceObject.Subject(),
createChatsInputChange$ = new external_rxjs_namespaceObject.Subject(),
textOnlyInputChange$ = new external_rxjs_namespaceObject.Subject(),
useStepTimingInputChange$ = new external_rxjs_namespaceObject.Subject(),
timingStepCountInputChange$ = new external_rxjs_namespaceObject.Subject()
return (
(0, external_rxjs_namespaceObject.merge)(
langSelectChange$.pipe(
(0, external_rxjs_operators_namespaceObject.map)(getInputValue),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
;(userConfig.lang = x), GM.setValue("FYC_LANG", x)
})
),
fontSelectChange$.pipe(
(0, external_rxjs_operators_namespaceObject.map)(getInputValue),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
;(userConfig.font = x), GM.setValue("FYC_FONT", x)
})
),
colorInputInput$.pipe(
(0, external_rxjs_operators_namespaceObject.map)(getInputValue),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
;(userConfig.color = x), GM.setValue("FYC_COLOR", x)
})
),
colorOwnerInputInput$.pipe(
(0, external_rxjs_operators_namespaceObject.map)(getInputValue),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
;(userConfig.ownerColor = x),
GM.setValue("FYC_COLOR_OWNER", x)
})
),
colorModeratorInputInput$.pipe(
(0, external_rxjs_operators_namespaceObject.map)(getInputValue),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
;(userConfig.moderatorColor = x),
GM.setValue("FYC_COLOR_MODERATOR", x)
})
),
colorMemberInputInput$.pipe(
(0, external_rxjs_operators_namespaceObject.map)(getInputValue),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
;(userConfig.memberColor = x),
GM.setValue("FYC_COLOR_MEMBER", x)
})
),
chatOpacityInputInput$.pipe(
(0, external_rxjs_operators_namespaceObject.map)(getInputValue),
(0, external_rxjs_operators_namespaceObject.map)(parseFloat),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
;(userConfig.chatOpacity = x), GM.setValue("FYC_OPACITY", x)
})
),
fontSizeInputInput$.pipe(
(0, external_rxjs_operators_namespaceObject.map)(getInputValue),
(0, external_rxjs_operators_namespaceObject.map)(parseFloat),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
;(userConfig.fontSize = x), GM.setValue("FYC_SIZE", x)
})
),
fontWeightInputInput$.pipe(
(0, external_rxjs_operators_namespaceObject.map)(getInputValue),
(0, external_rxjs_operators_namespaceObject.map)(parseFloat),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
;(userConfig.fontWeight = x), GM.setValue("FYC_WEIGHT", x)
})
),
shadowFontWeightInputInput$.pipe(
(0, external_rxjs_operators_namespaceObject.map)(getInputValue),
(0, external_rxjs_operators_namespaceObject.map)(parseFloat),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
;(userConfig.shadowFontWeight = x),
GM.setValue("FYC_WEIGHT_SHADOW", x)
})
),
flowSpeedInputInput$.pipe(
(0, external_rxjs_operators_namespaceObject.map)(getInputValue),
(0, external_rxjs_operators_namespaceObject.map)(parseFloat),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
;(userConfig.flowSpeed = x), GM.setValue("FYC_SPEED", x)
})
),
maxChatCountInputInput$.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.maxChatCount = x),
((flowChats, maxChatCount) => {
flowChats
.splice(0, Math.max(0, flowChats.length - maxChatCount))
.forEach(x => {
external_log_default().debug("RemoveOldChat"),
x.element.remove()
})
})(flowChats, x),
GM.setValue("FYC_LIMIT", x)
})
),
maxChatLengthInputInput$.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.maxChatLength = x), GM.setValue("FYC_MAX", x)
})
),
laneCountInputInput$.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.laneCount = x), GM.setValue("FYC_LANE_DIV", x)
})
),
banTabChange$.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.currentBanTab = x
})
),
bannedWordsTextAreaChange$.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 = x),
GM.setValue("FYC_NG_WORDS", x.join("\n"))
})
),
bannedWordRegexsTextAreaChange$.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 {
new RegExp(regex)
} catch (error) {
logFyc(`Invalid Regex: ${regex}`),
external_log_default().warn(error),
(panelState.bannedWordRegexsError += `${error} in ${regex};`),
(valid = !1)
}
}),
valid &&
((userConfig.bannedWordRegexs = x),
GM.setValue("FYC_NG_REG_WORDS", x.join("\n"))),
(panelState.bannedWordRegexsValid = valid)
})
),
bannedUsersTextAreaChange$.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 = x),
GM.setValue("FYC_NG_USERS", x.join("\n"))
})
),
simplifyChatFieldInputChange$.pipe(
(0, external_rxjs_operators_namespaceObject.map)(
getInputChecked
),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
;(userConfig.simplifyChatField = x),
GM.setValue("FYC_SIMPLE_CHAT_FIELD", x)
})
),
createBanButtonInputChange$.pipe(
(0, external_rxjs_operators_namespaceObject.map)(
getInputChecked
),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
;(userConfig.createBanButtons = x),
GM.setValue("FYC_NG_BUTTON", x)
})
),
displayModeratorNameInputChange$.pipe(
(0, external_rxjs_operators_namespaceObject.map)(
getInputChecked
),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
;(userConfig.displayModeratorName = x),
GM.setValue("FYC_DISPLAY_MODERATOR_NAME", x)
})
),
createChatsInputChange$.pipe(
(0, external_rxjs_operators_namespaceObject.map)(
getInputChecked
),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
;(userConfig.createChats = x),
GM.setValue("FYC_TOGGLE_CREATE_COMMENTS", x)
})
),
textOnlyInputChange$.pipe(
(0, external_rxjs_operators_namespaceObject.map)(
getInputChecked
),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
;(userConfig.textOnly = x), GM.setValue("FYC_TEXT_ONLY", x)
})
),
useStepTimingInputChange$.pipe(
(0, external_rxjs_operators_namespaceObject.map)(
getInputChecked
),
(0, external_rxjs_operators_namespaceObject.tap)(x => {
;(userConfig.timingFunction = x
? stepTiming(panelState.timingStepCount)
: "linear"),
GM.setValue(
"FYC_TIMING_FUNCTION",
userConfig.timingFunction
)
})
),
timingStepCountInputChange$.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 = stepTiming(x)),
GM.setValue(
"FYC_TIMING_FUNCTION",
userConfig.timingFunction
)
})
)
)
.pipe(
(0, external_rxjs_operators_namespaceObject.tap)(() => {
flowChats
.filter(chat => !chat.animationEnded)
.forEach(chat => {
stylizeChat(chat, userConfig),
animateChat(chat, flowChats, mainState, userConfig)
})
})
)
.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,
display: "flex",
position: "absolute",
bottom: "40px",
right: "0px",
padding: "6px",
color: "#fff",
fontSize: "14px",
width: "648px",
border: "solid 1px #666",
},
},
[
external_m_default()("div", { style: panelBoxStyle }, [
settingRow(getLang().language, [
external_m_default()(
"select",
{
style: { width: "60%" },
selectedIndex: langOptions.findIndex(
x => x[0] === userConfig.lang
),
onchange: lib(langSelectChange$),
},
langOptions.map(x => settingPanel_option(...x))
),
]),
settingRow(getLang().font, [
external_m_default()(
"select",
{
style: { width: "60%" },
selectedIndex: fontOptions.findIndex(
x => x[0] === userConfig.font
),
onchange: lib(fontSelectChange$),
},
fontOptions.map(x =>
settingPanel_option(
x[0],
"FYC_JA" === userConfig.lang ? x[2] : x[1]
)
)
),
]),
settingRow(getLang().color, [
textColorRow(
userConfig.color,
exampleTextStyle(),
lib(colorInputInput$)
),
]),
settingRow(getLang().ownerColor, [
textColorRow(
userConfig.ownerColor,
exampleTextStyle(),
lib(colorOwnerInputInput$)
),
]),
settingRow(getLang().moderatorColor, [
textColorRow(
userConfig.moderatorColor,
exampleTextStyle(),
lib(colorModeratorInputInput$)
),
]),
settingRow(getLang().memberColor, [
textColorRow(
userConfig.memberColor,
exampleTextStyle(),
lib(colorMemberInputInput$)
),
]),
external_m_default()(
"div",
{ style: { textAlign: "right", margin: "3px 6px" } },
external_m_default()(
"a",
{
style: { color: "white" },
href:
"https://gf.qytechs.cn/en/scripts/411442-flow-youtube-chat/feedback",
target: "_blank",
},
getLang().feedback
)
),
]),
external_m_default()("div", { style: panelBoxStyle }, [
settingRow(getLang().chatOpacity, [
rangeRow(
0,
1,
0.05,
userConfig.chatOpacity,
lib(chatOpacityInputInput$)
),
]),
settingRow(getLang().fontSize, [
rangeRow(
0.1,
2,
0.1,
userConfig.fontSize,
lib(fontSizeInputInput$)
),
]),
settingRow(getLang().fontWeight, [
rangeRow(
10,
1e3,
10,
userConfig.fontWeight,
lib(fontWeightInputInput$)
),
]),
settingRow(getLang().shadowFontWeight, [
rangeRow(
0,
3,
0.1,
userConfig.shadowFontWeight,
lib(shadowFontWeightInputInput$)
),
]),
settingRow(getLang().flowSpeed, [
rangeRow(
1,
50,
1,
userConfig.flowSpeed,
lib(flowSpeedInputInput$)
),
]),
settingRow(getLang().maxChatCount, [
rangeRow(
5,
200,
5,
userConfig.maxChatCount,
lib(maxChatCountInputInput$)
),
]),
settingRow(getLang().maxChatLength, [
rangeRow(
5,
200,
5,
userConfig.maxChatLength,
lib(maxChatLengthInputInput$)
),
]),
settingRow(getLang().laneCount, [
rangeRow(
1,
20,
1,
userConfig.laneCount,
lib(laneCountInputInput$)
),
]),
]),
external_m_default()("div", { style: panelBoxStyle }, [
((labels = [
getLang().bannedWords,
getLang().bannedWordRegexs,
getLang().bannedUsers,
]),
(tabs = [
[
external_m_default()(
"textarea",
{
rows: 4,
style: textAreaStyle,
onchange: lib(bannedWordsTextAreaChange$),
},
userConfig.bannedWords.join("\n")
),
],
[
external_m_default()(
"span",
panelState.bannedWordRegexsValid
? ""
: `${getLang().error}: ${
panelState.bannedWordRegexsError
}`
),
external_m_default()(
"textarea",
{
rows: 4,
style: textAreaStyle,
onchange: lib(bannedWordRegexsTextAreaChange$),
},
panelState.bannedWordRegexs.join("\n")
),
],
[
external_m_default()(
"textarea",
{
rows: 4,
style: textAreaStyle,
onchange: lib(bannedUsersTextAreaChange$),
},
userConfig.bannedUsers.join("\n")
),
],
]),
(currentTab = panelState.currentBanTab),
(onchange = lib(banTabChange$)),
external_m_default()("div", [
external_m_default()(
"select",
{
style: { width: "100%" },
selectedIndex: currentTab,
onchange,
},
labels.map((x, i) =>
settingPanel_option(i.toString(), x)
)
),
...tabs.map((x, i) =>
external_m_default()(
"div",
{
style: {
display: i === currentTab ? "block" : "none",
},
},
x
)
),
])),
external_m_default()(
"fieldset",
{ style: fieldSetStyle },
[
external_m_default()("legend", getLang().chatField),
checkboxRow(
getLang().simplifyChatField,
userConfig.simplifyChatField,
lib(simplifyChatFieldInputChange$)
),
checkboxRow(
getLang().createBanButton,
userConfig.createBanButtons,
lib(createBanButtonInputChange$)
),
]
),
external_m_default()(
"fieldset",
{ style: fieldSetStyle },
[
external_m_default()("legend", getLang().video),
checkboxRow(
getLang().displayModeratorName,
userConfig.displayModeratorName,
lib(displayModeratorNameInputChange$)
),
checkboxRow(
getLang().createChats,
userConfig.createChats,
lib(createChatsInputChange$)
),
checkboxRow(
getLang().textOnly,
userConfig.textOnly,
lib(textOnlyInputChange$)
),
checkboxRow(
getLang().useStepTiming,
useStepTiming(),
lib(useStepTimingInputChange$)
),
external_m_default()(
"div",
{
style: {
display: useStepTiming() ? "block" : "none",
},
},
settingRow(getLang().timingStepCount, [
rangeRow(
1,
400,
1,
panelState.timingStepCount,
lib(timingStepCountInputChange$)
),
])
),
]
),
]),
]
)
var labels, tabs, currentTab, onchange
},
}
)
},
settingComponent = (flowChats, recreateCss, mainState, userConfig) => {
const state = { showPanel: !1 },
panel = settingPanel(flowChats, 0, mainState, state, userConfig),
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.17L136.02 58.22L136.65 58.29L137.3 58.39L137.95 58.52L138.61 58.66L139.27 58.83L139.94 59.01L140.61 59.22L141.29 59.45L141.98 59.7L142.66 59.96L143.35 60.25L144.05 60.55L144.74 60.87L145.44 61.2L146.15 61.55L146.85 61.92L147.56 62.3L148.27 62.69L148.97 63.1L149.69 63.52L150.4 63.95L151.11 64.4L196.98 91.31L197.88 90.81L206.8 86.34L215.92 82.22L216.84 81.84L216.84 224.11L214.42 226.66L210.89 230.67L207.51 234.82L204.29 239.1L201.23 243.51L198.33 248.04L195.6 252.69L193.05 257.45L190.68 262.32L188.49 267.29L186.49 272.36L184.67 277.53L183.06 282.79L181.65 288.14L180.44 293.57L179.44 299.08L178.66 304.65L178.09 310.3L177.75 316.01L177.63 321.78L177.75 327.56L178.09 333.27L178.66 338.91L179.44 344.49L180.44 350L181.65 355.43L183.06 360.77L184.67 366.04L186.49 371.2L188.49 376.28L190.68 381.25L193.05 386.12L195.6 390.88L198.33 395.53L201.23 400.06L204.29 404.47L207.51 408.75L210.89 412.89L214.42 416.91L218.1 420.78L221.92 424.51L225.88 428.08L229.97 431.51L234.2 434.77L238.54 437.87L243.01 440.81L247.6 443.57L252.3 446.16L257.1 448.56L262.01 450.78L267.02 452.81L272.12 454.65L277.31 456.28L282.59 457.72L287.95 458.94L293.38 459.95L298.89 460.75L304.46 461.32L310.09 461.67L315.79 461.78L321.48 461.67L327.12 461.32L332.69 460.75L338.2 459.95L343.63 458.94L348.99 457.72L354.27 456.28L359.46 454.65L364.56 452.81L369.57 450.78L374.48 448.56L379.28 446.16L383.98 443.57L388.57 440.81L393.03 437.87L397.38 434.77L401.61 431.51L405.7 428.08L409.66 424.51L413.48 420.78L417.16 416.91L420.69 412.89L424.07 408.75L427.29 404.47L430.35 400.06L433.25 395.53L435.97 390.88L438.53 386.12L440.9 381.25L443.09 376.28L445.09 371.2L446.9 366.04L448.52 360.77L449.93 355.43L451.14 350L452.14 344.49L452.92 338.91L453.49 333.27L453.83 327.56L453.95 321.78L453.83 316.01L453.77 314.95L487.06 314.95L627.33 378.59L627.31 378.6L626.83 379L626.32 379.38L625.8 379.75L625.25 380.11L624.68 380.47L624.1 380.81L623.5 381.15L622.87 381.48L622.24 381.8L621.58 382.11L620.91 382.42L620.22 382.72L619.52 383.01L618.81 383.31L618.08 383.59L617.34 383.87L616.58 384.15L615.82 384.43L615.04 384.7L614.26 384.98L613.46 385.25L612.66 385.52L611.84 385.78L560.61 399.62L559.29 403.96L555.92 413.56L552.21 422.99L548.14 432.23L543.73 441.27L543.23 442.18L569.79 488.66L570.23 489.38L570.65 490.1L571.07 490.82L571.47 491.54L571.86 492.26L572.24 492.98L572.6 493.69L572.94 494.4L573.27 495.11L573.59 495.82L573.89 496.52L574.17 497.22L574.43 497.92L574.67 498.61L574.9 499.3L575.1 499.98L575.29 500.65L575.45 501.33L575.59 501.99L575.71 502.65L575.81 503.31L575.89 503.96L575.94 504.6L575.96 505.23L575.97 505.85L575.94 506.47L575.89 507.08L575.81 507.68L575.71 508.27L575.58 508.86L575.42 509.43L575.22 510L575 510.55L574.75 511.09L574.47 511.63L574.16 512.15L573.81 512.66L573.44 513.16L573.03 513.64L572.58 514.12L505.59 582L505.12 582.45L504.65 582.86L504.16 583.24L503.67 583.58L503.16 583.89L502.65 584.16L502.12 584.4L501.59 584.61L501.05 584.79L500.5 584.93L499.94 585.05L499.38 585.14L498.8 585.2L498.22 585.23L497.63 585.24L497.03 585.22L496.42 585.18L495.8 585.11L495.18 585.02L494.55 584.9L493.91 584.77L493.26 584.61L492.61 584.44L491.95 584.24L491.28 584.03L490.6 583.8L489.92 583.55L489.23 583.29L488.54 583.01L487.83 582.71L487.13 582.41L486.41 582.09L485.69 581.76L484.96 581.42L484.23 581.06L483.49 580.7L482.74 580.33L481.99 579.95L481.23 579.56L480.47 579.17L434.6 552.26L433.7 552.76L424.78 557.23L415.66 561.35L406.36 565.12L396.89 568.53L392.6 569.87L378.95 621.78L378.68 622.61L378.42 623.42L378.15 624.23L377.88 625.03L377.61 625.81L377.34 626.59L377.06 627.35L376.78 628.1L376.5 628.84L376.21 629.57L375.92 630.28L375.62 630.97L375.32 631.65L375.01 632.32L374.69 632.96L374.37 633.59L374.04 634.2L373.7 634.8L373.35 635.37L372.99 635.92L372.63 636.46L372.25 636.97L371.86 637.46L371.46 637.92L371.05 638.37L370.63 638.79L370.19 639.18L369.74 639.55L369.28 639.89L368.8 640.21L368.31 640.5L367.81 640.76L367.29 641L366.75 641.2L366.19 641.38L365.62 641.52L365.03 641.64L364.43 641.72L363.8 641.77L363.16 641.78L268.42 641.78L267.78 641.77L267.14 641.72L266.53 641.64L265.93 641.52L265.34 641.38L264.77 641.2L264.22 641L263.68 640.76L263.15 640.5L262.63 640.21L262.13 639.89L261.64 639.55L261.17 639.18L260.71 638.79L260.26 638.37L259.83 637.92L259.4 637.46L258.99 636.97L258.59 636.46L258.21 635.92L257.83 635.37L257.47 634.8L257.11 634.2L256.77 633.59L256.44 632.96L256.12 632.32L255.81 631.65L255.51 630.97L255.22 630.28L254.94 629.57L254.67 628.84L254.41 628.1L254.16 627.35L253.91 626.59L253.68 625.81L253.45 625.03L253.24 624.23L253.03 623.42L252.82 622.61L252.63 621.78L238.98 569.87L234.69 568.53L225.22 565.12L215.92 561.35L206.8 557.23L197.88 552.76L196.8 552.17L151.11 578.98L150.4 579.42L149.69 579.86L148.97 580.28L148.27 580.68L147.56 581.08L146.85 581.46L146.15 581.83L145.44 582.18L144.74 582.51L144.05 582.83L143.35 583.13L142.66 583.42L141.98 583.68L141.29 583.93L140.61 584.16L139.94 584.36L139.27 584.55L138.61 584.72L137.95 584.86L137.3 584.98L136.65 585.08L136.02 585.16L135.38 585.21L134.76 585.24L134.14 585.24L133.53 585.21L132.93 585.16L132.34 585.08L131.75 584.98L131.18 584.84L130.61 584.68L130.05 584.49L129.51 584.26L128.97 584.01L128.45 583.73L127.93 583.41L127.43 583.06L126.94 582.68L126.46 582.26L125.99 581.81L59 513.93L58.55 513.45L58.15 512.97L57.78 512.48L57.44 511.98L57.14 511.46L56.87 510.94L56.63 510.41L56.42 509.87L56.25 509.33L56.1 508.77L55.99 508.2L55.9 507.63L55.84 507.05L55.81 506.45L55.8 505.85L55.82 505.25L55.86 504.63L55.93 504.01L56.02 503.37L56.13 502.73L56.27 502.09L56.42 501.43L56.59 500.77L56.78 500.1L57 499.42L57.22 498.74L57.47 498.05L57.73 497.35L58 496.64L58.29 495.93L58.59 495.21L58.91 494.49L59.24 493.76L59.57 493.02L59.92 492.28L60.28 491.53L60.65 490.77L61.02 490.01L61.4 489.24L61.79 488.47L88.29 442.09L87.85 441.27L83.44 432.23L79.37 422.99L75.65 413.56L72.29 403.96L70.96 399.62L19.74 385.78L18.92 385.52L18.12 385.25L17.32 384.98L16.54 384.7L15.76 384.43L15 384.15L14.24 383.87L13.5 383.59L12.77 383.31L12.06 383.01L11.36 382.72L10.67 382.42L10 382.11L9.34 381.8L8.7 381.48L8.08 381.15L7.48 380.81L6.9 380.47L6.33 380.11L5.78 379.75L5.26 379.38L4.75 379L4.27 378.6L3.81 378.2L3.37 377.78L2.96 377.35L2.57 376.91L2.2 376.46L1.87 375.99L1.55 375.51L1.27 375.01L1.01 374.5L0.78 373.97L0.57 373.42L0.4 372.86L0.26 372.28L0.15 371.68L0.07 371.07L0.02 370.44L0 369.78L0 273.78L0.02 273.13L0.07 272.49L0.15 271.87L0.26 271.26L0.4 270.67L0.57 270.09L0.78 269.52L1.01 268.98L1.27 268.44L1.55 267.92L1.87 267.41L2.2 266.92L2.57 266.44L2.96 265.97L3.37 265.52L3.81 265.07L4.27 264.65L4.75 264.23L5.26 263.83L5.78 263.43L6.33 263.05L6.9 262.68L7.48 262.33L8.08 261.98L8.7 261.64L9.34 261.32L10 261L10.67 260.7L11.36 260.41L12.06 260.12L12.77 259.85L13.5 259.58L14.24 259.33L15 259.08L15.76 258.84L16.54 258.62L17.32 258.4L18.12 258.18L18.92 257.98L19.74 257.78L70.96 243.95L72.29 239.6L75.65 230L79.37 220.58L83.44 211.34L87.85 202.3L88.35 201.39L61.79 154.91L61.4 154.13L61.02 153.37L60.65 152.61L60.28 151.85L59.92 151.1L59.57 150.36L59.24 149.62L58.91 148.89L58.59 148.16L58.29 147.45L58 146.73L57.73 146.03L57.47 145.33L57.22 144.64L57 143.96L56.78 143.28L56.59 142.61L56.42 141.95L56.27 141.29L56.13 140.64L56.02 140L55.93 139.37L55.86 138.75L55.82 138.13L55.8 137.52L55.81 136.92L55.84 136.33L55.9 135.75L55.99 135.17L56.1 134.61L56.25 134.05L56.42 133.5L56.63 132.96L56.87 132.43L57.14 131.91L57.44 131.4L57.78 130.9L58.15 130.41L58.55 129.92L59 129.45L125.99 61.57L126.46 61.12L126.94 60.7L127.43 60.32L127.93 59.97L128.45 59.65L128.97 59.37L129.51 59.11L130.05 58.89L130.61 58.7L131.18 58.53L131.75 58.4L132.34 58.29L132.93 58.21L133.53 58.16L134.14 58.14L134.76 58.14L135.38 58.17ZM576.75 2.01L579.53 2.29L582.28 2.69L584.99 3.18L587.66 3.79L590.29 4.49L592.88 5.3L595.42 6.2L597.92 7.2L600.37 8.29L602.76 9.47L605.11 10.75L607.39 12.11L609.62 13.55L611.79 15.08L613.9 16.68L615.94 18.37L617.91 20.13L619.82 21.96L621.65 23.87L623.41 25.84L625.1 27.89L626.71 29.99L628.23 32.16L629.68 34.39L631.04 36.68L632.31 39.02L633.49 41.42L634.59 43.86L635.58 46.36L636.49 48.91L637.29 51.49L638 54.13L638.6 56.8L639.1 59.51L639.49 62.25L639.77 65.03L639.94 67.84L640 70.68L640 208.48L639.94 211.32L639.77 214.13L639.49 216.91L639.1 219.66L638.6 222.37L638 225.04L637.29 227.67L636.49 230.26L635.58 232.8L634.59 235.3L633.49 237.75L632.31 240.14L631.04 242.49L629.68 244.77L628.23 247L626.71 249.17L625.1 251.28L623.41 253.32L621.65 255.29L619.82 257.2L617.91 259.03L615.94 260.79L613.9 262.48L611.79 264.09L609.62 265.61L607.39 267.06L605.11 268.42L602.76 269.69L601.78 270.18L623.59 340.98L481.84 277.38L326.79 277.38L323.95 277.32L321.14 277.15L318.36 276.87L315.62 276.48L312.91 275.98L310.24 275.38L307.6 274.67L305.02 273.87L302.47 272.96L299.97 271.96L297.53 270.87L295.13 269.69L292.79 268.42L290.5 267.06L288.27 265.61L286.1 264.09L284 262.48L281.95 260.79L279.98 259.03L278.07 257.2L276.24 255.29L274.48 253.32L272.8 251.28L271.19 249.17L269.66 247L268.22 244.77L266.86 242.49L265.59 240.14L264.4 237.75L263.31 235.3L262.31 232.8L261.41 230.26L260.6 227.67L259.9 225.04L259.29 222.37L258.8 219.66L258.41 216.91L258.12 214.13L257.95 211.32L257.89 208.48L257.89 70.68L257.95 67.84L258.12 65.03L258.41 62.25L258.8 59.51L259.29 56.8L259.9 54.13L260.6 51.49L261.41 48.91L262.31 46.36L263.31 43.86L264.4 41.42L265.59 39.02L266.86 36.68L268.22 34.39L269.66 32.16L271.19 29.99L272.8 27.89L274.48 25.84L276.24 23.87L278.07 21.96L279.98 20.13L281.95 18.37L284 16.68L286.1 15.08L288.27 13.55L290.5 12.11L292.79 10.75L295.13 9.47L297.53 8.29L299.97 7.2L302.47 6.2L305.02 5.3L307.6 4.49L310.24 3.79L312.91 3.18L315.62 2.69L318.36 2.29L321.14 2.01L323.95 1.84L326.79 1.78L571.1 1.78L573.94 1.84L576.75 2.01Z",
})
),
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 ? "設定" : "Settings"
),
]
),
}
)
})(state, userConfig)
return {
view: () =>
external_m_default()("span", { style: { display: "contents" } }, [
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 = () =>
livePage_getChatFrame() &&
livePage_getChatField() &&
livePage_getPlayer(),
initialize = async () => {
logFyc("Script started")
const userConfig = await (async () => ({
lang: tapNonNull(await GM.getValue("FYC_LANG", "FYC_EN")),
font: tapNonNull(await GM.getValue("FYC_FONT", "")),
chatOpacity: tapNonNull(await GM.getValue("FYC_OPACITY", 1)),
color: tapNonNull(await GM.getValue("FYC_COLOR", "#FFFFFF")),
ownerColor: tapNonNull(
await GM.getValue("FYC_COLOR_OWNER", "#ffd600")
),
moderatorColor: tapNonNull(
await GM.getValue("FYC_COLOR_MODERATOR", "#5e84f1")
),
memberColor: tapNonNull(
await GM.getValue("FYC_COLOR_MEMBER", "#2ba640")
),
fontSize: tapNonNull(await GM.getValue("FYC_SIZE", 1)),
fontWeight: tapNonNull(await GM.getValue("FYC_WEIGHT", 730)),
shadowFontWeight: tapNonNull(
await GM.getValue("FYC_WEIGHT_SHADOW", 1)
),
maxChatCount: tapNonNull(await GM.getValue("FYC_LIMIT", 25)),
flowSpeed: tapNonNull(await GM.getValue("FYC_SPEED", 18)),
maxChatLength: tapNonNull(await GM.getValue("FYC_MAX", 100)),
laneCount: tapNonNull(await GM.getValue("FYC_LANE_DIV", 12)),
bannedWords: tapNonNull(await GM.getValue("FYC_NG_WORDS", ""))
.split(/\r\n|\n/)
.filter(x => "" !== x),
bannedWordRegexs: tapNonNull(
await GM.getValue("FYC_NG_REG_WORDS", "")
)
.split(/\r\n|\n/)
.filter(x => "" !== x),
bannedUsers: tapNonNull(await GM.getValue("FYC_NG_USERS", ""))
.split(/\r\n|\n/)
.filter(x => "" !== x),
createChats: tapNonNull(
await GM.getValue("FYC_TOGGLE_CREATE_COMMENTS", !0)
),
displayChats: tapNonNull(
await GM.getValue("FYC_DISPLAY_COMMENTS", !0)
),
createBanButtons: tapNonNull(
await GM.getValue("FYC_NG_BUTTON", !0)
),
simplifyChatField: tapNonNull(
await GM.getValue("FYC_SIMPLE_CHAT_FIELD", !1)
),
displayModeratorName: tapNonNull(
await GM.getValue("FYC_DISPLAY_MODERATOR_NAME", !0)
),
textOnly: tapNonNull(await GM.getValue("FYC_TEXT_ONLY", !1)),
timingFunction: tapNonNull(
await GM.getValue("FYC_TIMING_FUNCTION", "linear")
),
}))(),
reinitSubject = new external_rxjs_namespaceObject.Subject(),
reinitialize = lib(reinitSubject),
chatScrn = (() => {
const element = document.createElement("div")
return (
element.classList.add("fyc_chat_screen"),
(element.style.pointerEvents = "none"),
(element.style.zIndex = "30"),
element
)
})(),
flowChats = []
let chatField, video, player
const mainState = { videoPlaying: !1, playerRect: new DOMRect() }
let storedHref = window.location.href
new MutationObserver(async () => {
storedHref !== window.location.href &&
((storedHref = window.location.href),
logFyc("URL Changed", storedHref),
await reinitialize())
}).observe(document, { childList: !0, subtree: !0 })
const chatObserver = chatFieldObserver(
chatScrn,
flowChats,
mainState,
userConfig
),
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
flowChats.forEach(x => {
x.element.style.visibility = newDisplay
? "visible"
: "hidden"
}),
(userConfig.displayChats = newDisplay),
GM.setValue("FYC_DISPLAY_COMMENTS", newDisplay)
})
)
.subscribe()
const label = () =>
"チャット" + (userConfig.displayChats ? "非表示" : "表示")
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:
"M 11 12 L 28 12 Q 29 12 29 13 L 29 22 Q 29 23 28 23 L 27 23 L 27 25 L 23 23 L 11 23 Q 10 23 10 22 L 10 13 Q 10 12 11 12 Z",
fill: "#fff",
"fill-opacity": userConfig.displayChats ? "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), (x.style.display = "contents")),
Boolean(parent)
)
}
),
settingComp = settingComponent(flowChats, 0, mainState, userConfig),
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),
(x.style.display = "contents")),
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
const chatFieldDetached =
chatField &&
!(null ===
(_b =
null === (_a = livePage_getChatFrame()) ||
void 0 === _a
? void 0
: _a.contentDocument) || void 0 === _b
? void 0
: _b.contains(chatField)) &&
!document.contains(chatField),
logDetached = x => `${x} detached, will reload...`
chatFieldDetached &&
(logDetached("Chat field"), (chatField = void 0))
const videoDetached = video && !document.contains(video)
videoDetached &&
(logDetached("Video"),
(video = void 0),
(mainState.videoPlaying = !1))
const playerDetached = player && !document.contains(player)
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 =>
logFyc(
x
? "Found the chat container and the player"
: "Waiting to load..."
)
),
(0, external_rxjs_operators_namespaceObject.filter)(Boolean)
)
),
(0, external_rxjs_operators_namespaceObject.tap)(() =>
logFyc("Wait for 2300ms...")
),
(0, external_rxjs_operators_namespaceObject.delay)(2300),
(0, external_rxjs_operators_namespaceObject.tap)(() =>
logFyc("Initializing...")
),
(0, external_rxjs_operators_namespaceObject.tap)(() => {
var _a
flowChats.splice(0, flowChats.length).forEach(chat => {
chat.element.remove()
}),
chatObserver.disconnect(),
(chatField = livePage_getChatField()),
chatField &&
chatObserver.observe(chatField, { childList: !0 }),
(video = livePage_getMainVideo()),
video &&
(external_log_default().debug("AppendChatScreen"),
(mainState.videoPlaying = !video.paused),
null === (_a = livePage_getPlayer()) ||
void 0 === _a ||
_a.insertAdjacentElement("afterbegin", chatScrn)),
playerResizeObserver.disconnect(),
(player = livePage_getPlayer()),
player && playerResizeObserver.observe(player),
mountToggleChatBtn(toggleChatBtn),
mountSettingComp(settingComp),
createScriptCss(),
(chatField && video && player) || reinitialize()
}),
(0, external_rxjs_operators_namespaceObject.switchMap)(
setChatFrameCss
),
(0, external_rxjs_operators_namespaceObject.switchMap)(() =>
(0, external_rxjs_namespaceObject.merge)(
...(video
? [
videoToggleStream(video).pipe(
(0, external_rxjs_operators_namespaceObject.tap)(
playing => {
;(mainState.videoPlaying = playing),
flowChats.forEach(chat => {
animateChat(
chat,
flowChats,
mainState,
userConfig
)
})
}
)
),
]
: []),
playerResizeSubject.pipe(
(0, external_rxjs_operators_namespaceObject.debounceTime)(
800
),
(0, external_rxjs_operators_namespaceObject.startWith)([]),
(0, external_rxjs_operators_namespaceObject.tap)(() => {
var _a
logFyc("Resize detected"),
(mainState.playerRect =
null !==
(_a =
null == player
? void 0
: player.getBoundingClientRect()) &&
void 0 !== _a
? _a
: new DOMRect()),
flowChats.forEach(chat => {
stylizeChat(chat, userConfig),
animateChat(chat, flowChats, mainState, userConfig)
})
})
)
)
),
(0, external_rxjs_operators_namespaceObject.retryWhen)(x =>
x.pipe(
(0, external_rxjs_operators_namespaceObject.tap)(() =>
logFyc("Errored:")
),
(0, external_rxjs_operators_namespaceObject.tap)(
external_log_default().warn
)
)
)
)
.subscribe(),
await reinitialize()
}
;(async () => {
external_log_namespaceObject.setLevel("info")
try {
await initialize()
} catch (error) {
external_log_namespaceObject.error(error)
}
})()
})()
})()