YouTube 超快聊天

YouTube直播聊天的终极性能提升

当前为 2025-06-12 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name YouTube Super Fast Chat
  3. // @version 0.102.12
  4. // @license MIT
  5. // @name:ja YouTube スーパーファーストチャット
  6. // @name:zh-TW YouTube 超快聊天
  7. // @name:zh-CN YouTube 超快聊天
  8. // @icon https://raw.githubusercontent.com/cyfung1031/userscript-supports/main/icons/super-fast-chat.png
  9. // @namespace UserScript
  10. // @match https://www.youtube.com/live_chat*
  11. // @match https://www.youtube.com/live_chat_replay*
  12. // @author CY Fung
  13. // @run-at document-start
  14. // @grant none
  15. // @unwrap
  16. // @allFrames true
  17. // @inject-into page
  18. // @require https://update.greasyfork.org/scripts/475632/1361351/ytConfigHacks.js
  19. // @require https://cdn.jsdelivr.net/gh/cyfung1031/userscript-supports@c2b707e4977f77792042d4a5015fb188aae4772e/library/nextBrowserTick.min.js
  20. //
  21. // @compatible firefox Violentmonkey
  22. // @compatible firefox Tampermonkey
  23. // @compatible firefox FireMonkey
  24. // @compatible chrome Violentmonkey
  25. // @compatible chrome Tampermonkey
  26. // @compatible opera Violentmonkey
  27. // @compatible opera Tampermonkey
  28. // @compatible safari Stay
  29. // @compatible edge Violentmonkey
  30. // @compatible edge Tampermonkey
  31. // @compatible brave Violentmonkey
  32. // @compatible brave Tampermonkey
  33. //
  34. // @description Ultimate Performance Boost for YouTube Live Chats
  35. // @description:ja YouTubeのライブチャットの究極のパフォーマンスブースト
  36. // @description:zh-TW YouTube直播聊天的終極性能提升
  37. // @description:zh-CN YouTube直播聊天的终极性能提升
  38. //
  39. // ==/UserScript==
  40.  
  41. ((__CONTEXT__) => {
  42. 'use strict';
  43.  
  44. /** @type {WeakMapConstructor} */
  45. const WeakMap = window.WeakMapOriginal || window.WeakMap;
  46.  
  47. const DEBUG_LOG_GROUP_EXPAND = +localStorage.__debugSuperFastChat__ > 0;
  48. const DEBUG_LOG_HIDE_OK = true;
  49. const DEBUG_skipLog001 = true;
  50. const DEBUG_preprocessChatLiveActions = false;
  51. const DEBUG_customCreateComponent = false;
  52. // const SHOW_DEVTOOL_DEBUG = true; // for debug use
  53. const SHOW_DEVTOOL_DEBUG = typeof ResizeObserver === 'function' && CSS.supports('position-area:center');
  54.  
  55. // *********** DON'T REPORT NOT WORKING DUE TO THE CHANGED SETTINGS ********************
  56. // The settings are FIXED! You might change them to try but if the script does not work due to your change, please, don't report them as issues
  57.  
  58. /// -------------------------------------------------------------------------
  59.  
  60. const USE_ADVANCED_TICKING = true; // DONT CHANGE
  61. // << if USE_ADVANCED_TICKING >>
  62. const FIX_TIMESTAMP_FOR_REPLAY = true;
  63. const ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION = true; // MUST BE true
  64. const REUSE_TICKER = true; // for better memory control; currently it is only available in ADVANCED_TICKING; to be further reviewed << NO EFFECT SINCE ENABLE_TICKERS_BOOSTED_STAMPING IS USED >>
  65. // << end >>
  66.  
  67. const ENABLE_CHAT_MESSAGES_BOOSTED_STAMPING = true; // TRUE to boost chat messages rendering (DONT CHANGE)
  68. const ENABLE_TICKERS_BOOSTED_STAMPING = true; // TRUE to boost chat messages rendering (DONT CHANGE)
  69. const DISABLE_DYNAMIC_TICKER_WIDTH = true; // We use the opacity change instead
  70. const FIX_REMOVE_TICKER_ITEM_BY_ID = true; // TRUE by default
  71.  
  72. /// -------------------------------------------------------------------------
  73.  
  74. // ENABLE_REDUCED_MAXITEMS_FOR_FLUSH and MAX_ITEMS_FOR_FULL_FLUSH are removed due to ENABLE_CHAT_MESSAGES_BOOSTED_STAMPING is introduced
  75.  
  76. // const ENABLE_REDUCED_MAXITEMS_FOR_FLUSH = true; // TRUE to enable trimming down to MAX_ITEMS_FOR_FULL_FLUSH (25) messages when there are too many unrendered messages
  77. const MAX_ITEMS_FOR_TOTAL_DISPLAY = 90; // By default, 250 latest messages will be displayed, but displaying MAX_ITEMS_FOR_TOTAL_DISPLAY (90) messages is already sufficient. (not exceeding 900)
  78. // const MAX_ITEMS_FOR_FULL_FLUSH = 25; // If there are too many new (stacked) messages not yet rendered, clean all and flush MAX_ITEMS_FOR_FULL_FLUSH (25) latest messages then incrementally added back to MAX_ITEMS_FOR_TOTAL_DISPLAY (90) messages. (not exceeding 900)
  79.  
  80. const ENABLE_NO_SMOOTH_TRANSFORM = true; // Depends on whether you want the animation effect for new chat messages <<< DON'T CHANGE >>>
  81. // const USE_OPTIMIZED_ON_SCROLL_ITEMS = true; // TRUE for the majority
  82. const ENABLE_OVERFLOW_ANCHOR_PREFERRED = true; // Enable `overflow-anchor: auto` to lock the scroll list at the bottom for no smooth transform. (Safari is not supported)
  83.  
  84. const FIX_SHOW_MORE_BUTTON_LOCATION = true; // When there are voting options (bottom panel), move the "show more" button to the top.
  85. const FIX_INPUT_PANEL_OVERFLOW_ISSUE = true; // When the super chat button is flicking with color, the scrollbar might come out.
  86. const FIX_INPUT_PANEL_BORDER_ISSUE = true; // No border should be allowed if there is an empty input panel.
  87. const SET_CONTAIN_FOR_CHATROOM = true; // Rendering hacks (`contain`) for chatroom elements. [ General ]
  88.  
  89. const FORCE_CONTENT_VISIBILITY_UNSET = true; // Content-visibility should be always VISIBLE for high performance and great rendering.
  90. const FORCE_WILL_CHANGE_UNSET = true; // Will-change should be always UNSET (auto) for high performance and low energy impact.
  91.  
  92. // Replace requestAnimationFrame timers with custom implementation
  93. const ENABLE_RAF_HACK_TICKERS = true; // When there is a ticker
  94. const ENABLE_RAF_HACK_DOCKED_MESSAGE = true; // To be confirmed
  95. const ENABLE_RAF_HACK_INPUT_RENDERER = true; // To be confirmed
  96. const ENABLE_RAF_HACK_EMOJI_PICKER = true; // When changing the page of the emoji picker
  97.  
  98. // Force rendering all the character subsets of the designated font(s) before messages come (Pre-Rendering of Text)
  99. const ENABLE_FONT_PRE_RENDERING_PREFERRED = 1 | 2 | 4 | 8 | 16;
  100.  
  101. // Backdrop `filter: blur(4px)` inside the iframe can extend to the whole page, causing a negative visual impact on the video you are watching.
  102. const NO_BACKDROP_FILTER_WHEN_MENU_SHOWN = true;
  103.  
  104. // Data Manipulation for Participants (Participant List)
  105. // << if DO_PARTICIPANT_LIST_HACKS >>
  106. const DO_PARTICIPANT_LIST_HACKS = true; // TRUE for the majority
  107. const SHOW_PARTICIPANT_CHANGES_IN_CONSOLE = false; // Just too annoying to show them all in popular chat
  108. const CHECK_CHANGE_TO_PARTICIPANT_RENDERER_CONTENT = true; // Only consider changes in renderable content (not concerned with the last chat message of the participants)
  109. const PARTICIPANT_UPDATE_ONLY_ONLY_IF_MODIFICATION_DETECTED = true;
  110. // << end >>
  111.  
  112. // show more button
  113. const ENABLE_SHOW_MORE_BLINKER = true; // BLINK WHEN NEW MESSAGES COME
  114.  
  115. // faster stampDomArray_ for participants list creation
  116. const ENABLE_FLAGS_MAINTAIN_STABLE_LIST_VAL = 1; // 0 - OFF; 1 - ON; 2 - ON(PARTICIPANTS_LIST ONLY)
  117. const USE_MAINTAIN_STABLE_LIST_ONLY_WHEN_KS_FLAG_IS_SET = false;
  118.  
  119. // reuse yt components
  120. const ENABLE_FLAGS_REUSE_COMPONENTS = true;
  121.  
  122. // ShadyDom Free is buggy
  123. const DISABLE_FLAGS_SHADYDOM_FREE = true;
  124.  
  125. // images <Group#I01>
  126. const AUTHOR_PHOTO_SINGLE_THUMBNAIL = 1; // 0 - disable; 1- smallest; 2- largest
  127. const EMOJI_IMAGE_SINGLE_THUMBNAIL = 1; // 0 - disable; 1- smallest; 2- largest
  128. const LEAST_IMAGE_SIZE = 48; // minium size = 48px
  129.  
  130. const DO_LINK_PREFETCH = true; // DO NOT CHANGE
  131. // << if DO_LINK_PREFETCH >>
  132. const ENABLE_BASE_PREFETCHING = true; // (SUB-)DOMAIN | dns-prefetch & preconnect
  133. const ENABLE_PRELOAD_THUMBNAIL = true; // subresource (prefetch) [LINK for Images]
  134. const SKIP_PRELOAD_EMOJI = true;
  135. const PREFETCH_LIMITED_SIZE_EMOJI = 512; // DO NOT CHANGE THIS
  136. const PREFETCH_LIMITED_SIZE_AUTHOR_PHOTO = 68; // DO NOT CHANGE THIS
  137. // << end >>
  138.  
  139. const FIX_SETSRC_AND_THUMBNAILCHANGE_ = true; // Function Replacement for yt-img-shadow....
  140. const FIX_THUMBNAIL_DATACHANGED = true; // Function Replacement for yt-live-chat-author-badge-renderer..dataChanged
  141. // const REMOVE_PRELOADAVATARFORADDACTION = false; // Function Replacement for yt-live-chat-renderer..preloadAvatarForAddAction
  142.  
  143. const FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION = true; // important [depends on <Group#I01>]
  144. const FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT = true; // [depends on <Group#I01>]
  145.  
  146. // BROWSER SUPPORT: Chrome 75+, Edge 79+, Safari 13.1+, Firefox 63+, Opera 62+
  147. const TICKER_MAX_STEPS_LIMIT = 500; // NOT LESS THAN 5 STEPS!!
  148. // (( KEEP AS ALTERNATIVE IF USE_ADVANCED_TICKING NOT WORKING ))
  149. // [limiting 500 max steps] is recommended for "confortable visual change"
  150. // min. step increment 0.2% => max steps: 500 => 800ms per each update
  151. // min. step increment 0.5% => max steps: 200 => 1000ms per each update
  152. // min. step increment 1.0% => max steps: 100 => 1000ms per each update
  153. // min. step increment 2.5% => max steps: 40 => 1000ms per each update
  154. // min. step increment 5.0% => max steps: 20 => 1250ms per each update
  155. const ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX = true; // for video playback's ticker issue. [ Playback Replay - Pause at Middle - Backwards Seeking ]
  156. const SKIP_VIDEO_PLAYBACK_PROGRESS_STATE_FIX_FOR_NO_TIMEFX = false; // debug use; yt-live-chat-ticker-renderer might not require ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX
  157. // << end >>
  158.  
  159. const FIX_TOOLTIP_DISPLAY = true; // changed in 2024.05.02; updated in 2025.01.10
  160. const USE_VANILLA_DEREF = true;
  161. const FIX_DROPDOWN_DERAF = true; // DONT CHANGE
  162.  
  163.  
  164. const CACHE_SHOW_CONTEXT_MENU_FOR_REOPEN = true; // cache the menu data and used for the next reopen
  165. const ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU = false; // pause auto scroll faster when the context menu is about to show
  166. const ENABLE_MUTEX_FOR_SHOW_CONTEXT_MENU = true; // avoid multiple requests on the same time
  167.  
  168. const BOOST_MENU_OPENCHANGED_RENDERING = true;
  169. const FIX_CLICKING_MESSAGE_MENU_DISPLAY_ON_MOUSE_CLICK = true; // click again = close
  170. const NO_ITEM_TAP_FOR_NON_STATIONARY_TAP = true; // dont open the menu (e.g. text message) if cursor is moved or long press
  171. const TAP_ACTION_DURATION = 280; // exceeding 280ms would not consider as a tap action
  172. const PREREQUEST_CONTEXT_MENU_ON_MOUSE_DOWN = true; // require CACHE_SHOW_CONTEXT_MENU_FOR_REOPEN = true
  173. // const FIX_MENU_CAPTURE_SCROLL = true;
  174. const CHAT_MENU_REFIT_ALONG_SCROLLING = 0; // 0 for locking / default; 1 for unlocking only; 2 for unlocking and refit
  175.  
  176. const RAF_FIX_keepScrollClamped = true;
  177. const RAF_FIX_scrollIncrementally = 2; // 0: no action; 1: basic fix; 2: also fix scroll position
  178.  
  179. // << if BOOST_MENU_OPENCHANGED_RENDERING >>
  180. const FIX_MENU_POSITION_N_SIZING_ON_SHOWN = 1; // correct size and position when the menu dropdown opens
  181.  
  182. const CHECK_JSONPRUNE = true; // This is a bug in Brave
  183. // << end >>
  184.  
  185. // const LIVE_CHAT_FLUSH_ON_FOREGROUND_ONLY = false;
  186.  
  187. const CHANGE_MANAGER_UNSUBSCRIBE = true;
  188.  
  189. const INTERACTIVITY_BACKGROUND_ANIMATION = 1; // mostly for pinned message
  190. // 0 = default Yt animation background [= no fix];
  191. // 1 = disable default animation background [= keep special animation];
  192. // 2 = disable all animation backgrounds [= no animation backbround]
  193.  
  194. const CLOSE_TICKER_PINNED_MESSAGE_WHEN_HEADER_CLICKED = true;
  195.  
  196. const MAX_TOOLTIP_NO_WRAP_WIDTH = '72vw'; // '' for disable; accept values like '60px', '25vw'
  197.  
  198. const DISABLE_Translation_By_Google = true;
  199.  
  200. const FASTER_ICON_RENDERING = true;
  201.  
  202. const DELAY_FOCUSEDCHANGED = true;
  203.  
  204. const skipErrorForhandleAddChatItemAction_ = true; // currently depends on ENABLE_NO_SMOOTH_TRANSFORM
  205. const fixChildrenIssue801 = true; // if __children801__ is set [fix polymer controller method extration for `.set()`]
  206.  
  207. const SUPPRESS_refreshOffsetContainerHeight_ = true; // added in FEB 2024; true for default layout options; no effect if ENABLE_NO_SMOOTH_TRANSFORM is false
  208.  
  209. const NO_FILTER_DROPDOWN_BORDER = true; // added in 2024.03.02
  210.  
  211. const FIX_ANIMATION_TICKER_TEXT_POSITION = true; // CSS fix; experimental; added in 2024.04.07
  212. const FIX_AUTHOR_CHIP_BADGE_POSITION = true;
  213.  
  214. const FIX_ToggleRenderPolymerControllerExtractionBug = false; // to be reviewed
  215.  
  216. const REACTION_ANIMATION_PANEL_CSS_FIX = true;
  217.  
  218. const FIX_UNKNOWN_BUG_FOR_OVERLAY = true; // no .prepare() in backdrop element. reason is unknown.
  219.  
  220. const FIX_MOUSEOVER_FN = true; // avoid onMouseOver_ being triggerd quite a lot
  221.  
  222. // -------------------------------
  223.  
  224. const USE_OBTAIN_LCR_BY_BOTH_METHODS = false; // true for play safe
  225.  
  226. const FIX_MEMORY_LEAKAGE_TICKER_ACTIONMAP = true; // To fix Memory Leakage in yt-live-chat-ticker-...-item-renderer
  227. const FIX_MEMORY_LEAKAGE_TICKER_STATSBAR = true; // To fix Memory Leakage in updateStatsBarAndMaybeShowAnimation
  228. const FIX_MEMORY_LEAKAGE_TICKER_TIMER = true; // To fix Memory Leakage in setContainerWidth, slideDown, collapse // Dec 2024 fix in advance tickering
  229. const FIX_MEMORY_LEAKAGE_TICKER_DATACHANGED_setContainerWidth = true; // To fix Memory Leakage due to _.ytLiveChatTickerItemBehavior.setContainerWidth()
  230.  
  231.  
  232. // const USE_RM_ON_FOUNTAIN_MODEL = false; // No longer working since 2025.04.15
  233. // const DEBUG_RM_ON_FOUNTAIN_MODEL = false;
  234. // const FOUNTAIN_MODEL_TIME_CONFIRM = 1600; // 800 not sufficient; re-adding?
  235. const MODIFY_EMIT_MESSAGES_FOR_BOOST_CHAT = true; // enabled for boost chat only; instant emit & no background flush
  236.  
  237. /**
  238. *
  239. *
  240. *
  241. *
  242. *
  243. rendererStamperObserver_: function(a, b, c) {
  244. if (c.path == a) {
  245. if (c.value === void 0 && !this.hasDataPath_[a])
  246. return;
  247. this.hasDataPath_[a] = c.value !== void 0
  248. }
  249. this.rendererStamperApplyChangeRecord_(a, b, c)
  250. },
  251.  
  252.  
  253. addStampDomObserverFns_: function() {
  254. for (var a in this.stampDom) {
  255. var b = this.stampDom[a];
  256. b.id ? (this[SQa(b.id)] = this.rendererStamperObserver_.bind(this, a, b.id),
  257. this.hasDataPath_[a] = !1) : Er(new Dn("Bad rendererstamper config",this.is + ":" + a))
  258. }
  259. },
  260. *
  261. *
  262. *
  263. *
  264. *
  265. */
  266.  
  267.  
  268.  
  269.  
  270.  
  271.  
  272. // <<<<< FOR MEMORY LEAKAGE >>>>
  273.  
  274. // ========= EXPLANTION FOR 0.2% @ step timing [min. 0.2%] ===========
  275. /*
  276.  
  277. ### Time Approach
  278.  
  279. // all below values can make the time interval > 250ms
  280. // 250ms (practical value) refers to the minimum frequency for timeupdate in most browsers (typically, shorter timeupdate interval in modern browsers)
  281. if (totalDuration > 400000) stepInterval = 0.2; // 400000ms with 0.2% increment => 800ms
  282. else if (totalDuration > 200000) stepInterval = 0.5; // 200000ms with 0.5% increment => 1000ms
  283. else if (totalDuration > 100000) stepInterval = 1; // 100000ms with 1% increment => 1000ms
  284. else if (totalDuration > 50000) stepInterval = 2; // 50000ms with 2% increment => 1000ms
  285. else if (totalDuration > 25000) stepInterval = 5; // 25000ms with 5% increment => 1250ms
  286.  
  287. ### Pixel Check
  288. // Target Max Pixel Increment < 5px for Short Period Ticker (Rapid Background Change)
  289. // Assume total width <= 99px for short period ticker, like small donation & member welcome
  290. 99px * 5% = 4.95px < 5px [Condition Fulfilled]
  291.  
  292. ### Example - totalDuration = 280000
  293. totalDuration 280000
  294. stepInterval 0.5
  295. numOfSteps = Math.round(100 / stepInterval) = 200
  296. time interval = 280000 / 200 = 1400ms <acceptable>
  297.  
  298. ### Example - totalDuration = 18000
  299. totalDuration 18000
  300. stepInterval 5
  301. numOfSteps = Math.round(100 / stepInterval) = 20
  302. time interval = 18000 / 20 = 900ms <acceptable>
  303.  
  304. ### Example - totalDuration = 5000
  305. totalDuration 5000
  306. stepInterval 5
  307. numOfSteps = Math.round(100 / stepInterval) = 20
  308. time interval = 5000 / 20 = 250ms <threshold value>
  309.  
  310. ### Example - totalDuration = 3600
  311. totalDuration 3600
  312. stepInterval 5
  313. numOfSteps = Math.round(100 / stepInterval) = 20
  314. time interval = 3600 / 20 = 180ms <reasonable for 3600ms ticker>
  315.  
  316. */
  317.  
  318. // =======================================================================================================
  319.  
  320. // AUTOMAICALLY DETERMINED
  321. const ENABLE_FLAGS_MAINTAIN_STABLE_LIST = ENABLE_FLAGS_MAINTAIN_STABLE_LIST_VAL === 1;
  322. const ENABLE_FLAGS_MAINTAIN_STABLE_LIST_FOR_PARTICIPANTS_LIST = ENABLE_FLAGS_MAINTAIN_STABLE_LIST_VAL >= 1;
  323. const CHAT_MENU_SCROLL_UNLOCKING = CHAT_MENU_REFIT_ALONG_SCROLLING >= 1;
  324.  
  325.  
  326. // image sizing code
  327. // (d = (d = KC(a.customThumbnail.thumbnails, 16)) ? lc(oc(d)) : null)
  328.  
  329.  
  330. // function KC(a, b, c, d) {
  331. // d = void 0 === d ? "width" : d;
  332. // if (!a || !a.length)
  333. // return null;
  334. // if (z("kevlar_tuner_should_always_use_device_pixel_ratio")) {
  335. // var e = window.devicePixelRatio;
  336. // z("kevlar_tuner_should_clamp_device_pixel_ratio") ? e = Math.min(e, zl("kevlar_tuner_clamp_device_pixel_ratio")) : z("kevlar_tuner_should_use_thumbnail_factor") && (e = zl("kevlar_tuner_thumbnail_factor"));
  337. // HC = e
  338. // } else
  339. // HC || (HC = window.devicePixelRatio);
  340. // e = HC;
  341. // z("kevlar_tuner_should_always_use_device_pixel_ratio") ? b *= e : 1 < e && (b *= e);
  342. // if (z("kevlar_tuner_min_thumbnail_quality"))
  343. // return a[0].url || null;
  344. // e = a.length;
  345. // if (z("kevlar_tuner_max_thumbnail_quality"))
  346. // return a[e - 1].url || null;
  347. // if (c)
  348. // for (var h = 0; h < e; h++)
  349. // if (0 <= a[h].url.indexOf(c))
  350. // return a[h].url || null;
  351. // for (c = 0; c < e; c++)
  352. // if (a[c][d] >= b)
  353. // return a[c].url || null;
  354. // for (b = e - 1; 0 < b; b--)
  355. // if (a[b][d])
  356. // return a[b].url || null;
  357. // return a[0].url || null
  358. // }
  359.  
  360.  
  361. /// ------
  362.  
  363. // https://www.youtube.com/watch?v=byyvH5t0hKc
  364. // yt-live-chat-ticker-creator-goal-view-model
  365. // no ticker effect on timing
  366.  
  367. /*
  368.  
  369.  
  370. {
  371. "id": "ChwKGkNQS0pyNV9NdG9vREZVYlB6Z2FkRHWFUv2E",
  372. "initialTickerText": {
  373. "content": "Goal",
  374. "styleRuns": [
  375. {
  376. "startIndex": 0,
  377. "length": 4
  378. }
  379. ]
  380. },
  381. "tickerIcon": {
  382. "sources": [
  383. {
  384. "clientResource": {
  385. "imageName": "TARGET_ADD"
  386. }
  387. }
  388. ]
  389. },
  390. "showGoalStatusCommand": {
  391. "innertubeCommand": {
  392. "clickTrackingParams": "CCQQ7NANIhMI58DT_ef5rhMVxMW1Cx4qBzTz",
  393. "showEngagementPanelEndpoint": {
  394. "engagementPanel": {
  395. "engagementPanelSectionListRenderer": {
  396. "header": {
  397. "engagementPanelTitleHeaderRenderer": {
  398. "actionButton": {
  399. "buttonRenderer": {
  400. "icon": {
  401. "iconType": "QUESTION_CIRCLE"
  402. },
  403. "trackingParams": "CCgQ8FsiEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  404. "command": {
  405. "clickTrackingParams": "CCgQ8FsiEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  406. "commandExecutorCommand": {
  407. "commands": [
  408. {
  409. "clickTrackingParams": "CCgQ8FsiEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  410. "liveChatDialogEndpoint": {
  411. "content": {
  412. "liveChatDialogRenderer": {
  413. "trackingParams": "CCkQzS8iEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  414. "title": {
  415. "runs": [
  416. {
  417. "text": "Super Chat Goal"
  418. }
  419. ]
  420. },
  421. "dialogMessages": [
  422. {
  423. "runs": [
  424. {
  425. "text": "Join the fun by participating in the goal! "
  426. },
  427. {
  428. "text": "Learn more.\n",
  429. "navigationEndpoint": {
  430. "clickTrackingParams": "CCkQzS8iEwjm0Iz72rbKBxXT1EQBJekHNQM="
  431. }
  432. }
  433. ]
  434. },
  435. {
  436. "runs": [
  437. {
  438. "text": "How to participate",
  439. "bold": true,
  440. "textColor": 4294967295
  441. },
  442. {
  443. "text": "\n"
  444. },
  445. {
  446. "text": "1. Press \"Continue\"\n2. Purchase a Super Chat \n3. Watch the progress towards the goal\n4. Celebrate achieving it with the community!",
  447. "textColor": 4294967295
  448. }
  449. ]
  450. }
  451. ],
  452. "confirmButton": {
  453. "buttonRenderer": {
  454. "style": "STYLE_MONO_FILLED",
  455. "size": "SIZE_DEFAULT",
  456. "isDisabled": false,
  457. "text": {
  458. "simpleText": "Got it"
  459. },
  460. "trackingParams": "CCoQ8FsiEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  461. "accessibilityData": {
  462. "accessibilityData": {
  463. "label": "Got it"
  464. }
  465. }
  466. }
  467. }
  468. }
  469. }
  470. }
  471. },
  472. {
  473. "clickTrackingParams": "CCgQ8FsiEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  474. "hideEngagementPanelEndpoint": {
  475. "identifier": {
  476. "surface": "ENGAGEMENT_PANEL_SURFACE_LIVE_CHAT",
  477. "tag": "creator_goal_progress_engagement_panel"
  478. }
  479. }
  480. }
  481. ]
  482. }
  483. }
  484. }
  485. },
  486. "trackingParams": "CCUQ040EIhMI58DT_ef5rhMVxMW1Cx4qBzTz"
  487. }
  488. },
  489. "content": {
  490. "sectionListRenderer": {
  491. "contents": [
  492. {
  493. "creatorGoalProgressFlowViewModel": {
  494. "creatorGoalEntityKey": "EgtieXl2SDV0MGhLYyG7BzhF",
  495. "progressFlowButton": {
  496. "buttonViewModel": {
  497. "onTap": {
  498. "innertubeCommand": {
  499. "clickTrackingParams": "CCcQ8FsiEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  500. "commandMetadata": {
  501. "webCommandMetadata": {
  502. "ignoreNavigation": true
  503. }
  504. },
  505. "liveChatPurchaseMessageEndpoint": {
  506. "params": "Q2lrcUp3b1lWVU14ZFdObmIwTmZjMGQzZDE5RmRYVTFhVTF4Y0ZGM0VndGllWGwyU0RWME1HaExZeEFCSUFFNEFFSUNDQUUlM0Q="
  507. }
  508. }
  509. },
  510. "style": "BUTTON_VIEW_MODEL_STYLE_MONO",
  511. "trackingParams": "CCcQ8FsiEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  512. "type": "BUTTON_VIEW_MODEL_TYPE_FILLED",
  513. "titleFormatted": {
  514. "content": "Continue",
  515. "styleRuns": [
  516. {
  517. "startIndex": 0,
  518. "length": 8
  519. }
  520. ]
  521. }
  522. }
  523. },
  524. "progressCountA11yLabel": "Super Chat goal progress: $0 out of $1"
  525. }
  526. }
  527. ],
  528. "trackingParams": "CCYQui8iEwjm0Iz72rbKBxXT1EQBJekHNQM="
  529. }
  530. },
  531. "identifier": {
  532. "surface": "ENGAGEMENT_PANEL_SURFACE_LIVE_CHAT",
  533. "tag": "creator_goal_progress_engagement_panel"
  534. }
  535. }
  536. },
  537. "identifier": {
  538. "surface": "ENGAGEMENT_PANEL_SURFACE_LIVE_CHAT",
  539. "tag": "creator_goal_progress_engagement_panel"
  540. },
  541. "engagementPanelPresentationConfigs": {
  542. "engagementPanelPopupPresentationConfig": {
  543. "popupType": "PANEL_POPUP_TYPE_DIALOG"
  544. }
  545. }
  546. }
  547. }
  548. },
  549. "creatorGoalEntityKey": "EgtieXl2SDV0MGhLYyG7BzhF",
  550. "shouldShowSetUpFlowOnMobile": true,
  551. "a11yLabel": "See Super Chat goal",
  552. "loggingDirectives": {
  553. "trackingParams": "CCQQ7NANIhMI58DT_ef5rhMVxMW1Cx4qBzTz",
  554. "visibility": {
  555. "types": "12"
  556. }
  557. }
  558. }
  559.  
  560.  
  561. */
  562.  
  563.  
  564. // ------
  565.  
  566. const { IntersectionObserver } = __CONTEXT__;
  567. let _x69;
  568. try {
  569. _x69 = document.createAttributeNS("http://www.w3.org/2000/svg", "nil").addEventListener;
  570. } catch (e) { }
  571. const pureAddEventListener = _x69;
  572. if (!pureAddEventListener) return console.warn("pureAddEventListener cannot be obtained.");
  573.  
  574. /** @type {globalThis.PromiseConstructor} */
  575. const Promise = (async () => { })().constructor; // YouTube hacks Promise in WaterFox Classic and "Promise.resolve(0)" nevers resolve.
  576. const [setTimeout_] = [setTimeout];
  577. // let jsonParseFix = null;
  578. const Image_ = Image;
  579. /** @type {typeof HTMLElement} */
  580. const HTMLElement_ = Reflect.getPrototypeOf(HTMLTitleElement);
  581.  
  582. const nextBrowserTick_ = nextBrowserTick;
  583. if (typeof nextBrowserTick_ !== "function" || (nextBrowserTick_.version || 0) < 2) {
  584. console.log('nextBrowserTick is not found.');
  585. return;
  586. }
  587.  
  588. if (!IntersectionObserver) return console.warn("Your browser does not support IntersectionObserver.\nPlease upgrade to the latest version.");
  589. if (typeof WebAssembly !== 'object') return console.warn("Your browser is too old.\nPlease upgrade to the latest version."); // for passive and once
  590.  
  591. if (typeof CSS === 'undefined' || typeof (CSS || 0).supports !== 'function' || !CSS.supports('left', 'clamp(-100%, calc( -100% * 0.5 ), 0%)')) {
  592. return console.warn("Your browser is too old.\nPlease upgrade to the latest version."); // for advanced tickering
  593. }
  594.  
  595.  
  596. // necessity of cssText3_smooth_transform_position to be checked.
  597. const cssText3_smooth_transform_position = ENABLE_NO_SMOOTH_TRANSFORM ? `
  598.  
  599. #item-offset.style-scope.yt-live-chat-item-list-renderer > #items.style-scope.yt-live-chat-item-list-renderer {
  600. position: static !important;
  601. }
  602.  
  603. `: '';
  604.  
  605. // fallback if dummy style fn fails
  606. const cssText4_smooth_transform_forced_props = ENABLE_NO_SMOOTH_TRANSFORM ? `
  607.  
  608. /* optional */
  609. #item-offset.style-scope.yt-live-chat-item-list-renderer {
  610. height: auto !important;
  611. min-height: unset !important;
  612. }
  613.  
  614. #items.style-scope.yt-live-chat-item-list-renderer {
  615. transform: translateY(0px) !important;
  616. }
  617.  
  618. /* optional */
  619.  
  620. `: '';
  621.  
  622. const cssText5 = SET_CONTAIN_FOR_CHATROOM ? `
  623.  
  624. /* ------------------------------------------------------------------------------------------------------------- */
  625.  
  626. yt-live-chat-author-chip #chat-badges.yt-live-chat-author-chip, yt-live-chat-author-chip #chat-badges.yt-live-chat-author-chip yt-live-chat-author-badge-renderer, yt-live-chat-author-chip #chat-badges.yt-live-chat-author-chip yt-live-chat-author-badge-renderer #image, yt-live-chat-author-chip #chat-badges.yt-live-chat-author-chip yt-live-chat-author-badge-renderer #image img {
  627. contain: layout style;
  628. }
  629.  
  630. #items.style-scope.yt-live-chat-item-list-renderer {
  631. contain: layout paint style;
  632. }
  633.  
  634. #item-offset.style-scope.yt-live-chat-item-list-renderer {
  635. contain: style;
  636. }
  637.  
  638. #item-scroller.style-scope.yt-live-chat-item-list-renderer {
  639. contain: size style;
  640. }
  641.  
  642. #contents.style-scope.yt-live-chat-item-list-renderer, #chat.style-scope.yt-live-chat-renderer, img.style-scope.yt-img-shadow[width][height] {
  643. contain: size layout paint style;
  644. }
  645.  
  646. .style-scope.yt-live-chat-ticker-renderer[role="button"][aria-label], .style-scope.yt-live-chat-ticker-renderer[role="button"][aria-label] > #container {
  647. contain: layout paint style;
  648. }
  649.  
  650. yt-live-chat-text-message-renderer.style-scope.yt-live-chat-item-list-renderer, yt-live-chat-membership-item-renderer.style-scope.yt-live-chat-item-list-renderer, yt-live-chat-paid-message-renderer.style-scope.yt-live-chat-item-list-renderer, yt-live-chat-banner-manager.style-scope.yt-live-chat-item-list-renderer {
  651. contain: layout style;
  652. }
  653.  
  654. tp-yt-paper-tooltip[style*="inset"][role="tooltip"] {
  655. contain: layout paint style;
  656. }
  657.  
  658. /* ------------------------------------------------------------------------------------------------------------- */
  659.  
  660. ` : '';
  661.  
  662. const cssText6b_show_more_button = FIX_SHOW_MORE_BUTTON_LOCATION ? `
  663.  
  664. yt-live-chat-renderer[has-action-panel-renderer] #show-more.yt-live-chat-item-list-renderer{
  665. top: 4px;
  666. transition-property: top;
  667. bottom: unset;
  668. }
  669.  
  670. yt-live-chat-renderer[has-action-panel-renderer] #show-more.yt-live-chat-item-list-renderer[disabled]{
  671. top: -42px;
  672. }
  673.  
  674. `: '';
  675.  
  676. const cssText6c_input_panel_overflow = FIX_INPUT_PANEL_OVERFLOW_ISSUE ? `
  677.  
  678. #input-panel #picker-buttons yt-live-chat-icon-toggle-button-renderer#product-picker {
  679. contain: layout style;
  680. }
  681.  
  682. #chat.yt-live-chat-renderer ~ #panel-pages.yt-live-chat-renderer {
  683. overflow: visible;
  684. }
  685.  
  686. `: '';
  687.  
  688. const cssText6d_input_panel_border = FIX_INPUT_PANEL_BORDER_ISSUE ? `
  689.  
  690. html #panel-pages.yt-live-chat-renderer > #input-panel.yt-live-chat-renderer:not(:empty) {
  691. --yt-live-chat-action-panel-top-border: none;
  692. }
  693.  
  694. html #panel-pages.yt-live-chat-renderer > #input-panel.yt-live-chat-renderer.iron-selected > *:first-child {
  695. border-top: 1px solid var(--yt-live-chat-panel-pages-border-color);
  696. }
  697.  
  698. html #panel-pages.yt-live-chat-renderer {
  699. border-top: 0;
  700. border-bottom: 0;
  701. }
  702.  
  703. `: '';
  704.  
  705. const cssText7b_content_visibility_unset = FORCE_CONTENT_VISIBILITY_UNSET ? `
  706.  
  707. img,
  708. yt-img-shadow[height][width],
  709. yt-img-shadow {
  710. content-visibility: visible !important;
  711. }
  712.  
  713. ` : '';
  714.  
  715. const cssText7c_will_change_unset = FORCE_WILL_CHANGE_UNSET ? `
  716.  
  717. /* remove YouTube constant will-change */
  718. /* constant value will slow down the performance; default auto */
  719.  
  720. /* www-player.css */
  721. html .ytp-contextmenu,
  722. html .ytp-settings-menu {
  723. will-change: unset;
  724. }
  725.  
  726. /* frequently matched elements */
  727. html .fill.yt-interaction,
  728. html .stroke.yt-interaction,
  729. html .yt-spec-touch-feedback-shape__fill,
  730. html .yt-spec-touch-feedback-shape__stroke {
  731. will-change: unset;
  732. }
  733.  
  734. /* live_chat_polymer.js */
  735. /*
  736. html .toggle-button.tp-yt-paper-toggle-button,
  737. html #primaryProgress.tp-yt-paper-progress,
  738. html #secondaryProgress.tp-yt-paper-progress,
  739. html #onRadio.tp-yt-paper-radio-button,
  740. html .fill.yt-interaction,
  741. html .stroke.yt-interaction,
  742. html .yt-spec-touch-feedback-shape__fill,
  743. html .yt-spec-touch-feedback-shape__stroke {
  744. will-change: unset;
  745. }
  746. */
  747.  
  748. /* desktop_polymer_enable_wil_icons.js */
  749. /* html .fill.yt-interaction,
  750. html .stroke.yt-interaction, */
  751. html tp-yt-app-header::before,
  752. html tp-yt-iron-list,
  753. html #items.tp-yt-iron-list > *,
  754. html #onRadio.tp-yt-paper-radio-button,
  755. html .toggle-button.tp-yt-paper-toggle-button,
  756. html ytd-thumbnail-overlay-toggle-button-renderer[use-expandable-tooltip] #label.ytd-thumbnail-overlay-toggle-button-renderer,
  757. html #items.ytd-post-multi-image-renderer,
  758. html #items.ytd-horizontal-card-list-renderer,
  759. html #items.yt-horizontal-list-renderer,
  760. html #left-arrow.yt-horizontal-list-renderer,
  761. html #right-arrow.yt-horizontal-list-renderer,
  762. html #items.ytd-video-description-infocards-section-renderer,
  763. html #items.ytd-video-description-music-section-renderer,
  764. html #chips.ytd-feed-filter-chip-bar-renderer,
  765. html #chips.yt-chip-cloud-renderer,
  766. html #items.ytd-merch-shelf-renderer,
  767. html #items.ytd-product-details-image-carousel-renderer,
  768. html ytd-video-preview,
  769. html #player-container.ytd-video-preview,
  770. html #primaryProgress.tp-yt-paper-progress,
  771. html #secondaryProgress.tp-yt-paper-progress,
  772. html ytd-miniplayer[enabled] /* ,
  773. html .yt-spec-touch-feedback-shape__fill,
  774. html .yt-spec-touch-feedback-shape__stroke */ {
  775. will-change: unset;
  776. }
  777.  
  778. /* other */
  779. .ytp-videowall-still-info-content[class],
  780. .ytp-suggestion-image[class] {
  781. will-change: unset !important;
  782. }
  783.  
  784. ` : '';
  785.  
  786. const ENABLE_FONT_PRE_RENDERING = typeof HTMLElement_.prototype.append === 'function' ? (ENABLE_FONT_PRE_RENDERING_PREFERRED || 0) : 0;
  787. const cssText8_fonts_pre_render = ENABLE_FONT_PRE_RENDERING ? `
  788.  
  789. elzm-fonts {
  790. visibility: collapse;
  791. position: fixed;
  792. top: -10px;
  793. left: -10px;
  794. font-size: 10pt;
  795. line-height: 100%;
  796. width: 100px;
  797. height: 100px;
  798. transform: scale(0.1);
  799. transform: scale(0.01);
  800. transform: scale(0.001);
  801. transform-origin: 0 0;
  802. contain: strict;
  803. display: block;
  804.  
  805. pointer-events: none !important;
  806. user-select: none !important;
  807. }
  808.  
  809. elzm-fonts[id]#elzm-fonts-yk75g {
  810. user-select: none !important;
  811. pointer-events: none !important;
  812. }
  813.  
  814. elzm-font {
  815. visibility: collapse;
  816. position: absolute;
  817. line-height: 100%;
  818. width: 100px;
  819. height: 100px;
  820. contain: strict;
  821. display: block;
  822.  
  823. user-select: none !important;
  824. pointer-events: none !important;
  825. }
  826.  
  827. elzm-font::before {
  828. visibility: collapse;
  829. position: absolute;
  830. line-height: 100%;
  831. width: 100px;
  832. height: 100px;
  833. contain: strict;
  834. display: block;
  835.  
  836. content: '0aZ!@#$~^&*()_-+[]{}|;:><?\\0460\\0301\\0900\\1F00\\0370\\0102\\0100\\28EB2\\28189\\26DA0\\25A9C\\249BB\\23F61\\22E8B\\21927\\21076\\2048E\\1F6F5\\FF37\\F94F\\F0B2\\9F27\\9D9A\\9BEA\\9A6B\\98EC\\9798\\9602\\949D\\9370\\926B\\913A\\8FA9\\8E39\\8CC1\\8B26\\8983\\8804\\8696\\8511\\83BC\\828D\\8115\\7F9A\\7E5B\\7D07\\7B91\\7A2C\\78D2\\776C\\7601\\74AA\\73B9\\7265\\70FE\\6FBC\\6E88\\6D64\\6C3F\\6A9C\\6957\\67FE\\66B3\\6535\\63F2\\628E\\612F\\5FE7\\5E6C\\5CEE\\5B6D\\5A33\\58BC\\575B\\5611\\54BF\\536E\\51D0\\505D\\4F22\\4AD1\\41DB\\3B95\\3572\\2F3F\\26FD\\25A1\\2477\\208D\\1D0A\\1FB\\A1\\A3\\B4\\2CB\\60\\10C\\E22\\A5\\4E08\\B0\\627\\2500\\5E\\201C\\3C\\B7\\23\\26\\3E\\D\\20\\25EE8\\1F235\\FFD7\\FA10\\F92D\\9E8B\\9C3E\\9AE5\\98EB\\971D\\944A\\92BC\\9143\\8F52\\8DC0\\8B2D\\8973\\87E2\\8655\\84B4\\82E8\\814A\\7F77\\7D57\\7BC8\\7A17\\7851\\768C\\7511\\736C\\7166\\6F58\\6D7C\\6B85\\69DD\\6855\\667E\\64D2\\62CF\\6117\\5F6C\\5D9B\\5BBC\\598B\\57B3\\5616\\543F\\528D\\50DD\\4F57\\4093\\3395\\32B5\\31C8\\3028\\2F14\\25E4\\24D1\\2105\\2227\\A8\\2D9\\2CA\\2467\\B1\\2020\\2466\\251C\\266B\\AF\\4E91\\221E\\2464\\2266\\2207\\4E32\\25B3\\2463\\2010\\2103\\3014\\25C7\\24\\25BD\\4E18\\2460\\21D2\\2015\\2193\\4E03\\7E\\25CB\\2191\\25BC\\3D\\500D\\4E01\\25\\30F6\\2605\\266A\\40\\2B\\4E16\\7C\\A9\\4E\\21\\1F1E9\\FEE3\\F0A7\\9F3D\\9DFA\\9C3B\\9A5F\\98C8\\972A\\95B9\\94E7\\9410\\92B7\\914C\\8FE2\\8E2D\\8CAF\\8B5E\\8A02\\8869\\86E4\\8532\\83B4\\82A9\\814D\\7FFA\\7ED7\\7DC4\\7CCC\\7BC3\\7ACA\\797C\\783E\\770F\\760A\\74EF\\73E7\\72DD\\719C\\7005\\6ED8\\6DC3\\6CB2\\6A01\\68E1\\6792\\663A\\64F8\\63BC\\623B\\60FA\\5FD1\\5EA3\\5D32\\5BF5\\5AB2\\5981\\5831\\570A\\5605\\5519\\53FB\\52A2\\5110\\4FE3\\4EB8\\3127\\279C\\2650\\254B\\23E9\\207B\\1D34\\2AE\\176\\221A\\161\\200B\\300C\\4E4C\\1F921\\FF78\\FA0A\\F78A\\9EB9\\9D34\\9BD3\\9A6F\\9912\\97C6\\964E\\950C\\93E4\\92E5\\91F0\\90BB\\8F68\\8E18\\8B6C\\89F6\\889B\\874C\\8602\\84B1\\8378\\826E\\8113\\7FB1\\7EAF\\7D89\\7C20\\7AFB\\7988\\7840\\7705\\75CC\\749A\\73B3\\727F\\7113\\6FE8\\6ED6\\6DD3\\6CDA\\6BBB\\6A31\\6900\\67D9\\66A7\\655D\\6427\\630D\\61C6\\60AC\\5F78\\5E34\\5CE0\\5B80\\5A51\\590B\\57A1\\566F\\5551\\543D\\52DB\\518F\\5032\\3A17\\305C\\2749\\264A\\2567\\2476\\2139\\1EC0\\11AF\\2C8\\1AF\\E17\\2190\\2022\\2502\\2312\\2025\\50';
  837.  
  838. user-select: none !important;
  839. pointer-events: none !important;
  840. }
  841.  
  842. `: '';
  843.  
  844. const cssText9_no_backdrop_filter_when_menu_shown = NO_BACKDROP_FILTER_WHEN_MENU_SHOWN ? `
  845. tp-yt-iron-dropdown.yt-live-chat-app ytd-menu-popup-renderer {
  846. -webkit-backdrop-filter: none;
  847. backdrop-filter: none;
  848. }
  849. `: '';
  850.  
  851. const cssText10_show_more_blinker = ENABLE_SHOW_MORE_BLINKER ? `
  852.  
  853. @keyframes blinker-miuzp {
  854. 0%, 60%, 100% {
  855. opacity: 1;
  856. }
  857. 30% {
  858. opacity: 0.6;
  859. }
  860. }
  861.  
  862. yt-icon-button#show-more.has-new-messages-miuzp {
  863. animation: blinker-miuzp 1.74s linear infinite;
  864. }
  865.  
  866. `: '';
  867.  
  868. const cssText11_entire_message_clickable = FIX_CLICKING_MESSAGE_MENU_DISPLAY_ON_MOUSE_CLICK ? `
  869.  
  870. yt-live-chat-paid-message-renderer.yt-live-chat-item-list-renderer[whole-message-clickable] #menu.style-scope[class] {
  871. pointer-events: none !important;
  872. }
  873.  
  874. yt-live-chat-membership-item-renderer.yt-live-chat-item-list-renderer[whole-message-clickable] #menu.style-scope[class] {
  875. pointer-events: none !important;
  876. }
  877.  
  878. yt-live-chat-paid-sticker-renderer.yt-live-chat-item-list-renderer[whole-message-clickable] #menu.style-scope[class] {
  879. pointer-events: none !important;
  880. }
  881.  
  882. yt-live-chat-text-message-renderer.yt-live-chat-item-list-renderer[whole-message-clickable] #menu.style-scope[class] {
  883. pointer-events: none !important; /* TO_BE_REVIEWED */
  884. }
  885.  
  886. yt-live-chat-auto-mod-message-renderer.yt-live-chat-item-list-renderer[whole-message-clickable] #menu.style-scope[class] {
  887. pointer-events: none !important;
  888. }
  889.  
  890. `: '';
  891.  
  892. const cssText12_nowrap_tooltip = MAX_TOOLTIP_NO_WRAP_WIDTH && typeof MAX_TOOLTIP_NO_WRAP_WIDTH === 'string' ? `
  893.  
  894.  
  895. tp-yt-paper-tooltip[role="tooltip"] {
  896. box-sizing: content-box !important;
  897. margin: 0px !important;
  898. padding: 0px !important;
  899. contain: none !important;
  900. }
  901.  
  902. tp-yt-paper-tooltip[role="tooltip"] #tooltip[style-target="tooltip"] {
  903. box-sizing: content-box !important;
  904. display: inline-block;
  905. contain: none !important;
  906. }
  907.  
  908.  
  909. tp-yt-paper-tooltip[role="tooltip"] #tooltip[style-target="tooltip"]{
  910. max-width: ${MAX_TOOLTIP_NO_WRAP_WIDTH};
  911. width: max-content;
  912. text-overflow: ellipsis;
  913. overflow: hidden;
  914. white-space: nowrap;
  915. }
  916.  
  917.  
  918. `: '';
  919.  
  920.  
  921. const cssText13_no_text_select_when_menu_visible = `
  922. [menu-visible] {
  923. --sfc47-text-select: none;
  924. }
  925. [menu-visible] #header[id][class],
  926. [menu-visible] #content[id][class],
  927. [menu-visible] #header[id][class] *,
  928. [menu-visible] #content[id][class] * {
  929. user-select: var(--sfc47-text-select) !important;
  930. }
  931. [menu-visible] #menu {
  932. --sfc47-text-select: inherit;
  933. }
  934. `;
  935.  
  936. const cssText14_NO_FILTER_DROPDOWN_BORDER = NO_FILTER_DROPDOWN_BORDER ? `
  937. yt-live-chat-header-renderer.yt-live-chat-renderer #label.yt-dropdown-menu::before {
  938. border:0;
  939. }
  940. ` : '';
  941.  
  942. const cssText15_FIX_ANIMATION_TICKER_TEXT_POSITION = FIX_ANIMATION_TICKER_TEXT_POSITION ? `
  943. .style-scope.yt-live-chat-ticker-renderer #animation-container[id][class] {
  944. position: relative;
  945. display: grid;
  946. grid-auto-columns: 1fr;
  947. grid-auto-rows: 1fr;
  948. grid-template-columns: repeat(1, 1fr);
  949. gap: 7px;
  950. padding-bottom: 0;
  951. margin-bottom: 0;
  952. padding-top: 0;
  953. align-self: flex-start;
  954. flex-wrap: nowrap;
  955. margin-top: 1px;
  956. }
  957.  
  958. .style-scope.yt-live-chat-ticker-renderer #animation-container > [id][class] {
  959. margin-top: 0px;
  960. margin-bottom: 0px;
  961. flex-direction: row;
  962. flex-wrap: nowrap;
  963. align-items: center;
  964. justify-content: flex-start;
  965. }
  966.  
  967. .style-scope.yt-live-chat-ticker-renderer #animation-container > [id][class]:first-child::after {
  968. content: '補';
  969. visibility: collapse;
  970. display: inline-block;
  971. position: relative;
  972. width: 0;
  973. line-height: 22px;
  974. }
  975.  
  976. ` : '';
  977.  
  978. const cssText16_FIX_AUTHOR_CHIP_BADGE_POSITION = FIX_AUTHOR_CHIP_BADGE_POSITION ? `
  979. #card #author-name-chip > yt-live-chat-author-chip[single-line] {
  980. flex-wrap: nowrap;
  981. white-space: nowrap;
  982. display: inline-flex;
  983. flex-direction: row;
  984. text-wrap: nowrap;
  985. flex-shrink: 0;
  986. align-items: center;
  987. }
  988.  
  989. #card #author-name-chip {
  990. display: inline-flex;
  991. flex-direction: row;
  992. align-items: flex-start;
  993. }
  994. `: '';
  995.  
  996.  
  997. // Example: https://www.youtube.com/watch?v=Xfytz-igsuc
  998. const cssText17_FIX_overwidth_banner_message = `
  999. yt-live-chat-banner-manager#live-chat-banner.style-scope.yt-live-chat-item-list-renderer {
  1000. max-width: 100%;
  1001. box-sizing: border-box;
  1002. }
  1003. `;
  1004.  
  1005.  
  1006. const cssText18_REACTION_ANIMATION_PANEL_CSS_FIX = REACTION_ANIMATION_PANEL_CSS_FIX ? `
  1007. #reaction-control-panel-overlay[class] {
  1008. contain: strict;
  1009. margin: 0;
  1010. padding: 0;
  1011. border: 0;
  1012. box-sizing: border-box;
  1013. will-change: initial;
  1014. }
  1015. #reaction-control-panel-overlay[class] *[class] {
  1016. will-change: initial;
  1017. }
  1018. `: '';
  1019.  
  1020. const cssText19_FOR_ADVANCED_TICKING = USE_ADVANCED_TICKING ? `
  1021.  
  1022. ticker-bg-overlay {
  1023. display: block;
  1024. position: absolute;
  1025. z-index: -1;
  1026. box-sizing: border-box;
  1027. border: 0;
  1028. padding: 0;
  1029. margin: 0;
  1030. width: 200%;
  1031. top: 0;
  1032. bottom: 0;
  1033. left: clamp(-100%, calc( -100% * ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) ), 0%);
  1034. contain: strict;
  1035. pointer-events: none;
  1036. }
  1037. ticker-bg-overlay-end2 {
  1038.  
  1039. all:unset;
  1040. position: fixed;
  1041. display: block;
  1042. margin-left: -0.5px;
  1043. top: 8px;
  1044. left: clamp(-250px, calc( 250px * ( ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) - 1 ) ), 2px);
  1045.  
  1046. width: 1px;
  1047. height: 1px;
  1048. opacity: 0;
  1049. pointer-events: none;
  1050. box-sizing: border-box;
  1051. border: 0;
  1052. padding: 0;
  1053. margin: 0;
  1054. contain: strict;
  1055. z-index: -1;
  1056. visibility: collapse;
  1057.  
  1058.  
  1059. }
  1060.  
  1061.  
  1062. /* .r6-closing-ticker is provided in ADVANCED_TICKING */
  1063. /* so .r6-width-adjustable is only available for ADVANCED_TICKING too */
  1064.  
  1065. /* DO NOT use .r6-width-adjustable ~ .r6-width-adjustable => very laggy */
  1066.  
  1067. /*
  1068. yt-live-chat-ticker-renderer {
  1069. --r6-transition-duration: 0.2s;
  1070. }
  1071.  
  1072. .r6-width-adjustable, .yt-live-chat-ticker-stampdom {
  1073. --r6-transition-duration-v: var(--r6-transition-duration);
  1074. transition: var(--r6-transition-duration-v);
  1075. }
  1076.  
  1077. .r6-width-adjustable-f {
  1078. --r6-transition-duration-v: 0s;
  1079. }
  1080.  
  1081. .r6-closing-ticker[class] {
  1082. --r6-transition-duration-v: var(--r6-transition-duration);
  1083. }
  1084. */
  1085.  
  1086.  
  1087.  
  1088. .r6-width-adjustable {
  1089. --r6-min-width: 0;
  1090. min-width: var(--r6-min-width);
  1091. }
  1092.  
  1093. .r6-width-adjustable-f {
  1094. --r6-min-width: max-content;
  1095. }
  1096.  
  1097. .r6-closing-ticker[class] {
  1098. --r6-min-width: 0;
  1099. }
  1100.  
  1101. ` : '';
  1102.  
  1103. const cssText20_TICKER_SIZING = ENABLE_TICKERS_BOOSTED_STAMPING && DISABLE_DYNAMIC_TICKER_WIDTH ? `
  1104.  
  1105. :root {
  1106. --ticker-items-gap: 8px;
  1107. }
  1108. #ticker-items.yt-live-chat-ticker-renderer {
  1109. position: relative;
  1110. transform: translateZ(1px);
  1111. box-sizing: border-box;
  1112. contain: style;
  1113. display: flex;
  1114. flex-direction: row;
  1115. gap: var(--ticker-items-gap);
  1116. }
  1117. #container.yt-live-chat-ticker-renderer {
  1118. contain: layout paint style;
  1119. }
  1120.  
  1121. .yt-live-chat-ticker-stampdom {
  1122. position: static;
  1123. width: max-content;
  1124. content-visibility:auto;
  1125. }
  1126. .yt-live-chat-ticker-stampdom[class] {
  1127. transition: none;
  1128. }
  1129. .yt-live-chat-ticker-stampdom-container {
  1130. position: static;
  1131. width: max-content;
  1132. content-visibility:auto;
  1133. }
  1134.  
  1135. .yt-live-chat-ticker-stampdom {
  1136. margin-right:0 !important; /* flex gap 8px */
  1137. }
  1138.  
  1139. /* default animation */
  1140. .yt-live-chat-ticker-stampdom {
  1141. animation: ticker-shown-animation 220ms ease-in 0s 1 normal forwards;
  1142. }
  1143. /* default animation */
  1144. @keyframes ticker-shown-animation {
  1145. 0%, 70%, 100% { opacity: 1; }
  1146. 30% { opacity: 0.2; }
  1147. }
  1148.  
  1149.  
  1150. ` : "";
  1151. // const cssText19_FOR_ADVANCED_TICKING = `
  1152.  
  1153. // ticker-bg-overlay {
  1154. // display: block;
  1155. // position: absolute;
  1156. // z-index: -1;
  1157. // box-sizing: border-box;
  1158. // border: 0;
  1159. // padding: 0;
  1160. // margin: 0;
  1161. // width: 200%;
  1162. // top: 0;
  1163. // bottom: 0;
  1164. // left: clamp(-100%, calc( -100% * ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) ), 0%);
  1165. // contain: strict;
  1166. // }
  1167. // /*
  1168. // ticker-bg-overlay-end {
  1169. // position: absolute;
  1170. // right: 0px;
  1171. // top: 50%;
  1172. // display: block;
  1173. // width: 1px;
  1174. // height: 1px;
  1175. // opacity: 0;
  1176. // pointer-events: none;
  1177. // box-sizing: border-box;
  1178. // border: 0;
  1179. // padding: 0;
  1180. // margin: 0;
  1181. // contain: strict;
  1182. // }
  1183. // */
  1184.  
  1185. // ticker-bg-overlay-end2 {
  1186.  
  1187. // all:unset;
  1188. // position: fixed;
  1189. // display: block;
  1190. // margin-left: -0.5px;
  1191. // top: 8px;
  1192. // left: clamp(-250px, calc( 250px * ( ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) - 1 ) ), 2px);
  1193.  
  1194. // width: 1px;
  1195. // height: 1px;
  1196. // opacity: 0;
  1197. // pointer-events: none;
  1198. // box-sizing: border-box;
  1199. // border: 0;
  1200. // padding: 0;
  1201. // margin: 0;
  1202. // contain: strict;
  1203. // z-index: -1;
  1204. // visibility: collapse;
  1205.  
  1206.  
  1207. // }
  1208.  
  1209. // /* USE_ADVANCED_TICKING */
  1210.  
  1211. // /*
  1212.  
  1213. // .ticker-no-transition-time, .ticker-no-transition-time [id] {
  1214. // transition-duration: 0s !important;
  1215. // }
  1216.  
  1217. // [r6-advanced-ticking] .style-scope.yt-live-chat-ticker-renderer ~ .style-scope.yt-live-chat-ticker-renderer:not(.r6-closing-ticker) {
  1218. // transition-duration: 0s !important;
  1219. // }
  1220.  
  1221. // */
  1222.  
  1223. // .r6-width-adjustable ~ .r6-width-adjustable {
  1224. // --r6-min-width: max-content;
  1225. // }
  1226.  
  1227. // .r6-closing-ticker[class] {
  1228. // --r6-min-width: 0px;
  1229. // }
  1230.  
  1231. // .r6-width-adjustable {
  1232. // min-width: var(--r6-min-width, 0px);
  1233. // }
  1234.  
  1235.  
  1236. // /*
  1237.  
  1238.  
  1239. // .r6-width-adjustable {
  1240. // transition-duration: var(--r6-transition-duration, 0s) !important;
  1241. // }
  1242.  
  1243. // .r6-width-adjustable-first {
  1244. // --r6-transition-duration: 0.2s;
  1245. // }
  1246.  
  1247. // .r6-width-adjustable ~ .r6-width-adjustable-first {
  1248. // --r6-transition-duration: 0s;
  1249. // }
  1250.  
  1251. // .r6-closing-ticker {
  1252. // --r6-transition-duration: 0.2s;
  1253. // }
  1254. // */
  1255.  
  1256. // /*
  1257.  
  1258.  
  1259. // ey.style.position = 'absolute';
  1260. // ey.style.right = '0px';
  1261. // ey.style.top = '50%';
  1262. // ey.style.display='block';
  1263. // ey.style.width='1px';
  1264. // ey.style.height='1px';
  1265. // ey.style.opacity = '0';
  1266.  
  1267. // em.style.display = 'block';
  1268. // em.style.position = 'absolute';
  1269. // em.style.boxSizing = 'border-box';
  1270. // em.style.width = '200%';
  1271. // em.style.top = '0';
  1272. // em.style.bottom = '0';
  1273. // // em.style.height = '100%';
  1274.  
  1275.  
  1276. // // em.style.left = '-50%';
  1277. // // em.style.left = "clamp(-100%, calc( -100% * ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) ), 0%)";
  1278.  
  1279. // */
  1280.  
  1281. // `;
  1282.  
  1283. const addCss = () => `
  1284.  
  1285. yt-live-chat-renderer {
  1286. max-height: 100vh;
  1287. }
  1288.  
  1289. @property --ticker-rtime {
  1290. syntax: "<percentage>";
  1291. inherits: false;
  1292. initial-value: 0%;
  1293. }
  1294.  
  1295. .run-ticker {
  1296. --ticker-bg:linear-gradient(90deg, var(--ticker-c1),var(--ticker-c1) var(--ticker-rtime),var(--ticker-c2) var(--ticker-rtime),var(--ticker-c2));
  1297. }
  1298.  
  1299. .run-ticker,
  1300. yt-live-chat-ticker-renderer #items > * > #container.run-ticker,
  1301. yt-live-chat-ticker-renderer[class] #items[class] > *[class] > #container.run-ticker[class]
  1302. {
  1303. background: var(--ticker-bg) !important;
  1304. }
  1305.  
  1306. yt-live-chat-ticker-dummy777-item-renderer {
  1307. background: #00000001;
  1308. }
  1309.  
  1310. yt-live-chat-ticker-dummy777-item-renderer[dummy777] {
  1311. position: fixed !important;
  1312. top: -1000px !important;
  1313. left: -1000px !important;
  1314. font-size: 1px !important;
  1315. color: transparent !important;
  1316. pointer-events: none !important;
  1317. z-index: -1 !important;
  1318. contain: strict !important;
  1319. box-sizing: border-box !important;
  1320. pointer-events: none !important;
  1321. user-select: none !important;
  1322. max-width: 1px !important;
  1323. max-height: 1px !important;
  1324. overflow: hidden !important;
  1325. visibility: collapse !important;
  1326. display: none !important;
  1327. }
  1328.  
  1329. yt-live-chat-ticker-dummy777-item-renderer #container {
  1330. background: inherit;
  1331. }
  1332.  
  1333.  
  1334. ${cssText8_fonts_pre_render}
  1335.  
  1336. ${cssText9_no_backdrop_filter_when_menu_shown}
  1337.  
  1338. @supports (contain: layout paint style) {
  1339.  
  1340. ${cssText5}
  1341.  
  1342. }
  1343.  
  1344. @supports (color: var(--general)) {
  1345.  
  1346. html {
  1347. --yt-live-chat-item-list-renderer-padding: 0px 0px;
  1348. }
  1349.  
  1350. ${cssText3_smooth_transform_position}
  1351.  
  1352. ${cssText7c_will_change_unset}
  1353.  
  1354. ${cssText7b_content_visibility_unset}
  1355.  
  1356. yt-live-chat-item-list-renderer:not([allow-scroll]) #item-scroller.yt-live-chat-item-list-renderer {
  1357. overflow-y: scroll;
  1358. padding-right: 0;
  1359. }
  1360.  
  1361. ${cssText4_smooth_transform_forced_props}
  1362.  
  1363. yt-icon[icon="down_arrow"] > *, yt-icon-button#show-more > * {
  1364. pointer-events: none !important;
  1365. }
  1366.  
  1367. #continuations, #continuations * {
  1368. contain: strict;
  1369. position: fixed;
  1370. top: 2px;
  1371. height: 1px;
  1372. width: 2px;
  1373. height: 1px;
  1374. visibility: collapse;
  1375. }
  1376.  
  1377. ${cssText6b_show_more_button}
  1378.  
  1379. ${cssText6d_input_panel_border}
  1380.  
  1381. ${cssText6c_input_panel_overflow}
  1382.  
  1383. }
  1384.  
  1385.  
  1386. @supports (overflow-anchor: auto) {
  1387.  
  1388. .no-anchor * {
  1389. overflow-anchor: none;
  1390. }
  1391. .no-anchor > item-anchor {
  1392. overflow-anchor: auto;
  1393. }
  1394. #item-scroller.style-scope.yt-live-chat-item-list-renderer[class] {
  1395. overflow-anchor: initial !important; /* whenever ENABLE_OVERFLOW_ANCHOR or not */
  1396. }
  1397. }
  1398.  
  1399. item-anchor {
  1400.  
  1401. height: 1px;
  1402. width: 100%;
  1403. transform: scaleY(0.00001);
  1404. transform-origin:0 0;
  1405. contain: strict;
  1406. opacity:0;
  1407. display:flex;
  1408. position:relative;
  1409. flex-shrink:0;
  1410. flex-grow:0;
  1411. margin-bottom:0;
  1412. overflow:hidden;
  1413. box-sizing:border-box;
  1414. visibility: visible;
  1415. content-visibility: visible;
  1416. contain-intrinsic-size: auto 1px;
  1417. pointer-events:none !important;
  1418.  
  1419. }
  1420.  
  1421. html item-anchor {
  1422.  
  1423. height: 1px;
  1424. width: 1px;
  1425. top: auto;
  1426. left: auto;
  1427. right: auto;
  1428. bottom: auto;
  1429. transform: translateY(-1px);
  1430. position: absolute;
  1431. z-index: -1;
  1432.  
  1433. }
  1434.  
  1435. @supports (color: var(--pre-rendering)) {
  1436.  
  1437. @keyframes dontRenderAnimation {
  1438. 0% {
  1439. background-position-x: 3px;
  1440. }
  1441. 100% {
  1442. background-position-x: 4px;
  1443. }
  1444. }
  1445.  
  1446. .dont-render[class] {
  1447. /* visibility: collapse !important; */
  1448. /* visibility: collapse will make innerText become "" which conflicts with BetterStreamChat; see https://greasyfork.org/scripts/469878/discussions/197267 */
  1449.  
  1450. transform: scale(0.01) !important;
  1451. transform: scale(0.00001) !important;
  1452. transform: scale(0.0000001) !important;
  1453. transform-origin: 0 0 !important;
  1454. z-index: -1 !important;
  1455. contain: strict !important;
  1456. box-sizing: border-box !important;
  1457.  
  1458. height: 1px !important;
  1459. height: 0.1px !important;
  1460. height: 0.01px !important;
  1461. height: 0.0001px !important;
  1462. height: 0.000001px !important;
  1463.  
  1464. animation: dontRenderAnimation 1ms linear 80ms 1 normal forwards !important;
  1465.  
  1466. pointer-events: none !important;
  1467. user-select: none !important;
  1468.  
  1469. }
  1470.  
  1471. #sk35z {
  1472. display: block !important;
  1473.  
  1474. visibility: collapse !important;
  1475.  
  1476. transform: scale(0.01) !important;
  1477. transform: scale(0.00001) !important;
  1478. transform: scale(0.0000001) !important;
  1479. transform-origin: 0 0 !important;
  1480. z-index: -1 !important;
  1481. contain: strict !important;
  1482. box-sizing: border-box !important;
  1483.  
  1484. height: 1px !important;
  1485. height: 0.1px !important;
  1486. height: 0.01px !important;
  1487. height: 0.0001px !important;
  1488. height: 0.000001px !important;
  1489.  
  1490. position: absolute !important;
  1491. top: -1000px !important;
  1492. left: -1000px !important;
  1493.  
  1494. }
  1495.  
  1496. }
  1497.  
  1498. [rNgzQ] {
  1499. opacity: 0 !important;
  1500. pointer-events: none !important;
  1501. }
  1502.  
  1503.  
  1504. ${cssText10_show_more_blinker}
  1505.  
  1506. ${cssText11_entire_message_clickable}
  1507.  
  1508. ${cssText12_nowrap_tooltip}
  1509.  
  1510. ${cssText13_no_text_select_when_menu_visible}
  1511.  
  1512. ${cssText14_NO_FILTER_DROPDOWN_BORDER}
  1513.  
  1514. ${cssText15_FIX_ANIMATION_TICKER_TEXT_POSITION}
  1515.  
  1516. ${cssText16_FIX_AUTHOR_CHIP_BADGE_POSITION}
  1517.  
  1518. ${cssText17_FIX_overwidth_banner_message}
  1519.  
  1520. ${cssText18_REACTION_ANIMATION_PANEL_CSS_FIX}
  1521.  
  1522. ${cssText19_FOR_ADVANCED_TICKING}
  1523.  
  1524. ${cssText20_TICKER_SIZING}
  1525.  
  1526. `;
  1527.  
  1528. const win = typeof unsafeWindow !== 'undefined' ? unsafeWindow : (this instanceof Window ? this : window);
  1529.  
  1530. // Create a unique key for the script and check if it is already running
  1531. const hkey_script = 'mchbwnoasqph';
  1532. if (win[hkey_script]) throw new Error('Duplicated Userscript Calling'); // avoid duplicated scripting
  1533. win[hkey_script] = true;
  1534.  
  1535. const setTimeoutX0 = setTimeout;
  1536. const clearTimeoutX0 = clearTimeout;
  1537. const setIntervalX0 = setInterval;
  1538. const clearIntervalX0 = clearInterval;
  1539.  
  1540. const __shady_native_appendChild = HTMLElement_.prototype.__shady_native_appendChild || HTMLElement_.prototype.appendChild;
  1541. const __shady_native_removeChild = HTMLElement_.prototype.__shady_native_removeChild || HTMLElement_.prototype.removeChild;
  1542.  
  1543. const isEmptyObject = (obj) => {
  1544. for (const key in obj) {
  1545. if (obj.hasOwnProperty(key)) return false;
  1546. }
  1547. return true;
  1548. }
  1549.  
  1550. const firstObjectKey = (obj) => {
  1551. for (const key in obj) {
  1552. if (obj.hasOwnProperty(key) && typeof obj[key] === 'object') return key;
  1553. }
  1554. return null;
  1555. }
  1556.  
  1557.  
  1558. class LimitedSizeSet extends Set {
  1559. constructor(n) {
  1560. super();
  1561. this.limit = n;
  1562. }
  1563.  
  1564. add(key) {
  1565. if (!super.has(key)) {
  1566. super.add(key);
  1567. let n = super.size - this.limit;
  1568. if (n > 0) {
  1569. const iterator = super.values();
  1570. do {
  1571. const firstKey = iterator.next().value; // Get the first (oldest) key
  1572. super.delete(firstKey); // Delete the oldest key
  1573. } while (--n > 0)
  1574. }
  1575. }
  1576. }
  1577.  
  1578. removeAdd(key) {
  1579. super.delete(key);
  1580. this.add(key);
  1581. }
  1582.  
  1583. }
  1584.  
  1585.  
  1586. function deepCopy(obj, skipKeys) {
  1587. skipKeys = skipKeys || [];
  1588. if (!obj || typeof obj !== 'object') return obj;
  1589. if (Array.isArray(obj)) {
  1590. return obj.map(item => deepCopy(item, skipKeys));
  1591. }
  1592. const copy = {};
  1593. for (let key in obj) {
  1594. if (!skipKeys.includes(key)) {
  1595. copy[key] = deepCopy(obj[key], skipKeys);
  1596. }
  1597. }
  1598. return copy;
  1599. }
  1600.  
  1601. class Mutex {
  1602.  
  1603. constructor() {
  1604. this.p = Promise.resolve()
  1605. }
  1606.  
  1607. /**
  1608. * @param {(lockResolve: () => void)} f
  1609. */
  1610. lockWith(f) {
  1611. this.p = this.p.then(() => new Promise(f).catch(console.warn))
  1612. }
  1613.  
  1614. }
  1615.  
  1616. const PromiseExternal = ((resolve_, reject_) => {
  1617. const h = (resolve, reject) => { resolve_ = resolve; reject_ = reject };
  1618. return class PromiseExternal extends Promise {
  1619. constructor(cb = h) {
  1620. super(cb);
  1621. if (cb === h) {
  1622. /** @type {(value: any) => void} */
  1623. this.resolve = resolve_;
  1624. /** @type {(reason?: any) => void} */
  1625. this.reject = reject_;
  1626. }
  1627. }
  1628. };
  1629. })();
  1630.  
  1631. let ttpHTML = (s) => {
  1632. ttpHTML = s => s;
  1633. if (typeof trustedTypes !== 'undefined' && trustedTypes.defaultPolicy === null) {
  1634. let s = s => s;
  1635. trustedTypes.createPolicy('default', { createHTML: s, createScriptURL: s, createScript: s });
  1636. }
  1637. return s;
  1638. }
  1639.  
  1640. // const nextBrowserTick_ = nextBrowserTick;
  1641. // const nextBrowserTick_ = (f) => {
  1642. // typeof nextBrowserTick === 'function' ? nextBrowserTick(f) : setTimeout(f, Number.MIN_VALUE);
  1643. // };
  1644.  
  1645.  
  1646. // const { accurateTiming, isAccurateTimingUsable } = (() => {
  1647. // let audioCtx_ = null;
  1648. // let sampleRate = 0;
  1649. // const isAccurateTimingUsable = () => sampleRate > 0;
  1650. // const kill = () => {
  1651. // sampleRate = audioCtx_.currentTime;
  1652. // document.removeEventListener('pointerdown', listener, { capture: true, passive: true });
  1653. // document.removeEventListener('keydown', listener, { capture: true, passive: true });
  1654. // };
  1655. // const listener = (e) => {
  1656. // if (e.isTrusted === true) {
  1657. // if (!audioCtx_) {
  1658. // audioCtx_ = new (window.AudioContext || window.webkitAudioContext)();
  1659. // }
  1660. // if (audioCtx_.state === 'suspended') {
  1661. // const p = audioCtx_.resume();
  1662. // if (p && typeof p.then === 'function') p.then(kill);
  1663. // } else if (audioCtx_.state === 'running') {
  1664. // kill();
  1665. // }
  1666. // }
  1667. // };
  1668. // document.addEventListener('pointerdown', listener, { capture: true, passive: true });
  1669. // document.addEventListener('keydown', listener, { capture: true, passive: true });
  1670. // const fnSym = Symbol()
  1671. // const commonOscClean = (osc) => {
  1672. // osc[fnSym] = osc.onended = null;
  1673. // }
  1674. // const commonOscOnEnded = function () {
  1675. // this[fnSym]()
  1676. // Promise.resolve(this).then(commonOscClean)
  1677. // }
  1678. // let buffer_;
  1679. // const accurateTiming = (fn, delay) => {
  1680. // if (!sampleRate) return false;
  1681. // const audioCtx = audioCtx_;
  1682. // const ct = audioCtx.currentTime;
  1683.  
  1684. // if (!(delay >= 0)) delay = 0;
  1685. // const stopTime = ct + delay;
  1686. // let startTime = ct + delay - (1 / sampleRate);
  1687. // if (startTime === stopTime) startTime -= 1;
  1688. // if (startTime < 0) startTime = 0;
  1689.  
  1690. // if (!buffer_) {
  1691. // buffer_ = audioCtx.createBuffer(1, 1, sampleRate);
  1692. // // const data = buffer.getChannelData(0)
  1693. // // data[0] = 1e-20 // tiny pulse – not silent!
  1694. // }
  1695.  
  1696. // const buffer = buffer_;
  1697. // const source = audioCtx.createBufferSource()
  1698. // source.buffer = buffer
  1699. // source.connect(audioCtx.destination) // or silent gain node
  1700.  
  1701. // source[fnSym] = fn
  1702. // source.onended = commonOscOnEnded
  1703. // source.start(startTime) // schedule start
  1704.  
  1705. // return true;
  1706. // }
  1707. // return { accurateTiming, isAccurateTimingUsable }
  1708. // })();
  1709.  
  1710. const toUniqueArr = (arr) => {
  1711. const s = new Set(arr);
  1712. const r = [...s];
  1713. s.clear();
  1714. return r;
  1715. }
  1716.  
  1717. let qWidthAdjustable = null;
  1718.  
  1719. /** @type {typeof PromiseExternal.prototype | null} */
  1720. let relayPromise = null;
  1721.  
  1722.  
  1723. /** @type {typeof PromiseExternal.prototype | null} */
  1724. let onPlayStateChangePromise = null;
  1725.  
  1726.  
  1727. const reuseId = `${Math.floor(Math.random() * 314159265359 + 314159265359).toString(36)}`;
  1728.  
  1729. const reuseStore = new Map();
  1730. reuseStore.set = reuseStore.setOriginal || reuseStore.set;
  1731.  
  1732. let onPageContainer = null;
  1733.  
  1734. const customCreateComponent = (component, data, bool)=>{
  1735.  
  1736. const componentTag = typeof component === 'string' ? component : typeof (component||0).component === 'string' ? (component||0).component : '';
  1737. if(componentTag){
  1738.  
  1739. if(REUSE_TICKER && data.id && data.fullDurationSec){
  1740. // bool (param c) is true by default; just force it to reuse no matter true or false
  1741.  
  1742. if (!bool) {
  1743. // show a warning if it is false.
  1744. console.warn('[yt-chat] REUSE_TICKER: reuse bool is false');
  1745. }
  1746.  
  1747. const record = reuseStore.get(`<${componentTag}>${data.id}:${data.fullDurationSec}`);
  1748.  
  1749. const cnt = kRef(record);
  1750.  
  1751.  
  1752. if(cnt && cnt.isAttached === false){
  1753.  
  1754. const hostElement = cnt.hostElement;
  1755.  
  1756. if(hostElement instanceof HTMLElement_ && hostElement.isConnected === false && hostElement.parentNode === null && hostElement.getAttribute('__reuseid__')===reuseId ){
  1757.  
  1758. // console.log(952, cnt.hostElement.parentNode)
  1759. // debugger;
  1760. if (hostElement.hasAttribute('__nogc__')) {
  1761.  
  1762. Promise.resolve(hostElement).then((hostElement) => {
  1763. // microtask to provide some time for DOM attachment.
  1764. hostElement.isConnected && hostElement.removeAttribute('__nogc__');
  1765. });
  1766.  
  1767. }
  1768.  
  1769. // ------- follow rm3 -------
  1770.  
  1771. // a.prototype._initializeProtoProperties = function(c) {
  1772. // this.__data = Object.create(c);
  1773. // this.__dataPending = Object.create(c);
  1774. // this.__dataOld = {}
  1775. // }
  1776. // a.prototype._initializeProperties = function() {
  1777. // this.__dataProto && (this._initializeProtoProperties(this.__dataProto),
  1778. // this.__dataProto = null);
  1779. // b.prototype._initializeProperties.call(this)
  1780. // }
  1781. // ;
  1782.  
  1783. if(!cnt.__dataInvalid && cnt.__dataEnabled && cnt.__dataReady ){
  1784.  
  1785. // console.log(12883);
  1786.  
  1787.  
  1788. if (!onPageContainer) {
  1789. let p = document.createElement('noscript');
  1790. p.style.all = 'unset';
  1791. document.body.prepend(p);
  1792. onPageContainer = p;
  1793. }
  1794.  
  1795. onPageContainer.appendChild(hostElement); // to fix some issues for the rendered elements
  1796.  
  1797. cnt.__dataInvalid = false;
  1798. cnt.__dataEnabled = true;
  1799. cnt.__dataReady = true;
  1800. // cnt._initializeProtoProperties(cnt.data)
  1801.  
  1802. // window.meaa = cnt.$.container;
  1803. if (cnt.__data) cnt.__data = Object.assign({}, cnt.__data);
  1804. cnt.__dataPending = {};
  1805. cnt.__dataOld = {}
  1806.  
  1807. try{
  1808. cnt.markDirty();
  1809. }catch(e){}
  1810. try{
  1811. cnt.markDirtyVisibilityObserver();
  1812. }catch(e){}
  1813. try{
  1814. cnt.wasPrescan = cnt.wasVisible = !1
  1815. }catch(e){}
  1816. // try{
  1817. // cnt._setPendingProperty('data', Object.assign({}, cntData), !0);
  1818. // }catch(e){}
  1819. // // cnt.__dataInvalid = false;
  1820. // // cnt._enableProperties();
  1821.  
  1822. // try {
  1823. // cnt._flushProperties();
  1824. // } catch (e) { }
  1825. // cnt.ready();
  1826.  
  1827. return hostElement;
  1828.  
  1829. }
  1830.  
  1831.  
  1832. // console.log(12323)
  1833.  
  1834. // setTimeoutX0(()=>{
  1835. // console.log(window.meaa.parentNode)
  1836. // }, 1000)
  1837.  
  1838.  
  1839. // ------------ commented ------------
  1840. // cnt.__dataInvalid = false;
  1841. // cnt.__dataEnabled = false;
  1842. // if (cnt.__dataPending && typeof cnt.__dataPending === 'object') cnt.__dataPending = null;
  1843. // if (cnt.__dataOld && typeof cnt.__dataOld === 'object') cnt.__dataOld = null;
  1844. // if (cnt.__dataCounter && typeof cnt.__dataCounter === 'number') cnt.__dataCounter = 0;
  1845. // if ('__dataClientsInitialized' in cnt || '__dataClientsReady' in cnt) {
  1846. // cnt.__dataClientsReady = !1;
  1847. // cnt.__dataLinkedPaths = cnt.__dataToNotify = cnt.__dataPendingClients = null;
  1848. // cnt.__dataHasPaths = !1;
  1849. // cnt.__dataCompoundStorage = null; // cnt.__dataCompoundStorage = cnt.__dataCompoundStorage || null;
  1850. // cnt.__dataHost = null; // cnt.__dataHost = cnt.__dataHost || null;
  1851. // if (!cnt.__dataTemp) cnt.__dataTemp = {}; // cnt.__dataTemp = {};
  1852. // cnt.__dataClientsInitialized = !1;
  1853. // }
  1854. // try{
  1855. // cnt._flushProperties();
  1856. // }catch(e){
  1857. // console.warn(e)
  1858. // }
  1859. // for (const elm of cnt.hostElement.getElementsByTagName('*')) {
  1860. // if (elm.is) {
  1861. // const cnt = insp(elm);
  1862. // cnt.__dataInvalid = false;
  1863. // cnt.__dataEnabled = false;
  1864. // if (cnt.__dataPending && typeof cnt.__dataPending === 'object') cnt.__dataPending = null;
  1865. // if (cnt.__dataOld && typeof cnt.__dataOld === 'object') cnt.__dataOld = null;
  1866. // if (cnt.__dataCounter && typeof cnt.__dataCounter === 'number') cnt.__dataCounter = 0;
  1867. // if ('__dataClientsInitialized' in cnt || '__dataClientsReady' in cnt) {
  1868. // cnt.__dataClientsReady = !1;
  1869. // cnt.__dataLinkedPaths = cnt.__dataToNotify = cnt.__dataPendingClients = null;
  1870. // cnt.__dataHasPaths = !1;
  1871. // cnt.__dataCompoundStorage = null; // cnt.__dataCompoundStorage = cnt.__dataCompoundStorage || null;
  1872. // cnt.__dataHost = null; // cnt.__dataHost = cnt.__dataHost || null;
  1873. // if (!cnt.__dataTemp) cnt.__dataTemp = {}; // cnt.__dataTemp = {};
  1874. // cnt.__dataClientsInitialized = !1;
  1875. // }
  1876. // try {
  1877. // cnt._flushProperties();
  1878. // } catch (e) {
  1879. // console.warn(e)
  1880. // }
  1881. // if (elm.nodeName === 'YT-ICON') {
  1882. // // console.log(2133, JSON.stringify( cnt.__data))
  1883. // const qq = Object.assign({}, cnt.__data)
  1884. // console.log(1232466)
  1885. // const _qww = cnt;
  1886. // cnt.__data = new Proxy(Object.assign({}, qq), {
  1887. // get(target, p) {
  1888. // console.log(12838, p)
  1889. // if (p === 'icon') {
  1890. // window.wmk = _qww.hostElement;
  1891. // // debugger;
  1892. // }
  1893. // return target[p]
  1894. // },
  1895. // set(target, p, v) {
  1896. // console.log(12839, p)
  1897. // target[p] = v;
  1898. // if (p === 'icon') debugger;
  1899. // return true;
  1900. // }
  1901. // });
  1902. // Promise.resolve(cnt).then((cnt) => {
  1903. // cnt.__data = Object.assign({}, qq);
  1904. // });
  1905. // }
  1906. // // let q = elm.nextSibling;
  1907. // // let h = elm.parentNode;
  1908. // // elm.remove();
  1909. // // h.insertBefore(elm, q);
  1910. // // console.log(2233, elm)
  1911. // }
  1912. // }
  1913. // ------------ commented ------------
  1914.  
  1915. // ------- follow rm3 -------
  1916.  
  1917. // console.log('[yt-chat] reuse')
  1918.  
  1919.  
  1920.  
  1921. }
  1922.  
  1923. }
  1924.  
  1925. }
  1926.  
  1927. }
  1928. DEBUG_customCreateComponent && console.log(component, data, bool);
  1929. /*
  1930.  
  1931. const cntData = this.data;
  1932. reuseStore.set(`${cntData.id}:${cntData.fullDurationSec}`, mWeakRef(this));
  1933. */
  1934.  
  1935. }
  1936.  
  1937. const valAssign = (elm, attr, val) => {
  1938. if (typeof val === 'number') val = val.toFixed(3);
  1939. const currentVal = elm.style.getPropertyValue(attr);
  1940. if (currentVal === '' || !(Math.abs(currentVal - val) < 1e-5)) {
  1941. elm.style.setProperty(attr, val);
  1942. return true;
  1943. }
  1944. return false;
  1945. };
  1946.  
  1947. const insp = o => o ? (o.polymerController || o.inst || o || 0) : (o || 0);
  1948. const indr = o => insp(o).$ || o.$ || 0;
  1949.  
  1950.  
  1951. const getAttributes = (node) => {
  1952. const attrs = node.attributes;
  1953. const res = {};
  1954. for (const { name, value } of attrs) {
  1955. res[name] = value;
  1956. }
  1957. res['"'] = attrs.length;
  1958. // const res = new Array(attrs.length);
  1959. // for (let i = 0; i < res.length; i++) {
  1960. // const { name, value } = attrs[i];
  1961. // res[i] = { name, value };
  1962. // }
  1963. return res;
  1964. };
  1965.  
  1966. // const __refreshData938o__ = {};
  1967. // const __refreshData938__ = function (prop, opt) {
  1968. // const d = this[prop];
  1969. // if (d) {
  1970. // this._setPendingProperty(prop, __refreshData938o__, opt);
  1971. // this._setPendingProperty(prop, d, opt);
  1972. // this._invalidateProperties();
  1973. // }
  1974. // };
  1975.  
  1976. // const __refreshData933__ = function (prop, opt) {
  1977. // const d = this[prop];
  1978. // if (d) {
  1979. // this.signalProxy.setWithPath([prop], d);
  1980. // }
  1981. // }
  1982.  
  1983. // const setupRefreshData930 = (cnt) => {
  1984. // if (cnt.__refreshData930__ !== undefined) return;
  1985. // const cProto = Reflect.getPrototypeOf(cnt);
  1986. // let r = null;
  1987. // let flag = 0;
  1988. // if (typeof cnt._setPendingProperty === 'function' && typeof cnt._invalidateProperties === 'function' && cnt._setPendingProperty.length === 3 && cnt._invalidateProperties.length === 0) {
  1989. // flag |= 1;
  1990. // }
  1991. // if (typeof cnt.signalProxy !== "undefined") {
  1992. // flag |= 2;
  1993. // }
  1994. // if (typeof (cnt.signalProxy || 0).setWithPath === 'function' && cnt.signalProxy.setWithPath.length === 2) {
  1995. // flag |= 4;
  1996. // }
  1997. // if (r === 1) r = __refreshData938__;
  1998. // // else if (r === 6) r = __refreshData933__;
  1999. // cProto.__refreshData930__ = r;
  2000. // // ytd-comments-header-renderer : no _invalidateProperties (cnt.signalProxy.setWithPath)
  2001. // }
  2002.  
  2003. // const __refreshProps938__ = function () {
  2004. // const __data = this.__data;
  2005. // if (__data) {
  2006. // for (const key in __data) {
  2007. // const v = __data[key];
  2008. // if (typeof v === 'boolean') {
  2009. // this._setPendingProperty(key, !v) && this._setPendingProperty(key, v);
  2010. // } else if (typeof v === 'string') {
  2011. // this._setPendingProperty(key, `!${v}`) && this._setPendingProperty(key, `${v}`);
  2012. // } else if (typeof v === 'number') {
  2013. // this._setPendingProperty(key, v + 1) && this._setPendingProperty(key, v);
  2014. // }
  2015. // }
  2016. // }
  2017. // }
  2018.  
  2019. // const setupRefreshProps930 = (cnt) => {
  2020. // if (cnt.__refreshProps930__ !== undefined) return;
  2021. // const cProto = Reflect.getPrototypeOf(cnt);
  2022. // let r = null;
  2023. // let flag = 0;
  2024. // if (typeof cnt._setPendingProperty === 'function' && typeof cnt._invalidateProperties === 'function' && cnt._setPendingProperty.length === 3 && cnt._invalidateProperties.length === 0) {
  2025. // flag |= 1;
  2026. // }
  2027. // if (typeof cnt.signalProxy !== "undefined") {
  2028. // flag |= 2;
  2029. // }
  2030. // if (typeof (cnt.signalProxy || 0).setWithPath === 'function' && cnt.signalProxy.setWithPath.length === 2) {
  2031. // flag |= 4;
  2032. // }
  2033. // if (r === 1) r = __refreshProps938__;
  2034. // cProto.__refreshProps930__ = r;
  2035. // // ytd-comments-header-renderer : no _invalidateProperties (cnt.signalProxy.setWithPath)
  2036. // }
  2037.  
  2038. // const refreshChildrenYtIcons = (node) => {
  2039. // let goNext = false;
  2040. // for (const iconElm of node.getElementsByTagName('yt-icon')) {
  2041. // try {
  2042. // const cnt = insp(iconElm);
  2043. // setupRefreshProps930(cnt);
  2044. // if (cnt.__refreshProps930__) {
  2045. // cnt.__refreshProps930__();
  2046. // goNext = true;
  2047. // }
  2048. // // cnt.removeIconShape(); // detach iconShapeDataSignal?
  2049. // // cnt._setPendingProperty('isAttached', false);
  2050. // } catch (e) { }
  2051. // if (!goNext) break;
  2052. // }
  2053. // }
  2054.  
  2055.  
  2056. // const imageFetchCache = new Set();
  2057. // const imageFetch = function (imageLink) {
  2058. // return new Promise(resolve => {
  2059. // let img = null;
  2060. // for (const cacheWR of imageFetchCache) {
  2061. // let p = kRef(cacheWR);
  2062. // if (!p) {
  2063. // imageFetchCache.delete(cacheWR);
  2064. // } else if (img.busy588 === false) {
  2065. // img = p;
  2066. // break;
  2067. // }
  2068. // }
  2069. // if (!img) {
  2070. // img = new Image_();
  2071. // imageFetchCache.add(mWeakRef(img));
  2072. // }
  2073. // img.busy588 = true;
  2074.  
  2075. // window.mkek = imageFetchCache.size;
  2076. // let f = () => {
  2077. // resolve && resolve();
  2078. // resolve = null;
  2079. // img.onload = null;
  2080. // img.onerror = null;
  2081. // img.busy588 = false;
  2082. // img = null;
  2083. // }
  2084. // img.onload = f;
  2085. // img.onerror = f;
  2086. // img.src = imageLink;
  2087. // f = null;
  2088. // imageLink = null;
  2089. // });
  2090. // };
  2091.  
  2092.  
  2093. const autoTimerFn = (() => {
  2094.  
  2095. let p1 = null;
  2096. let p2 = null;
  2097. let p3 = null;
  2098. setInterval(() => {
  2099. if (p1) p1.resolve();
  2100. p1 = p2;
  2101. p2 = p3;
  2102. p3 = null;
  2103. }, 345.00123);
  2104.  
  2105. return () => {
  2106. const p = (p3 || (p3 = new PromiseExternal()));
  2107. return p;
  2108. };
  2109.  
  2110. })();
  2111.  
  2112. const __mockChildren__ = { get length() { return 0 } };
  2113. const mockCommentElement = (x) => {
  2114. // for flow chat
  2115. if (x instanceof Node && x.nodeType !== 1 && !x.children) {
  2116. x.children = __mockChildren__;
  2117. }
  2118. return x;
  2119. }
  2120.  
  2121. const wme = mockCommentElement(document.createComment('1'));
  2122. let wmp = new PromiseExternal();
  2123. const wmo = new MutationObserver(() => {
  2124. wmp.resolve();
  2125. wmp = new PromiseExternal();
  2126. });
  2127. wmo.observe(wme, { characterData: true });
  2128.  
  2129.  
  2130. let playEventsStack = Promise.resolve();
  2131.  
  2132.  
  2133. let playerProgressChangedArg1 = null;
  2134. let playerProgressChangedArg2 = null;
  2135. let playerProgressChangedArg3 = null;
  2136.  
  2137. let dntElementWeak = null;
  2138.  
  2139.  
  2140. let timestampUnderLiveMode = false;
  2141.  
  2142. const updateTickerCurrentTime = () => {
  2143.  
  2144. if (resistanceUpdateDebugMode) {
  2145. console.log('updateTickerCurrentTime')
  2146.  
  2147. if (!dntElementWeak || !kRef(dntElementWeak)) dntElementWeak = mWeakRef(document.querySelector('yt-live-chat-ticker-renderer'));
  2148. timestampUnderLiveMode = true;
  2149. }
  2150.  
  2151. const dntElement = kRef(dntElementWeak);
  2152. const v = timestampUnderLiveMode ? (Date.now() / 1000 - timeOriginDT / 1000) : playerProgressChangedArg1;
  2153. if (dntElement instanceof HTMLElement_ && v >= 0) {
  2154. valAssign(dntElement, '--ticker-current-time', v);
  2155. }
  2156. }
  2157.  
  2158. // ================== FOR USE_ADVANCED_TICKING ================
  2159.  
  2160. const timeOriginDT = +new Date(Math.floor(performance.timeOrigin)) - 1000;
  2161. let startResistanceUpdaterStarted = false;
  2162.  
  2163. const RESISTANCE_UPDATE_OPT = 3;
  2164. let resistanceUpdateLast = 0;
  2165. let resistanceUpdateBusy = false;
  2166. const resistanceUpdateDebugMode = false;
  2167. const allBackgroundOverLays = document.getElementsByTagName('ticker-bg-overlay');
  2168. // const rgFlag = {};
  2169. const resistanceUpdateFn = (b) => {
  2170. if (!resistanceUpdateDebugMode && allBackgroundOverLays.length === 0) return;
  2171. resistanceUpdateBusy = false;
  2172. const t = Date.now();
  2173. const d = t - resistanceUpdateLast;
  2174. if (d > 375) {
  2175. resistanceUpdateLast = t;
  2176. updateTickerCurrentTime();
  2177. }
  2178. }
  2179. const resistanceUpdateFn_ = (forced = false) => {
  2180. if (forced === true || timestampUnderLiveMode) {
  2181. if (!resistanceUpdateBusy) {
  2182. resistanceUpdateBusy = true;
  2183. Promise.resolve().then(resistanceUpdateFn);
  2184. }
  2185. }
  2186. }
  2187. const startResistanceUpdater = () => {
  2188.  
  2189. if (startResistanceUpdaterStarted) return;
  2190. startResistanceUpdaterStarted = true;
  2191.  
  2192. if (RESISTANCE_UPDATE_OPT & 1)
  2193. document.addEventListener('yt-action', () => {
  2194. resistanceUpdateFn_(true);
  2195. }, true)
  2196.  
  2197. resistanceUpdateFn_(true);
  2198. setIntervalX0(resistanceUpdateFn_, 400);
  2199. }
  2200.  
  2201. if(resistanceUpdateDebugMode) startResistanceUpdater();
  2202.  
  2203.  
  2204. function dr(s) {
  2205. // reserved for future use
  2206. return s;
  2207. // return window.deWeakJS ? window.deWeakJS(s) : s;
  2208. }
  2209.  
  2210.  
  2211. const getProto = (element) => {
  2212. if (element) {
  2213. const cnt = insp(element);
  2214. return cnt.constructor.prototype || null;
  2215. }
  2216. return null;
  2217. }
  2218.  
  2219.  
  2220.  
  2221. const logFn = (key, f) => {
  2222. return Function.prototype.bind.call(console.log, console, `%c ${key}`, 'background: #222; color: #bada55', f);
  2223. }
  2224.  
  2225.  
  2226.  
  2227. const assertor = (f) => f() || (console.assert(false, `${f}`), false);
  2228.  
  2229. const fnIntegrity_oldv1 = (f, d) => {
  2230.  
  2231.  
  2232. if (!f || typeof f !== 'function') {
  2233. console.warn('f is not a function', f);
  2234. return;
  2235. }
  2236. // return; // M44
  2237. let p = `${f}`, s = 0, j = -1, w = 0;
  2238. // return; // M44
  2239. for (let i = 0, l = p.length; i < l; i++) {
  2240. const t = p[i];
  2241. if (((t >= 'a' && t <= 'z') || (t >= 'A' && t <= 'Z'))) {
  2242. if (j < i - 1) w++;
  2243. j = i;
  2244. } else {
  2245. s++;
  2246. }
  2247. }
  2248. // if(p.length > 44 && p.length < 50){
  2249.  
  2250. // (window.skam|| (window.skam=[])).push(p);
  2251. // return false;
  2252. // }
  2253.  
  2254. // if(p.length > 405 && p.length < 415 ){ //350 450
  2255.  
  2256.  
  2257. // //  [353, 411, 411, 411]
  2258.  
  2259. // // if(p.length >= 350 && p.length<=450){
  2260.  
  2261. // // (window.skam|| (window.skam=[])).push(p.length);
  2262. // // }
  2263. // (window.skam|| (window.skam=[])).push(p);
  2264. // return false;
  2265. // }
  2266.  
  2267. // if(p.length < 50) return true; else return false;
  2268. // return; // M44
  2269. let itz = `${f.length}.${s}.${w}`;
  2270. if (!d) {
  2271. return itz;
  2272. } else if (itz !== d) {
  2273. console.warn('fnIntegrity=false', itz);
  2274. return false;
  2275. } else {
  2276. return true;
  2277. }
  2278. }
  2279.  
  2280.  
  2281. const fnIntegrity = (f, d) => {
  2282.  
  2283.  
  2284. if (!f || typeof f !== 'function') {
  2285. console.warn('f is not a function', f);
  2286. return;
  2287. }
  2288. // return; // M44
  2289. let p = `${f}`, s = 0, j = -1, w = 0, q = ' ';
  2290. // return; // M44
  2291. for (let i = 0, l = p.length; i < l; i++) {
  2292. let t = p[i];
  2293. if (((t >= 'a' && t <= 'z') || (t >= 'A' && t <= 'Z'))) {
  2294. if (j < i - 1) {
  2295. w++;
  2296. if (q === '$') s--;
  2297. }
  2298. j = i;
  2299. } else {
  2300. s++;
  2301. }
  2302. q = t;
  2303. }
  2304. // if(p.length > 44 && p.length < 50){
  2305.  
  2306. // (window.skam|| (window.skam=[])).push(p);
  2307. // return false;
  2308. // }
  2309.  
  2310. // if(p.length > 405 && p.length < 415 ){ //350 450
  2311.  
  2312.  
  2313. // //  [353, 411, 411, 411]
  2314.  
  2315. // // if(p.length >= 350 && p.length<=450){
  2316.  
  2317. // // (window.skam|| (window.skam=[])).push(p.length);
  2318. // // }
  2319. // (window.skam|| (window.skam=[])).push(p);
  2320. // return false;
  2321. // }
  2322.  
  2323. // if(p.length < 50) return true; else return false;
  2324. // return; // M44
  2325. let itz = `${f.length}.${s}.${w}`;
  2326. if (!d) {
  2327. return itz;
  2328. } else if (itz !== d) {
  2329. console.warn('fnIntegrity=false', itz);
  2330. return false;
  2331. } else {
  2332. return true;
  2333. }
  2334. }
  2335.  
  2336. const px2cm = (px) => px * window.devicePixelRatio * 0.026458333;
  2337. const px2mm = (px) => px * window.devicePixelRatio * 0.26458333;
  2338.  
  2339. // let createElement_fountain_model_fn = null;
  2340. // let createElement_fountain_model_enabled = null;
  2341.  
  2342. // ; (USE_RM_ON_FOUNTAIN_MODEL) && (()=>{
  2343. // document.createElement4719 = document.createElement;
  2344. // document.createElement = function (a) {
  2345. // if (createElement_fountain_model_enabled) {
  2346. // const r = createElement_fountain_model_fn(a);
  2347. // if (r) return r;
  2348. // }
  2349. // return document.createElement4719(a);
  2350. // }
  2351. // })();
  2352.  
  2353. ; (ENABLE_FLAGS_MAINTAIN_STABLE_LIST || ENABLE_FLAGS_REUSE_COMPONENTS || DISABLE_FLAGS_SHADYDOM_FREE) && (() => {
  2354.  
  2355. const _config_ = () => {
  2356. try {
  2357. return ytcfg.data_;
  2358. } catch (e) { }
  2359. return null;
  2360. };
  2361.  
  2362. const flagsFn = (EXPERIMENT_FLAGS) => {
  2363.  
  2364. // console.log(700)
  2365.  
  2366. if (!EXPERIMENT_FLAGS) return;
  2367.  
  2368. if (ENABLE_FLAGS_MAINTAIN_STABLE_LIST) {
  2369. if (USE_MAINTAIN_STABLE_LIST_ONLY_WHEN_KS_FLAG_IS_SET ? EXPERIMENT_FLAGS.kevlar_should_maintain_stable_list === true : true) {
  2370. // EXPERIMENT_FLAGS.kevlar_tuner_should_test_maintain_stable_list = true; // timestamp toggle issue
  2371. EXPERIMENT_FLAGS.kevlar_should_maintain_stable_list = true;
  2372. // console.log(701)
  2373. }
  2374. }
  2375.  
  2376. if (ENABLE_FLAGS_REUSE_COMPONENTS) {
  2377. EXPERIMENT_FLAGS.kevlar_tuner_should_test_reuse_components = true;
  2378. EXPERIMENT_FLAGS.kevlar_tuner_should_reuse_components = true;
  2379. // console.log(702);
  2380. }
  2381.  
  2382. if (DISABLE_FLAGS_SHADYDOM_FREE) {
  2383. EXPERIMENT_FLAGS.enable_shadydom_free_scoped_node_methods = false;
  2384. EXPERIMENT_FLAGS.enable_shadydom_free_scoped_query_methods = false;
  2385. EXPERIMENT_FLAGS.enable_shadydom_free_scoped_readonly_properties_batch_one = false;
  2386. EXPERIMENT_FLAGS.enable_shadydom_free_parent_node = false;
  2387. EXPERIMENT_FLAGS.enable_shadydom_free_children = false;
  2388. EXPERIMENT_FLAGS.enable_shadydom_free_last_child = false;
  2389. }
  2390.  
  2391. // EXPERIMENT_FLAGS.enable_button_behavior_reuse = false;
  2392.  
  2393. };
  2394.  
  2395. const uf = (config_) => {
  2396. config_ = config_ || _config_();
  2397. if (config_) {
  2398. const { EXPERIMENT_FLAGS, EXPERIMENTS_FORCED_FLAGS } = config_;
  2399. if (EXPERIMENT_FLAGS) {
  2400. flagsFn(EXPERIMENT_FLAGS);
  2401. if (EXPERIMENTS_FORCED_FLAGS) flagsFn(EXPERIMENTS_FORCED_FLAGS);
  2402. }
  2403. }
  2404. }
  2405.  
  2406. window._ytConfigHacks.add((config_) => {
  2407. uf(config_);
  2408. });
  2409.  
  2410. uf();
  2411.  
  2412. })();
  2413.  
  2414. if (DISABLE_Translation_By_Google) {
  2415.  
  2416. let mo = new MutationObserver(() => {
  2417.  
  2418. if (!mo) return;
  2419. let h = document.head;
  2420. if (!h) return;
  2421. mo.disconnect();
  2422. mo.takeRecords();
  2423. mo = null;
  2424.  
  2425. let meta = document.createElement('meta');
  2426. meta.setAttribute('name', 'google');
  2427. meta.setAttribute('content', 'notranslate');
  2428. h.appendChild(meta);
  2429.  
  2430.  
  2431. });
  2432. mo.observe(document, { subtree: true, childList: true });
  2433. }
  2434.  
  2435. console.assert(MAX_ITEMS_FOR_TOTAL_DISPLAY > 0)
  2436. // console.assert(MAX_ITEMS_FOR_TOTAL_DISPLAY > 0 && MAX_ITEMS_FOR_FULL_FLUSH > 0 && MAX_ITEMS_FOR_TOTAL_DISPLAY > MAX_ITEMS_FOR_FULL_FLUSH)
  2437.  
  2438. const isContainSupport = CSS.supports('contain', 'layout paint style');
  2439. if (!isContainSupport) {
  2440. console.warn("Your browser does not support css property 'contain'.\nPlease upgrade to the latest version.".trim());
  2441. }
  2442.  
  2443. const isOverflowAnchorSupport = CSS.supports('overflow-anchor', 'auto');
  2444. if (!isOverflowAnchorSupport) {
  2445. console.warn("Your browser does not support css property 'overflow-anchor'.\nPlease upgrade to the latest version.".trim());
  2446. }
  2447.  
  2448. const ENABLE_OVERFLOW_ANCHOR = ENABLE_OVERFLOW_ANCHOR_PREFERRED && isOverflowAnchorSupport && ENABLE_NO_SMOOTH_TRANSFORM && typeof ResizeObserver === 'function';
  2449. let WITH_SCROLL_ANCHOR = false;
  2450.  
  2451. const fxOperator = (proto, propertyName) => {
  2452. let propertyDescriptorGetter = null;
  2453. try {
  2454. propertyDescriptorGetter = Object.getOwnPropertyDescriptor(proto, propertyName).get;
  2455. } catch (e) { }
  2456. return typeof propertyDescriptorGetter === 'function' ? (e) => {
  2457. try {
  2458.  
  2459. return propertyDescriptorGetter.call(dr(e));
  2460. } catch (e) { }
  2461. return e[propertyName];
  2462. } : (e) => e[propertyName];
  2463. };
  2464.  
  2465. const nodeParent = fxOperator(Node.prototype, 'parentNode');
  2466. const nPrevElem = fxOperator(HTMLElement_.prototype, 'previousElementSibling');
  2467. const nNextElem = fxOperator(HTMLElement_.prototype, 'nextElementSibling');
  2468. const nLastElem = fxOperator(HTMLElement_.prototype, 'lastElementChild');
  2469.  
  2470. let groupCI = [];
  2471. let groupDI = 0;
  2472.  
  2473. const [console_] = [console];
  2474. const console1 = {
  2475. log(...args) {
  2476. if (!SHOW_DEVTOOL_DEBUG) return;
  2477. if (groupDI === 1) return grouppedConsoleLog(...args);
  2478. return console_.log(...args);
  2479. },
  2480. warn(...args) {
  2481. if (!SHOW_DEVTOOL_DEBUG) return;
  2482. if (groupDI === 1) return grouppedConsoleWarn(...args);
  2483. return console_.warn(...args);
  2484. },
  2485. debug(...args) {
  2486. if (!SHOW_DEVTOOL_DEBUG) return;
  2487. if (groupDI === 1) return grouppedConsoleDebug(...args);
  2488. return console_.debug(...args);
  2489. }
  2490. }
  2491. const grouppedConsoleLog = (...args) => {
  2492. if (DEBUG_LOG_HIDE_OK) {
  2493. for (const arg of args) {
  2494. if (typeof arg !== 'string') break;
  2495. if (arg.endsWith('OK')) return;
  2496. }
  2497. }
  2498. groupCI.push(['log', ...args]);
  2499. }
  2500. const grouppedConsoleWarn = (...args) => {
  2501. groupCI.push(['warn', ...args]);
  2502. }
  2503. const grouppedConsoleDebug = (...args) => {
  2504. groupCI.push(['debug', ...args]);
  2505. }
  2506. const groupCollapsed = (text1, text2) => {
  2507. if (!SHOW_DEVTOOL_DEBUG) return;
  2508. if (groupDI !== 0) console_.warn('groupDI in groupCollapsed fails', groupDI);
  2509. groupDI++;
  2510. groupCI.length = 0;
  2511.  
  2512. let w = 'groupCollapsed';
  2513. if (DEBUG_LOG_GROUP_EXPAND) w = 'group';
  2514. groupCI.push([w, `%c${text1}%c${text2}`,
  2515. "background-color: #010502; color: #6acafe; font-weight: 700; padding: 2px;",
  2516. "background-color: #010502; color: #6ad9fe; font-weight: 300; padding: 2px;"
  2517. ]);
  2518. }
  2519. const groupEnd = () => {
  2520. if (!SHOW_DEVTOOL_DEBUG) return;
  2521. groupDI--;
  2522. if (groupDI !== 0) console_.warn('groupDI in groupEnd fails', groupDI);
  2523. if (groupCI.length >= 0) {
  2524. let withContent = false;
  2525. for (const entry of groupCI) {
  2526. if (entry[0] === 'group' || entry[0] === 'groupCollapsed') continue;
  2527. if (entry[1] === '[Begin]' || entry[1] === '[End]') continue;
  2528. withContent = true;
  2529. break;
  2530. }
  2531. if (withContent) {
  2532. for (const entry of groupCI) {
  2533. const args = entry.slice(1);
  2534. let colorHighLight = '';
  2535. for (const arg of args) {
  2536. if (typeof arg !== 'string') {
  2537. colorHighLight = '';
  2538. break;
  2539. }
  2540. if (arg === 'OK' || arg === 'NG') {
  2541. colorHighLight = arg;
  2542. } else {
  2543. if (arg.endsWith(' OK')) colorHighLight = 'OK';
  2544. else if (arg.endsWith(' NG')) colorHighLight = 'NG';
  2545. }
  2546. }
  2547. let print = args;
  2548. if (colorHighLight) {
  2549. print = [args.map(e => `%c${e}`).join(' '), ...args.map(e => {
  2550. if (colorHighLight === 'OK' && e.includes(colorHighLight)) return "background-color:rgb(29, 29, 29); color:rgb(57, 215, 83); font-weight: 600;";
  2551. if (colorHighLight === 'NG' && e.includes(colorHighLight)) return "background-color:rgb(29, 29, 29); color:rgb(215, 133, 57); font-weight: 600;";
  2552. return "background-color:rgb(29, 29, 29); color:rgb(231, 231, 231); font-weight: 400;";
  2553. })];
  2554. }
  2555. console[entry[0]](...print);
  2556. }
  2557. console.groupEnd();
  2558. groupCI.length = 0;
  2559. }
  2560. }
  2561. }
  2562.  
  2563. // const microNow = () => performance.now() + (performance.timeOrigin || performance.timing.navigationStart);
  2564.  
  2565.  
  2566. const EVENT_KEY_ON_REGISTRY_READY = "ytI-ce-registry-created";
  2567. const onRegistryReady = (callback) => {
  2568. if (typeof customElements === 'undefined') {
  2569. if (!('__CE_registry' in document)) {
  2570. // https://github.com/webcomponents/polyfills/
  2571. Object.defineProperty(document, '__CE_registry', {
  2572. get() {
  2573. // return undefined
  2574. },
  2575. set(nv) {
  2576. if (typeof nv == 'object') {
  2577. delete this.__CE_registry;
  2578. this.__CE_registry = nv;
  2579. this.dispatchEvent(new CustomEvent(EVENT_KEY_ON_REGISTRY_READY));
  2580. }
  2581. return true;
  2582. },
  2583. enumerable: false,
  2584. configurable: true
  2585. })
  2586. }
  2587. let eventHandler = (evt) => {
  2588. document.removeEventListener(EVENT_KEY_ON_REGISTRY_READY, eventHandler, false);
  2589. const f = callback;
  2590. callback = null;
  2591. eventHandler = null;
  2592. f();
  2593. };
  2594. document.addEventListener(EVENT_KEY_ON_REGISTRY_READY, eventHandler, false);
  2595. } else {
  2596. callback();
  2597. }
  2598. };
  2599.  
  2600. const promiseForCustomYtElementsReady = new Promise(onRegistryReady);
  2601.  
  2602. const renderReadyPn = typeof ResizeObserver !== 'undefined' ? (sizingTarget) => {
  2603.  
  2604. return new Promise(resolve => {
  2605.  
  2606. let ro = new ResizeObserver(entries => {
  2607. if (entries && entries.length >= 1) {
  2608. resolve();
  2609. ro.disconnect();
  2610. ro = null;
  2611. }
  2612. });
  2613. ro.observe(sizingTarget);
  2614.  
  2615.  
  2616.  
  2617. });
  2618.  
  2619. } : (sizingTarget) => {
  2620.  
  2621.  
  2622. return new Promise(resolve => {
  2623.  
  2624. let io = new IntersectionObserver(entries => {
  2625. if (entries && entries.length >= 1) {
  2626. resolve();
  2627. io.disconnect();
  2628. io = null;
  2629. }
  2630. });
  2631. io.observe(sizingTarget);
  2632.  
  2633.  
  2634.  
  2635. });
  2636.  
  2637. };
  2638.  
  2639. /* globals WeakRef:false */
  2640.  
  2641. /** @type {(o: Object | null) => WeakRef | null} */
  2642. const mWeakRef = typeof WeakRef === 'function' ? (o => o ? new WeakRef(o) : null) : (o => o || null);
  2643.  
  2644. /** @type {(wr: Object | null) => Object | null} */
  2645. const kRef = (wr => (wr && wr.deref) ? wr.deref() : wr);
  2646.  
  2647. const { insertBeforeNaFn, appendChildNaFn } = (() => {
  2648. // native methods
  2649.  
  2650. const insertBefore = HTMLElement_.prototype.insertBefore;
  2651. const appendChild = HTMLElement_.prototype.appendChild;
  2652.  
  2653. return {
  2654. insertBeforeNaFn: (parent, node, child) => {
  2655. insertBefore.call(parent, node, child);
  2656. },
  2657. appendChildNaFn: (parent, node) => {
  2658. appendChild.call(parent, node);
  2659. }
  2660. };
  2661.  
  2662. /*
  2663. const insertBeforeFn = (parent, node, child) => {
  2664. if ('__shady_native_insertBefore' in parent) parent.__shady_native_insertBefore(node, child);
  2665. else parent.insertBefore(node, child);
  2666. }
  2667.  
  2668. const appendChildFn = (parent, node) =>{
  2669. if('__shady_native_appendChild' in parent) parent.__shady_native_appendChild(node);
  2670. else parent.appendChild(node);
  2671. }
  2672. */
  2673.  
  2674. })();
  2675.  
  2676.  
  2677.  
  2678. let __LCRInjection__ = 0; // 0 for no injection
  2679. const LCRImmedidates = []; // array of sync. func
  2680.  
  2681. let getLCRDummyP_ = null;
  2682. // lcrPromiseFn
  2683. const getLCRDummy = () => {
  2684.  
  2685. /* remarks */
  2686.  
  2687. /*
  2688.  
  2689. // YouTube uses `<ps-dom-if class="style-scope ytd-live-chat-frame"><template></template></ps-dom-if>` to create yt-live-chat-renderer
  2690. // <ps-dom-if> is located inside ytd-live-chat-frame#chat in main frame
  2691. // <ps-dom-if>.hostElement is located as iframe's yt-live-chat-app > div#contents > yt-live-chat-renderer
  2692.  
  2693. */
  2694.  
  2695.  
  2696. // direct createElement or createComponent_ will make the emoji rendering crashed. reason TBC
  2697.  
  2698. return getLCRDummyP_ || (getLCRDummyP_ = Promise.all([customElements.whenDefined('yt-live-chat-app'), customElements.whenDefined('yt-live-chat-renderer')]).then(async () => {
  2699.  
  2700. const tag = "yt-live-chat-renderer"
  2701. let dummy = document.querySelector(tag);
  2702. if (!dummy) {
  2703.  
  2704. let mo = null;
  2705.  
  2706. const ytLiveChatApp = document.querySelector('yt-live-chat-app') || document.createElement('yt-live-chat-app');
  2707.  
  2708. const lcaProto = getProto(ytLiveChatApp);
  2709. let fz38;
  2710.  
  2711. let qt38=0;
  2712. let bypass = false;
  2713.  
  2714.  
  2715. dummy = await new Promise(resolve => {
  2716.  
  2717.  
  2718. if (typeof lcaProto.createComponent_ === 'function' && !lcaProto.createComponent99_ && lcaProto.createComponent_.length === 3) {
  2719. console.log('[yt-chat-lcr] lcaProto.createComponent_ is found');
  2720.  
  2721. lcaProto.createComponent99_ = lcaProto.createComponent_;
  2722. lcaProto.createComponent98_ = function (a, b, c) {
  2723. const z = customCreateComponent(a,b,c);
  2724. if(z !== undefined) return z;
  2725. // (3) ['yt-live-chat-renderer', {…}, true]
  2726. const r = this.createComponent99_(a, b,c);
  2727. const componentTag = (typeof a === 'string' ? a : (a||0).component) || `${(r||0).nodeName}`.toLowerCase();
  2728. if ( componentTag === 'yt-live-chat-renderer' && !bypass) {
  2729. qt38 = 1;
  2730.  
  2731. __LCRInjection__ = __LCRInjection__ | 1;
  2732.  
  2733. // r.polymerController.__proto__.handleLiveChatActions471_ = r.polymerController.__proto__.handleLiveChatActions_;
  2734. // r.polymerController.__proto__.handleLiveChatActions_ = function (arr) {
  2735.  
  2736.  
  2737. // preprocessChatLiveActions(arr);
  2738.  
  2739. // return this.handleLiveChatActions471_(arr);
  2740.  
  2741.  
  2742. // }
  2743.  
  2744. for (const f of LCRImmedidates) {
  2745. f(r);
  2746. }
  2747. LCRImmedidates.length = 0;
  2748.  
  2749. resolve(r); // note: this dom is not yet adopted, but promise resolve is later than ops.
  2750. console.log('[yt-chat-lcr] element found by method 1');
  2751. }
  2752. return r;
  2753. };
  2754. lcaProto.createComponent_ = lcaProto.createComponent98_;
  2755.  
  2756. if (!USE_OBTAIN_LCR_BY_BOTH_METHODS) return;
  2757.  
  2758. }
  2759.  
  2760. // console.log('[yt-chat] lcaProto traditional');
  2761.  
  2762. const pz38 = document.getElementsByTagName(tag);
  2763. fz38 = () => {
  2764. const t = pz38[0]
  2765. if (t) {
  2766. qt38 = 2;
  2767.  
  2768. __LCRInjection__ = __LCRInjection__ | 2;
  2769. resolve(t);
  2770. console.log('[yt-chat-lcr] element found by method 2');
  2771. }
  2772. };
  2773. mo = new MutationObserver(fz38);
  2774. mo.observe(document, { subtree: true, childList: true, attributes: true });
  2775. document.addEventListener('yt-action', fz38, true);
  2776. fz38();
  2777.  
  2778. });
  2779.  
  2780. bypass = true;
  2781.  
  2782. if (mo) {
  2783. mo.disconnect();
  2784. mo.takeRecords();
  2785. mo = null;
  2786. }
  2787. if (fz38) {
  2788. document.removeEventListener('yt-action', fz38, true);
  2789. fz38 = null;
  2790. }
  2791. console.log(`[yt-chat-lcr] lcr appears, dom = ${document.getElementsByTagName(tag).length}, method = ${qt38}`);
  2792.  
  2793.  
  2794. // if (lcaProto.createComponent99_ && lcaProto.createComponent_ && lcaProto.createComponent98_ === lcaProto.createComponent_) {
  2795. // lcaProto.createComponent_ = lcaProto.createComponent99_;
  2796. // lcaProto.createComponent99_ = null;
  2797. // lcaProto.createComponent98_ = null;
  2798. // }
  2799.  
  2800. } else {
  2801. console.log('[yt-chat-lcr] lcr exists');
  2802. }
  2803. return dummy;
  2804.  
  2805. }));
  2806. }
  2807.  
  2808. const { addCssManaged } = (() => {
  2809.  
  2810. const addFontPreRendering = () => {
  2811.  
  2812. groupCollapsed("YouTube Super Fast Chat", " | Fonts Pre-Rendering");
  2813.  
  2814. let efsContainer = document.createElement('elzm-fonts');
  2815. efsContainer.id = 'elzm-fonts-yk75g'
  2816.  
  2817. const arr = [];
  2818. let p = document.createElement('elzm-font');
  2819. arr.push(p);
  2820.  
  2821. if (ENABLE_FONT_PRE_RENDERING & 1) {
  2822. for (const size of [100, 200, 300, 400, 500, 600, 700, 800, 900]) {
  2823.  
  2824. p = document.createElement('elzm-font');
  2825. p.style.fontWeight = size;
  2826. arr.push(p);
  2827. }
  2828. }
  2829.  
  2830. if (ENABLE_FONT_PRE_RENDERING & 2) {
  2831. for (const size of [100, 200, 300, 400, 500, 600, 700, 800, 900]) {
  2832.  
  2833. p = document.createElement('elzm-font');
  2834. p.style.fontFamily = 'Roboto';
  2835. p.style.fontWeight = size;
  2836. arr.push(p);
  2837. }
  2838. }
  2839.  
  2840. if (ENABLE_FONT_PRE_RENDERING & 4) {
  2841. for (const size of [100, 200, 300, 400, 500, 600, 700, 800, 900]) {
  2842.  
  2843. p = document.createElement('elzm-font');
  2844. p.style.fontFamily = '"YouTube Noto",Roboto,Arial,Helvetica,sans-serif';
  2845. p.style.fontWeight = size;
  2846. arr.push(p);
  2847. }
  2848. }
  2849.  
  2850.  
  2851. if (ENABLE_FONT_PRE_RENDERING & 8) {
  2852. for (const size of [100, 200, 300, 400, 500, 600, 700, 800, 900]) {
  2853.  
  2854. p = document.createElement('elzm-font');
  2855. p.style.fontFamily = '"Noto",Roboto,Arial,Helvetica,sans-serif';
  2856. p.style.fontWeight = size;
  2857. arr.push(p);
  2858. }
  2859. }
  2860.  
  2861.  
  2862. if (ENABLE_FONT_PRE_RENDERING & 16) {
  2863. for (const size of [100, 200, 300, 400, 500, 600, 700, 800, 900]) {
  2864.  
  2865. p = document.createElement('elzm-font');
  2866. p.style.fontFamily = 'sans-serif';
  2867. p.style.fontWeight = size;
  2868. arr.push(p);
  2869. }
  2870. }
  2871.  
  2872. console1.log('number of elzm-font elements', arr.length);
  2873.  
  2874. HTMLElement_.prototype.append.apply(efsContainer, arr);
  2875.  
  2876. (document.body || document.documentElement).appendChild(efsContainer);
  2877.  
  2878.  
  2879. console1.log('elzm-font elements have been added to the page for rendering.');
  2880.  
  2881. groupEnd();
  2882.  
  2883. }
  2884.  
  2885. let isCssAdded = false;
  2886.  
  2887. function addCssElement() {
  2888. let s = document.createElement('style');
  2889. s.id = 'ewRvC';
  2890. return s;
  2891. }
  2892.  
  2893. const addCssManaged = () => {
  2894. if (!isCssAdded && document.documentElement && document.head) {
  2895. isCssAdded = true;
  2896. document.head.appendChild(dr(addCssElement())).textContent = addCss();
  2897. if (ENABLE_FONT_PRE_RENDERING) {
  2898. Promise.resolve().then(addFontPreRendering)
  2899. }
  2900. }
  2901. }
  2902.  
  2903. return { addCssManaged };
  2904. })();
  2905.  
  2906.  
  2907. const { setupStyle } = (() => {
  2908.  
  2909. const sp7 = Symbol();
  2910.  
  2911. const proxyHelperFn = (dummy) => ({
  2912.  
  2913. get(target, prop) {
  2914. return (prop in dummy) ? dummy[prop] : prop === sp7 ? target : target[prop];
  2915. },
  2916. set(target, prop, value) {
  2917. if (!(prop in dummy)) {
  2918. target[prop] = value;
  2919. }
  2920. return true;
  2921. },
  2922. has(target, prop) {
  2923. return (prop in target);
  2924. },
  2925. deleteProperty(target, prop) {
  2926. return true;
  2927. },
  2928. ownKeys(target) {
  2929. return Object.keys(target);
  2930. },
  2931. defineProperty(target, key, descriptor) {
  2932. return Object.defineProperty(target, key, descriptor);
  2933. },
  2934. getOwnPropertyDescriptor(target, key) {
  2935. return Object.getOwnPropertyDescriptor(target, key);
  2936. },
  2937.  
  2938. });
  2939.  
  2940. const setupStyle = (m1, m2) => {
  2941. if (!ENABLE_NO_SMOOTH_TRANSFORM) return;
  2942.  
  2943. const dummy1v = {
  2944. transform: '',
  2945. height: '',
  2946. minHeight: '',
  2947. paddingBottom: '',
  2948. paddingTop: ''
  2949. };
  2950.  
  2951. const dummyStyleFn = (k) => (function () { const style = this[sp7]; return style[k](...arguments); });
  2952. for (const k of ['toString', 'getPropertyPriority', 'getPropertyValue', 'item', 'removeProperty', 'setProperty']) {
  2953. dummy1v[k] = dummyStyleFn(k);
  2954. }
  2955.  
  2956. const dummy1p = proxyHelperFn(dummy1v);
  2957. const sp1v = new Proxy(m1.style, dummy1p);
  2958. const sp2v = new Proxy(m2.style, dummy1p);
  2959. Object.defineProperty(m1, 'style', { get() { return sp1v }, set() { }, enumerable: true, configurable: true });
  2960. Object.defineProperty(m2, 'style', { get() { return sp2v }, set() { }, enumerable: true, configurable: true });
  2961. m1.removeAttribute("style");
  2962. m2.removeAttribute("style");
  2963.  
  2964. }
  2965.  
  2966. return { setupStyle };
  2967.  
  2968. })();
  2969.  
  2970.  
  2971.  
  2972. function setThumbnails(config) {
  2973.  
  2974. const { baseObject, thumbnails, flag0, imageLinks } = config;
  2975.  
  2976. if (flag0 || (ENABLE_PRELOAD_THUMBNAIL && imageLinks)) {
  2977.  
  2978.  
  2979. if (thumbnails && thumbnails.length > 0) {
  2980. if (flag0 > 0 && thumbnails.length > 1) {
  2981. let pSize = 0;
  2982. let newThumbnails = [];
  2983. for (const thumbnail of thumbnails) {
  2984. if (!thumbnail || !thumbnail.url) continue;
  2985. const squarePhoto = thumbnail.width === thumbnail.height && typeof thumbnail.width === 'number';
  2986. const condSize = pSize <= 0 || (flag0 === 1 ? pSize > thumbnail.width : pSize < thumbnail.width);
  2987. const leastSizeFulfilled = squarePhoto ? thumbnail.width >= LEAST_IMAGE_SIZE : true;
  2988. if ((!squarePhoto || condSize) && leastSizeFulfilled) {
  2989. newThumbnails.push(thumbnail);
  2990. if (imageLinks) imageLinks.add(thumbnail.url);
  2991. }
  2992. if (squarePhoto && condSize && leastSizeFulfilled) {
  2993. pSize = thumbnail.width;
  2994. }
  2995. }
  2996. if (thumbnails.length !== newThumbnails.length && thumbnails === baseObject.thumbnails && newThumbnails.length > 0) {
  2997. baseObject.thumbnails = newThumbnails;
  2998. } else {
  2999. newThumbnails.length = 0;
  3000. }
  3001. newThumbnails = null;
  3002. } else {
  3003. for (const thumbnail of thumbnails) {
  3004. if (thumbnail && thumbnail.url) {
  3005. if (imageLinks) imageLinks.add(thumbnail.url);
  3006. }
  3007. }
  3008. }
  3009. }
  3010.  
  3011. }
  3012. }
  3013.  
  3014. function fixLiveChatItem(item, imageLinks) {
  3015. const liveChatTextMessageRenderer = (item || 0).liveChatTextMessageRenderer || 0;
  3016. if (liveChatTextMessageRenderer) {
  3017. const messageRuns = (liveChatTextMessageRenderer.message || 0).runs || 0;
  3018. if (messageRuns && messageRuns.length > 0) {
  3019. for (const run of messageRuns) {
  3020. const emojiImage = (((run || 0).emoji || 0).image || 0);
  3021. setThumbnails({
  3022. baseObject: emojiImage,
  3023. thumbnails: emojiImage.thumbnails,
  3024. flag0: EMOJI_IMAGE_SINGLE_THUMBNAIL,
  3025. imageLinks
  3026. });
  3027. }
  3028. }
  3029. const authorPhoto = liveChatTextMessageRenderer.authorPhoto || 0;
  3030. setThumbnails({
  3031. baseObject: authorPhoto,
  3032. thumbnails: authorPhoto.thumbnails,
  3033. flag0: AUTHOR_PHOTO_SINGLE_THUMBNAIL,
  3034. imageLinks
  3035. });
  3036. }
  3037. }
  3038.  
  3039.  
  3040.  
  3041. let kptPF = null;
  3042. const emojiPrefetched = new LimitedSizeSet(PREFETCH_LIMITED_SIZE_EMOJI);
  3043. const authorPhotoPrefetched = new LimitedSizeSet(PREFETCH_LIMITED_SIZE_AUTHOR_PHOTO);
  3044.  
  3045. const linkerOnload = function () {
  3046. this.resolveFn({
  3047. link: this,
  3048. success: true
  3049. });
  3050. this.remove();
  3051. };
  3052. const linkerOnError = function () {
  3053. this.resolveFn({
  3054. link: this,
  3055. success: false
  3056. });
  3057. this.remove();
  3058. };
  3059. function linker(link, rel, href, _as) {
  3060. return new Promise(resolve => {
  3061. if (!link) link = document.createElement('link');
  3062. link.rel = rel;
  3063. if (_as) link.setAttribute('as', _as);
  3064. link.resolveFn = resolve;
  3065. link.onload = linkerOnload;
  3066. link.onerror = linkerOnError;
  3067. link.href = href;
  3068. document.head.appendChild(link);
  3069. link = null;
  3070. });
  3071. }
  3072.  
  3073. // ------- side process [sideProcesses] -------
  3074. const reuseFixDataViewModel = (elm) => {
  3075. // detach data-view model signal
  3076. return Promise.resolve(elm).then((elm) => {
  3077. for (const node of elm.getElementsByTagName('*')) {
  3078. const cnt = insp(node);
  3079. if (typeof cnt.dispose === 'function' && cnt.dispose.length === 0) {
  3080. try {
  3081. cnt.dispose();
  3082. } catch (e) { }
  3083. } else if (typeof node.dispose === 'function' && node.dispose.length === 0) {
  3084. try {
  3085. node.dispose();
  3086. } catch (e) { }
  3087. }
  3088. }
  3089. }).catch(console.warn);;
  3090. };
  3091. const reuseFixYtIconRendering = (elm) => {
  3092. // make properties fresh for flushing
  3093. // return Promise.resolve(elm).then((elm) => {
  3094. // refreshChildrenYtIcons(elm);
  3095. // }).catch(console.warn);;
  3096. };
  3097. const tickerMessageRemovalMo = new MutationObserver(() => {
  3098. const elements = document.querySelectorAll('[ticker-message-removed]:nth-child(n + 40)');
  3099. for (const s of elements) {
  3100. insp(s).requestRemoval();
  3101. }
  3102. });
  3103. tickerMessageRemovalMo.observe(document, { subtree: true, attributes: true, attributeFilter: ['ticker-message-removed'] });
  3104. const onVisibleItemStampNodeRemoval = (elmId) => {
  3105. // set the corresponding ticker [ticker-message-removed]
  3106. return Promise.resolve(elmId).then((elmId) => {
  3107. const tickerElm = document.querySelector(`.style-scope.yt-live-chat-ticker-renderer[id="${elmId}"]`);
  3108. if (tickerElm) {
  3109. tickerElm.setAttribute('ticker-message-removed', '');
  3110. }
  3111. }).catch(console.warn);;
  3112. };
  3113. let onTickerItemStampNodeAddedwaiting = false;
  3114. const onTickerItemStampNodeAdded = () =>{
  3115. // remove the stale ticker(s)
  3116. if (onTickerItemStampNodeAddedwaiting) return;
  3117. onTickerItemStampNodeAddedwaiting = true;
  3118. return Promise.resolve().then(() => {
  3119. onTickerItemStampNodeAddedwaiting = false;
  3120. const selector = "[ticker-message-removed]:nth-child(n + 40)";
  3121. const tickerElm = document.querySelector(selector);
  3122. if (tickerElm) { // likely false
  3123. const tickerElms = document.querySelectorAll(selector);
  3124. for (const tickerElm of tickerElms) insp(tickerElm).requestRemoval();
  3125. }
  3126. }).catch(console.warn);;
  3127. };
  3128. // const mutationDelayedRefreshData = async (cnt) => {
  3129. // // ensure data is invalidated correctly after mutation
  3130. // return Promise.resolve(cnt).then(async cnt => {
  3131. // wme.data = `${(wme.data & 7) + 1}`;
  3132. // await wmp;
  3133. // cnt.__refreshData930__ && cnt.data && cnt.isAttached && cnt.parentComponent && cnt.__refreshData930__('data', !0);
  3134. // });
  3135. // }
  3136. // ------- side process [sideProcesses] -------
  3137.  
  3138. const cleanContext = async (win) => {
  3139. const waitFn = requestAnimationFrame; // shall have been binded to window
  3140. try {
  3141. let mx = 16; // MAX TRIAL
  3142. const frameId = 'vanillajs-iframe-v1';
  3143. /** @type {HTMLIFrameElement | null} */
  3144. let frame = document.getElementById(frameId);
  3145. let removeIframeFn = null;
  3146. if (!frame) {
  3147. frame = document.createElement('iframe');
  3148. frame.id = frameId;
  3149. const blobURL = typeof webkitCancelAnimationFrame === 'function' && typeof kagi === 'undefined' ? (frame.src = URL.createObjectURL(new Blob([], { type: 'text/html' }))) : null; // avoid Brave Crash
  3150. frame.sandbox = 'allow-same-origin'; // script cannot be run inside iframe but API can be obtained from iframe
  3151. let n = document.createElement('noscript'); // wrap into NOSCRPIT to avoid reflow (layouting)
  3152. n.appendChild(frame);
  3153. while (!document.documentElement && mx-- > 0) await new Promise(waitFn); // requestAnimationFrame here could get modified by YouTube engine
  3154. const root = document.documentElement;
  3155. root.appendChild(n); // throw error if root is null due to exceeding MAX TRIAL
  3156. if (blobURL) Promise.resolve().then(() => URL.revokeObjectURL(blobURL));
  3157.  
  3158. removeIframeFn = (setTimeout) => {
  3159. const removeIframeOnDocumentReady = (e) => {
  3160. e && win.removeEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false);
  3161. e = n;
  3162. n = win = removeIframeFn = 0;
  3163. setTimeout ? setTimeout(() => e.remove(), 200) : e.remove();
  3164. }
  3165. if (!setTimeout || document.readyState !== 'loading') {
  3166. removeIframeOnDocumentReady();
  3167. } else {
  3168. win.addEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false);
  3169. }
  3170. }
  3171. }
  3172. while (!frame.contentWindow && mx-- > 0) await new Promise(waitFn);
  3173. const fc = frame.contentWindow;
  3174. if (!fc) throw "window is not found."; // throw error if root is null due to exceeding MAX TRIAL
  3175. try {
  3176. const { requestAnimationFrame, setTimeout, cancelAnimationFrame, setInterval, clearInterval, getComputedStyle } = fc;
  3177. const res = { requestAnimationFrame, setTimeout, cancelAnimationFrame, setInterval, clearInterval, getComputedStyle };
  3178. for (let k in res) res[k] = res[k].bind(win); // necessary
  3179. if (removeIframeFn) Promise.resolve(res.setTimeout).then(removeIframeFn);
  3180.  
  3181. /** @type {HTMLElement} */
  3182. const HTMLElementProto = fc.HTMLElement.prototype;
  3183. /** @type {EventTarget} */
  3184. const EventTargetProto = fc.EventTarget.prototype;
  3185. // jsonParseFix = {
  3186. // _JSON: fc.JSON, _parse: fc.JSON.parse
  3187. // }
  3188. return {
  3189. ...res,
  3190. animate: HTMLElementProto.animate,
  3191. addEventListener: EventTargetProto.addEventListener,
  3192. removeEventListener: EventTargetProto.removeEventListener
  3193. };
  3194. } catch (e) {
  3195. if (removeIframeFn) removeIframeFn();
  3196. return null;
  3197. }
  3198. } catch (e) {
  3199. console.warn(e);
  3200. return null;
  3201. }
  3202. };
  3203.  
  3204. cleanContext(win).then(__CONTEXT__ => {
  3205. if (!__CONTEXT__) return null;
  3206.  
  3207. const { requestAnimationFrame, setTimeout, cancelAnimationFrame, setInterval, clearInterval, animate, getComputedStyle, addEventListener, removeEventListener } = __CONTEXT__;
  3208.  
  3209. const wmComputedStyle = new WeakMap();
  3210. const getComputedStyleCached = (elem) => {
  3211. let cs = wmComputedStyle.get(elem);
  3212. if (!cs) {
  3213. cs = getComputedStyle(elem);
  3214. wmComputedStyle.set(elem, cs);
  3215. }
  3216. return cs;
  3217. }
  3218.  
  3219.  
  3220. const isGPUAccelerationAvailable = (() => {
  3221. // https://gist.github.com/cvan/042b2448fcecefafbb6a91469484cdf8
  3222. try {
  3223. const canvas = document.createElement('canvas');
  3224. return !!(canvas.getContext('webgl') || canvas.getContext('experimental-webgl'));
  3225. } catch (e) {
  3226. return false;
  3227. }
  3228. })();
  3229.  
  3230. const foregroundPromiseFn_noGPU = (() => {
  3231.  
  3232. if (isGPUAccelerationAvailable) return null;
  3233.  
  3234. const pd = Object.getOwnPropertyDescriptor(Document.prototype, 'visibilityState');
  3235. if (!pd || typeof pd.get !== 'function') return null;
  3236. const pdGet = pd.get;
  3237.  
  3238. let pr = null;
  3239.  
  3240. let hState = pdGet.call(document) === 'hidden';
  3241. // let cid = 0;
  3242. pureAddEventListener.call(document, 'visibilitychange', (evt) => {
  3243. const newHState = pdGet.call(document) === 'hidden';
  3244. if (hState !== newHState) {
  3245. // if (cid > 0) cid = clearInterval(cid);
  3246. hState = newHState;
  3247. if (!hState && pr) pr = pr.resolve();
  3248. }
  3249. });
  3250.  
  3251. // cid = setInterval(() => {
  3252. // const newHState = document.visibilityState === 'hidden';
  3253. // if (hState !== newHState) {
  3254. // hState = newHState;
  3255. // if (!hState && pr) pr = pr.resolve();
  3256. // }
  3257. // }, 100);
  3258.  
  3259.  
  3260. return (() => {
  3261. if (pr) return pr;
  3262. const w = ((!hState && setTimeout(() => {
  3263. if (!hState && pr === w) pr = pr.resolve();
  3264. })), (pr = new PromiseExternal()));
  3265. return w;
  3266. });
  3267.  
  3268. })();
  3269.  
  3270. // window.foregroundPromiseFn_noGPU = foregroundPromiseFn_noGPU;
  3271.  
  3272. let rafPromise = null;
  3273. const getRafPromise = () => rafPromise || (rafPromise = new Promise(resolve => {
  3274. requestAnimationFrame(hRes => {
  3275. rafPromise = null;
  3276. resolve(hRes);
  3277. });
  3278. }));
  3279. const foregroundPromiseFn = foregroundPromiseFn_noGPU || getRafPromise;
  3280.  
  3281. // const iAFP = foregroundPromiseFn_noGPU ? foregroundPromiseFn_noGPU : typeof IntersectionObserver === 'undefined' ? getRafPromise : (() => {
  3282.  
  3283. // const ioWM = new WeakMap();
  3284. // const ek = Symbol();
  3285. // /** @type {IntersectionObserverCallback} */
  3286. // const ioCb = (entries, observer) => {
  3287. // /** @type {PromiseExternal} */
  3288. // const pr = observer[ek];
  3289. // const resolve = pr.resolve;
  3290. // let target;
  3291. // if (resolve && (target = ((entries ? entries[0] : 0) || 0).target) instanceof Element) {
  3292. // pr.resolve = null;
  3293. // observer.unobserve(target);
  3294. // resolve();
  3295. // }
  3296. // };
  3297. // /**
  3298. // *
  3299. // * @param {Element} elm
  3300. // * @returns {Promise<void>}
  3301. // */
  3302. // const iAFP = (elm) => {
  3303. // let io = ioWM.get(elm);
  3304. // if (!io) {
  3305. // io = new IntersectionObserver(ioCb);
  3306. // ioWM.set(elm, io); // strong reference
  3307. // }
  3308. // let pr = io[ek];
  3309. // if (!pr) {
  3310. // pr = io[ek] = new PromiseExternal();
  3311. // io.observe(elm);
  3312. // }
  3313. // return pr;
  3314. // }
  3315.  
  3316. // return iAFP;
  3317.  
  3318. // })();
  3319.  
  3320. let playerState = null;
  3321. let _playerState = null;
  3322. let lastPlayerProgress = null;
  3323. let relayCount = 0;
  3324. let playerEventsByIframeRelay = false;
  3325. let isPlayProgressTriggered = false;
  3326. let waitForInitialDataCompletion = 0;
  3327.  
  3328.  
  3329.  
  3330. // let aeConstructor = null;
  3331.  
  3332. // << __openedChanged82 >>
  3333. let currentMenuPivotWR = null;
  3334.  
  3335. // << if DO_PARTICIPANT_LIST_HACKS >>
  3336. const beforeParticipantsMap = new WeakMap();
  3337. // << end >>
  3338.  
  3339.  
  3340.  
  3341. // << if onRegistryReadyForDOMOperations >>
  3342.  
  3343. let dt0 = Date.now() - 2000;
  3344. const dateNow = () => Date.now() - dt0;
  3345. // let lastScroll = 0;
  3346. // let lastLShow = 0;
  3347. let lastWheel = 0;
  3348. let lastMouseUp = 0;
  3349. let currentMouseDown = false;
  3350. let lastTouchDown = 0;
  3351. let lastTouchUp = 0;
  3352. let currentTouchDown = false;
  3353. let lastUserInteraction = 0;
  3354.  
  3355. let scrollChatFn = null;
  3356.  
  3357. // let skipDontRender = true; // true first; false by flushActiveItems_
  3358. // let allowDontRender = null;
  3359.  
  3360. // ---- #items mutation ----
  3361. // let firstList = true;
  3362.  
  3363. // << end >>
  3364.  
  3365.  
  3366. const stackMarcoTask = (f) => {
  3367. return new Promise(resolve => {
  3368. nextBrowserTick_(async () => {
  3369. try {
  3370. await f();
  3371. } catch (e) {
  3372. console.warn(e);
  3373. } finally {
  3374. resolve();
  3375. }
  3376. });
  3377. })
  3378. };
  3379.  
  3380.  
  3381. const elementFirstElementChild = Object.getOwnPropertyDescriptor(Element.prototype, 'firstElementChild');
  3382. const sFirstElementChild = Symbol();
  3383. Object.defineProperty(Element.prototype, sFirstElementChild, elementFirstElementChild);
  3384.  
  3385. const elementLastElementChild = Object.getOwnPropertyDescriptor(Element.prototype, 'lastElementChild');
  3386. const sLastElementChild = Symbol();
  3387. Object.defineProperty(Element.prototype, sLastElementChild, elementLastElementChild);
  3388.  
  3389. const elementPrevElementSibling = Object.getOwnPropertyDescriptor(Element.prototype, 'previousElementSibling');
  3390. const sPrevElementSibling = Symbol();
  3391. Object.defineProperty(Element.prototype, sPrevElementSibling, elementPrevElementSibling);
  3392.  
  3393. const elementNextElementSibling = Object.getOwnPropertyDescriptor(Element.prototype, 'nextElementSibling');
  3394. const sNextElementSibling = Symbol();
  3395. Object.defineProperty(Element.prototype, sNextElementSibling, elementNextElementSibling);
  3396.  
  3397. const firstComponentChildFn = (elNode) => {
  3398. elNode = elNode[sFirstElementChild];
  3399. while ((elNode instanceof Element) && !elNode.is) elNode = elNode[sNextElementSibling];
  3400. return elNode;
  3401. }
  3402. const lastComponentChildFn = (elNode) => {
  3403. elNode = elNode[sLastElementChild];
  3404. while ((elNode instanceof Element) && !elNode.is) elNode = elNode[sPrevElementSibling];
  3405. return elNode;
  3406. }
  3407. const nextComponentSiblingFn = (elNode) => {
  3408. do {
  3409. elNode = elNode[sNextElementSibling];
  3410. } while ((elNode instanceof Element) && !elNode.is);
  3411. return elNode;
  3412. }
  3413.  
  3414. const nativeNow = performance.constructor.prototype.now.bind(performance);
  3415.  
  3416. const queueMicrotask_ = typeof queueMicrotask === 'function' ? queueMicrotask : (f) => (Promise.resolve().then(f), void 0);
  3417.  
  3418. const executeTaskBatch = function (taskArr, firstMarco = true) {
  3419. if (!(taskArr || 0).length) throw new TypeError(`Illegal invocation`);
  3420. return new Promise(resolveFinal => {
  3421. let resolveFn = null;
  3422. const len = taskArr.length;
  3423. const results = new Array(len);
  3424. const makePromise = () => new Promise(resolve => { resolveFn = resolve });
  3425. let firedCount = 0;
  3426. const executor = () => {
  3427. if (taskArr.length !== len) throw new TypeError(`Illegal invocation`);
  3428. const resolveFn_ = resolveFn;
  3429. let t0 = 0;
  3430. let next = 0;
  3431. taskArr.forEach((task, idx) => {
  3432. if (typeof (task || 0) !== 'object') throw new TypeError(`Illegal invocation`);
  3433. if (!task.fired) {
  3434. queueMicrotask_(() => {
  3435. if (next || task.fired) return;
  3436. task.fired = true;
  3437. if (++firedCount === len) next |= 2;
  3438. if (!t0) t0 = nativeNow() + 10;
  3439. const { fn } = task;
  3440. results[idx] = fn(task); // sync task only
  3441. if (nativeNow() > t0) next |= 1;
  3442. });
  3443. }
  3444. });
  3445. queueMicrotask_(() => resolveFn_(next))
  3446. }
  3447. const looper = (next) => {
  3448. if (!next) throw new TypeError(`Illegal invocation`);
  3449. if (next & 2) {
  3450. if (next & 1) {
  3451. nextBrowserTick_(() => resolveFinal(results))
  3452. } else {
  3453. resolveFinal(results);
  3454. }
  3455. } else {
  3456. const p = makePromise();
  3457. nextBrowserTick_(executor);
  3458. p.then(looper);
  3459. }
  3460. }
  3461. const p = makePromise();
  3462. firstMarco ? nextBrowserTick_(executor) : executor();
  3463. p.then(looper);
  3464.  
  3465. })
  3466.  
  3467. }
  3468. // window.executeTaskBatch = executeTaskBatch;
  3469.  
  3470.  
  3471. const renderMap = new WeakMap();
  3472.  
  3473.  
  3474. // reserved for future use
  3475. const countKeys = (H) => {
  3476.  
  3477. const countKeys_ = (H, u, q, l) => {
  3478. if (u.has(H)) return;
  3479. u.add(H);
  3480. const pds = Object.getOwnPropertyDescriptors(H);
  3481. for (const name in pds) {
  3482. const pd_ = pds[name];
  3483. const o = pd_.value;
  3484. if (o && pd_.configurable && pd_.writable && !(o instanceof EventTarget)) {
  3485. if (typeof o === 'object') {
  3486. q.push([l, name.length]);
  3487. countKeys_(o, u, q, l+1);
  3488. }
  3489. }
  3490. }
  3491. };
  3492. const m = [];
  3493. countKeys_(H, new WeakSet(), m, 0);
  3494. return `-${tupleHash(m, false).toString(36)}${tupleHash(m, true).toString(36)}`; // 12 chars
  3495. }
  3496.  
  3497. // reserved for future use
  3498. function tupleHash(pairs, reversed) {
  3499. let hash = 17; // Prime seed
  3500. const prime1 = 31;
  3501. for (let i = 0; i < pairs.length; i++) {
  3502. const [a_, b_] = pairs[i];
  3503. const a = reversed ? b_ : a_;
  3504. const b = reversed ? a_ : b_;
  3505. // Combine a and b into pairHash
  3506. let pairHash = ((a * prime1) ^ b) >>> 0;
  3507. // Mix pairHash into hash with bitwise operations
  3508. hash ^= pairHash;
  3509. hash = ((hash << 5) | (hash >>> 27)) >>> 0; // Rotate left 5 bits
  3510. hash = (hash * 37 + 11) >>> 0; // Small prime multiplier and offset
  3511. }
  3512. // Finalize to ensure fixed range (optional: constrain to 30 bits)
  3513. return 0x2FFFFFFF + (hash & 0x3FFFFFFF); // Mask to 30 bits (max: 1073741823)
  3514. }
  3515.  
  3516.  
  3517. const rendererStamperFactory = (cProto, options) => {
  3518.  
  3519. let pDivResourceEventCount = 0;
  3520.  
  3521. const pDivOnResource = function (evt) {
  3522. const target = evt.target;
  3523. if (target && target.nodeType === 1 && target.nodeName === "IMG") {
  3524. pDivResourceEventCount = (pDivResourceEventCount & 1073741823) + 1;
  3525. }
  3526. };
  3527.  
  3528. const { key, stamperDomClass, preloadFn } = options;
  3529.  
  3530. // const newDoc = document.implementation.createHTMLDocument("NewDoc");
  3531. const pSpace = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
  3532. document.documentElement.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3533. mockCommentElement(document.documentElement.lastChild);
  3534. document.documentElement.lastChild.replaceWith(pSpace);
  3535. const pNode = document.createElement('ns-538');
  3536. pSpace.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3537. mockCommentElement(pSpace.lastChild);
  3538. pSpace.lastChild.replaceWith(pNode);
  3539.  
  3540. const pDiv = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
  3541. if (typeof pNode.attachShadow === 'function') {
  3542. const pShadow = pNode.attachShadow({ mode: "open" });
  3543. pShadow.replaceChildren(pDiv);
  3544. } else {
  3545. pNode.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3546. mockCommentElement(pNode.lastChild);
  3547. pNode.lastChild.replaceWith(pDiv);
  3548. }
  3549.  
  3550. const pDivNew = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
  3551.  
  3552. pDiv.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3553. mockCommentElement(pDiv.lastChild);
  3554. pDiv.lastChild.replaceWith(pDivNew);
  3555.  
  3556. pDivNew.addEventListener('load', pDivOnResource, true);
  3557. pDivNew.addEventListener('error', pDivOnResource, true);
  3558.  
  3559. const wmRemoved = new Map();
  3560. wmRemoved.set = wmRemoved.setOriginal || wmRemoved.set;
  3561.  
  3562. // const wmMapToItem = new WeakMap();
  3563. // let wmPendingList = null;
  3564.  
  3565. const nullComponents = new Map();
  3566. nullComponents.set = nullComponents.setOriginal || nullComponents.set;
  3567.  
  3568. const componentDefaultAttributes = new WeakMap();
  3569.  
  3570. const fnKeyH = `${key}$$c472`;
  3571. let spliceTempDisabled = false;
  3572.  
  3573. cProto.__ensureContainerDomApi7577 = function (cId) {
  3574. const container = this.getStampContainer_(cId);
  3575. if (container && !container.__checkedDomApi33__) {
  3576. container.__checkedDomApi33__ = true;
  3577. if (!container.__domApi) {
  3578. if (typeof this.stampDomArray366_ === 'function' && this.stampDomArray366_.length === 6) {
  3579. let c = container;
  3580. try {
  3581. this.stampDomArray366_.call({
  3582. getStampContainer_(d) {
  3583. return c
  3584. },
  3585. get is() {
  3586. throw new Error('');
  3587. },
  3588. get hostElement() {
  3589. throw new Error('');
  3590. }
  3591. }, 0, cId, false, false, false, false);
  3592. } catch (e) { }
  3593. c = null;
  3594. }
  3595. }
  3596. }
  3597. }
  3598.  
  3599. cProto[fnKeyH] = async function (cTag, cId, pr00) {
  3600.  
  3601. // console.log(38806)
  3602. if (!this) return;
  3603. const fxCounter_ = this.fxCounter5355 = (this.fxCounter5355 & 1073741823) + 1;
  3604.  
  3605. // await the current executing task (if any)
  3606. // and avoid stacking in the same marco task
  3607. await Promise.all([pr00, nextBrowserTick_()]);
  3608. if (fxCounter_ !== this.fxCounter5355) return;
  3609.  
  3610. const addedCount0 = this.ec389a;
  3611. const removedCount0 = this.ec389r;
  3612.  
  3613. this.ec389 = false;
  3614. this.ec389a = 0;
  3615. this.ec389r = 0;
  3616.  
  3617. if (!addedCount0 && !removedCount0) return;
  3618. const stampDom_ = (this.stampDom || 0)[cTag] || 0;
  3619. const stampDomMap_ = stampDom_.mapping;
  3620. const stampDomEvent_ = stampDom_.events;
  3621. if (!stampDomMap_) return;
  3622. if (!this.__ensureContainerDomApi7577) return;
  3623. const hostElement = this.hostElement;
  3624. if (!hostElement) return;
  3625.  
  3626. spliceTempDisabled = true;
  3627.  
  3628. this.__ensureContainerDomApi7577(cId);
  3629.  
  3630. const isTickerRendering = cTag === 'tickerItems';
  3631. const isMessageListRendering = cTag === 'visibleItems';
  3632.  
  3633. // coming process can be stacked as ec389a and ec389r are reset.
  3634.  
  3635. const deObjectComponent = (itemEntry) => {
  3636. const I = firstObjectKey(itemEntry);
  3637. const L = stampDomMap_[I];
  3638. const H = itemEntry[I];
  3639. return [L, H];
  3640. };
  3641.  
  3642. let renderNodeCount = 0;
  3643.  
  3644. let renderOrdering = {};
  3645. let doFix = false;
  3646. const renderEntries = this[cTag].map((item) => {
  3647. const [L, H] = deObjectComponent(item);
  3648. const componentName = this.getComponentName_(L, H);
  3649. if (H && H.id && componentName) {
  3650. if (!H.__renderOrderId422__) {
  3651. H.__renderOrderId422__ = this.renderOrderId411 = (this.renderOrderId411 & 1073741823) + 1;
  3652. }
  3653. let p = renderOrdering[`${componentName}#${H.id}`];
  3654. if (p) doFix = true;
  3655. if (!p || p > H.__renderOrderId422__) {
  3656. renderOrdering[`${componentName}#${H.id}`] = H.__renderOrderId422__;
  3657. }
  3658. return [item, L, H, componentName, `${componentName}#${H.id}`]
  3659. } else {
  3660. return [item, L, H, componentName, true]
  3661. }
  3662. });
  3663. if (doFix) {
  3664. const arr = this[cTag];
  3665. for (let i = renderEntries.length - 1; i >= 0; i--) {
  3666. const e = renderEntries[i];
  3667. let m = e[4];
  3668. if (m === true) {
  3669. } else if (renderOrdering[m] === e[2].__renderOrderId422__) {
  3670. } else {
  3671. arr.splice(i, 1);
  3672. renderEntries.splice(i, 1);
  3673. }
  3674. }
  3675. }
  3676. renderOrdering = null;
  3677.  
  3678. const renderList = renderEntries.map((e) => {
  3679. const [item, L, H, componentName] = e;
  3680. const node = kRef(renderMap.get(H));
  3681. if (node && hostElement.contains(node)) {
  3682. renderNodeCount++;
  3683. return node;
  3684. } else if (node && !hostElement.contains(node)) {
  3685. renderMap.delete(H);
  3686. return item;
  3687. } else {
  3688. return item;
  3689. }
  3690. });
  3691.  
  3692. const isRenderListEmpty = renderList.length === 0;
  3693.  
  3694. // console.log(1773, this.ec389a, this.ec389r)
  3695.  
  3696. this.ec389a = 0;
  3697. this.ec389r = 0;
  3698.  
  3699.  
  3700. // this.ec389 = null;
  3701. // this.ec389a = 0;
  3702. // this.ec389r = 0;
  3703.  
  3704. let addedCounter = 0;
  3705. let removedCounter = 0;
  3706.  
  3707. const createConnectedComponentElm = (insertionObj, L, H, componentName) => {
  3708. // const reusable = false;
  3709. // const componentName = this.getComponentName_(L, H);
  3710. let component;
  3711. if (!nullComponents.has(componentName)) {
  3712. nullComponents.set(componentName, (component = document.createElement(componentName)));
  3713. component.className = stamperDomClass;
  3714. // shadowElm.insertAdjacentElement('beforeend', component);
  3715. } else {
  3716. component = nullComponents.get(componentName);
  3717. }
  3718. component = component.cloneNode(false);
  3719.  
  3720. // const cnt = insp(component);
  3721.  
  3722. // cnt.__dataOld = cnt.__dataPending = null;
  3723. pDivNew.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3724. mockCommentElement(pDivNew.lastChild);
  3725. pDivNew.lastChild.replaceWith(component);
  3726. // cnt.__dataOld = cnt.__dataPending = null;
  3727.  
  3728. return component;
  3729. }
  3730.  
  3731. const listDom = this.getStampContainer_(cId);
  3732.  
  3733. const pnForNewItem = (item) => {
  3734.  
  3735. const [L, H] = deObjectComponent(item);
  3736.  
  3737. const componentName = this.getComponentName_(L, H);
  3738.  
  3739. const wmList = wmRemoved.get(componentName.toLowerCase());
  3740.  
  3741. let connectedComponent = null;
  3742. if (wmList && (connectedComponent = wmList.firstElementChild)) {
  3743. if (this.telemetry_) this.telemetry_.reuse++;
  3744. // if (!wmPendingList) {
  3745. // wmPendingList = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
  3746. // wmPendingList.setAttributeNS('http://www.w3.org/2000/svg', 'wm-pending', 'true');
  3747. // pDiv.insertAdjacentElement('afterend', wmPendingList);
  3748. // }
  3749. // wmPendingList.insertAdjacentElement('beforeend', connectedComponent);
  3750. pDivNew.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3751. mockCommentElement(pDivNew.lastChild);
  3752. pDivNew.lastChild.replaceWith(connectedComponent);
  3753. const attrMap = connectedComponent.attributes;
  3754. const defaultAttrs = componentDefaultAttributes.get(connectedComponent);
  3755. if (defaultAttrs) {
  3756. for (const attr of [...attrMap]) {
  3757. const name = attr.name;
  3758. if (name in defaultAttrs) attr.value = defaultAttrs[name];
  3759. else attrMap.removeNamedItem(name);
  3760. }
  3761. if (attrMap.length !== defaultAttrs['"']) {
  3762. for (const name in defaultAttrs) {
  3763. if (!attrMap[name] && name !== '"') connectedComponent.setAttribute(name, defaultAttrs[name]);
  3764. }
  3765. }
  3766. }
  3767.  
  3768. } else {
  3769. connectedComponent = createConnectedComponentElm(item, L, H, componentName);
  3770. if (this.telemetry_) this.telemetry_.create++;
  3771. }
  3772. if (isTickerRendering) {
  3773. const container = connectedComponent.firstElementChild;
  3774. if (container) container.classList.add('yt-live-chat-ticker-stampdom-container');
  3775. }
  3776.  
  3777. return [item, L, H, connectedComponent];
  3778.  
  3779. };
  3780.  
  3781. let imgPreloadPr = null;
  3782. if (isMessageListRendering) {
  3783. const addedItems = renderList.filter(item => item === 'object' && (item instanceof Node));
  3784. imgPreloadPr = preloadFn(addedItems)();
  3785. }
  3786.  
  3787. spliceTempDisabled = false;
  3788.  
  3789. // const pt1 = performance.now();
  3790. // const newComponentsEntries = await Promise.all(renderList.map((item) => {
  3791. // return typeof item === 'object' && !(item instanceof Node) ? Promise.resolve(item).then(pnForNewItem) : item;
  3792. // }));
  3793. const newComponentsEntries = isRenderListEmpty ? [] : await executeTaskBatch(renderList.map(item => ({
  3794. item,
  3795. fn(task) {
  3796. const { item } = task;
  3797. return typeof item === 'object' && !(item instanceof Node) ? pnForNewItem(item) : item;
  3798. }
  3799. })));
  3800. // const pt2 = performance.now();
  3801.  
  3802. const imgPromises = [];
  3803.  
  3804. const imgPaths = new Set();
  3805.  
  3806. const pnForRenderNewItem = (entry) => {
  3807. const [item, L, H, connectedComponent] = entry;
  3808.  
  3809. const cnt = insp(connectedComponent);
  3810. // setupRefreshData930(cnt);
  3811. // if (typeof cnt.data === 'object' && cnt.__dataEnabled === true && cnt.__dataReady === true && cnt.__dataInvalid === false) {
  3812. // cnt.data = H;
  3813. // } else {
  3814. const q = this.deferRenderStamperBinding_
  3815. let q2;
  3816. if (typeof q === 'object') q2 = this.deferRenderStamperBinding_ = [];
  3817. this.deferRenderStamperBinding_(connectedComponent, L, Object.assign({}, H)); // pre-flush
  3818. this.flushRenderStamperComponentBindings_();
  3819. if (typeof q === 'object') {
  3820. this.deferRenderStamperBinding_ = q;
  3821. q2.length = 0;
  3822. }
  3823. // }
  3824. // if (cnt.__refreshData930__ && cnt.data) cnt.__refreshData930__('data', !0); // ensure data is invalidated
  3825.  
  3826. // fix yt-icon issue
  3827. // refreshChildrenYtIcons(connectedComponent);
  3828.  
  3829. // const imgs = connectedComponent.getElementsByTagName('IMG');
  3830. // if (imgs.length > 0) {
  3831. // for (let i = 0, l = imgs.length; i < l; i++) {
  3832. // const src = imgs[i].src;
  3833. // if (src.includes('://') && !imgPaths.has(src)) {
  3834. // imgPaths.add(src);
  3835. // imgPromises.push(imageFetch(src));
  3836. // }
  3837. // }
  3838. // }
  3839. componentDefaultAttributes.set(connectedComponent, getAttributes(connectedComponent));
  3840. return entry;
  3841. }
  3842.  
  3843. // const pt3 = performance.now();
  3844. // const newRenderedComponents = await Promise.all(newComponentsEntries.map((entry) => {
  3845. // return typeof entry === 'object' && !(entry instanceof Node) ? Promise.resolve(entry).then(pnForRenderNewItem) : entry;
  3846. // }));
  3847. const newRenderedComponents = isRenderListEmpty ? [] : await executeTaskBatch(newComponentsEntries.map(entry => ({
  3848. entry,
  3849. fn(task) {
  3850. const { entry } = task;
  3851. return typeof entry === 'object' && !(entry instanceof Node) ? pnForRenderNewItem(entry) : entry;
  3852. }
  3853. })));
  3854. // const pt4 = performance.now();
  3855.  
  3856. // console.log('xxss' , pt2-pt1, pt4-pt3)
  3857.  
  3858. this.flushRenderStamperComponentBindings_(); // ensure all deferred flush render tasks clear.
  3859.  
  3860. // imgPromises.push(imageFetch('data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'));
  3861. if (imgPromises.length > 0) {
  3862. const pr1 = Promise.all(imgPromises).catch(e => { });
  3863. const pr2 = autoTimerFn();
  3864. await Promise.race([pr1, pr2]).catch(e => { });
  3865. imgPaths.clear();
  3866. imgPromises.length = 0;
  3867. }
  3868. if (imgPreloadPr) await imgPreloadPr;
  3869.  
  3870. // const batching = [];
  3871. // let j = 0;
  3872. // let elNode;
  3873.  
  3874. const sideProcesses = [];
  3875.  
  3876. const removeStampNode_ = (elNode) => {
  3877.  
  3878. const elm = elNode;
  3879. const cnt = insp(elm);
  3880. let elemCount1 = elm.querySelectorAll('yt-img-shadow').length;
  3881.  
  3882. const elParent = elm.parentNode;
  3883. if (elm.__requestRemovalAt003__) {
  3884. elm.__requestRemovalAt003__ = 0;
  3885. } else {
  3886. if (cnt.requestRemoval) cnt.requestRemoval();
  3887. }
  3888. try {
  3889. (elParent.__domApi || elParent).removeChild(elm);
  3890. } catch (e) { }
  3891. const frag = document.createDocumentFragment();
  3892. frag.appendChild(elm);
  3893.  
  3894. const componentName = elm.nodeName.toLowerCase();
  3895. let wmList = wmRemoved.get(componentName);
  3896. if (!wmList) {
  3897. wmList = document.createDocumentFragment();
  3898. wmRemoved.set(componentName, wmList);
  3899. }
  3900. const data = cnt.data;
  3901. if (data) renderMap.delete(cnt.data);
  3902.  
  3903. let elemCount2 = elm.querySelectorAll('yt-img-shadow').length;
  3904.  
  3905. const [p1, p2] = [reuseFixDataViewModel(elm), reuseFixYtIconRendering(elm)];
  3906.  
  3907. sideProcesses.push(p1);
  3908. sideProcesses.push(p2);
  3909.  
  3910. if (!window.__fixTemplateReuse1058__ && elemCount1 !== elemCount2) return; // cannot reuse
  3911.  
  3912. Promise.all([elm, wmList, p1, p2]).then((r) => {
  3913. const [elm, wmList] = r;
  3914. wmList.appendChild(elm);
  3915. });
  3916. }
  3917.  
  3918. // const removeStampNode = async () => {
  3919.  
  3920. // removedCounter++;
  3921.  
  3922. // const nextElm = nextComponentSiblingFn(elNode);
  3923. // const elmId = elNode.id;
  3924. // removeStampNode_(elNode);
  3925. // // const dzid = this.getAttribute('dz-component-id');
  3926. // // ---- no-cache ----
  3927. // // try{
  3928. // // elm.remove();
  3929. // // }catch(e){}
  3930. // // ---- no-cache ----
  3931.  
  3932. // if (cTag === 'visibleItems') {
  3933. // sideProcesses.push(onVisibleItemStampNodeRemoval(elmId));
  3934. // }
  3935.  
  3936. // j++;
  3937. // elNode = nextElm;
  3938.  
  3939. // }
  3940.  
  3941. // if (typeof Polymer !== "undefined" && typeof Polymer.flush === "function") {
  3942. // // clear all pending rendering first
  3943. // await stackMarcoTask(async () => {
  3944. // Polymer.flush();
  3945. // });
  3946. // }
  3947.  
  3948. // main UI thread - DOM modification
  3949. await new Promise((resolveDM) => {
  3950. nextBrowserTick_(() => {
  3951.  
  3952. const isAtBottom = this.atBottom === true;
  3953. // if (ENABLE_OVERFLOW_ANCHOR && isAtBottom) {
  3954. // shouldScrollAfterFlush = true;
  3955. // }
  3956.  
  3957.  
  3958. const tasks = [];
  3959. let fragAppend = document.createDocumentFragment();
  3960. let shouldManualScroll = null;
  3961. let scrollTop1 = null, scrollTop2 = null;
  3962.  
  3963. const taskFn = {
  3964. remove: (task) => {
  3965.  
  3966. const { elNode } = task;
  3967.  
  3968. removedCounter++;
  3969.  
  3970. const elmId = elNode.id;
  3971. removeStampNode_(elNode);
  3972. // const dzid = this.getAttribute('dz-component-id');
  3973. // ---- no-cache ----
  3974. // try{
  3975. // elm.remove();
  3976. // }catch(e){}
  3977. // ---- no-cache ----
  3978.  
  3979. if (isMessageListRendering) {
  3980. sideProcesses.push(onVisibleItemStampNodeRemoval(elmId));
  3981. }
  3982.  
  3983. return 2
  3984.  
  3985. },
  3986. append: (task) => {
  3987.  
  3988. if (!fragAppend) return;
  3989.  
  3990. const { newNode, nodeAfter, parentNode, L, H } = task;
  3991.  
  3992. fragAppend.appendChild(newNode);
  3993.  
  3994.  
  3995. const itemScrollerX = (isMessageListRendering && isAtBottom) ? this.itemScroller : null;
  3996.  
  3997.  
  3998. if (itemScrollerX) {
  3999. if (scrollTop1 === null) scrollTop1 = itemScrollerX.scrollTop;
  4000. }
  4001.  
  4002. if (nodeAfter) {
  4003. (parentNode.__domApi || parentNode).insertBefore(fragAppend, nodeAfter);
  4004. } else {
  4005. (parentNode.__domApi || parentNode).appendChild(fragAppend);
  4006. }
  4007.  
  4008. this.deferRenderStamperBinding_(newNode, L, H);
  4009. this.flushRenderStamperComponentBindings_();
  4010.  
  4011.  
  4012. // nodeAfter ? nodeAfter.insertAdjacentElement('beforebegin', newNode) : parentNode.insertAdjacentElement('beforeend', newNode);
  4013. const connectedComponent = newNode;
  4014. const cnt = insp(connectedComponent);
  4015. renderMap.set(cnt.data, mWeakRef(connectedComponent));
  4016. // mutationDelayedRefreshData(cnt); // not included to sideProcesses
  4017. addedCounter++;
  4018.  
  4019. if (isTickerRendering) {
  4020. sideProcesses.push(onTickerItemStampNodeAdded());
  4021. }
  4022.  
  4023. if (itemScrollerX) {
  4024. if (scrollTop2 === null) scrollTop2 = itemScrollerX.scrollTop;
  4025. if (shouldManualScroll === null) shouldManualScroll = (scrollTop1 >= 0 && scrollTop2 >= 0 && Math.abs(scrollTop2 - scrollTop1) < 6);
  4026. if (shouldManualScroll) {
  4027. itemScrollerX.scrollTop = scrollTop2 + 16777216;
  4028. }
  4029. }
  4030.  
  4031. return 1
  4032. }
  4033. }
  4034.  
  4035. {
  4036. const indexMap = new WeakMap();
  4037. // let index = 0;
  4038.  
  4039. if (!isRenderListEmpty) {
  4040. for (let elNode_ = firstComponentChildFn(listDom), index = 0; elNode_ instanceof Node; elNode_ = nextComponentSiblingFn(elNode_)) {
  4041. indexMap.set(elNode_, index++);
  4042. }
  4043. }
  4044.  
  4045.  
  4046.  
  4047. const keepIndices = new Array(renderNodeCount);
  4048. let keepIndicesLen = 0, lastKeepIndex = -1, requireSort = false;
  4049. for (let i = 0, l = newRenderedComponents.length; i < l; i++) {
  4050. const entry = newRenderedComponents[i];
  4051. if (entry instanceof Node) {
  4052. const index = indexMap.get(entry);
  4053. keepIndices[keepIndicesLen++] = [index, entry];
  4054. if (index > lastKeepIndex) lastKeepIndex = index;
  4055. else requireSort = true;
  4056. }
  4057. }
  4058. keepIndices.length = keepIndicesLen;
  4059. if (requireSort) keepIndices.sort((a, b) => a[0] - b[0]);
  4060. let dk = 0;
  4061.  
  4062. let j = 0;
  4063. let elNode;
  4064.  
  4065. elNode = firstComponentChildFn(listDom);
  4066.  
  4067. if (!isRenderListEmpty) {
  4068. for (const rcEntry of newRenderedComponents) {
  4069. const index = indexMap.get(rcEntry);
  4070. if (typeof index === 'number') {
  4071. const indexEntry = keepIndices[dk++];
  4072. const [dIdx, dNode] = indexEntry;
  4073. indexMap.delete(rcEntry);
  4074. const idx = dIdx;
  4075. while (j < idx && elNode) {
  4076. tasks.push({
  4077. type: 'remove',
  4078. elNode,
  4079. fn: taskFn.remove
  4080. });
  4081. elNode = nextComponentSiblingFn(elNode);
  4082. j++;
  4083. }
  4084. if (j === idx) {
  4085. if (elNode) {
  4086. // if (dNode !== elNode) tasks.push({
  4087. // type: 'swap',
  4088. // earlyNode: indexEntry[1],
  4089. // laterNode: elNode
  4090. // });
  4091. elNode = nextComponentSiblingFn(elNode);
  4092. j++;
  4093. } else {
  4094. console.warn('elNode is not available?', renderList, addedCount0, removedCount0, j, idx);
  4095. }
  4096. }
  4097. } else if (rcEntry instanceof Node) {
  4098. // interruped by the external like clearList
  4099.  
  4100. tasks.push({
  4101. type: 'remove',
  4102. elNode: rcEntry,
  4103. fn: taskFn.remove
  4104. });
  4105.  
  4106. } else {
  4107. const [item, L, H, connectedComponent] = rcEntry;
  4108.  
  4109. tasks.push({
  4110. type: 'append',
  4111. newNode: connectedComponent,
  4112. nodeAfter: elNode,
  4113. parentNode: listDom,
  4114. item, L, H,
  4115. fn: taskFn.append
  4116. });
  4117.  
  4118. }
  4119.  
  4120. }
  4121. }
  4122.  
  4123. while (elNode) {
  4124.  
  4125. tasks.push({
  4126. type: 'remove',
  4127. elNode,
  4128. fn: taskFn.remove
  4129. });
  4130. elNode = nextComponentSiblingFn(elNode);
  4131.  
  4132. }
  4133.  
  4134. }
  4135.  
  4136. if (tasks.length >= 1) {
  4137. executeTaskBatch(tasks).then(() => {
  4138. fragAppend = null;
  4139. resolveDM();
  4140. }).catch(console.warn);
  4141. }
  4142.  
  4143. });
  4144. }).catch(console.warn);
  4145.  
  4146. {
  4147. const arr = this[cTag];
  4148. let b = 0;
  4149. b = b | this._setPendingPropertyOrPath(`${cTag}.splices`, {}, true, true);
  4150. b = b | this._setPendingPropertyOrPath(`${cTag}.length`, arr.length, true, true);
  4151. b && this._invalidateProperties();
  4152. }
  4153.  
  4154. // this.flushRenderStamperComponentBindings_(); // just in case...
  4155.  
  4156. await Promise.all(sideProcesses);
  4157.  
  4158. const detail = {
  4159. container: listDom
  4160. };
  4161. stampDomEvent_ && this.hostElement.dispatchEvent(new CustomEvent("yt-rendererstamper-finished", {
  4162. bubbles: !0,
  4163. cancelable: !1,
  4164. composed: !0,
  4165. detail
  4166. }));
  4167. detail.container = null;
  4168.  
  4169. // if (typeof Polymer !== "undefined" && typeof Polymer.flush === "function") {
  4170. // // clear all remaining rendering before promise resolve
  4171. // await stackMarcoTask(async () => {
  4172. // Polymer.flush();
  4173. // });
  4174. // }
  4175.  
  4176. }
  4177.  
  4178. // proceedStampDomArraySplices371_ // proceedStampDomArraySplices381_
  4179. cProto[key] = function (cTag, cId, indexSplice) {
  4180.  
  4181. if (spliceTempDisabled) return true;
  4182. // console.log('proceedStampDomArraySplices_')
  4183. // assume no error -> no try catch (performance consideration)
  4184. const { index, addedCount, removed } = indexSplice;
  4185. const removedCount = removed ? removed.length : indexSplice.removedCount;
  4186. indexSplice = null;
  4187. if (!addedCount && !removedCount) {
  4188. console.warn('proceedStampDomArraySplices_', 'Error 001');
  4189. return false;
  4190. }
  4191. if (this.ec389) {
  4192. this.ec389a += addedCount;
  4193. this.ec389r += removedCount;
  4194. } else {
  4195. if (this.ec389a || this.ec389r) {
  4196. console.warn('proceedStampDomArraySplices_', 'Error 002');
  4197. return false;
  4198. }
  4199. this.ec389 = true;
  4200. this.ec389a = addedCount;
  4201. this.ec389r = removedCount;
  4202.  
  4203. const pr00 = this.ec389pr;
  4204. const pr11 = this.ec389pr = this[fnKeyH](cTag, cId, pr00).catch(console.warn);
  4205.  
  4206. if (cTag === 'visibleItems') {
  4207. this.prDelay288 = pr11;
  4208. }
  4209. }
  4210.  
  4211. return true;
  4212. }
  4213.  
  4214.  
  4215. }
  4216.  
  4217.  
  4218. class RAFHub {
  4219. constructor() {
  4220. /** @type {number} */
  4221. this.startAt = 8170;
  4222. /** @type {number} */
  4223. this.counter = 0;
  4224. /** @type {number} */
  4225. this.rid = 0;
  4226. /** @type {Map<number, FrameRequestCallback>} */
  4227. this.funcs = new Map();
  4228. const funcs = this.funcs;
  4229. /** @type {FrameRequestCallback} */
  4230. this.bCallback = this.mCallback.bind(this);
  4231. this.pClear = () => funcs.clear();
  4232. this.keepRAF = false;
  4233. }
  4234. /** @param {DOMHighResTimeStamp} highResTime */
  4235. mCallback(highResTime) {
  4236. this.rid = 0;
  4237. Promise.resolve().then(this.pClear);
  4238. this.funcs.forEach(func => Promise.resolve(highResTime).then(func).catch(console.warn));
  4239. }
  4240. /** @param {FrameRequestCallback} f */
  4241. request(f) {
  4242. const cid = this.startAt + (this.counter = (this.counter & 1073741823) + 1);
  4243. this.funcs.set(cid, f);
  4244. if (this.rid === 0) this.rid = requestAnimationFrame(this.bCallback);
  4245. return cid;
  4246. }
  4247. /** @param {number} cid */
  4248. cancel(cid) {
  4249. cid = +cid;
  4250. if (cid > 0) {
  4251. if (cid <= this.startAt) {
  4252. return cancelAnimationFrame(cid);
  4253. }
  4254. if (this.rid > 0) {
  4255. this.funcs.delete(cid);
  4256. if (this.funcs.size === 0 && !this.keepRAF) {
  4257. cancelAnimationFrame(this.rid);
  4258. this.rid = 0;
  4259. }
  4260. }
  4261. }
  4262. }
  4263. }
  4264.  
  4265. function basePrefetching() {
  4266.  
  4267. new Promise(resolve => {
  4268.  
  4269. if (document.readyState !== 'loading') {
  4270. resolve();
  4271. } else {
  4272. win.addEventListener("DOMContentLoaded", resolve, false);
  4273. }
  4274.  
  4275. }).then(() => {
  4276. const hostL1 = [
  4277. 'https://www.youtube.com', 'https://googlevideo.com',
  4278. 'https://googleapis.com', 'https://accounts.youtube.com',
  4279. 'https://www.gstatic.com', 'https://ggpht.com',
  4280. 'https://yt3.ggpht.com', 'https://yt4.ggpht.com'
  4281. ];
  4282.  
  4283. const hostL2 = [
  4284. 'https://youtube.com',
  4285. 'https://fonts.googleapis.com', 'https://fonts.gstatic.com'
  4286. ];
  4287.  
  4288. let link = null;
  4289.  
  4290. function kn() {
  4291.  
  4292. link = document.createElement('link');
  4293. if (link.relList && link.relList.supports) {
  4294. kptPF = (link.relList.supports('dns-prefetch') ? 1 : 0) + (link.relList.supports('preconnect') ? 2 : 0) + (link.relList.supports('prefetch') ? 4 : 0) + (link.relList.supports('subresource') ? 8 : 0) + (link.relList.supports('preload') ? 16 : 0)
  4295. } else {
  4296. kptPF = 0;
  4297. }
  4298.  
  4299. groupCollapsed("YouTube Super Fast Chat", " | PREFETCH SUPPORTS");
  4300. if (ENABLE_BASE_PREFETCHING) console1.log('dns-prefetch', (kptPF & 1) ? 'OK' : 'NG');
  4301. if (ENABLE_BASE_PREFETCHING) console1.log('preconnect', (kptPF & 2) ? 'OK' : 'NG');
  4302. if (ENABLE_PRELOAD_THUMBNAIL) console1.log('prefetch', (kptPF & 4) ? 'OK' : 'NG');
  4303. if (ENABLE_PRELOAD_THUMBNAIL) console1.log('preload', (kptPF & 16) ? 'OK' : 'NG');
  4304. groupEnd();
  4305.  
  4306. }
  4307.  
  4308. for (const h of hostL1) {
  4309.  
  4310. if (kptPF === null) kn();
  4311. if (ENABLE_BASE_PREFETCHING) {
  4312. // if (kptPF & 1) {
  4313. // linker(link, 'dns-prefetch', h);
  4314. // link = null;
  4315. // }
  4316. if (kptPF & 2) {
  4317. linker(link, 'preconnect', h);
  4318. link = null;
  4319. }
  4320. }
  4321. }
  4322.  
  4323. for (const h of hostL2) {
  4324. if (kptPF === null) kn();
  4325. if (ENABLE_BASE_PREFETCHING) {
  4326. if (kptPF & 1) {
  4327. linker(link, 'dns-prefetch', h);
  4328. link = null;
  4329. }
  4330. }
  4331. }
  4332.  
  4333. })
  4334.  
  4335.  
  4336. }
  4337.  
  4338. if (DO_LINK_PREFETCH) basePrefetching();
  4339.  
  4340. const { notifyPath7081 } = (() => {
  4341. // DO_PARTICIPANT_LIST_HACKS
  4342.  
  4343. const mutexParticipants = new Mutex();
  4344.  
  4345. let uvid = 0;
  4346. let r95dm = 0;
  4347. let c95dm = -1;
  4348.  
  4349. const foundMap = (base, content) => {
  4350. /*
  4351. let lastSearch = 0;
  4352. let founds = base.map(baseEntry => {
  4353. let search = content.indexOf(baseEntry, lastSearch);
  4354. if (search < 0) return false;
  4355. lastSearch = search + 1;
  4356. return true;
  4357. });
  4358. return founds;
  4359. */
  4360. const contentSet = new Set(content);
  4361. const r = base.map(baseEntry => contentSet.has(baseEntry));
  4362. contentSet.clear();
  4363. return r
  4364.  
  4365. }
  4366.  
  4367.  
  4368.  
  4369. let participantsForSpliceWR = null;
  4370.  
  4371. class IndexSpliceEntry {
  4372. /**
  4373. *
  4374. * @param {number} _index
  4375. * @param {number} _addedCount
  4376. * @param {any[]} _removed
  4377. */
  4378. constructor(_index, _addedCount, _removed) {
  4379. this.index = _index;
  4380. this.addedCount = _addedCount;
  4381. this.removed = _removed;
  4382. }
  4383. get __proxy312__() {
  4384. return 1
  4385. }
  4386. get type() {
  4387. return 'splice'
  4388. }
  4389. get object() {
  4390. return kRef(participantsForSpliceWR); // avoid memory leakage
  4391. }
  4392. }
  4393.  
  4394. const spliceIndicesFunc = (beforeParticipants, participants, idsBefore, idsAfter) => {
  4395.  
  4396. let foundsForAfter = foundMap(idsAfter, idsBefore);
  4397. let foundsForBefore = foundMap(idsBefore, idsAfter);
  4398.  
  4399. const nAfter = foundsForAfter.length;
  4400. const nBefore = foundsForBefore.length;
  4401.  
  4402. const indexSplices = [];
  4403. const contentUpdates = [];
  4404. participantsForSpliceWR = null;
  4405. for (let i = 0, j = 0; i < nBefore || j < nAfter;) {
  4406. if (beforeParticipants[i] === participants[j]) {
  4407. i++; j++;
  4408. } else if (idsBefore[i] === idsAfter[j]) {
  4409. // content changed
  4410. contentUpdates.push({ indexI: i, indexJ: j })
  4411. i++; j++;
  4412. } else {
  4413. let addedCount = 0;
  4414. for (let q = j; q < nAfter; q++) {
  4415. if (foundsForAfter[q] === false) addedCount++;
  4416. else break;
  4417. }
  4418. let removedCount = 0;
  4419. for (let q = i; q < nBefore; q++) {
  4420. if (foundsForBefore[q] === false) removedCount++;
  4421. else break;
  4422. }
  4423. if (!addedCount && !removedCount) {
  4424. throw 'ERROR(0xFF32): spliceIndicesFunc';
  4425. }
  4426. const entry = new IndexSpliceEntry(
  4427. j,
  4428. addedCount,
  4429. removedCount >= 1 ? beforeParticipants.slice(i, i + removedCount) : []
  4430. );
  4431. indexSplices.push(entry);
  4432. i += removedCount;
  4433. j += addedCount;
  4434. }
  4435. }
  4436. foundsForBefore = null;
  4437. foundsForAfter = null;
  4438. idsBefore = null;
  4439. idsAfter = null;
  4440. beforeParticipants = null;
  4441. participantsForSpliceWR = indexSplices.length > 0 ? mWeakRef(participants) : null;
  4442. participants = null;
  4443. return { indexSplices, contentUpdates };
  4444.  
  4445. }
  4446.  
  4447. /*
  4448.  
  4449. customElements.get("yt-live-chat-participant-renderer").prototype.notifyPath=function(){ console.log(123); console.log(new Error().stack)}
  4450.  
  4451. VM63631:1 Error
  4452. at customElements.get.notifyPath (<anonymous>:1:122)
  4453. at e.forwardRendererStamperChanges_ (live_chat_polymer.js:4453:35)
  4454. at e.rendererStamperApplyChangeRecord_ (live_chat_polymer.js:4451:12)
  4455. at e.rendererStamperObserver_ (live_chat_polymer.js:4448:149)
  4456. at Object.pu [as fn] (live_chat_polymer.js:1692:118)
  4457. at ju (live_chat_polymer.js:1674:217)
  4458. at a._propertiesChanged (live_chat_polymer.js:1726:122)
  4459. at b._flushProperties (live_chat_polymer.js:1597:200)
  4460. at a._invalidateProperties (live_chat_polymer.js:1718:69)
  4461. at a.notifyPath (live_chat_polymer.js:1741:182)
  4462.  
  4463. */
  4464.  
  4465. function convertToIds(participants) {
  4466. return participants.map(participant => {
  4467. if (!participant || typeof participant !== 'object') {
  4468. console.warn('Error(0xFA41): convertToIds', participant);
  4469. return participant; // just in case
  4470. }
  4471. let keys = Object.keys(participant);
  4472. // liveChatTextMessageRenderer
  4473. // liveChatParticipantRenderer - livestream channel owner [no authorExternalChannelId]
  4474. // liveChatPaidMessageRenderer
  4475. /*
  4476.  
  4477. 'yt-live-chat-participant-renderer' utilizes the following:
  4478. authorName.simpleText: string
  4479. authorPhoto.thumbnails: Object{url:string, width:int, height:int} []
  4480. authorBadges[].liveChatAuthorBadgeRenderer.icon.iconType: string
  4481. authorBadges[].liveChatAuthorBadgeRenderer.tooltip: string
  4482. authorBadges[].liveChatAuthorBadgeRenderer.accessibility.accessibilityData: Object{label:string}
  4483.  
  4484. */
  4485. if (keys.length !== 1) {
  4486. console.warn('Error(0xFA42): convertToIds', participant);
  4487. return participant; // just in case
  4488. }
  4489. let key = keys[0];
  4490. let renderer = (participant[key] || 0);
  4491. let authorName = (renderer.authorName || 0);
  4492. let text = `${authorName.simpleText || authorName.text}`
  4493. let res = participant; // fallback if it is not a vaild entry
  4494. if (typeof text !== 'string') {
  4495. console.warn('Error(0xFA53): convertToIds', participant);
  4496. } else {
  4497. text = `${renderer.authorExternalChannelId || 'null'}|${text || ''}`;
  4498. if (text.length > 1) res = text;
  4499. }
  4500. return res;
  4501. // return renderer?`${renderer.id}|${renderer.authorExternalChannelId}`: '';
  4502. // note: renderer.id will be changed if the user typed something to trigger the update of the participants' record.
  4503. });
  4504. }
  4505.  
  4506. const checkChangeToParticipantRendererContent = CHECK_CHANGE_TO_PARTICIPANT_RENDERER_CONTENT ? (p1, p2) => {
  4507. // just update when content is changed.
  4508. if (p1.authorName !== p2.authorName) return true;
  4509. if (p1.authorPhoto !== p2.authorPhoto) return true;
  4510. if (p1.authorBadges !== p2.authorBadges) return true;
  4511. return false;
  4512. } : (p1, p2) => {
  4513. // keep integrity all the time.
  4514. return p1 !== p2; // always true
  4515. }
  4516.  
  4517. function notifyPath7081(path) { // cnt "yt-live-chat-participant-list-renderer"
  4518.  
  4519. if (PARTICIPANT_UPDATE_ONLY_ONLY_IF_MODIFICATION_DETECTED) {
  4520. if (path !== "participantsManager.participants") {
  4521. return this.__notifyPath5036__.apply(this, arguments);
  4522. }
  4523. if (c95dm === r95dm) return;
  4524. } else {
  4525. const stack = new Error().stack;
  4526. if (path !== "participantsManager.participants" || stack.indexOf('.onParticipantsChanged') < 0) {
  4527. return this.__notifyPath5036__.apply(this, arguments);
  4528. }
  4529. }
  4530.  
  4531. if (uvid > 1e8) uvid = uvid % 100;
  4532. let tid = ++uvid;
  4533.  
  4534.  
  4535. // const cnt = this; // "yt-live-chat-participant-list-renderer"
  4536.  
  4537. const wNode = mWeakRef(this);
  4538.  
  4539. mutexParticipants.lockWith(lockResolve => {
  4540.  
  4541. const cnt = kRef(wNode);
  4542.  
  4543. const participants00 = (((cnt || 0).participantsManager || 0).participants || 0);
  4544.  
  4545. if (tid !== uvid || !cnt || typeof (participants00 || 0).splice !== 'function') {
  4546. lockResolve();
  4547. return;
  4548. }
  4549.  
  4550. let doUpdate = false;
  4551.  
  4552. if (PARTICIPANT_UPDATE_ONLY_ONLY_IF_MODIFICATION_DETECTED) {
  4553.  
  4554. if (!participants00.r94dm) {
  4555. participants00.r94dm = 1;
  4556. r95dm = (r95dm & 1073741823) + 1;
  4557. participants00.push = function () {
  4558. r95dm = (r95dm & 1073741823) + 1;
  4559. return Array.prototype.push.apply(this, arguments);
  4560. }
  4561. participants00.pop = function () {
  4562. r95dm = (r95dm & 1073741823) + 1;
  4563. return Array.prototype.pop.apply(this, arguments);
  4564. }
  4565. participants00.shift = function () {
  4566. r95dm = (r95dm & 1073741823) + 1;
  4567. return Array.prototype.shift.apply(this, arguments);
  4568. }
  4569. participants00.unshift = function () {
  4570. r95dm = (r95dm & 1073741823) + 1;
  4571. return Array.prototype.unshift.apply(this, arguments);
  4572. }
  4573. participants00.splice = function () {
  4574. r95dm = (r95dm & 1073741823) + 1;
  4575. return Array.prototype.splice.apply(this, arguments);
  4576. }
  4577. participants00.sort = function () {
  4578. r95dm = (r95dm & 1073741823) + 1;
  4579. return Array.prototype.sort.apply(this, arguments);
  4580. }
  4581. participants00.reverse = function () {
  4582. r95dm = (r95dm & 1073741823) + 1;
  4583. return Array.prototype.reverse.apply(this, arguments);
  4584. }
  4585. }
  4586.  
  4587. if (c95dm !== r95dm) {
  4588. c95dm = r95dm;
  4589. doUpdate = true;
  4590. }
  4591.  
  4592. } else {
  4593. doUpdate = true;
  4594. }
  4595.  
  4596. if (!doUpdate) {
  4597. lockResolve();
  4598. return;
  4599. }
  4600.  
  4601. const participants = participants00.slice(0);
  4602. const beforeParticipants = beforeParticipantsMap.get(cnt) || [];
  4603. beforeParticipantsMap.set(cnt, participants);
  4604.  
  4605. const resPromise = (async () => {
  4606.  
  4607. if (beforeParticipants.length === 0) {
  4608. // not error
  4609. return 0;
  4610. }
  4611.  
  4612. let countOfElements = cnt.__getAllParticipantsDOMRenderedLength__()
  4613.  
  4614. // console.log(participants.length, doms.length) // different if no requestAnimationFrame
  4615. if (beforeParticipants.length !== countOfElements) {
  4616. // there is somewrong for the cache. - sometimes happen
  4617. return 0;
  4618. }
  4619.  
  4620. const idsBefore = convertToIds(beforeParticipants);
  4621. const idsAfter = convertToIds(participants);
  4622.  
  4623. let { indexSplices, contentUpdates } = spliceIndicesFunc(beforeParticipants, participants, idsBefore, idsAfter);
  4624.  
  4625. let res = 1; // default 1 for no update
  4626.  
  4627. if (indexSplices.length >= 1) {
  4628.  
  4629.  
  4630. // let p2 = participants.slice(indexSplices[0].index, indexSplices[0].index+indexSplices[0].addedCount);
  4631. // let p1 = indexSplices[0].removed;
  4632. // console.log(indexSplices.length, indexSplices ,p1,p2, convertToIds(p1),convertToIds(p2))
  4633.  
  4634. /* folllow
  4635. a.notifyPath(c + ".splices", d);
  4636. a.notifyPath(c + ".length", b.length);
  4637. */
  4638. // stampDomArraySplices_
  4639.  
  4640.  
  4641. await new Promise(resolve => {
  4642. cnt.resolveForDOMRendering781 = resolve;
  4643.  
  4644. cnt.__notifyPath5036__("participantsManager.participants.splices", {
  4645. indexSplices
  4646. });
  4647. indexSplices = null;
  4648. participantsForSpliceWR = null;
  4649. cnt.__notifyPath5036__("participantsManager.participants.length",
  4650. participants.length
  4651. );
  4652.  
  4653. });
  4654.  
  4655. // play safe for the change of 'length'
  4656. await nextBrowserTick_();
  4657.  
  4658. countOfElements = cnt.__getAllParticipantsDOMRenderedLength__();
  4659.  
  4660. const wrongSize = participants.length !== countOfElements
  4661. if (wrongSize) {
  4662. console.warn("ERROR(0xE2C3): notifyPath7081", beforeParticipants.length, participants.length, doms.length)
  4663. return 0;
  4664. }
  4665.  
  4666. res = 2 | 4;
  4667.  
  4668. } else {
  4669.  
  4670. indexSplices = null;
  4671. participantsForSpliceWR = null;
  4672.  
  4673. if (participants.length !== countOfElements) {
  4674. // other unhandled cases
  4675. return 0;
  4676. }
  4677.  
  4678. }
  4679.  
  4680. // participants.length === countOfElements before contentUpdates
  4681. if (contentUpdates.length >= 1) {
  4682. for (const contentUpdate of contentUpdates) {
  4683. let isChanged = checkChangeToParticipantRendererContent(beforeParticipants[contentUpdate.indexI], participants[contentUpdate.indexJ]);
  4684. if (isChanged) {
  4685. cnt.__notifyPath5036__(`participantsManager.participants[${contentUpdate.indexJ}]`);
  4686. res |= 4 | 8;
  4687. }
  4688. }
  4689. }
  4690. contentUpdates = null;
  4691.  
  4692. return res;
  4693.  
  4694.  
  4695. })();
  4696.  
  4697.  
  4698. resPromise.then(async (resValue) => {
  4699. const condition = resValue === 0 ? 1 : (resValue & 4) === 4 ? 2 : 0;
  4700. const isLogRequired = SHOW_PARTICIPANT_CHANGES_IN_CONSOLE && condition > 0;
  4701. isLogRequired && groupCollapsed("Participant List Change", `tid = ${tid}; res = ${resValue}`);
  4702. if (condition === 1) {
  4703. isLogRequired && console1.log("Full Refresh begins");
  4704. await new Promise(resolve => {
  4705. cnt.resolveForDOMRendering781 = resolve;
  4706. cnt.__notifyPath5036__("participantsManager.participants"); // full refresh
  4707. });
  4708. isLogRequired && console1.log("Full Refresh ends");
  4709. } else if (condition === 2) {
  4710. isLogRequired && console1.log(`Number of participants (before): ${beforeParticipants.length}`);
  4711. isLogRequired && console1.log(`Number of participants (after): ${participants.length}`);
  4712. isLogRequired && console1.log(`Total number of rendered participants: ${cnt.__getAllParticipantsDOMRenderedLength__()}`);
  4713. isLogRequired && console1.log(`Participant Renderer Content Updated: ${(resValue & 8) === 8}`);
  4714. // requestAnimationFrame is required to avoid particiant update during DOM changing (stampDomArraySplices_)
  4715. // mutex lock with requestAnimationFrame can also disable participants update in background
  4716. }
  4717. isLogRequired && groupEnd();
  4718. (condition === 2) && (await new Promise(requestAnimationFrame));
  4719. lockResolve();
  4720. });
  4721.  
  4722. });
  4723.  
  4724. }
  4725.  
  4726. return { notifyPath7081 };
  4727.  
  4728. })();
  4729.  
  4730. const whenDefinedMultiple = async (tags) => {
  4731.  
  4732. const sTags = [...new Set(tags)];
  4733. const len = sTags.length;
  4734.  
  4735. const pTags = new Array(len);
  4736. for (let i = 0; i < len; i++) {
  4737. pTags[i] = customElements.whenDefined(sTags[i]);
  4738. }
  4739.  
  4740. await Promise.all(pTags);
  4741. pTags.length = 0;
  4742.  
  4743. return sTags;
  4744.  
  4745. }
  4746.  
  4747. const onRegistryReadyForDataManipulation = () => {
  4748.  
  4749. function dummy5035(a, b, c) { }
  4750. function dummy411(a, b, c) { }
  4751.  
  4752.  
  4753.  
  4754. customElements.whenDefined("yt-live-chat-participant-list-renderer").then(() => {
  4755.  
  4756. if (!DO_PARTICIPANT_LIST_HACKS) return;
  4757.  
  4758. const tag = "yt-live-chat-participant-list-renderer";
  4759. const cProto = getProto(document.createElement(tag));
  4760. if (!cProto || typeof cProto.attached !== 'function') {
  4761. // for _registered, proto.attached shall exist when the element is defined.
  4762. // for controller extraction, attached shall exist when instance creates.
  4763. console.warn(`proto.attached for ${tag} is unavailable.`);
  4764. return;
  4765. }
  4766.  
  4767.  
  4768. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-participant-list-renderer hacks");
  4769.  
  4770. const fgsArr = ['kevlar_tuner_should_test_maintain_stable_list', 'kevlar_should_maintain_stable_list', 'kevlar_tuner_should_test_reuse_components', 'kevlar_tuner_should_reuse_components'];
  4771. const fgs = {};
  4772. for (const key of fgsArr) fgs[key] = undefined;
  4773.  
  4774. try {
  4775. const EXPERIMENT_FLAGS = ytcfg.data_.EXPERIMENT_FLAGS;
  4776. for (const key of fgsArr) fgs[key] = EXPERIMENT_FLAGS[key];
  4777. } catch (e) { }
  4778. console1.log(`EXPERIMENT_FLAGS: ${JSON.stringify(fgs, null, 2)}`);
  4779.  
  4780. const canDoReplacement = (() => {
  4781. if (typeof cProto.__notifyPath5035__ === 'function' && cProto.__notifyPath5035__.name !== 'dummy5035') {
  4782. console.warn('YouTube Live Chat Tamer is running.');
  4783. return;
  4784. }
  4785.  
  4786. if (typeof cProto.__attached411__ === 'function' && cProto.__attached411__.name !== 'dummy411') {
  4787. console.warn('YouTube Live Chat Tamer is running.');
  4788. return;
  4789. }
  4790.  
  4791. cProto.__notifyPath5035__ = dummy5035 // just to against Live Chat Tamer
  4792. cProto.__attached411__ = dummy411 // just to against Live Chat Tamer
  4793.  
  4794. if (typeof cProto.flushRenderStamperComponentBindings_ !== 'function' || cProto.flushRenderStamperComponentBindings_.length !== 0) {
  4795. console.warn("ERROR(0xE355): cProto.flushRenderStamperComponentBindings_ not found");
  4796. return;
  4797. }
  4798.  
  4799. if (typeof cProto.flushRenderStamperComponentBindings66_ === 'function') {
  4800. console.warn("ERROR(0xE356): cProto.flushRenderStamperComponentBindings66_");
  4801. return;
  4802. }
  4803.  
  4804. if (typeof cProto.__getAllParticipantsDOMRenderedLength__ === 'function') {
  4805. console.warn("ERROR(0xE357): cProto.__getAllParticipantsDOMRenderedLength__");
  4806. return;
  4807. }
  4808. return true;
  4809. })();
  4810.  
  4811. console1.log(`Data Manipulation Boost = ${canDoReplacement}`);
  4812.  
  4813. assertor(() => fnIntegrity(cProto.attached, '0.32.22')) // just warning
  4814. if (typeof cProto.flushRenderStamperComponentBindings_ === 'function') {
  4815. const fiRSCB = fnIntegrity(cProto.flushRenderStamperComponentBindings_);
  4816. console1.log(`flushRenderStamperComponentBindings_ ### ${fiRSCB} ###`);
  4817. } else {
  4818. console1.log("flushRenderStamperComponentBindings_ - not found");
  4819. }
  4820. // assertor(() => fnIntegrity(cProto.flushRenderStamperComponentBindings_, '0.386.233')) // just warning
  4821.  
  4822. if (typeof cProto.flushRenderStamperComponentBindings_ === 'function') {
  4823. cProto.flushRenderStamperComponentBindings66_ = cProto.flushRenderStamperComponentBindings_;
  4824. cProto.flushRenderStamperComponentBindings_ = function () {
  4825. // console.log('flushRenderStamperComponentBindings_')
  4826. this.flushRenderStamperComponentBindings66_();
  4827. if (this.resolveForDOMRendering781) {
  4828. this.resolveForDOMRendering781();
  4829. this.resolveForDOMRendering781 = null;
  4830. }
  4831. };
  4832. }
  4833.  
  4834. cProto.__getAllParticipantsDOMRenderedLength__ = function () {
  4835. const container = ((this || 0).$ || 0).participants;
  4836. if (!container) return 0;
  4837. return HTMLElement_.prototype.querySelectorAll.call(container, 'yt-live-chat-participant-renderer').length;
  4838. }
  4839.  
  4840. const onPageElements = [...document.querySelectorAll('yt-live-chat-participant-list-renderer:not(.n9fJ3)')];
  4841.  
  4842. cProto.__attached412__ = cProto.attached;
  4843. const fpPList = function (hostElement) {
  4844. const cnt = insp(hostElement);
  4845. if (beforeParticipantsMap.has(cnt)) return;
  4846. hostElement.classList.add('n9fJ3');
  4847.  
  4848. assertor(() => (cnt.__dataEnabled === true && cnt.__dataReady === true));
  4849. if (typeof cnt.notifyPath !== 'function' || typeof cnt.__notifyPath5036__ !== 'undefined') {
  4850. console.warn("ERROR(0xE318): yt-live-chat-participant-list-renderer")
  4851. return;
  4852. }
  4853.  
  4854. groupCollapsed("Participant List attached", "");
  4855. cnt.__notifyPath5036__ = cnt.notifyPath
  4856. const participants = ((cnt.participantsManager || 0).participants || 0);
  4857. assertor(() => (participants.length > -1 && typeof participants.slice === 'function'));
  4858. console1.log(`initial number of participants: ${participants.length}`);
  4859. const newParticipants = (participants.length >= 1 && typeof participants.slice === 'function') ? participants.slice(0) : [];
  4860. beforeParticipantsMap.set(cnt, newParticipants);
  4861. cnt.notifyPath = notifyPath7081;
  4862. console1.log(`CHECK_CHANGE_TO_PARTICIPANT_RENDERER_CONTENT = ${CHECK_CHANGE_TO_PARTICIPANT_RENDERER_CONTENT}`);
  4863. groupEnd();
  4864. }
  4865. cProto.attached = function () {
  4866. fpPList(this.hostElement || this);
  4867. this.__attached412__.apply(this, arguments);
  4868. };
  4869.  
  4870.  
  4871. if (ENABLE_FLAGS_MAINTAIN_STABLE_LIST_FOR_PARTICIPANTS_LIST) {
  4872.  
  4873. /** @type {boolean | (()=>boolean)} */
  4874. let toUseMaintainStableList = USE_MAINTAIN_STABLE_LIST_ONLY_WHEN_KS_FLAG_IS_SET ? (() => ytcfg.data_.EXPERIMENT_FLAGS.kevlar_should_maintain_stable_list === true) : true;
  4875. if (typeof cProto.stampDomArray_ === 'function' && cProto.stampDomArray_.length === 6 && !cProto.stampDomArray_.nIegT && !cProto.stampDomArray66_) {
  4876.  
  4877. let lastMessageDate = 0;
  4878. cProto.stampDomArray66_ = cProto.stampDomArray_;
  4879.  
  4880. cProto.stampDomArray_ = function (...args) {
  4881. if (args[0] && args[0].length > 0 && args[1] === "participants" && args[2] && args[3] === true && !args[5]) {
  4882. if (typeof toUseMaintainStableList === 'function') {
  4883. toUseMaintainStableList = toUseMaintainStableList();
  4884. }
  4885. args[5] = toUseMaintainStableList;
  4886. let currentDate = Date.now();
  4887. if (currentDate - lastMessageDate > 440) {
  4888. lastMessageDate = currentDate;
  4889. console.log('maintain_stable_list for participants list', toUseMaintainStableList);
  4890. }
  4891. }
  4892. return this.stampDomArray66_.apply(this, args);
  4893. }
  4894.  
  4895. cProto.stampDomArray_.nIegT = 1;
  4896.  
  4897. }
  4898. console1.log(`ENABLE_FLAGS_MAINTAIN_STABLE_LIST_FOR_PARTICIPANTS_LIST - OK`);
  4899. } else {
  4900. console1.log(`ENABLE_FLAGS_MAINTAIN_STABLE_LIST_FOR_PARTICIPANTS_LIST - NG`);
  4901. }
  4902.  
  4903. groupEnd();
  4904.  
  4905. if (onPageElements.length >= 1) {
  4906. for (const s of onPageElements) {
  4907. if (insp(s).isAttached === true) {
  4908. fpPList(s);
  4909. }
  4910. }
  4911. }
  4912.  
  4913. }).catch(console.warn);
  4914.  
  4915. };
  4916.  
  4917. if (DO_PARTICIPANT_LIST_HACKS) {
  4918. promiseForCustomYtElementsReady.then(onRegistryReadyForDataManipulation);
  4919. }
  4920.  
  4921.  
  4922.  
  4923. const rafHub = (ENABLE_RAF_HACK_TICKERS || ENABLE_RAF_HACK_DOCKED_MESSAGE || ENABLE_RAF_HACK_INPUT_RENDERER || ENABLE_RAF_HACK_EMOJI_PICKER) ? new RAFHub() : null;
  4924.  
  4925. const transitionEndHooks = new WeakSet();
  4926. const transitionEndAfterFnSimple = new WeakMap();
  4927. let transitionEndAfterFnSimpleEnable = 0;
  4928. // let prevTransitionClosing = null;
  4929.  
  4930. const passiveCapture = typeof IntersectionObserver === 'function' ? { capture: true, passive: true } : true;
  4931.  
  4932.  
  4933. const transitionEndAfterFn = (evt) => {
  4934. if (transitionEndAfterFnSimpleEnable > 0 && evt.propertyName && !evt.pseudoElement) {
  4935. const elm = evt.target;
  4936. const f = transitionEndAfterFnSimple.get(elm);
  4937. if (f) {
  4938. transitionEndAfterFnSimple.delete(elm);
  4939. f.resolve(evt.propertyName);
  4940. }
  4941. }
  4942. };
  4943.  
  4944. const fixChildrenIssue = !!fixChildrenIssue801;
  4945. if (fixChildrenIssue && typeof Object.getOwnPropertyDescriptor === 'function' && typeof Proxy !== 'undefined') {
  4946. let fixChildrenIssue_status = false;
  4947. const divProto = HTMLDivElement.prototype;
  4948. const polymerControllerSetData3 = function (c, d, e) {
  4949. return insp(this).set(c, d, e);
  4950. }
  4951. const polymerControllerSetData2 = function (c, d) {
  4952. return insp(this).set(c, d);
  4953. }
  4954. const dummyFn = function () {
  4955. console.log('dummyFn', ...arguments);
  4956. };
  4957.  
  4958. const wm44 = new Map();
  4959. function unPolymerSet(elem) {
  4960. const is = elem.is;
  4961. if (is && !elem.set) {
  4962. let rt = wm44.get(is);
  4963. if (!rt) {
  4964. rt = 1;
  4965. const cnt = insp(elem);
  4966. if (cnt !== elem && cnt && typeof cnt.set === 'function') {
  4967. const pcSet = cnt.constructor.prototype.set;
  4968. if (pcSet && typeof pcSet === 'function' && pcSet.length === 3) {
  4969. rt = polymerControllerSetData3;
  4970. } else if (pcSet && typeof pcSet === 'function' && pcSet.length === 2) {
  4971. rt = polymerControllerSetData2;
  4972. }
  4973. }
  4974. wm44.set(is, rt);
  4975. }
  4976. if (typeof rt === 'function') {
  4977. elem.set = rt;
  4978. } else {
  4979. elem.set = dummyFn;
  4980. }
  4981. }
  4982. }
  4983. if (!divProto.__children577__ && !divProto.__children578__) {
  4984.  
  4985. const dp = Object.getOwnPropertyDescriptor(Element.prototype, 'children');
  4986. const dp2 = Object.getOwnPropertyDescriptor(HTMLElement_.prototype, 'children');
  4987. const dp3 = Object.getOwnPropertyDescriptor(divProto, 'children');
  4988.  
  4989. if (dp && dp.configurable === true && dp.enumerable === true && typeof dp.get === 'function' && !dp2 && !dp3) {
  4990.  
  4991. if (divProto instanceof HTMLElement_ && divProto instanceof Element) {
  4992.  
  4993. let m = Object.assign({}, dp);
  4994. divProto.__children577__ = dp.get;
  4995. divProto.__children578__ = function () {
  4996. if (this.__children803__) return this.__children803__;
  4997. if (this.__children801__) {
  4998. let arr = [];
  4999. for (let elem = this.firstElementChild; elem !== null; elem = elem.nextElementSibling) {
  5000. if (elem.is) {
  5001. unPolymerSet(elem);
  5002. arr.push(elem);
  5003. }
  5004. }
  5005. if (this.__children801__ === 2) this.__children803__ = arr;
  5006. return arr;
  5007. }
  5008. return 577;
  5009. };
  5010. m.get = function () {
  5011. const r = this.__children578__();
  5012. if (r !== 577) return r;
  5013. return this.__children577__();
  5014. };
  5015. Object.defineProperty(divProto, 'children', m);
  5016.  
  5017. fixChildrenIssue_status = true;
  5018.  
  5019. }
  5020. }
  5021.  
  5022. }
  5023.  
  5024. if (!fixChildrenIssue_status) {
  5025. console.log('fixChildrenIssue - set NG')
  5026. }
  5027.  
  5028.  
  5029. }
  5030.  
  5031.  
  5032. const watchUserCSS = () => {
  5033.  
  5034. // if (!CSS.supports('contain-intrinsic-size', 'auto var(--wsr94)')) return;
  5035.  
  5036. const getElemFromWR = (nr) => {
  5037. const n = kRef(nr);
  5038. if (n && n.isConnected) return n;
  5039. return null;
  5040. }
  5041.  
  5042. const clearContentVisibilitySizing = () => {
  5043. Promise.resolve().then(() => {
  5044.  
  5045. const e = document.querySelector('#show-more[disabled]');
  5046. let btnShowMoreWR = e ? mWeakRef(e) : null;
  5047.  
  5048. let lastVisibleItemWR = null;
  5049. for (const elm of document.querySelectorAll('[wsr93]')) {
  5050. if (elm.getAttribute('wsr93') === 'visible') lastVisibleItemWR = mWeakRef(elm);
  5051. elm.setAttribute('wsr93', '');
  5052. // custom CSS property --wsr94 not working when attribute wsr93 removed
  5053. }
  5054. foregroundPromiseFn().then(() => {
  5055. const btnShowMore = getElemFromWR(btnShowMoreWR); btnShowMoreWR = null;
  5056. if (btnShowMore) btnShowMore.click();
  5057. else {
  5058. // would not work if switch it frequently
  5059. const lastVisibleItem = getElemFromWR(lastVisibleItemWR); lastVisibleItemWR = null;
  5060. if (lastVisibleItem) {
  5061.  
  5062. Promise.resolve()
  5063. .then(() => lastVisibleItem.scrollIntoView())
  5064. .then(() => lastVisibleItem.scrollIntoView(false))
  5065. .then(() => lastVisibleItem.scrollIntoView({ behavior: "instant", block: "end", inline: "nearest" }))
  5066. .catch(e => { }) // break the chain when method not callable
  5067.  
  5068. }
  5069. }
  5070. });
  5071.  
  5072. }).catch(console.warn);
  5073.  
  5074. }
  5075.  
  5076. const mutObserver = new MutationObserver((mutations) => {
  5077. for (const mutation of mutations) {
  5078. if ((mutation.addedNodes || 0).length >= 1) {
  5079. for (const addedNode of mutation.addedNodes) {
  5080. if (addedNode.nodeName === 'STYLE') {
  5081. clearContentVisibilitySizing();
  5082. return;
  5083. }
  5084. }
  5085. }
  5086. if ((mutation.removedNodes || 0).length >= 1) {
  5087. for (const removedNode of mutation.removedNodes) {
  5088. if (removedNode.nodeName === 'STYLE') {
  5089. clearContentVisibilitySizing();
  5090. return;
  5091. }
  5092. }
  5093. }
  5094. }
  5095. });
  5096.  
  5097. mutObserver.observe(document.documentElement, {
  5098. childList: true,
  5099. subtree: false
  5100. });
  5101. mutObserver.observe(document.head, {
  5102. childList: true,
  5103. subtree: false
  5104. });
  5105. mutObserver.observe(document.body, {
  5106. childList: true,
  5107. subtree: false
  5108. });
  5109.  
  5110. }
  5111.  
  5112.  
  5113. const { lcRendererElm, visObserver } = (() => {
  5114.  
  5115. let lcRendererWR = null;
  5116.  
  5117. const lcRendererElm = () => {
  5118. let lcRenderer = kRef(lcRendererWR);
  5119. if (!lcRenderer || !lcRenderer.isConnected) {
  5120. lcRenderer = document.querySelector('yt-live-chat-item-list-renderer.yt-live-chat-renderer');
  5121. lcRendererWR = lcRenderer ? mWeakRef(lcRenderer) : null;
  5122. }
  5123. return lcRenderer;
  5124. };
  5125.  
  5126.  
  5127. let hasFirstShowMore = false;
  5128. // let lastVisible = null;
  5129.  
  5130. const visObserverFn = (entry) => {
  5131.  
  5132. const target = entry.target;
  5133. if (!target || !target.hasAttribute('wsr93')) return;
  5134. // if(target.classList.contains('dont-render')) return;
  5135. let isVisible = entry.isIntersecting === true && entry.intersectionRatio > 0.5;
  5136. // const h = entry.boundingClientRect.height;
  5137. /*
  5138. if (h < 16) { // wrong: 8 (padding/margin); standard: 32; test: 16 or 20
  5139. // e.g. under fullscreen. the element created but not rendered.
  5140. target.setAttribute('wsr93', '');
  5141. return;
  5142. }
  5143. */
  5144. if (isVisible) {
  5145. // target.style.setProperty('--wsr94', h + 'px');
  5146. target.setAttribute('wsr93', 'visible');
  5147. // lastVisible = mWeakRef(target);
  5148. if (nNextElem(target) === null) {
  5149.  
  5150. // firstVisibleItemDetected = true;
  5151. /*
  5152. if (dateNow() - lastScroll < 80) {
  5153. lastLShow = 0;
  5154. lastScroll = 0;
  5155. Promise.resolve().then(clickShowMore);
  5156. } else {
  5157. lastLShow = dateNow();
  5158. }
  5159. */
  5160. // lastLShow = dateNow();
  5161. } else if (!hasFirstShowMore) { // should more than one item being visible
  5162. // implement inside visObserver to ensure there is sufficient delay
  5163. hasFirstShowMore = true;
  5164. // foregroundPromiseFn().then(() => {
  5165. // // foreground page
  5166. // // page visibly ready -> load the latest comments at initial loading
  5167. // const lcRenderer = lcRendererElm();
  5168. // if (lcRenderer) {
  5169. // nextBrowserTick_(() => {
  5170. // const cnt = insp(lcRenderer);
  5171. // if (cnt.isAttached === false || (cnt.hostElement || cnt).isConnected === false) return;
  5172. // cnt.scrollToBottom_();
  5173. // });
  5174. // }
  5175. // });
  5176. }
  5177. }
  5178. else if (target.getAttribute('wsr93') === 'visible') { // ignore target.getAttribute('wsr93') === '' to avoid wrong sizing
  5179.  
  5180. // target.style.setProperty('--wsr94', h + 'px');
  5181. target.setAttribute('wsr93', 'hidden');
  5182. } // note: might consider 0 < entry.intersectionRatio < 0.5 and target.getAttribute('wsr93') === '' <new last item>
  5183.  
  5184. }
  5185.  
  5186.  
  5187.  
  5188. const visObserver = new IntersectionObserver((entries) => {
  5189.  
  5190. for (const entry of entries) {
  5191.  
  5192. Promise.resolve(entry).then(visObserverFn);
  5193.  
  5194. }
  5195.  
  5196. }, {
  5197. rootMargin: "0px",
  5198. threshold: [0.05, 0.95],
  5199. });
  5200.  
  5201.  
  5202. return { lcRendererElm, visObserver }
  5203.  
  5204.  
  5205. })();
  5206.  
  5207. // let itemsResizeObserverAttached = false;
  5208. // const resizeObserverFallback = new IntersectionObserver((mutation, observer) => {
  5209. // const itemScroller = mutation[0].target;
  5210. // observer.unobserve(itemScroller);
  5211. // if (itemScroller.scrollTop === 0) itemScroller.scrollTop = window.screen.height; // scrollTop changing
  5212. // });
  5213.  
  5214. const itemScrollerResizeObserver = typeof ResizeObserver === 'function' && ENABLE_OVERFLOW_ANCHOR ? new ResizeObserver((mutations) => {
  5215. const mutation = mutations[mutations.length - 1];
  5216. // console.log('resizeObserver', mutation)
  5217. const itemScroller = (mutation || 0).target;
  5218. if (!itemScroller) return;
  5219. const listDom = itemScroller.closest('yt-live-chat-item-list-renderer');
  5220. if (!listDom) return;
  5221. const listCnt = insp(listDom);
  5222. if(listCnt.visibleItems.length === 0) return;
  5223. if (listCnt.atBottom !== true) return;
  5224. // if (itemScroller.scrollTop === 0) {
  5225. itemScroller.scrollTop = 16777216; // scrollTop changing
  5226. // }
  5227. }) : null;
  5228.  
  5229. const { setupMutObserver } = (() => {
  5230.  
  5231.  
  5232. const mutFn = (items) => {
  5233. let seqIndex = -1;
  5234. const elementSet = new Set();
  5235. elementSet.add = elementSet.addOriginal || elementSet.add;
  5236. for (let node = nLastElem(items); node !== null; node = nPrevElem(node)) { // from bottom
  5237. let found = node.hasAttribute('wsr93') ? (node.hasAttribute('yt-chat-item-seq') ? 2 : 1) : 0;
  5238. if (found === 1) node.removeAttribute('wsr93'); // reuse -> wsr93: hidden after re-attach
  5239. if (found === 2) {
  5240. seqIndex = parseInt(node.getAttribute('yt-chat-item-seq'), 10);
  5241. break;
  5242. }
  5243. visObserver.unobserve(node); // reuse case
  5244. node.setAttribute('wsr93', '');
  5245. visObserver.observe(node);
  5246. elementSet.add(node);
  5247. }
  5248. let iter = elementSet.values();
  5249. let i = seqIndex + elementSet.size;
  5250. for (let curr; curr = iter.next().value;) { // from bottom
  5251. curr.setAttribute('yt-chat-item-seq', i % 60);
  5252. curr.classList.add('yt-chat-item-' + ((i % 2) ? 'odd' : 'even'));
  5253. i--;
  5254. }
  5255. iter = null;
  5256. elementSet.clear();
  5257. }
  5258.  
  5259. // const itemsResizeObserver = typeof ResizeObserver === 'function' && 0 ? new ResizeObserver((mutations) => {
  5260. // const mutation = mutations[mutations.length - 1];
  5261. // // console.log('resizeObserver', mutation)
  5262. // const items = (mutation || 0).target;
  5263. // if (!items) return;
  5264. // const listDom = items.closest('yt-live-chat-item-list-renderer');
  5265. // if (!listDom) return;
  5266. // const listCnt = insp(listDom);
  5267. // if (listCnt.atBottom !== true) return;
  5268. // const itemScroller = listCnt.itemScroller || listCnt.$['item-scroller'] || listCnt.querySelector('#item-scroller') || 0;
  5269. // // if (itemScroller.scrollTop === 0) {
  5270. // itemScroller.scrollTop = mutation.contentRect.height; // scrollTop changing
  5271. // // }
  5272. // }) : null;
  5273. // itemsResizeObserverAttached = itemsResizeObserver !== null;
  5274.  
  5275. const mutObserver = new MutationObserver((mutations) => {
  5276. const items = (mutations[0] || 0).target;
  5277. if (!items) return;
  5278. mutFn(items);
  5279. });
  5280.  
  5281. const setupMutObserver = (items) => {
  5282. scrollChatFn = null;
  5283. mutObserver.disconnect();
  5284. mutObserver.takeRecords();
  5285. if (items) {
  5286. if (typeof items.__appendChild932__ === 'function') {
  5287. if (typeof items.appendChild === 'function') items.appendChild = items.__appendChild932__;
  5288. if (typeof items.__shady_native_appendChild === 'function') items.__shady_native_appendChild = items.__appendChild932__;
  5289. }
  5290. mutObserver.observe(items, {
  5291. childList: true,
  5292. subtree: false
  5293. });
  5294. mutFn(items);
  5295.  
  5296.  
  5297. // if (itemsResizeObserver) itemsResizeObserver.observe(items);
  5298.  
  5299. // const isFirstList = firstList;
  5300. // firstList = false;
  5301.  
  5302.  
  5303. if (items && items.nextElementSibling === null) {
  5304. items.parentNode.appendChild(dr(document.createElement('item-anchor')));
  5305. WITH_SCROLL_ANCHOR = true;
  5306. if (ENABLE_OVERFLOW_ANCHOR) {
  5307. items.classList.add('no-anchor');
  5308. nodeParent(items).classList.add('no-anchor'); // required
  5309. }
  5310. }
  5311.  
  5312.  
  5313.  
  5314.  
  5315. if (ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX) {
  5316.  
  5317. (() => {
  5318.  
  5319. const tag = 'yt-iframed-player-events-relay'
  5320. const dummy = document.createElement(tag);
  5321.  
  5322. const cProto = getProto(dummy);
  5323. if (!cProto || !cProto.handlePostMessage_) {
  5324. console.warn(`proto.handlePostMessage_ for ${tag} is unavailable.`);
  5325. return;
  5326. }
  5327.  
  5328. if (typeof cProto.handlePostMessage_ === 'function' && !cProto.handlePostMessage66_ && !cProto.handlePostMessage67_ ) {
  5329.  
  5330. cProto.handlePostMessage66_ = cProto.handlePostMessage_;
  5331.  
  5332. const handlePostMessageAfterPromiseA = (da) => {
  5333.  
  5334. if (!da || typeof da !== 'object') return;
  5335.  
  5336. if ('yt-player-state-change' in da) {
  5337.  
  5338. const qc = da['yt-player-state-change'];
  5339.  
  5340.  
  5341. let isQcChanged = false;
  5342.  
  5343. if (qc === 2) { isQcChanged = qc !== _playerState; _playerState = 2; relayCount = 0; } // paused
  5344. else if (qc === 3) { isQcChanged = qc !== _playerState; _playerState = 3; } // playing
  5345. else if (qc === 1) { isQcChanged = qc !== _playerState; _playerState = 1; } // playing
  5346.  
  5347.  
  5348. if ((isQcChanged) && playerState !== _playerState) {
  5349. playerEventsByIframeRelay = true;
  5350. onPlayStateChangePromise = new Promise((resolve) => {
  5351. const k = _playerState;
  5352. foregroundPromiseFn().then(() => {
  5353. if (k === _playerState && playerState !== _playerState) playerState = _playerState;
  5354. onPlayStateChangePromise = null;
  5355. resolve();
  5356. })
  5357. }).catch(console.warn);
  5358.  
  5359. }
  5360.  
  5361. } else if ('yt-player-video-progress' in da) {
  5362. const vp = da['yt-player-video-progress'];
  5363.  
  5364.  
  5365. relayCount++;
  5366. lastPlayerProgress = vp > 0 ? vp : 0; // no use ?
  5367.  
  5368.  
  5369. if (relayPromise && vp > 0 && relayCount >= 2) {
  5370. if (onPlayStateChangePromise) {
  5371. onPlayStateChangePromise.then(() => {
  5372. relayPromise && relayPromise.resolve();
  5373. relayPromise = null;
  5374. })
  5375. } else {
  5376. relayPromise.resolve();
  5377. relayPromise = null;
  5378. }
  5379. }
  5380.  
  5381. }
  5382.  
  5383. };
  5384.  
  5385. cProto.handlePostMessage67_ = function (a) {
  5386.  
  5387. let da = a.data;
  5388. const wNode = mWeakRef(this);
  5389. // const wData = mWeakRef(da);
  5390.  
  5391. playEventsStack = playEventsStack.then(() => {
  5392.  
  5393. const cnt = kRef(wNode);
  5394. // const da = kRef(wData);
  5395.  
  5396. if (!cnt || !a || !da) return;
  5397. handlePostMessageAfterPromiseA(da);
  5398. da = null;
  5399.  
  5400. const r = cnt.handlePostMessage66_(a);
  5401. a = null;
  5402.  
  5403. }).catch(console.warn);
  5404.  
  5405. }
  5406.  
  5407. const handlePostMessageAfterPromiseB = (da) => {
  5408.  
  5409. const lcr = document.querySelector('yt-live-chat-renderer');
  5410. const psc = document.querySelector("yt-player-seek-continuation");
  5411. if (lcr && psc && lcr.replayBuffer_) {
  5412.  
  5413. const rbProgress = lcr.replayBuffer_.lastVideoOffsetTimeMsec;
  5414. const daProgress = da['yt-player-video-progress'] * 1000
  5415. // document.querySelector('yt-live-chat-renderer').playerProgressChanged_(1e-5);
  5416.  
  5417. const front_ = (lcr.replayBuffer_.replayQueue || 0).front_;
  5418. const back_ = (lcr.replayBuffer_.replayQueue || 0).back_;
  5419.  
  5420. // console.log(deepCopy( front_))
  5421. // console.log(deepCopy( back_))
  5422. // console.log(rbProgress, daProgress, )
  5423. if (front_ && back_ && rbProgress > daProgress && back_.length > 2 && back_.some(e => e && +e.videoOffsetTimeMsec > daProgress) && back_.some(e => e && +e.videoOffsetTimeMsec < daProgress)) {
  5424. // no action
  5425. // console.log('ss1')
  5426. } else if (rbProgress < daProgress + 3400 && rbProgress > daProgress - 1200) {
  5427. // daProgress - 1200 < rbProgress < daProgress + 3400
  5428. // console.log('ss2')
  5429. } else {
  5430.  
  5431. lcr.previousProgressSec = 1E-5;
  5432. // lcr._setIsSeeking(!0),
  5433. lcr.replayBuffer_.clear()
  5434. psc.fireSeekContinuation_(da['yt-player-video-progress']);
  5435. }
  5436.  
  5437. }
  5438.  
  5439.  
  5440. };
  5441.  
  5442. cProto.handlePostMessage_ = function (a) {
  5443.  
  5444. let da = (a || 0).data || 0;
  5445. const wNode = mWeakRef(this);
  5446.  
  5447. if (typeof da !== 'object') return;
  5448.  
  5449. if (waitForInitialDataCompletion === 1) return;
  5450.  
  5451. if (!isPlayProgressTriggered) {
  5452. isPlayProgressTriggered = true; // set once
  5453.  
  5454. if ('yt-player-video-progress' in da) {
  5455. waitForInitialDataCompletion = 1;
  5456.  
  5457. const wrapWith = (data) => {
  5458. const { origin } = a;
  5459. return {
  5460. origin,
  5461. data
  5462. };
  5463. }
  5464.  
  5465. this.handlePostMessage67_(wrapWith({
  5466. "yt-iframed-parent-ready": true
  5467. }));
  5468.  
  5469.  
  5470. playEventsStack = playEventsStack.then(() => {
  5471.  
  5472. const cnt = kRef(wNode);
  5473.  
  5474. if (!cnt || !a || !da) return;
  5475.  
  5476. handlePostMessageAfterPromiseB(da);
  5477. da = null;
  5478.  
  5479. waitForInitialDataCompletion = 2;
  5480.  
  5481. const r = cnt.handlePostMessage_(a); // isPlayProgressTriggered is set
  5482. a = null;
  5483.  
  5484. }).catch(console.warn);
  5485.  
  5486. return;
  5487.  
  5488. }
  5489.  
  5490. }
  5491.  
  5492. this.handlePostMessage67_(a);
  5493.  
  5494. }
  5495.  
  5496. }
  5497.  
  5498.  
  5499. })();
  5500.  
  5501. }
  5502.  
  5503.  
  5504. }
  5505. }
  5506.  
  5507. return { setupMutObserver };
  5508.  
  5509.  
  5510.  
  5511. })();
  5512.  
  5513. const setupEvents = () => {
  5514. // not called when boost chat is enabled
  5515.  
  5516. // global - currentMouseDown, lastUserInteraction
  5517.  
  5518. let scrollCount = 0;
  5519. let lastScrollCount = -1;
  5520. let lastMouseDown = 0;
  5521.  
  5522. const passiveCapture = typeof IntersectionObserver === 'function' ? { capture: true, passive: true } : true;
  5523.  
  5524. // const delayFlushActiveItemsAfterUserActionK_ = () => {
  5525.  
  5526. // const lcRenderer = lcRendererElm();
  5527. // if (lcRenderer) {
  5528. // const cnt = insp(lcRenderer);
  5529. // if (!cnt.hasUserJustInteracted11_) return;
  5530. // if (cnt.atBottom && cnt.allowScroll && cnt.activeItems_.length >= 1 && cnt.hasUserJustInteracted11_()) {
  5531. // cnt.delayFlushActiveItemsAfterUserAction11_ && cnt.delayFlushActiveItemsAfterUserAction11_();
  5532. // }
  5533. // }
  5534.  
  5535. // }
  5536.  
  5537. const delayFlushActiveItemsAfterUserActionK_ = null;
  5538.  
  5539. document.addEventListener('scroll', (evt) => {
  5540. if (!evt || !evt.isTrusted) return;
  5541. // lastScroll = dateNow();
  5542. scrollCount = (scrollCount & 1073741823) + 1;
  5543. }, passiveCapture); // support contain => support passive
  5544.  
  5545. document.addEventListener('wheel', (evt) => {
  5546. if (!evt || !evt.isTrusted) return;
  5547. if (lastScrollCount === scrollCount) return;
  5548. lastScrollCount = scrollCount;
  5549. lastWheel = dateNow();
  5550. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5551. }, passiveCapture); // support contain => support passive
  5552.  
  5553. document.addEventListener('mousedown', (evt) => {
  5554. if (!evt || !evt.isTrusted) return;
  5555. if (((evt || 0).target || 0).id !== 'item-scroller') return;
  5556. lastMouseDown = dateNow();
  5557. currentMouseDown = true;
  5558. lastUserInteraction = lastMouseDown;
  5559. }, passiveCapture);
  5560.  
  5561. document.addEventListener('pointerdown', (evt) => {
  5562. if (!evt || !evt.isTrusted) return;
  5563. if (((evt || 0).target || 0).id !== 'item-scroller') return;
  5564. lastMouseDown = dateNow();
  5565. currentMouseDown = true;
  5566. lastUserInteraction = lastMouseDown;
  5567. }, passiveCapture);
  5568.  
  5569. document.addEventListener('click', (evt) => {
  5570. if (!evt || !evt.isTrusted) return;
  5571. if (((evt || 0).target || 0).id !== 'item-scroller') return;
  5572. lastMouseDown = lastMouseUp = dateNow();
  5573. currentMouseDown = false;
  5574. lastUserInteraction = lastMouseDown;
  5575. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5576. }, passiveCapture);
  5577.  
  5578. document.addEventListener('tap', (evt) => {
  5579. if (!evt || !evt.isTrusted) return;
  5580. if (((evt || 0).target || 0).id !== 'item-scroller') return;
  5581. lastMouseDown = lastMouseUp = dateNow();
  5582. currentMouseDown = false;
  5583. lastUserInteraction = lastMouseDown;
  5584. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5585. }, passiveCapture);
  5586.  
  5587.  
  5588. document.addEventListener('mouseup', (evt) => {
  5589. if (!evt || !evt.isTrusted) return;
  5590. if (currentMouseDown) {
  5591. lastMouseUp = dateNow();
  5592. currentMouseDown = false;
  5593. lastUserInteraction = lastMouseUp;
  5594. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5595. }
  5596. }, passiveCapture);
  5597.  
  5598.  
  5599. document.addEventListener('pointerup', (evt) => {
  5600. if (!evt || !evt.isTrusted) return;
  5601. if (currentMouseDown) {
  5602. lastMouseUp = dateNow();
  5603. currentMouseDown = false;
  5604. lastUserInteraction = lastMouseUp;
  5605. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5606. }
  5607. }, passiveCapture);
  5608.  
  5609. document.addEventListener('touchstart', (evt) => {
  5610. if (!evt || !evt.isTrusted) return;
  5611. lastTouchDown = dateNow();
  5612. currentTouchDown = true;
  5613. lastUserInteraction = lastTouchDown;
  5614. }, passiveCapture);
  5615.  
  5616. document.addEventListener('touchmove', (evt) => {
  5617. if (!evt || !evt.isTrusted) return;
  5618. lastTouchDown = dateNow();
  5619. currentTouchDown = true;
  5620. lastUserInteraction = lastTouchDown;
  5621. }, passiveCapture);
  5622.  
  5623. document.addEventListener('touchend', (evt) => {
  5624. if (!evt || !evt.isTrusted) return;
  5625. if (currentTouchDown) {
  5626. lastTouchUp = dateNow();
  5627. currentTouchDown = false;
  5628. lastUserInteraction = lastTouchUp;
  5629. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5630. }
  5631. }, passiveCapture);
  5632.  
  5633. document.addEventListener('touchcancel', (evt) => {
  5634. if (!evt || !evt.isTrusted) return;
  5635. if (currentTouchDown) {
  5636. lastTouchUp = dateNow();
  5637. currentTouchDown = false;
  5638. lastUserInteraction = lastTouchUp;
  5639. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5640. }
  5641. }, passiveCapture);
  5642.  
  5643.  
  5644. }
  5645.  
  5646. // const getTimestampUsec = (itemRenderer) => {
  5647. // if (itemRenderer && 'timestampUsec' in itemRenderer) {
  5648. // return itemRenderer.timestampUsec
  5649. // } else if (itemRenderer && itemRenderer.showItemEndpoint) {
  5650. // const messageRenderer = ((itemRenderer.showItemEndpoint.showLiveChatItemEndpoint || 0).renderer || 0);
  5651. // if (messageRenderer) {
  5652.  
  5653. // const messageRendererKey = firstObjectKey(messageRenderer);
  5654. // if (messageRendererKey && messageRenderer[messageRendererKey]) {
  5655. // const messageRendererData = messageRenderer[messageRendererKey];
  5656. // if (messageRendererData && 'timestampUsec' in messageRendererData) {
  5657. // return messageRendererData.timestampUsec
  5658. // }
  5659. // }
  5660. // }
  5661. // }
  5662. // return null;
  5663. // }
  5664.  
  5665. const onRegistryReadyForDOMOperations = () => {
  5666.  
  5667. let firstCheckedOnYtInit = false;
  5668.  
  5669. const assertorURL = () => assertor(() => location.pathname.startsWith('/live_chat') && (location.search.indexOf('continuation=') > 0 || location.search.indexOf('v=') > 0));
  5670.  
  5671. const mightFirstCheckOnYtInit = () => {
  5672. if (firstCheckedOnYtInit) return;
  5673. firstCheckedOnYtInit = true;
  5674.  
  5675. if (!document.body || !document.head) return;
  5676. if (!assertorURL()) return;
  5677.  
  5678. addCssManaged();
  5679.  
  5680. let efsContainer = document.getElementById('elzm-fonts-yk75g');
  5681. if (efsContainer && efsContainer.parentNode !== document.body) {
  5682. document.body.appendChild(efsContainer);
  5683. }
  5684.  
  5685. };
  5686.  
  5687. if (!assertorURL()) return;
  5688. // if (!assertor(() => document.getElementById('yt-masthead') === null)) return;
  5689.  
  5690.  
  5691. const { weakWrap } = (() => {
  5692.  
  5693.  
  5694. // const tickerFuncProps = new Set([
  5695. // 'animateShowStats', 'animateHideStats', // updateStatsBarAndMaybeShowAnimationRevised
  5696. // 'collapse', // slideDownNoSelfLeakage
  5697. // 'requestRemoval', // collapseNoSelfLeakage
  5698. // 'setContainerWidth', 'get', 'set', // deletedChangedNoSelfLeakage
  5699. // 'computeAriaLabel', //dataChanged
  5700. // 'startCountdown', // dataChanged [in case]
  5701. // ]);
  5702.  
  5703. // const tickerTags = new Set([
  5704. // "yt-live-chat-ticker-renderer",
  5705. // "yt-live-chat-ticker-paid-message-item-renderer",
  5706. // "yt-live-chat-ticker-paid-sticker-item-renderer",
  5707. // "yt-live-chat-ticker-sponsor-item-renderer"
  5708. // ]);
  5709.  
  5710. // const emptySet = new Set();
  5711.  
  5712.  
  5713.  
  5714. // const tickerFuncPropsFn = (cnt) => {
  5715.  
  5716. // const is = `${cnt.is}`;
  5717.  
  5718. // if (tickerTags.has(is)) {
  5719. // let flg = 0;
  5720. // if (cnt.get && cnt.set) flg |= 1;
  5721. // if (cnt.setContainerWidth && cnt.collapse && cnt.requestRemoval) flg |= 2;
  5722. // if (cnt.animateShowStats && cnt.animateHideStats) flg |= 4;
  5723. // if (cnt.startCountdown) flg |= 8;
  5724. // console.log(`DEBUG flag_6877 = ${flg}`, is);
  5725. // // DEBUG flag_6877 = 15 yt-live-chat-ticker-paid-message-item-renderer
  5726. // // DEBUG flag_6877 = 11 yt-live-chat-ticker-sponsor-item-renderer
  5727. // return tickerFuncProps;
  5728. // }
  5729.  
  5730. // return emptySet;
  5731.  
  5732.  
  5733. // }
  5734.  
  5735.  
  5736. // const smb = Symbol();
  5737. const vmb = 'dtz02' // Symbol(); // return kThis for thisArg
  5738. const vmc = 'dtz04' // Symbol(); // whether it is proxied fn
  5739. const vmd = 'dtz08' // Symbol(); // self fn proxy (fn--fn)
  5740.  
  5741.  
  5742.  
  5743.  
  5744. const thisConversionFn = (thisArg) => {
  5745. if (!thisArg) return null;
  5746. const kThis = thisArg[vmb];
  5747. if (kThis) {
  5748. const ref = kThis.ref;
  5749. return (ref ? kRef(ref) : null) || null;
  5750. }
  5751. return thisArg;
  5752. }
  5753.  
  5754. const pFnHandler2 = {
  5755. get(target, prop) {
  5756. if (prop === vmc) return target;
  5757. return Reflect.get(target, prop);
  5758. },
  5759. apply(target, thisArg, argumentsList) {
  5760. thisArg = thisConversionFn(thisArg);
  5761. if (thisArg) return Reflect.apply(target, thisArg, argumentsList);
  5762. }
  5763. }
  5764.  
  5765.  
  5766. const proxySelfHandler = {
  5767. get(target, prop) {
  5768. if(prop === vmb) return target;
  5769. const ref = target.ref;
  5770. const cnt = kRef(ref);
  5771. if (!cnt) return;
  5772. if (typeof cnt[prop] === 'function' && !cnt[prop][vmc] && !cnt[prop][vmb]) {
  5773. if (!cnt[prop][vmd]) cnt[prop][vmd] = new Proxy(cnt[prop], pFnHandler2);
  5774. return cnt[prop][vmd];
  5775. }
  5776. return cnt[prop];
  5777. },
  5778. set(target, prop, value) {
  5779. const cnt = kRef(target.ref);
  5780. if (!cnt) return true;
  5781. if(value && (value[vmc] || value[vmb])){
  5782. cnt[prop] = value[vmc] || thisConversionFn(value);
  5783. return true;
  5784. }
  5785. cnt[prop] = value;
  5786. return true;
  5787. }
  5788. };
  5789.  
  5790. const weakWrap = (thisArg) => {
  5791. thisArg = thisConversionFn(thisArg);
  5792. if (!thisArg) {
  5793. console.error('thisArg is not found');
  5794. return null;
  5795. }
  5796. return new Proxy({ ref: mWeakRef(thisArg) }, proxySelfHandler);
  5797. }
  5798.  
  5799.  
  5800.  
  5801.  
  5802.  
  5803.  
  5804. if (!window.getComputedStyle533 && typeof window.getComputedStyle === 'function') {
  5805. window.getComputedStyle533 = window.getComputedStyle;
  5806. window.getComputedStyle = function (a, ...args) {
  5807. a = thisConversionFn(a);
  5808. if (a) {
  5809. return getComputedStyle533(a, ...args);
  5810. }
  5811. return null;
  5812. }
  5813. }
  5814.  
  5815.  
  5816.  
  5817.  
  5818.  
  5819.  
  5820.  
  5821. // const fnProxySelf = function (...args) {
  5822. // const cnt = kRef(this.ref);
  5823. // if (cnt) {
  5824. // return cnt[this.prop](...args); // might throw error
  5825. // }
  5826. // }
  5827. // const proxySelfHandler = {
  5828. // get(target, prop) {
  5829. // const ref = target.ref;
  5830. // const cnt = kRef(ref);
  5831. // if (!cnt) return;
  5832. // if (prop === 'dtz06') return 1;
  5833. // if (typeof cnt[prop] === 'function') {
  5834. // if (!target.funcs.has(prop)) {
  5835. // console.warn(`proxy get to function | prop: ${prop} | is: ${cnt.is}`);
  5836. // }
  5837. // if (!target[`$$${prop}$$`]) target[`$$${prop}$$`] = fnProxySelf.bind({ prop, ref });
  5838. // return target[`$$${prop}$$`];
  5839. // }
  5840. // return cnt[prop];
  5841. // },
  5842. // set(target, prop, value) {
  5843. // const cnt = kRef(target.ref);
  5844. // if (!cnt) return true;
  5845. // if (typeof value === 'function') {
  5846. // console.warn(`proxy set to function | prop: ${prop} | is: ${cnt.is}`);
  5847. // cnt[prop] = value;
  5848. // return true;
  5849. // }
  5850. // cnt[prop] = value;
  5851. // return true;
  5852. // }
  5853. // };
  5854.  
  5855. // return { tickerFuncPropsFn, proxySelfHandler }
  5856.  
  5857. return {weakWrap}
  5858. })();
  5859.  
  5860.  
  5861.  
  5862. if (document.documentElement && document.head) {
  5863. addCssManaged();
  5864. }
  5865. // console.log(document.body===null)
  5866.  
  5867. const preprocessChatLiveActionsMap = new WeakSet();
  5868.  
  5869. const toLAObj=(aItem)=>{
  5870.  
  5871. if (!aItem || typeof aItem !== 'object') return false;
  5872. const key = firstObjectKey(aItem); // addLiveChatTickerItemAction
  5873. if (!key) return false;
  5874. let obj = aItem[key];
  5875. if (!obj || typeof obj !== 'object') return false;
  5876.  
  5877. if (typeof (obj.item || 0) == 'object' && firstObjectKey(obj) === 'item') {
  5878. obj = obj.item;
  5879. const key = firstObjectKey(obj);
  5880. if (key) {
  5881. obj = obj[key];
  5882. }
  5883. }
  5884.  
  5885. return obj;
  5886.  
  5887. };
  5888.  
  5889. const groupsK38=[];
  5890.  
  5891.  
  5892. function intervalsOverlap(a1, a2, b1, b2) {
  5893. // Order the intervals without using Math functions
  5894. var startA = a1 <= a2 ? a1 : a2;
  5895. var endA = a1 <= a2 ? a2 : a1;
  5896.  
  5897. var startB = b1 <= b2 ? b1 : b2;
  5898. var endB = b1 <= b2 ? b2 : b1;
  5899.  
  5900. // Check for overlap
  5901. return endA >= startB && endB >= startA;
  5902. }
  5903.  
  5904.  
  5905.  
  5906. const insertIntoSortedArrayA28 = (arr, val) => {
  5907. let left = 0;
  5908. const n = arr.length;
  5909. let right = n;
  5910.  
  5911. // Binary search to find the correct insertion index:
  5912. // We want the first index where arr[index][2] >= val[2].
  5913. while (left < right) {
  5914. const mid = (left + right) >>> 1;
  5915. if (arr[mid][0] < val[0]) {
  5916. left = mid + 1;
  5917. } else {
  5918. right = mid;
  5919. }
  5920. }
  5921.  
  5922. // 'left' is now the insertion index
  5923. left === n ? arr.push(val): arr.splice(left, 0, val);
  5924. };
  5925.  
  5926. function removeNullsInPlace(arr, startI = 0) {
  5927. let insertPos = startI;
  5928. for (let i = startI; i < arr.length; i++) {
  5929. if (arr[i] !== null) {
  5930. insertPos !== i && (arr[insertPos] = arr[i]);
  5931. insertPos++;
  5932. }
  5933. }
  5934. arr.length = insertPos; // Remove the trailing nulls.
  5935. }
  5936.  
  5937. let fir = 0;
  5938.  
  5939. const limitAddition = (a, b) => {
  5940. // Number.MAX_SAFE_INTEGER = 9007199254740991
  5941. // formula = Math.round((a + b) / (1 + a * b / k / k))
  5942. // avoid a*b > 9007199254740991
  5943. // say a, b <= 94800000
  5944. // Consider (x+x) - (x+x) / (1 + x^2 / k^2) < 0.49
  5945. // x < 130095
  5946.  
  5947. const w = 130095;
  5948. if (a < w && b < w) return a + b;
  5949. const k2 = 94800000 * 94800000;
  5950. return Math.round((a + b) / (1 + (a * b) / k2));
  5951. }
  5952.  
  5953. const preprocessChatLiveActions = (arr, ct_) =>{
  5954.  
  5955. if (!ct_) ct_ = Date.now();
  5956.  
  5957. if (!fir) {
  5958.  
  5959. if (!__LCRInjection__) {
  5960. console.error('[yt-chat] preprocessChatLiveActions might fail because of no __LCRInjection__');
  5961. }
  5962.  
  5963. DEBUG_preprocessChatLiveActions && console.log('[yt-chat-debug] 5990', 'preprocessChatLiveActions', arr)
  5964.  
  5965. DEBUG_preprocessChatLiveActions && console.log('[yt-chat-debug] 5991', document.querySelectorAll('yt-live-chat-ticker-renderer #ticker-items [class]').length)
  5966.  
  5967. fir = 1;
  5968. // debugger;
  5969. }
  5970.  
  5971. if (!arr || !arr.length) return arr;
  5972.  
  5973. if (preprocessChatLiveActionsMap.has(arr)) return arr;
  5974. preprocessChatLiveActionsMap.add(arr);
  5975.  
  5976.  
  5977.  
  5978. const ct = ct_;
  5979.  
  5980. let groups_ = null;
  5981.  
  5982. // console.log(1237005);
  5983. // const conversionMap = new WeakMap();
  5984.  
  5985. const additionalInfo = new WeakMap();
  5986.  
  5987. // const adjustmentMap = new Map();
  5988.  
  5989. if (FIX_TIMESTAMP_FOR_REPLAY) {
  5990.  
  5991. // console.log('group02331')
  5992. // console.time('FIX_TIMESTAMP_FOR_REPLAY')
  5993.  
  5994. // const stack = new Array(arr.length);
  5995. // let stackL = 0;
  5996.  
  5997. // const arrHash = new Array(arr.length);
  5998.  
  5999.  
  6000. const groups = groupsK38;
  6001. // const delta = 2.0; // head-to-tail + 0.5 + 0.5 = 1.0 -> symmetric -> 1.0 * 2 = 2.0
  6002. // (2)
  6003. // (1.5, 2.5)
  6004. // (1.51, 2.49)
  6005. // -> (1.01, 2.01) , (1.99, 2.99)
  6006. // 2.99 - 1.01 = 1.98 -> 2
  6007.  
  6008.  
  6009.  
  6010. const pushToGroup = (t0mu)=>{
  6011.  
  6012. const t0auDv = t0mu - 1e6; // t0buDv - t0auDv = 2e6
  6013. const t0buDv = t0mu + 1e6;
  6014. // const t0auEv = t0mu - 2e6;
  6015. // const t0buEv = t0mu + 2e6;
  6016.  
  6017. let groupK = false;
  6018. // let m = -1;
  6019. // let q= 0;
  6020. //const qq =true;
  6021. //qq && console.log('-------')
  6022.  
  6023. let lastRight = null;
  6024. let lastK = null;
  6025. let deletedStartIndex = -1;
  6026.  
  6027. for (let k = 0, kl = groups.length; k < kl; k++) {
  6028.  
  6029. const group = groups[k];
  6030. const [groupStart, groupEnd, gCount] = group;
  6031. //qq && console.log(`-- ${k} ----- ${groupMid} : [${groupStart},${groupEnd}] || C1 = ${t0buEv < groupMid} || C2 = ${t0auEv > groupMid}`);
  6032.  
  6033. // if (t0bsEv < groupMid) continue; // if(t0m + 1.0 < groupMid - 1.0) continue;
  6034. // if (m < 0) m = k;
  6035. // if (t0asEv > groupMid){
  6036. // continue; // if(t0m - 1.0 > groupMid + 1.0) break;
  6037. // }
  6038.  
  6039.  
  6040. // if (m < 0) m = k;
  6041.  
  6042. if (lastRight > groupStart) {
  6043. if (!groupK) {
  6044. // just in case sth wrong
  6045. console.warn('logic ERROR');
  6046. groups[k] = null;
  6047. if(deletedStartIndex < 0) deletedStartIndex = k;
  6048. break;
  6049. } else {
  6050.  
  6051.  
  6052. // GroupA: N_a' = N_a + n_e{1} ; Note n_e is the only way to shift right to cause " (lastRight > groupStart) "
  6053. // GroupB: N_b
  6054. // Merge Group (A) = N_a' + N_b
  6055.  
  6056. // without entry moditification, no overlap
  6057. // this must be due to entry moditifcation
  6058. // entry is already count. so can be skipped after merging
  6059.  
  6060. // for merging, groupA will move to right side but left than groupB, so no overlap to groupC
  6061.  
  6062. const group = groups[lastK];
  6063. const newN = limitAddition(group[2], gCount);
  6064.  
  6065. const factor = gCount / (group[2] + gCount);
  6066.  
  6067. // group[0] = (group[0] * group[2] + groupStart * gCount) / (group[2] + gCount)
  6068. group[0] += (groupStart - group[0]) * factor;
  6069.  
  6070. // group[1] = lastRight = (group[1] * group[2] + groupEnd * gCount) / (group[2] + gCount)
  6071. group[1] += (groupEnd - group[1]) * factor;
  6072.  
  6073. group[2] = newN;
  6074. // no change of lastK
  6075. groups[k] = null;
  6076. if(deletedStartIndex < 0) deletedStartIndex = k;
  6077. continue;
  6078. }
  6079. }
  6080.  
  6081. const minGroupStart = lastRight; // all groupStart, groupEnd >= minGroupStart for k, k+1, ...
  6082. if (t0buDv < minGroupStart) {
  6083. // no overlapping could be possible
  6084. break;
  6085. }
  6086.  
  6087. if (intervalsOverlap(t0auDv, t0buDv, groupStart, groupEnd)) {
  6088.  
  6089. groupK = true;
  6090.  
  6091. // if (t0auDv > groupStart) group[0] = t0auDv;
  6092. // else if (t0buDv < groupEnd) group[1] = t0buDv;
  6093.  
  6094. // const newStart = (groupStart * gCount + t0auDv) / (gCount + 1);
  6095. const newStart = groupStart + (t0auDv - groupStart) * 1 / (gCount + 1);
  6096.  
  6097. if (newStart < lastRight) {
  6098. // n_e{1} will make N_b shift left
  6099.  
  6100. // GroupA: N_a
  6101. // GroupB: N_b
  6102. // Merge Group (A) = N_a + N_b + n_e{1}
  6103.  
  6104. const group = groups[lastK];
  6105. const newN = limitAddition(limitAddition(group[2], gCount), 1);
  6106. const f1 = gCount / (group[2] + gCount + 1);
  6107. const f2 = 1 / (group[2] + gCount + 1);
  6108.  
  6109. // group[0] = (group[0] * group[2] + groupStart * gCount + t0auDv) / (group[2] + gCount + 1);
  6110. group[0] += (groupStart - group[0]) * f1 + (t0auDv - group[0]) * f2;
  6111.  
  6112. // group[1] = lastRight = (group[1] * group[2] + groupEnd * gCount + t0buDv) / (group[2] + gCount + 1)
  6113. lastRight = (group[1] += (groupEnd - group[1]) * f1 + (t0buDv - group[1]) * f2);
  6114.  
  6115. group[2] = newN;
  6116. // no change of lastK
  6117. groups[k] = null;
  6118. if(deletedStartIndex < 0) deletedStartIndex = k;
  6119. continue;
  6120.  
  6121. } else {
  6122. // n_e{1} will make N_b shift either left or right
  6123.  
  6124. // GroupT: N_t
  6125. // Group (T) = N_t + n_e{1}
  6126.  
  6127. const newN = limitAddition(gCount, 1);
  6128.  
  6129. group[0] = newStart;
  6130. // group[1] = lastRight = (groupEnd * gCount + t0buDv) / (gCount + 1);
  6131. group[1] = lastRight = groupEnd + (t0buDv - groupEnd) * 1 / (gCount + 1);
  6132. group[2] = newN;
  6133.  
  6134. lastK = k;
  6135.  
  6136. // (t0asDv > groupStart) && (t0bsDv < groupEnd) means full containement
  6137. // however, group size is smaller than or equal to t0width
  6138. }
  6139.  
  6140.  
  6141. } else {
  6142. // just update record for next iteration
  6143.  
  6144. lastRight = groupEnd;
  6145. lastK = k;
  6146. }
  6147.  
  6148.  
  6149.  
  6150. }
  6151.  
  6152. if (deletedStartIndex >= 0) {
  6153. // rarely used
  6154.  
  6155. removeNullsInPlace(groups, deletedStartIndex);
  6156.  
  6157. }
  6158. if (!groupK) {
  6159. // groups.push([t0auDv, t0buDv, 1]);
  6160. insertIntoSortedArrayA28(groups, [t0auDv, t0buDv, 1]);
  6161. // insertIntoSortedArrayA27(groups, [t0auDv, t0buDv, t0mu]);
  6162. }
  6163.  
  6164.  
  6165. }
  6166.  
  6167. let autoTimeStampFrameChoose = 0;
  6168.  
  6169. // console.log('group02332')
  6170. for (let j = 0, l = arr.length; j < l; j++) {
  6171. const aItem = arr[j];
  6172.  
  6173. const obj = toLAObj(aItem);
  6174. if (obj === false) continue;
  6175.  
  6176. let p = obj.timestampText;
  6177. let p2, p3=null, p4a=null, p4b=null;
  6178. if(p&&p.simpleText ) p2 = p.simpleText;
  6179.  
  6180. let q = obj.timestampUsec ;
  6181. let q2;
  6182.  
  6183. if(q && +q > 1110553200000000) q2 = +q;
  6184. if (q2 > 0 && !autoTimeStampFrameChoose) {
  6185. const q2cc = Math.round(q2 / 1e6);
  6186. autoTimeStampFrameChoose = q2cc - (q2cc % 10000000);
  6187. if (q2cc - autoTimeStampFrameChoose < 2000000) autoTimeStampFrameChoose -= 10000000;
  6188. // around 10day range
  6189. // exceeded ~10day -> above 10000000
  6190. }
  6191.  
  6192. // console.log('group02333', p2, q2)
  6193. // console.log(3775, q2/1e6, autoTimeStampFrameChoose)
  6194.  
  6195. if(p2 && q2){
  6196.  
  6197. let m;
  6198.  
  6199. if (m = /^\s*(-?)(\d+):(\d+)\s*$/.exec(p2)) {
  6200. let c0z = m[1] ? -1 : 1;
  6201. let c1 = (+m[2]);
  6202. let c2 = (+m[3]);
  6203. if (c0z > 0 && c1 >= 0 && c2 >= 0) {
  6204.  
  6205. p3 = c1 * 60 + c2;
  6206. } else if (c0z < 0 && c1 >= 0 && c2 >= 0) {
  6207. // -4:43 -> -4:42 -> -4:41 ... -> -4:01 -> -4:00 -> -3:59 -> -3:58
  6208. // -> ... -1:01 -> -1:00 -> -0:59 -> ... -> -0:02 -> -0:01 -> -0:00 -> 0:00 -> ...
  6209.  
  6210. p3 = (-c1 * 60) + (-c2);
  6211.  
  6212. }
  6213. if (p3 !== null) {
  6214. // 0:14 -> 13.5s ~ 14.4999s -> [13.5, 14.5)
  6215. p4a = p3 - 0.5;
  6216. p4b = p3 + 0.5;
  6217. }
  6218. } else if (m = /^\s*(-?)(\d+):(\d+):(\d+)\s*$/.exec(p2)) {
  6219.  
  6220. let c0z = m[1] ? -1 : 1;
  6221. let c1 = (+m[2]);
  6222. let c2 = (+m[3]);
  6223. let c3 = (+m[4]);
  6224.  
  6225.  
  6226.  
  6227. if (c0z > 0 && c1 >= 0 && c2 >= 0 && c3 >= 0) {
  6228.  
  6229. p3 = c1 * 60 * 60 + c2 * 60 + c3;
  6230. } else if (c0z < 0 && c1 >= 0 && c2 >= 0 && c3>=0) {
  6231. // -4:43 -> -4:42 -> -4:41 ... -> -4:01 -> -4:00 -> -3:59 -> -3:58
  6232. // -> ... -1:01 -> -1:00 -> -0:59 -> ... -> -0:02 -> -0:01 -> -0:00 -> 0:00 -> ...
  6233.  
  6234. p3 = (-c1 * 60 * 60) + (-c2 * 60) + (-c3);
  6235.  
  6236. }
  6237. if (p3 !== null) {
  6238. // 0:14 -> 13.5s ~ 14.4999s -> [13.5, 14.5)
  6239. p4a = p3 - 0.5;
  6240. p4b = p3 + 0.5;
  6241. }
  6242.  
  6243.  
  6244. }
  6245.  
  6246. }
  6247.  
  6248. if(p4a !== null && p4b !== null && q2 > 0){
  6249.  
  6250. // q2_us = t0_us + dt_us
  6251. // p4a_us <= dt_us < p4b_us
  6252. let p4au = p4a * 1e6;
  6253. let p4bu = p4b * 1e6;
  6254.  
  6255. // p4a_us <= q2_us - t0_us < p4b_us
  6256.  
  6257.  
  6258. // p4a_us - q2_us <= - t0_us < p4b_us - q2_us
  6259.  
  6260. // -p4a_us + q2_us >= t0_us > -p4b_us + q2_us
  6261.  
  6262.  
  6263. let t0au = q2 - p4bu; // q2_us - p4b_us
  6264. let t0bu = q2 - p4au; // q2_us - p4a_us
  6265.  
  6266. // t0 (t0au, t0bu]
  6267.  
  6268. const t0mu = (t0au+t0bu)/2;
  6269.  
  6270. // stack[stackL++]=({
  6271. // id: obj.id,
  6272. // idx: j,
  6273. // p2,
  6274. // // q2s : (q2/ 1e6 - autoTimeStampFrameChoose).toFixed(2),
  6275. // p3,
  6276. // /*
  6277. // timestampText: obj.timestampText,
  6278. // timestampUsec: obj.timestampUsec, // us = 1/1000 ms
  6279. // q2,
  6280. // p4a,
  6281. // p4b,
  6282. // */
  6283. // q2s: +(q2 / 1e6 - autoTimeStampFrameChoose).toFixed(2),
  6284. // t0as: +(t0au / 1e6 - autoTimeStampFrameChoose).toFixed(2),
  6285. // t0bs: +(t0bu /1e6 - autoTimeStampFrameChoose).toFixed(2),
  6286.  
  6287. // t0au,
  6288. // t0bu,
  6289. // t0mu
  6290. // });
  6291.  
  6292. // console.log('group02334')
  6293. let wobj = additionalInfo.get(obj);
  6294. if(!wobj) additionalInfo.set(obj, wobj = {});
  6295.  
  6296. wobj.timestampUsecOriginal = q2;
  6297. // wobj.timestampUsecAdjusted = q2;
  6298. wobj.t0au = t0au;
  6299. wobj.t0bu = t0bu;
  6300. wobj.t0mu = t0mu;
  6301.  
  6302. // arrHash[j] = {
  6303. // index: j,
  6304. // id: obj.id,
  6305. // timestampUsec: q2,
  6306. // t0au,
  6307. // t0bu,
  6308. // t0mu
  6309. // };
  6310.  
  6311. pushToGroup(t0mu);
  6312.  
  6313. // console.log('group02335')
  6314. // console.log('grouping', `${obj.id}.${obj.timestampUsec}`);
  6315.  
  6316. // timestamp (q2) can be incorrect.
  6317.  
  6318. // https://www.youtube.com/watch?v=IKKar5SS29E
  6319. // ChwKGkNQZUxfXzZxLS04Q0ZXNGxyUVlkODZrQzNR
  6320.  
  6321. /*
  6322.  
  6323.  
  6324. [
  6325. {
  6326. "id": "ChwKGkNNWHZqXy1xLS04Q0ZXNGxyUVlkODZrQzNR",
  6327. "p2": "2:04",
  6328. "p3": 124,
  6329. "t0as": 8320733.78,
  6330. "t0bs": 8320734.78
  6331. },
  6332. {
  6333. "id": "ChwKGkNQZUxfXzZxLS04Q0ZXNGxyUVlkODZrQzNR",
  6334. "p2": "2:04",
  6335. "p3": 124,
  6336. "t0as": 8320898.89, // incorrect
  6337. "t0bs": 8320899.89
  6338. }
  6339. ]
  6340.  
  6341.  
  6342. */
  6343.  
  6344. }
  6345.  
  6346.  
  6347.  
  6348.  
  6349. }
  6350.  
  6351. // stack.length = stackL;
  6352.  
  6353.  
  6354. groups_ = groups;
  6355. // console.log('groups', groups)
  6356.  
  6357. }
  6358.  
  6359. // console.log(1237006);
  6360.  
  6361. // console.log(5592,1)
  6362. const groupMids = FIX_TIMESTAMP_FOR_REPLAY ? groups_.map(group=>{
  6363.  
  6364. const [groupStart, groupEnd ] = group;
  6365. const groupMid = (groupStart+groupEnd)/2;
  6366. return groupMid;
  6367. }): null;
  6368. // console.log('groupMids', groupMids)
  6369.  
  6370.  
  6371. // console.log(1237007);
  6372.  
  6373. const adjustTimestampFn = (obj) => {
  6374.  
  6375. const groupCount = groupMids.length;
  6376.  
  6377. if (groupCount < 1) return null;
  6378.  
  6379. // const obj = toLAObj(aItem);
  6380. if (obj === false) return null;
  6381.  
  6382. const wobj = additionalInfo.get(obj);
  6383. if (!wobj) return null;
  6384.  
  6385. const { t0mu } = wobj;
  6386.  
  6387.  
  6388. let i0 = 0;
  6389.  
  6390. if (groupCount >= 3) {
  6391. // For larger arrays, use binary search.
  6392. let low = 0;
  6393. let high = groupCount - 1;
  6394.  
  6395. while (high - low > 1) {
  6396. const mid = (low + high) >>> 1;
  6397. if (groupMids[mid] >= t0mu) {
  6398. high = mid;
  6399. } else {
  6400. low = mid;
  6401. }
  6402. }
  6403. i0 = low;
  6404.  
  6405. }
  6406.  
  6407. let upperDiff = -1;
  6408. let lowerDiff = -1;
  6409. for (let i = i0; i < groupCount; i++) {
  6410. const y = groupMids[i] - t0mu;
  6411. if (y >= 0) {
  6412. upperDiff = y; // >=0, entry > value is found
  6413. break;
  6414. }
  6415. lowerDiff = -y; // >0, cache
  6416. }
  6417.  
  6418.  
  6419. const d1 = upperDiff;
  6420. const d2 = lowerDiff;
  6421.  
  6422.  
  6423. // console.log(5381, index1 ,d1, index2 , d2);
  6424.  
  6425. if (d1 >= 0 && ((d2 < 0) || (d1 <= d2))) {
  6426. wobj.chosenT0 = t0mu + d1; // groupMids[index1];
  6427. } else if (d2 >= 0 && ((d1 < 0) || (d2 <= d1))) {
  6428. wobj.chosenT0 = t0mu - d2; // groupMids[index2];
  6429. } else {
  6430. console.warn('logic error');
  6431. return null;
  6432. }
  6433.  
  6434. const adjusted = wobj.timestampUsecOriginal - wobj.chosenT0;
  6435.  
  6436. wobj.timestampUsecAdjusted = adjusted + 1110553200000000;
  6437.  
  6438. // console.log('adjusted', `${obj.id}.${obj.timestampUsec}`, wobj.timestampUsecOriginal - wobj.chosenT0);
  6439.  
  6440. // adjustmentMap.set(`${obj.id}.${obj.timestampUsec}`, wobj.timestampUsecOriginal - wobj.chosenT0);
  6441.  
  6442. return adjusted;
  6443.  
  6444.  
  6445.  
  6446. };
  6447.  
  6448.  
  6449. // console.log(5592,2)
  6450. // console.log(1237008);
  6451. // if (FIX_TIMESTAMP_FOR_REPLAY) {
  6452.  
  6453.  
  6454. // try{
  6455.  
  6456. // // console.log('groupmid',groupMids, groups);
  6457.  
  6458. // for(let j = 0; j< arr.length;j++){
  6459. // if(groupMids.length<1) break;
  6460.  
  6461. // const aItem = arr[j];
  6462. // const obj = toLAObj(aItem);
  6463. // if (obj === false) continue;
  6464.  
  6465. // const wobj = additionalInfo.get(obj);
  6466. // if(!wobj) continue;
  6467.  
  6468. // // wobj.timestampUsecOriginal = q2;
  6469. // // wobj.timestampUsecAdjusted = q2;
  6470. // // wobj.t0au = t0au;
  6471. // // wobj.t0bu = t0bu;
  6472. // // wobj.t0mu = t0mu;
  6473.  
  6474. // const {t0au, t0bu, t0mu} = wobj;
  6475.  
  6476. // let upper = -1;
  6477.  
  6478. // for(let i = 0; i <groupMids.length;i++){
  6479. // const groupMid = groupMids[i];
  6480. // if(groupMid>= t0mu){
  6481. // upper = i;
  6482. // break;
  6483. // }
  6484. // }
  6485. // let index1, index2;
  6486. // if(upper>-1){
  6487. // index1 = upper-1;
  6488. // index2 = upper;
  6489. // }else{
  6490. // index1 = groups.length-1;
  6491. // index2 = -1;
  6492. // }
  6493. // let d1 = null;
  6494. // if(index1 >=0){
  6495. // d1 = Math.abs(groupMids[index1] - t0mu);
  6496. // }
  6497.  
  6498. // let d2 = null;
  6499. // if(index2 >=0){
  6500. // d2 = Math.abs(groupMids[index2] - t0mu);
  6501. // }
  6502. // // console.log(5381, index1 ,d1, index2 , d2);
  6503. // if(d1 >= 0 && ((d1 <= d2) || (d2 === null)) ){
  6504.  
  6505. // wobj.chosenT0 = groupMids[index1];
  6506. // } else if(d2 >= 0 && ((d2 <= d1) || (d1 === null))){
  6507. // wobj.chosenT0 = groupMids[index2];
  6508. // } else {
  6509. // console.warn('logic error');
  6510. // continue;
  6511. // }
  6512.  
  6513. // wobj.timestampUsecAdjusted = wobj.timestampUsecOriginal - wobj.chosenT0 + 1110553200000000;
  6514.  
  6515. // console.log('adjusted', `${obj.id}.${obj.timestampUsec}`, wobj.timestampUsecOriginal - wobj.chosenT0);
  6516.  
  6517. // adjustmentMap.set(`${obj.id}.${obj.timestampUsec}`, wobj.timestampUsecOriginal - wobj.chosenT0);
  6518. // // conversionMap.set(obj, arrHash[j].adjustedTime);
  6519.  
  6520. // // console.log(5382, index, id, t0mu, arrHash[j].adjustedT0, arrHash[j].timestampUsec, arrHash[j].adjustedTime);
  6521.  
  6522. // }
  6523.  
  6524.  
  6525. // }catch(e){
  6526. // console.warn(e);
  6527. // }
  6528.  
  6529.  
  6530.  
  6531.  
  6532.  
  6533. // // if(stack.length > 1){
  6534. // // stack.sort((a,b)=>{
  6535. // // return a.t0mu - b.t0mu
  6536. // // });
  6537. // // // small to large
  6538. // // // console.log(34588, stack.map(e=>e.t0as))
  6539. // // }
  6540.  
  6541. // // grouping
  6542.  
  6543.  
  6544.  
  6545.  
  6546. // // if (stack.length > 0) {
  6547.  
  6548. // // try {
  6549.  
  6550. // // for (let j = 0, l = stack.length; j < l; j++) {
  6551. // // pushToGroup(stack[j].t0mu);
  6552.  
  6553. // // }
  6554.  
  6555. // // }catch(e){
  6556.  
  6557. // // console.warn(e)
  6558. // // }
  6559.  
  6560. // // // console.log(4882, groups.map(e=>e.slice()), stack.slice())
  6561.  
  6562. // // }
  6563.  
  6564.  
  6565.  
  6566.  
  6567. // // console.log(376, 'group', groups);
  6568.  
  6569.  
  6570. // // consolidated group
  6571. // // const consolidatedGroups = doConsolidation(groups);
  6572.  
  6573.  
  6574.  
  6575.  
  6576.  
  6577.  
  6578. // // if(stack.length > 1){
  6579.  
  6580.  
  6581. // // // // console.log(341, 'consolidatedGroups', consolidatedGroups ,groups.map(e=>{
  6582. // // // // return e.map(noTransform);
  6583. // // // // // return e.map(prettyNum);
  6584. // // // // }))
  6585.  
  6586.  
  6587. // // // console.log(344, 'groups', groups.map(e=>{
  6588. // // // return e.map(noTransform);
  6589. // // // // return e.map(prettyNum);
  6590. // // // }))
  6591.  
  6592. // // // // for(const s of stack){
  6593. // // // // for(const g of consolidatedGroups){
  6594. // // // // if(s.t0as<=g.cen && s.t0bs >=g.cen ){
  6595. // // // // s.cen = g.cen;
  6596. // // // // break;
  6597. // // // // }
  6598. // // // // }
  6599.  
  6600. // // // // }
  6601.  
  6602. // // // console.log(377, stack) // Ms
  6603.  
  6604. // // }
  6605.  
  6606.  
  6607. // // console.timeEnd('FIX_TIMESTAMP_FOR_REPLAY')
  6608.  
  6609. // }
  6610.  
  6611.  
  6612.  
  6613.  
  6614.  
  6615.  
  6616.  
  6617.  
  6618.  
  6619. // console.log(5592,5)
  6620.  
  6621.  
  6622. // console.log('preprocessChatLiveActions', arr)
  6623.  
  6624.  
  6625. const mapper = new Map();
  6626. mapper.set = mapper.setOriginal || mapper.set;
  6627.  
  6628. // without delaying. get the time of request
  6629. // (both streaming and replay, but replay relys on progress update so background operation is suppressed)
  6630.  
  6631. for (let j = 0, l = arr.length; j < l; j++) {
  6632. const aItem = arr[j];
  6633.  
  6634. const obj = toLAObj(aItem);
  6635. if(obj === false) continue;
  6636.  
  6637. if (obj.id && !obj.__timestampActionRequest__) {
  6638. // for all item entries
  6639. obj.__timestampActionRequest__ = ct;
  6640. }
  6641.  
  6642. if (obj.id && obj.__timestampActionRequest__ > 0 && obj.durationSec > 0 && obj.fullDurationSec) {
  6643.  
  6644. // console.log(948700, obj , obj.id, (obj.fullDurationSec - obj.durationSec) * 1000)
  6645. const m = obj.__timestampActionRequest__ - (obj.fullDurationSec - obj.durationSec) * 1000;
  6646.  
  6647. // obj.__t374__ = (obj.fullDurationSec - obj.durationSec) * 1000;
  6648. // obj.__t375__ = obj.__timestampActionRequest__ - (obj.fullDurationSec - obj.durationSec) * 1000;
  6649. // console.log(5993, obj)
  6650. // obj.__orderTime__ = m;
  6651. mapper.set(aItem, m);
  6652.  
  6653.  
  6654. }
  6655.  
  6656. }
  6657.  
  6658. if (mapper.size > 1) {
  6659.  
  6660. const idxices = [];
  6661.  
  6662. // sort ticker
  6663. let mArr1 = arr.filter((aItem,idx) => {
  6664.  
  6665. if (mapper.has(aItem)) {
  6666. idxices.push(idx);
  6667. return true;
  6668. }
  6669. return false;
  6670.  
  6671. });
  6672.  
  6673.  
  6674. let mArr2 = mArr1/*.slice(0)*/.sort((a, b) => {
  6675. return mapper.get(a) - mapper.get(b);
  6676. // low index = oldest = smallest timestamp
  6677. });
  6678.  
  6679.  
  6680.  
  6681. // console.log(948701, arr.slice(0));
  6682. for(let j = 0, l=mArr1.length;j <l;j++){
  6683.  
  6684. const idx = idxices[j];
  6685. // arr[idx] = mArr1[j]
  6686. arr[idx] = mArr2[j];
  6687.  
  6688. // const obj1 = toObj(mArr1[j]);
  6689. // const obj2 = toObj(mArr2[j]);
  6690.  
  6691. // console.log(948705, idx, obj1 , obj1.id, (obj1.fullDurationSec - obj1.durationSec) * 1000, obj1.__orderTime__)
  6692.  
  6693. // console.log(948706, idx, obj2 , obj2.id, (obj2.fullDurationSec - obj2.durationSec) * 1000, obj2.__orderTime__)
  6694.  
  6695. }
  6696.  
  6697. // console.log(5994,arr)
  6698.  
  6699. // console.log(948702, arr.slice(0));
  6700. // console.log(948701, arr);
  6701. // arr = arr.map(aItem => {
  6702. // const idx = mArr1.indexOf(aItem);
  6703. // if (idx < 0) return aItem;
  6704. // return mArr2[idx];
  6705. // });
  6706. // console.log(948702, arr);
  6707.  
  6708. // mostly in order, but some not in order
  6709.  
  6710.  
  6711. // eg
  6712.  
  6713. /*
  6714.  
  6715.  
  6716. 948711 68 '1734488590715474'
  6717. 948711 69 '1734488590909853'
  6718. 948711 70 '1734488594763719'
  6719. 948711 71 '1734488602334615' <
  6720. 948711 72 '1734488602267214' <
  6721. 948711 73 '1734488602751771'
  6722. */
  6723.  
  6724. // arr.filter(aItem=>{
  6725.  
  6726. // const p = toObj(aItem);
  6727. // if(p.timestampUsec) return true;
  6728.  
  6729. // }).forEach((aItem,idx)=>{
  6730.  
  6731. // const p = toObj(aItem);
  6732. // console.log(948711, idx, p.timestampUsec);
  6733. // })
  6734.  
  6735. // return arr;
  6736.  
  6737. }
  6738.  
  6739. // console.log(1237001);
  6740.  
  6741. {
  6742.  
  6743. const mapper = new Map();
  6744. mapper.set = mapper.setOriginal || mapper.set;
  6745.  
  6746. const idxices = [];
  6747.  
  6748. let mArr1 = arr.filter((aItem,idx) => {
  6749.  
  6750. const obj = toLAObj(aItem);
  6751. if (!obj) return false;
  6752.  
  6753. const baseText = obj.timestampText;
  6754. const baseTime = +obj.timestampUsec;
  6755. if (!baseTime || !baseText) return false;
  6756. // const timestampUsec = +toLAObj(aItem).timestampUsec; // +false.x = NaN
  6757. // const timestampUsec = +toLAObj(aItem).adjustedTime;
  6758.  
  6759. let timestampUsec;
  6760.  
  6761. // console.log(1237002)
  6762. if (FIX_TIMESTAMP_FOR_REPLAY) {
  6763.  
  6764. // const adjustmentTime = adjustmentMap.get(`${obj.id}.${obj.timestampUsec}`);
  6765.  
  6766. // // const wobj = additionalInfo.get(obj);
  6767.  
  6768. // // if(!wobj){
  6769. // // console.warn('FIX_TIMESTAMP_FOR_REPLAY - no wobj', obj)
  6770. // // return false;
  6771. // // }
  6772.  
  6773. // // timestampUsec = +wobj.timestampUsecAdjusted;
  6774. // if (!Number.isFinite(adjustmentTime)) {
  6775. // console.warn(`FIX_TIMESTAMP_FOR_REPLAY - no adjustmentTime for ${obj.id}.${obj.timestampUsec}`, obj, [...adjustmentMap])
  6776. // return false;
  6777. // }
  6778. // timestampUsec = adjustmentTime;
  6779.  
  6780.  
  6781. const adjustmentTime = adjustTimestampFn(obj);
  6782.  
  6783. if (!Number.isFinite(adjustmentTime)) {
  6784.  
  6785. console.warn(`FIX_TIMESTAMP_FOR_REPLAY - no adjustmentTime for ${obj.id}.${obj.timestampUsec}`, obj);
  6786. return false;
  6787. }
  6788. timestampUsec = adjustmentTime;
  6789.  
  6790.  
  6791. } else {
  6792.  
  6793. if (!Number.isFinite(baseTime)) {
  6794. console.warn(`no baseTime for ${obj.id}.${obj.timestampUsec}`, obj);
  6795.  
  6796. return false;
  6797. }
  6798. timestampUsec = baseTime;
  6799.  
  6800. }
  6801.  
  6802. // if(timestampUsec > 0){
  6803. idxices.push(idx);
  6804. mapper.set(aItem, timestampUsec)
  6805. return true;
  6806. // }
  6807. // return false;
  6808.  
  6809. });
  6810.  
  6811. if(mapper.size > 1){
  6812.  
  6813.  
  6814. // console.log(1237004)
  6815. let mArr2 = mArr1/*.slice(0)*/.sort((a, b) => {
  6816. return mapper.get(a) - mapper.get(b);
  6817. // low index = oldest = smallest timestamp
  6818. });
  6819.  
  6820.  
  6821.  
  6822. // console.log(948701, arr.slice(0));
  6823. for(let j = 0, l=mArr1.length;j <l;j++){
  6824.  
  6825. const idx = idxices[j];
  6826. arr[idx] = mArr2[j];
  6827.  
  6828. // const obj1 = toObj(mArr1[j]);
  6829. // const obj2 = toObj(mArr2[j]);
  6830.  
  6831.  
  6832. // console.log(948711, idx, obj1 === obj2, obj1, obj1.timestampUsec);
  6833. // console.log(948712, idx, obj1 === obj2, obj2, obj2.timestampUsec);
  6834. }
  6835.  
  6836. }
  6837.  
  6838.  
  6839. }
  6840.  
  6841. // console.log(1237005)
  6842.  
  6843. // console.log(378, arr);
  6844.  
  6845. return arr;
  6846.  
  6847.  
  6848. }
  6849.  
  6850. if (ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION) {
  6851.  
  6852. console.log('[yt-chat-control] ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION is used.')
  6853.  
  6854. // console.log('ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION 0001')
  6855.  
  6856. const pop078 = function () {
  6857. const r = this.pop78();
  6858.  
  6859. if (r && (r.actions || 0).length >= 1 && r.videoOffsetTimeMsec) {
  6860. for (const action of r.actions) {
  6861.  
  6862. const itemActionKey = !action ? null : 'addChatItemAction' in action ? 'addChatItemAction' : 'addLiveChatTickerItemAction' in action ? 'addLiveChatTickerItemAction' : null;
  6863. if (itemActionKey) {
  6864.  
  6865. const itemAction = action[itemActionKey];
  6866. const item = (itemAction || 0).item;
  6867. if (typeof item === 'object') {
  6868.  
  6869. const rendererKey = firstObjectKey(item);
  6870. if (rendererKey) {
  6871. const renderer = item[rendererKey];
  6872. if (renderer && typeof renderer === 'object') {
  6873. renderer.__videoOffsetTimeMsec__ = r.videoOffsetTimeMsec;
  6874. renderer.__progressAt__ = playerProgressChangedArg1;
  6875.  
  6876. // console.log(48117006)
  6877. }
  6878.  
  6879. }
  6880.  
  6881. }
  6882. }
  6883. }
  6884. }
  6885. return r;
  6886. }
  6887.  
  6888.  
  6889.  
  6890. const replayQueueProxyHandler = {
  6891. get(target, prop, receiver) {
  6892. if (prop === 'qe3') return 1;
  6893. const v = target[prop];
  6894. if (prop === 'front_') {
  6895. if (v && typeof v.length === 'number') {
  6896. if (!v.pop78) {
  6897. v.pop78 = v.pop;
  6898. v.pop = pop078;
  6899. }
  6900. }
  6901. }
  6902. return v;
  6903. }
  6904. };
  6905.  
  6906. // lcrFn2 will run twice to ensure the method is successfully injected.
  6907. const lcrFn2 = (lcrDummy)=>{
  6908. // make minimal function overhead by pre-defining all possible outside.
  6909.  
  6910. const tag = "yt-live-chat-renderer"
  6911. const dummy = lcrDummy;
  6912.  
  6913. const cProto = getProto(dummy);
  6914. if (!cProto || !cProto.attached) {
  6915. console.warn(`proto.attached for ${tag} is unavailable.`);
  6916. return;
  6917. }
  6918.  
  6919. // mightFirstCheckOnYtInit();
  6920. // groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-renderer hacks");
  6921. // console.log("[Begin]");
  6922.  
  6923.  
  6924. if (typeof cProto.playerProgressChanged_ === 'function' && !cProto.playerProgressChanged32_) {
  6925.  
  6926. cProto.playerProgressChanged32_ = cProto.playerProgressChanged_;
  6927.  
  6928.  
  6929. cProto.playerProgressChanged_ = function (a, b, c) {
  6930. // console.log(48117005)
  6931. if (a === 0) a = arguments[0] = Number.MIN_VALUE; // avoid issue dealing with zero value
  6932. playerProgressChangedArg1 = a;
  6933. playerProgressChangedArg2 = b;
  6934. playerProgressChangedArg3 = c;
  6935. const replayBuffer_ = this.replayBuffer_;
  6936. if (replayBuffer_) {
  6937. const replayQueue = replayBuffer_.replayQueue
  6938. if (replayQueue && typeof replayQueue === 'object' && !replayQueue.qe3) {
  6939. replayBuffer_.replayQueue = new Proxy(replayBuffer_.replayQueue, replayQueueProxyHandler);
  6940. }
  6941. }
  6942. Promise.resolve().then(updateTickerCurrentTime);
  6943. return this.playerProgressChanged32_.apply(this, arguments);
  6944. };
  6945.  
  6946. }
  6947.  
  6948. // console.log("[End]");
  6949. // groupEnd();
  6950.  
  6951.  
  6952. };
  6953. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  6954.  
  6955.  
  6956. // console.log('ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION 0002')
  6957.  
  6958. // getLCRDummy() must be called for injection
  6959. getLCRDummy().then(lcrFn2);
  6960.  
  6961. }
  6962.  
  6963. const stackDM = (()=>{
  6964.  
  6965. let cm, stack, mo;
  6966.  
  6967. let firstRun = ()=>{
  6968. cm = mockCommentElement(document.createComment('1'));
  6969. stack = new Set();
  6970. mo = new MutationObserver(()=>{
  6971. const stack_ = stack;
  6972. stack = new Set();
  6973. // for(const value of stack_){
  6974. // Promise.resolve(value).then(f=>f());
  6975. // }
  6976. for(const value of stack_){
  6977. value();
  6978. }
  6979. stack_.clear();
  6980. });
  6981. mo.observe(cm, {characterData: true});
  6982.  
  6983. }
  6984.  
  6985.  
  6986. const stackDM = (f) => {
  6987.  
  6988. if (firstRun) firstRun = firstRun();
  6989. stack.add(f);
  6990. cm.data = `${(cm.data & 1) + 1}`;
  6991. }
  6992. return stackDM;
  6993. })();
  6994. window.stackDM = stackDM;
  6995.  
  6996.  
  6997. const widthReq = (()=>{
  6998.  
  6999. let widthIORes;
  7000. let widthIO;
  7001.  
  7002. let firstRun = () => {
  7003. widthIORes = new WeakMap();
  7004. widthIO = new IntersectionObserver((mutations) => {
  7005. const r = new Map();
  7006. for (const mutation of mutations) {
  7007. r.set(mutation.target, mutation.boundingClientRect);
  7008. }
  7009.  
  7010. for (const [elm, rect] of r) {
  7011. widthIO.unobserve(elm);
  7012. const o = widthIORes.get(elm);
  7013. o && widthIORes.delete(elm);
  7014. const { promise, values } = o || {};
  7015. if (promise && values) {
  7016. values.width = rect.width;
  7017. promise.resolve(values);
  7018. }
  7019. }
  7020. });
  7021. };
  7022.  
  7023. const widthReq = (elm) => {
  7024.  
  7025. if (firstRun) firstRun = firstRun();
  7026.  
  7027. {
  7028. const { promise, values } = widthIORes.get(elm) || {};
  7029. if (promise) return promise;
  7030. }
  7031.  
  7032. const promise = new PromiseExternal();
  7033. widthIORes.set(elm, { promise, values: {} });
  7034. widthIO.unobserve(elm);
  7035. widthIO.observe(elm);
  7036.  
  7037. return promise;
  7038.  
  7039. }
  7040. return widthReq;
  7041. })();
  7042.  
  7043.  
  7044.  
  7045.  
  7046. customElements.whenDefined('yt-live-chat-item-list-renderer').then(() => {
  7047.  
  7048.  
  7049. const tag = "yt-live-chat-item-list-renderer"
  7050. const dummy = document.createElement(tag);
  7051.  
  7052. const cProto = getProto(dummy);
  7053. if (!cProto || !cProto.attached) {
  7054. console.warn(`proto.attached for ${tag} is unavailable.`);
  7055. return;
  7056. }
  7057.  
  7058. mightFirstCheckOnYtInit();
  7059. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-item-list-renderer hacks");
  7060. console1.log("[Begin]");
  7061.  
  7062. const mclp = cProto;
  7063. const _flag0281_ = window._flag0281_;
  7064.  
  7065. try {
  7066. assertor(() => typeof mclp.scrollToBottom_ === 'function');
  7067. assertor(() => typeof mclp.flushActiveItems_ === 'function');
  7068. assertor(() => typeof mclp.canScrollToBottom_ === 'function');
  7069. assertor(() => typeof mclp.setAtBottom === 'function');
  7070. assertor(() => typeof mclp.scrollToBottom66_ === 'undefined');
  7071. assertor(() => typeof mclp.flushActiveItems66_ === 'undefined');
  7072. } catch (e) { }
  7073.  
  7074.  
  7075. try {
  7076. assertor(() => typeof mclp.attached === 'function');
  7077. assertor(() => typeof mclp.detached === 'function');
  7078. assertor(() => typeof mclp.canScrollToBottom_ === 'function');
  7079. assertor(() => typeof mclp.isSmoothScrollEnabled_ === 'function');
  7080. assertor(() => typeof mclp.maybeResizeScrollContainer_ === 'function');
  7081. assertor(() => typeof mclp.refreshOffsetContainerHeight_ === 'function');
  7082. assertor(() => typeof mclp.smoothScroll_ === 'function');
  7083. assertor(() => typeof mclp.resetSmoothScroll_ === 'function');
  7084. } catch (e) { }
  7085.  
  7086. mclp.prDelay171 = null;
  7087.  
  7088. let myk = 0; // showNewItems77_
  7089. let mlf = 0; // flushActiveItems77_
  7090. let myw = 0; // onScrollItems77_
  7091. let mzt = 0; // handleLiveChatActions77_
  7092. let mlg = 0; // delayFlushActiveItemsAfterUserAction11_
  7093. let zarr = null;
  7094.  
  7095. if ((_flag0281_ & 0x2000) == 0) {
  7096.  
  7097. if ((mclp.clearList || 0).length === 0) {
  7098. (_flag0281_ & 0x2) == 0 && assertor(() => fnIntegrity(mclp.clearList, '0.106.50'));
  7099. mclp.clearList66 = mclp.clearList;
  7100. mclp.clearList = function () {
  7101. myk = (myk & 1073741823) + 1;
  7102. mlf = (mlf & 1073741823) + 1;
  7103. myw = (myw & 1073741823) + 1;
  7104. mzt = (mzt & 1073741823) + 1;
  7105. mlg = (mlg & 1073741823) + 1;
  7106. zarr = null;
  7107. this.prDelay171 = null;
  7108. this.clearList66();
  7109. };
  7110. console1.log("clearList", "OK");
  7111. } else {
  7112. console1.log("clearList", "NG");
  7113. }
  7114.  
  7115. }
  7116.  
  7117.  
  7118.  
  7119. let onListRendererAttachedDone = false;
  7120.  
  7121. function setList(itemOffset, items) {
  7122.  
  7123. const isFirstTime = onListRendererAttachedDone === false;
  7124.  
  7125. if (isFirstTime) {
  7126. onListRendererAttachedDone = true;
  7127. Promise.resolve().then(watchUserCSS);
  7128. addCssManaged();
  7129.  
  7130. const isBoostChatEnabled = (window._flag0281_ & 0x40000) === 0x40000;
  7131. if (!isBoostChatEnabled) setupEvents();
  7132. }
  7133.  
  7134. setupStyle(itemOffset, items);
  7135.  
  7136. setupMutObserver(items);
  7137.  
  7138. console.log('[yt-chat] setupMutObserver DONE')
  7139. }
  7140.  
  7141.  
  7142. const deferSeqFns = []; // ensure correct sequence
  7143. let deferSeqFnI = 0;
  7144. const deferCallbackLooper = entry => {
  7145. nextBrowserTick_(() => {
  7146. const { a, b } = entry;
  7147. const cnt = kRef(a);
  7148. if (cnt && b) b.call(cnt);
  7149. entry.a = entry.b = null;
  7150. });
  7151. }
  7152. const deferCallback = async (cnt, callback) => {
  7153. const a = cnt.__weakRef9441__ || (cnt.__weakRef9441__ = mWeakRef(cnt));
  7154. deferSeqFns[deferSeqFnI++] = { a, b: callback };
  7155. if (deferSeqFnI > 1) return;
  7156. const pr288 = cnt.prDelay288;
  7157. await pr288;
  7158. wme.data = `${(wme.data & 7) + 1}`;
  7159. await wmp;
  7160. const l = deferSeqFnI;
  7161. deferSeqFnI = 0;
  7162. for (let i = 0; i < l; i++) {
  7163. const o = deferSeqFns[i];
  7164. deferSeqFns[i] = null;
  7165. Promise.resolve(o).then(deferCallbackLooper);
  7166. }
  7167. };
  7168.  
  7169. let showMoreBtnTransitionTrigg = null;
  7170.  
  7171. mclp.__showMoreBtn_transitionstart011__ = function (evt) {
  7172. showMoreBtnTransitionTrigg = true;
  7173. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7174. if (newVisibility === "visible") {
  7175. const btn = evt.target;
  7176. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7177. }
  7178. };
  7179.  
  7180.  
  7181. mclp.__showMoreBtn_transitionend011__ = function (evt) {
  7182. showMoreBtnTransitionTrigg = true;
  7183. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7184. if (newVisibility === "hidden") {
  7185. const btn = evt.target;
  7186. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7187. }
  7188. };
  7189. mclp.attached419 = async function () {
  7190.  
  7191. if (!this.isAttached) return;
  7192.  
  7193. let maxTrial = 16;
  7194. while (!this.$ || !this.$['item-scroller'] || !this.$['item-offset'] || !this.$['items']) {
  7195. if (--maxTrial < 0 || !this.isAttached) return;
  7196. await nextBrowserTick_();
  7197. // await new Promise(requestAnimationFrame);
  7198. }
  7199.  
  7200. if (this.isAttached !== true) return;
  7201.  
  7202. if (!this.$) {
  7203. console.warn("!this.$");
  7204. return;
  7205. }
  7206. if (!this.$) return;
  7207. /** @type {HTMLElement | null} */
  7208. const itemScroller = this.$['item-scroller'];
  7209. /** @type {HTMLElement | null} */
  7210. const itemOffset = this.$['item-offset'];
  7211. /** @type {HTMLElement | null} */
  7212. const items = this.$['items'];
  7213.  
  7214. if (!itemScroller || !itemOffset || !items) {
  7215. console.warn("items.parentNode !== itemOffset");
  7216. return;
  7217. }
  7218.  
  7219. if (nodeParent(items) !== itemOffset) {
  7220.  
  7221. console.warn("items.parentNode !== itemOffset");
  7222. return;
  7223. }
  7224.  
  7225.  
  7226. if (items.id !== 'items' || itemOffset.id !== "item-offset") {
  7227.  
  7228. console.warn("id incorrect");
  7229. return;
  7230. }
  7231.  
  7232. const isTargetItems = HTMLElement_.prototype.matches.call(items, '#item-offset.style-scope.yt-live-chat-item-list-renderer > #items.style-scope.yt-live-chat-item-list-renderer')
  7233.  
  7234. if (!isTargetItems) {
  7235. console.warn("!isTargetItems");
  7236. return;
  7237. }
  7238.  
  7239. setList(itemOffset, items);
  7240.  
  7241. if (WITH_SCROLL_ANCHOR) this.__itemAnchorColl011__ = itemOffset.getElementsByTagName('item-anchor');
  7242. else this.__itemAnchorColl011__ = null;
  7243.  
  7244.  
  7245.  
  7246. // btn-show-more-transition
  7247. const btn = this.$['show-more'];
  7248. if (btn) {
  7249. if (!this.__showMoreBtn_transitionstart012__) this.__showMoreBtn_transitionstart012__ = this.__showMoreBtn_transitionstart011__.bind(this);
  7250. if (!this.__showMoreBtn_transitionend012__) this.__showMoreBtn_transitionend012__ = this.__showMoreBtn_transitionend011__.bind(this);
  7251. btn.addEventListener('transitionrun', this.__showMoreBtn_transitionstart012__, false);
  7252. btn.addEventListener('transitionstart', this.__showMoreBtn_transitionstart012__, false);
  7253. btn.addEventListener('transitionend', this.__showMoreBtn_transitionend012__, false);
  7254. btn.addEventListener('transitioncancel', this.__showMoreBtn_transitionend012__, false);
  7255. }
  7256.  
  7257. // fix panel height changing issue (ENABLE_OVERFLOW_ANCHOR only)
  7258. if (itemScrollerResizeObserver) itemScrollerResizeObserver.observe(this.itemScroller || this.$['item-scroller']);
  7259.  
  7260. }
  7261.  
  7262. mclp.attached331 = mclp.attached;
  7263. mclp.attached = function () {
  7264. this.attached419 && this.attached419();
  7265. return this.attached331();
  7266. }
  7267.  
  7268. mclp.detached331 = mclp.detached;
  7269.  
  7270. mclp.detached = function () {
  7271. setupMutObserver();
  7272. return this.detached331();
  7273. }
  7274.  
  7275. const t29s = document.querySelectorAll("yt-live-chat-item-list-renderer");
  7276. for (const t29 of t29s) {
  7277. const cnt = insp(t29);
  7278. if (cnt.isAttached === true) {
  7279. cnt.attached419();
  7280. }
  7281. }
  7282.  
  7283. if ((mclp.async || 0).length === 2 && (mclp.cancelAsync || 0).length === 1) {
  7284.  
  7285. assertor(() => fnIntegrity(mclp.async, '2.24.15'));
  7286. assertor(() => fnIntegrity(mclp.cancelAsync, '1.15.8'));
  7287.  
  7288. /** @type {Map<number, any>} */
  7289. const aMap = new Map();
  7290. const mcid = setTimeout(() => 0, 0.625);
  7291. const maid = requestAnimationFrame(() => 0);
  7292. clearTimeout(mcid);
  7293. cancelAnimationFrame(maid);
  7294. const count0 = mcid + maid + 1740;
  7295. let count = count0;
  7296. mclp.async66 = mclp.async;
  7297. mclp.async = function (e, f) {
  7298. // ensure the previous operation is done
  7299. // .async is usually after the time consuming functions like flushActiveItems_ and scrollToBottom_
  7300. const hasF = arguments.length === 2;
  7301. if (count > 1e9) count = count0 + 9;
  7302. const resId = ++count;
  7303. aMap.set(resId, e);
  7304. const pr1 = Promise.all([this.prDelay288, wmp, this.prDelay171, Promise.resolve()]);
  7305. const pr2 = autoTimerFn();
  7306. Promise.race([pr1, pr2]).then(() => {
  7307. const rp = aMap.get(resId);
  7308. if (typeof rp !== 'function') {
  7309. return;
  7310. }
  7311. const asyncEn = function () {
  7312. return aMap.delete(resId) && rp.apply(this, arguments);
  7313. };
  7314. aMap.set(resId, hasF ? this.async66(asyncEn, f) : this.async66(asyncEn));
  7315. });
  7316.  
  7317. return resId;
  7318. }
  7319.  
  7320. mclp.cancelAsync66 = mclp.cancelAsync;
  7321. mclp.cancelAsync = function (resId) {
  7322. if (resId <= count0) {
  7323. this.cancelAsync66(resId);
  7324. } else if (aMap.has(resId)) {
  7325. const rp = aMap.get(resId);
  7326. aMap.delete(resId);
  7327. if (typeof rp !== 'function') {
  7328. this.cancelAsync66(rp);
  7329. }
  7330. }
  7331. }
  7332.  
  7333. console1.log("async", "OK");
  7334. } else {
  7335. console1.log("async", "NG");
  7336. }
  7337.  
  7338.  
  7339. if ((_flag0281_ & 0x2) == 0) {
  7340. if ((mclp.showNewItems_ || 0).length === 0 && ENABLE_NO_SMOOTH_TRANSFORM) {
  7341.  
  7342. assertor(() => fnIntegrity(mclp.showNewItems_, '0.170.79'));
  7343. mclp.showNewItems66_ = mclp.showNewItems_;
  7344. mclp.showNewItems_ = function () {
  7345. //
  7346. }
  7347.  
  7348. console1.log("showNewItems_", "OK");
  7349. } else {
  7350. console1.log("showNewItems_", "NG");
  7351. }
  7352.  
  7353. }
  7354.  
  7355.  
  7356.  
  7357. if ((_flag0281_ & 0x2) == 0) {
  7358. if ((mclp.onScrollItems_ || 0).length === 1) {
  7359.  
  7360. if (mclp.onScrollItems3641_) {
  7361.  
  7362. } else {
  7363. assertor(() => fnIntegrity(mclp.onScrollItems_, '1.17.9'));
  7364.  
  7365. }
  7366.  
  7367. if (typeof mclp.setAtBottom === 'function' && mclp.setAtBottom.length === 0) {
  7368.  
  7369. mclp.setAtBottom217 = mclp.setAtBottom;
  7370. mclp.setAtBottom = function () {
  7371. const v = this.ec217;
  7372. if (typeof v !== 'boolean') return this.setAtBottom217();
  7373. const u = this.atBottom;
  7374. if (u !== v && typeof u === 'boolean') this.atBottom = v;
  7375. // this.atBottom = a.scrollTop >= a.scrollHeight - a.clientHeight - 15
  7376. }
  7377.  
  7378. let lastScrollTarget = null;
  7379. mclp.onScrollItems66_ = mclp.onScrollItems_;
  7380. let callback = () => { };
  7381.  
  7382. // let itemScrollerWR = null;
  7383. let lastEvent = null;
  7384.  
  7385. let io2 = null, io1 = null;
  7386. const io2f = (entries, observer) => {
  7387. const entry = entries[entries.length - 1];
  7388. if (entry.target !== lastScrollTarget) return;
  7389. callback(entry);
  7390. };
  7391. const io1f = (entries, observer) => {
  7392. const entry = entries[entries.length - 1];
  7393. observer.unobserve(entry.target);
  7394. if (entry.target !== lastScrollTarget) return;
  7395. lastScrollTarget = null;
  7396. callback(entry);
  7397. };
  7398. mclp.onScrollItems3885cb2_ = function (entry) {
  7399. const v = (entry.isIntersecting === true);
  7400. this.ec217 = v;
  7401. this.onScrollItems66_(lastEvent);
  7402. this.ec217 = null;
  7403. }
  7404. mclp.onScrollItems3885cb1_ = function (entry) {
  7405. const v = (entry.intersectionRatio > 0.98);
  7406. this.ec217 = v;
  7407. this.onScrollItems66_(lastEvent);
  7408. this.ec217 = null;
  7409. };
  7410.  
  7411. mclp.onScrollItems_ = function (evt) {
  7412.  
  7413. if (evt === lastEvent) return;
  7414. if (evt && lastEvent && evt.timeStamp === lastEvent.timeStamp) return;
  7415. lastEvent = evt;
  7416. const ytRendererBehavior = this.ytRendererBehavior || 0;
  7417. if (typeof ytRendererBehavior.onScroll === 'function') ytRendererBehavior.onScroll(evt);
  7418. const coll = this.__itemAnchorColl011__;
  7419. if (coll) {
  7420. const anchorElement = coll.length === 1 ? coll[0] : null;
  7421. if (lastScrollTarget !== anchorElement) {
  7422. if (io2) io2.disconnect();
  7423. lastScrollTarget = anchorElement;
  7424. if (anchorElement) {
  7425. if (!this.onScrollItems3886cb2_) this.onScrollItems3886cb2_ = this.onScrollItems3885cb2_.bind(this);
  7426. callback = this.onScrollItems3886cb2_;
  7427. if (!io2) io2 = new IntersectionObserver(io2f);
  7428. io2.observe(anchorElement);
  7429. }
  7430. }
  7431. } else {
  7432. const items = this.$.items;
  7433. if (!items) return this.onScrollItems66_();
  7434. const lastComponent = lastComponentChildFn(items);
  7435. if (!lastComponent) return this.onScrollItems66_();
  7436. if (lastScrollTarget === lastComponent) return;
  7437. lastScrollTarget = lastComponent;
  7438.  
  7439. if (io1) io1.disconnect();
  7440. if (!this.onScrollItems3886cb1_) this.onScrollItems3886cb1_ = this.onScrollItems3885cb1_.bind(this);
  7441. callback = this.onScrollItems3886cb1_;
  7442. if (!io1) io1 = new IntersectionObserver(io1f);
  7443. io1.observe(lastComponent);
  7444. }
  7445. };
  7446.  
  7447. }
  7448.  
  7449. console1.log("onScrollItems_", "OK");
  7450. } else {
  7451. console1.log("onScrollItems_", "NG");
  7452. }
  7453. }
  7454.  
  7455.  
  7456. if ((_flag0281_ & 0x40) == 0) {
  7457.  
  7458. if (ENABLE_NO_SMOOTH_TRANSFORM && SUPPRESS_refreshOffsetContainerHeight_ && typeof mclp.refreshOffsetContainerHeight_ === 'function' && !mclp.refreshOffsetContainerHeight26_ && mclp.refreshOffsetContainerHeight_.length === 0) {
  7459. assertor(() => fnIntegrity(mclp.refreshOffsetContainerHeight_, '0.31.21'));
  7460. mclp.refreshOffsetContainerHeight26_ = mclp.refreshOffsetContainerHeight_;
  7461. mclp.refreshOffsetContainerHeight_ = function () {
  7462. // var a = this.itemScroller.clientHeight;
  7463. // this.itemOffset.style.height = this.items.clientHeight + "px";
  7464. // this.bottomAlignMessages && (this.itemOffset.style.minHeight = a + "px")
  7465. }
  7466. console1.log("refreshOffsetContainerHeight_", "OK");
  7467. } else {
  7468. console1.log("refreshOffsetContainerHeight_", "NG");
  7469. }
  7470.  
  7471. }
  7472.  
  7473. if ((_flag0281_ & 0x2000) == 0) {
  7474. if ((mclp.flushActiveItems_ || 0).length === 0) {
  7475.  
  7476. if ((_flag0281_ & 0x2) == 0) {
  7477.  
  7478. const sfi = fnIntegrity(mclp.flushActiveItems_);
  7479.  
  7480. if (sfi === '0.156.86') {
  7481.  
  7482. // https://www.youtube.com/s/desktop/2cf5dafc/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  7483.  
  7484.  
  7485. // f.flushActiveItems_ = function() {
  7486. // var a = this;
  7487. // if (this.activeItems_.length > 0)
  7488. // if (this.canScrollToBottom_()) {
  7489. // var b = Math.max(this.visibleItems.length + this.activeItems_.length - this.data.maxItemsToDisplay, 0);
  7490. // b && this.splice("visibleItems", 0, b);
  7491. // if (this.isSmoothScrollEnabled_() || this.dockableMessages.length)
  7492. // this.preinsertHeight_ = this.items.clientHeight;
  7493. // this.activeItems_.unshift("visibleItems");
  7494. // try {
  7495. // this.push.apply(this, this.activeItems_)
  7496. // } catch (c) {
  7497. // $m(c)
  7498. // }
  7499. // this.activeItems_ = [];
  7500. // this.isSmoothScrollEnabled_() ? this.canScrollToBottom_() && wy(function() {
  7501. // a.showNewItems_()
  7502. // }) : wy(function() {
  7503. // a.refreshOffsetContainerHeight_();
  7504. // a.maybeScrollToBottom_()
  7505. // })
  7506. // } else
  7507. // this.activeItems_.length > this.data.maxItemsToDisplay && this.activeItems_.splice(0, this.activeItems_.length - this.data.maxItemsToDisplay)
  7508. // }
  7509. } else if (sfi === '0.150.84') {
  7510. // https://www.youtube.com/s/desktop/e4d15d2c/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  7511. // var b = Math.max(this.visibleItems.length + this.activeItems_.length - this.data.maxItemsToDisplay, 0);
  7512. // b && this.splice("visibleItems", 0, b);
  7513. // if (this.isSmoothScrollEnabled_() || this.dockableMessages.length)
  7514. // this.preinsertHeight_ = this.items.clientHeight;
  7515. // this.activeItems_.unshift("visibleItems");
  7516. // try {
  7517. // this.push.apply(this, this.activeItems_)
  7518. // } catch (c) {
  7519. // nm(c)
  7520. // }
  7521. // this.activeItems_ = [];
  7522. // this.isSmoothScrollEnabled_() ? this.canScrollToBottom_() && zQ(function() {
  7523. // a.showNewItems_()
  7524. // }) : zQ(function() {
  7525. // a.maybeScrollToBottom_()
  7526. // })
  7527. } else if (sfi === '0.137.81' || sfi === '0.138.81') {
  7528. // e.g. https://www.youtube.com/yts/jsbin/live_chat_polymer-vflCyWEBP/live_chat_polymer.js
  7529. } else {
  7530. assertor(() => fnIntegrity(mclp.flushActiveItems_, '0.157.86'))
  7531. || logFn('mclp.flushActiveItems_', mclp.flushActiveItems_)();
  7532. }
  7533. }
  7534.  
  7535. let hasMoreMessageState = !ENABLE_SHOW_MORE_BLINKER ? -1 : 0;
  7536.  
  7537. mclp.flushActiveItems66a_ = mclp.flushActiveItems_;
  7538. // let lastLastRow = null;
  7539.  
  7540.  
  7541. const preloadFn = (acItems) => {
  7542. let waitFor = [];
  7543. /** @type {Set<string>} */
  7544. const imageLinks = new Set();
  7545. imageLinks.add = imageLinks.addOriginal || imageLinks.add;
  7546.  
  7547. if (ENABLE_PRELOAD_THUMBNAIL || EMOJI_IMAGE_SINGLE_THUMBNAIL || AUTHOR_PHOTO_SINGLE_THUMBNAIL) {
  7548. for (const item of acItems) {
  7549. fixLiveChatItem(item, imageLinks);
  7550. }
  7551. }
  7552. if (ENABLE_PRELOAD_THUMBNAIL && kptPF !== null && (kptPF & (8 | 4)) && imageLinks.size > 0) {
  7553.  
  7554. // reference: https://github.com/Yuanfang-fe/Blog-X/issues/34
  7555. const rel = kptPF & 8 ? 'subresource' : kptPF & 16 ? 'preload' : kptPF & 4 ? 'prefetch' : '';
  7556. // preload performs the high priority fetching.
  7557. // prefetch delays the chat display if the video resoruce is demanding.
  7558.  
  7559. if (rel) {
  7560.  
  7561. imageLinks.forEach(imageLink => {
  7562. let d = false;
  7563. if (SKIP_PRELOAD_EMOJI && imageLink.includes('.ggpht.com/')) return;
  7564. const isEmoji = imageLink.includes('/emoji/');
  7565. const pretechedSet = isEmoji ? emojiPrefetched : authorPhotoPrefetched;
  7566. if (!pretechedSet.has(imageLink)) {
  7567. pretechedSet.add(imageLink);
  7568. d = true;
  7569. }
  7570. if (d) {
  7571. waitFor.push(linker(null, rel, imageLink, 'image'));
  7572.  
  7573. }
  7574. })
  7575.  
  7576. }
  7577.  
  7578. }
  7579. imageLinks.clear();
  7580.  
  7581. return async () => {
  7582. if (waitFor.length > 0) {
  7583. await Promise.race([new Promise(r => setTimeout(r, 250)), Promise.all(waitFor)]);
  7584. }
  7585. waitFor.length = 0;
  7586. waitFor = null;
  7587. };
  7588.  
  7589. };
  7590.  
  7591. if (ENABLE_CHAT_MESSAGES_BOOSTED_STAMPING && `${mclp.flushActiveItems_}`.includes("this.push.apply(this,this.activeItems_)") && `${mclp.flushActiveItems_}`.includes(`this.splice("visibleItems",0,`)
  7592. && !cProto.notifyPath371 && !cProto.proceedStampDomArraySplices381_
  7593. && !cProto.stampDomArraySplices381_ && !cProto.push377 && !cProto.splice377) {
  7594.  
  7595. {
  7596.  
  7597. rendererStamperFactory(cProto, {
  7598. key: 'proceedStampDomArraySplices381_',
  7599. stamperDomClass: 'style-scope yt-live-chat-item-list-renderer yt-live-chat-item-list-stampdom',
  7600. preloadFn
  7601. });
  7602. cProto.notifyPath371 = cProto.notifyPath;
  7603.  
  7604. cProto.stampDomArraySplices381_ = cProto.stampDomArraySplices_;
  7605.  
  7606. if (typeof cProto.stampDomArraySplices381_ === 'function' && cProto.stampDomArraySplices381_.length >= 3) {
  7607.  
  7608. cProto.stampDomArraySplices_ = function (a, b, c) {
  7609. if (a === 'visibleItems' && b === 'items' && (c || 0).indexSplices) {
  7610. // if (this.ec388) {
  7611. const indexSplices = c.indexSplices;
  7612. if (indexSplices.length === 1 || typeof indexSplices.length === "undefined") {
  7613. const indexSplice = indexSplices[0] || indexSplices;
  7614. if (indexSplice.type === 'splice' && (indexSplice.addedCount >= 1 || (indexSplice.removed || []).length >= 1)) {
  7615. // console.log(1059, a, b, indexSplice);
  7616. if (this.proceedStampDomArraySplices381_(a, b, indexSplice)) return;
  7617. }
  7618. }
  7619. // } else {
  7620. // console.warn('stampDomArraySplices_ warning', ...arguments);
  7621. // }
  7622. }
  7623. return this.stampDomArraySplices381_(...arguments);
  7624. }
  7625. } else {
  7626. console.warn('0xF0230 Function Signature Changed');
  7627. }
  7628.  
  7629. cProto.stampDomArray366_ = cProto.stampDomArray_;
  7630.  
  7631. if (typeof cProto.stampDomArray366_ === 'function' && cProto.stampDomArray366_.length >= 5) {
  7632. cProto.stampDomArray_ = function (items, containerId, componentConfig, rxConfig, shouldCallback, isStableList) {
  7633. const isTickerRendering = items === this.tickerItems && containerId === 'ticker-items';
  7634. const isMessageListRendering = items === this.visibleItems && containerId === 'items';
  7635.  
  7636. if (!isTickerRendering && !isMessageListRendering) {
  7637. console.log('stampDomArray_ warning 0xF501', ...arguments)
  7638. return this.stampDomArray366_(...arguments);
  7639. }
  7640.  
  7641. const container = (this.$ || 0)[containerId];
  7642. if (!container) {
  7643. console.log('stampDomArray_ warning 0xF502', ...arguments)
  7644. return this.stampDomArray366_(...arguments);
  7645. }
  7646.  
  7647. if (container[sFirstElementChild] === null && items.length === 0) {
  7648.  
  7649. } else {
  7650. const cTag = isTickerRendering ? 'tickerItems' : 'visibleItems';
  7651. this.proceedStampDomArraySplices381_(cTag, containerId, {
  7652. addedCount: items.length,
  7653. removedCount: container.childElementCount
  7654. });
  7655. }
  7656.  
  7657. const f = () => {
  7658. this.markDirty && this.markDirty();
  7659. const detail = {
  7660. container
  7661. };
  7662. shouldCallback && this.hostElement.dispatchEvent(new CustomEvent("yt-rendererstamper-finished", {
  7663. bubbles: !0,
  7664. cancelable: !1,
  7665. composed: !0,
  7666. detail
  7667. }));
  7668. detail.container = null;
  7669. };
  7670.  
  7671. if (this.ec389pr) {
  7672. this.ec389pr.then(f)
  7673. } else {
  7674. f();
  7675. }
  7676.  
  7677. };
  7678. } else {
  7679. console.warn('0xF0230 Function Signature Changed');
  7680. }
  7681.  
  7682. mclp.push377 = mclp.push;
  7683. mclp.splice377 = mclp.splice;
  7684.  
  7685. const emptyArr = [];
  7686. emptyArr.push = () => 0;
  7687. emptyArr.unshift = () => 0;
  7688. emptyArr.pop = () => void 0;
  7689. emptyArr.shift = () => void 0;
  7690. emptyArr.splice = () => void 0;
  7691. emptyArr.slice = function () { return this };
  7692.  
  7693. if (typeof mclp.push377 === 'function' && mclp.push377.length >= 1) {
  7694. mclp.push = function (cTag, ...fnArgs) {
  7695. if (cTag !== 'visibleItems' || !fnArgs.length || !fnArgs[0]) return this.push377(...arguments);
  7696. const arr = this.visibleItems;
  7697. const len = arr.length;
  7698. const newTotalLen = arr.push(...fnArgs);
  7699. const addedCount = fnArgs.length;
  7700. // console.log('push')
  7701. this.proceedStampDomArraySplices381_('visibleItems', 'items', {
  7702. index: len, addedCount: addedCount, removedCount: 0
  7703. })
  7704. return newTotalLen;
  7705. }
  7706. } else {
  7707. console.warn('0xF0230 Function Signature Changed');
  7708. }
  7709.  
  7710. if (typeof mclp.splice377 === 'function' && mclp.splice377.length >= 1) {
  7711. mclp.splice = function (cTag, ...fnArgs) {
  7712. if (cTag !== 'visibleItems' || !fnArgs.length || (fnArgs.length === 2 && !fnArgs[1]) || (fnArgs.length > 2 && !fnArgs[2])) return this.splice377(...arguments);
  7713. const arr = this.visibleItems;
  7714. const removed = arr.splice(...fnArgs);
  7715. const removedCount = removed.length;
  7716. const addedCount = (fnArgs.length > 2 ? fnArgs.length - 2 : 0);
  7717. if (fnArgs.length >= 2 && removedCount !== fnArgs[1]) {
  7718. console.warn(`incorrect splice count. expected = ${fnArgs[1]}; actual = ${removedCount}`);
  7719. }
  7720. // console.log('splice')
  7721. this.proceedStampDomArraySplices381_('visibleItems', 'items', {
  7722. index: fnArgs[0], addedCount: addedCount, removedCount
  7723. })
  7724. return removed;
  7725. }
  7726. } else {
  7727. console.warn('0xF0230 Function Signature Changed');
  7728. }
  7729.  
  7730. }
  7731.  
  7732. mclp.flushActiveItemsFix001_ = function () {
  7733.  
  7734. // fix YouTube wrong code
  7735. // var b = Math.max(this.visibleItems.length + this.activeItems_.length - this.data.maxItemsToDisplay, 0);
  7736. // b && this.splice("visibleItems", 0, b);
  7737. // e.g. 0 + 99 - 90 = 9
  7738.  
  7739. const data = this.data;
  7740. if (!data) return;
  7741. const visibleItems = this.visibleItems;
  7742. const activeItems_ = this.activeItems_;
  7743. if (!visibleItems || !activeItems_) return;
  7744. const viLen = visibleItems.length;
  7745. const aiLen = activeItems_.length;
  7746. const maxDisplayLen = data.maxItemsToDisplay;
  7747. if (!maxDisplayLen) return;
  7748. if (viLen + aiLen > maxDisplayLen) {
  7749. if (aiLen > maxDisplayLen) activeItems_.splice(0, aiLen - maxDisplayLen);
  7750. // visibleItems splice done by original flushActiveItems_
  7751. }
  7752. }
  7753.  
  7754. mclp.flushActiveItems3641_ = mclp.flushActiveItems_;
  7755.  
  7756. mclp.__moreItemButtonBlinkingCheck183__ = function () {
  7757. const hasPendingItems = (this.activeItems_ && this.activeItems_.length > 0) ? 1 : 0;
  7758. const shouldChange = (hasMoreMessageState === (1 - hasPendingItems));
  7759. if (shouldChange) {
  7760. hasMoreMessageState = hasPendingItems;
  7761. const showMore = (this.$ || 0)['show-more'];
  7762. if (showMore) {
  7763. showMore.classList.toggle('has-new-messages-miuzp', hasPendingItems ? true : false);
  7764. }
  7765. }
  7766. }
  7767.  
  7768. let ps00 = false;
  7769. mclp.flushActiveItems_ = function () {
  7770. if (ps00) return;
  7771. // console.log('flushActiveItems_')
  7772. ps00 = true;
  7773. deferCallback(this, () => {
  7774. ps00 = false;
  7775. // console.log('flushActiveItems3641_')
  7776. if (this.activeItems_.length > 0) {
  7777. const data = this.data;
  7778. if (data) {
  7779. if (data.maxItemsToDisplay > MAX_ITEMS_FOR_TOTAL_DISPLAY) data.maxItemsToDisplay = MAX_ITEMS_FOR_TOTAL_DISPLAY;
  7780. this.flushActiveItemsFix001_(); // bug fix
  7781. this.flushActiveItems3641_();
  7782. if (ENABLE_SHOW_MORE_BLINKER) {
  7783. this.__moreItemButtonBlinkingCheck183__(); // blink the button if there are activeItems remaining.
  7784. }
  7785. }
  7786. }
  7787. }).catch(console.warn);
  7788. };
  7789.  
  7790. mclp.showNewItems3641_ = mclp.showNewItems_;
  7791. mclp.refreshOffsetContainerHeight3641_ = mclp.refreshOffsetContainerHeight_;
  7792. mclp.maybeScrollToBottom3641_ = mclp.maybeScrollToBottom_;
  7793.  
  7794. let ps01 = false;
  7795. mclp.showNewItems_ = function () {
  7796. if (ps01) return;
  7797. // console.log('showNewItems_')
  7798. ps01 = true;
  7799. deferCallback(this, () => {
  7800. ps01 = false;
  7801. this.showNewItems3641_();
  7802. }).catch(console.warn);
  7803. };
  7804.  
  7805. if (!ENABLE_NO_SMOOTH_TRANSFORM && !mclp.refreshOffsetContainerHeight26_) {
  7806. let ps02 = false;
  7807. mclp.refreshOffsetContainerHeight_ = function () {
  7808. if (ps02) return;
  7809. // console.log('refreshOffsetContainerHeight_')
  7810. ps02 = true;
  7811. deferCallback(this, () => {
  7812. ps02 = false;
  7813. this.refreshOffsetContainerHeight3641_();
  7814. }).catch(console.warn);
  7815. };
  7816. }
  7817.  
  7818.  
  7819. let ps03 = false;
  7820. mclp.maybeScrollToBottom_ = function () {
  7821. if (ps03) return;
  7822. // console.log('maybeScrollToBottom_')
  7823. ps03 = true;
  7824. deferCallback(this, () => {
  7825. ps03 = false;
  7826. if (this.atBottom === true) {
  7827.  
  7828. // if (itemsResizeObserverAttached !== true && this.atBottom === true) {
  7829. // // fallback for old browser
  7830. // const itemScroller = this.itemScroller || this.$['item-scroller'] || this.querySelector('#item-scroller') || 0;
  7831. // if (itemScroller.scrollTop === 0) {
  7832. // resizeObserverFallback.observe(itemScroller);
  7833. // }
  7834. // }
  7835. } else {
  7836.  
  7837. this.maybeScrollToBottom3641_();
  7838. }
  7839. }).catch(console.warn);
  7840. };
  7841.  
  7842. mclp.onScrollItems3641_ = mclp.onScrollItems_;
  7843. mclp.maybeResizeScrollContainer3641_ = mclp.maybeResizeScrollContainer_;
  7844. mclp.handleLiveChatActions3641_ = mclp.handleLiveChatActions_;
  7845.  
  7846. let ps11 = false;
  7847. mclp.onScrollItems_ = function (a) {
  7848. if (ps11) return;
  7849. // console.log('onScrollItems_')
  7850. ps11 = true;
  7851. deferCallback(this, () => {
  7852. ps11 = false;
  7853. this.onScrollItems3641_(a);
  7854. }).catch(console.warn);
  7855. };
  7856.  
  7857. if (!ENABLE_NO_SMOOTH_TRANSFORM) { // no function for ENABLE_NO_SMOOTH_TRANSFORM
  7858. let ps12 = false;
  7859. mclp.maybeResizeScrollContainer_ = function (a) {
  7860. if (ps12) return;
  7861. // console.log('maybeResizeScrollContainer_')
  7862. ps12 = true;
  7863. deferCallback(this, () => {
  7864. ps12 = false;
  7865. this.maybeResizeScrollContainer3641_(a);
  7866. }).catch(console.warn);
  7867. };
  7868. }
  7869.  
  7870. }
  7871.  
  7872. console1.log("flushActiveItems_", "OK");
  7873. } else {
  7874. console1.log("flushActiveItems_", "NG");
  7875. }
  7876. }
  7877.  
  7878.  
  7879. if ((_flag0281_ & 0x40) == 0 ) {
  7880.  
  7881.  
  7882. let showBtnLastState = null;
  7883. let lastAtBottomState = null;
  7884. // let showMoreBtnTransitionTrigg = false;
  7885. mclp.atBottomChanged314_ = mclp.atBottomChanged_;
  7886. mclp.atBottomChanged_ = function () {
  7887.  
  7888. const currentAtBottomState = this.atBottom;
  7889. if(lastAtBottomState === currentAtBottomState) return;
  7890. lastAtBottomState = currentAtBottomState;
  7891.  
  7892. // console.log(1289, showMoreBtnTransitionTrigg)
  7893.  
  7894. /*
  7895. if (!this.___btn3848___) {
  7896. this.___btn3848___ = true;
  7897. const btn = ((this || 0).$ || 0)["show-more"] || 0;
  7898. if (btn) {
  7899. btn.addEventListener('transitionstart', (evt) => {
  7900. showMoreBtnTransitionTrigg = true;
  7901. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7902. if (newVisibility === "visible") {
  7903. const btn = evt.target;
  7904. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7905. }
  7906. });
  7907. btn.addEventListener('transitionend', (evt) => {
  7908. showMoreBtnTransitionTrigg = true;
  7909. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7910. if (newVisibility === "hidden") {
  7911. const btn = evt.target;
  7912. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7913. }
  7914. });
  7915. btn.addEventListener('transitioncancel', (evt) => {
  7916. showMoreBtnTransitionTrigg = true;
  7917. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7918. if (newVisibility === "hidden") {
  7919. const btn = evt.target;
  7920. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7921. }
  7922. });
  7923. }
  7924. }
  7925. */
  7926.  
  7927. // btn-show-more-transition
  7928. if (showMoreBtnTransitionTrigg) return;
  7929.  
  7930. const btn = ((this || 0).$ || 0)["show-more"] || 0;
  7931. if (!btn) return this.atBottomChanged314_();
  7932.  
  7933. const showBtnCurrentState = btn.hasAttribute('disabled');
  7934. if (showBtnLastState === showBtnCurrentState) return;
  7935. showBtnLastState = showBtnCurrentState;
  7936.  
  7937. if (this.visibleItems.length === 0) {
  7938. if (this.atBottom === true) {
  7939. btn.setAttribute('disabled', '');
  7940. showBtnLastState = true;
  7941. }
  7942. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7943. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7944. return;
  7945. }
  7946.  
  7947. nextBrowserTick_(() => {
  7948.  
  7949. if (showMoreBtnTransitionTrigg) return;
  7950.  
  7951. // fallback
  7952.  
  7953. // const isAtBottom = this.atBottom === true;
  7954. // if (isAtBottom) {
  7955. // if (!this.hideShowMoreAsync_) {
  7956. // this.hideShowMoreAsync_ = setTimeoutX0(function () {
  7957. // const btn = ((this || 0).$ || 0)["#show-more"] || 0;
  7958. // if (btn) btn.style.visibility = "hidden";
  7959. // }, 200 - 0.125);
  7960. // }
  7961. // } else {
  7962. // if (this.hideShowMoreAsync_) {
  7963. // clearTimeoutX0(this.hideShowMoreAsync_);
  7964. // this.hideShowMoreAsync_ = null;
  7965. // }
  7966. // const btn = ((this || 0).$ || 0)["#show-more"] || 0;
  7967. // if (btn) btn.style.visibility = "visible";
  7968. // }
  7969.  
  7970. const btn = ((this || 0).$ || 0)["show-more"] || 0;
  7971. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7972.  
  7973. if (newVisibility === "hidden") {
  7974. console.warn('show-more-btn no transition')
  7975. }
  7976.  
  7977. if (btn && btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7978.  
  7979. });
  7980.  
  7981. };
  7982.  
  7983. }
  7984.  
  7985.  
  7986.  
  7987. if ((_flag0281_ & 0x2) == 0) {
  7988. if ((mclp.handleLiveChatActions_ || 0).length === 1) {
  7989.  
  7990. const sfi = fnIntegrity(mclp.handleLiveChatActions_);
  7991. // handleLiveChatActions66_
  7992. if (sfi === '1.40.20') {
  7993. // https://www.youtube.com/s/desktop/c01ea7e3/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  7994.  
  7995.  
  7996. // f.handleLiveChatActions_ = function(a) {
  7997. // var b = this;
  7998. // a.length && (a.forEach(this.handleLiveChatAction_, this),
  7999. // this.maybeResizeScrollContainer_(a),
  8000. // this.flushActiveItems_(),
  8001. // $u(function() {
  8002. // b.maybeScrollToBottom_()
  8003. // }))
  8004. // }
  8005.  
  8006. } else if (sfi === '1.39.20') {
  8007. // TBC
  8008. } else if (sfi === '1.31.17') {
  8009. // original
  8010. } else if (mclp.handleLiveChatActions3641_){
  8011. } else {
  8012. assertor(() => fnIntegrity(mclp.handleLiveChatActions_, '1.40.20'))
  8013. || logFn('mclp.handleLiveChatActions_', mclp.handleLiveChatActions_)();
  8014. }
  8015.  
  8016. mclp.handleLiveChatActions66_ = mclp.handleLiveChatActions_;
  8017.  
  8018. mclp.handleLiveChatActions_ = function (arr) {
  8019.  
  8020. try {
  8021. preprocessChatLiveActions(arr);
  8022. } catch (e) {
  8023. console.warn(e);
  8024. }
  8025.  
  8026. this.handleLiveChatActions66_(arr);
  8027.  
  8028. resistanceUpdateFn_(true);
  8029. }
  8030. console1.log("handleLiveChatActions_", "OK");
  8031. } else {
  8032. console1.log("handleLiveChatActions_", "NG");
  8033. }
  8034. }
  8035.  
  8036. // we do not need to do user interaction check for Boost Chat (0x40000)
  8037. const noScrollToBottomCheckForBoostChat = (_flag0281_ & 0x40000) === 0x40000;
  8038.  
  8039. if (noScrollToBottomCheckForBoostChat === false) {
  8040.  
  8041. mclp.hasUserJustInteracted11_ = () => {
  8042. const t = dateNow();
  8043. return (t - lastWheel < 80) || currentMouseDown || currentTouchDown || (t - lastUserInteraction < 80);
  8044. }
  8045.  
  8046. if ((mclp.canScrollToBottom_ || 0).length === 0 && !mclp.canScrollToBottom157_) {
  8047.  
  8048. assertor(() => fnIntegrity(mclp.canScrollToBottom_, '0.9.5'));
  8049.  
  8050. mclp.canScrollToBottom157_ = mclp.canScrollToBottom_;
  8051. mclp.canScrollToBottom_ = function () {
  8052. return this.canScrollToBottom157_() && !this.hasUserJustInteracted11_();
  8053. }
  8054.  
  8055. console1.log("canScrollToBottom_", "OK");
  8056.  
  8057.  
  8058. } else {
  8059. console1.log("canScrollToBottom_", "NG");
  8060. }
  8061.  
  8062. }
  8063.  
  8064. if (ENABLE_NO_SMOOTH_TRANSFORM) {
  8065.  
  8066. mclp.isSmoothScrollEnabled_ = function () {
  8067. return false;
  8068. }
  8069.  
  8070. mclp.maybeResizeScrollContainer_ = function () {
  8071. //
  8072. }
  8073.  
  8074. mclp.refreshOffsetContainerHeight_ = function () {
  8075. //
  8076. }
  8077.  
  8078. mclp.smoothScroll_ = function () {
  8079. //
  8080. }
  8081.  
  8082. mclp.resetSmoothScroll_ = function () {
  8083. //
  8084. }
  8085. console1.log("ENABLE_NO_SMOOTH_TRANSFORM", "OK");
  8086. } else {
  8087. console1.log("ENABLE_NO_SMOOTH_TRANSFORM", "NG");
  8088. }
  8089.  
  8090. if ((_flag0281_ & 0x8) == 0) {
  8091.  
  8092.  
  8093. if (typeof mclp.forEachItem_ === 'function' && !mclp.forEachItem66_ && skipErrorForhandleAddChatItemAction_ && mclp.forEachItem_.length === 1) {
  8094.  
  8095. mclp.forEachItem66_ = mclp.forEachItem_;
  8096. mclp.forEachItem_ = function (a) {
  8097.  
  8098. if ((this._flag0281_ & 0x8) == 0x8) return this.forEachItem66_(a);
  8099.  
  8100. // ƒ (a){this.visibleItems.forEach(a.bind(this,"visibleItems"));this.activeItems_.forEach(a.bind(this,"activeItems_"))}
  8101.  
  8102. try {
  8103.  
  8104. let items801 = false;
  8105. if (typeof a === 'function') {
  8106. const items = this.items;
  8107. if (items instanceof HTMLDivElement) {
  8108. const ev = this.visibleItems;
  8109. const ea = this.activeItems_;
  8110. if (ev && ea && ev.length >= 0 && ea.length >= 0) {
  8111. items801 = items;
  8112. }
  8113. }
  8114. }
  8115.  
  8116. if (items801) {
  8117. items801.__children801__ = 1;
  8118. const res = this.forEachItem66_(a);
  8119. items801.__children801__ = 0;
  8120. return res;
  8121. }
  8122.  
  8123. } catch (e) { }
  8124. return this.forEachItem66_(a);
  8125.  
  8126.  
  8127. // this.visibleItems.forEach((val, idx, arr)=>{
  8128. // a.call(this, 'visibleItems', val, idx, arr);
  8129. // });
  8130.  
  8131. // this.activeItems_.forEach((val, idx, arr)=>{
  8132. // a.call(this, 'activeItems_', val, idx, arr);
  8133. // });
  8134.  
  8135.  
  8136.  
  8137. }
  8138.  
  8139.  
  8140. }
  8141.  
  8142. }
  8143.  
  8144. if (typeof mclp.handleAddChatItemAction_ === 'function' && !mclp.handleAddChatItemAction66_ && FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION && (EMOJI_IMAGE_SINGLE_THUMBNAIL || AUTHOR_PHOTO_SINGLE_THUMBNAIL)) {
  8145.  
  8146. mclp.handleAddChatItemAction66_ = mclp.handleAddChatItemAction_;
  8147. mclp.handleAddChatItemAction_ = function (a) {
  8148. try {
  8149. if (a && typeof a === 'object' && !('length' in a)) {
  8150. fixLiveChatItem(a.item, null);
  8151. console.assert(arguments[0] === a);
  8152. }
  8153. } catch (e) { console.warn(e) }
  8154. let res;
  8155. if (skipErrorForhandleAddChatItemAction_) { // YouTube Native Engine Issue
  8156. try {
  8157. res = this.handleAddChatItemAction66_.apply(this, arguments);
  8158. } catch (e) {
  8159. if (e && (e.message || '').includes('.querySelector(')) {
  8160. console.log("skipErrorForhandleAddChatItemAction_", e.message);
  8161. } else {
  8162. throw e;
  8163. }
  8164. }
  8165. } else {
  8166. res = this.handleAddChatItemAction66_.apply(this, arguments);
  8167. }
  8168. return res;
  8169. }
  8170.  
  8171. if (FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION) console1.log("handleAddChatItemAction_ [ FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION ]", "OK");
  8172. } else {
  8173.  
  8174. if (FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION) console1.log("handleAddChatItemAction_ [ FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION ]", "OK");
  8175. }
  8176.  
  8177.  
  8178. if (typeof mclp.handleReplaceChatItemAction_ === 'function' && !mclp.handleReplaceChatItemAction66_ && FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT && (EMOJI_IMAGE_SINGLE_THUMBNAIL || AUTHOR_PHOTO_SINGLE_THUMBNAIL)) {
  8179.  
  8180. mclp.handleReplaceChatItemAction66_ = mclp.handleReplaceChatItemAction_;
  8181. mclp.handleReplaceChatItemAction_ = function (a) {
  8182. try {
  8183. if (a && typeof a === 'object' && !('length' in a)) {
  8184. fixLiveChatItem(a.replacementItem, null);
  8185. console.assert(arguments[0] === a);
  8186. }
  8187. } catch (e) { console.warn(e) }
  8188. return this.handleReplaceChatItemAction66_.apply(this, arguments);
  8189. }
  8190.  
  8191. if (FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT) console1.log("handleReplaceChatItemAction_ [ FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT ]", "OK");
  8192. } else {
  8193.  
  8194. if (FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT) console1.log("handleReplaceChatItemAction_ [ FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT ]", "OK");
  8195. }
  8196.  
  8197. console1.log("[End]");
  8198. groupEnd();
  8199.  
  8200. }).catch(console.warn);
  8201.  
  8202.  
  8203. const tickerContainerSetAttribute = function (attrName, attrValue) { // ensure '14.30000001%'.toFixed(1)
  8204.  
  8205. let yd = (this.__dataHost || insp(this).__dataHost || 0).__data;
  8206.  
  8207. if (arguments.length === 2 && attrName === 'style' && yd && attrValue) {
  8208.  
  8209. // let v = yd.containerStyle.privateDoNotAccessOrElseSafeStyleWrappedValue_;
  8210. let v = `${attrValue}`;
  8211. // conside a ticker is 101px width
  8212. // 1% = 1.01px
  8213. // 0.2% = 0.202px
  8214.  
  8215.  
  8216. const ratio1 = (yd.ratio * 100);
  8217. if (ratio1 > -1) { // avoid NaN
  8218.  
  8219. // countdownDurationMs
  8220. // 600000 - 0.2% <1% = 6s> <0.2% = 1.2s>
  8221. // 300000 - 0.5% <1% = 3s> <0.5% = 1.5s>
  8222. // 150000 - 1% <1% = 1.5s>
  8223. // 75000 - 2% <1% =0.75s > <2% = 1.5s>
  8224. // 30000 - 5% <1% =0.3s > <5% = 1.5s>
  8225.  
  8226. // 99px * 5% = 4.95px
  8227.  
  8228. // 15000 - 10% <1% =0.15s > <10% = 1.5s>
  8229.  
  8230.  
  8231. // 1% Duration
  8232.  
  8233. let ratio2 = ratio1;
  8234.  
  8235. const ydd = yd.data;
  8236. if (ydd) {
  8237.  
  8238. const d1 = ydd.durationSec;
  8239. const d2 = ydd.fullDurationSec;
  8240.  
  8241. // @ step timing [min. 0.2%]
  8242. let numOfSteps = 500;
  8243. if ((d1 === d2 || (d1 + 1 === d2)) && d1 > 1) {
  8244. if (d2 > 400) numOfSteps = 500; // 0.2%
  8245. else if (d2 > 200) numOfSteps = 200; // 0.5%
  8246. else if (d2 > 100) numOfSteps = 100; // 1%
  8247. else if (d2 > 50) numOfSteps = 50; // 2%
  8248. else if (d2 > 25) numOfSteps = 20; // 5% (max => 99px * 5% = 4.95px)
  8249. else numOfSteps = 20;
  8250. }
  8251. if (numOfSteps > TICKER_MAX_STEPS_LIMIT) numOfSteps = TICKER_MAX_STEPS_LIMIT;
  8252. if (numOfSteps < 5) numOfSteps = 5;
  8253.  
  8254. const rd = numOfSteps / 100.0;
  8255.  
  8256. ratio2 = Math.round(ratio2 * rd) / rd;
  8257.  
  8258. // ratio2 = Math.round(ratio2 * 5) / 5;
  8259. ratio2 = ratio2.toFixed(1);
  8260. v = v.replace(`${ratio1}%`, `${ratio2}%`).replace(`${ratio1}%`, `${ratio2}%`);
  8261.  
  8262. if (yd.__style_last__ === v) return;
  8263. yd.__style_last__ = v;
  8264. // do not consider any delay here.
  8265. // it shall be inside the looping for all properties changes. all the css background ops are in the same microtask.
  8266.  
  8267. }
  8268. }
  8269.  
  8270. HTMLElement_.prototype.setAttribute.call(dr(this), attrName, v);
  8271.  
  8272.  
  8273. } else {
  8274. HTMLElement_.prototype.setAttribute.apply(dr(this), arguments);
  8275. }
  8276.  
  8277. };
  8278.  
  8279.  
  8280. const fpTicker = (renderer) => {
  8281. const cnt = insp(renderer);
  8282. assertor(() => typeof (cnt || 0).is === 'string');
  8283. assertor(() => ((cnt || 0).hostElement || 0).nodeType === 1);
  8284. const container = (cnt.$ || 0).container;
  8285. if (container) {
  8286. assertor(() => (container || 0).nodeType === 1);
  8287. assertor(() => typeof container.setAttribute === 'function');
  8288. container.setAttribute = tickerContainerSetAttribute;
  8289. } else {
  8290. console.warn(`"container" does not exist in ${cnt.is}`);
  8291. }
  8292. };
  8293.  
  8294.  
  8295. const tags = [
  8296. "yt-live-chat-ticker-renderer",
  8297. "yt-live-chat-ticker-paid-message-item-renderer",
  8298. "yt-live-chat-ticker-paid-sticker-item-renderer",
  8299. "yt-live-chat-ticker-sponsor-item-renderer"
  8300. ];
  8301.  
  8302. const tagsItemRenderer = [
  8303. "yt-live-chat-ticker-renderer",
  8304. "yt-live-chat-ticker-paid-message-item-renderer",
  8305. "yt-live-chat-ticker-paid-sticker-item-renderer",
  8306. "yt-live-chat-ticker-sponsor-item-renderer"
  8307. ];
  8308.  
  8309. // const wmList = new Set;
  8310.  
  8311. true && (new MutationObserver((mutations) => {
  8312.  
  8313. const s = new Set();
  8314. for (const mutation of mutations) {
  8315. if (mutation.type === 'attributes') {
  8316. s.add(mutation.target);
  8317. }
  8318. }
  8319. for (const target of s) {
  8320. const p = target && target.isConnected === true ? target.getAttribute('q92wb') : '';
  8321. if (p === '1') {
  8322. target.setAttribute('q92wb', '2');
  8323. const cnt = insp(target);
  8324. const dataId = ((cnt || 0).data || 0).id;
  8325. if (cnt && typeof cnt.requestRemoval49 === 'function' && dataId) {
  8326. target.id = dataId;
  8327. cnt.requestRemoval49();
  8328. target.setAttribute('q92wb', '3');
  8329. }
  8330. } else if (p === '3') {
  8331. target.setAttribute('q92wb', '4');
  8332. const cnt = insp(target);
  8333. const dataId = ((cnt || 0).data || 0).id;
  8334. if (cnt && typeof cnt.requestRemoval49 === 'function' && dataId) {
  8335. target.id = dataId;
  8336. const parentComponent = target.closest('yt-live-chat-ticker-renderer') || cnt.parentComponent;
  8337. const parentCnt = insp(parentComponent);
  8338. if(parentComponent && parentCnt && parentCnt.removeTickerItemById){
  8339. parentCnt.removeTickerItemById(dataId);
  8340. target.setAttribute('q92wb', '5');
  8341. }
  8342. }
  8343. }
  8344. }
  8345. s.clear();
  8346.  
  8347. })).observe(document, { attributes: true, attributeFilter: ['q92wb'], subtree: true });
  8348.  
  8349. Promise.all(tags.map(tag => customElements.whenDefined(tag))).then(() => {
  8350.  
  8351. mightFirstCheckOnYtInit();
  8352. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-ticker-... hacks");
  8353. console1.log("[Begin]");
  8354.  
  8355.  
  8356. let tickerAttachmentId = 0;
  8357.  
  8358.  
  8359. const __requestRemoval__ = function (cnt) {
  8360. if (cnt.hostElement && typeof cnt.requestRemoval === 'function') {
  8361. try {
  8362. const id = (cnt.data || 0).id;
  8363. if (!id) cnt.data = { id: 1 };
  8364. } catch (e) { }
  8365. try {
  8366. cnt.requestRemoval();
  8367. return true;
  8368. } catch (e) { }
  8369. }
  8370. return false;
  8371. }
  8372.  
  8373.  
  8374. const overlayBgMap = new WeakMap();
  8375.  
  8376. const dProto = {
  8377.  
  8378.  
  8379. /**
  8380. *
  8381.  
  8382. f.updateStatsBarAndMaybeShowAnimation = function(a, b, c) {
  8383. var d = this;
  8384. a || c();
  8385. a && this.statsBar && this.username && this.textContent && (this.isMouseOver ? (b(),
  8386. c()) : (a = this.animateShowStats(),
  8387. this.data.animationOrigin && this.data.trackingParams && aB().stateChanged(this.data.trackingParams, {
  8388. animationEventData: {
  8389. origin: this.data.animationOrigin
  8390. }
  8391. }),
  8392. a.finished.then(function() {
  8393. var e;
  8394. setTimeout(function() {
  8395. b();
  8396. c();
  8397. if (!d.isMouseOver) {
  8398. var g, k;
  8399. d.animateHideStats(((g = d.data) == null ? void 0 : g.dynamicStateData.stateSlideDurationMs) || 0, ((k = d.data) == null ? void 0 : k.dynamicStateData.stateUpdateDelayAfterMs) || 0)
  8400. }
  8401. }, ((e = d.data) == null ? void 0 : e.dynamicStateData.stateUpdateDelayBeforeMs) || 0)
  8402. })))
  8403. }
  8404.  
  8405. *
  8406. */
  8407.  
  8408.  
  8409.  
  8410. /**
  8411. *
  8412. *
  8413.  
  8414. f.animateShowStats = function() {
  8415. var a = this.textContent.animate({
  8416. transform: "translateY(-30px)"
  8417. }, {
  8418. duration: this.data.dynamicStateData.stateSlideDurationMs,
  8419. fill: "forwards"
  8420. });
  8421. this.username.animate({
  8422. opacity: 0
  8423. }, {
  8424. duration: 500,
  8425. fill: "forwards"
  8426. });
  8427. this.statsBar.animate({
  8428. opacity: 1
  8429. }, {
  8430. duration: 500,
  8431. fill: "forwards"
  8432. });
  8433. return a
  8434. }
  8435. ;
  8436. f.animateHideStats = function(a, b) {
  8437. this.textContent.animate({
  8438. transform: "translateY(0)"
  8439. }, {
  8440. duration: a,
  8441. fill: "forwards",
  8442. delay: b
  8443. });
  8444. this.username.animate({
  8445. opacity: 1
  8446. }, {
  8447. duration: 300,
  8448. fill: "forwards",
  8449. delay: b
  8450. });
  8451. this.statsBar.animate({
  8452. opacity: 0
  8453. }, {
  8454. duration: 300,
  8455. fill: "forwards",
  8456. delay: b
  8457. })
  8458. }
  8459. *
  8460. */
  8461.  
  8462. updateStatsBarAndMaybeShowAnimationRevised: function (a, b, c) {
  8463. // prevent memory leakage due to d.data was asked in a.finished.then
  8464. try{
  8465. // console.log('updateStatsBarAndMaybeShowAnimation called', this.is)
  8466. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8467. return this.updateStatsBarAndMaybeShowAnimation38.call(this.__proxySelf0__, a, b, c);
  8468. }catch(e){
  8469. console.log('updateStatsBarAndMaybeShowAnimationRevised ERROR');
  8470. console.error(e);
  8471. }
  8472. },
  8473.  
  8474. detachedForMemoryLeakage: function () {
  8475.  
  8476. try{
  8477.  
  8478. this.actionHandlerBehavior.unregisterActionMap(this.behaviorActionMap)
  8479.  
  8480. // this.behaviorActionMap = 0;
  8481. // this.isVisibilityRoot = 0;
  8482.  
  8483.  
  8484. }catch(e){}
  8485.  
  8486. return this.detached582MemoryLeak();
  8487. },
  8488.  
  8489. detachedForTickerInit: function () {
  8490.  
  8491. Promise.resolve(this).then((cnt) => {
  8492. if (cnt.isAttached) return;
  8493. cnt.isAttached === false && ((cnt.$ || 0).container || 0).isConnected === false && __requestRemoval__(cnt);
  8494. cnt.rafId > 1 && rafHub.cancel(cnt.rafId);
  8495. }).catch(console.warn);
  8496.  
  8497.  
  8498. const hostElement = (this || 0).hostElement;
  8499. if (USE_ADVANCED_TICKING && (this || 0).__isTickerItem58__ && hostElement instanceof HTMLElement_) {
  8500. // otherwise the startCountDown not working
  8501. hostElement.style.removeProperty('--ticker-start-time');
  8502. hostElement.style.removeProperty('--ticker-duration-time');
  8503.  
  8504. if (kRef(qWidthAdjustable) === hostElement) {
  8505.  
  8506. // need to update the first ticker
  8507. const q = document.querySelector('.r6-width-adjustable');
  8508. if (q instanceof HTMLElement_ && q.classList.contains('r6-width-adjustable-f')) {
  8509. q.classList.remove('r6-width-adjustable-f');
  8510. }
  8511. qWidthAdjustable = mWeakRef(q);
  8512.  
  8513. }
  8514. }
  8515.  
  8516. let r;
  8517. try {
  8518. r = this.detached77();
  8519. } catch (e) {
  8520. console.warn(e);
  8521. }
  8522. this.__ticker_attachmentId__ = 0;
  8523. return r;
  8524. },
  8525.  
  8526. attachedForTickerInit: function () {
  8527. this.__ticker_attachmentId__ = tickerAttachmentId = (tickerAttachmentId & 1073741823) + 1;
  8528.  
  8529. const hostElement = (this || 0).hostElement;
  8530. if (USE_ADVANCED_TICKING && (this || 0).__isTickerItem58__ && hostElement instanceof HTMLElement_) {
  8531. const prevElement = kRef(qWidthAdjustable);
  8532. if (prevElement instanceof HTMLElement_) {
  8533. prevElement.classList.add('r6-width-adjustable-f');
  8534. }
  8535. if (hostElement.__fgvm573__) {
  8536. hostElement.classList.remove('r6-closing-ticker');
  8537. hostElement.classList.remove('r6-width-adjustable-f');
  8538. } else {
  8539. hostElement.__fgvm573__ = 1;
  8540. hostElement.classList.add('r6-width-adjustable');
  8541. }
  8542. qWidthAdjustable = mWeakRef(hostElement);
  8543. }
  8544.  
  8545.  
  8546. fpTicker(hostElement || this);
  8547. return this.attached77();
  8548.  
  8549. },
  8550.  
  8551.  
  8552.  
  8553. setContainerWidthNoSelfLeakage: function(){
  8554. // prevent memory leakage due ot delay function
  8555. try{
  8556. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8557. return this.setContainerWidth55.call(this.__proxySelf0__);
  8558. }catch(e){
  8559. console.log('setContainerWidthNoSelfLeakage ERROR');
  8560. console.error(e);
  8561. }
  8562.  
  8563. },
  8564.  
  8565. slideDownNoSelfLeakage: function(){
  8566. // prevent memory leakage due ot delay function
  8567. try{
  8568. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8569. return this.slideDown55.call(this.__proxySelf0__);
  8570. }catch(e){
  8571. console.log('slideDownNoSelfLeakage ERROR');
  8572. console.error(e);
  8573. }
  8574.  
  8575. },
  8576.  
  8577. collapseNoSelfLeakage: function(){
  8578. // prevent memory leakage due ot delay function
  8579. try{
  8580. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8581. return this.collapse55.call(this.__proxySelf0__);
  8582. }catch(e){
  8583. console.log('collapseNoSelfLeakage ERROR');
  8584. console.error(e);
  8585. }
  8586. },
  8587.  
  8588. deletedChangedNoSelfLeakage: function(){
  8589. // prevent memory leakage due ot delay function
  8590. try{
  8591. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8592. return this.deletedChanged55.call(this.__proxySelf0__);
  8593. }catch(e){
  8594. console.log('deletedChangedNoSelfLeakage ERROR');
  8595. console.error(e);
  8596. }
  8597.  
  8598. },
  8599.  
  8600.  
  8601.  
  8602.  
  8603. /** @type {()} */
  8604. handlePauseReplayForPlaybackProgressState: function () {
  8605. if (!playerEventsByIframeRelay) return this.handlePauseReplay66.apply(this, arguments);
  8606.  
  8607. const attachementId = this.__ticker_attachmentId__;
  8608. if(!attachementId) return;
  8609.  
  8610. const jr = mWeakRef(this);
  8611.  
  8612. if (onPlayStateChangePromise) {
  8613.  
  8614. const tid = this._Y7rtu = (this._Y7rtu & 1073741823) + 1;
  8615.  
  8616. onPlayStateChangePromise.then(() => {
  8617. const cnt = kRef(jr) || 0;
  8618. if (attachementId !== cnt.__ticker_attachmentId__) return;
  8619. if (cnt.isAttached) {
  8620. if (tid === cnt._Y7rtu && !onPlayStateChangePromise && typeof cnt.handlePauseReplay === 'function' && cnt.hostElement) cnt.handlePauseReplay.apply(cnt, arguments);
  8621. // this.handlePauseReplay can be undefined if it is memory cleaned
  8622. }
  8623. });
  8624.  
  8625. return;
  8626. }
  8627.  
  8628. if (playerState !== 2) return;
  8629. if (this.isAttached) {
  8630. const tid = this._Y7rtk = (this._Y7rtk & 1073741823) + 1;
  8631. const tc = relayCount;
  8632. foregroundPromiseFn().then(() => {
  8633. const cnt = kRef(jr);
  8634. if (attachementId !== (cnt || 0).__ticker_attachmentId__) return;
  8635. if (cnt.isAttached) {
  8636. if (tid === cnt._Y7rtk && tc === relayCount && playerState === 2 && _playerState === playerState && cnt.hostElement) {
  8637. cnt.handlePauseReplay66();
  8638. }
  8639. }
  8640. })
  8641. }
  8642. },
  8643.  
  8644. /** @type {()} */
  8645. handleResumeReplayForPlaybackProgressState: function () {
  8646. if (!playerEventsByIframeRelay) return this.handleResumeReplay66.apply(this, arguments);
  8647.  
  8648. const attachementId = this.__ticker_attachmentId__;
  8649. if(!attachementId) return;
  8650.  
  8651. const jr = mWeakRef(this);
  8652. if (onPlayStateChangePromise) {
  8653.  
  8654. const tid = this._Y7rtv = (this._Y7rtv & 1073741823) + 1;
  8655.  
  8656. onPlayStateChangePromise.then(() => {
  8657. const cnt = kRef(jr);
  8658. if(attachementId !== (cnt || 0).__ticker_attachmentId__) return;
  8659. if (tid === cnt._Y7rtv && !onPlayStateChangePromise && typeof cnt.handleResumeReplay === 'function' && cnt.hostElement) cnt.handleResumeReplay.apply(cnt, arguments);
  8660. // this.handleResumeReplay can be undefined if it is memory cleaned
  8661. });
  8662.  
  8663. return;
  8664. }
  8665.  
  8666.  
  8667. if (playerState !== 1) return;
  8668. if (this.isAttached) {
  8669. const tc = relayCount;
  8670.  
  8671. relayPromise = relayPromise || new PromiseExternal();
  8672. relayPromise.then(() => {
  8673. const cnt = kRef(jr);
  8674. if(attachementId !== (cnt || 0).__ticker_attachmentId__) return;
  8675. if (relayCount > tc && playerState === 1 && _playerState === playerState && cnt.hostElement) {
  8676. cnt.handleResumeReplay66();
  8677. }
  8678. });
  8679. }
  8680. },
  8681.  
  8682. /** @type {(a,)} */
  8683. handleReplayProgressForPlaybackProgressState: function (a) {
  8684. if (this.isAttached) {
  8685. const attachementId = this.__ticker_attachmentId__;
  8686. if(!attachementId) return;
  8687. const tid = this._Y7rtk = (this._Y7rtk & 1073741823) + 1;
  8688. const jr = mWeakRef(kRef(this));
  8689. foregroundPromiseFn().then(() => {
  8690. const cnt = kRef(jr);
  8691. if(attachementId !== (cnt || 0).__ticker_attachmentId__) return;
  8692. if (cnt.isAttached) {
  8693. if (tid === cnt._Y7rtk && cnt.hostElement) {
  8694. cnt.handleReplayProgress66(a);
  8695. }
  8696. }
  8697. })
  8698. }
  8699. }
  8700.  
  8701.  
  8702. }
  8703.  
  8704.  
  8705.  
  8706. const isTickerItemsScrolling = function () {
  8707. const elm = document.querySelector('#ticker-bar.yt-live-chat-ticker-renderer');
  8708. if (!elm) return false;
  8709. return (elm.scrollLeft > 0);
  8710. }
  8711.  
  8712.  
  8713.  
  8714.  
  8715. const u37fn = function (cnt) {
  8716.  
  8717. if (cnt.__dataEnabled === false || cnt.__dataInvalid === true) return;
  8718.  
  8719. if (!__LCRInjection__) {
  8720. console.error('[yt-chat] USE_ADVANCED_TICKING fails because of no __LCRInjection__');
  8721. }
  8722.  
  8723. const cntData = ((cnt || 0).__data || 0).data || (cnt || 0).data || 0;
  8724. if (!cntData) return;
  8725. const cntElement = cnt.hostElement;
  8726. if (!(cntElement instanceof HTMLElement_)) return;
  8727.  
  8728. const duration = (cntData.fullDurationSec || cntData.durationSec || 0);
  8729.  
  8730. let ct;
  8731.  
  8732. if (__LCRInjection__ && cntData && duration > 0 && !('__progressAt__' in cntData)) {
  8733. ct = Date.now();
  8734.  
  8735. if (!cntData.__timestampActionRequest__) {
  8736. console.log(' 5688001 ');
  8737. // console.log(`(5688001) ${new Error().stack}`);
  8738. }
  8739. cntData.__liveTimestamp__ = (((cntData.__timestampActionRequest__ || ct) - timeOriginDT) / 1000) || Number.MIN_VALUE;
  8740. timestampUnderLiveMode = true;
  8741. } else if (__LCRInjection__ && cntData && duration > 0 && cntData.__progressAt__ > 0) {
  8742. timestampUnderLiveMode = false;
  8743. }
  8744. // console.log(48117007, cntData)
  8745.  
  8746. let tk = cntData.__progressAt__ || cntData.__liveTimestamp__;
  8747.  
  8748. if (!tk) {
  8749. console.log('time property is not found', !!__LCRInjection__, !!cntData, !!(duration > 0), !('__progressAt__' in cntData), cntData.__progressAt__, cntData.__liveTimestamp__);
  8750. return;
  8751. }
  8752.  
  8753.  
  8754.  
  8755. const liveOffsetMs = ct > 0 && cntData.__timestampActionRequest__ > 0 ? ct - cntData.__timestampActionRequest__ : 0;
  8756.  
  8757. // console.log(1237, liveOffsetMs, cntData.durationSec)
  8758.  
  8759. if (liveOffsetMs > 0) {
  8760. cntData.durationSec -= Math.floor(liveOffsetMs / 1000);
  8761. if (cntData.durationSec < 0) cntData.durationSec = 0;
  8762. // console.log(1238, liveOffsetMs, cntData.durationSec)
  8763. if (!cntData.durationSec) {
  8764. try {
  8765. cnt.requestRemoval();
  8766. } catch (e) { }
  8767. return;
  8768. }
  8769. }
  8770.  
  8771.  
  8772. let offset = cntData.fullDurationSec - cntData.durationSec; // consider this is live replay video, offset can be > 0
  8773. if (offset > 0) tk -= offset;
  8774. // in livestreaming. tk can be negative as we use performance.timeOrigin for t=0s time frame
  8775.  
  8776.  
  8777.  
  8778. const existingOverlaySelector = `ticker-bg-overlay[ticker-id="${cnt.__ticker_attachmentId__}"]`;
  8779.  
  8780. const q = kRef(overlayBgMap.get(cnt));
  8781.  
  8782. let r = valAssign(cntElement, '--ticker-start-time', tk);
  8783.  
  8784. if ((r || !q || q.isConnected === false) && duration > 0) {
  8785.  
  8786. // t0 ...... 1 ... fullDurationSec
  8787. // tk ...... k ... fullDurationSec-durationSec
  8788. // t0-fullDurationSec ...... 0 ... 0
  8789.  
  8790. // now - (fullDurationSec-durationSec)
  8791.  
  8792.  
  8793. // update dntElementWeak
  8794. const dnt = cnt.parentComponent;
  8795. const dntElement = dnt ? dnt.hostElement || dnt : 0;
  8796. if (dntElement) {
  8797. dntElementWeak = mWeakRef(dntElement);
  8798. resistanceUpdateBusy = false;
  8799. if (!startResistanceUpdaterStarted) startResistanceUpdater();
  8800. else updateTickerCurrentTime();
  8801. }
  8802.  
  8803.  
  8804. // create overlay if needed
  8805. if (!cntElement.querySelector(existingOverlaySelector)) {
  8806.  
  8807. // remove if any
  8808. const oldElement = cntElement.querySelector('ticker-bg-overlay');
  8809. if (oldElement) oldElement.remove();
  8810.  
  8811. // use advancedTicking, ticker enabled
  8812. cnt.__advancedTicking038__ = 1;
  8813.  
  8814. const em = q || document.createElement('ticker-bg-overlay');
  8815.  
  8816. overlayBgMap.set(cnt, mWeakRef(em));
  8817. // const ey = document.createElement('ticker-bg-overlay-end');
  8818. const wy = document.createElement('ticker-bg-overlay-end2');
  8819.  
  8820. const cr1 = cnt.colorFromDecimal(cntData.startBackgroundColor);
  8821. const cr2 = cnt.colorFromDecimal(cntData.endBackgroundColor);
  8822.  
  8823. const container = cnt.$.container;
  8824.  
  8825. em.setAttribute('ticker-id', `${cnt.__ticker_attachmentId__}`);
  8826.  
  8827. const tid = `ticker-${cnt.__ticker_attachmentId__}-${Math.floor(Math.random() * 314159265359 + 314159265359).toString(36)}`;
  8828.  
  8829. em.id = `${tid}-b`;
  8830. em.style.background = `linear-gradient(90deg, ${cr1},${cr1} 50%,${cr2} 50%,${cr2})`;
  8831.  
  8832. if (!(container instanceof HTMLElement_)) {
  8833. // em.insertBefore(ey, em.firstChild);
  8834. insertBeforeNaFn(cntElement, em, cntElement.firstChild); // cntElement.insertBefore(em, cntElement.firstChild);
  8835. cntElement.style.borderRadius = '16px';
  8836. container.style.borderRadius = 'initial';
  8837. } else {
  8838. // em.insertBefore(ey, em.firstChild);
  8839. insertBeforeNaFn(container, em, container.firstChild); // container.insertBefore(em, container.firstChild);
  8840. }
  8841.  
  8842. // em.style.left = '-50%';
  8843. // em.style.left = "clamp(-100%, calc( -100% * ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) ), 0%)";
  8844.  
  8845. if (container instanceof HTMLElement_) {
  8846.  
  8847. container.style.background = 'transparent';
  8848. container.style.backgroundColor = 'transparent';
  8849. // container.style.zIndex = '1';
  8850. }
  8851. // em.style.zIndex = '-1';
  8852. valAssign(cntElement, '--ticker-duration-time', duration)
  8853.  
  8854. valAssign(wy, '--ticker-start-time', tk);
  8855. valAssign(wy, '--ticker-duration-time', duration);
  8856. wy.id = `${tid}-e`;
  8857.  
  8858. appendChildNaFn(dntElement, wy);
  8859.  
  8860. // if (wio instanceof IntersectionObserver) {
  8861. // wio.observe(ey);
  8862. // }
  8863.  
  8864. const wio2 = dProto.wio2;
  8865. if (wio2 instanceof IntersectionObserver) {
  8866. wio2.observe(wy);
  8867. }
  8868.  
  8869. }
  8870. }
  8871. };
  8872.  
  8873.  
  8874.  
  8875. const timeFn749 = (cnt) => {
  8876. cnt = kRef(cnt);
  8877. if (!cnt) return;
  8878. cnt.__startCountdownAdv477__ = Date.now();
  8879.  
  8880. if (
  8881. cnt
  8882. && (cnt.hostElement && cnt.isAttached && cnt.hostElement.isConnected)
  8883. && cnt.parentComponent // startCountdown is triggered by dataChanged; // not yet attached to the actual dom tree
  8884. && cnt.__ticker_attachmentId__
  8885. ) {
  8886.  
  8887. const data = cnt.data;
  8888. const dataId = data ? ((cnt || 0).data || 0).id : null;
  8889. const elemId = ((cnt || 0).hostElement || 0).id;
  8890.  
  8891. if (dataId && dataId === elemId) {
  8892.  
  8893. const attachId = cnt.__ticker_attachmentId__;
  8894. const uid = `${attachId}!${dataId}`;
  8895.  
  8896. if (data.__wsi6c__ !== uid) {
  8897. data.__wsi6c__ = uid;
  8898. Promise.resolve(cnt).then(u37fn);
  8899. return true;
  8900. }
  8901.  
  8902. }
  8903.  
  8904. }
  8905.  
  8906. return false;
  8907. }
  8908.  
  8909. let tagI = 0;
  8910. for (const tag of tagsItemRenderer) { // ##tag##
  8911.  
  8912. tagI++;
  8913.  
  8914. const dummy = document.createElement(tag);
  8915.  
  8916. const cProto = getProto(dummy);
  8917. if (!cProto || !cProto.attached) {
  8918. console1.warn(`proto.attached for ${tag} is unavailable.`);
  8919. continue;
  8920. }
  8921.  
  8922. if (FIX_MEMORY_LEAKAGE_TICKER_ACTIONMAP && typeof cProto.detached582MemoryLeak !== 'function' && typeof cProto.detached === 'function') {
  8923. cProto.detached582MemoryLeak = cProto.detached;
  8924. cProto.detached = dProto.detachedForMemoryLeakage;
  8925. }
  8926.  
  8927. cProto.detached77 = cProto.detached;
  8928. cProto.detached = dProto.detachedForTickerInit;
  8929.  
  8930. cProto.attached77 = cProto.attached;
  8931.  
  8932. cProto.attached = dProto.attachedForTickerInit;
  8933.  
  8934. let flgLeakageFixApplied = 0;
  8935.  
  8936. if (FIX_MEMORY_LEAKAGE_TICKER_STATSBAR && typeof cProto.updateStatsBarAndMaybeShowAnimation === 'function' && !cProto.updateStatsBarAndMaybeShowAnimation38 && cProto.updateStatsBarAndMaybeShowAnimation.length === 3) {
  8937.  
  8938. cProto.updateStatsBarAndMaybeShowAnimation38 = cProto.updateStatsBarAndMaybeShowAnimation;
  8939. cProto.updateStatsBarAndMaybeShowAnimation = dProto.updateStatsBarAndMaybeShowAnimationRevised;
  8940.  
  8941. flgLeakageFixApplied |= 2;
  8942. } else {
  8943. // the function is only in yt-live-chat-ticker-paid-message-item-renderer
  8944. }
  8945.  
  8946.  
  8947. // ------------- withTimerFn_ -------------
  8948.  
  8949. let withTimerFn_ = 0;
  8950. if (typeof cProto.startCountdown === 'function' && typeof cProto.updateTimeout === 'function' && typeof cProto.isAnimationPausedChanged === 'function') {
  8951.  
  8952. // console.log('startCountdown', typeof cProto.startCountdown)
  8953. // console.log('updateTimeout', typeof cProto.updateTimeout)
  8954. // console.log('isAnimationPausedChanged', typeof cProto.isAnimationPausedChanged)
  8955.  
  8956. // <<< to be reviewed cProto.updateTimeout --- isTimingFunctionHackable -- doHack >>>
  8957. const isTimingFunctionHackable = fnIntegrity(cProto.startCountdown, '2.66.37') && fnIntegrity(cProto.updateTimeout, '1.76.45') && fnIntegrity(cProto.isAnimationPausedChanged, '2.56.30')
  8958. if (!isTimingFunctionHackable) console1.log('isTimingFunctionHackable = false');
  8959. withTimerFn_ = isTimingFunctionHackable ? 2 : 1;
  8960. } else {
  8961. let flag = 0;
  8962. if (typeof cProto.startCountdown === 'function') flag |= 1;
  8963. if (typeof cProto.updateTimeout === 'function') flag |= 2;
  8964. if (typeof cProto.isAnimationPausedChanged === 'function') flag |= 4;
  8965.  
  8966. console1.log(`Skip Timing Function Modification[#${tagI}]: ${flag} / ${1 + 2 + 4}`, ` ${tag}`);
  8967. // console.log(Object.getOwnPropertyNames(cProto))
  8968. // continue;
  8969. }
  8970.  
  8971. // ------------- withTimerFn_ -------------
  8972.  
  8973. // ------------- ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX -------------
  8974.  
  8975. let urt = 0;
  8976.  
  8977. if (ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX) {
  8978.  
  8979.  
  8980. /**
  8981. *
  8982. f.handlePauseReplay = function() {
  8983. this.isAnimationPaused = !0;
  8984. this.detlaSincePausedSecs = 0
  8985. }
  8986. */
  8987.  
  8988. /**
  8989. *
  8990.  
  8991. f.handlePauseReplay = function() {
  8992. this.isReplayPaused = !0
  8993. }
  8994. *
  8995. */
  8996.  
  8997. if (typeof cProto.handlePauseReplay === 'function' && !cProto.handlePauseReplay66 && cProto.handlePauseReplay.length === 0) {
  8998. const fi = fnIntegrity(cProto.handlePauseReplay);
  8999. urt++;
  9000. if (fi === '0.8.2' || fi === '0.12.4') {
  9001. } else {
  9002. assertor(() => fnIntegrity(cProto.handlePauseReplay, '0.8.2'));
  9003. }
  9004. } else {
  9005. if (withTimerFn_ > 0) console1.log('Error for setting cProto.handlePauseReplay', tag)
  9006. }
  9007.  
  9008. if (typeof cProto.handleResumeReplay === 'function' && !cProto.handleResumeReplay66 && cProto.handleResumeReplay.length === 0) {
  9009. urt++;
  9010. assertor(() => fnIntegrity(cProto.handleResumeReplay, '0.8.2'));
  9011. } else {
  9012. if (withTimerFn_ > 0) console1.log('Error for setting cProto.handleResumeReplay', tag)
  9013. }
  9014.  
  9015. if (typeof cProto.handleReplayProgress === 'function' && !cProto.handleReplayProgress66 && cProto.handleReplayProgress.length === 1) {
  9016. urt++;
  9017. assertor(() => fnIntegrity(cProto.handleReplayProgress, '1.16.13'));
  9018. } else {
  9019. if (withTimerFn_ > 0) console1.log('Error for setting cProto.handleReplayProgress', tag)
  9020. }
  9021.  
  9022.  
  9023.  
  9024. }
  9025.  
  9026. const ENABLE_VIDEO_PROGRESS_STATE_FIX_AND_URT_PASSED = ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX && urt === 3 && (SKIP_VIDEO_PLAYBACK_PROGRESS_STATE_FIX_FOR_NO_TIMEFX ? (withTimerFn_ > 0) : true);
  9027. cProto.__ENABLE_VIDEO_PROGRESS_STATE_FIX_AND_URT_PASSED__ = ENABLE_VIDEO_PROGRESS_STATE_FIX_AND_URT_PASSED;
  9028.  
  9029. if (ENABLE_VIDEO_PROGRESS_STATE_FIX_AND_URT_PASSED) {
  9030.  
  9031. cProto._Y7rtk = 0;
  9032. cProto._Y7rtu = 0;
  9033. cProto._Y7rtv = 0;
  9034.  
  9035. cProto.handlePauseReplay66 = cProto.handlePauseReplay;
  9036. cProto.handlePauseReplay = dProto.handlePauseReplayForPlaybackProgressState;
  9037.  
  9038. cProto.handleResumeReplay66 = cProto.handleResumeReplay;
  9039. cProto.handleResumeReplay = dProto.handleResumeReplayForPlaybackProgressState;
  9040.  
  9041. cProto.handleReplayProgress66 = cProto.handleReplayProgress;
  9042. cProto.handleReplayProgress = dProto.handleReplayProgressForPlaybackProgressState;
  9043.  
  9044. }
  9045.  
  9046. // ------------- ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX -------------
  9047.  
  9048. // ------------- FIX_MEMORY_LEAKAGE_TICKER_TIMER -------------
  9049.  
  9050. if (FIX_MEMORY_LEAKAGE_TICKER_TIMER) {
  9051. if (!USE_ADVANCED_TICKING && typeof cProto.setContainerWidth === 'function' && !cProto.setContainerWidth55 && cProto.setContainerWidth.length === 0) {
  9052. cProto.setContainerWidth55 = cProto.setContainerWidth;
  9053. cProto.setContainerWidth = dProto.setContainerWidthNoSelfLeakage;
  9054. flgLeakageFixApplied |= 4;
  9055. }
  9056. if (!USE_ADVANCED_TICKING && typeof cProto.slideDown === 'function' && !cProto.slideDown55 && cProto.slideDown.length === 0) {
  9057. cProto.slideDown55 = cProto.slideDown;
  9058. cProto.slideDown = dProto.slideDownNoSelfLeakage;
  9059. flgLeakageFixApplied |= 8;
  9060. }
  9061. if (!USE_ADVANCED_TICKING && typeof cProto.collapse === 'function' && !cProto.collapse55 && cProto.collapse.length === 0) {
  9062. cProto.collapse55 = cProto.collapse;
  9063. cProto.collapse = dProto.collapseNoSelfLeakage;
  9064. flgLeakageFixApplied |= 16;
  9065. }
  9066. if (typeof cProto.deletedChanged === 'function' && !cProto.deletedChanged55 && cProto.deletedChanged.length === 0) {
  9067.  
  9068. cProto.deletedChanged55 = cProto.deletedChanged;
  9069. cProto.deletedChanged = dProto.deletedChangedNoSelfLeakage;
  9070. flgLeakageFixApplied |= 32;
  9071. }
  9072.  
  9073. }
  9074.  
  9075. const flgTotal = USE_ADVANCED_TICKING ? 1 + 2 + 32 : 1 + 2 + 4 + 8 + 16 + 32;
  9076.  
  9077. console1.log(`FIX_MEMORY_LEAKAGE_TICKER_[#${tagI}]: ${flgLeakageFixApplied} / ${flgTotal}`, cProto.is);
  9078.  
  9079. // ------------- FIX_MEMORY_LEAKAGE_TICKER_TIMER -------------
  9080.  
  9081.  
  9082.  
  9083. const canDoAdvancedTicking = 1 &&
  9084. ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION &&
  9085. typeof cProto.startCountdown === 'function' && !cProto.startCountdown49 && cProto.startCountdown.length === 2 &&
  9086. typeof cProto.updateTimeout === 'function' && !cProto.updateTimeout49 && cProto.updateTimeout.length === 1 &&
  9087. typeof cProto.isAnimationPausedChanged === 'function' && !cProto.isAnimationPausedChanged49 && cProto.isAnimationPausedChanged.length === 2 &&
  9088. typeof cProto.setContainerWidth === 'function' && cProto.setContainerWidth.length === 0 &&
  9089. typeof cProto.requestRemoval === 'function' && !cProto.requestRemoval49 && cProto.requestRemoval.length === 0
  9090. CSS.supports("left","clamp(-100%, calc( -100% * ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) ), 0%)");
  9091.  
  9092.  
  9093.  
  9094. if (USE_ADVANCED_TICKING && canDoAdvancedTicking && ENABLE_TICKERS_BOOSTED_STAMPING) {
  9095. // startResistanceUpdater();
  9096. // live replay video -> 48117005 -> 48117006 keep fire. ->48117007 0 -> 48117007 {...}
  9097. // live stream video -> 48117007 0 -> 48117007 YES
  9098.  
  9099. document.documentElement.setAttribute('r6-advanced-ticking', '');
  9100. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::START`)
  9101.  
  9102. const wio2 = dProto.wio2 || (dProto.wio2 = new IntersectionObserver((mutations) => {
  9103.  
  9104. for (const mutation of mutations) {
  9105. if (mutation.isIntersecting) {
  9106.  
  9107. const marker = mutation.target;
  9108. let endId = marker.id
  9109. if (!endId) continue;
  9110. let tid = endId.substring(0, endId.length - 2);
  9111. if (!tid) continue;
  9112. // let bId = `${tid}-b`;
  9113. const bgElm = document.querySelector(`#${tid}-b`);
  9114. if (!bgElm) continue;
  9115. const overlay = bgElm;
  9116.  
  9117. wio2.unobserve(marker);
  9118. marker.remove();
  9119. let p = overlay || 0;
  9120. let cn = 4;
  9121. while ((p = p.parentElement) instanceof HTMLElement_) {
  9122. if (p instanceof HTMLElement_) {
  9123. const cnt = insp(p);
  9124. if (cnt && typeof cnt.slideDown === 'function' && typeof cnt.setContainerWidth === 'function' && cnt.__advancedTicking038__ === 1) {
  9125.  
  9126. cnt.__advancedTicking038__ = 2;
  9127.  
  9128. let deletionMode = false;
  9129. const cntData = ((cnt || 0).__data || 0).data || (cnt || 0).data || 0;
  9130. if (timestampUnderLiveMode && cntData && cntData.durationSec > 0 && cntData.__timestampActionRequest__ > 0) {
  9131.  
  9132. // time choose - 0.2s for transition (slideDown sliding-down)
  9133. // 60hz = 17ms
  9134. // choose 0.28s
  9135. const targetFutureTime = cntData.__timestampActionRequest__ + cntData.durationSec * 1000;
  9136. // check whether the targetFutureTime is already the past
  9137. if (targetFutureTime + 280 < Date.now()) {
  9138. // just dispose
  9139. deletionMode = true;
  9140. }
  9141. } else if (__LCRInjection__ && !timestampUnderLiveMode && cntData && cntData.durationSec > 0 && cntData.__progressAt__ > 0) {
  9142.  
  9143. const targetFutureTime = (cntData.__progressAt__ + cntData.durationSec);
  9144. // check whether the targetFutureTime is already the past
  9145. if (targetFutureTime + 0.28 < playerProgressChangedArg1) {
  9146. // just dispose
  9147. deletionMode = true;
  9148. }
  9149.  
  9150.  
  9151. }
  9152.  
  9153.  
  9154. if (deletionMode) {
  9155. __requestRemoval__(cnt);
  9156. } else {
  9157.  
  9158. const w = cnt.hostElement.style.width;
  9159. if (w === "auto" || w === "") cnt.setContainerWidth();
  9160. cnt.slideDown();
  9161. }
  9162.  
  9163. break;
  9164. }
  9165. }
  9166. cn--;
  9167. if (!cn) {
  9168. console.log('cnt not found for ticker-bg-overlay');
  9169. break;
  9170. }
  9171. }
  9172.  
  9173.  
  9174. }
  9175. }
  9176.  
  9177. // console.log(mutations);
  9178. }, {
  9179.  
  9180. rootMargin: '0px',
  9181. threshold: [1]
  9182.  
  9183. }));
  9184.  
  9185.  
  9186.  
  9187. cProto.__isTickerItem58__ = 1;
  9188. cProto.attached747 = cProto.attached;
  9189. cProto.attached = function () {
  9190. const hostElement = (this || 0).hostElement;
  9191. if (hostElement && hostElement.hasAttribute('q92wb')) hostElement.removeAttribute('q92wb');
  9192. if (hostElement && hostElement.__requestRemovalAt003__) hostElement.__requestRemovalAt003__ = 0;
  9193. Promise.resolve().then(() => {
  9194. if (this.hostElement && this.isAttached && this.hostElement.isConnected && this.parentComponent) {
  9195. if (this.__startCountdownAdv477__) Promise.resolve(this).then(timeFn749);
  9196. }
  9197. }).catch(console.warn);
  9198. return this.attached747();
  9199. };
  9200. cProto.startCountdown = dProto.startCountdownAdv || (dProto.startCountdownAdv = function (a, b) {
  9201.  
  9202.  
  9203. timeFn749(this);
  9204.  
  9205.  
  9206. });
  9207.  
  9208. cProto.updateTimeout = dProto.updateTimeoutAdv || (dProto.updateTimeoutAdv = function (a) {
  9209.  
  9210.  
  9211.  
  9212. });
  9213.  
  9214. cProto.isAnimationPausedChanged = dProto.isAnimationPausedChangedAdv || (dProto.isAnimationPausedChangedAdv = function (a, b) {
  9215.  
  9216.  
  9217.  
  9218. });
  9219.  
  9220.  
  9221. if (typeof cProto.slideDown === 'function' && !cProto.slideDown43 && cProto.slideDown.length === 0) {
  9222.  
  9223. cProto.slideDown43 = cProto.slideDown;
  9224. cProto.slideDown = dProto.slideDownAdv || (dProto.slideDownAdv = async function () {
  9225.  
  9226. // console.log('calling slideDown', Date.now())
  9227. if (this.__advancedTicking038__) {
  9228.  
  9229. if (this.__advancedTicking038__ === 1) this.__advancedTicking038__ = 2; // ignore intersectionobserver detection
  9230.  
  9231.  
  9232. const hostElement = this.hostElement;
  9233. const container = this.$.container;
  9234.  
  9235. const parentComponentCnt = insp(this.parentComponent);
  9236. const parentComponentElm = parentComponentCnt? parentComponentCnt.hostElement : null;
  9237.  
  9238. if (hostElement instanceof HTMLElement_ && container instanceof HTMLElement_ && parentComponentElm instanceof HTMLElement_) {
  9239. // const prevTransitionClosingElm = kRef(prevTransitionClosing);
  9240. // if (prevTransitionClosingElm !== hostElement) {
  9241. // prevTransitionClosingElm && prevTransitionClosingElm.classList.add('ticker-no-transition-time');
  9242. // prevTransitionClosing = mWeakRef(hostElement);
  9243. // }
  9244. // if (hostElement.classList.contains('ticker-no-transition-time')) hostElement.classList.remove('ticker-no-transition-time');
  9245. hostElement.classList.add('r6-closing-ticker');
  9246.  
  9247. if (!transitionEndHooks.has(parentComponentElm)) {
  9248. transitionEndHooks.add(parentComponentElm);
  9249. document.addEventListener('transitionend', transitionEndAfterFn, passiveCapture);
  9250. }
  9251.  
  9252. const pr = new PromiseExternal();
  9253. transitionEndAfterFnSimple.set(hostElement, pr);
  9254. transitionEndAfterFnSimple.set(container, pr);
  9255. transitionEndAfterFnSimpleEnable++;
  9256. hostElement.classList.add("sliding-down");
  9257. await pr.then();
  9258. transitionEndAfterFnSimpleEnable--;
  9259. transitionEndAfterFnSimple.delete(hostElement);
  9260. transitionEndAfterFnSimple.delete(container);
  9261. if (this && this.hostElement instanceof HTMLElement_) {
  9262.  
  9263. this.collapse();
  9264. }
  9265. return;
  9266. }
  9267. }
  9268. this.slideDown43();
  9269.  
  9270. });
  9271.  
  9272.  
  9273. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::slideDown - OK`)
  9274. } else {
  9275.  
  9276. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::slideDown - NG`)
  9277. }
  9278.  
  9279.  
  9280. if (typeof cProto.collapse === 'function' && !cProto.collapse43 && cProto.collapse.length === 0) {
  9281. cProto.collapse43 = cProto.collapse;
  9282. cProto.collapse = dProto.collapseAdv || (dProto.collapseAdv = async function () {
  9283.  
  9284.  
  9285. if (this.__advancedTicking038__) {
  9286.  
  9287.  
  9288. if (this.__advancedTicking038__ === 1) this.__advancedTicking038__ = 2; // ignore intersectionobserver detection
  9289.  
  9290.  
  9291. const hostElement = this.hostElement;
  9292. const container = this.$.container;
  9293.  
  9294. const parentComponentCnt = insp(this.parentComponent);
  9295. const parentComponentElm = parentComponentCnt ? parentComponentCnt.hostElement : null;
  9296.  
  9297. if (hostElement instanceof HTMLElement_ && container instanceof HTMLElement_ && parentComponentElm instanceof HTMLElement_) {
  9298. // const prevTransitionClosingElm = kRef(prevTransitionClosing);
  9299. // if (prevTransitionClosingElm !== hostElement) {
  9300. // prevTransitionClosingElm && prevTransitionClosingElm.classList.add('ticker-no-transition-time');
  9301. // prevTransitionClosing = mWeakRef(hostElement);
  9302. // }
  9303. // if (hostElement.classList.contains('ticker-no-transition-time')) hostElement.classList.remove('ticker-no-transition-time');
  9304. hostElement.classList.add('r6-closing-ticker');
  9305.  
  9306. if (!transitionEndHooks.has(parentComponentElm)) {
  9307. transitionEndHooks.add(parentComponentElm);
  9308. document.addEventListener('transitionend', transitionEndAfterFn, passiveCapture);
  9309. }
  9310.  
  9311. const pr = new PromiseExternal();
  9312. transitionEndAfterFnSimple.set(hostElement, pr);
  9313. transitionEndAfterFnSimple.set(container, pr);
  9314. transitionEndAfterFnSimpleEnable++;
  9315. hostElement.classList.add("collapsing");
  9316. hostElement.style.width = "0";
  9317. await pr.then();
  9318. transitionEndAfterFnSimpleEnable--;
  9319. transitionEndAfterFnSimple.delete(hostElement);
  9320. transitionEndAfterFnSimple.delete(container);
  9321. if (this && this.hostElement instanceof HTMLElement_) {
  9322.  
  9323. this.requestRemoval();
  9324. }
  9325.  
  9326. return;
  9327. }
  9328.  
  9329.  
  9330. }
  9331. this.collapse43();
  9332.  
  9333.  
  9334. });
  9335.  
  9336. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::collapse - OK`)
  9337. } else {
  9338.  
  9339. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::collapse - NG`)
  9340. }
  9341.  
  9342.  
  9343.  
  9344. if (typeof cProto.requestRemoval === 'function' && !cProto.requestRemoval49 && cProto.requestRemoval.length === 0) {
  9345.  
  9346. cProto.requestRemoval49 = cProto.requestRemoval;
  9347. cProto.requestRemoval = dProto.requestRemovalAdv || (dProto.requestRemovalAdv = function () {
  9348.  
  9349. const hostElement = this.hostElement;
  9350. hostElement.__requestRemovalAt003__ = Date.now();
  9351. if (this.__advancedTicking038__) {
  9352. try {
  9353. const overlayBg = hostElement.querySelector('ticker-bg-overlay[id]');
  9354. if (overlayBg) {
  9355. const overlayBgId = overlayBg.id;
  9356. const tid = overlayBgId ? overlayBgId.substring(0, overlayBgId.length - 2) : '';
  9357. const endElm = tid ? document.querySelector(`#${tid}-e`) : null;
  9358. if (endElm) {
  9359. wio2.unobserve(endElm);
  9360. endElm.remove();
  9361. }
  9362. }
  9363. } catch (e) { }
  9364. this.__advancedTicking038__ = 2;
  9365. // console.log('requestRemoval!!')
  9366. if (hostElement instanceof HTMLElement_) {
  9367. // otherwise the startCountDown not working
  9368. hostElement.style.removeProperty('--ticker-start-time');
  9369. hostElement.style.removeProperty('--ticker-duration-time');
  9370. }
  9371. if (REUSE_TICKER) {
  9372. const cntData = this.data;
  9373. if (hostElement instanceof HTMLElement_ && cntData.id && cntData.fullDurationSec && !hostElement.hasAttribute('__reuseid__')) {
  9374. hostElement.setAttribute('__reuseid__', reuseId);
  9375. hostElement.setAttribute('__nogc__', ''); // provided to leakage detection script
  9376. // this.__markReuse13__ = true;
  9377. reuseStore.set(`<${this.is}>${cntData.id}:${cntData.fullDurationSec}`, mWeakRef(this));
  9378. }
  9379. }
  9380. }
  9381. if (hostElement instanceof HTMLElement_) {
  9382. // try {
  9383. // // hostElement.remove();
  9384.  
  9385. // if (!hostElement.classList.contains('ticker-no-transition-time')) hostElement.classList.add('ticker-no-transition-time');
  9386. // } catch (e) { }
  9387.  
  9388. try {
  9389.  
  9390. hostElement.classList.remove('r6-closing-ticker');
  9391. hostElement.classList.remove('r6-width-adjustable-f');
  9392. } catch (e) { }
  9393.  
  9394. // if(ADVANCED_TICKING_MEMORY_CLEAN_FOR_REMOVAL){
  9395. // const wr = mWeakRef(hostElement);
  9396. // const wf = ()=>{
  9397. // const element = kRef(wr);
  9398. // if(!element) {
  9399. // console.log('[yt-chat-removalrequest] element was memory cleaned.');
  9400. // return;
  9401. // }
  9402.  
  9403. // setTimeout(wf, 8000);
  9404. // if(element.isConnected){
  9405. // console.log('[yt-chat-removalrequest] element is still connected to DOM Tree.');
  9406. // return;
  9407. // }
  9408.  
  9409. // const cnt = insp(element)
  9410. // if(typeof cnt.requestRemoval !== 'function'){
  9411.  
  9412. // console.log('[yt-chat-removalrequest] element is not connected to cnt.');
  9413. // return;
  9414. // }
  9415. // console.log('[yt-chat-removalrequest] element is not GC.');
  9416. // try{
  9417. // cnt.data = null;
  9418. // }catch(e){}
  9419.  
  9420. // Object.setPrototypeOf(cnt, Object.prototype);
  9421. // for(const k of Object.getOwnPropertyNames(cnt)){
  9422. // try{
  9423. // cnt[k] = null;
  9424. // }catch(e){}
  9425.  
  9426. // try{
  9427. // delete cnt[k];
  9428. // }catch(e){}
  9429. // }
  9430.  
  9431.  
  9432. // for(const k of Object.getOwnPropertySymbols(cnt)){
  9433. // try{
  9434. // cnt[k] = null;
  9435. // }catch(e){}
  9436.  
  9437. // try{
  9438. // delete cnt[k];
  9439. // }catch(e){}
  9440. // }
  9441.  
  9442. // }
  9443. // setTimeout(wf, 8000);
  9444. // }
  9445.  
  9446. hostElement.setAttribute('q92wb', '1');
  9447. }
  9448. });
  9449.  
  9450.  
  9451. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::requestRemoval - OK`)
  9452. } else {
  9453.  
  9454. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::requestRemoval - NG`)
  9455. }
  9456.  
  9457.  
  9458. if (typeof cProto.computeContainerStyle === 'function' && !cProto.computeContainerStyle49 && cProto.computeContainerStyle.length === 2) {
  9459. cProto.computeContainerStyle49 = cProto.computeContainerStyle;
  9460. cProto.computeContainerStyle = dProto.computeContainerStyleAdv || (dProto.computeContainerStyleAdv = function (a, b) {
  9461. if (this.__advancedTicking038__) {
  9462. return "";
  9463. }
  9464. return this.computeContainerStyle49(a, b);
  9465. });
  9466.  
  9467.  
  9468. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::computeContainerStyle - OK`)
  9469. } else {
  9470.  
  9471. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::computeContainerStyle - NG`)
  9472. }
  9473.  
  9474.  
  9475.  
  9476. if(ENABLE_TICKERS_BOOSTED_STAMPING && DISABLE_DYNAMIC_TICKER_WIDTH && typeof cProto.updateWidthOnDataChanged === 'function' && cProto.updateWidthOnDataChanged.length === 0 && !cProto.updateWidthOnDataChanged41){
  9477.  
  9478. cProto.updateWidthOnDataChanged41 = cProto.updateWidthOnDataChanged;
  9479. cProto.updateWidthOnDataChanged = dProto.updateWidthOnDataChangedAdv || (dProto.updateWidthOnDataChangedAdv = function(){
  9480. const style = this.hostElement.style;
  9481. style.width = "";
  9482. style.overflow = "";
  9483. });
  9484.  
  9485. }
  9486.  
  9487.  
  9488. if (!cProto.setStandardContainerWidth8447) {
  9489. cProto.setStandardContainerWidth8447 = dProto.setStandardContainerWidthAdv || (dProto.setStandardContainerWidthAdv = async function (kName) {
  9490.  
  9491. if (this.__startCountdownAdv477__) Promise.resolve(this).then(timeFn749);
  9492.  
  9493. const hostElement = (this || 0).hostElement;
  9494. const container = this.$.container;
  9495.  
  9496. let qw = null;
  9497. let qt = '';
  9498.  
  9499. {
  9500.  
  9501. let maxC = 4;
  9502.  
  9503. for (let p = qt = hostElement.getAttribute('r6-ticker-width') || ''; maxC--;) {
  9504.  
  9505. const ed = `${hostElement.id}`
  9506. if (!p || !p.startsWith(`${ed}::`)) {
  9507.  
  9508. const w = hostElement.style.width;
  9509. if (w !== '' && w !== 'auto') hostElement.style.width = 'auto';
  9510.  
  9511. const res = await widthReq(container);
  9512.  
  9513. if (res.width < 1 || !Number.isFinite(res.width)) {
  9514. // just skip due to iron-page hidden
  9515. return;
  9516. }
  9517.  
  9518. hostElement.setAttribute('r6-ticker-width', p = qt = `${ed}::${(res.width).toFixed(2)}`);
  9519.  
  9520. } else {
  9521. qw = p.split('::');
  9522. break;
  9523. }
  9524.  
  9525. }
  9526.  
  9527. }
  9528.  
  9529. if (!qw) {
  9530.  
  9531. console.log('container width failure');
  9532. if(kName === 'setContainerWidth') this.setContainerWidth41(); else this.setRevampContainerWidth41();
  9533. return; // failure
  9534. }
  9535.  
  9536.  
  9537. const shouldAnimateIn = ((this || 0).ytLiveChatTickerItemBehavior || 0).shouldAnimateIn || (this || 0).shouldAnimateIn || false;
  9538. if (shouldAnimateIn) {
  9539.  
  9540. stackDM(async () => {
  9541.  
  9542. if (hostElement.getAttribute('r6-ticker-width') !== qt || hostElement.isConnected !== true) return;
  9543. if (hostElement.previousElementSibling || isTickerItemsScrolling()) {
  9544.  
  9545. hostElement.style.width = `${qw[1]}px`;
  9546.  
  9547. } else {
  9548.  
  9549. const w = hostElement.style.width;
  9550. if (w !== '0px' && w !== '0') hostElement.style.width = '0';
  9551.  
  9552. await widthReq(container);
  9553.  
  9554. hostElement.style.width = `${qw[1]}px`;
  9555. }
  9556.  
  9557.  
  9558. });
  9559.  
  9560.  
  9561. } else {
  9562.  
  9563.  
  9564. stackDM(async () => {
  9565.  
  9566.  
  9567.  
  9568. if (hostElement.getAttribute('r6-ticker-width') !== qt || hostElement.isConnected !== true) return;
  9569.  
  9570. hostElement.style.width = `${qw[1]}px`;
  9571.  
  9572. });
  9573. }
  9574.  
  9575.  
  9576.  
  9577. });
  9578. }
  9579.  
  9580. if (typeof cProto.setRevampContainerWidth === 'function' && !cProto.setRevampContainerWidth41 && cProto.setRevampContainerWidth.length === 0 && typeof cProto.setStandardContainerWidth8447 === 'function' && cProto.setStandardContainerWidth8447.length === 1) {
  9581. cProto.setRevampContainerWidth41 = cProto.setRevampContainerWidth;
  9582. if (ENABLE_TICKERS_BOOSTED_STAMPING && DISABLE_DYNAMIC_TICKER_WIDTH) {
  9583.  
  9584. cProto.setRevampContainerWidth = dProto.setRevampContainerWidthAdv || (dProto.setRevampContainerWidthAdv = async function () {
  9585. const hostElement = this.hostElement;
  9586. if (((hostElement || 0).style || 0).width) hostElement.style.width = '';
  9587. return;
  9588. });
  9589.  
  9590. } else {
  9591.  
  9592.  
  9593.  
  9594. cProto.setRevampContainerWidth = dProto.setRevampContainerWidthAdv || (dProto.setRevampContainerWidthAdv = async function () {
  9595.  
  9596. // not sure the reason for auto instead of pixel.
  9597. // this is a new function in Dec 2024, but not mainly adopted in the coding yet
  9598.  
  9599. /*
  9600. var a = this;
  9601. (R(this.hostElement).querySelector("#container").clientWidth || 0) === 0 ? (this.hostElement.style.overflow = "visible",
  9602. this.hostElement.style.width = "auto") : (this.hostElement.style.overflow = "hidden",
  9603. this.ytLiveChatTickerItemBehavior.shouldAnimateIn ? (this.hostElement.style.width = "0",
  9604. Zu(function() {
  9605. a.hostElement.style.width = "auto"
  9606. }, 1)) : this.hostElement.style.width = "auto")
  9607. */
  9608.  
  9609.  
  9610. return this.setStandardContainerWidth8447('setRevampContainerWidth');
  9611.  
  9612. });
  9613. }
  9614.  
  9615.  
  9616. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::setRevampContainerWidth - OK`)
  9617. } else {
  9618.  
  9619. DEBUG_skipLog001 || console1.log(`USE_ADVANCED_TICKING[#${tagI}]::setRevampContainerWidth - NG (acceptable)`)
  9620. }
  9621.  
  9622.  
  9623. if (typeof cProto.setContainerWidth === 'function' && !cProto.setContainerWidth41 && cProto.setContainerWidth.length === 0 && typeof cProto.setStandardContainerWidth8447 === 'function' && cProto.setStandardContainerWidth8447.length === 1) {
  9624. cProto.setContainerWidth41 = cProto.setContainerWidth;
  9625.  
  9626. if (ENABLE_TICKERS_BOOSTED_STAMPING && DISABLE_DYNAMIC_TICKER_WIDTH) {
  9627.  
  9628. cProto.setContainerWidth = dProto.setContainerWidthAdv || (dProto.setContainerWidthAdv = async function () {
  9629. const hostElement = this.hostElement;
  9630. if (((hostElement || 0).style || 0).width) hostElement.style.width = '';
  9631. return;
  9632. });
  9633.  
  9634. } else {
  9635.  
  9636. cProto.setContainerWidth = dProto.setContainerWidthAdv || (dProto.setContainerWidthAdv = async function () {
  9637.  
  9638.  
  9639.  
  9640. /*
  9641. var a = this
  9642. , b = R(this.hostElement).querySelector("#container").clientWidth || 0;
  9643. b === 0 ? (this.hostElement.style.overflow = "visible",
  9644. this.hostElement.style.width = "auto") : (this.hostElement.style.overflow = "hidden",
  9645. this.shouldAnimateIn ? (this.hostElement.style.width = "0",
  9646. Zu(function() {
  9647. a.hostElement.style.width = b + "px"
  9648. }, 1)) : this.hostElement.style.width = b + "px")
  9649. */
  9650. return this.setStandardContainerWidth8447('setContainerWidth');
  9651.  
  9652. });
  9653.  
  9654. }
  9655.  
  9656.  
  9657.  
  9658. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::setContainerWidth - OK`)
  9659. } else {
  9660.  
  9661.  
  9662. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::setContainerWidth - NG`)
  9663. }
  9664.  
  9665.  
  9666.  
  9667.  
  9668. } else if (USE_ADVANCED_TICKING) {
  9669. console1.log(`USE_ADVANCED_TICKING[#${tagI}] is not injected.`);
  9670. }
  9671.  
  9672.  
  9673.  
  9674. }
  9675.  
  9676. const selector = tags.join(', ');
  9677. const elements = document.querySelectorAll(selector);
  9678. if (elements.length >= 1) {
  9679. for (const elm of elements) {
  9680. if (insp(elm).isAttached === true) {
  9681. fpTicker(elm);
  9682. }
  9683. }
  9684. }
  9685.  
  9686. console1.log("[End]");
  9687. groupEnd();
  9688.  
  9689.  
  9690. }).catch(console.warn);
  9691.  
  9692. if(FIX_MEMORY_LEAKAGE_TICKER_DATACHANGED_setContainerWidth){
  9693.  
  9694. /**
  9695. *
  9696. *
  9697. *
  9698. *
  9699. cT.prototype.dataChanged = function() {
  9700. var a = this;
  9701. this.data && (Q(this.hostElement).querySelector("#content").style.color = this.ytLiveChatTickerItemBehavior.colorFromDecimal(this.data.detailTextColor),
  9702. this.hostElement.ariaLabel = this.computeAriaLabel(this.data),
  9703. this.ytLiveChatTickerItemBehavior.startCountdown(this.data.durationSec, this.data.fullDurationSec),
  9704. qw(function() {
  9705. a.ytLiveChatTickerItemBehavior.setContainerWidth()
  9706. }))
  9707. }
  9708.  
  9709.  
  9710. znb.prototype.dataChanged = function(a) {
  9711. var b = this;
  9712. a && (a.tickerThumbnails.length > 1 && Q(this.hostElement).querySelector("#content").classList.add("multiple-thumbnails"),
  9713. this.ytLiveChatTickerItemBehavior.startCountdown(a.durationSec, a.fullDurationSec),
  9714. qw(function() {
  9715. b.ytLiveChatTickerItemBehavior.setContainerWidth()
  9716. }))
  9717. }
  9718.  
  9719. *
  9720. */
  9721.  
  9722. const dProto = {
  9723. dataChanged54500: function () {
  9724. // prevent memory leakage due to _.ytLiveChatTickerItemBehavior.setContainerWidth() in _.dataChanged
  9725. if (typeof (this.ytLiveChatTickerItemBehavior || 0).setContainerWidth === 'function') {
  9726. try {
  9727. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  9728. return this.dataChanged544.call(this.__proxySelf0__);
  9729. } catch (e) {
  9730. console.log('dataChanged54500 ERROR');
  9731. console.error(e);
  9732. }
  9733. } else {
  9734. return this.dataChanged544();
  9735. }
  9736. },
  9737. dataChanged54501: function (a) {
  9738. // prevent memory leakage due to _.ytLiveChatTickerItemBehavior.setContainerWidth() in _.dataChanged
  9739. if (typeof (this.ytLiveChatTickerItemBehavior || 0).setContainerWidth === 'function') {
  9740. try {
  9741. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  9742. return this.dataChanged544.call(this.__proxySelf0__, a);
  9743. } catch (e) {
  9744. console.log('dataChanged54501 ERROR');
  9745. console.error(e);
  9746. }
  9747. } else {
  9748. return this.dataChanged544(a);
  9749. }
  9750. },
  9751. }
  9752.  
  9753. for (const sto of [
  9754. 'yt-live-chat-ticker-sponsor-item-renderer',
  9755. 'yt-live-chat-ticker-paid-sticker-item-renderer'
  9756. ].map(tag => [tag, customElements.whenDefined(tag)])) {
  9757.  
  9758. const [tag, promise] = sto;
  9759.  
  9760. promise.then(()=>{
  9761.  
  9762. const dummy = document.createElement(tag);
  9763.  
  9764. const cProto = getProto(dummy);
  9765. if (!cProto || !cProto.attached) {
  9766. console.warn(`proto.attached for ${tag} is unavailable.`);
  9767. return;
  9768. }
  9769.  
  9770. if (!cProto.dataChanged || cProto.dataChanged544 || typeof cProto.dataChanged !== 'function' || !(cProto.dataChanged.length >= 0 && cProto.dataChanged.length <= 1)) return;
  9771.  
  9772. cProto.dataChanged544 = cProto.dataChanged;
  9773.  
  9774. if (cProto.dataChanged.length === 0) cProto.dataChanged = dProto.dataChanged54500;
  9775. else if (cProto.dataChanged.length === 1) cProto.dataChanged = dProto.dataChanged54501;
  9776.  
  9777.  
  9778.  
  9779. })
  9780.  
  9781.  
  9782. }
  9783.  
  9784. }
  9785.  
  9786. customElements.whenDefined('yt-live-chat-ticker-renderer').then(() => {
  9787.  
  9788. mightFirstCheckOnYtInit();
  9789. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-ticker-renderer hacks");
  9790. console1.log("[Begin]");
  9791. (() => {
  9792.  
  9793. /* pending!!
  9794.  
  9795. handleLiveChatAction
  9796.  
  9797. removeTickerItemById
  9798.  
  9799. _itemsChanged
  9800. itemsChanged
  9801.  
  9802. handleMarkChatItemAsDeletedAction
  9803. handleMarkChatItemsByAuthorAsDeletedAction
  9804. handleRemoveChatItemByAuthorAction
  9805.  
  9806.  
  9807. */
  9808.  
  9809. const tag = "yt-live-chat-ticker-renderer"
  9810. const dummy = document.createElement(tag);
  9811.  
  9812. const cProto = getProto(dummy);
  9813. if (!cProto || !cProto.attached) {
  9814. console1.warn(`proto.attached for ${tag} is unavailable.`);
  9815. return;
  9816. }
  9817.  
  9818. if (FIX_REMOVE_TICKER_ITEM_BY_ID && typeof cProto.splice === 'function' && typeof cProto.markDirty === 'function' && typeof cProto.removeTickerItemById === 'function' && !cProto.removeTickerItemById737) {
  9819. cProto.removeTickerItemById737 = cProto.removeTickerItemById;
  9820. cProto.removeTickerItemById = function (a) {
  9821. // console.log('removeTickerItemById#01', a);
  9822. if (this.tickerItemsQuery !== '#ticker-items' || typeof (a || 0) !== 'string') return this.removeTickerItemById737(a);
  9823. // console.log('removeTickerItemById#02', a);
  9824. const hostElement = this.hostElement;
  9825. if (!hostElement || !a) return this.removeTickerItemById737(a);
  9826. // console.log('removeTickerItemById#03', a);
  9827. const arr = hostElement.querySelectorAll(`[id="${a}"]`);
  9828. const s = new Set();
  9829. if (typeof (a || 0) === 'string') s.add(a);
  9830. for (const elem of arr) {
  9831. if (!elem) continue;
  9832. const elemId = elem.id;
  9833. if (!elemId) continue;
  9834. s.add(elemId);
  9835. const data = (insp(elem).data || 0);
  9836. if (data) {
  9837. const u = data.id;
  9838. if (u) s.add(u);
  9839. else data.id = elemId;
  9840. }
  9841. }
  9842. const tickerItems = this.tickerItems;
  9843. let deleteCount = 0;
  9844. for (let i = tickerItems.length - 1; i >= 0; i--) {
  9845. const obj = tickerItems[i];
  9846. if (!obj || typeof obj !== 'object') continue;
  9847. const key = firstObjectKey(obj);
  9848. if (!key) continue;
  9849. const dataObj = obj[key];
  9850. const dataId = (dataObj || 0).id;
  9851. if (s.has(dataId)) {
  9852. this.splice("tickerItems", i, 1);
  9853. this.markDirty();
  9854. deleteCount++;
  9855. }
  9856. }
  9857. // console.log('removeTickerItemById#06', a, deleteCount);
  9858. s.has(this.highlightId) && (this.highlightId = void 0);
  9859. // console.log('removeTickerItemById#07', a, deleteCount);
  9860. }
  9861. }
  9862.  
  9863. // const imgCollection = document.getElementsByTagName('IMG');
  9864.  
  9865. if (ENABLE_TICKERS_BOOSTED_STAMPING && typeof cProto.notifyPath === 'function' && cProto.notifyPath.length === 2 && typeof cProto.stampDomArraySplices_ === 'function' && cProto.stampDomArraySplices_.length === 3
  9866. && !cProto.notifyPath371 && !cProto.proceedStampDomArraySplices371_
  9867. && !cProto.stampDomArraySplices371_ && !cProto.stampDomArray366_) {
  9868.  
  9869. rendererStamperFactory(cProto, {
  9870. key: 'proceedStampDomArraySplices371_',
  9871. stamperDomClass: 'style-scope yt-live-chat-ticker-renderer yt-live-chat-ticker-stampdom'
  9872. });
  9873.  
  9874. cProto.notifyPath371 = cProto.notifyPath;
  9875.  
  9876. cProto.stampDomArraySplices371_ = cProto.stampDomArraySplices_;
  9877.  
  9878. if (typeof cProto.stampDomArraySplices371_ === 'function' && cProto.stampDomArraySplices371_.length >= 3) {
  9879. cProto.stampDomArraySplices_ = function (a, b, c) {
  9880. if (a === 'tickerItems' && b === 'ticker-items' && (c || 0).indexSplices) {
  9881. // if (this.ec388) {
  9882. const indexSplices = c.indexSplices;
  9883. if (indexSplices.length === 1 || typeof indexSplices.length === "undefined") {
  9884. const indexSplice = indexSplices[0] || indexSplices;
  9885. if (indexSplice.type === 'splice' && (indexSplice.addedCount >= 1 || (indexSplice.removed || 0).length >= 1)) {
  9886. // console.log(1059, a, b, indexSplice);
  9887. if (this.proceedStampDomArraySplices371_(a, b, indexSplice)) return;
  9888. }
  9889. }
  9890. // } else {
  9891. // console.warn('stampDomArraySplices_ warning', ...arguments);
  9892. // }
  9893. }
  9894. return this.stampDomArraySplices371_(...arguments);
  9895. };
  9896. } else {
  9897. console.warn('0xF0230 Function Signature Changed');
  9898. }
  9899.  
  9900. cProto.stampDomArray366_ = cProto.stampDomArray_;
  9901. if (typeof cProto.stampDomArray366_ === 'function' && cProto.stampDomArray366_.length >= 5) {
  9902. cProto.stampDomArray_ = function (items, containerId, componentConfig, rxConfig, shouldCallback, isStableList) {
  9903. const isTickerRendering = items === this.tickerItems && containerId === 'ticker-items';
  9904. const isMessageListRendering = items === this.visibleItems && containerId === 'items';
  9905.  
  9906. if (!isTickerRendering && !isMessageListRendering) {
  9907. console.log('stampDomArray_ warning 0xF501', ...arguments)
  9908. return this.stampDomArray366_(...arguments);
  9909. }
  9910.  
  9911. const container = (this.$ || 0)[containerId];
  9912. if (!container) {
  9913. console.log('stampDomArray_ warning 0xF502', ...arguments)
  9914. return this.stampDomArray366_(...arguments);
  9915. }
  9916.  
  9917. if (container[sFirstElementChild] === null && items.length === 0) {
  9918.  
  9919. } else {
  9920. const cTag = isTickerRendering ? 'tickerItems' : 'visibleItems';
  9921. this.proceedStampDomArraySplices371_(cTag, containerId, {
  9922. addedCount: items.length,
  9923. removedCount: container.childElementCount
  9924. });
  9925. }
  9926.  
  9927. const f = () => {
  9928. this.markDirty && this.markDirty();
  9929. const detail = {
  9930. container
  9931. };
  9932. shouldCallback && this.hostElement.dispatchEvent(new CustomEvent("yt-rendererstamper-finished", {
  9933. bubbles: !0,
  9934. cancelable: !1,
  9935. composed: !0,
  9936. detail
  9937. }));
  9938. detail.container = null;
  9939. };
  9940.  
  9941. if (this.ec389pr) {
  9942. this.ec389pr.then(f)
  9943. } else {
  9944. f();
  9945. }
  9946.  
  9947. };
  9948. } else {
  9949. console.warn('0xF0230 Function Signature Changed');
  9950. }
  9951.  
  9952. }
  9953.  
  9954. if (typeof cProto.createComponent_ === 'function' && cProto.createComponent_.length === 3 && !cProto.createComponent58_) {
  9955.  
  9956. cProto.createComponent58_ = cProto.createComponent_;
  9957. cProto.createComponent_ = function (a, b, c) {
  9958.  
  9959. const z = customCreateComponent(a, b, c);
  9960. if (z !== undefined) return z;
  9961. const r = this.createComponent58_(a, b, c);
  9962. return r;
  9963.  
  9964. }
  9965.  
  9966. } else {
  9967. console.warn('0xF0230 Function Signature Changed');
  9968. }
  9969.  
  9970.  
  9971. /* Dec 2024 */
  9972.  
  9973. /*
  9974.  
  9975.  
  9976. f.handleLiveChatActions = function(a) {
  9977. a.length && (a.forEach(this.handleLiveChatAction, this),
  9978. this.updateHighlightedItem(),
  9979. this.shouldAnimateIn = !0)
  9980. }
  9981. ;
  9982. f.handleLiveChatAction = function(a) {
  9983. var b = z(a, fL)
  9984. , c = z(a, gL)
  9985. , d = z(a, eL)
  9986. , e = z(a, gdb)
  9987. , g = z(a, rdb)
  9988. , k = z(a, Deb);
  9989. a = z(a, Ceb);
  9990. b ? this.unshift("tickerItems", b.item) : c ? this.handleMarkChatItemAsDeletedAction(c) : d ? this.removeTickerItemById(d.targetItemId) : e ? this.handleMarkChatItemsByAuthorAsDeletedAction(e) : g ? this.handleRemoveChatItemByAuthorAction(g) : k ? this.showCreatorGoalTickerChip(k) : a && this.removeCreatorGoalTickerChip(a)
  9991. }
  9992. */
  9993.  
  9994.  
  9995. if (USE_ADVANCED_TICKING && !cProto.handleLiveChatActions47 && typeof cProto.handleLiveChatActions === 'function' && cProto.handleLiveChatActions.length === 1) {
  9996.  
  9997. cProto.handleLiveChatActions47 = cProto.handleLiveChatActions;
  9998.  
  9999. cProto.handleLiveChatActions = function (a) {
  10000.  
  10001. // first loading in livestream. so this is required for sorting.
  10002.  
  10003. try {
  10004. preprocessChatLiveActions(a);
  10005. } catch (e) {
  10006. console.warn(e);
  10007. }
  10008. return this.handleLiveChatActions47(a);
  10009.  
  10010. }
  10011.  
  10012. console1.log("USE_ADVANCED_TICKING::handleLiveChatActions - OK");
  10013.  
  10014. } else if (USE_ADVANCED_TICKING) {
  10015.  
  10016.  
  10017. console1.log("USE_ADVANCED_TICKING::handleLiveChatActions - NG");
  10018.  
  10019. }
  10020.  
  10021. // yt-live-chat-ticker-renderer hacks
  10022.  
  10023.  
  10024. if (RAF_FIX_keepScrollClamped) {
  10025.  
  10026. // to be improved
  10027.  
  10028. if (typeof cProto.keepScrollClamped === 'function' && !cProto.keepScrollClamped72 && fnIntegrity(cProto.keepScrollClamped) === '0.17.10') {
  10029.  
  10030. cProto.keepScrollClamped72 = cProto.keepScrollClamped;
  10031. cProto.keepScrollClamped = function () {
  10032.  
  10033. const cnt = kRef(this);
  10034. if (!cnt) return;
  10035. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10036.  
  10037. cnt._bound_keepScrollClamped = cnt._bound_keepScrollClamped || cnt.keepScrollClamped.bind(mWeakRef(cnt));
  10038. cnt.scrollClampRaf = requestAnimationFrame(cnt._bound_keepScrollClamped);
  10039. cnt.maybeClampScroll()
  10040. }
  10041.  
  10042. console1.log('RAF_FIX: keepScrollClamped', tag, "OK")
  10043. } else {
  10044.  
  10045. assertor(() => fnIntegrity(cProto.keepScrollClamped, '0.17.10'));
  10046. console1.log('RAF_FIX: keepScrollClamped', tag, "NG")
  10047. }
  10048.  
  10049. }
  10050.  
  10051.  
  10052. if (RAF_FIX_scrollIncrementally && typeof cProto.startScrolling === 'function' && typeof cProto.scrollIncrementally === 'function'
  10053. && '|1.43.31|1.44.31|'.indexOf('|' + fnIntegrity(cProto.startScrolling) + '|') >= 0
  10054. && '|1.78.45|1.82.43|1.43.31|'.indexOf('|' + fnIntegrity(cProto.scrollIncrementally) + '|') >= 0) {
  10055. // to be replaced by animator
  10056.  
  10057. cProto.startScrolling = function (a) {
  10058.  
  10059. const cnt = kRef(this);
  10060. if (!cnt) return;
  10061. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10062.  
  10063. cnt.scrollStopHandle && cnt.cancelAsync(cnt.scrollStopHandle);
  10064. cnt.asyncHandle && cancelAnimationFrame(cnt.asyncHandle);
  10065. cnt.lastFrameTimestamp = cnt.scrollStartTime = performance.now();
  10066. cnt.scrollRatePixelsPerSecond = a;
  10067. cnt._bound_scrollIncrementally = cnt._bound_scrollIncrementally || cnt.scrollIncrementally.bind(mWeakRef(cnt));
  10068. cnt.asyncHandle = requestAnimationFrame(cnt._bound_scrollIncrementally)
  10069. };
  10070.  
  10071. // related functions: startScrollBack, startScrollingLeft, startScrollingRight, etc.
  10072.  
  10073. /**
  10074. *
  10075. * // 2024.12.17
  10076. * // https://www.youtube.com/s/desktop/f7495da0/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  10077.  
  10078. f.startScrolling = function(a) {
  10079. this.scrollStopHandle && $u(this.scrollStopHandle);
  10080. this.asyncHandle && window.cancelAnimationFrame(this.asyncHandle);
  10081. this.scrollStartTime = performance.now();
  10082. this.lastFrameTimestamp = performance.now();
  10083. this.scrollRatePixelsPerSecond = a;
  10084. this.asyncHandle = window.requestAnimationFrame(this.scrollIncrementally.bind(this))
  10085. }
  10086. ;
  10087. f.scrollIncrementally = function(a) {
  10088. var b = a - (this.lastFrameTimestamp || 0);
  10089. R(this.hostElement).querySelector(this.tickerBarQuery).scrollLeft += b / 1E3 * (this.scrollRatePixelsPerSecond || 0);
  10090. this.maybeClampScroll();
  10091. this.updateArrows();
  10092. this.lastFrameTimestamp = a;
  10093. R(this.hostElement).querySelector(this.tickerBarQuery).scrollLeft > 0 || this.scrollRatePixelsPerSecond && this.scrollRatePixelsPerSecond > 0 ? this.asyncHandle = window.requestAnimationFrame(this.scrollIncrementally.bind(this)) : this.stopScrolling()
  10094. }
  10095. ;
  10096. *
  10097. */
  10098.  
  10099. /**
  10100. *
  10101. // 2024.12.20
  10102.  
  10103.  
  10104.  
  10105. f.startScrolling = function(a) {
  10106. this.scrollStopHandle && av(this.scrollStopHandle);
  10107. this.asyncHandle && window.cancelAnimationFrame(this.asyncHandle);
  10108. this.scrollStartTime = performance.now();
  10109. this.lastFrameTimestamp = performance.now();
  10110. this.scrollRatePixelsPerSecond = a;
  10111. this.asyncHandle = window.requestAnimationFrame(this.scrollIncrementally.bind(this))
  10112. }
  10113.  
  10114. *
  10115. *
  10116. */
  10117.  
  10118. cProto.__getTickerBarQuery__ = function () {
  10119. const tickerBarQuery = this.tickerBarQuery === '#items' ? this.$.items : this.hostElement.querySelector(this.tickerBarQuery);
  10120. return tickerBarQuery;
  10121. }
  10122.  
  10123. cProto.scrollIncrementally = (RAF_FIX_scrollIncrementally === 2) ? function (a) {
  10124.  
  10125. const cnt = kRef(this);
  10126. if (!cnt) return;
  10127. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10128.  
  10129. const b = a - (cnt.lastFrameTimestamp || 0);
  10130. const rate = cnt.scrollRatePixelsPerSecond
  10131. const q = b / 1E3 * (rate || 0);
  10132.  
  10133. const tickerBarQuery = cnt.__getTickerBarQuery__();
  10134. if (!tickerBarQuery) return; // memory leakage. to be reviewed
  10135. const sl = tickerBarQuery.scrollLeft;
  10136. // console.log(rate, sl, q)
  10137. if (cnt.lastFrameTimestamp == cnt.scrollStartTime) {
  10138.  
  10139. } else if (q > -1e-5 && q < 1e-5) {
  10140.  
  10141. } else {
  10142. let cond1 = sl > 0 && rate > 0 && q > 0;
  10143. let cond2 = sl > 0 && rate < 0 && q < 0;
  10144. let cond3 = sl < 1e-5 && sl > -1e-5 && rate > 0 && q > 0;
  10145. if (cond1 || cond2 || cond3) {
  10146. tickerBarQuery.scrollLeft += q;
  10147. cnt.maybeClampScroll();
  10148. cnt.updateArrows();
  10149. }
  10150. }
  10151.  
  10152. cnt.lastFrameTimestamp = a;
  10153. cnt._bound_scrollIncrementally = cnt._bound_scrollIncrementally || cnt.scrollIncrementally.bind(mWeakRef(cnt));
  10154. 0 < tickerBarQuery.scrollLeft || rate && 0 < rate ? cnt.asyncHandle = requestAnimationFrame(cnt._bound_scrollIncrementally) : cnt.stopScrolling()
  10155. } : function (a) {
  10156.  
  10157. const cnt = kRef(this);
  10158. if (!cnt) return;
  10159. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10160.  
  10161. const b = a - (cnt.lastFrameTimestamp || 0);
  10162. const tickerBarQuery = cnt.__getTickerBarQuery__();
  10163. if (!tickerBarQuery) return; // memory leakage. to be reviewed
  10164. tickerBarQuery.scrollLeft += b / 1E3 * (cnt.scrollRatePixelsPerSecond || 0);
  10165. cnt.maybeClampScroll();
  10166. cnt.updateArrows();
  10167. cnt.lastFrameTimestamp = a;
  10168. cnt._bound_scrollIncrementally = cnt._bound_scrollIncrementally || cnt.scrollIncrementally.bind(mWeakRef(cnt));
  10169. 0 < tickerBarQuery.scrollLeft || cnt.scrollRatePixelsPerSecond && 0 < cnt.scrollRatePixelsPerSecond ? cnt.asyncHandle = requestAnimationFrame(cnt._bound_scrollIncrementally) : cnt.stopScrolling()
  10170. };
  10171.  
  10172. console1.log(`RAF_FIX: scrollIncrementally${RAF_FIX_scrollIncrementally}`, tag, "OK")
  10173. } else {
  10174. assertor(() => fnIntegrity(cProto.startScrolling, '1.43.31'))
  10175. || logFn('cProto.startScrolling', cProto.startScrolling)();
  10176. assertor(() => fnIntegrity(cProto.scrollIncrementally, '1.78.45'))
  10177. || logFn('cProto.scrollIncrementally', cProto.scrollIncrementally)();
  10178. console1.log('RAF_FIX: scrollIncrementally', tag, "NG")
  10179. }
  10180.  
  10181.  
  10182. if (CLOSE_TICKER_PINNED_MESSAGE_WHEN_HEADER_CLICKED && typeof cProto.attached === 'function' && !cProto.attached37 && typeof cProto.detached === 'function' && !cProto.detached37) {
  10183.  
  10184. cProto.attached37 = cProto.attached;
  10185. cProto.detached37 = cProto.detached;
  10186.  
  10187. let naohzId = 0;
  10188. cProto.__naohzId__ = 0;
  10189. cProto.attached = function () {
  10190. Promise.resolve(this).then((cnt) => {
  10191.  
  10192. const hostElement = cnt.hostElement || cnt;
  10193. if (!(hostElement instanceof HTMLElement_)) return;
  10194. if (!HTMLElement_.prototype.matches.call(hostElement, '.yt-live-chat-renderer')) return;
  10195. const ironPage = HTMLElement_.prototype.closest.call(hostElement, 'iron-pages.yt-live-chat-renderer');
  10196. // or #chat-messages
  10197. if (!ironPage) return;
  10198.  
  10199. if (cnt.__naohzId__) removeEventListener.call(ironPage, 'click', cnt.messageBoxClickHandlerForFade, { capture: false, passive: true });
  10200. cnt.__naohzId__ = naohzId = (naohzId & 1073741823) + 1;
  10201. ironPage.setAttribute('naohz', `${+cnt.__naohzId__}`);
  10202.  
  10203. addEventListener.call(ironPage, 'click', cnt.messageBoxClickHandlerForFade, { capture: false, passive: true });
  10204.  
  10205. cnt = null;
  10206.  
  10207. });
  10208. return this.attached37.apply(this, arguments);
  10209. };
  10210. cProto.detached = function () {
  10211. Promise.resolve(this).then((cnt) => {
  10212.  
  10213. const ironPage = document.querySelector(`iron-pages[naohz="${+cnt.__naohzId__}"]`);
  10214. if (!ironPage) return;
  10215.  
  10216. removeEventListener.call(ironPage, 'click', cnt.messageBoxClickHandlerForFade, { capture: false, passive: true });
  10217.  
  10218. cnt = null;
  10219.  
  10220. });
  10221. return this.detached37.apply(this, arguments);
  10222. };
  10223.  
  10224. const clickFade = (u) => {
  10225. u.click();
  10226. };
  10227. cProto.messageBoxClickHandlerForFade = async (evt) => {
  10228.  
  10229. const target = (evt || 0).target || 0;
  10230. if (!target) return;
  10231.  
  10232. for (let p = target; p instanceof HTMLElement_; p = nodeParent(p)) {
  10233. const is = p.is;
  10234. if (typeof is === 'string' && is) {
  10235.  
  10236. if (is === 'yt-live-chat-pinned-message-renderer') {
  10237. return;
  10238. }
  10239. if (is === 'iron-pages' || is === 'yt-live-chat-renderer' || is === 'yt-live-chat-app') {
  10240. const fade = HTMLElement_.prototype.querySelector.call(p, 'yt-live-chat-pinned-message-renderer:not([hidden]) #fade');
  10241. if (fade) {
  10242. Promise.resolve(fade).then(clickFade);
  10243. evt && evt.stopPropagation();
  10244. }
  10245. return;
  10246. }
  10247. if (is !== 'yt-live-chat-ticker-renderer') {
  10248. if (is.startsWith('yt-live-chat-ticker-')) return;
  10249. if (!is.endsWith('-renderer')) return;
  10250. }
  10251.  
  10252. } else {
  10253. if ((p.nodeName || '').includes('BUTTON')) return;
  10254. }
  10255.  
  10256. }
  10257. };
  10258.  
  10259. console1.log("CLOSE_TICKER_PINNED_MESSAGE_WHEN_HEADER_CLICKED - OK")
  10260.  
  10261. } else {
  10262. console1.log("CLOSE_TICKER_PINNED_MESSAGE_WHEN_HEADER_CLICKED - NG")
  10263. }
  10264.  
  10265.  
  10266. })();
  10267.  
  10268. console1.log("[End]");
  10269.  
  10270. groupEnd();
  10271.  
  10272. }).catch(console.warn);
  10273.  
  10274.  
  10275.  
  10276. if (ENABLE_RAF_HACK_INPUT_RENDERER || DELAY_FOCUSEDCHANGED) {
  10277.  
  10278. customElements.whenDefined("yt-live-chat-message-input-renderer").then(() => {
  10279.  
  10280. mightFirstCheckOnYtInit();
  10281. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-message-input-renderer hacks");
  10282. console1.log("[Begin]");
  10283. (() => {
  10284.  
  10285.  
  10286.  
  10287. const tag = "yt-live-chat-message-input-renderer"
  10288. const dummy = document.createElement(tag);
  10289.  
  10290. const cProto = getProto(dummy);
  10291. if (!cProto || !cProto.attached) {
  10292. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10293. return;
  10294. }
  10295.  
  10296.  
  10297. if (ENABLE_RAF_HACK_INPUT_RENDERER && rafHub !== null) {
  10298.  
  10299. let doHack = false;
  10300. if (typeof cProto.handleTimeout === 'function' && typeof cProto.updateTimeout === 'function') {
  10301.  
  10302. // not cancellable
  10303.  
  10304. // <<< to be reviewed cProto.updateTimeout --- isTimingFunctionHackable -- doHack >>>
  10305.  
  10306. doHack = fnIntegrity(cProto.handleTimeout, '1.27.16') && fnIntegrity(cProto.updateTimeout, '1.50.33');
  10307.  
  10308. if (!doHack) console1.log('doHack = false')
  10309.  
  10310. }
  10311. // doHack = false; // M55
  10312.  
  10313. if (doHack) {
  10314.  
  10315. cProto.handleTimeout = function (a) {
  10316.  
  10317. const cnt = kRef(this);
  10318. if (!cnt) return;
  10319. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10320.  
  10321. console.log('cProto.handleTimeout', tag)
  10322. if (!cnt.boundUpdateTimeout38_) cnt.boundUpdateTimeout38_ = cnt.updateTimeout.bind(mWeakRef(cnt));
  10323. cnt.timeoutDurationMs = cnt.timeoutMs = a;
  10324. cnt.countdownRatio = 1;
  10325. 0 === cnt.lastTimeoutTimeMs && rafHub.request(cnt.boundUpdateTimeout38_)
  10326. };
  10327. cProto.updateTimeout = function (a) {
  10328.  
  10329. const cnt = kRef(this);
  10330. if (!cnt) return;
  10331. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10332.  
  10333. console.log('cProto.updateTimeout', tag)
  10334. if (!cnt.boundUpdateTimeout38_) cnt.boundUpdateTimeout38_ = cnt.updateTimeout.bind(mWeakRef(cnt));
  10335. cnt.lastTimeoutTimeMs && (cnt.timeoutMs = Math.max(0, cnt.timeoutMs - (a - cnt.lastTimeoutTimeMs)),
  10336. cnt.countdownRatio = cnt.timeoutMs / cnt.timeoutDurationMs);
  10337. cnt.isAttached && cnt.timeoutMs ? (cnt.lastTimeoutTimeMs = a,
  10338. rafHub.request(cnt.boundUpdateTimeout38_)) : cnt.lastTimeoutTimeMs = 0
  10339. };
  10340.  
  10341. console1.log('RAF_HACK_INPUT_RENDERER', tag, "OK")
  10342. } else {
  10343.  
  10344. console1.log('typeof handleTimeout', typeof cProto.handleTimeout)
  10345. console1.log('typeof updateTimeout', typeof cProto.updateTimeout)
  10346.  
  10347. console1.log('RAF_HACK_INPUT_RENDERER', tag, "NG")
  10348. }
  10349.  
  10350.  
  10351. }
  10352.  
  10353. if (DELAY_FOCUSEDCHANGED && typeof cProto.onFocusedChanged === 'function' && cProto.onFocusedChanged.length === 1 && !cProto.onFocusedChanged372) {
  10354. cProto.onFocusedChanged372 = cProto.onFocusedChanged;
  10355. cProto.onFocusedChanged = function (a) {
  10356. Promise.resolve(this).then((cnt) => {
  10357. if (cnt.isAttached === true) cnt.onFocusedChanged372(a);
  10358. cnt = null;
  10359. }).catch(console.warn);
  10360. }
  10361. }
  10362.  
  10363. })();
  10364.  
  10365. console1.log("[End]");
  10366.  
  10367. groupEnd();
  10368.  
  10369.  
  10370. })
  10371.  
  10372. }
  10373.  
  10374.  
  10375. if (ENABLE_RAF_HACK_EMOJI_PICKER && rafHub !== null) {
  10376.  
  10377. customElements.whenDefined("yt-emoji-picker-renderer").then(() => {
  10378.  
  10379. mightFirstCheckOnYtInit();
  10380. groupCollapsed("YouTube Super Fast Chat", " | yt-emoji-picker-renderer hacks");
  10381. console1.log("[Begin]");
  10382. (() => {
  10383.  
  10384. const tag = "yt-emoji-picker-renderer"
  10385. const dummy = document.createElement(tag);
  10386.  
  10387. const cProto = getProto(dummy);
  10388. if (!cProto || !cProto.attached) {
  10389. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10390. return;
  10391. }
  10392.  
  10393. let doHack = false;
  10394. if (typeof cProto.animateScroll_ === 'function') {
  10395.  
  10396. // not cancellable
  10397. console1.log('animateScroll_: function - OK')
  10398.  
  10399. doHack = fnIntegrity(cProto.animateScroll_, '1.102.49')
  10400.  
  10401. } else {
  10402.  
  10403. console1.log('animateScroll_', typeof cProto.animateScroll_)
  10404. }
  10405.  
  10406. if (doHack) {
  10407.  
  10408. const querySelector = HTMLElement_.prototype.querySelector;
  10409. const U = (element) => ({
  10410. querySelector: (selector) => querySelector.call(element, selector)
  10411. });
  10412.  
  10413. cProto.animateScroll_ = function (a) {
  10414.  
  10415. const cnt = kRef(this);
  10416. if (!cnt) return;
  10417. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10418.  
  10419. // console.log('cProto.animateScroll_', tag) // yt-emoji-picker-renderer
  10420. if (!cnt.boundAnimateScroll39_) cnt.boundAnimateScroll39_ = cnt.animateScroll_.bind(mWeakRef(cnt));
  10421. cnt.lastAnimationTime_ || (cnt.lastAnimationTime_ = a);
  10422. a -= cnt.lastAnimationTime_;
  10423. 200 > a ? (U(cnt.hostElement).querySelector("#categories").scrollTop = cnt.animationStart_ + (cnt.animationEnd_ - cnt.animationStart_) * a / 200,
  10424. rafHub.request(cnt.boundAnimateScroll39_)) : (null != cnt.animationEnd_ && (U(cnt.hostElement).querySelector("#categories").scrollTop = cnt.animationEnd_),
  10425. cnt.animationEnd_ = cnt.animationStart_ = null,
  10426. cnt.lastAnimationTime_ = 0);
  10427. cnt.updateButtons_()
  10428. }
  10429.  
  10430. console1.log('ENABLE_RAF_HACK_EMOJI_PICKER', tag, "OK")
  10431. } else {
  10432.  
  10433. console1.log('ENABLE_RAF_HACK_EMOJI_PICKER', tag, "NG")
  10434. }
  10435.  
  10436. })();
  10437.  
  10438. console1.log("[End]");
  10439.  
  10440. groupEnd();
  10441. });
  10442. }
  10443.  
  10444. if (ENABLE_RAF_HACK_DOCKED_MESSAGE && rafHub !== null) {
  10445.  
  10446. customElements.whenDefined("yt-live-chat-docked-message").then(() => {
  10447.  
  10448. mightFirstCheckOnYtInit();
  10449. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-docked-message hacks");
  10450. console1.log("[Begin]");
  10451. (() => {
  10452.  
  10453. const tag = "yt-live-chat-docked-message"
  10454. const dummy = document.createElement(tag);
  10455.  
  10456. const cProto = getProto(dummy);
  10457. if (!cProto || !cProto.attached) {
  10458. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10459. return;
  10460. }
  10461.  
  10462. let doHack = false;
  10463. if (typeof cProto.detached === 'function' && typeof cProto.checkIntersections === 'function' && typeof cProto.onDockableMessagesChanged === 'function' && typeof cProto.boundCheckIntersections === 'undefined') {
  10464.  
  10465. // cancelable - this.intersectRAF <detached>
  10466. // yt-live-chat-docked-message
  10467. // boundCheckIntersections <-> checkIntersections
  10468. // onDockableMessagesChanged
  10469. // this.intersectRAF = window.requestAnimationFrame(this.boundCheckIntersections);
  10470.  
  10471. console1.log(`detached: function - OK`)
  10472. console1.log('checkIntersections: function - OK')
  10473. console1.log('onDockableMessagesChanged: function - OK')
  10474.  
  10475. doHack = fnIntegrity(cProto.detached, '0.32.22') && fnIntegrity(cProto.checkIntersections, '0.128.85') && fnIntegrity(cProto.onDockableMessagesChanged, '0.20.11')
  10476.  
  10477. } else {
  10478.  
  10479. console1.log('detached', typeof cProto.detached, 'NG')
  10480. console1.log('checkIntersections', typeof cProto.checkIntersections, 'NG')
  10481. console1.log('onDockableMessagesChanged', typeof cProto.onDockableMessagesChanged, 'NG')
  10482. }
  10483.  
  10484. if (doHack) {
  10485.  
  10486. cProto.__boundCheckIntersectionsSubstitutionFn__ = function () {
  10487. const cnt = this;
  10488. if (!cnt.i5zmk && typeof cnt.boundCheckIntersections === 'function' && typeof cnt.checkIntersections === 'function') {
  10489. cnt.i5zmk = 1
  10490. cnt.boundCheckIntersections = cnt.checkIntersections.bind(mWeakRef(cnt));
  10491. }
  10492. }
  10493.  
  10494. cProto.checkIntersections = function () {
  10495.  
  10496. const cnt = kRef(this);
  10497. if (!cnt) return;
  10498. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10499.  
  10500. if(typeof cnt.__boundCheckIntersectionsSubstitutionFn__ === 'function') cnt.__boundCheckIntersectionsSubstitutionFn__();
  10501.  
  10502. // console.log('cProto.checkIntersections', tag)
  10503. if (cnt.dockableMessages.length) {
  10504. cnt.intersectRAF = rafHub.request(cnt.boundCheckIntersections);
  10505. let a = cnt.dockableMessages[0]
  10506. , b = cnt.hostElement.getBoundingClientRect();
  10507. a = a.getBoundingClientRect();
  10508. let c = a.top - b.top
  10509. , d = 8 >= c;
  10510. c = 8 >= c - cnt.hostElement.clientHeight;
  10511. if (d) {
  10512. let e;
  10513. for (; d;) {
  10514. e = cnt.dockableMessages.shift();
  10515. d = cnt.dockableMessages[0];
  10516. if (!d)
  10517. break;
  10518. d = d.getBoundingClientRect();
  10519. c = d.top - b.top;
  10520. let f = 8 >= c;
  10521. if (8 >= c - a.height)
  10522. if (f)
  10523. a = d;
  10524. else
  10525. return;
  10526. d = f
  10527. }
  10528. cnt.dock(e)
  10529. } else
  10530. c && cnt.dockedItem && cnt.clear()
  10531. } else
  10532. cnt.intersectRAF = 0
  10533. }
  10534.  
  10535. cProto.onDockableMessagesChanged = function () {
  10536. const cnt = this;
  10537. if(typeof cnt.__boundCheckIntersectionsSubstitutionFn__ === 'function') cnt.__boundCheckIntersectionsSubstitutionFn__();
  10538. // console.log('cProto.onDockableMessagesChanged', tag) // yt-live-chat-docked-message
  10539. cnt.dockableMessages.length && !cnt.intersectRAF && (cnt.intersectRAF = rafHub.request(cnt.boundCheckIntersections))
  10540. }
  10541.  
  10542. cProto.detached = function () {
  10543. this.intersectRAF && rafHub.cancel(this.intersectRAF)
  10544. }
  10545.  
  10546. console1.log('ENABLE_RAF_HACK_DOCKED_MESSAGE', tag, "OK")
  10547. } else {
  10548.  
  10549. console1.log('ENABLE_RAF_HACK_DOCKED_MESSAGE', tag, "NG")
  10550. }
  10551.  
  10552. })();
  10553.  
  10554. console1.log("[End]");
  10555.  
  10556. groupEnd();
  10557.  
  10558. }).catch(console.warn);
  10559.  
  10560. }
  10561.  
  10562. if (FIX_SETSRC_AND_THUMBNAILCHANGE_) {
  10563.  
  10564. customElements.whenDefined("yt-img-shadow").then(() => {
  10565.  
  10566. mightFirstCheckOnYtInit();
  10567. groupCollapsed("YouTube Super Fast Chat", " | yt-img-shadow hacks");
  10568. console1.log("[Begin]");
  10569. (() => {
  10570.  
  10571. const tag = "yt-img-shadow"
  10572. const dummy = document.createElement(tag);
  10573.  
  10574. const cProto = getProto(dummy);
  10575. if (!cProto || !cProto.attached) {
  10576. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10577. return;
  10578. }
  10579.  
  10580. if (typeof cProto.thumbnailChanged_ === 'function' && !cProto.thumbnailChanged66_) {
  10581.  
  10582. cProto.thumbnailChanged66_ = cProto.thumbnailChanged_;
  10583. cProto.thumbnailChanged_ = function (a) {
  10584.  
  10585. if (this.oldThumbnail_ && this.thumbnail && this.oldThumbnail_.thumbnails === this.thumbnail.thumbnails) return;
  10586. if (!this.oldThumbnail_ && !this.thumbnail) return;
  10587.  
  10588. return this.thumbnailChanged66_.apply(this, arguments)
  10589.  
  10590. }
  10591. console1.log("cProto.thumbnailChanged_ - OK");
  10592.  
  10593. } else {
  10594. console1.log("cProto.thumbnailChanged_ - NG");
  10595.  
  10596. }
  10597. if (typeof cProto.setSrc_ === 'function' && !cProto.setSrc66_) {
  10598.  
  10599. cProto.setSrc66_ = cProto.setSrc_;
  10600. cProto.setSrc_ = function (a) {
  10601. if ((((this || 0).$ || 0).img || 0).src === a) return;
  10602. return this.setSrc66_.apply(this, arguments)
  10603. }
  10604.  
  10605. console1.log("cProto.setSrc_ - OK");
  10606. } else {
  10607.  
  10608. console1.log("cProto.setSrc_ - NG");
  10609. }
  10610.  
  10611. })();
  10612.  
  10613. console1.log("[End]");
  10614.  
  10615. groupEnd();
  10616.  
  10617. }).catch(console.warn);
  10618.  
  10619. }
  10620.  
  10621. if (FIX_THUMBNAIL_DATACHANGED) {
  10622.  
  10623. customElements.whenDefined("yt-live-chat-author-badge-renderer").then(() => {
  10624.  
  10625. mightFirstCheckOnYtInit();
  10626. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-author-badge-renderer hacks");
  10627. console1.log("[Begin]");
  10628. (() => {
  10629.  
  10630. const tag = "yt-live-chat-author-badge-renderer"
  10631. const dummy = document.createElement(tag);
  10632.  
  10633. const cProto = getProto(dummy);
  10634. if (!cProto || !cProto.attached) {
  10635. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10636. return;
  10637. }
  10638.  
  10639. if (typeof cProto.dataChanged === 'function' && !cProto.dataChanged86 && '|0.169.106|'.includes(`|${fnIntegrity(cProto.dataChanged)}|`)) {
  10640.  
  10641. cProto.dataChanged86 = cProto.dataChanged;
  10642. cProto.dataChanged = function () {
  10643.  
  10644. /* 2024.12.15 */
  10645. /*
  10646. zO.prototype.dataChanged = function() {
  10647. for (var a = Ov(R(this.hostElement).querySelector("#image")); a.firstChild; )
  10648. a.removeChild(a.firstChild);
  10649. if (this.data)
  10650. if (this.data.icon) {
  10651. var b = document.createElement("yt-icon");
  10652. this.data.icon.iconType === "MODERATOR" && this.enableNewModeratorBadge ? (b.polymerController.icon = "yt-sys-icons:shield-filled",
  10653. b.polymerController.defaultToFilled = !0) : b.polymerController.icon = "live-chat-badges:" + this.data.icon.iconType.toLowerCase();
  10654. a.appendChild(b)
  10655. } else if (this.data.customThumbnail) {
  10656. b = document.createElement("img");
  10657. var c;
  10658. (c = (c = UA(this.data.customThumbnail.thumbnails, 16)) ? Yb(kc(c)) : null) ? (b.src = c,
  10659. a.appendChild(b),
  10660. b.setAttribute("alt", this.hostElement.ariaLabel || "")) : Fq(new Zn("Could not compute URL for thumbnail",this.data.customThumbnail))
  10661. }
  10662. }
  10663. */
  10664.  
  10665. const a = (this || 0).data;
  10666. const image = ((this || 0).$ || 0).image;
  10667. if (image && a && image.firstElementChild) {
  10668. const exisiting = image.firstElementChild;
  10669. if (exisiting === image.lastElementChild) {
  10670.  
  10671. if (a.icon && exisiting.nodeName.toUpperCase() === 'YT-ICON') {
  10672.  
  10673. const c = exisiting;
  10674. const t = insp(c);
  10675. const w = ('icon' in t || 'defaultToFilled' in t) ? t : c;
  10676. if ("MODERATOR" === a.icon.iconType && this.enableNewModeratorBadge) {
  10677. if (w.icon !== "yt-sys-icons:shield-filled") w.icon = "yt-sys-icons:shield-filled";
  10678. if (w.defaultToFilled !== true) w.defaultToFilled = true;
  10679. } else {
  10680. const p = "live-chat-badges:" + a.icon.iconType.toLowerCase();;
  10681. if (w.icon !== p) w.icon = p;
  10682. if (w.defaultToFilled !== false) w.defaultToFilled = false;
  10683. }
  10684. return;
  10685.  
  10686.  
  10687. } else if (a.customThumbnail && exisiting.nodeName.toUpperCase() == 'IMG') {
  10688.  
  10689. const c = exisiting;
  10690. if (a.customThumbnail.thumbnails.map(e => e.url).includes(c.src)) {
  10691.  
  10692. c.setAttribute("alt", this.hostElement.ariaLabel || "");
  10693. return;
  10694. }
  10695. /*
  10696.  
  10697. var d;
  10698. (d = (d = KC(a.customThumbnail.thumbnails, 16)) ? lc(oc(d)) : null) ? (c.src = d,
  10699.  
  10700. c.setAttribute("alt", this.hostElement.ariaLabel || "")) : lq(new tm("Could not compute URL for thumbnail", a.customThumbnail))
  10701. */
  10702. }
  10703.  
  10704. }
  10705. }
  10706. return this.dataChanged86.apply(this, arguments)
  10707.  
  10708. }
  10709. console1.log("cProto.dataChanged - OK");
  10710.  
  10711. } else if (typeof cProto.dataChanged === 'function' && !cProto.dataChanged86 && '|1.163.100|1.162.100|1.160.97|1.159.97|'.includes(`|${fnIntegrity(cProto.dataChanged)}|`)) {
  10712.  
  10713. cProto.dataChanged86 = cProto.dataChanged;
  10714. cProto.dataChanged = function (a) {
  10715.  
  10716. /*
  10717.  
  10718. for (var b = xC(Z(this.hostElement).querySelector("#image")); b.firstChild; )
  10719. b.removeChild(b.firstChild);
  10720. if (a)
  10721. if (a.icon) {
  10722. var c = document.createElement("yt-icon");
  10723. "MODERATOR" === a.icon.iconType && this.enableNewModeratorBadge ? (c.icon = "yt-sys-icons:shield-filled",
  10724. c.defaultToFilled = !0) : c.icon = "live-chat-badges:" + a.icon.iconType.toLowerCase();
  10725. b.appendChild(c)
  10726. } else if (a.customThumbnail) {
  10727. c = document.createElement("img");
  10728. var d;
  10729. (d = (d = KC(a.customThumbnail.thumbnails, 16)) ? lc(oc(d)) : null) ? (c.src = d,
  10730. b.appendChild(c),
  10731. c.setAttribute("alt", this.hostElement.ariaLabel || "")) : lq(new tm("Could not compute URL for thumbnail",a.customThumbnail))
  10732. }
  10733.  
  10734. */
  10735.  
  10736.  
  10737. /* 2024.04.20 */
  10738. /*
  10739. for (var b = Tx(N(this.hostElement).querySelector("#image")); b.firstChild; )
  10740. b.removeChild(b.firstChild);
  10741. if (a)
  10742. if (a.icon) {
  10743. var c = document.createElement("yt-icon");
  10744. "MODERATOR" === a.icon.iconType && this.enableNewModeratorBadge ? (c.polymerController.icon = "yt-sys-icons:shield-filled",
  10745. c.polymerController.defaultToFilled = !0) : c.polymerController.icon = "live-chat-badges:" + a.icon.iconType.toLowerCase();
  10746. b.appendChild(c)
  10747. } else if (a.customThumbnail) {
  10748. c = document.createElement("img");
  10749. var d;
  10750. (d = (d = WD(a.customThumbnail.thumbnails, 16)) ? Sb(ec(d)) : null) ? (c.src = d,
  10751. b.appendChild(c),
  10752. c.setAttribute("alt", this.hostElement.ariaLabel || "")) : nr(new mn("Could not compute URL for thumbnail",a.customThumbnail))
  10753. }
  10754. */
  10755.  
  10756. const image = ((this || 0).$ || 0).image
  10757. if (image && a && image.firstElementChild) {
  10758. const exisiting = image.firstElementChild;
  10759. if (exisiting === image.lastElementChild) {
  10760.  
  10761. if (a.icon && exisiting.nodeName.toUpperCase() === 'YT-ICON') {
  10762.  
  10763. const c = exisiting;
  10764. const t = insp(c);
  10765. const w = ('icon' in t || 'defaultToFilled' in t) ? t : c;
  10766. if ("MODERATOR" === a.icon.iconType && this.enableNewModeratorBadge) {
  10767. if (w.icon !== "yt-sys-icons:shield-filled") w.icon = "yt-sys-icons:shield-filled";
  10768. if (w.defaultToFilled !== true) w.defaultToFilled = true;
  10769. } else {
  10770. const p = "live-chat-badges:" + a.icon.iconType.toLowerCase();;
  10771. if (w.icon !== p) w.icon = p;
  10772. if (w.defaultToFilled !== false) w.defaultToFilled = false;
  10773. }
  10774. return;
  10775.  
  10776.  
  10777. } else if (a.customThumbnail && exisiting.nodeName.toUpperCase() == 'IMG') {
  10778.  
  10779. const c = exisiting;
  10780. if (a.customThumbnail.thumbnails.map(e => e.url).includes(c.src)) {
  10781.  
  10782. c.setAttribute("alt", this.hostElement.ariaLabel || "");
  10783. return;
  10784. }
  10785. /*
  10786.  
  10787. var d;
  10788. (d = (d = KC(a.customThumbnail.thumbnails, 16)) ? lc(oc(d)) : null) ? (c.src = d,
  10789.  
  10790. c.setAttribute("alt", this.hostElement.ariaLabel || "")) : lq(new tm("Could not compute URL for thumbnail", a.customThumbnail))
  10791. */
  10792. }
  10793.  
  10794. }
  10795. }
  10796. return this.dataChanged86.apply(this, arguments)
  10797.  
  10798. }
  10799. console1.log("cProto.dataChanged - OK");
  10800.  
  10801. } else {
  10802. assertor(() => fnIntegrity(cProto.dataChanged, '0.169.106'));
  10803. console1.log("cProto.dataChanged - NG");
  10804.  
  10805. }
  10806.  
  10807. })();
  10808.  
  10809. console1.log("[End]");
  10810.  
  10811. groupEnd();
  10812.  
  10813. }).catch(console.warn);
  10814.  
  10815.  
  10816. }
  10817.  
  10818. if (USE_ADVANCED_TICKING) {
  10819. // leading the emoji cannot be rendered.
  10820.  
  10821. // const qz38 = lcrPromiseFn();
  10822.  
  10823. // qz38.then((lcrGet) => {
  10824.  
  10825. // const tag = "yt-live-chat-renderer"
  10826. // const dummy = lcrGet();
  10827.  
  10828. const lcrFn2 = (lcrDummy) => {
  10829.  
  10830. const tag = "yt-live-chat-renderer"
  10831. const dummy = lcrDummy;
  10832.  
  10833.  
  10834. const cProto = getProto(dummy);
  10835.  
  10836. // dummy.usePatchedLifecycles = false;
  10837. // dummy.data = null;
  10838. // dummy.__data = null;
  10839. // Object.setPrototypeOf(dummy, Object.prototype);
  10840. if (!cProto || !cProto.attached) {
  10841. console.warn(`proto.attached for ${tag} is unavailable.`);
  10842. return;
  10843. }
  10844.  
  10845. /*
  10846. <tp-yt-paper-tooltip class="style-scope yt-live-chat-author-badge-renderer" role="tooltip" tabindex="-1" style="--paper-tooltip-delay-in: 0ms; inset: -63.3984px auto auto 0px;
  10847. */
  10848.  
  10849. if (cProto && typeof cProto.immediatelyApplyLiveChatActions === 'function' && cProto.immediatelyApplyLiveChatActions.length === 1 && !cProto.immediatelyApplyLiveChatActions82) {
  10850. cProto.immediatelyApplyLiveChatActions82 = cProto.immediatelyApplyLiveChatActions;
  10851. cProto.immediatelyApplyLiveChatActions = function (arr) {
  10852.  
  10853.  
  10854. // console.log(1237)
  10855. try {
  10856. preprocessChatLiveActions(arr);
  10857. } catch (e) {
  10858. console.warn(e);
  10859. }
  10860. return this.immediatelyApplyLiveChatActions82(arr);
  10861. };
  10862. }
  10863.  
  10864.  
  10865. if (cProto && typeof cProto.preprocessActions_ === 'function' && cProto.preprocessActions_.length === 1 && !cProto.preprocessActions82_) {
  10866. cProto.preprocessActions82_ = cProto.preprocessActions_;
  10867. cProto.preprocessActions_ = function (arr) {
  10868.  
  10869. const ct_ = Date.now();
  10870.  
  10871. arr = this.preprocessActions82_(arr);
  10872.  
  10873. try {
  10874. preprocessChatLiveActions(arr, ct_);
  10875. } catch (e) {
  10876. console.warn(e);
  10877. }
  10878. return arr;
  10879. };
  10880. }
  10881.  
  10882.  
  10883.  
  10884. };
  10885. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  10886. getLCRDummy().then(lcrFn2);
  10887. }
  10888.  
  10889. if (MODIFY_EMIT_MESSAGES_FOR_BOOST_CHAT) {
  10890.  
  10891. const lcrFn2 = (lcrDummy) => {
  10892.  
  10893. const tag = "yt-live-chat-renderer"
  10894. const dummy = lcrDummy;
  10895.  
  10896.  
  10897. const cProto = getProto(dummy);
  10898.  
  10899. // dummy.usePatchedLifecycles = false;
  10900. // dummy.data = null;
  10901. // dummy.__data = null;
  10902. // Object.setPrototypeOf(dummy, Object.prototype);
  10903. if (!cProto || !cProto.attached) {
  10904. console.warn(`proto.attached for ${tag} is unavailable.`);
  10905. return;
  10906. }
  10907.  
  10908. /*
  10909.  
  10910. // https://www.youtube.com/s/desktop/c01ea7e3/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  10911.  
  10912.  
  10913. YP.prototype.emitSmoothedMessages = function() {
  10914. this.JSC$10797_nextUpdateId = null;
  10915. if (this.JSC$10797_messageQueue.length) {
  10916. var a = 1E4;
  10917. this.JSC$10797_estimatedUpdateInterval !== null && this.JSC$10797_lastUpdateTime !== null && (a = this.JSC$10797_estimatedUpdateInterval - Date.now() + this.JSC$10797_lastUpdateTime);
  10918. var b = this.JSC$10797_messageQueue.length < a / 80 ? 1 : Math.ceil(this.JSC$10797_messageQueue.length / (a / 80));
  10919. var c = aba(this.JSC$10797_messageQueue.splice(0, b));
  10920. this.callback && this.callback(c);
  10921. this.JSC$10797_messageQueue.length && (b === 1 ? (b = a / this.JSC$10797_messageQueue.length,
  10922. b *= Math.random() + .5,
  10923. b = Math.min(1E3, b),
  10924. b = Math.max(80, b)) : b = 80,
  10925. this.JSC$10797_nextUpdateId = window.setTimeout(this.emitSmoothedMessages.bind(this), b))
  10926. }
  10927. }
  10928. // emitSmoothedMessages: say b = 1000, 858.24, 529.49, 357.15, 194.96, 82.12, 80, 80, 80 ....
  10929.  
  10930. */
  10931.  
  10932.  
  10933. const _flag0281_ = window._flag0281_;
  10934.  
  10935.  
  10936. if ((_flag0281_ & 0x40000) === 0x40000 && cProto && typeof cProto.preprocessActions_ === 'function' && cProto.preprocessActions_.length === 1 && !cProto.preprocessActions92_) {
  10937. // we can disable smooth message emitting if boost chat is enabled (0x40000)
  10938. let byPass = false;
  10939. let q33 = false;
  10940. let key_estimatedUpdateInterval = '';
  10941. let key_lastUpdateTime = '';
  10942. let key_messageQueue = '';
  10943. const emitSmoothedMessagesInstantFn = function () {
  10944. if (byPass) return this.emitSmoothedMessages018();
  10945. byPass = true;
  10946. try {
  10947. if (!q33) {
  10948. const keys = Object.getOwnPropertyNames(this);
  10949. for (const key of keys) {
  10950. if (`${key}`.endsWith('_estimatedUpdateInterval')) key_estimatedUpdateInterval = key;
  10951. else if (`${key}`.endsWith('_lastUpdateTime')) key_lastUpdateTime = key;
  10952. else if (`${key}`.endsWith('_messageQueue')) key_messageQueue = key;
  10953. else continue;
  10954. if (key_estimatedUpdateInterval && key_lastUpdateTime && key_messageQueue) break;
  10955. }
  10956. if (key_estimatedUpdateInterval && key_lastUpdateTime && key_messageQueue) {
  10957. q33 = true;
  10958. }
  10959. }
  10960. if (key_estimatedUpdateInterval && key_lastUpdateTime) {
  10961. this[key_estimatedUpdateInterval] = 78; // 80 - 2
  10962. this[key_lastUpdateTime] = Date.now() - 1;
  10963. }
  10964. } catch (e) { }
  10965. // console.log(19893,key_estimatedUpdateInterval, key_lastUpdateTime)
  10966. // make a = this.JSC$10797_estimatedUpdateInterval - Date.now() + this.JSC$10797_lastUpdateTime small
  10967.  
  10968. // this.JSC$10797_estimatedUpdateInterval = Date.now() + 1
  10969. // this.JSC$10797_lastUpdateTime = Date.now()
  10970.  
  10971. // if (!window.setTimeout837) {
  10972. // window.setTimeout837 = window.setTimeout;
  10973. // window.setTimeout838 = function (f, d) {
  10974. // if (arguments.length !== 2) return window.setTimeout837(...arguments);
  10975. // console.log(12883, d)
  10976. // return window.setTimeout837(f, d > 80 ? 80 : d)
  10977. // }
  10978. // }
  10979. // else if (window.setTimeout837 !== window.setTimeout) {
  10980. // window.setTimeout837 = window.setTimeout;
  10981. // }
  10982. // let r;
  10983. // if (window.setTimeout837 && window.setTimeout838) {
  10984. // window.setTimeout = window.setTimeout838;
  10985. // r = this.emitSmoothedMessages018();
  10986. // window.setTimeout = window.setTimeout837;
  10987. // } else {
  10988. // r = this.emitSmoothedMessages018();
  10989. // }
  10990. let doInNextCall = false;
  10991. try {
  10992. const messageQueue = key_messageQueue ? this[key_messageQueue] : null;
  10993. if (!messageQueue || !messageQueue.length) {
  10994.  
  10995. } else if (messageQueue.length > 255) {
  10996.  
  10997. } else if (!document.hidden) {
  10998.  
  10999. } else {
  11000. doInNextCall = true;
  11001. }
  11002. } catch (e) { }
  11003.  
  11004. let r;
  11005. if (doInNextCall) {
  11006. setTimeout_(() => this.emitSmoothedMessages019(), 250);
  11007. } else {
  11008. r = this.emitSmoothedMessages018();
  11009. }
  11010. byPass = false;
  11011. return r;
  11012. };
  11013. cProto.preprocessActions92_ = cProto.preprocessActions_;
  11014. cProto.preprocessActions_ = function (arr) {
  11015.  
  11016. arr = this.preprocessActions92_(arr);
  11017.  
  11018. try {
  11019.  
  11020. const smoothedQueue_ = this.smoothedQueue_;
  11021. if (smoothedQueue_ && !smoothedQueue_.__fix018__) {
  11022. smoothedQueue_.__fix018__ = true;
  11023. if (!smoothedQueue_.emitSmoothedMessages018 && typeof smoothedQueue_.emitSmoothedMessages === 'function' && smoothedQueue_.emitSmoothedMessages.length === 0) {
  11024. smoothedQueue_.emitSmoothedMessages018 = smoothedQueue_.emitSmoothedMessages;
  11025. smoothedQueue_.emitSmoothedMessages019 = emitSmoothedMessagesInstantFn;
  11026. smoothedQueue_.emitSmoothedMessages = emitSmoothedMessagesInstantFn;
  11027. }
  11028. }
  11029. } catch (e) {
  11030. console.warn(e);
  11031. }
  11032. return arr;
  11033. };
  11034. }
  11035.  
  11036.  
  11037.  
  11038.  
  11039. };
  11040. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  11041. getLCRDummy().then(lcrFn2);
  11042. }
  11043.  
  11044.  
  11045. if (FIX_TOOLTIP_DISPLAY) {
  11046.  
  11047. // ----------------------------------------------------------------------------------------------------
  11048.  
  11049. const checkPDGet = (pd) => {
  11050. return pd && pd.get && !pd.set && pd.enumerable && pd.configurable;
  11051. }
  11052.  
  11053. const tooltipUIWM = new WeakMap();
  11054. const tooltipInitProps = {};
  11055. const createTooltipIfRequired_ = function () {
  11056. let r;
  11057. if (tooltipUIWM.get(this) === void 0) {
  11058. const w = document.createElement;
  11059. let EU = null;
  11060. tooltipUIWM.set(this, null);
  11061. document.createElement = function () {
  11062. let r = w.apply(this, arguments);
  11063. EU = r;
  11064. return r;
  11065. };
  11066. r = this.createTooltipIfRequired14_();
  11067. document.createElement = w;
  11068. if (EU instanceof HTMLElement_ && EU.is) {
  11069. tooltipUIWM.set(this, EU);
  11070. EU.setAttribute('__nogc__', ''); // avoid gc process script
  11071.  
  11072. if (typeof EU.offset === 'number') tooltipInitProps['offset'] = EU.offset;
  11073. if (typeof EU.fitToVisibleBounds === 'boolean') tooltipInitProps['fitToVisibleBounds'] = EU.fitToVisibleBounds;
  11074. if (typeof EU.position === 'string') tooltipInitProps['position'] = EU.position;
  11075. if (typeof EU.for === 'string') tooltipInitProps['for'] = EU.for;
  11076.  
  11077. // this.__mcT__ = EU.outerHTML;
  11078. // EU.__dataX = JSON.stringify(EU.__data);
  11079. // EU.__dataY = Object.entries(EU);
  11080.  
  11081. // <<< FOR DEBUG >>>
  11082. // let kx;
  11083. // Object.defineProperty(EU, '_target', {
  11084. // get(){
  11085. // return kx;
  11086. // },
  11087. // set(nv){
  11088. // kx= nv;
  11089. // debugger;
  11090. // return true;
  11091. // }
  11092. // });
  11093. // <<< FOR DEBUG >>>
  11094.  
  11095. if (typeof Polymer !== 'undefined' && Polymer.__fixedGetOwnerRoot__ && Polymer.__fixedQuerySelector__) {
  11096.  
  11097. } else {
  11098. let eProto = null;
  11099. const euCnt = insp(EU);
  11100. if (checkPDGet(Object.getOwnPropertyDescriptor(euCnt.constructor.prototype || {}, 'target'))) {
  11101.  
  11102. eProto = euCnt.constructor.prototype;
  11103. } else if (checkPDGet(Object.getOwnPropertyDescriptor(EU.constructor.prototype || {}, 'target'))) {
  11104.  
  11105. eProto = EU.constructor.prototype;
  11106. }
  11107. if (eProto) {
  11108. delete eProto.target;
  11109. /*
  11110.  
  11111. get target() {
  11112. var a = Pv(this).parentNode, b = Pv(this).getOwnerRoot(), c;
  11113. this.for ? c = Pv(b).querySelector("#" + this.for) : c = a.nodeType == Node.DOCUMENT_FRAGMENT_NODE ? b.host : a;
  11114. return c
  11115. },
  11116. */
  11117. Object.defineProperty(eProto, 'target', {
  11118. get() {
  11119. const cnt = insp(this);
  11120. const hostElement = cnt.hostElement || cnt;
  11121. let a = hostElement.parentNode, b = hostElement.getRootNode();
  11122. const fr = cnt.for || hostElement.for;
  11123. return (fr ? b.querySelector("#" + fr) : a)
  11124. }
  11125. })
  11126. }
  11127. }
  11128. // setInterval(()=>EU.updatePosition(), 100)
  11129.  
  11130. } else {
  11131. tooltipUIWM.set(this, null);
  11132. }
  11133. } else {
  11134. r = this.createTooltipIfRequired14_();
  11135. }
  11136.  
  11137. const EU = tooltipUIWM.get(this);
  11138. if (EU) {
  11139. EU.remove();
  11140. if (typeof tooltipInitProps.offset === 'number') EU['offset'] = tooltipInitProps.offset;
  11141. if (typeof tooltipInitProps.fitToVisibleBounds === 'boolean') EU['fitToVisibleBounds'] = tooltipInitProps.fitToVisibleBounds;
  11142. try {
  11143. if (typeof tooltipInitProps.position === 'string') EU['position'] = tooltipInitProps.position;
  11144. if (typeof tooltipInitProps.for === 'string') EU['for'] = tooltipInitProps.for; else delete EU.for;
  11145. } catch (e) { }
  11146. }
  11147.  
  11148. // 2025.01.10 fix
  11149. const CS = EU;
  11150. if (!CS._showing && CS.__shady_parentNode && CS.__shady_parentNode !== CS.parentNode) {
  11151. if (CS.__shady_parentNode) {
  11152. try {
  11153. CS.__shady_parentNode.__shady_removeChild(CS);
  11154. } catch (e) { }
  11155. }
  11156. if (CS.__shady_parentNode) {
  11157. try {
  11158. CS.__shady_parentNode.removeChild(CS);
  11159. } catch (e) { }
  11160. }
  11161. if (CS.__shady_parentNode) {
  11162. try {
  11163. CS.__shady_parentNode.__shady_native_removeChild(CS);
  11164. } catch (e) { }
  11165. }
  11166. if (CS.__shady_parentNode) {
  11167. try {
  11168. __shady_native_removeChild.call(CS.__shady_parentNode, CS);
  11169. } catch (e) { }
  11170. }
  11171. if (CS.parentNode && !CS.__shady_parentNode) {
  11172. try {
  11173. __shady_native_removeChild.call(CS.parentNode, CS);
  11174. } catch (e) { }
  11175. }
  11176. }
  11177.  
  11178. return r;
  11179. };
  11180.  
  11181.  
  11182. // added in 2024.05.02
  11183. const lcrFn2 = (lcrDummy) => {
  11184.  
  11185. // console.log(8171, 99);
  11186. const tag = "yt-live-chat-renderer"
  11187. const dummy = lcrDummy;
  11188.  
  11189. const cProto = getProto(dummy);
  11190. if (!cProto || !cProto.attached) {
  11191. console.warn(`proto.attached for ${tag} is unavailable.`);
  11192. return;
  11193. }
  11194.  
  11195. /*
  11196. <tp-yt-paper-tooltip class="style-scope yt-live-chat-author-badge-renderer" role="tooltip" tabindex="-1" style="--paper-tooltip-delay-in: 0ms; inset: -63.3984px auto auto 0px;
  11197. */
  11198.  
  11199. if (cProto && typeof cProto.createTooltipIfRequired_ === 'function' && cProto.createTooltipIfRequired_.length === 0 && !cProto.createTooltipIfRequired14_) {
  11200. cProto.createTooltipIfRequired14_ = cProto.createTooltipIfRequired_;
  11201. cProto.createTooltipIfRequired_ = createTooltipIfRequired_;
  11202. }
  11203.  
  11204. };
  11205. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  11206. getLCRDummy().then(lcrFn2);
  11207.  
  11208. // ----------------------------------------------------------------------------------------------------
  11209.  
  11210. customElements.whenDefined("tp-yt-paper-tooltip").then(() => {
  11211.  
  11212. mightFirstCheckOnYtInit();
  11213. groupCollapsed("YouTube Super Fast Chat", " | tp-yt-paper-tooltip hacks");
  11214. console1.log("[Begin]");
  11215. (() => {
  11216.  
  11217. const tag = "tp-yt-paper-tooltip"
  11218. const dummy = document.createElement(tag);
  11219.  
  11220. const cProto = getProto(dummy);
  11221. if (!cProto || !cProto.attached) {
  11222. console1.warn(`proto.attached for ${tag} is unavailable.`);
  11223. return;
  11224. }
  11225.  
  11226. if (typeof cProto.attached === 'function' && typeof cProto.detached === 'function' && cProto._readyClients && cProto._attachDom && cProto.ready && !cProto._readyClients43) {
  11227.  
  11228. cProto._readyClients43 = cProto._readyClients;
  11229. cProto._readyClients = function () {
  11230. // console.log(1238)
  11231.  
  11232. let r = cProto._readyClients43.apply(this, arguments);
  11233. if (this.$ && this.$$ && this.$.tooltip) this.root = null; // fix this.root = null != (b = a.root) ? b : this.host
  11234. return r;
  11235. }
  11236.  
  11237. console1.log("_readyClients - OK");
  11238.  
  11239. } else {
  11240. console1.log("_readyClients - NG");
  11241.  
  11242. }
  11243.  
  11244. if (typeof cProto.show === 'function' && !cProto.show17) {
  11245. cProto.show17 = cProto.show;
  11246. cProto.show = function () {
  11247.  
  11248. let r = this.show17.apply(this, arguments);
  11249. this._showing === true && Promise.resolve(this).then((cnt) => {
  11250. const tooltip = (cnt.$ || 0).tooltip;
  11251.  
  11252. if (tooltip && tooltip.firstElementChild === null) {
  11253. let text = tooltip.textContent;
  11254. if (typeof text === 'string' && text.length >= 2) {
  11255. tooltip.textContent = text.trim();
  11256. }
  11257. }
  11258. cnt = null;
  11259. }).catch(console.warn)
  11260. return r;
  11261. }
  11262.  
  11263. console1.log("trim tooltip content - OK");
  11264.  
  11265. } else {
  11266. console1.log("trim tooltip content - NG");
  11267.  
  11268. }
  11269.  
  11270.  
  11271. })();
  11272.  
  11273. console1.log("[End]");
  11274.  
  11275. groupEnd();
  11276.  
  11277. }).catch(console.warn);
  11278.  
  11279. }
  11280.  
  11281.  
  11282. if (FIX_CLICKING_MESSAGE_MENU_DISPLAY_ON_MOUSE_CLICK) {
  11283.  
  11284. const hookDocumentMouseDownSetupFn = () => {
  11285.  
  11286. let muzTimestamp = 0;
  11287. let nszDropdown = null;
  11288.  
  11289. const handlerObject = {
  11290.  
  11291. muHandler282: function (evt) {
  11292. // console.log(evt, 7, document.querySelector('tp-yt-iron-dropdown[focused].style-scope.yt-live-chat-app'))
  11293. if (!evt || !evt.isTrusted || !muzTimestamp) return;
  11294. const dropdown = nszDropdown;
  11295. muzTimestamp = 0;
  11296. nszDropdown = null;
  11297.  
  11298. const kurMPCe = kRef(currentMenuPivotWR) || 0;
  11299. const hostElement = kurMPCe.hostElement || kurMPCe; // should be always hostElement === kurMPCe ?
  11300. if (!hostElement.hasAttribute('menu-visible')) return;
  11301.  
  11302. const chatBanner = HTMLElement_.prototype.closest.call(hostElement, 'yt-live-chat-banner-renderer') || 0;
  11303. if (chatBanner) return;
  11304.  
  11305. if (dropdown && dropdown.positionTarget && hostElement.contains(dropdown.positionTarget)) {
  11306. muzTimestamp = Date.now();
  11307. evt.stopImmediatePropagation();
  11308. evt.stopPropagation();
  11309. Promise.resolve(dropdown).then((dropdown) => {
  11310. dropdown.cancel();
  11311. dropdown = null;
  11312. });
  11313. }
  11314.  
  11315. },
  11316.  
  11317. mlHandler282: function (evt) {
  11318. muzTimestamp = 0;
  11319. nszDropdown = null;
  11320. },
  11321.  
  11322. ckHandler282: function (evt) {
  11323. if (!evt || !evt.isTrusted || !muzTimestamp) return;
  11324. if (Date.now() - muzTimestamp < 40) {
  11325. muzTimestamp = Date.now();
  11326. evt.stopImmediatePropagation();
  11327. evt.stopPropagation();
  11328. }
  11329. },
  11330.  
  11331. tapHandler282: function (evt) {
  11332. if (!evt || !evt.isTrusted || !muzTimestamp) return;
  11333. if (Date.now() - muzTimestamp < 40) {
  11334. muzTimestamp = Date.now();
  11335. evt.stopImmediatePropagation();
  11336. evt.stopPropagation();
  11337. }
  11338. },
  11339.  
  11340. handleEvent(evt) {
  11341. if (evt) {
  11342. const kurMPCe = kRef(currentMenuPivotWR) || 0;
  11343. const kurMPCc = insp(kurMPCe);
  11344. const hostElement = kurMPCc.hostElement || kurMPCc;
  11345. if (!kurMPCc || kurMPCc.isAttached !== true || hostElement.isConnected !== true) return;
  11346. switch (evt.type) {
  11347. case 'mouseup':
  11348. return this.muHandler282(evt);
  11349. case 'mouseleave':
  11350. return this.mlHandler282(evt);
  11351. case 'tap':
  11352. return this.tapHandler282(evt);
  11353. case 'click':
  11354. return this.ckHandler282(evt);
  11355. }
  11356. }
  11357. }
  11358.  
  11359. }
  11360.  
  11361. document.addEventListener('mousedown', function (evt) {
  11362.  
  11363. if (!evt || !evt.isTrusted || !evt.target) return;
  11364.  
  11365. muzTimestamp = 0;
  11366. nszDropdown = null;
  11367.  
  11368. /** @type {HTMLElement | null} */
  11369. const kurMP = kRef(currentMenuPivotWR);
  11370. if (!kurMP) return;
  11371. const kurMPCe = HTMLElement_.prototype.closest.call(kurMP, '[menu-visible]') || 0; // element
  11372.  
  11373. if (!kurMPCe || !kurMPCe.hasAttribute('whole-message-clickable')) return;
  11374.  
  11375. const kurMPCc = insp(kurMPCe); // controller
  11376.  
  11377. if (!kurMPCc.isClickableChatRow111 || !kurMPCc.isClickableChatRow111() || !HTMLElement_.prototype.contains.call(kurMPCe, evt.target)) return;
  11378.  
  11379. const chatBanner = HTMLElement_.prototype.closest.call(kurMPCe, 'yt-live-chat-banner-renderer') || 0;
  11380. if (chatBanner) return;
  11381.  
  11382. let targetDropDown = null;
  11383. for (const dropdown of document.querySelectorAll('tp-yt-iron-dropdown.style-scope.yt-live-chat-app')) {
  11384. if (dropdown && dropdown.positionTarget === kurMP) {
  11385. targetDropDown = dropdown;
  11386. }
  11387. }
  11388.  
  11389. if (!targetDropDown) return;
  11390.  
  11391. if (evt.target.closest('ytd-menu-popup-renderer')) return;
  11392.  
  11393. if ((nszDropdown = targetDropDown)) {
  11394. muzTimestamp = Date.now();
  11395. evt.stopImmediatePropagation();
  11396. evt.stopPropagation();
  11397. currentMenuPivotWR = mWeakRef(kurMPCe);
  11398.  
  11399. const listenOpts = { capture: true, passive: false, once: true };
  11400.  
  11401. // remove unexcecuted eventHandler
  11402. document.removeEventListener('mouseup', handlerObject, listenOpts);
  11403. document.removeEventListener('mouseleave', handlerObject, listenOpts);
  11404. document.removeEventListener('tap', handlerObject, listenOpts);
  11405. document.removeEventListener('click', handlerObject, listenOpts);
  11406.  
  11407. // inject one time eventHandler to by pass events
  11408. document.addEventListener('mouseup', handlerObject, listenOpts);
  11409. document.addEventListener('mouseleave', handlerObject, listenOpts);
  11410. document.addEventListener('tap', handlerObject, listenOpts);
  11411. document.addEventListener('click', handlerObject, listenOpts);
  11412.  
  11413. }
  11414.  
  11415. }, true);
  11416.  
  11417. }
  11418.  
  11419.  
  11420. // yt-live-chat-paid-message-renderer ??
  11421.  
  11422. /*
  11423.  
  11424. [...(new Set([...document.querySelectorAll('*')].filter(e=>e.is&&('shouldSupportWholeItemClick' in e)).map(e=>e.is))).keys()]
  11425.  
  11426.  
  11427. "yt-live-chat-ticker-paid-message-item-renderer"
  11428. "yt-live-chat-ticker-paid-sticker-item-renderer"
  11429. "yt-live-chat-paid-message-renderer"
  11430. "yt-live-chat-text-message-renderer"
  11431. "yt-live-chat-paid-sticker-renderer"
  11432.  
  11433. */
  11434.  
  11435.  
  11436. whenDefinedMultiple([
  11437.  
  11438. "yt-live-chat-paid-message-renderer",
  11439. "yt-live-chat-membership-item-renderer",
  11440. "yt-live-chat-paid-sticker-renderer",
  11441. "yt-live-chat-text-message-renderer",
  11442. "yt-live-chat-auto-mod-message-renderer",
  11443.  
  11444. /*
  11445. "yt-live-chat-ticker-paid-message-item-renderer",
  11446. "yt-live-chat-ticker-paid-sticker-item-renderer",
  11447. "yt-live-chat-paid-message-renderer",
  11448. "yt-live-chat-text-message-renderer",
  11449. "yt-live-chat-paid-sticker-renderer",
  11450.  
  11451. "yt-live-chat-ticker-sponsor-item-renderer",
  11452. "yt-live-chat-banner-header-renderer",
  11453. "ytd-sponsorships-live-chat-gift-purchase-announcement-renderer",
  11454. "ytd-sponsorships-live-chat-header-renderer",
  11455. "ytd-sponsorships-live-chat-gift-redemption-announcement-renderer",
  11456.  
  11457.  
  11458.  
  11459.  
  11460. "yt-live-chat-auto-mod-message-renderer",
  11461. "yt-live-chat-text-message-renderer",
  11462. "yt-live-chat-paid-message-renderer",
  11463.  
  11464. "yt-live-chat-legacy-paid-message-renderer",
  11465. "yt-live-chat-membership-item-renderer",
  11466. "yt-live-chat-paid-sticker-renderer",
  11467. "yt-live-chat-donation-announcement-renderer",
  11468. "yt-live-chat-moderation-message-renderer",
  11469. "ytd-sponsorships-live-chat-gift-purchase-announcement-renderer",
  11470. "ytd-sponsorships-live-chat-gift-redemption-announcement-renderer",
  11471. "yt-live-chat-viewer-engagement-message-renderer",
  11472.  
  11473. */
  11474.  
  11475.  
  11476. ]).then(sTags => {
  11477. // return; // M33
  11478.  
  11479. mightFirstCheckOnYtInit();
  11480. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-message-renderer(s)... hacks");
  11481. console1.log("[Begin]");
  11482. let doMouseHook = false;
  11483.  
  11484. const dProto = {
  11485. isClickableChatRow111: function () {
  11486. return (
  11487. this.data && typeof this.shouldSupportWholeItemClick === 'function' && typeof this.hasModerationOverlayVisible === 'function' &&
  11488. this.data.contextMenuEndpoint && this.wholeMessageClickable && this.shouldSupportWholeItemClick() && !this.hasModerationOverlayVisible()
  11489. ); // follow .onItemTap(a)
  11490. }
  11491. };
  11492.  
  11493. for (const sTag of sTags) { // ##tag##
  11494.  
  11495.  
  11496. (() => {
  11497.  
  11498. const tag = sTag;
  11499. const dummy = document.createElement(tag);
  11500.  
  11501. const cProto = getProto(dummy);
  11502. if (!cProto || !cProto.attached) {
  11503. console1.warn(`proto.attached for ${tag} is unavailable.`);
  11504. return;
  11505. }
  11506.  
  11507. const dCnt = insp(dummy);
  11508. if ('wholeMessageClickable' in dCnt && typeof dCnt.hasModerationOverlayVisible === 'function' && typeof dCnt.shouldSupportWholeItemClick === 'function') {
  11509.  
  11510. cProto.isClickableChatRow111 = dProto.isClickableChatRow111;
  11511.  
  11512. const toHookDocumentMouseDown = typeof cProto.shouldSupportWholeItemClick === 'function' && typeof cProto.hasModerationOverlayVisible === 'function';
  11513.  
  11514. if (toHookDocumentMouseDown) {
  11515. doMouseHook = true;
  11516. }
  11517.  
  11518. console1.log("shouldSupportWholeItemClick - OK", tag);
  11519.  
  11520. } else {
  11521.  
  11522. console1.log("shouldSupportWholeItemClick - NG", tag);
  11523. }
  11524.  
  11525.  
  11526. })();
  11527.  
  11528. }
  11529.  
  11530.  
  11531. if (doMouseHook) {
  11532.  
  11533. hookDocumentMouseDownSetupFn();
  11534.  
  11535. console1.log("FIX_CLICKING_MESSAGE_MENU_DISPLAY_ON_MOUSE_CLICK - Doc MouseEvent OK");
  11536. }
  11537.  
  11538. console1.log("[End]");
  11539.  
  11540. groupEnd();
  11541.  
  11542.  
  11543. }).catch(console.warn);
  11544.  
  11545.  
  11546. // https://www.youtube.com/watch?v=oQzFi1NO7io
  11547.  
  11548.  
  11549. }
  11550.  
  11551. if (NO_ITEM_TAP_FOR_NON_STATIONARY_TAP) {
  11552. let targetElementCntWR = null;
  11553. let _e0 = null;
  11554. document.addEventListener('mousedown', (e) => {
  11555. if (!e || !e.isTrusted) return;
  11556. let element = e.target;
  11557. for (; element instanceof HTMLElement_; element = element.parentNode) {
  11558. if (element.is) break;
  11559. }
  11560. if (!element || !element.is) return;
  11561. if (element.closest('ytd-menu-popup-renderer')) return;
  11562. const cnt = insp(element);
  11563. if (typeof cnt.onItemTap === 'function') {
  11564. cnt._onItemTap_isNonStationary = 0;
  11565. const cProto = getProto(element);
  11566. if (!cProto.onItemTap366 && typeof cProto.onItemTap === 'function' && cProto.onItemTap.length === 1) {
  11567. cProto.onItemTap366 = cProto.onItemTap; // note: [onItemTap] .some(function(){...})
  11568. cProto.onItemTap = function (a) {
  11569. const t = this._onItemTap_isNonStationary;
  11570. this._onItemTap_isNonStationary = 0;
  11571. if (t > Date.now()) return;
  11572. return this.onItemTap366.apply(this, arguments)
  11573. }
  11574. }
  11575. _e0 = e;
  11576. targetElementCntWR = mWeakRef(cnt);
  11577. } else {
  11578. _e0 = null;
  11579. targetElementCntWR = null;
  11580. }
  11581. }, { capture: true, passive: true });
  11582.  
  11583. document.addEventListener('mouseup', (e) => {
  11584. if (!e || !e.isTrusted) return;
  11585. const e0 = _e0;
  11586. _e0 = null;
  11587. if (!e0) return;
  11588. const cnt = kRef(targetElementCntWR);
  11589. targetElementCntWR = null;
  11590. if (!cnt) return;
  11591. if (e.timeStamp - e0.timeStamp > TAP_ACTION_DURATION) {
  11592. cnt._onItemTap_isNonStationary = Date.now() + 40;
  11593. } else if (`${window.getSelection()}`.trim().replace(/[\u2000-\u200a\u202f\u2800\u200B\u200C\u200D\uFEFF]+/g, '').length >= 1) {
  11594. cnt._onItemTap_isNonStationary = Date.now() + 40;
  11595. } else {
  11596. const dx = e.clientX - e0.clientX;
  11597. const dy = e.clientY - e0.clientY;
  11598. const dd = Math.sqrt(dx * dx + dy * dy);
  11599. const ddmm = px2mm(dd);
  11600. if (ddmm > 1.0) {
  11601. cnt._onItemTap_isNonStationary = Date.now() + 40;
  11602. } else {
  11603. cnt._onItemTap_isNonStationary = 0;
  11604. }
  11605. }
  11606. }, { capture: true, passive: true });
  11607.  
  11608. }
  11609.  
  11610.  
  11611. const __showContextMenu_assign_lock_with_external_unlock_ = function (targetCnt) {
  11612.  
  11613. let rr = null;
  11614. const p1 = new Promise(resolve => {
  11615. rr = resolve;
  11616. });
  11617.  
  11618. const p1unlock = () => {
  11619. const f = rr;
  11620. if (f) {
  11621. rr = null;
  11622. f();
  11623. }
  11624. }
  11625.  
  11626. return {
  11627. p1,
  11628. p1unlock,
  11629. assignLock: (targetCnt, timeout) => {
  11630. targetCnt.__showContextMenu_assign_lock__(p1);
  11631. if (timeout) setTimeout(p1unlock, timeout);
  11632. }
  11633. }
  11634.  
  11635. }
  11636.  
  11637. if (PREREQUEST_CONTEXT_MENU_ON_MOUSE_DOWN) {
  11638.  
  11639. document.addEventListener('mousedown', function (evt) {
  11640.  
  11641. const maxloopDOMTreeElements = 4;
  11642. const maxloopYtCompontents = 4;
  11643. let j1 = 0;
  11644. let j2 = 0;
  11645. let target = (evt || 0).target || 0;
  11646. if (!target) return;
  11647. if (target.closest('ytd-menu-popup-renderer')) return;
  11648.  
  11649. while (target instanceof HTMLElement_) {
  11650. if (++j1 > maxloopDOMTreeElements) break;
  11651. if (typeof (target.is || insp(target).is || null) === 'string') break;
  11652. target = nodeParent(target);
  11653. }
  11654. const components = [];
  11655. while (target instanceof HTMLElement_) {
  11656. if (++j2 > maxloopYtCompontents) break;
  11657. const cnt = insp(target);
  11658. if (typeof (target.is || cnt.is || null) === 'string') {
  11659. components.push(target);
  11660. }
  11661. if (typeof cnt.showContextMenu === 'function') break;
  11662. target = target.parentComponent || cnt.parentComponent || null;
  11663. }
  11664. if (!(target instanceof HTMLElement_)) return;
  11665. const targetCnt = insp(target);
  11666. if (typeof targetCnt.handleGetContextMenuResponse_ !== 'function' || typeof targetCnt.handleGetContextMenuError !== 'function') {
  11667. console.log('Error Found: handleGetContextMenuResponse_ OR handleGetContextMenuError is not defined on a component with showContextMenu')
  11668. return;
  11669. }
  11670.  
  11671. const endpoint = (targetCnt.data || 0).contextMenuEndpoint
  11672. if (!endpoint) return;
  11673. if (targetCnt.opened || !targetCnt.isAttached) return;
  11674.  
  11675. if (typeof targetCnt.__cacheResolvedEndpointData__ !== 'function') {
  11676. console.log(`preRequest for showContextMenu in ${targetCnt.is} is not yet supported.`)
  11677. }
  11678.  
  11679. const targetDollar = indr(target);
  11680.  
  11681. let doPreRequest = false;
  11682. if (components.length >= 2 && components[0].id === 'menu-button' && (targetDollar || 0)['menu-button'] === components[0]) {
  11683. doPreRequest = true;
  11684. } else if (components.length === 1 && components[0] === target) {
  11685. doPreRequest = true;
  11686. } else if (components.length >= 2 && components[0].id === 'author-photo' && (targetDollar || 0)['author-photo'] === components[0]) {
  11687. doPreRequest = true;
  11688. }
  11689. if (doPreRequest === false) {
  11690. console.log('doPreRequest = fasle on showContextMenu', components);
  11691. return;
  11692. }
  11693.  
  11694. if (typeof targetCnt.__getCachedEndpointData__ !== 'function' || targetCnt.__getCachedEndpointData__(endpoint)) return;
  11695.  
  11696. if ((typeof targetCnt.__showContextMenu_mutex_unlock_isEmpty__ === 'function') && !targetCnt.__showContextMenu_mutex_unlock_isEmpty__()) {
  11697. console.log('preRequest on showContextMenu aborted due to stacked network request');
  11698. return;
  11699. }
  11700.  
  11701.  
  11702. const onSuccess = (a) => {
  11703. /*
  11704.  
  11705. dQ() && (a = a.response);
  11706. a.liveChatItemContextMenuSupportedRenderers && a.liveChatItemContextMenuSupportedRenderers.menuRenderer && this.showContextMenu_(a.liveChatItemContextMenuSupportedRenderers.menuRenderer);
  11707. a.actions && Eu(this.hostElement, "yt-live-chat-actions", [a.actions])
  11708.  
  11709. */
  11710.  
  11711. a = a.response || a;
  11712.  
  11713. if (!a) {
  11714. console.log('unexpected error in prerequest for showContextMenu.onSuccess');
  11715. return;
  11716. }
  11717.  
  11718. let z = null;
  11719. a.liveChatItemContextMenuSupportedRenderers && a.liveChatItemContextMenuSupportedRenderers.menuRenderer && (z = a.liveChatItemContextMenuSupportedRenderers.menuRenderer);
  11720.  
  11721. if (z) {
  11722. a = z;
  11723. targetCnt.__cacheResolvedEndpointData__(endpoint, a, true);
  11724. }
  11725.  
  11726. };
  11727. const onFailure = (a) => {
  11728.  
  11729. /*
  11730.  
  11731. if (a instanceof Error || a instanceof Object || a instanceof String)
  11732. var b = a;
  11733. hq(new xm("Error encountered calling GetLiveChatItemContextMenu",b))
  11734.  
  11735. */
  11736.  
  11737. targetCnt.__cacheResolvedEndpointData__(endpoint, null);
  11738. // console.log('onFailure', a)
  11739.  
  11740. };
  11741.  
  11742. if (doPreRequest) {
  11743.  
  11744. let propertyCounter = 0;
  11745. const pm1 = __showContextMenu_assign_lock_with_external_unlock_(targetCnt);
  11746. const p1Timeout = 800;
  11747. const proxyKey = '__$$__proxy_to_this__$$__' + Date.now();
  11748.  
  11749. try {
  11750.  
  11751. const onSuccessHelperFn = function () {
  11752. pm1.p1unlock();
  11753. if (propertyCounter !== 5) {
  11754. console.log('Error in prerequest for showContextMenu.onSuccessHelperFn')
  11755. return;
  11756. }
  11757. if (this[proxyKey] !== targetCnt) {
  11758. console.log('Error in prerequest for showContextMenu.this');
  11759. return;
  11760. }
  11761. onSuccess(...arguments);
  11762. };
  11763. const onFailureHelperFn = function () {
  11764. pm1.p1unlock();
  11765. if (propertyCounter !== 5) {
  11766. console.log('Error in prerequest for showContextMenu.onFailureHelperFn')
  11767. return;
  11768. }
  11769. if (this[proxyKey] !== targetCnt) {
  11770. console.log('Error in prerequest for showContextMenu.this');
  11771. return;
  11772. }
  11773. onFailure(...arguments);
  11774.  
  11775. }
  11776. const fakeTargetCnt = new Proxy({
  11777. __showContextMenu_forceNativeRequest__: 1,
  11778. get handleGetContextMenuResponse_() {
  11779. propertyCounter += 2;
  11780. return onSuccessHelperFn;
  11781. },
  11782. get handleGetContextMenuError() {
  11783. propertyCounter += 3;
  11784. return onFailureHelperFn;
  11785. }
  11786. }, {
  11787. get(_, key, receiver) {
  11788. if (key in _) return _[key];
  11789. if (key === proxyKey) return targetCnt;
  11790.  
  11791. let giveNative = false;
  11792. if (key in targetCnt) {
  11793. if (key === 'data') giveNative = true;
  11794. else if (typeof targetCnt[key] === 'function') giveNative = true;
  11795. }
  11796. if (giveNative) return targetCnt[key];
  11797. }
  11798. });
  11799.  
  11800. const fakeEvent = (() => {
  11801. const { target, bubbles, cancelable, cancelBubble, srcElement, timeStamp, defaultPrevented, currentTarget, composed } = evt;
  11802. const nf = function () { }
  11803. const [stopPropagation, stopImmediatePropagation, preventDefault] = [nf, nf, nf];
  11804.  
  11805. return {
  11806. type: 'tap',
  11807. eventPhase: 0,
  11808. isTrusted: false,
  11809. __composed: true,
  11810. bubbles, cancelable, cancelBubble, timeStamp,
  11811. target, srcElement, defaultPrevented, currentTarget, composed,
  11812. stopPropagation, stopImmediatePropagation, preventDefault
  11813. };
  11814. })(evt);
  11815. targetCnt.showContextMenu.call(fakeTargetCnt, fakeEvent);
  11816.  
  11817.  
  11818. } catch (e) {
  11819. console.warn(e);
  11820. propertyCounter = 7;
  11821.  
  11822. }
  11823. if (propertyCounter !== 5) {
  11824. console.log('Error in prerequest for showContextMenu', propertyCounter);
  11825. return;
  11826. }
  11827.  
  11828. pm1.assignLock(targetCnt, p1Timeout);
  11829.  
  11830. }
  11831.  
  11832.  
  11833.  
  11834.  
  11835.  
  11836.  
  11837. }, true);
  11838.  
  11839.  
  11840. }
  11841.  
  11842.  
  11843.  
  11844. /*
  11845.  
  11846. const w=new Set(); for(const a of document.getElementsByTagName('*')) if(a.showContextMenu && a.showContextMenu_) w.add(a.is||''); console.log([...w.keys()])
  11847.  
  11848. */
  11849.  
  11850. whenDefinedMultiple([
  11851. "yt-live-chat-ticker-sponsor-item-renderer",
  11852. "yt-live-chat-ticker-paid-message-item-renderer",
  11853.  
  11854. "yt-live-chat-banner-header-renderer",
  11855. "yt-live-chat-text-message-renderer",
  11856. "ytd-sponsorships-live-chat-gift-purchase-announcement-renderer",
  11857. "ytd-sponsorships-live-chat-header-renderer",
  11858. "ytd-sponsorships-live-chat-gift-redemption-announcement-renderer",
  11859.  
  11860. "yt-live-chat-paid-sticker-renderer",
  11861. "yt-live-chat-viewer-engagement-message-renderer",
  11862. "yt-live-chat-paid-message-renderer"
  11863.  
  11864.  
  11865.  
  11866.  
  11867. ]).then(sTags => {
  11868.  
  11869. mightFirstCheckOnYtInit();
  11870. groupCollapsed("YouTube Super Fast Chat", " | fixShowContextMenu");
  11871. console1.log("[Begin]");
  11872.  
  11873.  
  11874. const __showContextMenu_mutex__ = new Mutex();
  11875. let __showContextMenu_mutex_unlock__ = null;
  11876. let lastShowMenuTarget = null;
  11877.  
  11878.  
  11879.  
  11880.  
  11881. const wm37 = new WeakMap();
  11882.  
  11883. const dProto = {
  11884.  
  11885.  
  11886. // CACHE_SHOW_CONTEXT_MENU_FOR_REOPEN
  11887.  
  11888. __cacheResolvedEndpointData__: (endpoint, a, doDeepCopy) => {
  11889. if (a) {
  11890. if (doDeepCopy) a = deepCopy(a);
  11891. wm37.set(endpoint, a);
  11892. } else {
  11893. wm37.remove(endpoint);
  11894. }
  11895. },
  11896. __getCachedEndpointData__: function (endpoint) {
  11897. endpoint = endpoint || (this.data || 0).contextMenuEndpoint || 0;
  11898. if (endpoint) return wm37.get(endpoint);
  11899. return null;
  11900. },
  11901. /** @type {(resolvedEndpoint: any) => void 0} */
  11902. __showCachedContextMenu__: function (resolvedEndpoint) { // non-null
  11903.  
  11904. resolvedEndpoint = deepCopy(resolvedEndpoint);
  11905. // let b = deepCopy(resolvedEndpoint, ['trackingParams', 'clickTrackingParams'])
  11906. Promise.resolve(resolvedEndpoint).then((resolvedEndpoint) => {
  11907. this.__showContextMenu_skip_cacheResolvedEndpointData__ = 1;
  11908. this.showContextMenu_(resolvedEndpoint);
  11909. this.__showContextMenu_skip_cacheResolvedEndpointData__ = 0;
  11910. resolvedEndpoint = null;
  11911. });
  11912.  
  11913.  
  11914. },
  11915.  
  11916.  
  11917.  
  11918. showContextMenuForCacheReopen: function (a) {
  11919. if (this && this.__showContextMenu_forceNativeRequest__) return this.showContextMenu37(a);
  11920. if (!this || !this.isAttached) return; // in case; avoid Error: No provider for: InjectionToken(NETWORK_TOKEN) in _.showContextMenu
  11921. if (!this.__showContextMenu_forceNativeRequest__) {
  11922. const endpoint = (this.data || 0).contextMenuEndpoint || 0;
  11923. if (endpoint) {
  11924. const resolvedEndpoint = this.__getCachedEndpointData__(endpoint);
  11925. if (resolvedEndpoint) {
  11926. this.__showCachedContextMenu__(resolvedEndpoint);
  11927. a && a.stopPropagation()
  11928. return;
  11929. }
  11930. }
  11931. }
  11932. return this.showContextMenu37(a);
  11933. },
  11934.  
  11935. showContextMenuForCacheReopen_: function (a) {
  11936. if (this && this.__showContextMenu_forceNativeRequest__) return this.showContextMenu37_(a);
  11937. if (!this || !this.isAttached) return; // in case; avoid Error: No provider for: InjectionToken(NETWORK_TOKEN) in _.showContextMenu
  11938. if (!this.__showContextMenu_skip_cacheResolvedEndpointData__) {
  11939. const endpoint = (this.data || 0).contextMenuEndpoint || 0;
  11940. if (endpoint) {
  11941. const f = this.__cacheResolvedEndpointData__;
  11942. if (typeof f === 'function') f(endpoint, a, true);
  11943. }
  11944. }
  11945. return this.showContextMenu37_(a);
  11946. },
  11947.  
  11948. // ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU
  11949.  
  11950. showContextMenuWithDisableScroll: function (a) {
  11951.  
  11952. const endpoint = (this.data || 0).contextMenuEndpoint || 0;
  11953. if (endpoint && typeof this.is === 'string' && this.menuVisible === false && this.menuOpen === false) {
  11954.  
  11955. const parentComponent = this.parentComponent;
  11956. if (parentComponent && parentComponent.is === 'yt-live-chat-item-list-renderer' && parentComponent.contextMenuOpen === false && parentComponent.allowScroll === true) {
  11957. parentComponent.contextMenuOpen = true; // computeAllowScroll_(contextMenuOpen, moderationModeEnabled): allowScroll = !(contextMenuOpen || moderationModeEnabled)
  11958. }
  11959. }
  11960.  
  11961. return this.showContextMenu48.apply(this, arguments);
  11962.  
  11963. },
  11964.  
  11965. // ENABLE_MUTEX_FOR_SHOW_CONTEXT_MENU
  11966.  
  11967. __showContextMenu_mutex_unlock_isEmpty__: () => {
  11968. return __showContextMenu_mutex_unlock__ === null;
  11969. },
  11970.  
  11971. __showContextMenu_assign_lock__: function (p) {
  11972.  
  11973. const mutex = __showContextMenu_mutex__;
  11974.  
  11975. mutex.lockWith(unlock => {
  11976. p.then(unlock);
  11977. p = null;
  11978. unlock = null;
  11979. });
  11980.  
  11981. },
  11982.  
  11983. showContextMenuWithMutex: function (a) {
  11984. if (this.__showContextMenu_forceNativeRequest__) return this.showContextMenu47(a);
  11985. if (!this || !this.isAttached) return; // in case; avoid Error: No provider for: InjectionToken(NETWORK_TOKEN) in _.showContextMenu
  11986. lastShowMenuTarget = this;
  11987. const wNode = mWeakRef(this);
  11988.  
  11989.  
  11990. const mutex = __showContextMenu_mutex__;
  11991.  
  11992. mutex.lockWith(unlock => {
  11993. const cnt = kRef(wNode);
  11994. if (lastShowMenuTarget !== cnt || !cnt) {
  11995. unlock();
  11996. return;
  11997. }
  11998.  
  11999. setTimeout(unlock, 800); // in case network failure
  12000. __showContextMenu_mutex_unlock__ = unlock;
  12001. try {
  12002. cnt.showContextMenu47(a);
  12003. } catch (e) {
  12004. console.warn(e);
  12005. unlock(); // in case function script error
  12006. }
  12007.  
  12008. });
  12009.  
  12010.  
  12011. },
  12012.  
  12013. showContextMenuWithMutex_: function (a) {
  12014.  
  12015. if (__showContextMenu_mutex_unlock__ && this === lastShowMenuTarget) {
  12016. __showContextMenu_mutex_unlock__();
  12017. __showContextMenu_mutex_unlock__ = null;
  12018. }
  12019. return this.showContextMenu47_(a);
  12020.  
  12021. }
  12022.  
  12023. }
  12024.  
  12025. for (const tag of sTags) { // ##tag##
  12026.  
  12027. (() => {
  12028.  
  12029. const dummy = document.createElement(tag);
  12030.  
  12031. const cProto = getProto(dummy);
  12032. if (!cProto || !cProto.attached) {
  12033. console1.warn(`proto.attached for ${tag} is unavailable.`);
  12034. return;
  12035. }
  12036.  
  12037.  
  12038. if (CACHE_SHOW_CONTEXT_MENU_FOR_REOPEN && typeof cProto.showContextMenu === 'function' && typeof cProto.showContextMenu_ === 'function' && !cProto.showContextMenu37 && !cProto.showContextMenu37_ && cProto.showContextMenu.length === 1 && cProto.showContextMenu_.length === 1) {
  12039. cProto.showContextMenu37_ = cProto.showContextMenu_;
  12040. cProto.showContextMenu37 = cProto.showContextMenu;
  12041. cProto.__showContextMenu_forceNativeRequest__ = 0;
  12042. cProto.__cacheResolvedEndpointData__ = dProto.__cacheResolvedEndpointData__
  12043. cProto.__getCachedEndpointData__ = dProto.__getCachedEndpointData__
  12044. cProto.__showCachedContextMenu__ = dProto.__showCachedContextMenu__
  12045. cProto.showContextMenu = dProto.showContextMenuForCacheReopen;
  12046. cProto.showContextMenu_ = dProto.showContextMenuForCacheReopen_;
  12047. console1.log("CACHE_SHOW_CONTEXT_MENU_FOR_REOPEN - OK", tag);
  12048. } else {
  12049. console1.log("CACHE_SHOW_CONTEXT_MENU_FOR_REOPEN - NG", tag);
  12050. }
  12051.  
  12052. if (ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU && typeof cProto.showContextMenu === 'function' && typeof cProto.showContextMenu_ === 'function' && !cProto.showContextMenu48 && !cProto.showContextMenu48_ && cProto.showContextMenu.length === 1 && cProto.showContextMenu_.length === 1) {
  12053. cProto.showContextMenu48 = cProto.showContextMenu;
  12054. cProto.showContextMenu = dProto.showContextMenuWithDisableScroll;
  12055. console1.log("ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU - OK", tag);
  12056. } else if (!ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU) {
  12057. DEBUG_skipLog001 || console1.log("ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU - N/A", tag);
  12058. } else {
  12059. console1.log("ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU - NG", tag);
  12060. }
  12061.  
  12062.  
  12063. if (ENABLE_MUTEX_FOR_SHOW_CONTEXT_MENU && typeof cProto.showContextMenu === 'function' && typeof cProto.showContextMenu_ === 'function' && !cProto.showContextMenu47 && !cProto.showContextMenu47_ && cProto.showContextMenu.length === 1 && cProto.showContextMenu_.length === 1) {
  12064. cProto.showContextMenu47_ = cProto.showContextMenu_;
  12065. cProto.showContextMenu47 = cProto.showContextMenu;
  12066. cProto.__showContextMenu_mutex_unlock_isEmpty__ = dProto.__showContextMenu_mutex_unlock_isEmpty__;
  12067. cProto.__showContextMenu_assign_lock__ = dProto.__showContextMenu_assign_lock__;
  12068. cProto.showContextMenu = dProto.showContextMenuWithMutex;
  12069. cProto.showContextMenu_ = dProto.showContextMenuWithMutex_;
  12070. console1.log("ENABLE_MUTEX_FOR_SHOW_CONTEXT_MENU - OK", tag);
  12071. } else {
  12072. console1.log("ENABLE_MUTEX_FOR_SHOW_CONTEXT_MENU - NG", tag);
  12073. }
  12074.  
  12075. })();
  12076.  
  12077. }
  12078.  
  12079. console1.log("[End]");
  12080.  
  12081. groupEnd();
  12082.  
  12083. }).catch(console.warn);
  12084.  
  12085.  
  12086.  
  12087. if (FIX_UNKNOWN_BUG_FOR_OVERLAY) {
  12088. // this is to fix " TypeError: this.backdropElement.prepare is not a function "
  12089.  
  12090. customElements.whenDefined('tp-yt-paper-dialog').then(() => {
  12091.  
  12092.  
  12093. mightFirstCheckOnYtInit();
  12094. groupCollapsed("YouTube Super Fast Chat", " | tp-yt-paper-dialog hacks");
  12095. console1.log("[Begin]");
  12096. (() => {
  12097.  
  12098. const tag = "tp-yt-paper-dialog";
  12099. const dummy = document.createElement(tag);
  12100.  
  12101. const cProto = getProto(dummy);
  12102. if (!cProto || !cProto.attached) {
  12103. console1.warn(`proto.attached for ${tag} is unavailable.`);
  12104. return;
  12105. }
  12106.  
  12107. if (typeof cProto.__openedChanged === 'function' && !cProto.__openedChanged49 && cProto.__openedChanged.length === 0) {
  12108.  
  12109.  
  12110. cProto.__openedChanged49 = cProto.__openedChanged;
  12111.  
  12112. cProto.__openedChanged = function () {
  12113. const manager = (this || 0)._manager || 0;
  12114. if (manager && !manager.trackBackdrop49 && manager.trackBackdrop) {
  12115. manager.trackBackdrop49 = manager.trackBackdrop;
  12116. if (manager.trackBackdrop.length === 0) {
  12117. manager.trackBackdrop = function () {
  12118. try {
  12119. return this.trackBackdrop49();
  12120. } catch (e) {
  12121. let showMessage = true;
  12122. if (e instanceof TypeError && e.message === 'this.backdropElement.prepare is not a function') {
  12123. // this is well known issue.
  12124. showMessage = false;
  12125. }
  12126. showMessage && console.log('manager.trackBackdrop', e);
  12127. }
  12128. }
  12129. }
  12130. }
  12131. return this.__openedChanged49();
  12132. };
  12133.  
  12134.  
  12135. }
  12136.  
  12137.  
  12138. })();
  12139.  
  12140.  
  12141. console1.log("[End]");
  12142.  
  12143. groupEnd();
  12144.  
  12145.  
  12146. }).catch(console.warn);
  12147.  
  12148. }
  12149.  
  12150.  
  12151. customElements.whenDefined('tp-yt-iron-dropdown').then(() => {
  12152.  
  12153. mightFirstCheckOnYtInit();
  12154. groupCollapsed("YouTube Super Fast Chat", " | tp-yt-iron-dropdown hacks");
  12155. console1.log("[Begin]");
  12156. (() => {
  12157.  
  12158. const tag = "tp-yt-iron-dropdown";
  12159. const dummy = document.createElement(tag);
  12160.  
  12161. const cProto = getProto(dummy);
  12162. if (!cProto || !cProto.attached) {
  12163. console1.warn(`proto.attached for ${tag} is unavailable.`);
  12164. return;
  12165. }
  12166.  
  12167. if (USE_VANILLA_DEREF && typeof cProto.__deraf === 'function' && cProto.__deraf.length === 2 && !cProto.__deraf34 && fnIntegrity(cProto.__deraf) === '2.42.24') {
  12168. cProto.__deraf_hn__ = function (sId, fn) {
  12169. const rhKey = `_rafHandler_${sId}`;
  12170. const m = this[rhKey] || (this[rhKey] = new WeakMap());
  12171. if (m.has(fn)) return m.get(fn);
  12172. const resFn = () => {
  12173. this.__rafs[sId] = null;
  12174. fn.call(this)
  12175. };
  12176. m.set(fn, resFn);
  12177. m.set(resFn, resFn);
  12178. return resFn;
  12179. };
  12180. cProto.__deraf34 = cProto.__deraf;
  12181. cProto.__deraf = function (a, b) { // sId, fn
  12182. let c = this.__rafs;
  12183. null !== c[a] && cancelAnimationFrame(c[a]);
  12184. c[a] = requestAnimationFrame(this.__deraf_hn__(a, b));
  12185. };
  12186. console1.log("USE_VANILLA_DEREF - OK");
  12187. } else {
  12188. console1.log("USE_VANILLA_DEREF - NG");
  12189. }
  12190.  
  12191. if (FIX_DROPDOWN_DERAF && typeof cProto.__deraf === 'function' && cProto.__deraf.length === 2 && !cProto.__deraf66) {
  12192. cProto.__deraf66 = cProto.__deraf;
  12193. cProto.__deraf = function (sId, fn) {
  12194. if (this.__byPassRAF__) {
  12195. Promise.resolve(this).then((cnt) => {
  12196. fn.call(cnt);
  12197. cnt = null;
  12198. });
  12199. }
  12200. let r = this.__deraf66.apply(this, arguments);
  12201. return r;
  12202. }
  12203. console1.log("FIX_DROPDOWN_DERAF - OK");
  12204. } else {
  12205. console1.log("FIX_DROPDOWN_DERAF - NG");
  12206. }
  12207.  
  12208.  
  12209. if (BOOST_MENU_OPENCHANGED_RENDERING && typeof cProto.__openedChanged === 'function' && !cProto.__mtChanged__ && fnIntegrity(cProto.__openedChanged) === '0.46.20') {
  12210.  
  12211. let lastClose = null;
  12212. let lastOpen = null;
  12213. let cid = 0;
  12214.  
  12215. cProto.__mtChanged__ = function (b) {
  12216.  
  12217. Promise.resolve(this).then((cnt) => {
  12218. cnt._applyFocus();
  12219. return cnt;
  12220. }).then((cnt) => {
  12221. b ? cnt._renderOpened() : cnt._renderClosed();
  12222. cnt = null;
  12223. }).catch(console.warn);
  12224.  
  12225. };
  12226.  
  12227. const __moChanged__ = () => {
  12228. if (!cid) return;
  12229. // console.log(553, !!lastOpen, !!lastClose);
  12230. cid = 0;
  12231. if (lastOpen && !lastClose && lastOpen.isAttached) {
  12232. lastOpen.__mtChanged__(1)
  12233. } else if (lastClose && !lastOpen && lastClose.isAttached) {
  12234. lastClose.__mtChanged__(0);
  12235. }
  12236. lastOpen = null;
  12237. lastClose = null;
  12238. };
  12239.  
  12240.  
  12241. if (typeof cProto._openedChanged === 'function' && !cProto._openedChanged66) {
  12242. cProto._openedChanged66 = cProto._openedChanged;
  12243. cProto._openedChanged = function () {
  12244. // this.__byPassRAF__ = !lastOpen ? true : false; // or just true?
  12245. this.__byPassRAF__ = true;
  12246. let r = this._openedChanged66.apply(this, arguments);
  12247. this.__byPassRAF__ = false;
  12248. return r;
  12249. }
  12250. }
  12251.  
  12252. const pSetGet = (key, pdThis, pdBase) => {
  12253. // note: this is not really a standard way for the getOwnPropertyDescriptors; but it is sufficient to make the job done
  12254. return {
  12255. get: (pdThis[key] || 0).get || (pdBase[key] || 0).get,
  12256. set: (pdThis[key] || 0).set || (pdBase[key] || 0).set
  12257. };
  12258. };
  12259.  
  12260. cProto.__modifiedMenuPropsFn__ = function () {
  12261. const pdThis = Object.getOwnPropertyDescriptors(this.constructor.prototype)
  12262. const pdBase = Object.getOwnPropertyDescriptors(this)
  12263.  
  12264. const pdAutoFitOnAttach = pSetGet('autoFitOnAttach', pdThis, pdBase);
  12265. const pdExpandSizingTargetForScrollbars = pSetGet('expandSizingTargetForScrollbars', pdThis, pdBase);
  12266. const pdAllowOutsideScroll = pSetGet('allowOutsideScroll', pdThis, pdBase);
  12267.  
  12268. if (pdAutoFitOnAttach.get || pdAutoFitOnAttach.set) {
  12269. console.warn('there is setter/getter for autoFitOnAttach');
  12270. return;
  12271. }
  12272. if (pdExpandSizingTargetForScrollbars.get || pdExpandSizingTargetForScrollbars.set) {
  12273. console.warn('there is setter/getter for expandSizingTargetForScrollbars');
  12274. return;
  12275. }
  12276. if (!pdAllowOutsideScroll.get || !pdAllowOutsideScroll.set) {
  12277. console.warn('there is NO setter-getter for allowOutsideScroll');
  12278. return;
  12279. }
  12280.  
  12281. let { autoFitOnAttach, expandSizingTargetForScrollbars, allowOutsideScroll } = this;
  12282.  
  12283. this.__AllowOutsideScrollPD__ = pdAllowOutsideScroll;
  12284.  
  12285. const fitEnable = CHAT_MENU_REFIT_ALONG_SCROLLING === 2;
  12286.  
  12287. Object.defineProperties(this, {
  12288. autoFitOnAttach: {
  12289. get() {
  12290. if (fitEnable && this._modifiedMenuPropOn062__) return true;
  12291. return autoFitOnAttach;
  12292. },
  12293. set(nv) {
  12294. autoFitOnAttach = nv;
  12295. return true;
  12296. },
  12297. enumerable: true,
  12298. configurable: true
  12299. }, expandSizingTargetForScrollbars: {
  12300. get() {
  12301. if (fitEnable && this._modifiedMenuPropOn062__) return true;
  12302. return expandSizingTargetForScrollbars;
  12303. },
  12304. set(nv) {
  12305. expandSizingTargetForScrollbars = nv;
  12306. return true;
  12307. },
  12308. enumerable: true,
  12309. configurable: true
  12310. }, allowOutsideScroll: {
  12311. get() {
  12312. if (this._modifiedMenuPropOn062__) return true;
  12313. return allowOutsideScroll;
  12314. },
  12315. set(nv) {
  12316. allowOutsideScroll = nv;
  12317. this.__AllowOutsideScrollPD__.set.call(this, nv);
  12318. return true;
  12319. },
  12320. enumerable: true,
  12321. configurable: true
  12322. }
  12323. })
  12324. };
  12325.  
  12326. /*
  12327. // ***** position() to be changed. *****
  12328. tp-yt-iron-dropdown[class], tp-yt-iron-dropdown[class] #contentWrapper, tp-yt-iron-dropdown[class] ytd-menu-popup-renderer[class] {
  12329.  
  12330. overflow: visible !important;
  12331. min-width: max-content !important;
  12332. max-width: max-content !important;
  12333. max-height: max-content !important;
  12334. min-height: max-content !important;
  12335. white-space: nowrap;
  12336. }
  12337.  
  12338. */
  12339. if (FIX_MENU_POSITION_N_SIZING_ON_SHOWN && typeof cProto.position === 'function' && !cProto.position34 && typeof cProto.refit === 'function') {
  12340.  
  12341. let m34 = 0;
  12342. cProto.__refitByPosition__ = function () {
  12343. m34++;
  12344. if (m34 <= 0) m34 = 0;
  12345. if (m34 !== 1) return;
  12346. const hostElement = this.hostElement || this;
  12347. if (document.visibilityState === 'visible') {
  12348. const sizingTarget = this.sizingTarget;
  12349. if (!sizingTarget) {
  12350. m34 = 0;
  12351. return;
  12352. }
  12353. hostElement.setAttribute('rNgzQ', '');
  12354. sizingTarget.setAttribute('rNgzQ', '');
  12355.  
  12356. const gn = () => {
  12357. hostElement.removeAttribute('rNgzQ');
  12358. sizingTarget.removeAttribute('rNgzQ');
  12359. }
  12360.  
  12361. const an = async () => {
  12362. while (m34 >= 1) {
  12363. await renderReadyPn(sizingTarget);
  12364. if (this.opened && this.isAttached && sizingTarget.isConnected === true && sizingTarget === this.sizingTarget) {
  12365. if (sizingTarget.matches('ytd-menu-popup-renderer[slot="dropdown-content"].yt-live-chat-app')) this.refit();
  12366. }
  12367. m34--;
  12368. }
  12369. m34 = 0;
  12370. Promise.resolve().then(gn);
  12371. }
  12372. setTimeout(an, 4); // wait those resizing function calls
  12373.  
  12374.  
  12375. } else {
  12376. m34 = 0;
  12377. }
  12378. }
  12379. cProto.position34 = cProto.position
  12380. cProto.position = function () {
  12381. if (this._positionInitialize_) {
  12382. this._positionInitialize_ = 0;
  12383. this.__refitByPosition__();
  12384. }
  12385. let r = cProto.position34.apply(this, arguments);
  12386. return r;
  12387. }
  12388. console1.log("FIX_MENU_POSITION_ON_SHOWN - OK");
  12389.  
  12390. } else {
  12391.  
  12392. console1.log("FIX_MENU_POSITION_ON_SHOWN - NG");
  12393.  
  12394. }
  12395.  
  12396.  
  12397.  
  12398. cProto.__openedChanged = function () {
  12399. // console.log(123445)
  12400. this._positionInitialize_ = 1;
  12401. // this.removeAttribute('horizontal-align')
  12402. // this.removeAttribute('vertical-align')
  12403. if (typeof this.__menuTypeCheck__ !== 'boolean') {
  12404. this.__menuTypeCheck__ = true;
  12405. if (CHAT_MENU_SCROLL_UNLOCKING) {
  12406. this._modifiedMenuPropOn062__ = false;
  12407. // console.log(513, this.positionTarget && this.positionTarget.classList.contains('yt-live-chat-text-message-renderer'))
  12408. // this.autoFitOnAttach = true;
  12409. // this.expandSizingTargetForScrollbars = true;
  12410. // this.allowOutsideScroll = true;
  12411. // console.log(519,Object.getOwnPropertyDescriptors(this.constructor.prototype))
  12412. this.__modifiedMenuPropsFn__();
  12413. // this.constrain= function(){}
  12414. // this.position= function(){}
  12415.  
  12416. // this.autoFitOnAttach = true;
  12417. // this.expandSizingTargetForScrollbars = true;
  12418. // this.allowOutsideScroll = true;
  12419. }
  12420. }
  12421. if (CHAT_MENU_SCROLL_UNLOCKING && this.opened) {
  12422. let newValue = null;
  12423. const positionTarget = this.positionTarget;
  12424. if (positionTarget && positionTarget.classList.contains('yt-live-chat-text-message-renderer')) {
  12425. if (this._modifiedMenuPropOn062__ === false) {
  12426. newValue = true;
  12427. }
  12428. } else if (this._modifiedMenuPropOn062__ === true) {
  12429. newValue = false;
  12430. }
  12431. if (newValue !== null) {
  12432. const beforeAllowOutsideScroll = this.allowOutsideScroll;
  12433. this._modifiedMenuPropOn062__ = newValue;
  12434. const afterAllowOutsideScroll = this.allowOutsideScroll;
  12435. if (beforeAllowOutsideScroll !== afterAllowOutsideScroll) this.__AllowOutsideScrollPD__.set.call(this, afterAllowOutsideScroll);
  12436. }
  12437. }
  12438.  
  12439. if (this.opened) {
  12440.  
  12441. Promise.resolve().then(() => {
  12442.  
  12443. this._prepareRenderOpened();
  12444. }).then(() => {
  12445. // console.log('[yt-chat-dialog]', this._manager)
  12446. try{
  12447. this._manager.addOverlay(this);
  12448. }catch(e){
  12449. console.log('this._manager.addOverlay(this) fails.')
  12450. }
  12451. if (this._manager._overlays.length === 1) {
  12452. lastOpen = this;
  12453. lastClose = null;
  12454. } else {
  12455. return 1;
  12456. }
  12457. // if (cid) {
  12458. // clearTimeout(cid);
  12459. // cid = -1;
  12460. // this.__moChanged__();
  12461. // cid = 0;
  12462. // } else {
  12463. // cid = -1;
  12464. // this.__moChanged__();
  12465. // cid = 0;
  12466. // }
  12467. // cid = cid > 0 ? clearTimeout(cid) : 0;
  12468. // console.log(580, this.positionTarget && this.positionTarget.classList.contains('yt-live-chat-text-message-renderer'))
  12469. // cid = cid || setTimeout(__moChanged__, delay1);
  12470. cid = cid || requestAnimationFrame(__moChanged__);
  12471. }).then((r) => {
  12472.  
  12473. if (r) this.__mtChanged__(1);
  12474. }).catch(console.warn);
  12475.  
  12476. } else {
  12477. Promise.resolve().then(() => {
  12478. // console.log('[yt-chat-dialog]', this._manager)
  12479. try{
  12480. this._manager.removeOverlay(this);
  12481. }catch(e){
  12482. console.log('this._manager.removeOverlay(this) fails.')
  12483. }
  12484. if (this._manager._overlays.length === 0) {
  12485. lastClose = this;
  12486. lastOpen = null;
  12487. } else {
  12488. return 1;
  12489. }
  12490. // cid = cid > 0 ? clearTimeout(cid) : 0;
  12491. // console.log(581, this.positionTarget && this.positionTarget.classList.contains('yt-live-chat-text-message-renderer'))
  12492. // cid = cid || setTimeout(__moChanged__, delay1);
  12493. cid = cid || requestAnimationFrame(__moChanged__);
  12494. }).then((r) => {
  12495. if (r) this.__mtChanged__(0);
  12496. }).catch(console.warn);
  12497.  
  12498. }
  12499.  
  12500. }
  12501. console1.log("BOOST_MENU_OPENCHANGED_RENDERING - OK");
  12502.  
  12503. } else {
  12504.  
  12505. assertor(() => fnIntegrity(cProto.__openedChanged, '0.46.20'));
  12506. console1.log("FIX_MENU_REOPEN_RENDER_PERFORMANC_1 - NG");
  12507.  
  12508. }
  12509.  
  12510.  
  12511. if (FIX_CLICKING_MESSAGE_MENU_DISPLAY_ON_MOUSE_CLICK && typeof cProto.__openedChanged === 'function' && !cProto.__openedChanged82) {
  12512.  
  12513. cProto.__openedChanged82 = cProto.__openedChanged;
  12514.  
  12515.  
  12516. cProto.__openedChanged = function () {
  12517. const positionTarget = this.positionTarget;
  12518. currentMenuPivotWR = positionTarget ? mWeakRef(positionTarget) : null;
  12519. return this.__openedChanged82.apply(this, arguments);
  12520. }
  12521. }
  12522.  
  12523.  
  12524. })();
  12525.  
  12526. console1.log("[End]");
  12527.  
  12528. groupEnd();
  12529.  
  12530. }).catch(console.warn);
  12531.  
  12532.  
  12533.  
  12534. FIX_ToggleRenderPolymerControllerExtractionBug && customElements.whenDefined('yt-live-chat-toggle-renderer').then(() => {
  12535.  
  12536. mightFirstCheckOnYtInit();
  12537. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-toggle-renderer hacks");
  12538. console1.log("[Begin]");
  12539. (() => {
  12540.  
  12541. const tag = "yt-live-chat-toggle-renderer";
  12542. const dummy = document.createElement(tag);
  12543.  
  12544. const cProto = getProto(dummy);
  12545. if (!cProto || !cProto.attached) {
  12546. console1.warn(`proto.attached for ${tag} is unavailable.`);
  12547. return;
  12548. }
  12549.  
  12550. })();
  12551.  
  12552. console1.log("[End]");
  12553. groupEnd();
  12554.  
  12555. });
  12556.  
  12557. FIX_MOUSEOVER_FN && (() => {
  12558.  
  12559. // this is to show tooltip for emoji
  12560.  
  12561.  
  12562. let lastShow = 0;
  12563.  
  12564. const wm = new WeakSet();
  12565. const mo1 = new MutationObserver((mutations) => {
  12566.  
  12567. for (const p of document.querySelectorAll('[shared-tooltip-text]:not([__a6cwm__])')) {
  12568. p.setAttribute('__a6cwm__', '');
  12569. }
  12570.  
  12571. });
  12572. mo1.observe(document, { subtree: true, attributes: true, attributeFilter: ['shared-tooltip-text'], childList: true });
  12573.  
  12574. const mo2 = new MutationObserver((mutations) => {
  12575.  
  12576. for (const mutation of mutations) {
  12577. const p = mutation.target;
  12578. if (mutation.attributeName) {
  12579. if (p.getAttribute('shared-tooltip-text')) { // allow hack
  12580. wm.add(p);
  12581. for (const e of p.getElementsByTagName('*')) {
  12582. wm.add(e);
  12583. }
  12584. } else {
  12585. if (wm.has(p)) {
  12586. wm.remove(p);
  12587. for (const e of p.getElementsByTagName('*')) {
  12588. wm.remove(e);
  12589. }
  12590. }
  12591. }
  12592. }
  12593. }
  12594. });
  12595. mo2.observe(document, { subtree: true, attributes: true, attributeFilter: ['__a6cwm__', 'shared-tooltip-text'], childList: false });
  12596.  
  12597.  
  12598. let done = 0;
  12599. // lcrFn2 will run twice to ensure the method is successfully injected.
  12600. const lcrFn2 = (lcrDummy) => {
  12601. // make minimal function overhead by pre-defining all possible outside.
  12602.  
  12603. const tag = "yt-live-chat-renderer"
  12604. const dummy = lcrDummy;
  12605.  
  12606. const cProto = getProto(dummy);
  12607. if (!cProto || !cProto.attached) {
  12608. console.warn(`proto.attached for ${tag} is unavailable.`);
  12609. return;
  12610. }
  12611.  
  12612. // mightFirstCheckOnYtInit();
  12613. // groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-renderer hacks");
  12614. // console.log("[Begin]");
  12615.  
  12616.  
  12617.  
  12618. if (done !== 1 && typeof cProto.onMouseOver_ === 'function' && !cProto.onMouseOver37_ && typeof cProto.createTooltipIfRequired_ === 'function' && cProto.createTooltipIfRequired_.length === 0) {
  12619.  
  12620. done = 1;
  12621. const onMouseOver37_ = cProto.onMouseOver37_ = cProto.onMouseOver_;
  12622.  
  12623. const checkMatch = (() => {
  12624.  
  12625.  
  12626. let accessList = [];
  12627. let withError = false;
  12628. try {
  12629.  
  12630. onMouseOver37_.call(lcrDummy, {
  12631. type: 'mouseover',
  12632. target: new Proxy({
  12633. nodeName: 'DIV',
  12634. tagName: 'DIV',
  12635. getAttribute: function () { },
  12636. parentNode: null
  12637. }, {
  12638. get(target, p) {
  12639. accessList.push(`getter:${p}`);
  12640. if (!(p in target)) throw Error(`getter ${p} is not found`);
  12641. },
  12642. set(target, p, v) {
  12643. accessList.push(`setter:${p}`);
  12644. throw Error(`setter ${p} is not found`);
  12645. }
  12646. })
  12647. });
  12648. } catch (e) {
  12649. withError = true;
  12650. // console.warn(e);
  12651. }
  12652.  
  12653. if (withError) return false;
  12654.  
  12655. if (accessList.join(',') !== 'getter:getAttribute,getter:parentNode') return false;
  12656.  
  12657. accessList.length = 0;
  12658.  
  12659. let parent;
  12660. try {
  12661.  
  12662. parent = new Proxy({
  12663. nodeName: 'DIV',
  12664. tagName: 'DIV',
  12665. getAttribute: function (e) {
  12666.  
  12667. accessList.push(`getter:getAttribute(${e})`);
  12668. return e === 'shared-tooltip-text' ? ':cherry_blossom:' : null;
  12669.  
  12670. },
  12671. parentNode: null
  12672. }, {
  12673. get(target, p) {
  12674. accessList.push(`getter:${p}`);
  12675. if (!(p in target)) throw Error(`getter ${p} is not found`);
  12676. return target[p]
  12677. },
  12678. set(target, p, v) {
  12679. accessList.push(`setter:${p}`);
  12680. throw Error(`setter ${p} is not found`);
  12681. }
  12682. });
  12683.  
  12684. onMouseOver37_.call(lcrDummy, {
  12685. type: 'mouseover',
  12686. target: new Proxy({
  12687. nodeName: 'IMG',
  12688. tagName: 'IMG',
  12689. id: 'img',
  12690. getAttribute: function (e) {
  12691.  
  12692. accessList.push(`getter:getAttribute(${e})`);
  12693. return e === 'shared-tooltip-text' ? ':cherry_blossom:' : null;
  12694.  
  12695. },
  12696. get parentNode() {
  12697. return parent
  12698. },
  12699. get parentElement() {
  12700. return parent
  12701. }
  12702. }, {
  12703. get(target, p) {
  12704. accessList.push(`getter:${p}`);
  12705. if (!(p in target)) throw Error(`getter ${p} is not found`);
  12706. return target[p]
  12707. },
  12708. set(target, p, v) {
  12709. accessList.push(`setter:${p}`);
  12710. throw Error(`setter ${p} is not found`);
  12711. }
  12712. })
  12713. });
  12714. } catch (e) {
  12715. withError = true;
  12716. // console.warn(e);
  12717. }
  12718. parent = null;
  12719.  
  12720. if (withError && accessList.join(',') === 'getter:getAttribute,getter:getAttribute,getter:getAttribute(shared-tooltip-text),getter:getAttribute,getter:getAttribute(shared-tooltip-text),getter:tagName,getter:parentElement,getter:id,getter:id,getter:$$') {
  12721. return true;
  12722. }
  12723.  
  12724.  
  12725.  
  12726. })();
  12727. if (checkMatch) {
  12728.  
  12729. cProto.onMouseOver_ = function (evt) {
  12730. const p = (evt || 0).target || 0;
  12731. if (p.nodeType === 1 && wm.has(p)) {
  12732. const ct = Date.now();
  12733. if (lastShow + 18 > ct) return;
  12734. const cnt = insp(this);
  12735. lastShow = ct;
  12736. try {
  12737. cnt.onMouseOver37_.call(this, evt);
  12738. } catch (e) {
  12739. console.warn(e);
  12740. }
  12741. }
  12742. };
  12743.  
  12744. const lcrs = toUniqueArr([lcrDummy, ...document.querySelectorAll('yt-live-chat-renderer')]);
  12745. for (const lcr of lcrs) {
  12746. const cnt = insp(lcr);
  12747. const hostElement = cnt.hostElement;
  12748. if (hostElement && cnt.isAttached === true && cnt.onMouseOver37_ === cProto.onMouseOver37_ && typeof cProto.onMouseOver_ === 'function' && cProto.onMouseOver_ !== cProto.onMouseOver37_ && cnt.onMouseOver_ === cProto.onMouseOver_) {
  12749. hostElement.removeEventListener("mouseover", cProto.onMouseOver37_, !0)
  12750. hostElement.addEventListener("mouseover", cProto.onMouseOver_, !0)
  12751. }
  12752. }
  12753.  
  12754. console.log('[yt-chat-lcr] FIX_MOUSEOVER_FN - OK')
  12755.  
  12756. } else {
  12757.  
  12758. console.log('[yt-chat-lcr] FIX_MOUSEOVER_FN - NG')
  12759.  
  12760. }
  12761.  
  12762. } else if (done !== 1) {
  12763. done = 2;
  12764. console.log('[yt-chat-lcr] FIX_MOUSEOVER_FN - NG')
  12765. }
  12766.  
  12767. // console.log("[End]");
  12768. // groupEnd();
  12769.  
  12770.  
  12771. };
  12772. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  12773. // getLCRDummy() must be called for injection
  12774. getLCRDummy().then(lcrFn2);
  12775.  
  12776. })();
  12777.  
  12778.  
  12779. /*
  12780.  
  12781.  
  12782.  
  12783.  
  12784.  
  12785. var FU = function() {
  12786. var a = this;
  12787. this.nextHandle_ = 1;
  12788. this.clients_ = {};
  12789. this.JSC$10323_callbacks_ = {};
  12790. this.unsubscribeAsyncHandles_ = {};
  12791. this.subscribe = vl(function(b, c, d) {
  12792. var e = Geb(b);
  12793. if (e in a.clients_)
  12794. e in a.unsubscribeAsyncHandles_ && Jq.cancel(a.unsubscribeAsyncHandles_[e]);
  12795. else {
  12796. a: {
  12797. var h = Geb(b), l;
  12798. for (l in a.unsubscribeAsyncHandles_) {
  12799. var m = a.clients_[l];
  12800. if (m instanceof KO) {
  12801. delete a.clients_[l];
  12802. delete a.JSC$10323_callbacks_[l];
  12803. Jq.cancel(a.unsubscribeAsyncHandles_[l]);
  12804. delete a.unsubscribeAsyncHandles_[l];
  12805. i6a(m);
  12806. m.objectId_ = new FQa(h);
  12807. m.register();
  12808. d = m;
  12809. break a
  12810. }
  12811. }
  12812. d.objectSource = b.invalidationId.objectSource;
  12813. d.objectId = h;
  12814. if (b = b.webAuthConfigurationData)
  12815. b.multiUserSessionIndex && (d.sessionIndex = parseInt(b.multiUserSessionIndex, 10)),
  12816. b.pageId && (d.pageId = b.pageId);
  12817. d = new KO(d,a.handleInvalidationData_.bind(a));
  12818. d.register()
  12819. }
  12820. a.clients_[e] = d;
  12821. a.JSC$10323_callbacks_[e] = {}
  12822. }
  12823. d = a.nextHandle_++;
  12824. a.JSC$10323_callbacks_[e][d] = c;
  12825. return d
  12826. })
  12827. };
  12828. FU.prototype.unsubscribe = function(a, b) {
  12829. var c = Geb(a);
  12830. if (c in this.JSC$10323_callbacks_ && (delete this.JSC$10323_callbacks_[c][b],
  12831. !this.JSC$10323_callbacks_[c].length)) {
  12832. var d = this.clients_[c];
  12833. b = Jq.run(function() {
  12834. ei(d);
  12835. delete this.clients_[c];
  12836. delete this.unsubscribeAsyncHandles_[c]
  12837. }
  12838. .bind(this));
  12839. this.unsubscribeAsyncHandles_[c] = b
  12840. }
  12841. }
  12842. ;
  12843.  
  12844.  
  12845. */
  12846.  
  12847.  
  12848. const onManagerFound = (dummyManager) => {
  12849. if (!dummyManager || typeof dummyManager !== 'object') return;
  12850.  
  12851. const mgrProto = dummyManager.constructor.prototype;
  12852.  
  12853. let keyCallbackStore = '';
  12854. for (const [key, v] of Object.entries(dummyManager)) {
  12855. if (key.includes('_callbacks_')) keyCallbackStore = key;
  12856. }
  12857.  
  12858. if (!keyCallbackStore || typeof mgrProto.unsubscribe !== 'function' || mgrProto.unsubscribe.length !== 2) return;
  12859.  
  12860. if (mgrProto.unsubscribe16) return;
  12861.  
  12862. mgrProto.unsubscribe16 = mgrProto.unsubscribe;
  12863.  
  12864. groupCollapsed("YouTube Super Fast Chat", " | *live-chat-manager* hacks");
  12865. console1.log("[Begin]");
  12866.  
  12867. const idMapper = new Map();
  12868.  
  12869. const convertId = function (objectId) {
  12870. if (!objectId || typeof objectId !== 'string') return null;
  12871.  
  12872. let result = idMapper.get(objectId)
  12873. if (result) return result;
  12874. result = atob(objectId.replace(/-/g, "+").replace(/_/g, "/"));
  12875. idMapper.set(objectId, result)
  12876. return result;
  12877. }
  12878.  
  12879.  
  12880. const rafHandleHolder = [];
  12881.  
  12882. let pzw = 0;
  12883. let lza = 0;
  12884. const rafHandlerFn = () => {
  12885. pzw = 0;
  12886. if (rafHandleHolder.length === 1) {
  12887. const f = rafHandleHolder[0];
  12888. rafHandleHolder.length = 0;
  12889. f();
  12890. } else if (rafHandleHolder.length > 1) {
  12891. const arr = rafHandleHolder.slice(0);
  12892. rafHandleHolder.length = 0;
  12893. for (const fn of arr) fn();
  12894. }
  12895. };
  12896.  
  12897.  
  12898. if (CHANGE_MANAGER_UNSUBSCRIBE) {
  12899.  
  12900. const checkIntegrityForSubscribe = (mgr) => {
  12901. if (mgr
  12902. && typeof mgr.unsubscribe16 === 'function' && mgr.unsubscribe16.length === 2
  12903. && typeof mgr.subscribe18 === 'function' && (mgr.subscribe18.length === 0 || mgr.subscribe18.length === 3)) {
  12904.  
  12905. const ns = new Set(Object.keys(mgr));
  12906. const ms = new Set(Object.keys(mgr.constructor.prototype));
  12907.  
  12908. if (ns.size >= 6 && ms.size >= 4) {
  12909. // including 'subscribe18'
  12910. // 'unsubscribe16', 'subscribe19'
  12911.  
  12912. let r = 0;
  12913. for (const k of ['nextHandle_', 'clients_', keyCallbackStore, 'unsubscribeAsyncHandles_', 'subscribe', 'subscribe18']) {
  12914. r += ns.has(k) ? 1 : 0;
  12915. }
  12916. for (const k of ['unsubscribe', 'handleInvalidationData_', 'unsubscribe16', 'subscribe19']) {
  12917. r += ms.has(k) ? 1 : 0;
  12918. }
  12919. if (r === 10) {
  12920. const isObject = (c) => (c || 0).constructor === Object;
  12921.  
  12922. if (isObject(mgr['clients_']) && isObject(mgr[keyCallbackStore]) && isObject(mgr['unsubscribeAsyncHandles_'])) {
  12923.  
  12924. return true;
  12925. }
  12926.  
  12927.  
  12928. }
  12929.  
  12930. }
  12931.  
  12932.  
  12933. }
  12934. return false;
  12935. }
  12936.  
  12937. mgrProto.subscribe19 = function (o, f, opts) {
  12938.  
  12939. const ct_clients_ = this.clients_ || 0;
  12940. const ct_handles_ = this.unsubscribeAsyncHandles_ || 0;
  12941.  
  12942. if (this.__doCustomSubscribe__ !== true || !ct_clients_ || !ct_handles_) return this.subscribe18.apply(this, arguments);
  12943.  
  12944. let objectId = ((o || 0).invalidationId || 0).objectId;
  12945. if (!objectId) return this.subscribe18.apply(this, arguments);
  12946. objectId = convertId(objectId);
  12947.  
  12948. // console.log('subscribe', objectId, ct_clients_[objectId], arguments);
  12949.  
  12950. if (ct_clients_[objectId]) {
  12951. if (ct_handles_[objectId] < 0) delete ct_handles_[objectId];
  12952. }
  12953.  
  12954. return this.subscribe18.apply(this, arguments);
  12955. }
  12956.  
  12957. mgrProto.unsubscribe = function (o, d) {
  12958. if (!this.subscribe18 && typeof this.subscribe === 'function') {
  12959. this.subscribe18 = this.subscribe;
  12960. this.subscribe = this.subscribe19;
  12961. this.__doCustomSubscribe__ = checkIntegrityForSubscribe(this);
  12962. }
  12963. const ct_clients_ = this.clients_;
  12964. const ct_handles_ = this.unsubscribeAsyncHandles_;
  12965. if (this.__doCustomSubscribe__ !== true || !ct_clients_ || !ct_handles_) return this.unsubscribe16.apply(this, arguments);
  12966.  
  12967. let objectId = ((o || 0).invalidationId || 0).objectId;
  12968. if (!objectId) return this.unsubscribe16.apply(this, arguments);
  12969.  
  12970. objectId = convertId(objectId);
  12971.  
  12972.  
  12973. // console.log('unsubscribe', objectId, ct_clients_[objectId], arguments);
  12974.  
  12975. const callbacks = this[keyCallbackStore] || 0;
  12976. const callbackObj = callbacks[objectId] || 0;
  12977.  
  12978.  
  12979. if (callbackObj && (delete callbackObj[d], isEmptyObject(callbackObj))) {
  12980. const w = ct_clients_[objectId];
  12981. lza = (lza & 1073741823) + 1;
  12982. const qta = -lza;
  12983. rafHandleHolder.push(() => {
  12984. if (qta === ct_handles_[objectId]) {
  12985. const o = {
  12986. callbacks, callbackObj,
  12987. client: ct_clients_[objectId],
  12988. handle: ct_handles_[objectId]
  12989. };
  12990. let p = 0;
  12991. try {
  12992. if (ct_clients_[objectId] === w) {
  12993. w && "function" === typeof w.dispose && w.dispose();
  12994. delete ct_clients_[objectId];
  12995. delete ct_handles_[objectId];
  12996. p = 1;
  12997. } else {
  12998. // w && "function" === typeof w.dispose && w.dispose();
  12999. // delete ct_clients_[objectId];
  13000. // delete ct_handles_[objectId];
  13001. p = 2;
  13002. }
  13003. } catch (e) {
  13004. console.warn(e);
  13005. }
  13006. console.log(`unsubscribed: ${p}`, this, o);
  13007. }
  13008. });
  13009. ct_handles_[objectId] = qta;
  13010. if (pzw === 0) {
  13011. pzw = requestAnimationFrame(rafHandlerFn);
  13012. }
  13013. }
  13014. }
  13015.  
  13016.  
  13017. console1.log("CHANGE_MANAGER_UNSUBSCRIBE - OK")
  13018.  
  13019. } else {
  13020.  
  13021. console1.log("CHANGE_MANAGER_UNSUBSCRIBE - NG")
  13022. }
  13023.  
  13024. console1.log("[End]");
  13025.  
  13026. groupEnd();
  13027.  
  13028. }
  13029.  
  13030.  
  13031.  
  13032. /*
  13033.  
  13034.  
  13035. a.prototype.async = function(e, h) {
  13036. return 0 < h ? Iq.run(e.bind(this), h) : ~Kq.run(e.bind(this))
  13037. }
  13038. ;
  13039. a.prototype.cancelAsync = function(e) {
  13040. 0 > e ? Kq.cancel(~e) : Iq.cancel(e)
  13041. }
  13042.  
  13043. */
  13044.  
  13045.  
  13046. (FASTER_ICON_RENDERING && Promise.all(
  13047. [
  13048. customElements.whenDefined("yt-icon-shape"),
  13049. customElements.whenDefined("yt-icon")
  13050. // document.createElement('icon-shape'),
  13051. ]
  13052. )).then(() => {
  13053. let cq = 0;
  13054. let dummys = [document.createElement('yt-icon-shape'), document.createElement('yt-icon')]
  13055. for (const dummy of dummys) {
  13056. let cProto = getProto(dummy);
  13057. if (cProto && typeof cProto.shouldRenderIconShape === 'function' && !cProto.shouldRenderIconShape571 && cProto.shouldRenderIconShape.length === 1) {
  13058. assertor(() => fnIntegrity(cProto.shouldRenderIconShape, '1.70.38'));
  13059. cq++;
  13060. cProto.shouldRenderIconShape571 = cProto.shouldRenderIconShape;
  13061. cProto.shouldRenderIconShape = function (a) {
  13062. if (this.isAnimatedIcon) return this.shouldRenderIconShape571(a);
  13063. if (!this.iconType || !this.iconShapeData) return this.shouldRenderIconShape571(a);
  13064. if (!this.iconName) return this.shouldRenderIconShape571(a);
  13065. return false;
  13066. // console.log(1051, this.iconType)
  13067. // console.log(1052, this.iconShapeData)
  13068. // console.log(1053, this.isAnimatedIcon)
  13069. }
  13070. }
  13071. // if(cProto && cProto.switchTemplateAtRegistration){
  13072. // cProto.switchTemplateAtRegistration = false;
  13073. // }
  13074. }
  13075. if (cq === 1) {
  13076. console.log("modified shouldRenderIconShape - Y")
  13077. } else {
  13078. console.log("modified shouldRenderIconShape - N", cq)
  13079. }
  13080. });
  13081.  
  13082. customElements.whenDefined("yt-invalidation-continuation").then(() => {
  13083.  
  13084. let __dummyManager__ = null;
  13085.  
  13086. mightFirstCheckOnYtInit();
  13087. groupCollapsed("YouTube Super Fast Chat", " | yt-invalidation-continuation hacks");
  13088. console1.log("[Begin]");
  13089. (() => {
  13090.  
  13091. const tag = "yt-invalidation-continuation"
  13092. const dummy = document.createElement(tag);
  13093.  
  13094. const cProto = getProto(dummy);
  13095. if (!cProto || !cProto.attached) {
  13096. console1.warn(`proto.attached for ${tag} is unavailable.`);
  13097. return;
  13098. }
  13099.  
  13100. const dummyManager = insp(dummy).manager_ || 0;
  13101. __dummyManager__ = dummyManager;
  13102.  
  13103.  
  13104. })();
  13105.  
  13106. console1.log("[End]");
  13107.  
  13108. groupEnd();
  13109.  
  13110.  
  13111.  
  13112. onManagerFound(__dummyManager__);
  13113.  
  13114. }).catch(console.warn);
  13115.  
  13116.  
  13117. if (INTERACTIVITY_BACKGROUND_ANIMATION >= 1) {
  13118.  
  13119. customElements.whenDefined("yt-live-interactivity-component-background").then(() => {
  13120.  
  13121. mightFirstCheckOnYtInit();
  13122. groupCollapsed("YouTube Super Fast Chat", " | yt-live-interactivity-component-background hacks");
  13123. console1.log("[Begin]");
  13124. (() => {
  13125.  
  13126. const tag = "yt-live-interactivity-component-background"
  13127. const dummy = document.createElement(tag);
  13128.  
  13129. const cProto = getProto(dummy);
  13130. if (!cProto || !cProto.attached) {
  13131. console1.warn(`proto.attached for ${tag} is unavailable.`);
  13132. return;
  13133. }
  13134.  
  13135. cProto.__toStopAfterRun__ = function (hostElement) {
  13136. let mo = new MutationObserver(() => {
  13137. mo.disconnect();
  13138. mo.takeRecords();
  13139. mo = null;
  13140. this.lottieAnimation && this.lottieAnimation.stop(); // primary
  13141. foregroundPromiseFn().then(() => { // if the lottieAnimation is started with rAf triggering
  13142. this.lottieAnimation && this.lottieAnimation.stop(); // fallback
  13143. });
  13144. });
  13145. mo.observe(hostElement, { subtree: true, childList: true });
  13146. }
  13147.  
  13148. if (INTERACTIVITY_BACKGROUND_ANIMATION >= 1 && typeof cProto.maybeLoadAnimationBackground === 'function' && !cProto.maybeLoadAnimationBackground77 && cProto.maybeLoadAnimationBackground.length === 0) {
  13149.  
  13150. cProto.maybeLoadAnimationBackground77 = cProto.maybeLoadAnimationBackground;
  13151. cProto.maybeLoadAnimationBackground = function () {
  13152. let toRun = true;
  13153. let stopAfterRun = false;
  13154. if (!this.__bypassDisableAnimationBackground__) {
  13155. let doFix = false;
  13156. if (INTERACTIVITY_BACKGROUND_ANIMATION === 1) {
  13157. if (!this.lottieAnimation) {
  13158. doFix = true;
  13159. }
  13160. } else if (INTERACTIVITY_BACKGROUND_ANIMATION === 2) {
  13161. doFix = true;
  13162. }
  13163. if (doFix) {
  13164. if (this.useAnimationBackground === true) {
  13165. console.log('DISABLE_INTERACTIVITY_BACKGROUND_ANIMATION', this.lottieAnimation);
  13166. }
  13167. toRun = true;
  13168. stopAfterRun = true;
  13169. }
  13170. }
  13171. if (toRun) {
  13172. if (stopAfterRun && (this.hostElement instanceof HTMLElement_)) {
  13173. this.__toStopAfterRun__(this.hostElement); // primary
  13174. }
  13175. const r = this.maybeLoadAnimationBackground77.apply(this, arguments);
  13176. if (stopAfterRun && this.lottieAnimation) {
  13177. this.lottieAnimation.stop(); // fallback if no mutation
  13178. }
  13179. return r;
  13180. }
  13181. }
  13182.  
  13183. console1.log(`INTERACTIVITY_BACKGROUND_ANIMATION(${INTERACTIVITY_BACKGROUND_ANIMATION}) - OK`);
  13184.  
  13185. } else {
  13186. console1.log(`INTERACTIVITY_BACKGROUND_ANIMATION(${INTERACTIVITY_BACKGROUND_ANIMATION}) - NG`);
  13187.  
  13188. }
  13189.  
  13190. })();
  13191.  
  13192. console1.log("[End]");
  13193.  
  13194. groupEnd();
  13195.  
  13196.  
  13197. }).catch(console.warn);
  13198.  
  13199. }
  13200.  
  13201.  
  13202. if (DELAY_FOCUSEDCHANGED) {
  13203.  
  13204. customElements.whenDefined("yt-live-chat-text-input-field-renderer").then(() => {
  13205.  
  13206.  
  13207. mightFirstCheckOnYtInit();
  13208. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-text-input-field-renderer hacks");
  13209. console1.log("[Begin]");
  13210. (() => {
  13211.  
  13212. const tag = "yt-live-chat-text-input-field-renderer"
  13213. const dummy = document.createElement(tag);
  13214.  
  13215. const cProto = getProto(dummy);
  13216. if (!cProto || !cProto.attached) {
  13217. console1.warn(`proto.attached for ${tag} is unavailable.`);
  13218. return;
  13219. }
  13220.  
  13221. if (DELAY_FOCUSEDCHANGED && typeof cProto.focusedChanged === 'function' && cProto.focusedChanged.length === 0 && !cProto.focusedChanged372) {
  13222. cProto.focusedChanged372 = cProto.focusedChanged;
  13223. cProto.focusedChanged = function () {
  13224. Promise.resolve(this).then((cnt) => {
  13225. if (cnt.isAttached === true) cnt.focusedChanged372();
  13226. });
  13227. }
  13228. }
  13229.  
  13230. })();
  13231.  
  13232. console1.log("[End]");
  13233.  
  13234. groupEnd();
  13235.  
  13236. });
  13237.  
  13238. }
  13239.  
  13240. }
  13241.  
  13242.  
  13243.  
  13244.  
  13245. promiseForCustomYtElementsReady.then(onRegistryReadyForDOMOperations);
  13246.  
  13247. const fixJsonParse = () => {
  13248.  
  13249. let p1 = window.onerror;
  13250.  
  13251. try {
  13252. JSON.parse("{}");
  13253. } catch (e) {
  13254. console.warn(e);
  13255. }
  13256.  
  13257. let p2 = window.onerror;
  13258.  
  13259. if (p1 !== p2) {
  13260.  
  13261.  
  13262. console.groupCollapsed(`%c${"YouTube Super Fast Chat"}%c${" | JS Engine Issue Found"}`,
  13263. "background-color: #010502; color: #fe806a; font-weight: 700; padding: 2px;",
  13264. "background-color: #010502; color: #fe806a; font-weight: 300; padding: 2px;"
  13265. );
  13266.  
  13267. console.warn("\nJSON.parse is hacked (e.g. Brave's script injection) which causes window.onerror changes on every JSON.parse call.\nPlease install https://greasyfork.org/scripts/473972-youtube-js-engine-tamer to fix the issue.\n");
  13268.  
  13269. console.groupEnd();
  13270.  
  13271. }
  13272.  
  13273. }
  13274.  
  13275. if (CHECK_JSONPRUNE) {
  13276. promiseForCustomYtElementsReady.then(fixJsonParse);
  13277. }
  13278.  
  13279. });
  13280.  
  13281.  
  13282.  
  13283. })({ IntersectionObserver });