Flow Youtube Chat

Youtubeのチャットをニコニコ風に画面上へ流すスクリプトです(再アップ,絵文字バグ修正済み)

目前为 2021-02-08 提交的版本。查看 最新版本

// ==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)
        }
      })()
    })()
})()

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址