YouTube 超快聊天

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

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

  1. // ==UserScript==
  2. // @name YouTube Super Fast Chat
  3. // @version 0.102.13
  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.gf.qytechs.cn/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://gf.qytechs.cn/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. let dataEntries_ = this[cTag];
  3647. const renderEntries = dataEntries_.map((item) => {
  3648. const [L, H] = deObjectComponent(item);
  3649. const componentName = this.getComponentName_(L, H);
  3650. if (H && H.id && componentName) {
  3651. const wId = `${componentName}#${H.id}`;
  3652. if (!H.__renderOrderId422__) {
  3653. H.__renderOrderId422__ = this.__renderOrderId411__ = (this.__renderOrderId411__ & 1073741823) + 1;
  3654. }
  3655. let p = renderOrdering[wId];
  3656. if (p) doFix = true;
  3657. if (!p || p > H.__renderOrderId422__) {
  3658. renderOrdering[wId] = H.__renderOrderId422__;
  3659. }
  3660. return [item, L, H, componentName, wId];
  3661. } else {
  3662. return [item, L, H, componentName, true];
  3663. }
  3664. });
  3665. if (doFix) {
  3666. for (let i = renderEntries.length - 1; i >= 0; i--) {
  3667. const e = renderEntries[i];
  3668. let m = e[4];
  3669. if (m === true) {
  3670. } else if (renderOrdering[m] === e[2].__renderOrderId422__) {
  3671. } else {
  3672. dataEntries_.splice(i, 1);
  3673. renderEntries.splice(i, 1);
  3674. }
  3675. }
  3676. }
  3677. dataEntries_ = null;
  3678. renderOrdering = null;
  3679.  
  3680. const renderList = renderEntries.map((e) => {
  3681. const [item, L, H, componentName] = e;
  3682. const node = kRef(renderMap.get(H));
  3683. if (node && hostElement.contains(node)) {
  3684. renderNodeCount++;
  3685. return node;
  3686. } else if (node && !hostElement.contains(node)) {
  3687. renderMap.delete(H);
  3688. return item;
  3689. } else {
  3690. return item;
  3691. }
  3692. });
  3693.  
  3694. const isRenderListEmpty = renderList.length === 0;
  3695.  
  3696. // console.log(1773, this.ec389a, this.ec389r)
  3697.  
  3698. this.ec389a = 0;
  3699. this.ec389r = 0;
  3700.  
  3701.  
  3702. // this.ec389 = null;
  3703. // this.ec389a = 0;
  3704. // this.ec389r = 0;
  3705.  
  3706. let addedCounter = 0;
  3707. let removedCounter = 0;
  3708.  
  3709. const createConnectedComponentElm = (insertionObj, L, H, componentName) => {
  3710. // const reusable = false;
  3711. // const componentName = this.getComponentName_(L, H);
  3712. let component;
  3713. if (!nullComponents.has(componentName)) {
  3714. nullComponents.set(componentName, (component = document.createElement(componentName)));
  3715. component.className = stamperDomClass;
  3716. // shadowElm.insertAdjacentElement('beforeend', component);
  3717. } else {
  3718. component = nullComponents.get(componentName);
  3719. }
  3720. component = component.cloneNode(false);
  3721.  
  3722. // const cnt = insp(component);
  3723.  
  3724. // cnt.__dataOld = cnt.__dataPending = null;
  3725. pDivNew.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3726. mockCommentElement(pDivNew.lastChild);
  3727. pDivNew.lastChild.replaceWith(component);
  3728. // cnt.__dataOld = cnt.__dataPending = null;
  3729.  
  3730. return component;
  3731. }
  3732.  
  3733. const listDom = this.getStampContainer_(cId);
  3734.  
  3735. const pnForNewItem = (item) => {
  3736.  
  3737. const [L, H] = deObjectComponent(item);
  3738.  
  3739. const componentName = this.getComponentName_(L, H);
  3740.  
  3741. const wmList = wmRemoved.get(componentName.toLowerCase());
  3742.  
  3743. let connectedComponent = null;
  3744. if (wmList && (connectedComponent = wmList.firstElementChild)) {
  3745. if (this.telemetry_) this.telemetry_.reuse++;
  3746. // if (!wmPendingList) {
  3747. // wmPendingList = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
  3748. // wmPendingList.setAttributeNS('http://www.w3.org/2000/svg', 'wm-pending', 'true');
  3749. // pDiv.insertAdjacentElement('afterend', wmPendingList);
  3750. // }
  3751. // wmPendingList.insertAdjacentElement('beforeend', connectedComponent);
  3752. pDivNew.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3753. mockCommentElement(pDivNew.lastChild);
  3754. pDivNew.lastChild.replaceWith(connectedComponent);
  3755. const attrMap = connectedComponent.attributes;
  3756. const defaultAttrs = componentDefaultAttributes.get(connectedComponent);
  3757. if (defaultAttrs) {
  3758. for (const attr of [...attrMap]) {
  3759. const name = attr.name;
  3760. if (name in defaultAttrs) attr.value = defaultAttrs[name];
  3761. else attrMap.removeNamedItem(name);
  3762. }
  3763. if (attrMap.length !== defaultAttrs['"']) {
  3764. for (const name in defaultAttrs) {
  3765. if (!attrMap[name] && name !== '"') connectedComponent.setAttribute(name, defaultAttrs[name]);
  3766. }
  3767. }
  3768. }
  3769.  
  3770. } else {
  3771. connectedComponent = createConnectedComponentElm(item, L, H, componentName);
  3772. if (this.telemetry_) this.telemetry_.create++;
  3773. }
  3774. if (isTickerRendering) {
  3775. const container = connectedComponent.firstElementChild;
  3776. if (container) container.classList.add('yt-live-chat-ticker-stampdom-container');
  3777. }
  3778.  
  3779. return [item, L, H, connectedComponent];
  3780.  
  3781. };
  3782.  
  3783. let imgPreloadPr = null;
  3784. if (isMessageListRendering) {
  3785. const addedItems = renderList.filter(item => item === 'object' && (item instanceof Node));
  3786. imgPreloadPr = preloadFn(addedItems)();
  3787. }
  3788.  
  3789. spliceTempDisabled = false;
  3790.  
  3791. // const pt1 = performance.now();
  3792. // const newComponentsEntries = await Promise.all(renderList.map((item) => {
  3793. // return typeof item === 'object' && !(item instanceof Node) ? Promise.resolve(item).then(pnForNewItem) : item;
  3794. // }));
  3795. const newComponentsEntries = isRenderListEmpty ? [] : await executeTaskBatch(renderList.map(item => ({
  3796. item,
  3797. fn(task) {
  3798. const { item } = task;
  3799. return typeof item === 'object' && !(item instanceof Node) ? pnForNewItem(item) : item;
  3800. }
  3801. })));
  3802. // const pt2 = performance.now();
  3803.  
  3804. const imgPromises = [];
  3805.  
  3806. const imgPaths = new Set();
  3807.  
  3808. const pnForRenderNewItem = (entry) => {
  3809. const [item, L, H, connectedComponent] = entry;
  3810.  
  3811. // const cnt = insp(connectedComponent);
  3812. // setupRefreshData930(cnt);
  3813. // if (typeof cnt.data === 'object' && cnt.__dataEnabled === true && cnt.__dataReady === true && cnt.__dataInvalid === false) {
  3814. // cnt.data = H;
  3815. // } else {
  3816. const q = this.deferRenderStamperBinding_
  3817. let q2;
  3818. if (typeof q === 'object') q2 = this.deferRenderStamperBinding_ = [];
  3819. this.deferRenderStamperBinding_(connectedComponent, L, Object.assign({}, H)); // pre-flush
  3820. this.flushRenderStamperComponentBindings_();
  3821. if (typeof q === 'object') {
  3822. this.deferRenderStamperBinding_ = q;
  3823. q2.length = 0;
  3824. }
  3825. // }
  3826. // if (cnt.__refreshData930__ && cnt.data) cnt.__refreshData930__('data', !0); // ensure data is invalidated
  3827.  
  3828. // fix yt-icon issue
  3829. // refreshChildrenYtIcons(connectedComponent);
  3830.  
  3831. // const imgs = connectedComponent.getElementsByTagName('IMG');
  3832. // if (imgs.length > 0) {
  3833. // for (let i = 0, l = imgs.length; i < l; i++) {
  3834. // const src = imgs[i].src;
  3835. // if (src.includes('://') && !imgPaths.has(src)) {
  3836. // imgPaths.add(src);
  3837. // imgPromises.push(imageFetch(src));
  3838. // }
  3839. // }
  3840. // }
  3841. componentDefaultAttributes.set(connectedComponent, getAttributes(connectedComponent));
  3842. return entry;
  3843. }
  3844.  
  3845. // const pt3 = performance.now();
  3846. // const newRenderedComponents = await Promise.all(newComponentsEntries.map((entry) => {
  3847. // return typeof entry === 'object' && !(entry instanceof Node) ? Promise.resolve(entry).then(pnForRenderNewItem) : entry;
  3848. // }));
  3849. const newRenderedComponents = isRenderListEmpty ? [] : await executeTaskBatch(newComponentsEntries.map(entry => ({
  3850. entry,
  3851. fn(task) {
  3852. const { entry } = task;
  3853. return typeof entry === 'object' && !(entry instanceof Node) ? pnForRenderNewItem(entry) : entry;
  3854. }
  3855. })));
  3856. // const pt4 = performance.now();
  3857.  
  3858. // console.log('xxss' , pt2-pt1, pt4-pt3)
  3859.  
  3860. this.flushRenderStamperComponentBindings_(); // ensure all deferred flush render tasks clear.
  3861.  
  3862. // imgPromises.push(imageFetch('data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'));
  3863. if (imgPromises.length > 0) {
  3864. const pr1 = Promise.all(imgPromises).catch(e => { });
  3865. const pr2 = autoTimerFn();
  3866. await Promise.race([pr1, pr2]).catch(e => { });
  3867. imgPaths.clear();
  3868. imgPromises.length = 0;
  3869. }
  3870. if (imgPreloadPr) await imgPreloadPr;
  3871.  
  3872. // const batching = [];
  3873. // let j = 0;
  3874. // let elNode;
  3875.  
  3876. const sideProcesses = [];
  3877.  
  3878. const removeStampNode_ = (elNode) => {
  3879.  
  3880. const elm = elNode;
  3881. const cnt = insp(elm);
  3882. let elemCount1 = elm.querySelectorAll('yt-img-shadow').length;
  3883.  
  3884. const elParent = elm.parentNode;
  3885. if (elm.__requestRemovalAt003__) {
  3886. elm.__requestRemovalAt003__ = 0;
  3887. } else {
  3888. if (cnt.requestRemoval) cnt.requestRemoval();
  3889. }
  3890. try {
  3891. (elParent.__domApi || elParent).removeChild(elm);
  3892. } catch (e) { }
  3893. const frag = document.createDocumentFragment();
  3894. frag.appendChild(elm);
  3895.  
  3896. const componentName = elm.nodeName.toLowerCase();
  3897. let wmList = wmRemoved.get(componentName);
  3898. if (!wmList) {
  3899. wmList = document.createDocumentFragment();
  3900. wmRemoved.set(componentName, wmList);
  3901. }
  3902. const data = cnt.data;
  3903. if (data) renderMap.delete(cnt.data);
  3904.  
  3905. let elemCount2 = elm.querySelectorAll('yt-img-shadow').length;
  3906.  
  3907. const [p1, p2] = [reuseFixDataViewModel(elm), reuseFixYtIconRendering(elm)];
  3908.  
  3909. sideProcesses.push(p1);
  3910. sideProcesses.push(p2);
  3911.  
  3912. if (!window.__fixTemplateReuse1058__ && elemCount1 !== elemCount2) return; // cannot reuse
  3913.  
  3914. Promise.all([elm, wmList, p1, p2]).then((r) => {
  3915. const [elm, wmList] = r;
  3916. wmList.appendChild(elm);
  3917. });
  3918. }
  3919.  
  3920. // const removeStampNode = async () => {
  3921.  
  3922. // removedCounter++;
  3923.  
  3924. // const nextElm = nextComponentSiblingFn(elNode);
  3925. // const elmId = elNode.id;
  3926. // removeStampNode_(elNode);
  3927. // // const dzid = this.getAttribute('dz-component-id');
  3928. // // ---- no-cache ----
  3929. // // try{
  3930. // // elm.remove();
  3931. // // }catch(e){}
  3932. // // ---- no-cache ----
  3933.  
  3934. // if (cTag === 'visibleItems') {
  3935. // sideProcesses.push(onVisibleItemStampNodeRemoval(elmId));
  3936. // }
  3937.  
  3938. // j++;
  3939. // elNode = nextElm;
  3940.  
  3941. // }
  3942.  
  3943. // if (typeof Polymer !== "undefined" && typeof Polymer.flush === "function") {
  3944. // // clear all pending rendering first
  3945. // await stackMarcoTask(async () => {
  3946. // Polymer.flush();
  3947. // });
  3948. // }
  3949.  
  3950. // main UI thread - DOM modification
  3951. await new Promise((resolveDM) => {
  3952. nextBrowserTick_(() => {
  3953.  
  3954. const isAtBottom = this.atBottom === true;
  3955. // if (ENABLE_OVERFLOW_ANCHOR && isAtBottom) {
  3956. // shouldScrollAfterFlush = true;
  3957. // }
  3958.  
  3959.  
  3960. const tasks = [];
  3961. let fragAppend = document.createDocumentFragment();
  3962. let shouldManualScroll = null;
  3963. let scrollTop1 = null, scrollTop2 = null;
  3964.  
  3965. const taskFn = {
  3966. remove: (task) => {
  3967.  
  3968. const { elNode } = task;
  3969.  
  3970. removedCounter++;
  3971.  
  3972. const elmId = elNode.id;
  3973. removeStampNode_(elNode);
  3974. // const dzid = this.getAttribute('dz-component-id');
  3975. // ---- no-cache ----
  3976. // try{
  3977. // elm.remove();
  3978. // }catch(e){}
  3979. // ---- no-cache ----
  3980.  
  3981. if (isMessageListRendering) {
  3982. sideProcesses.push(onVisibleItemStampNodeRemoval(elmId));
  3983. }
  3984.  
  3985. return 2
  3986.  
  3987. },
  3988. append: (task) => {
  3989.  
  3990. if (!fragAppend) return;
  3991.  
  3992. const { newNode, nodeAfter, parentNode, L, H } = task;
  3993.  
  3994. fragAppend.appendChild(newNode);
  3995.  
  3996.  
  3997. const itemScrollerX = (isMessageListRendering && isAtBottom) ? this.itemScroller : null;
  3998.  
  3999.  
  4000. if (itemScrollerX) {
  4001. if (scrollTop1 === null) scrollTop1 = itemScrollerX.scrollTop;
  4002. }
  4003.  
  4004. if (nodeAfter) {
  4005. (parentNode.__domApi || parentNode).insertBefore(fragAppend, nodeAfter);
  4006. } else {
  4007. (parentNode.__domApi || parentNode).appendChild(fragAppend);
  4008. }
  4009.  
  4010. this.deferRenderStamperBinding_(newNode, L, H);
  4011. this.flushRenderStamperComponentBindings_();
  4012.  
  4013.  
  4014. // nodeAfter ? nodeAfter.insertAdjacentElement('beforebegin', newNode) : parentNode.insertAdjacentElement('beforeend', newNode);
  4015. const connectedComponent = newNode;
  4016. const cnt = insp(connectedComponent);
  4017. renderMap.set(cnt.data, mWeakRef(connectedComponent));
  4018. // mutationDelayedRefreshData(cnt); // not included to sideProcesses
  4019. addedCounter++;
  4020.  
  4021. if (isTickerRendering) {
  4022. sideProcesses.push(onTickerItemStampNodeAdded());
  4023. }
  4024.  
  4025. if (itemScrollerX) {
  4026. if (scrollTop2 === null) scrollTop2 = itemScrollerX.scrollTop;
  4027. if (shouldManualScroll === null) shouldManualScroll = (scrollTop1 >= 0 && scrollTop2 >= 0 && Math.abs(scrollTop2 - scrollTop1) < 6);
  4028. if (shouldManualScroll) {
  4029. itemScrollerX.scrollTop = scrollTop2 + 16777216;
  4030. }
  4031. }
  4032.  
  4033. return 1
  4034. }
  4035. }
  4036.  
  4037. {
  4038. const indexMap = new WeakMap();
  4039. // let index = 0;
  4040.  
  4041. if (!isRenderListEmpty) {
  4042. for (let elNode_ = firstComponentChildFn(listDom), index = 0; elNode_ instanceof Node; elNode_ = nextComponentSiblingFn(elNode_)) {
  4043. indexMap.set(elNode_, index++);
  4044. }
  4045. }
  4046.  
  4047.  
  4048.  
  4049. const keepIndices = new Array(renderNodeCount);
  4050. let keepIndicesLen = 0, lastKeepIndex = -1, requireSort = false;
  4051. for (let i = 0, l = newRenderedComponents.length; i < l; i++) {
  4052. const entry = newRenderedComponents[i];
  4053. if (entry instanceof Node) {
  4054. const index = indexMap.get(entry);
  4055. keepIndices[keepIndicesLen++] = [index, entry];
  4056. if (index > lastKeepIndex) lastKeepIndex = index;
  4057. else requireSort = true;
  4058. }
  4059. }
  4060. keepIndices.length = keepIndicesLen;
  4061. if (requireSort) keepIndices.sort((a, b) => a[0] - b[0]);
  4062. let dk = 0;
  4063.  
  4064. let j = 0;
  4065. let elNode;
  4066.  
  4067. elNode = firstComponentChildFn(listDom);
  4068.  
  4069. if (!isRenderListEmpty) {
  4070. for (const rcEntry of newRenderedComponents) {
  4071. const index = indexMap.get(rcEntry);
  4072. if (typeof index === 'number') {
  4073. const indexEntry = keepIndices[dk++];
  4074. const [dIdx, dNode] = indexEntry;
  4075. indexMap.delete(rcEntry);
  4076. const idx = dIdx;
  4077. while (j < idx && elNode) {
  4078. tasks.push({
  4079. type: 'remove',
  4080. elNode,
  4081. fn: taskFn.remove
  4082. });
  4083. elNode = nextComponentSiblingFn(elNode);
  4084. j++;
  4085. }
  4086. if (j === idx) {
  4087. if (elNode) {
  4088. // if (dNode !== elNode) tasks.push({
  4089. // type: 'swap',
  4090. // earlyNode: indexEntry[1],
  4091. // laterNode: elNode
  4092. // });
  4093. elNode = nextComponentSiblingFn(elNode);
  4094. j++;
  4095. } else {
  4096. console.warn('elNode is not available?', renderList, addedCount0, removedCount0, j, idx);
  4097. }
  4098. }
  4099. } else if (rcEntry instanceof Node) {
  4100. // interruped by the external like clearList
  4101.  
  4102. tasks.push({
  4103. type: 'remove',
  4104. elNode: rcEntry,
  4105. fn: taskFn.remove
  4106. });
  4107.  
  4108. } else {
  4109. const [item, L, H, connectedComponent] = rcEntry;
  4110.  
  4111. tasks.push({
  4112. type: 'append',
  4113. newNode: connectedComponent,
  4114. nodeAfter: elNode,
  4115. parentNode: listDom,
  4116. item, L, H,
  4117. fn: taskFn.append
  4118. });
  4119.  
  4120. }
  4121.  
  4122. }
  4123. }
  4124.  
  4125. while (elNode) {
  4126.  
  4127. tasks.push({
  4128. type: 'remove',
  4129. elNode,
  4130. fn: taskFn.remove
  4131. });
  4132. elNode = nextComponentSiblingFn(elNode);
  4133.  
  4134. }
  4135.  
  4136. }
  4137.  
  4138. if (tasks.length >= 1) {
  4139. executeTaskBatch(tasks).then(() => {
  4140. fragAppend = null;
  4141. resolveDM();
  4142. }).catch(console.warn);
  4143. }
  4144.  
  4145. });
  4146. }).catch(console.warn);
  4147.  
  4148. {
  4149. const arr = this[cTag];
  4150. let b = 0;
  4151. b = b | this._setPendingPropertyOrPath(`${cTag}.splices`, {}, true, true);
  4152. b = b | this._setPendingPropertyOrPath(`${cTag}.length`, arr.length, true, true);
  4153. b && this._invalidateProperties();
  4154. }
  4155.  
  4156. // this.flushRenderStamperComponentBindings_(); // just in case...
  4157.  
  4158. await Promise.all(sideProcesses);
  4159.  
  4160. const detail = {
  4161. container: listDom
  4162. };
  4163. stampDomEvent_ && this.hostElement.dispatchEvent(new CustomEvent("yt-rendererstamper-finished", {
  4164. bubbles: !0,
  4165. cancelable: !1,
  4166. composed: !0,
  4167. detail
  4168. }));
  4169. detail.container = null;
  4170.  
  4171. // if (typeof Polymer !== "undefined" && typeof Polymer.flush === "function") {
  4172. // // clear all remaining rendering before promise resolve
  4173. // await stackMarcoTask(async () => {
  4174. // Polymer.flush();
  4175. // });
  4176. // }
  4177.  
  4178. }
  4179.  
  4180. // proceedStampDomArraySplices371_ // proceedStampDomArraySplices381_
  4181. cProto[key] = function (cTag, cId, indexSplice) {
  4182. if (spliceTempDisabled) return true;
  4183. // console.log('proceedStampDomArraySplices_')
  4184. // assume no error -> no try catch (performance consideration)
  4185. const { index, addedCount, removed } = indexSplice;
  4186. const removedCount = removed ? removed.length : indexSplice.removedCount;
  4187. indexSplice = null;
  4188. if (!addedCount && !removedCount) {
  4189. console.warn('proceedStampDomArraySplices_', 'Error 001');
  4190. return false;
  4191. }
  4192. if (this.ec389) {
  4193. this.ec389a += addedCount;
  4194. this.ec389r += removedCount;
  4195. } else {
  4196. if (this.ec389a || this.ec389r) {
  4197. console.warn('proceedStampDomArraySplices_', 'Error 002');
  4198. return false;
  4199. }
  4200. if (typeof (cTag || 0) !== 'string' || typeof (cId || 0) !== 'string') {
  4201. console.warn('proceedStampDomArraySplices_', 'Error 003');
  4202. return false;
  4203. }
  4204. this.ec389 = true;
  4205. this.ec389a = addedCount;
  4206. this.ec389r = removedCount;
  4207. const pr00 = this.ec389pr;
  4208. const pr11 = this.ec389pr = this[fnKeyH](cTag, cId, pr00).catch(console.warn);
  4209. if (cTag === 'visibleItems') {
  4210. this.prDelay288 = pr11;
  4211. }
  4212. }
  4213. return true;
  4214. };
  4215.  
  4216.  
  4217. }
  4218.  
  4219.  
  4220. class RAFHub {
  4221. constructor() {
  4222. /** @type {number} */
  4223. this.startAt = 8170;
  4224. /** @type {number} */
  4225. this.counter = 0;
  4226. /** @type {number} */
  4227. this.rid = 0;
  4228. /** @type {Map<number, FrameRequestCallback>} */
  4229. this.funcs = new Map();
  4230. const funcs = this.funcs;
  4231. /** @type {FrameRequestCallback} */
  4232. this.bCallback = this.mCallback.bind(this);
  4233. this.pClear = () => funcs.clear();
  4234. this.keepRAF = false;
  4235. }
  4236. /** @param {DOMHighResTimeStamp} highResTime */
  4237. mCallback(highResTime) {
  4238. this.rid = 0;
  4239. Promise.resolve().then(this.pClear);
  4240. this.funcs.forEach(func => Promise.resolve(highResTime).then(func).catch(console.warn));
  4241. }
  4242. /** @param {FrameRequestCallback} f */
  4243. request(f) {
  4244. const cid = this.startAt + (this.counter = (this.counter & 1073741823) + 1);
  4245. this.funcs.set(cid, f);
  4246. if (this.rid === 0) this.rid = requestAnimationFrame(this.bCallback);
  4247. return cid;
  4248. }
  4249. /** @param {number} cid */
  4250. cancel(cid) {
  4251. cid = +cid;
  4252. if (cid > 0) {
  4253. if (cid <= this.startAt) {
  4254. return cancelAnimationFrame(cid);
  4255. }
  4256. if (this.rid > 0) {
  4257. this.funcs.delete(cid);
  4258. if (this.funcs.size === 0 && !this.keepRAF) {
  4259. cancelAnimationFrame(this.rid);
  4260. this.rid = 0;
  4261. }
  4262. }
  4263. }
  4264. }
  4265. }
  4266.  
  4267. function basePrefetching() {
  4268.  
  4269. new Promise(resolve => {
  4270.  
  4271. if (document.readyState !== 'loading') {
  4272. resolve();
  4273. } else {
  4274. win.addEventListener("DOMContentLoaded", resolve, false);
  4275. }
  4276.  
  4277. }).then(() => {
  4278. const hostL1 = [
  4279. 'https://www.youtube.com', 'https://googlevideo.com',
  4280. 'https://googleapis.com', 'https://accounts.youtube.com',
  4281. 'https://www.gstatic.com', 'https://ggpht.com',
  4282. 'https://yt3.ggpht.com', 'https://yt4.ggpht.com'
  4283. ];
  4284.  
  4285. const hostL2 = [
  4286. 'https://youtube.com',
  4287. 'https://fonts.googleapis.com', 'https://fonts.gstatic.com'
  4288. ];
  4289.  
  4290. let link = null;
  4291.  
  4292. function kn() {
  4293.  
  4294. link = document.createElement('link');
  4295. if (link.relList && link.relList.supports) {
  4296. 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)
  4297. } else {
  4298. kptPF = 0;
  4299. }
  4300.  
  4301. groupCollapsed("YouTube Super Fast Chat", " | PREFETCH SUPPORTS");
  4302. if (ENABLE_BASE_PREFETCHING) console1.log('dns-prefetch', (kptPF & 1) ? 'OK' : 'NG');
  4303. if (ENABLE_BASE_PREFETCHING) console1.log('preconnect', (kptPF & 2) ? 'OK' : 'NG');
  4304. if (ENABLE_PRELOAD_THUMBNAIL) console1.log('prefetch', (kptPF & 4) ? 'OK' : 'NG');
  4305. if (ENABLE_PRELOAD_THUMBNAIL) console1.log('preload', (kptPF & 16) ? 'OK' : 'NG');
  4306. groupEnd();
  4307.  
  4308. }
  4309.  
  4310. for (const h of hostL1) {
  4311.  
  4312. if (kptPF === null) kn();
  4313. if (ENABLE_BASE_PREFETCHING) {
  4314. // if (kptPF & 1) {
  4315. // linker(link, 'dns-prefetch', h);
  4316. // link = null;
  4317. // }
  4318. if (kptPF & 2) {
  4319. linker(link, 'preconnect', h);
  4320. link = null;
  4321. }
  4322. }
  4323. }
  4324.  
  4325. for (const h of hostL2) {
  4326. if (kptPF === null) kn();
  4327. if (ENABLE_BASE_PREFETCHING) {
  4328. if (kptPF & 1) {
  4329. linker(link, 'dns-prefetch', h);
  4330. link = null;
  4331. }
  4332. }
  4333. }
  4334.  
  4335. })
  4336.  
  4337.  
  4338. }
  4339.  
  4340. if (DO_LINK_PREFETCH) basePrefetching();
  4341.  
  4342. const { notifyPath7081 } = (() => {
  4343. // DO_PARTICIPANT_LIST_HACKS
  4344.  
  4345. const mutexParticipants = new Mutex();
  4346.  
  4347. let uvid = 0;
  4348. let r95dm = 0;
  4349. let c95dm = -1;
  4350.  
  4351. const foundMap = (base, content) => {
  4352. /*
  4353. let lastSearch = 0;
  4354. let founds = base.map(baseEntry => {
  4355. let search = content.indexOf(baseEntry, lastSearch);
  4356. if (search < 0) return false;
  4357. lastSearch = search + 1;
  4358. return true;
  4359. });
  4360. return founds;
  4361. */
  4362. const contentSet = new Set(content);
  4363. const r = base.map(baseEntry => contentSet.has(baseEntry));
  4364. contentSet.clear();
  4365. return r
  4366.  
  4367. }
  4368.  
  4369.  
  4370.  
  4371. let participantsForSpliceWR = null;
  4372.  
  4373. class IndexSpliceEntry {
  4374. /**
  4375. *
  4376. * @param {number} _index
  4377. * @param {number} _addedCount
  4378. * @param {any[]} _removed
  4379. */
  4380. constructor(_index, _addedCount, _removed) {
  4381. this.index = _index;
  4382. this.addedCount = _addedCount;
  4383. this.removed = _removed;
  4384. }
  4385. get __proxy312__() {
  4386. return 1
  4387. }
  4388. get type() {
  4389. return 'splice'
  4390. }
  4391. get object() {
  4392. return kRef(participantsForSpliceWR); // avoid memory leakage
  4393. }
  4394. }
  4395.  
  4396. const spliceIndicesFunc = (beforeParticipants, participants, idsBefore, idsAfter) => {
  4397.  
  4398. let foundsForAfter = foundMap(idsAfter, idsBefore);
  4399. let foundsForBefore = foundMap(idsBefore, idsAfter);
  4400.  
  4401. const nAfter = foundsForAfter.length;
  4402. const nBefore = foundsForBefore.length;
  4403.  
  4404. const indexSplices = [];
  4405. const contentUpdates = [];
  4406. participantsForSpliceWR = null;
  4407. for (let i = 0, j = 0; i < nBefore || j < nAfter;) {
  4408. if (beforeParticipants[i] === participants[j]) {
  4409. i++; j++;
  4410. } else if (idsBefore[i] === idsAfter[j]) {
  4411. // content changed
  4412. contentUpdates.push({ indexI: i, indexJ: j })
  4413. i++; j++;
  4414. } else {
  4415. let addedCount = 0;
  4416. for (let q = j; q < nAfter; q++) {
  4417. if (foundsForAfter[q] === false) addedCount++;
  4418. else break;
  4419. }
  4420. let removedCount = 0;
  4421. for (let q = i; q < nBefore; q++) {
  4422. if (foundsForBefore[q] === false) removedCount++;
  4423. else break;
  4424. }
  4425. if (!addedCount && !removedCount) {
  4426. throw 'ERROR(0xFF32): spliceIndicesFunc';
  4427. }
  4428. const entry = new IndexSpliceEntry(
  4429. j,
  4430. addedCount,
  4431. removedCount >= 1 ? beforeParticipants.slice(i, i + removedCount) : []
  4432. );
  4433. indexSplices.push(entry);
  4434. i += removedCount;
  4435. j += addedCount;
  4436. }
  4437. }
  4438. foundsForBefore = null;
  4439. foundsForAfter = null;
  4440. idsBefore = null;
  4441. idsAfter = null;
  4442. beforeParticipants = null;
  4443. participantsForSpliceWR = indexSplices.length > 0 ? mWeakRef(participants) : null;
  4444. participants = null;
  4445. return { indexSplices, contentUpdates };
  4446.  
  4447. }
  4448.  
  4449. /*
  4450.  
  4451. customElements.get("yt-live-chat-participant-renderer").prototype.notifyPath=function(){ console.log(123); console.log(new Error().stack)}
  4452.  
  4453. VM63631:1 Error
  4454. at customElements.get.notifyPath (<anonymous>:1:122)
  4455. at e.forwardRendererStamperChanges_ (live_chat_polymer.js:4453:35)
  4456. at e.rendererStamperApplyChangeRecord_ (live_chat_polymer.js:4451:12)
  4457. at e.rendererStamperObserver_ (live_chat_polymer.js:4448:149)
  4458. at Object.pu [as fn] (live_chat_polymer.js:1692:118)
  4459. at ju (live_chat_polymer.js:1674:217)
  4460. at a._propertiesChanged (live_chat_polymer.js:1726:122)
  4461. at b._flushProperties (live_chat_polymer.js:1597:200)
  4462. at a._invalidateProperties (live_chat_polymer.js:1718:69)
  4463. at a.notifyPath (live_chat_polymer.js:1741:182)
  4464.  
  4465. */
  4466.  
  4467. function convertToIds(participants) {
  4468. return participants.map(participant => {
  4469. if (!participant || typeof participant !== 'object') {
  4470. console.warn('Error(0xFA41): convertToIds', participant);
  4471. return participant; // just in case
  4472. }
  4473. let keys = Object.keys(participant);
  4474. // liveChatTextMessageRenderer
  4475. // liveChatParticipantRenderer - livestream channel owner [no authorExternalChannelId]
  4476. // liveChatPaidMessageRenderer
  4477. /*
  4478.  
  4479. 'yt-live-chat-participant-renderer' utilizes the following:
  4480. authorName.simpleText: string
  4481. authorPhoto.thumbnails: Object{url:string, width:int, height:int} []
  4482. authorBadges[].liveChatAuthorBadgeRenderer.icon.iconType: string
  4483. authorBadges[].liveChatAuthorBadgeRenderer.tooltip: string
  4484. authorBadges[].liveChatAuthorBadgeRenderer.accessibility.accessibilityData: Object{label:string}
  4485.  
  4486. */
  4487. if (keys.length !== 1) {
  4488. console.warn('Error(0xFA42): convertToIds', participant);
  4489. return participant; // just in case
  4490. }
  4491. let key = keys[0];
  4492. let renderer = (participant[key] || 0);
  4493. let authorName = (renderer.authorName || 0);
  4494. let text = `${authorName.simpleText || authorName.text}`
  4495. let res = participant; // fallback if it is not a vaild entry
  4496. if (typeof text !== 'string') {
  4497. console.warn('Error(0xFA53): convertToIds', participant);
  4498. } else {
  4499. text = `${renderer.authorExternalChannelId || 'null'}|${text || ''}`;
  4500. if (text.length > 1) res = text;
  4501. }
  4502. return res;
  4503. // return renderer?`${renderer.id}|${renderer.authorExternalChannelId}`: '';
  4504. // note: renderer.id will be changed if the user typed something to trigger the update of the participants' record.
  4505. });
  4506. }
  4507.  
  4508. const checkChangeToParticipantRendererContent = CHECK_CHANGE_TO_PARTICIPANT_RENDERER_CONTENT ? (p1, p2) => {
  4509. // just update when content is changed.
  4510. if (p1.authorName !== p2.authorName) return true;
  4511. if (p1.authorPhoto !== p2.authorPhoto) return true;
  4512. if (p1.authorBadges !== p2.authorBadges) return true;
  4513. return false;
  4514. } : (p1, p2) => {
  4515. // keep integrity all the time.
  4516. return p1 !== p2; // always true
  4517. }
  4518.  
  4519. function notifyPath7081(path) { // cnt "yt-live-chat-participant-list-renderer"
  4520.  
  4521. if (PARTICIPANT_UPDATE_ONLY_ONLY_IF_MODIFICATION_DETECTED) {
  4522. if (path !== "participantsManager.participants") {
  4523. return this.__notifyPath5036__.apply(this, arguments);
  4524. }
  4525. if (c95dm === r95dm) return;
  4526. } else {
  4527. const stack = new Error().stack;
  4528. if (path !== "participantsManager.participants" || stack.indexOf('.onParticipantsChanged') < 0) {
  4529. return this.__notifyPath5036__.apply(this, arguments);
  4530. }
  4531. }
  4532.  
  4533. if (uvid > 1e8) uvid = uvid % 100;
  4534. let tid = ++uvid;
  4535.  
  4536.  
  4537. // const cnt = this; // "yt-live-chat-participant-list-renderer"
  4538.  
  4539. const wNode = mWeakRef(this);
  4540.  
  4541. mutexParticipants.lockWith(lockResolve => {
  4542.  
  4543. const cnt = kRef(wNode);
  4544.  
  4545. const participants00 = (((cnt || 0).participantsManager || 0).participants || 0);
  4546.  
  4547. if (tid !== uvid || !cnt || typeof (participants00 || 0).splice !== 'function') {
  4548. lockResolve();
  4549. return;
  4550. }
  4551.  
  4552. let doUpdate = false;
  4553.  
  4554. if (PARTICIPANT_UPDATE_ONLY_ONLY_IF_MODIFICATION_DETECTED) {
  4555.  
  4556. if (!participants00.r94dm) {
  4557. participants00.r94dm = 1;
  4558. r95dm = (r95dm & 1073741823) + 1;
  4559. participants00.push = function () {
  4560. r95dm = (r95dm & 1073741823) + 1;
  4561. return Array.prototype.push.apply(this, arguments);
  4562. }
  4563. participants00.pop = function () {
  4564. r95dm = (r95dm & 1073741823) + 1;
  4565. return Array.prototype.pop.apply(this, arguments);
  4566. }
  4567. participants00.shift = function () {
  4568. r95dm = (r95dm & 1073741823) + 1;
  4569. return Array.prototype.shift.apply(this, arguments);
  4570. }
  4571. participants00.unshift = function () {
  4572. r95dm = (r95dm & 1073741823) + 1;
  4573. return Array.prototype.unshift.apply(this, arguments);
  4574. }
  4575. participants00.splice = function () {
  4576. r95dm = (r95dm & 1073741823) + 1;
  4577. return Array.prototype.splice.apply(this, arguments);
  4578. }
  4579. participants00.sort = function () {
  4580. r95dm = (r95dm & 1073741823) + 1;
  4581. return Array.prototype.sort.apply(this, arguments);
  4582. }
  4583. participants00.reverse = function () {
  4584. r95dm = (r95dm & 1073741823) + 1;
  4585. return Array.prototype.reverse.apply(this, arguments);
  4586. }
  4587. }
  4588.  
  4589. if (c95dm !== r95dm) {
  4590. c95dm = r95dm;
  4591. doUpdate = true;
  4592. }
  4593.  
  4594. } else {
  4595. doUpdate = true;
  4596. }
  4597.  
  4598. if (!doUpdate) {
  4599. lockResolve();
  4600. return;
  4601. }
  4602.  
  4603. const participants = participants00.slice(0);
  4604. const beforeParticipants = beforeParticipantsMap.get(cnt) || [];
  4605. beforeParticipantsMap.set(cnt, participants);
  4606.  
  4607. const resPromise = (async () => {
  4608.  
  4609. if (beforeParticipants.length === 0) {
  4610. // not error
  4611. return 0;
  4612. }
  4613.  
  4614. let countOfElements = cnt.__getAllParticipantsDOMRenderedLength__()
  4615.  
  4616. // console.log(participants.length, doms.length) // different if no requestAnimationFrame
  4617. if (beforeParticipants.length !== countOfElements) {
  4618. // there is somewrong for the cache. - sometimes happen
  4619. return 0;
  4620. }
  4621.  
  4622. const idsBefore = convertToIds(beforeParticipants);
  4623. const idsAfter = convertToIds(participants);
  4624.  
  4625. let { indexSplices, contentUpdates } = spliceIndicesFunc(beforeParticipants, participants, idsBefore, idsAfter);
  4626.  
  4627. let res = 1; // default 1 for no update
  4628.  
  4629. if (indexSplices.length >= 1) {
  4630.  
  4631.  
  4632. // let p2 = participants.slice(indexSplices[0].index, indexSplices[0].index+indexSplices[0].addedCount);
  4633. // let p1 = indexSplices[0].removed;
  4634. // console.log(indexSplices.length, indexSplices ,p1,p2, convertToIds(p1),convertToIds(p2))
  4635.  
  4636. /* folllow
  4637. a.notifyPath(c + ".splices", d);
  4638. a.notifyPath(c + ".length", b.length);
  4639. */
  4640. // stampDomArraySplices_
  4641.  
  4642.  
  4643. await new Promise(resolve => {
  4644. cnt.resolveForDOMRendering781 = resolve;
  4645.  
  4646. cnt.__notifyPath5036__("participantsManager.participants.splices", {
  4647. indexSplices
  4648. });
  4649. indexSplices = null;
  4650. participantsForSpliceWR = null;
  4651. cnt.__notifyPath5036__("participantsManager.participants.length",
  4652. participants.length
  4653. );
  4654.  
  4655. });
  4656.  
  4657. // play safe for the change of 'length'
  4658. await nextBrowserTick_();
  4659.  
  4660. countOfElements = cnt.__getAllParticipantsDOMRenderedLength__();
  4661.  
  4662. const wrongSize = participants.length !== countOfElements
  4663. if (wrongSize) {
  4664. console.warn("ERROR(0xE2C3): notifyPath7081", beforeParticipants.length, participants.length, doms.length)
  4665. return 0;
  4666. }
  4667.  
  4668. res = 2 | 4;
  4669.  
  4670. } else {
  4671.  
  4672. indexSplices = null;
  4673. participantsForSpliceWR = null;
  4674.  
  4675. if (participants.length !== countOfElements) {
  4676. // other unhandled cases
  4677. return 0;
  4678. }
  4679.  
  4680. }
  4681.  
  4682. // participants.length === countOfElements before contentUpdates
  4683. if (contentUpdates.length >= 1) {
  4684. for (const contentUpdate of contentUpdates) {
  4685. let isChanged = checkChangeToParticipantRendererContent(beforeParticipants[contentUpdate.indexI], participants[contentUpdate.indexJ]);
  4686. if (isChanged) {
  4687. cnt.__notifyPath5036__(`participantsManager.participants[${contentUpdate.indexJ}]`);
  4688. res |= 4 | 8;
  4689. }
  4690. }
  4691. }
  4692. contentUpdates = null;
  4693.  
  4694. return res;
  4695.  
  4696.  
  4697. })();
  4698.  
  4699.  
  4700. resPromise.then(async (resValue) => {
  4701. const condition = resValue === 0 ? 1 : (resValue & 4) === 4 ? 2 : 0;
  4702. const isLogRequired = SHOW_PARTICIPANT_CHANGES_IN_CONSOLE && condition > 0;
  4703. isLogRequired && groupCollapsed("Participant List Change", `tid = ${tid}; res = ${resValue}`);
  4704. if (condition === 1) {
  4705. isLogRequired && console1.log("Full Refresh begins");
  4706. await new Promise(resolve => {
  4707. cnt.resolveForDOMRendering781 = resolve;
  4708. cnt.__notifyPath5036__("participantsManager.participants"); // full refresh
  4709. });
  4710. isLogRequired && console1.log("Full Refresh ends");
  4711. } else if (condition === 2) {
  4712. isLogRequired && console1.log(`Number of participants (before): ${beforeParticipants.length}`);
  4713. isLogRequired && console1.log(`Number of participants (after): ${participants.length}`);
  4714. isLogRequired && console1.log(`Total number of rendered participants: ${cnt.__getAllParticipantsDOMRenderedLength__()}`);
  4715. isLogRequired && console1.log(`Participant Renderer Content Updated: ${(resValue & 8) === 8}`);
  4716. // requestAnimationFrame is required to avoid particiant update during DOM changing (stampDomArraySplices_)
  4717. // mutex lock with requestAnimationFrame can also disable participants update in background
  4718. }
  4719. isLogRequired && groupEnd();
  4720. (condition === 2) && (await new Promise(requestAnimationFrame));
  4721. lockResolve();
  4722. });
  4723.  
  4724. });
  4725.  
  4726. }
  4727.  
  4728. return { notifyPath7081 };
  4729.  
  4730. })();
  4731.  
  4732. const whenDefinedMultiple = async (tags) => {
  4733.  
  4734. const sTags = [...new Set(tags)];
  4735. const len = sTags.length;
  4736.  
  4737. const pTags = new Array(len);
  4738. for (let i = 0; i < len; i++) {
  4739. pTags[i] = customElements.whenDefined(sTags[i]);
  4740. }
  4741.  
  4742. await Promise.all(pTags);
  4743. pTags.length = 0;
  4744.  
  4745. return sTags;
  4746.  
  4747. }
  4748.  
  4749. const onRegistryReadyForDataManipulation = () => {
  4750.  
  4751. function dummy5035(a, b, c) { }
  4752. function dummy411(a, b, c) { }
  4753.  
  4754.  
  4755.  
  4756. customElements.whenDefined("yt-live-chat-participant-list-renderer").then(() => {
  4757.  
  4758. if (!DO_PARTICIPANT_LIST_HACKS) return;
  4759.  
  4760. const tag = "yt-live-chat-participant-list-renderer";
  4761. const cProto = getProto(document.createElement(tag));
  4762. if (!cProto || typeof cProto.attached !== 'function') {
  4763. // for _registered, proto.attached shall exist when the element is defined.
  4764. // for controller extraction, attached shall exist when instance creates.
  4765. console.warn(`proto.attached for ${tag} is unavailable.`);
  4766. return;
  4767. }
  4768.  
  4769.  
  4770. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-participant-list-renderer hacks");
  4771.  
  4772. 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'];
  4773. const fgs = {};
  4774. for (const key of fgsArr) fgs[key] = undefined;
  4775.  
  4776. try {
  4777. const EXPERIMENT_FLAGS = ytcfg.data_.EXPERIMENT_FLAGS;
  4778. for (const key of fgsArr) fgs[key] = EXPERIMENT_FLAGS[key];
  4779. } catch (e) { }
  4780. console1.log(`EXPERIMENT_FLAGS: ${JSON.stringify(fgs, null, 2)}`);
  4781.  
  4782. const canDoReplacement = (() => {
  4783. if (typeof cProto.__notifyPath5035__ === 'function' && cProto.__notifyPath5035__.name !== 'dummy5035') {
  4784. console.warn('YouTube Live Chat Tamer is running.');
  4785. return;
  4786. }
  4787.  
  4788. if (typeof cProto.__attached411__ === 'function' && cProto.__attached411__.name !== 'dummy411') {
  4789. console.warn('YouTube Live Chat Tamer is running.');
  4790. return;
  4791. }
  4792.  
  4793. cProto.__notifyPath5035__ = dummy5035 // just to against Live Chat Tamer
  4794. cProto.__attached411__ = dummy411 // just to against Live Chat Tamer
  4795.  
  4796. if (typeof cProto.flushRenderStamperComponentBindings_ !== 'function' || cProto.flushRenderStamperComponentBindings_.length !== 0) {
  4797. console.warn("ERROR(0xE355): cProto.flushRenderStamperComponentBindings_ not found");
  4798. return;
  4799. }
  4800.  
  4801. if (typeof cProto.flushRenderStamperComponentBindings66_ === 'function') {
  4802. console.warn("ERROR(0xE356): cProto.flushRenderStamperComponentBindings66_");
  4803. return;
  4804. }
  4805.  
  4806. if (typeof cProto.__getAllParticipantsDOMRenderedLength__ === 'function') {
  4807. console.warn("ERROR(0xE357): cProto.__getAllParticipantsDOMRenderedLength__");
  4808. return;
  4809. }
  4810. return true;
  4811. })();
  4812.  
  4813. console1.log(`Data Manipulation Boost = ${canDoReplacement}`);
  4814.  
  4815. assertor(() => fnIntegrity(cProto.attached, '0.32.22')) // just warning
  4816. if (typeof cProto.flushRenderStamperComponentBindings_ === 'function') {
  4817. const fiRSCB = fnIntegrity(cProto.flushRenderStamperComponentBindings_);
  4818. console1.log(`flushRenderStamperComponentBindings_ ### ${fiRSCB} ###`);
  4819. } else {
  4820. console1.log("flushRenderStamperComponentBindings_ - not found");
  4821. }
  4822. // assertor(() => fnIntegrity(cProto.flushRenderStamperComponentBindings_, '0.386.233')) // just warning
  4823.  
  4824. if (typeof cProto.flushRenderStamperComponentBindings_ === 'function') {
  4825. cProto.flushRenderStamperComponentBindings66_ = cProto.flushRenderStamperComponentBindings_;
  4826. cProto.flushRenderStamperComponentBindings_ = function () {
  4827. // console.log('flushRenderStamperComponentBindings_')
  4828. this.flushRenderStamperComponentBindings66_();
  4829. if (this.resolveForDOMRendering781) {
  4830. this.resolveForDOMRendering781();
  4831. this.resolveForDOMRendering781 = null;
  4832. }
  4833. };
  4834. }
  4835.  
  4836. cProto.__getAllParticipantsDOMRenderedLength__ = function () {
  4837. const container = ((this || 0).$ || 0).participants;
  4838. if (!container) return 0;
  4839. return HTMLElement_.prototype.querySelectorAll.call(container, 'yt-live-chat-participant-renderer').length;
  4840. }
  4841.  
  4842. const onPageElements = [...document.querySelectorAll('yt-live-chat-participant-list-renderer:not(.n9fJ3)')];
  4843.  
  4844. cProto.__attached412__ = cProto.attached;
  4845. const fpPList = function (hostElement) {
  4846. const cnt = insp(hostElement);
  4847. if (beforeParticipantsMap.has(cnt)) return;
  4848. hostElement.classList.add('n9fJ3');
  4849.  
  4850. assertor(() => (cnt.__dataEnabled === true && cnt.__dataReady === true));
  4851. if (typeof cnt.notifyPath !== 'function' || typeof cnt.__notifyPath5036__ !== 'undefined') {
  4852. console.warn("ERROR(0xE318): yt-live-chat-participant-list-renderer")
  4853. return;
  4854. }
  4855.  
  4856. groupCollapsed("Participant List attached", "");
  4857. cnt.__notifyPath5036__ = cnt.notifyPath
  4858. const participants = ((cnt.participantsManager || 0).participants || 0);
  4859. assertor(() => (participants.length > -1 && typeof participants.slice === 'function'));
  4860. console1.log(`initial number of participants: ${participants.length}`);
  4861. const newParticipants = (participants.length >= 1 && typeof participants.slice === 'function') ? participants.slice(0) : [];
  4862. beforeParticipantsMap.set(cnt, newParticipants);
  4863. cnt.notifyPath = notifyPath7081;
  4864. console1.log(`CHECK_CHANGE_TO_PARTICIPANT_RENDERER_CONTENT = ${CHECK_CHANGE_TO_PARTICIPANT_RENDERER_CONTENT}`);
  4865. groupEnd();
  4866. }
  4867. cProto.attached = function () {
  4868. fpPList(this.hostElement || this);
  4869. this.__attached412__.apply(this, arguments);
  4870. };
  4871.  
  4872.  
  4873. if (ENABLE_FLAGS_MAINTAIN_STABLE_LIST_FOR_PARTICIPANTS_LIST) {
  4874.  
  4875. /** @type {boolean | (()=>boolean)} */
  4876. let toUseMaintainStableList = USE_MAINTAIN_STABLE_LIST_ONLY_WHEN_KS_FLAG_IS_SET ? (() => ytcfg.data_.EXPERIMENT_FLAGS.kevlar_should_maintain_stable_list === true) : true;
  4877. if (typeof cProto.stampDomArray_ === 'function' && cProto.stampDomArray_.length === 6 && !cProto.stampDomArray_.nIegT && !cProto.stampDomArray66_) {
  4878.  
  4879. let lastMessageDate = 0;
  4880. cProto.stampDomArray66_ = cProto.stampDomArray_;
  4881.  
  4882. cProto.stampDomArray_ = function (...args) {
  4883. if (args[0] && args[0].length > 0 && args[1] === "participants" && args[2] && args[3] === true && !args[5]) {
  4884. if (typeof toUseMaintainStableList === 'function') {
  4885. toUseMaintainStableList = toUseMaintainStableList();
  4886. }
  4887. args[5] = toUseMaintainStableList;
  4888. let currentDate = Date.now();
  4889. if (currentDate - lastMessageDate > 440) {
  4890. lastMessageDate = currentDate;
  4891. console.log('maintain_stable_list for participants list', toUseMaintainStableList);
  4892. }
  4893. }
  4894. return this.stampDomArray66_.apply(this, args);
  4895. }
  4896.  
  4897. cProto.stampDomArray_.nIegT = 1;
  4898.  
  4899. }
  4900. console1.log(`ENABLE_FLAGS_MAINTAIN_STABLE_LIST_FOR_PARTICIPANTS_LIST - OK`);
  4901. } else {
  4902. console1.log(`ENABLE_FLAGS_MAINTAIN_STABLE_LIST_FOR_PARTICIPANTS_LIST - NG`);
  4903. }
  4904.  
  4905. groupEnd();
  4906.  
  4907. if (onPageElements.length >= 1) {
  4908. for (const s of onPageElements) {
  4909. if (insp(s).isAttached === true) {
  4910. fpPList(s);
  4911. }
  4912. }
  4913. }
  4914.  
  4915. }).catch(console.warn);
  4916.  
  4917. };
  4918.  
  4919. if (DO_PARTICIPANT_LIST_HACKS) {
  4920. promiseForCustomYtElementsReady.then(onRegistryReadyForDataManipulation);
  4921. }
  4922.  
  4923.  
  4924.  
  4925. const rafHub = (ENABLE_RAF_HACK_TICKERS || ENABLE_RAF_HACK_DOCKED_MESSAGE || ENABLE_RAF_HACK_INPUT_RENDERER || ENABLE_RAF_HACK_EMOJI_PICKER) ? new RAFHub() : null;
  4926.  
  4927. const transitionEndHooks = new WeakSet();
  4928. const transitionEndAfterFnSimple = new WeakMap();
  4929. let transitionEndAfterFnSimpleEnable = 0;
  4930. // let prevTransitionClosing = null;
  4931.  
  4932. const passiveCapture = typeof IntersectionObserver === 'function' ? { capture: true, passive: true } : true;
  4933.  
  4934.  
  4935. const transitionEndAfterFn = (evt) => {
  4936. if (transitionEndAfterFnSimpleEnable > 0 && evt.propertyName && !evt.pseudoElement) {
  4937. const elm = evt.target;
  4938. const f = transitionEndAfterFnSimple.get(elm);
  4939. if (f) {
  4940. transitionEndAfterFnSimple.delete(elm);
  4941. f.resolve(evt.propertyName);
  4942. }
  4943. }
  4944. };
  4945.  
  4946. const fixChildrenIssue = !!fixChildrenIssue801;
  4947. if (fixChildrenIssue && typeof Object.getOwnPropertyDescriptor === 'function' && typeof Proxy !== 'undefined') {
  4948. let fixChildrenIssue_status = false;
  4949. const divProto = HTMLDivElement.prototype;
  4950. const polymerControllerSetData3 = function (c, d, e) {
  4951. return insp(this).set(c, d, e);
  4952. }
  4953. const polymerControllerSetData2 = function (c, d) {
  4954. return insp(this).set(c, d);
  4955. }
  4956. const dummyFn = function () {
  4957. console.log('dummyFn', ...arguments);
  4958. };
  4959.  
  4960. const wm44 = new Map();
  4961. function unPolymerSet(elem) {
  4962. const is = elem.is;
  4963. if (is && !elem.set) {
  4964. let rt = wm44.get(is);
  4965. if (!rt) {
  4966. rt = 1;
  4967. const cnt = insp(elem);
  4968. if (cnt !== elem && cnt && typeof cnt.set === 'function') {
  4969. const pcSet = cnt.constructor.prototype.set;
  4970. if (pcSet && typeof pcSet === 'function' && pcSet.length === 3) {
  4971. rt = polymerControllerSetData3;
  4972. } else if (pcSet && typeof pcSet === 'function' && pcSet.length === 2) {
  4973. rt = polymerControllerSetData2;
  4974. }
  4975. }
  4976. wm44.set(is, rt);
  4977. }
  4978. if (typeof rt === 'function') {
  4979. elem.set = rt;
  4980. } else {
  4981. elem.set = dummyFn;
  4982. }
  4983. }
  4984. }
  4985. if (!divProto.__children577__ && !divProto.__children578__) {
  4986.  
  4987. const dp = Object.getOwnPropertyDescriptor(Element.prototype, 'children');
  4988. const dp2 = Object.getOwnPropertyDescriptor(HTMLElement_.prototype, 'children');
  4989. const dp3 = Object.getOwnPropertyDescriptor(divProto, 'children');
  4990.  
  4991. if (dp && dp.configurable === true && dp.enumerable === true && typeof dp.get === 'function' && !dp2 && !dp3) {
  4992.  
  4993. if (divProto instanceof HTMLElement_ && divProto instanceof Element) {
  4994.  
  4995. let m = Object.assign({}, dp);
  4996. divProto.__children577__ = dp.get;
  4997. divProto.__children578__ = function () {
  4998. if (this.__children803__) return this.__children803__;
  4999. if (this.__children801__) {
  5000. let arr = [];
  5001. for (let elem = this.firstElementChild; elem !== null; elem = elem.nextElementSibling) {
  5002. if (elem.is) {
  5003. unPolymerSet(elem);
  5004. arr.push(elem);
  5005. }
  5006. }
  5007. if (this.__children801__ === 2) this.__children803__ = arr;
  5008. return arr;
  5009. }
  5010. return 577;
  5011. };
  5012. m.get = function () {
  5013. const r = this.__children578__();
  5014. if (r !== 577) return r;
  5015. return this.__children577__();
  5016. };
  5017. Object.defineProperty(divProto, 'children', m);
  5018.  
  5019. fixChildrenIssue_status = true;
  5020.  
  5021. }
  5022. }
  5023.  
  5024. }
  5025.  
  5026. if (!fixChildrenIssue_status) {
  5027. console.log('fixChildrenIssue - set NG')
  5028. }
  5029.  
  5030.  
  5031. }
  5032.  
  5033.  
  5034. const watchUserCSS = () => {
  5035.  
  5036. // if (!CSS.supports('contain-intrinsic-size', 'auto var(--wsr94)')) return;
  5037.  
  5038. const getElemFromWR = (nr) => {
  5039. const n = kRef(nr);
  5040. if (n && n.isConnected) return n;
  5041. return null;
  5042. }
  5043.  
  5044. const clearContentVisibilitySizing = () => {
  5045. Promise.resolve().then(() => {
  5046.  
  5047. const e = document.querySelector('#show-more[disabled]');
  5048. let btnShowMoreWR = e ? mWeakRef(e) : null;
  5049.  
  5050. let lastVisibleItemWR = null;
  5051. for (const elm of document.querySelectorAll('[wsr93]')) {
  5052. if (elm.getAttribute('wsr93') === 'visible') lastVisibleItemWR = mWeakRef(elm);
  5053. elm.setAttribute('wsr93', '');
  5054. // custom CSS property --wsr94 not working when attribute wsr93 removed
  5055. }
  5056. foregroundPromiseFn().then(() => {
  5057. const btnShowMore = getElemFromWR(btnShowMoreWR); btnShowMoreWR = null;
  5058. if (btnShowMore) btnShowMore.click();
  5059. else {
  5060. // would not work if switch it frequently
  5061. const lastVisibleItem = getElemFromWR(lastVisibleItemWR); lastVisibleItemWR = null;
  5062. if (lastVisibleItem) {
  5063.  
  5064. Promise.resolve()
  5065. .then(() => lastVisibleItem.scrollIntoView())
  5066. .then(() => lastVisibleItem.scrollIntoView(false))
  5067. .then(() => lastVisibleItem.scrollIntoView({ behavior: "instant", block: "end", inline: "nearest" }))
  5068. .catch(e => { }) // break the chain when method not callable
  5069.  
  5070. }
  5071. }
  5072. });
  5073.  
  5074. }).catch(console.warn);
  5075.  
  5076. }
  5077.  
  5078. const mutObserver = new MutationObserver((mutations) => {
  5079. for (const mutation of mutations) {
  5080. if ((mutation.addedNodes || 0).length >= 1) {
  5081. for (const addedNode of mutation.addedNodes) {
  5082. if (addedNode.nodeName === 'STYLE') {
  5083. clearContentVisibilitySizing();
  5084. return;
  5085. }
  5086. }
  5087. }
  5088. if ((mutation.removedNodes || 0).length >= 1) {
  5089. for (const removedNode of mutation.removedNodes) {
  5090. if (removedNode.nodeName === 'STYLE') {
  5091. clearContentVisibilitySizing();
  5092. return;
  5093. }
  5094. }
  5095. }
  5096. }
  5097. });
  5098.  
  5099. mutObserver.observe(document.documentElement, {
  5100. childList: true,
  5101. subtree: false
  5102. });
  5103. mutObserver.observe(document.head, {
  5104. childList: true,
  5105. subtree: false
  5106. });
  5107. mutObserver.observe(document.body, {
  5108. childList: true,
  5109. subtree: false
  5110. });
  5111.  
  5112. }
  5113.  
  5114.  
  5115. const { lcRendererElm, visObserver } = (() => {
  5116.  
  5117. let lcRendererWR = null;
  5118.  
  5119. const lcRendererElm = () => {
  5120. let lcRenderer = kRef(lcRendererWR);
  5121. if (!lcRenderer || !lcRenderer.isConnected) {
  5122. lcRenderer = document.querySelector('yt-live-chat-item-list-renderer.yt-live-chat-renderer');
  5123. lcRendererWR = lcRenderer ? mWeakRef(lcRenderer) : null;
  5124. }
  5125. return lcRenderer;
  5126. };
  5127.  
  5128.  
  5129. let hasFirstShowMore = false;
  5130. // let lastVisible = null;
  5131.  
  5132. const visObserverFn = (entry) => {
  5133.  
  5134. const target = entry.target;
  5135. if (!target || !target.hasAttribute('wsr93')) return;
  5136. // if(target.classList.contains('dont-render')) return;
  5137. let isVisible = entry.isIntersecting === true && entry.intersectionRatio > 0.5;
  5138. // const h = entry.boundingClientRect.height;
  5139. /*
  5140. if (h < 16) { // wrong: 8 (padding/margin); standard: 32; test: 16 or 20
  5141. // e.g. under fullscreen. the element created but not rendered.
  5142. target.setAttribute('wsr93', '');
  5143. return;
  5144. }
  5145. */
  5146. if (isVisible) {
  5147. // target.style.setProperty('--wsr94', h + 'px');
  5148. target.setAttribute('wsr93', 'visible');
  5149. // lastVisible = mWeakRef(target);
  5150. if (nNextElem(target) === null) {
  5151.  
  5152. // firstVisibleItemDetected = true;
  5153. /*
  5154. if (dateNow() - lastScroll < 80) {
  5155. lastLShow = 0;
  5156. lastScroll = 0;
  5157. Promise.resolve().then(clickShowMore);
  5158. } else {
  5159. lastLShow = dateNow();
  5160. }
  5161. */
  5162. // lastLShow = dateNow();
  5163. } else if (!hasFirstShowMore) { // should more than one item being visible
  5164. // implement inside visObserver to ensure there is sufficient delay
  5165. hasFirstShowMore = true;
  5166. // foregroundPromiseFn().then(() => {
  5167. // // foreground page
  5168. // // page visibly ready -> load the latest comments at initial loading
  5169. // const lcRenderer = lcRendererElm();
  5170. // if (lcRenderer) {
  5171. // nextBrowserTick_(() => {
  5172. // const cnt = insp(lcRenderer);
  5173. // if (cnt.isAttached === false || (cnt.hostElement || cnt).isConnected === false) return;
  5174. // cnt.scrollToBottom_();
  5175. // });
  5176. // }
  5177. // });
  5178. }
  5179. }
  5180. else if (target.getAttribute('wsr93') === 'visible') { // ignore target.getAttribute('wsr93') === '' to avoid wrong sizing
  5181.  
  5182. // target.style.setProperty('--wsr94', h + 'px');
  5183. target.setAttribute('wsr93', 'hidden');
  5184. } // note: might consider 0 < entry.intersectionRatio < 0.5 and target.getAttribute('wsr93') === '' <new last item>
  5185.  
  5186. }
  5187.  
  5188.  
  5189.  
  5190. const visObserver = new IntersectionObserver((entries) => {
  5191.  
  5192. for (const entry of entries) {
  5193.  
  5194. Promise.resolve(entry).then(visObserverFn);
  5195.  
  5196. }
  5197.  
  5198. }, {
  5199. rootMargin: "0px",
  5200. threshold: [0.05, 0.95],
  5201. });
  5202.  
  5203.  
  5204. return { lcRendererElm, visObserver }
  5205.  
  5206.  
  5207. })();
  5208.  
  5209. // let itemsResizeObserverAttached = false;
  5210. // const resizeObserverFallback = new IntersectionObserver((mutation, observer) => {
  5211. // const itemScroller = mutation[0].target;
  5212. // observer.unobserve(itemScroller);
  5213. // if (itemScroller.scrollTop === 0) itemScroller.scrollTop = window.screen.height; // scrollTop changing
  5214. // });
  5215.  
  5216. const itemScrollerResizeObserver = typeof ResizeObserver === 'function' && ENABLE_OVERFLOW_ANCHOR ? new ResizeObserver((mutations) => {
  5217. const mutation = mutations[mutations.length - 1];
  5218. // console.log('resizeObserver', mutation)
  5219. const itemScroller = (mutation || 0).target;
  5220. if (!itemScroller) return;
  5221. const listDom = itemScroller.closest('yt-live-chat-item-list-renderer');
  5222. if (!listDom) return;
  5223. const listCnt = insp(listDom);
  5224. if(listCnt.visibleItems.length === 0) return;
  5225. if (listCnt.atBottom !== true) return;
  5226. // if (itemScroller.scrollTop === 0) {
  5227. itemScroller.scrollTop = 16777216; // scrollTop changing
  5228. // }
  5229. }) : null;
  5230.  
  5231. const { setupMutObserver } = (() => {
  5232.  
  5233.  
  5234. const mutFn = (items) => {
  5235. let seqIndex = -1;
  5236. const elementSet = new Set();
  5237. elementSet.add = elementSet.addOriginal || elementSet.add;
  5238. for (let node = nLastElem(items); node !== null; node = nPrevElem(node)) { // from bottom
  5239. let found = node.hasAttribute('wsr93') ? (node.hasAttribute('yt-chat-item-seq') ? 2 : 1) : 0;
  5240. if (found === 1) node.removeAttribute('wsr93'); // reuse -> wsr93: hidden after re-attach
  5241. if (found === 2) {
  5242. seqIndex = parseInt(node.getAttribute('yt-chat-item-seq'), 10);
  5243. break;
  5244. }
  5245. visObserver.unobserve(node); // reuse case
  5246. node.setAttribute('wsr93', '');
  5247. visObserver.observe(node);
  5248. elementSet.add(node);
  5249. }
  5250. let iter = elementSet.values();
  5251. let i = seqIndex + elementSet.size;
  5252. for (let curr; curr = iter.next().value;) { // from bottom
  5253. curr.setAttribute('yt-chat-item-seq', i % 60);
  5254. curr.classList.add('yt-chat-item-' + ((i % 2) ? 'odd' : 'even'));
  5255. i--;
  5256. }
  5257. iter = null;
  5258. elementSet.clear();
  5259. }
  5260.  
  5261. // const itemsResizeObserver = typeof ResizeObserver === 'function' && 0 ? new ResizeObserver((mutations) => {
  5262. // const mutation = mutations[mutations.length - 1];
  5263. // // console.log('resizeObserver', mutation)
  5264. // const items = (mutation || 0).target;
  5265. // if (!items) return;
  5266. // const listDom = items.closest('yt-live-chat-item-list-renderer');
  5267. // if (!listDom) return;
  5268. // const listCnt = insp(listDom);
  5269. // if (listCnt.atBottom !== true) return;
  5270. // const itemScroller = listCnt.itemScroller || listCnt.$['item-scroller'] || listCnt.querySelector('#item-scroller') || 0;
  5271. // // if (itemScroller.scrollTop === 0) {
  5272. // itemScroller.scrollTop = mutation.contentRect.height; // scrollTop changing
  5273. // // }
  5274. // }) : null;
  5275. // itemsResizeObserverAttached = itemsResizeObserver !== null;
  5276.  
  5277. const mutObserver = new MutationObserver((mutations) => {
  5278. const items = (mutations[0] || 0).target;
  5279. if (!items) return;
  5280. mutFn(items);
  5281. });
  5282.  
  5283. const setupMutObserver = (items) => {
  5284. scrollChatFn = null;
  5285. mutObserver.disconnect();
  5286. mutObserver.takeRecords();
  5287. if (items) {
  5288. if (typeof items.__appendChild932__ === 'function') {
  5289. if (typeof items.appendChild === 'function') items.appendChild = items.__appendChild932__;
  5290. if (typeof items.__shady_native_appendChild === 'function') items.__shady_native_appendChild = items.__appendChild932__;
  5291. }
  5292. mutObserver.observe(items, {
  5293. childList: true,
  5294. subtree: false
  5295. });
  5296. mutFn(items);
  5297.  
  5298.  
  5299. // if (itemsResizeObserver) itemsResizeObserver.observe(items);
  5300.  
  5301. // const isFirstList = firstList;
  5302. // firstList = false;
  5303.  
  5304.  
  5305. if (items && items.nextElementSibling === null) {
  5306. items.parentNode.appendChild(dr(document.createElement('item-anchor')));
  5307. WITH_SCROLL_ANCHOR = true;
  5308. if (ENABLE_OVERFLOW_ANCHOR) {
  5309. items.classList.add('no-anchor');
  5310. nodeParent(items).classList.add('no-anchor'); // required
  5311. }
  5312. }
  5313.  
  5314.  
  5315.  
  5316.  
  5317. if (ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX) {
  5318.  
  5319. (() => {
  5320.  
  5321. const tag = 'yt-iframed-player-events-relay'
  5322. const dummy = document.createElement(tag);
  5323.  
  5324. const cProto = getProto(dummy);
  5325. if (!cProto || !cProto.handlePostMessage_) {
  5326. console.warn(`proto.handlePostMessage_ for ${tag} is unavailable.`);
  5327. return;
  5328. }
  5329.  
  5330. if (typeof cProto.handlePostMessage_ === 'function' && !cProto.handlePostMessage66_ && !cProto.handlePostMessage67_ ) {
  5331.  
  5332. cProto.handlePostMessage66_ = cProto.handlePostMessage_;
  5333.  
  5334. const handlePostMessageAfterPromiseA = (da) => {
  5335.  
  5336. if (!da || typeof da !== 'object') return;
  5337.  
  5338. if ('yt-player-state-change' in da) {
  5339.  
  5340. const qc = da['yt-player-state-change'];
  5341.  
  5342.  
  5343. let isQcChanged = false;
  5344.  
  5345. if (qc === 2) { isQcChanged = qc !== _playerState; _playerState = 2; relayCount = 0; } // paused
  5346. else if (qc === 3) { isQcChanged = qc !== _playerState; _playerState = 3; } // playing
  5347. else if (qc === 1) { isQcChanged = qc !== _playerState; _playerState = 1; } // playing
  5348.  
  5349.  
  5350. if ((isQcChanged) && playerState !== _playerState) {
  5351. playerEventsByIframeRelay = true;
  5352. onPlayStateChangePromise = new Promise((resolve) => {
  5353. const k = _playerState;
  5354. foregroundPromiseFn().then(() => {
  5355. if (k === _playerState && playerState !== _playerState) playerState = _playerState;
  5356. onPlayStateChangePromise = null;
  5357. resolve();
  5358. })
  5359. }).catch(console.warn);
  5360.  
  5361. }
  5362.  
  5363. } else if ('yt-player-video-progress' in da) {
  5364. const vp = da['yt-player-video-progress'];
  5365.  
  5366.  
  5367. relayCount++;
  5368. lastPlayerProgress = vp > 0 ? vp : 0; // no use ?
  5369.  
  5370.  
  5371. if (relayPromise && vp > 0 && relayCount >= 2) {
  5372. if (onPlayStateChangePromise) {
  5373. onPlayStateChangePromise.then(() => {
  5374. relayPromise && relayPromise.resolve();
  5375. relayPromise = null;
  5376. })
  5377. } else {
  5378. relayPromise.resolve();
  5379. relayPromise = null;
  5380. }
  5381. }
  5382.  
  5383. }
  5384.  
  5385. };
  5386.  
  5387. cProto.handlePostMessage67_ = function (a) {
  5388.  
  5389. let da = a.data;
  5390. const wNode = mWeakRef(this);
  5391. // const wData = mWeakRef(da);
  5392.  
  5393. playEventsStack = playEventsStack.then(() => {
  5394.  
  5395. const cnt = kRef(wNode);
  5396. // const da = kRef(wData);
  5397.  
  5398. if (!cnt || !a || !da) return;
  5399. handlePostMessageAfterPromiseA(da);
  5400. da = null;
  5401.  
  5402. const r = cnt.handlePostMessage66_(a);
  5403. a = null;
  5404.  
  5405. }).catch(console.warn);
  5406.  
  5407. }
  5408.  
  5409. const handlePostMessageAfterPromiseB = (da) => {
  5410.  
  5411. const lcr = document.querySelector('yt-live-chat-renderer');
  5412. const psc = document.querySelector("yt-player-seek-continuation");
  5413. if (lcr && psc && lcr.replayBuffer_) {
  5414.  
  5415. const rbProgress = lcr.replayBuffer_.lastVideoOffsetTimeMsec;
  5416. const daProgress = da['yt-player-video-progress'] * 1000
  5417. // document.querySelector('yt-live-chat-renderer').playerProgressChanged_(1e-5);
  5418.  
  5419. const front_ = (lcr.replayBuffer_.replayQueue || 0).front_;
  5420. const back_ = (lcr.replayBuffer_.replayQueue || 0).back_;
  5421.  
  5422. // console.log(deepCopy( front_))
  5423. // console.log(deepCopy( back_))
  5424. // console.log(rbProgress, daProgress, )
  5425. if (front_ && back_ && rbProgress > daProgress && back_.length > 2 && back_.some(e => e && +e.videoOffsetTimeMsec > daProgress) && back_.some(e => e && +e.videoOffsetTimeMsec < daProgress)) {
  5426. // no action
  5427. // console.log('ss1')
  5428. } else if (rbProgress < daProgress + 3400 && rbProgress > daProgress - 1200) {
  5429. // daProgress - 1200 < rbProgress < daProgress + 3400
  5430. // console.log('ss2')
  5431. } else {
  5432.  
  5433. lcr.previousProgressSec = 1E-5;
  5434. // lcr._setIsSeeking(!0),
  5435. lcr.replayBuffer_.clear()
  5436. psc.fireSeekContinuation_(da['yt-player-video-progress']);
  5437. }
  5438.  
  5439. }
  5440.  
  5441.  
  5442. };
  5443.  
  5444. cProto.handlePostMessage_ = function (a) {
  5445.  
  5446. let da = (a || 0).data || 0;
  5447. const wNode = mWeakRef(this);
  5448.  
  5449. if (typeof da !== 'object') return;
  5450.  
  5451. if (waitForInitialDataCompletion === 1) return;
  5452.  
  5453. if (!isPlayProgressTriggered) {
  5454. isPlayProgressTriggered = true; // set once
  5455.  
  5456. if ('yt-player-video-progress' in da) {
  5457. waitForInitialDataCompletion = 1;
  5458.  
  5459. const wrapWith = (data) => {
  5460. const { origin } = a;
  5461. return {
  5462. origin,
  5463. data
  5464. };
  5465. }
  5466.  
  5467. this.handlePostMessage67_(wrapWith({
  5468. "yt-iframed-parent-ready": true
  5469. }));
  5470.  
  5471.  
  5472. playEventsStack = playEventsStack.then(() => {
  5473.  
  5474. const cnt = kRef(wNode);
  5475.  
  5476. if (!cnt || !a || !da) return;
  5477.  
  5478. handlePostMessageAfterPromiseB(da);
  5479. da = null;
  5480.  
  5481. waitForInitialDataCompletion = 2;
  5482.  
  5483. const r = cnt.handlePostMessage_(a); // isPlayProgressTriggered is set
  5484. a = null;
  5485.  
  5486. }).catch(console.warn);
  5487.  
  5488. return;
  5489.  
  5490. }
  5491.  
  5492. }
  5493.  
  5494. this.handlePostMessage67_(a);
  5495.  
  5496. }
  5497.  
  5498. }
  5499.  
  5500.  
  5501. })();
  5502.  
  5503. }
  5504.  
  5505.  
  5506. }
  5507. }
  5508.  
  5509. return { setupMutObserver };
  5510.  
  5511.  
  5512.  
  5513. })();
  5514.  
  5515. const setupEvents = () => {
  5516. // not called when boost chat is enabled
  5517.  
  5518. // global - currentMouseDown, lastUserInteraction
  5519.  
  5520. let scrollCount = 0;
  5521. let lastScrollCount = -1;
  5522. let lastMouseDown = 0;
  5523.  
  5524. const passiveCapture = typeof IntersectionObserver === 'function' ? { capture: true, passive: true } : true;
  5525.  
  5526. // const delayFlushActiveItemsAfterUserActionK_ = () => {
  5527.  
  5528. // const lcRenderer = lcRendererElm();
  5529. // if (lcRenderer) {
  5530. // const cnt = insp(lcRenderer);
  5531. // if (!cnt.hasUserJustInteracted11_) return;
  5532. // if (cnt.atBottom && cnt.allowScroll && cnt.activeItems_.length >= 1 && cnt.hasUserJustInteracted11_()) {
  5533. // cnt.delayFlushActiveItemsAfterUserAction11_ && cnt.delayFlushActiveItemsAfterUserAction11_();
  5534. // }
  5535. // }
  5536.  
  5537. // }
  5538.  
  5539. const delayFlushActiveItemsAfterUserActionK_ = null;
  5540.  
  5541. document.addEventListener('scroll', (evt) => {
  5542. if (!evt || !evt.isTrusted) return;
  5543. // lastScroll = dateNow();
  5544. scrollCount = (scrollCount & 1073741823) + 1;
  5545. }, passiveCapture); // support contain => support passive
  5546.  
  5547. document.addEventListener('wheel', (evt) => {
  5548. if (!evt || !evt.isTrusted) return;
  5549. if (lastScrollCount === scrollCount) return;
  5550. lastScrollCount = scrollCount;
  5551. lastWheel = dateNow();
  5552. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5553. }, passiveCapture); // support contain => support passive
  5554.  
  5555. document.addEventListener('mousedown', (evt) => {
  5556. if (!evt || !evt.isTrusted) return;
  5557. if (((evt || 0).target || 0).id !== 'item-scroller') return;
  5558. lastMouseDown = dateNow();
  5559. currentMouseDown = true;
  5560. lastUserInteraction = lastMouseDown;
  5561. }, passiveCapture);
  5562.  
  5563. document.addEventListener('pointerdown', (evt) => {
  5564. if (!evt || !evt.isTrusted) return;
  5565. if (((evt || 0).target || 0).id !== 'item-scroller') return;
  5566. lastMouseDown = dateNow();
  5567. currentMouseDown = true;
  5568. lastUserInteraction = lastMouseDown;
  5569. }, passiveCapture);
  5570.  
  5571. document.addEventListener('click', (evt) => {
  5572. if (!evt || !evt.isTrusted) return;
  5573. if (((evt || 0).target || 0).id !== 'item-scroller') return;
  5574. lastMouseDown = lastMouseUp = dateNow();
  5575. currentMouseDown = false;
  5576. lastUserInteraction = lastMouseDown;
  5577. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5578. }, passiveCapture);
  5579.  
  5580. document.addEventListener('tap', (evt) => {
  5581. if (!evt || !evt.isTrusted) return;
  5582. if (((evt || 0).target || 0).id !== 'item-scroller') return;
  5583. lastMouseDown = lastMouseUp = dateNow();
  5584. currentMouseDown = false;
  5585. lastUserInteraction = lastMouseDown;
  5586. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5587. }, passiveCapture);
  5588.  
  5589.  
  5590. document.addEventListener('mouseup', (evt) => {
  5591. if (!evt || !evt.isTrusted) return;
  5592. if (currentMouseDown) {
  5593. lastMouseUp = dateNow();
  5594. currentMouseDown = false;
  5595. lastUserInteraction = lastMouseUp;
  5596. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5597. }
  5598. }, passiveCapture);
  5599.  
  5600.  
  5601. document.addEventListener('pointerup', (evt) => {
  5602. if (!evt || !evt.isTrusted) return;
  5603. if (currentMouseDown) {
  5604. lastMouseUp = dateNow();
  5605. currentMouseDown = false;
  5606. lastUserInteraction = lastMouseUp;
  5607. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5608. }
  5609. }, passiveCapture);
  5610.  
  5611. document.addEventListener('touchstart', (evt) => {
  5612. if (!evt || !evt.isTrusted) return;
  5613. lastTouchDown = dateNow();
  5614. currentTouchDown = true;
  5615. lastUserInteraction = lastTouchDown;
  5616. }, passiveCapture);
  5617.  
  5618. document.addEventListener('touchmove', (evt) => {
  5619. if (!evt || !evt.isTrusted) return;
  5620. lastTouchDown = dateNow();
  5621. currentTouchDown = true;
  5622. lastUserInteraction = lastTouchDown;
  5623. }, passiveCapture);
  5624.  
  5625. document.addEventListener('touchend', (evt) => {
  5626. if (!evt || !evt.isTrusted) return;
  5627. if (currentTouchDown) {
  5628. lastTouchUp = dateNow();
  5629. currentTouchDown = false;
  5630. lastUserInteraction = lastTouchUp;
  5631. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5632. }
  5633. }, passiveCapture);
  5634.  
  5635. document.addEventListener('touchcancel', (evt) => {
  5636. if (!evt || !evt.isTrusted) return;
  5637. if (currentTouchDown) {
  5638. lastTouchUp = dateNow();
  5639. currentTouchDown = false;
  5640. lastUserInteraction = lastTouchUp;
  5641. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5642. }
  5643. }, passiveCapture);
  5644.  
  5645.  
  5646. }
  5647.  
  5648. // const getTimestampUsec = (itemRenderer) => {
  5649. // if (itemRenderer && 'timestampUsec' in itemRenderer) {
  5650. // return itemRenderer.timestampUsec
  5651. // } else if (itemRenderer && itemRenderer.showItemEndpoint) {
  5652. // const messageRenderer = ((itemRenderer.showItemEndpoint.showLiveChatItemEndpoint || 0).renderer || 0);
  5653. // if (messageRenderer) {
  5654.  
  5655. // const messageRendererKey = firstObjectKey(messageRenderer);
  5656. // if (messageRendererKey && messageRenderer[messageRendererKey]) {
  5657. // const messageRendererData = messageRenderer[messageRendererKey];
  5658. // if (messageRendererData && 'timestampUsec' in messageRendererData) {
  5659. // return messageRendererData.timestampUsec
  5660. // }
  5661. // }
  5662. // }
  5663. // }
  5664. // return null;
  5665. // }
  5666.  
  5667. const onRegistryReadyForDOMOperations = () => {
  5668.  
  5669. let firstCheckedOnYtInit = false;
  5670.  
  5671. const assertorURL = () => assertor(() => location.pathname.startsWith('/live_chat') && (location.search.indexOf('continuation=') > 0 || location.search.indexOf('v=') > 0));
  5672.  
  5673. const mightFirstCheckOnYtInit = () => {
  5674. if (firstCheckedOnYtInit) return;
  5675. firstCheckedOnYtInit = true;
  5676.  
  5677. if (!document.body || !document.head) return;
  5678. if (!assertorURL()) return;
  5679.  
  5680. addCssManaged();
  5681.  
  5682. let efsContainer = document.getElementById('elzm-fonts-yk75g');
  5683. if (efsContainer && efsContainer.parentNode !== document.body) {
  5684. document.body.appendChild(efsContainer);
  5685. }
  5686.  
  5687. };
  5688.  
  5689. if (!assertorURL()) return;
  5690. // if (!assertor(() => document.getElementById('yt-masthead') === null)) return;
  5691.  
  5692.  
  5693. const { weakWrap } = (() => {
  5694.  
  5695.  
  5696. // const tickerFuncProps = new Set([
  5697. // 'animateShowStats', 'animateHideStats', // updateStatsBarAndMaybeShowAnimationRevised
  5698. // 'collapse', // slideDownNoSelfLeakage
  5699. // 'requestRemoval', // collapseNoSelfLeakage
  5700. // 'setContainerWidth', 'get', 'set', // deletedChangedNoSelfLeakage
  5701. // 'computeAriaLabel', //dataChanged
  5702. // 'startCountdown', // dataChanged [in case]
  5703. // ]);
  5704.  
  5705. // const tickerTags = new Set([
  5706. // "yt-live-chat-ticker-renderer",
  5707. // "yt-live-chat-ticker-paid-message-item-renderer",
  5708. // "yt-live-chat-ticker-paid-sticker-item-renderer",
  5709. // "yt-live-chat-ticker-sponsor-item-renderer"
  5710. // ]);
  5711.  
  5712. // const emptySet = new Set();
  5713.  
  5714.  
  5715.  
  5716. // const tickerFuncPropsFn = (cnt) => {
  5717.  
  5718. // const is = `${cnt.is}`;
  5719.  
  5720. // if (tickerTags.has(is)) {
  5721. // let flg = 0;
  5722. // if (cnt.get && cnt.set) flg |= 1;
  5723. // if (cnt.setContainerWidth && cnt.collapse && cnt.requestRemoval) flg |= 2;
  5724. // if (cnt.animateShowStats && cnt.animateHideStats) flg |= 4;
  5725. // if (cnt.startCountdown) flg |= 8;
  5726. // console.log(`DEBUG flag_6877 = ${flg}`, is);
  5727. // // DEBUG flag_6877 = 15 yt-live-chat-ticker-paid-message-item-renderer
  5728. // // DEBUG flag_6877 = 11 yt-live-chat-ticker-sponsor-item-renderer
  5729. // return tickerFuncProps;
  5730. // }
  5731.  
  5732. // return emptySet;
  5733.  
  5734.  
  5735. // }
  5736.  
  5737.  
  5738. // const smb = Symbol();
  5739. const vmb = 'dtz02' // Symbol(); // return kThis for thisArg
  5740. const vmc = 'dtz04' // Symbol(); // whether it is proxied fn
  5741. const vmd = 'dtz08' // Symbol(); // self fn proxy (fn--fn)
  5742.  
  5743.  
  5744.  
  5745.  
  5746. const thisConversionFn = (thisArg) => {
  5747. if (!thisArg) return null;
  5748. const kThis = thisArg[vmb];
  5749. if (kThis) {
  5750. const ref = kThis.ref;
  5751. return (ref ? kRef(ref) : null) || null;
  5752. }
  5753. return thisArg;
  5754. }
  5755.  
  5756. const pFnHandler2 = {
  5757. get(target, prop) {
  5758. if (prop === vmc) return target;
  5759. return Reflect.get(target, prop);
  5760. },
  5761. apply(target, thisArg, argumentsList) {
  5762. thisArg = thisConversionFn(thisArg);
  5763. if (thisArg) return Reflect.apply(target, thisArg, argumentsList);
  5764. }
  5765. }
  5766.  
  5767.  
  5768. const proxySelfHandler = {
  5769. get(target, prop) {
  5770. if(prop === vmb) return target;
  5771. const ref = target.ref;
  5772. const cnt = kRef(ref);
  5773. if (!cnt) return;
  5774. if (typeof cnt[prop] === 'function' && !cnt[prop][vmc] && !cnt[prop][vmb]) {
  5775. if (!cnt[prop][vmd]) cnt[prop][vmd] = new Proxy(cnt[prop], pFnHandler2);
  5776. return cnt[prop][vmd];
  5777. }
  5778. return cnt[prop];
  5779. },
  5780. set(target, prop, value) {
  5781. const cnt = kRef(target.ref);
  5782. if (!cnt) return true;
  5783. if(value && (value[vmc] || value[vmb])){
  5784. cnt[prop] = value[vmc] || thisConversionFn(value);
  5785. return true;
  5786. }
  5787. cnt[prop] = value;
  5788. return true;
  5789. }
  5790. };
  5791.  
  5792. const weakWrap = (thisArg) => {
  5793. thisArg = thisConversionFn(thisArg);
  5794. if (!thisArg) {
  5795. console.error('thisArg is not found');
  5796. return null;
  5797. }
  5798. return new Proxy({ ref: mWeakRef(thisArg) }, proxySelfHandler);
  5799. }
  5800.  
  5801.  
  5802.  
  5803.  
  5804.  
  5805.  
  5806. if (!window.getComputedStyle533 && typeof window.getComputedStyle === 'function') {
  5807. window.getComputedStyle533 = window.getComputedStyle;
  5808. window.getComputedStyle = function (a, ...args) {
  5809. a = thisConversionFn(a);
  5810. if (a) {
  5811. return getComputedStyle533(a, ...args);
  5812. }
  5813. return null;
  5814. }
  5815. }
  5816.  
  5817.  
  5818.  
  5819.  
  5820.  
  5821.  
  5822.  
  5823. // const fnProxySelf = function (...args) {
  5824. // const cnt = kRef(this.ref);
  5825. // if (cnt) {
  5826. // return cnt[this.prop](...args); // might throw error
  5827. // }
  5828. // }
  5829. // const proxySelfHandler = {
  5830. // get(target, prop) {
  5831. // const ref = target.ref;
  5832. // const cnt = kRef(ref);
  5833. // if (!cnt) return;
  5834. // if (prop === 'dtz06') return 1;
  5835. // if (typeof cnt[prop] === 'function') {
  5836. // if (!target.funcs.has(prop)) {
  5837. // console.warn(`proxy get to function | prop: ${prop} | is: ${cnt.is}`);
  5838. // }
  5839. // if (!target[`$$${prop}$$`]) target[`$$${prop}$$`] = fnProxySelf.bind({ prop, ref });
  5840. // return target[`$$${prop}$$`];
  5841. // }
  5842. // return cnt[prop];
  5843. // },
  5844. // set(target, prop, value) {
  5845. // const cnt = kRef(target.ref);
  5846. // if (!cnt) return true;
  5847. // if (typeof value === 'function') {
  5848. // console.warn(`proxy set to function | prop: ${prop} | is: ${cnt.is}`);
  5849. // cnt[prop] = value;
  5850. // return true;
  5851. // }
  5852. // cnt[prop] = value;
  5853. // return true;
  5854. // }
  5855. // };
  5856.  
  5857. // return { tickerFuncPropsFn, proxySelfHandler }
  5858.  
  5859. return {weakWrap}
  5860. })();
  5861.  
  5862.  
  5863.  
  5864. if (document.documentElement && document.head) {
  5865. addCssManaged();
  5866. }
  5867. // console.log(document.body===null)
  5868.  
  5869. const preprocessChatLiveActionsMap = new WeakSet();
  5870.  
  5871. const toLAObj=(aItem)=>{
  5872.  
  5873. if (!aItem || typeof aItem !== 'object') return false;
  5874. const key = firstObjectKey(aItem); // addLiveChatTickerItemAction
  5875. if (!key) return false;
  5876. let obj = aItem[key];
  5877. if (!obj || typeof obj !== 'object') return false;
  5878.  
  5879. if (typeof (obj.item || 0) == 'object' && firstObjectKey(obj) === 'item') {
  5880. obj = obj.item;
  5881. const key = firstObjectKey(obj);
  5882. if (key) {
  5883. obj = obj[key];
  5884. }
  5885. }
  5886.  
  5887. return obj;
  5888.  
  5889. };
  5890.  
  5891. const groupsK38=[];
  5892.  
  5893.  
  5894. function intervalsOverlap(a1, a2, b1, b2) {
  5895. // Order the intervals without using Math functions
  5896. var startA = a1 <= a2 ? a1 : a2;
  5897. var endA = a1 <= a2 ? a2 : a1;
  5898.  
  5899. var startB = b1 <= b2 ? b1 : b2;
  5900. var endB = b1 <= b2 ? b2 : b1;
  5901.  
  5902. // Check for overlap
  5903. return endA >= startB && endB >= startA;
  5904. }
  5905.  
  5906.  
  5907.  
  5908. const insertIntoSortedArrayA28 = (arr, val) => {
  5909. let left = 0;
  5910. const n = arr.length;
  5911. let right = n;
  5912.  
  5913. // Binary search to find the correct insertion index:
  5914. // We want the first index where arr[index][2] >= val[2].
  5915. while (left < right) {
  5916. const mid = (left + right) >>> 1;
  5917. if (arr[mid][0] < val[0]) {
  5918. left = mid + 1;
  5919. } else {
  5920. right = mid;
  5921. }
  5922. }
  5923.  
  5924. // 'left' is now the insertion index
  5925. left === n ? arr.push(val): arr.splice(left, 0, val);
  5926. };
  5927.  
  5928. function removeNullsInPlace(arr, startI = 0) {
  5929. let insertPos = startI;
  5930. for (let i = startI; i < arr.length; i++) {
  5931. if (arr[i] !== null) {
  5932. insertPos !== i && (arr[insertPos] = arr[i]);
  5933. insertPos++;
  5934. }
  5935. }
  5936. arr.length = insertPos; // Remove the trailing nulls.
  5937. }
  5938.  
  5939. let fir = 0;
  5940.  
  5941. const limitAddition = (a, b) => {
  5942. // Number.MAX_SAFE_INTEGER = 9007199254740991
  5943. // formula = Math.round((a + b) / (1 + a * b / k / k))
  5944. // avoid a*b > 9007199254740991
  5945. // say a, b <= 94800000
  5946. // Consider (x+x) - (x+x) / (1 + x^2 / k^2) < 0.49
  5947. // x < 130095
  5948.  
  5949. const w = 130095;
  5950. if (a < w && b < w) return a + b;
  5951. const k2 = 94800000 * 94800000;
  5952. return Math.round((a + b) / (1 + (a * b) / k2));
  5953. }
  5954.  
  5955. const preprocessChatLiveActions = (arr, ct_) =>{
  5956.  
  5957. if (!ct_) ct_ = Date.now();
  5958.  
  5959. if (!fir) {
  5960.  
  5961. if (!__LCRInjection__) {
  5962. console.error('[yt-chat] preprocessChatLiveActions might fail because of no __LCRInjection__');
  5963. }
  5964.  
  5965. DEBUG_preprocessChatLiveActions && console.log('[yt-chat-debug] 5990', 'preprocessChatLiveActions', arr)
  5966.  
  5967. DEBUG_preprocessChatLiveActions && console.log('[yt-chat-debug] 5991', document.querySelectorAll('yt-live-chat-ticker-renderer #ticker-items [class]').length)
  5968.  
  5969. fir = 1;
  5970. // debugger;
  5971. }
  5972.  
  5973. if (!arr || !arr.length) return arr;
  5974.  
  5975. if (preprocessChatLiveActionsMap.has(arr)) return arr;
  5976. preprocessChatLiveActionsMap.add(arr);
  5977.  
  5978.  
  5979.  
  5980. const ct = ct_;
  5981.  
  5982. let groups_ = null;
  5983.  
  5984. // console.log(1237005);
  5985. // const conversionMap = new WeakMap();
  5986.  
  5987. const additionalInfo = new WeakMap();
  5988.  
  5989. // const adjustmentMap = new Map();
  5990.  
  5991. if (FIX_TIMESTAMP_FOR_REPLAY) {
  5992.  
  5993. // console.log('group02331')
  5994. // console.time('FIX_TIMESTAMP_FOR_REPLAY')
  5995.  
  5996. // const stack = new Array(arr.length);
  5997. // let stackL = 0;
  5998.  
  5999. // const arrHash = new Array(arr.length);
  6000.  
  6001.  
  6002. const groups = groupsK38;
  6003. // const delta = 2.0; // head-to-tail + 0.5 + 0.5 = 1.0 -> symmetric -> 1.0 * 2 = 2.0
  6004. // (2)
  6005. // (1.5, 2.5)
  6006. // (1.51, 2.49)
  6007. // -> (1.01, 2.01) , (1.99, 2.99)
  6008. // 2.99 - 1.01 = 1.98 -> 2
  6009.  
  6010.  
  6011.  
  6012. const pushToGroup = (t0mu)=>{
  6013.  
  6014. const t0auDv = t0mu - 1e6; // t0buDv - t0auDv = 2e6
  6015. const t0buDv = t0mu + 1e6;
  6016. // const t0auEv = t0mu - 2e6;
  6017. // const t0buEv = t0mu + 2e6;
  6018.  
  6019. let groupK = false;
  6020. // let m = -1;
  6021. // let q= 0;
  6022. //const qq =true;
  6023. //qq && console.log('-------')
  6024.  
  6025. let lastRight = null;
  6026. let lastK = null;
  6027. let deletedStartIndex = -1;
  6028.  
  6029. for (let k = 0, kl = groups.length; k < kl; k++) {
  6030.  
  6031. const group = groups[k];
  6032. const [groupStart, groupEnd, gCount] = group;
  6033. //qq && console.log(`-- ${k} ----- ${groupMid} : [${groupStart},${groupEnd}] || C1 = ${t0buEv < groupMid} || C2 = ${t0auEv > groupMid}`);
  6034.  
  6035. // if (t0bsEv < groupMid) continue; // if(t0m + 1.0 < groupMid - 1.0) continue;
  6036. // if (m < 0) m = k;
  6037. // if (t0asEv > groupMid){
  6038. // continue; // if(t0m - 1.0 > groupMid + 1.0) break;
  6039. // }
  6040.  
  6041.  
  6042. // if (m < 0) m = k;
  6043.  
  6044. if (lastRight > groupStart) {
  6045. if (!groupK) {
  6046. // just in case sth wrong
  6047. console.warn('logic ERROR');
  6048. groups[k] = null;
  6049. if(deletedStartIndex < 0) deletedStartIndex = k;
  6050. break;
  6051. } else {
  6052.  
  6053.  
  6054. // GroupA: N_a' = N_a + n_e{1} ; Note n_e is the only way to shift right to cause " (lastRight > groupStart) "
  6055. // GroupB: N_b
  6056. // Merge Group (A) = N_a' + N_b
  6057.  
  6058. // without entry moditification, no overlap
  6059. // this must be due to entry moditifcation
  6060. // entry is already count. so can be skipped after merging
  6061.  
  6062. // for merging, groupA will move to right side but left than groupB, so no overlap to groupC
  6063.  
  6064. const group = groups[lastK];
  6065. const newN = limitAddition(group[2], gCount);
  6066.  
  6067. const factor = gCount / (group[2] + gCount);
  6068.  
  6069. // group[0] = (group[0] * group[2] + groupStart * gCount) / (group[2] + gCount)
  6070. group[0] += (groupStart - group[0]) * factor;
  6071.  
  6072. // group[1] = lastRight = (group[1] * group[2] + groupEnd * gCount) / (group[2] + gCount)
  6073. group[1] += (groupEnd - group[1]) * factor;
  6074.  
  6075. group[2] = newN;
  6076. // no change of lastK
  6077. groups[k] = null;
  6078. if(deletedStartIndex < 0) deletedStartIndex = k;
  6079. continue;
  6080. }
  6081. }
  6082.  
  6083. const minGroupStart = lastRight; // all groupStart, groupEnd >= minGroupStart for k, k+1, ...
  6084. if (t0buDv < minGroupStart) {
  6085. // no overlapping could be possible
  6086. break;
  6087. }
  6088.  
  6089. if (intervalsOverlap(t0auDv, t0buDv, groupStart, groupEnd)) {
  6090.  
  6091. groupK = true;
  6092.  
  6093. // if (t0auDv > groupStart) group[0] = t0auDv;
  6094. // else if (t0buDv < groupEnd) group[1] = t0buDv;
  6095.  
  6096. // const newStart = (groupStart * gCount + t0auDv) / (gCount + 1);
  6097. const newStart = groupStart + (t0auDv - groupStart) * 1 / (gCount + 1);
  6098.  
  6099. if (newStart < lastRight) {
  6100. // n_e{1} will make N_b shift left
  6101.  
  6102. // GroupA: N_a
  6103. // GroupB: N_b
  6104. // Merge Group (A) = N_a + N_b + n_e{1}
  6105.  
  6106. const group = groups[lastK];
  6107. const newN = limitAddition(limitAddition(group[2], gCount), 1);
  6108. const f1 = gCount / (group[2] + gCount + 1);
  6109. const f2 = 1 / (group[2] + gCount + 1);
  6110.  
  6111. // group[0] = (group[0] * group[2] + groupStart * gCount + t0auDv) / (group[2] + gCount + 1);
  6112. group[0] += (groupStart - group[0]) * f1 + (t0auDv - group[0]) * f2;
  6113.  
  6114. // group[1] = lastRight = (group[1] * group[2] + groupEnd * gCount + t0buDv) / (group[2] + gCount + 1)
  6115. lastRight = (group[1] += (groupEnd - group[1]) * f1 + (t0buDv - group[1]) * f2);
  6116.  
  6117. group[2] = newN;
  6118. // no change of lastK
  6119. groups[k] = null;
  6120. if(deletedStartIndex < 0) deletedStartIndex = k;
  6121. continue;
  6122.  
  6123. } else {
  6124. // n_e{1} will make N_b shift either left or right
  6125.  
  6126. // GroupT: N_t
  6127. // Group (T) = N_t + n_e{1}
  6128.  
  6129. const newN = limitAddition(gCount, 1);
  6130.  
  6131. group[0] = newStart;
  6132. // group[1] = lastRight = (groupEnd * gCount + t0buDv) / (gCount + 1);
  6133. group[1] = lastRight = groupEnd + (t0buDv - groupEnd) * 1 / (gCount + 1);
  6134. group[2] = newN;
  6135.  
  6136. lastK = k;
  6137.  
  6138. // (t0asDv > groupStart) && (t0bsDv < groupEnd) means full containement
  6139. // however, group size is smaller than or equal to t0width
  6140. }
  6141.  
  6142.  
  6143. } else {
  6144. // just update record for next iteration
  6145.  
  6146. lastRight = groupEnd;
  6147. lastK = k;
  6148. }
  6149.  
  6150.  
  6151.  
  6152. }
  6153.  
  6154. if (deletedStartIndex >= 0) {
  6155. // rarely used
  6156.  
  6157. removeNullsInPlace(groups, deletedStartIndex);
  6158.  
  6159. }
  6160. if (!groupK) {
  6161. // groups.push([t0auDv, t0buDv, 1]);
  6162. insertIntoSortedArrayA28(groups, [t0auDv, t0buDv, 1]);
  6163. // insertIntoSortedArrayA27(groups, [t0auDv, t0buDv, t0mu]);
  6164. }
  6165.  
  6166.  
  6167. }
  6168.  
  6169. let autoTimeStampFrameChoose = 0;
  6170.  
  6171. // console.log('group02332')
  6172. for (let j = 0, l = arr.length; j < l; j++) {
  6173. const aItem = arr[j];
  6174.  
  6175. const obj = toLAObj(aItem);
  6176. if (obj === false) continue;
  6177.  
  6178. let p = obj.timestampText;
  6179. let p2, p3=null, p4a=null, p4b=null;
  6180. if(p&&p.simpleText ) p2 = p.simpleText;
  6181.  
  6182. let q = obj.timestampUsec ;
  6183. let q2;
  6184.  
  6185. if(q && +q > 1110553200000000) q2 = +q;
  6186. if (q2 > 0 && !autoTimeStampFrameChoose) {
  6187. const q2cc = Math.round(q2 / 1e6);
  6188. autoTimeStampFrameChoose = q2cc - (q2cc % 10000000);
  6189. if (q2cc - autoTimeStampFrameChoose < 2000000) autoTimeStampFrameChoose -= 10000000;
  6190. // around 10day range
  6191. // exceeded ~10day -> above 10000000
  6192. }
  6193.  
  6194. // console.log('group02333', p2, q2)
  6195. // console.log(3775, q2/1e6, autoTimeStampFrameChoose)
  6196.  
  6197. if(p2 && q2){
  6198.  
  6199. let m;
  6200.  
  6201. if (m = /^\s*(-?)(\d+):(\d+)\s*$/.exec(p2)) {
  6202. let c0z = m[1] ? -1 : 1;
  6203. let c1 = (+m[2]);
  6204. let c2 = (+m[3]);
  6205. if (c0z > 0 && c1 >= 0 && c2 >= 0) {
  6206.  
  6207. p3 = c1 * 60 + c2;
  6208. } else if (c0z < 0 && c1 >= 0 && c2 >= 0) {
  6209. // -4:43 -> -4:42 -> -4:41 ... -> -4:01 -> -4:00 -> -3:59 -> -3:58
  6210. // -> ... -1:01 -> -1:00 -> -0:59 -> ... -> -0:02 -> -0:01 -> -0:00 -> 0:00 -> ...
  6211.  
  6212. p3 = (-c1 * 60) + (-c2);
  6213.  
  6214. }
  6215. if (p3 !== null) {
  6216. // 0:14 -> 13.5s ~ 14.4999s -> [13.5, 14.5)
  6217. p4a = p3 - 0.5;
  6218. p4b = p3 + 0.5;
  6219. }
  6220. } else if (m = /^\s*(-?)(\d+):(\d+):(\d+)\s*$/.exec(p2)) {
  6221.  
  6222. let c0z = m[1] ? -1 : 1;
  6223. let c1 = (+m[2]);
  6224. let c2 = (+m[3]);
  6225. let c3 = (+m[4]);
  6226.  
  6227.  
  6228.  
  6229. if (c0z > 0 && c1 >= 0 && c2 >= 0 && c3 >= 0) {
  6230.  
  6231. p3 = c1 * 60 * 60 + c2 * 60 + c3;
  6232. } else if (c0z < 0 && c1 >= 0 && c2 >= 0 && c3>=0) {
  6233. // -4:43 -> -4:42 -> -4:41 ... -> -4:01 -> -4:00 -> -3:59 -> -3:58
  6234. // -> ... -1:01 -> -1:00 -> -0:59 -> ... -> -0:02 -> -0:01 -> -0:00 -> 0:00 -> ...
  6235.  
  6236. p3 = (-c1 * 60 * 60) + (-c2 * 60) + (-c3);
  6237.  
  6238. }
  6239. if (p3 !== null) {
  6240. // 0:14 -> 13.5s ~ 14.4999s -> [13.5, 14.5)
  6241. p4a = p3 - 0.5;
  6242. p4b = p3 + 0.5;
  6243. }
  6244.  
  6245.  
  6246. }
  6247.  
  6248. }
  6249.  
  6250. if(p4a !== null && p4b !== null && q2 > 0){
  6251.  
  6252. // q2_us = t0_us + dt_us
  6253. // p4a_us <= dt_us < p4b_us
  6254. let p4au = p4a * 1e6;
  6255. let p4bu = p4b * 1e6;
  6256.  
  6257. // p4a_us <= q2_us - t0_us < p4b_us
  6258.  
  6259.  
  6260. // p4a_us - q2_us <= - t0_us < p4b_us - q2_us
  6261.  
  6262. // -p4a_us + q2_us >= t0_us > -p4b_us + q2_us
  6263.  
  6264.  
  6265. let t0au = q2 - p4bu; // q2_us - p4b_us
  6266. let t0bu = q2 - p4au; // q2_us - p4a_us
  6267.  
  6268. // t0 (t0au, t0bu]
  6269.  
  6270. const t0mu = (t0au+t0bu)/2;
  6271.  
  6272. // stack[stackL++]=({
  6273. // id: obj.id,
  6274. // idx: j,
  6275. // p2,
  6276. // // q2s : (q2/ 1e6 - autoTimeStampFrameChoose).toFixed(2),
  6277. // p3,
  6278. // /*
  6279. // timestampText: obj.timestampText,
  6280. // timestampUsec: obj.timestampUsec, // us = 1/1000 ms
  6281. // q2,
  6282. // p4a,
  6283. // p4b,
  6284. // */
  6285. // q2s: +(q2 / 1e6 - autoTimeStampFrameChoose).toFixed(2),
  6286. // t0as: +(t0au / 1e6 - autoTimeStampFrameChoose).toFixed(2),
  6287. // t0bs: +(t0bu /1e6 - autoTimeStampFrameChoose).toFixed(2),
  6288.  
  6289. // t0au,
  6290. // t0bu,
  6291. // t0mu
  6292. // });
  6293.  
  6294. // console.log('group02334')
  6295. let wobj = additionalInfo.get(obj);
  6296. if(!wobj) additionalInfo.set(obj, wobj = {});
  6297.  
  6298. wobj.timestampUsecOriginal = q2;
  6299. // wobj.timestampUsecAdjusted = q2;
  6300. wobj.t0au = t0au;
  6301. wobj.t0bu = t0bu;
  6302. wobj.t0mu = t0mu;
  6303.  
  6304. // arrHash[j] = {
  6305. // index: j,
  6306. // id: obj.id,
  6307. // timestampUsec: q2,
  6308. // t0au,
  6309. // t0bu,
  6310. // t0mu
  6311. // };
  6312.  
  6313. pushToGroup(t0mu);
  6314.  
  6315. // console.log('group02335')
  6316. // console.log('grouping', `${obj.id}.${obj.timestampUsec}`);
  6317.  
  6318. // timestamp (q2) can be incorrect.
  6319.  
  6320. // https://www.youtube.com/watch?v=IKKar5SS29E
  6321. // ChwKGkNQZUxfXzZxLS04Q0ZXNGxyUVlkODZrQzNR
  6322.  
  6323. /*
  6324.  
  6325.  
  6326. [
  6327. {
  6328. "id": "ChwKGkNNWHZqXy1xLS04Q0ZXNGxyUVlkODZrQzNR",
  6329. "p2": "2:04",
  6330. "p3": 124,
  6331. "t0as": 8320733.78,
  6332. "t0bs": 8320734.78
  6333. },
  6334. {
  6335. "id": "ChwKGkNQZUxfXzZxLS04Q0ZXNGxyUVlkODZrQzNR",
  6336. "p2": "2:04",
  6337. "p3": 124,
  6338. "t0as": 8320898.89, // incorrect
  6339. "t0bs": 8320899.89
  6340. }
  6341. ]
  6342.  
  6343.  
  6344. */
  6345.  
  6346. }
  6347.  
  6348.  
  6349.  
  6350.  
  6351. }
  6352.  
  6353. // stack.length = stackL;
  6354.  
  6355.  
  6356. groups_ = groups;
  6357. // console.log('groups', groups)
  6358.  
  6359. }
  6360.  
  6361. // console.log(1237006);
  6362.  
  6363. // console.log(5592,1)
  6364. const groupMids = FIX_TIMESTAMP_FOR_REPLAY ? groups_.map(group=>{
  6365.  
  6366. const [groupStart, groupEnd ] = group;
  6367. const groupMid = (groupStart+groupEnd)/2;
  6368. return groupMid;
  6369. }): null;
  6370. // console.log('groupMids', groupMids)
  6371.  
  6372.  
  6373. // console.log(1237007);
  6374.  
  6375. const adjustTimestampFn = (obj) => {
  6376.  
  6377. const groupCount = groupMids.length;
  6378.  
  6379. if (groupCount < 1) return null;
  6380.  
  6381. // const obj = toLAObj(aItem);
  6382. if (obj === false) return null;
  6383.  
  6384. const wobj = additionalInfo.get(obj);
  6385. if (!wobj) return null;
  6386.  
  6387. const { t0mu } = wobj;
  6388.  
  6389.  
  6390. let i0 = 0;
  6391.  
  6392. if (groupCount >= 3) {
  6393. // For larger arrays, use binary search.
  6394. let low = 0;
  6395. let high = groupCount - 1;
  6396.  
  6397. while (high - low > 1) {
  6398. const mid = (low + high) >>> 1;
  6399. if (groupMids[mid] >= t0mu) {
  6400. high = mid;
  6401. } else {
  6402. low = mid;
  6403. }
  6404. }
  6405. i0 = low;
  6406.  
  6407. }
  6408.  
  6409. let upperDiff = -1;
  6410. let lowerDiff = -1;
  6411. for (let i = i0; i < groupCount; i++) {
  6412. const y = groupMids[i] - t0mu;
  6413. if (y >= 0) {
  6414. upperDiff = y; // >=0, entry > value is found
  6415. break;
  6416. }
  6417. lowerDiff = -y; // >0, cache
  6418. }
  6419.  
  6420.  
  6421. const d1 = upperDiff;
  6422. const d2 = lowerDiff;
  6423.  
  6424.  
  6425. // console.log(5381, index1 ,d1, index2 , d2);
  6426.  
  6427. if (d1 >= 0 && ((d2 < 0) || (d1 <= d2))) {
  6428. wobj.chosenT0 = t0mu + d1; // groupMids[index1];
  6429. } else if (d2 >= 0 && ((d1 < 0) || (d2 <= d1))) {
  6430. wobj.chosenT0 = t0mu - d2; // groupMids[index2];
  6431. } else {
  6432. console.warn('logic error');
  6433. return null;
  6434. }
  6435.  
  6436. const adjusted = wobj.timestampUsecOriginal - wobj.chosenT0;
  6437.  
  6438. wobj.timestampUsecAdjusted = adjusted + 1110553200000000;
  6439.  
  6440. // console.log('adjusted', `${obj.id}.${obj.timestampUsec}`, wobj.timestampUsecOriginal - wobj.chosenT0);
  6441.  
  6442. // adjustmentMap.set(`${obj.id}.${obj.timestampUsec}`, wobj.timestampUsecOriginal - wobj.chosenT0);
  6443.  
  6444. return adjusted;
  6445.  
  6446.  
  6447.  
  6448. };
  6449.  
  6450.  
  6451. // console.log(5592,2)
  6452. // console.log(1237008);
  6453. // if (FIX_TIMESTAMP_FOR_REPLAY) {
  6454.  
  6455.  
  6456. // try{
  6457.  
  6458. // // console.log('groupmid',groupMids, groups);
  6459.  
  6460. // for(let j = 0; j< arr.length;j++){
  6461. // if(groupMids.length<1) break;
  6462.  
  6463. // const aItem = arr[j];
  6464. // const obj = toLAObj(aItem);
  6465. // if (obj === false) continue;
  6466.  
  6467. // const wobj = additionalInfo.get(obj);
  6468. // if(!wobj) continue;
  6469.  
  6470. // // wobj.timestampUsecOriginal = q2;
  6471. // // wobj.timestampUsecAdjusted = q2;
  6472. // // wobj.t0au = t0au;
  6473. // // wobj.t0bu = t0bu;
  6474. // // wobj.t0mu = t0mu;
  6475.  
  6476. // const {t0au, t0bu, t0mu} = wobj;
  6477.  
  6478. // let upper = -1;
  6479.  
  6480. // for(let i = 0; i <groupMids.length;i++){
  6481. // const groupMid = groupMids[i];
  6482. // if(groupMid>= t0mu){
  6483. // upper = i;
  6484. // break;
  6485. // }
  6486. // }
  6487. // let index1, index2;
  6488. // if(upper>-1){
  6489. // index1 = upper-1;
  6490. // index2 = upper;
  6491. // }else{
  6492. // index1 = groups.length-1;
  6493. // index2 = -1;
  6494. // }
  6495. // let d1 = null;
  6496. // if(index1 >=0){
  6497. // d1 = Math.abs(groupMids[index1] - t0mu);
  6498. // }
  6499.  
  6500. // let d2 = null;
  6501. // if(index2 >=0){
  6502. // d2 = Math.abs(groupMids[index2] - t0mu);
  6503. // }
  6504. // // console.log(5381, index1 ,d1, index2 , d2);
  6505. // if(d1 >= 0 && ((d1 <= d2) || (d2 === null)) ){
  6506.  
  6507. // wobj.chosenT0 = groupMids[index1];
  6508. // } else if(d2 >= 0 && ((d2 <= d1) || (d1 === null))){
  6509. // wobj.chosenT0 = groupMids[index2];
  6510. // } else {
  6511. // console.warn('logic error');
  6512. // continue;
  6513. // }
  6514.  
  6515. // wobj.timestampUsecAdjusted = wobj.timestampUsecOriginal - wobj.chosenT0 + 1110553200000000;
  6516.  
  6517. // console.log('adjusted', `${obj.id}.${obj.timestampUsec}`, wobj.timestampUsecOriginal - wobj.chosenT0);
  6518.  
  6519. // adjustmentMap.set(`${obj.id}.${obj.timestampUsec}`, wobj.timestampUsecOriginal - wobj.chosenT0);
  6520. // // conversionMap.set(obj, arrHash[j].adjustedTime);
  6521.  
  6522. // // console.log(5382, index, id, t0mu, arrHash[j].adjustedT0, arrHash[j].timestampUsec, arrHash[j].adjustedTime);
  6523.  
  6524. // }
  6525.  
  6526.  
  6527. // }catch(e){
  6528. // console.warn(e);
  6529. // }
  6530.  
  6531.  
  6532.  
  6533.  
  6534.  
  6535. // // if(stack.length > 1){
  6536. // // stack.sort((a,b)=>{
  6537. // // return a.t0mu - b.t0mu
  6538. // // });
  6539. // // // small to large
  6540. // // // console.log(34588, stack.map(e=>e.t0as))
  6541. // // }
  6542.  
  6543. // // grouping
  6544.  
  6545.  
  6546.  
  6547.  
  6548. // // if (stack.length > 0) {
  6549.  
  6550. // // try {
  6551.  
  6552. // // for (let j = 0, l = stack.length; j < l; j++) {
  6553. // // pushToGroup(stack[j].t0mu);
  6554.  
  6555. // // }
  6556.  
  6557. // // }catch(e){
  6558.  
  6559. // // console.warn(e)
  6560. // // }
  6561.  
  6562. // // // console.log(4882, groups.map(e=>e.slice()), stack.slice())
  6563.  
  6564. // // }
  6565.  
  6566.  
  6567.  
  6568.  
  6569. // // console.log(376, 'group', groups);
  6570.  
  6571.  
  6572. // // consolidated group
  6573. // // const consolidatedGroups = doConsolidation(groups);
  6574.  
  6575.  
  6576.  
  6577.  
  6578.  
  6579.  
  6580. // // if(stack.length > 1){
  6581.  
  6582.  
  6583. // // // // console.log(341, 'consolidatedGroups', consolidatedGroups ,groups.map(e=>{
  6584. // // // // return e.map(noTransform);
  6585. // // // // // return e.map(prettyNum);
  6586. // // // // }))
  6587.  
  6588.  
  6589. // // // console.log(344, 'groups', groups.map(e=>{
  6590. // // // return e.map(noTransform);
  6591. // // // // return e.map(prettyNum);
  6592. // // // }))
  6593.  
  6594. // // // // for(const s of stack){
  6595. // // // // for(const g of consolidatedGroups){
  6596. // // // // if(s.t0as<=g.cen && s.t0bs >=g.cen ){
  6597. // // // // s.cen = g.cen;
  6598. // // // // break;
  6599. // // // // }
  6600. // // // // }
  6601.  
  6602. // // // // }
  6603.  
  6604. // // // console.log(377, stack) // Ms
  6605.  
  6606. // // }
  6607.  
  6608.  
  6609. // // console.timeEnd('FIX_TIMESTAMP_FOR_REPLAY')
  6610.  
  6611. // }
  6612.  
  6613.  
  6614.  
  6615.  
  6616.  
  6617.  
  6618.  
  6619.  
  6620.  
  6621. // console.log(5592,5)
  6622.  
  6623.  
  6624. // console.log('preprocessChatLiveActions', arr)
  6625.  
  6626.  
  6627. const mapper = new Map();
  6628. mapper.set = mapper.setOriginal || mapper.set;
  6629.  
  6630. // without delaying. get the time of request
  6631. // (both streaming and replay, but replay relys on progress update so background operation is suppressed)
  6632.  
  6633. for (let j = 0, l = arr.length; j < l; j++) {
  6634. const aItem = arr[j];
  6635.  
  6636. const obj = toLAObj(aItem);
  6637. if(obj === false) continue;
  6638.  
  6639. if (obj.id && !obj.__timestampActionRequest__) {
  6640. // for all item entries
  6641. obj.__timestampActionRequest__ = ct;
  6642. }
  6643.  
  6644. if (obj.id && obj.__timestampActionRequest__ > 0 && obj.durationSec > 0 && obj.fullDurationSec) {
  6645.  
  6646. // console.log(948700, obj , obj.id, (obj.fullDurationSec - obj.durationSec) * 1000)
  6647. const m = obj.__timestampActionRequest__ - (obj.fullDurationSec - obj.durationSec) * 1000;
  6648.  
  6649. // obj.__t374__ = (obj.fullDurationSec - obj.durationSec) * 1000;
  6650. // obj.__t375__ = obj.__timestampActionRequest__ - (obj.fullDurationSec - obj.durationSec) * 1000;
  6651. // console.log(5993, obj)
  6652. // obj.__orderTime__ = m;
  6653. mapper.set(aItem, m);
  6654.  
  6655.  
  6656. }
  6657.  
  6658. }
  6659.  
  6660. if (mapper.size > 1) {
  6661.  
  6662. const idxices = [];
  6663.  
  6664. // sort ticker
  6665. let mArr1 = arr.filter((aItem,idx) => {
  6666.  
  6667. if (mapper.has(aItem)) {
  6668. idxices.push(idx);
  6669. return true;
  6670. }
  6671. return false;
  6672.  
  6673. });
  6674.  
  6675.  
  6676. let mArr2 = mArr1/*.slice(0)*/.sort((a, b) => {
  6677. return mapper.get(a) - mapper.get(b);
  6678. // low index = oldest = smallest timestamp
  6679. });
  6680.  
  6681.  
  6682.  
  6683. // console.log(948701, arr.slice(0));
  6684. for(let j = 0, l=mArr1.length;j <l;j++){
  6685.  
  6686. const idx = idxices[j];
  6687. // arr[idx] = mArr1[j]
  6688. arr[idx] = mArr2[j];
  6689.  
  6690. // const obj1 = toObj(mArr1[j]);
  6691. // const obj2 = toObj(mArr2[j]);
  6692.  
  6693. // console.log(948705, idx, obj1 , obj1.id, (obj1.fullDurationSec - obj1.durationSec) * 1000, obj1.__orderTime__)
  6694.  
  6695. // console.log(948706, idx, obj2 , obj2.id, (obj2.fullDurationSec - obj2.durationSec) * 1000, obj2.__orderTime__)
  6696.  
  6697. }
  6698.  
  6699. // console.log(5994,arr)
  6700.  
  6701. // console.log(948702, arr.slice(0));
  6702. // console.log(948701, arr);
  6703. // arr = arr.map(aItem => {
  6704. // const idx = mArr1.indexOf(aItem);
  6705. // if (idx < 0) return aItem;
  6706. // return mArr2[idx];
  6707. // });
  6708. // console.log(948702, arr);
  6709.  
  6710. // mostly in order, but some not in order
  6711.  
  6712.  
  6713. // eg
  6714.  
  6715. /*
  6716.  
  6717.  
  6718. 948711 68 '1734488590715474'
  6719. 948711 69 '1734488590909853'
  6720. 948711 70 '1734488594763719'
  6721. 948711 71 '1734488602334615' <
  6722. 948711 72 '1734488602267214' <
  6723. 948711 73 '1734488602751771'
  6724. */
  6725.  
  6726. // arr.filter(aItem=>{
  6727.  
  6728. // const p = toObj(aItem);
  6729. // if(p.timestampUsec) return true;
  6730.  
  6731. // }).forEach((aItem,idx)=>{
  6732.  
  6733. // const p = toObj(aItem);
  6734. // console.log(948711, idx, p.timestampUsec);
  6735. // })
  6736.  
  6737. // return arr;
  6738.  
  6739. }
  6740.  
  6741. // console.log(1237001);
  6742.  
  6743. {
  6744.  
  6745. const mapper = new Map();
  6746. mapper.set = mapper.setOriginal || mapper.set;
  6747.  
  6748. const idxices = [];
  6749.  
  6750. let mArr1 = arr.filter((aItem,idx) => {
  6751.  
  6752. const obj = toLAObj(aItem);
  6753. if (!obj) return false;
  6754.  
  6755. const baseText = obj.timestampText;
  6756. const baseTime = +obj.timestampUsec;
  6757. if (!baseTime || !baseText) return false;
  6758. // const timestampUsec = +toLAObj(aItem).timestampUsec; // +false.x = NaN
  6759. // const timestampUsec = +toLAObj(aItem).adjustedTime;
  6760.  
  6761. let timestampUsec;
  6762.  
  6763. // console.log(1237002)
  6764. if (FIX_TIMESTAMP_FOR_REPLAY) {
  6765.  
  6766. // const adjustmentTime = adjustmentMap.get(`${obj.id}.${obj.timestampUsec}`);
  6767.  
  6768. // // const wobj = additionalInfo.get(obj);
  6769.  
  6770. // // if(!wobj){
  6771. // // console.warn('FIX_TIMESTAMP_FOR_REPLAY - no wobj', obj)
  6772. // // return false;
  6773. // // }
  6774.  
  6775. // // timestampUsec = +wobj.timestampUsecAdjusted;
  6776. // if (!Number.isFinite(adjustmentTime)) {
  6777. // console.warn(`FIX_TIMESTAMP_FOR_REPLAY - no adjustmentTime for ${obj.id}.${obj.timestampUsec}`, obj, [...adjustmentMap])
  6778. // return false;
  6779. // }
  6780. // timestampUsec = adjustmentTime;
  6781.  
  6782.  
  6783. const adjustmentTime = adjustTimestampFn(obj);
  6784.  
  6785. if (!Number.isFinite(adjustmentTime)) {
  6786.  
  6787. console.warn(`FIX_TIMESTAMP_FOR_REPLAY - no adjustmentTime for ${obj.id}.${obj.timestampUsec}`, obj);
  6788. return false;
  6789. }
  6790. timestampUsec = adjustmentTime;
  6791.  
  6792.  
  6793. } else {
  6794.  
  6795. if (!Number.isFinite(baseTime)) {
  6796. console.warn(`no baseTime for ${obj.id}.${obj.timestampUsec}`, obj);
  6797.  
  6798. return false;
  6799. }
  6800. timestampUsec = baseTime;
  6801.  
  6802. }
  6803.  
  6804. // if(timestampUsec > 0){
  6805. idxices.push(idx);
  6806. mapper.set(aItem, timestampUsec)
  6807. return true;
  6808. // }
  6809. // return false;
  6810.  
  6811. });
  6812.  
  6813. if(mapper.size > 1){
  6814.  
  6815.  
  6816. // console.log(1237004)
  6817. let mArr2 = mArr1/*.slice(0)*/.sort((a, b) => {
  6818. return mapper.get(a) - mapper.get(b);
  6819. // low index = oldest = smallest timestamp
  6820. });
  6821.  
  6822.  
  6823.  
  6824. // console.log(948701, arr.slice(0));
  6825. for(let j = 0, l=mArr1.length;j <l;j++){
  6826.  
  6827. const idx = idxices[j];
  6828. arr[idx] = mArr2[j];
  6829.  
  6830. // const obj1 = toObj(mArr1[j]);
  6831. // const obj2 = toObj(mArr2[j]);
  6832.  
  6833.  
  6834. // console.log(948711, idx, obj1 === obj2, obj1, obj1.timestampUsec);
  6835. // console.log(948712, idx, obj1 === obj2, obj2, obj2.timestampUsec);
  6836. }
  6837.  
  6838. }
  6839.  
  6840.  
  6841. }
  6842.  
  6843. // console.log(1237005)
  6844.  
  6845. // console.log(378, arr);
  6846.  
  6847. return arr;
  6848.  
  6849.  
  6850. }
  6851.  
  6852. if (ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION) {
  6853.  
  6854. console.log('[yt-chat-control] ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION is used.')
  6855.  
  6856. // console.log('ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION 0001')
  6857.  
  6858. const pop078 = function () {
  6859. const r = this.pop78();
  6860.  
  6861. if (r && (r.actions || 0).length >= 1 && r.videoOffsetTimeMsec) {
  6862. for (const action of r.actions) {
  6863.  
  6864. const itemActionKey = !action ? null : 'addChatItemAction' in action ? 'addChatItemAction' : 'addLiveChatTickerItemAction' in action ? 'addLiveChatTickerItemAction' : null;
  6865. if (itemActionKey) {
  6866.  
  6867. const itemAction = action[itemActionKey];
  6868. const item = (itemAction || 0).item;
  6869. if (typeof item === 'object') {
  6870.  
  6871. const rendererKey = firstObjectKey(item);
  6872. if (rendererKey) {
  6873. const renderer = item[rendererKey];
  6874. if (renderer && typeof renderer === 'object') {
  6875. renderer.__videoOffsetTimeMsec__ = r.videoOffsetTimeMsec;
  6876. renderer.__progressAt__ = playerProgressChangedArg1;
  6877.  
  6878. // console.log(48117006)
  6879. }
  6880.  
  6881. }
  6882.  
  6883. }
  6884. }
  6885. }
  6886. }
  6887. return r;
  6888. }
  6889.  
  6890.  
  6891.  
  6892. const replayQueueProxyHandler = {
  6893. get(target, prop, receiver) {
  6894. if (prop === 'qe3') return 1;
  6895. const v = target[prop];
  6896. if (prop === 'front_') {
  6897. if (v && typeof v.length === 'number') {
  6898. if (!v.pop78) {
  6899. v.pop78 = v.pop;
  6900. v.pop = pop078;
  6901. }
  6902. }
  6903. }
  6904. return v;
  6905. }
  6906. };
  6907.  
  6908. // lcrFn2 will run twice to ensure the method is successfully injected.
  6909. const lcrFn2 = (lcrDummy)=>{
  6910. // make minimal function overhead by pre-defining all possible outside.
  6911.  
  6912. const tag = "yt-live-chat-renderer"
  6913. const dummy = lcrDummy;
  6914.  
  6915. const cProto = getProto(dummy);
  6916. if (!cProto || !cProto.attached) {
  6917. console.warn(`proto.attached for ${tag} is unavailable.`);
  6918. return;
  6919. }
  6920.  
  6921. // mightFirstCheckOnYtInit();
  6922. // groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-renderer hacks");
  6923. // console.log("[Begin]");
  6924.  
  6925.  
  6926. if (typeof cProto.playerProgressChanged_ === 'function' && !cProto.playerProgressChanged32_) {
  6927.  
  6928. cProto.playerProgressChanged32_ = cProto.playerProgressChanged_;
  6929.  
  6930.  
  6931. cProto.playerProgressChanged_ = function (a, b, c) {
  6932. // console.log(48117005)
  6933. if (a === 0) a = arguments[0] = Number.MIN_VALUE; // avoid issue dealing with zero value
  6934. playerProgressChangedArg1 = a;
  6935. playerProgressChangedArg2 = b;
  6936. playerProgressChangedArg3 = c;
  6937. const replayBuffer_ = this.replayBuffer_;
  6938. if (replayBuffer_) {
  6939. const replayQueue = replayBuffer_.replayQueue
  6940. if (replayQueue && typeof replayQueue === 'object' && !replayQueue.qe3) {
  6941. replayBuffer_.replayQueue = new Proxy(replayBuffer_.replayQueue, replayQueueProxyHandler);
  6942. }
  6943. }
  6944. Promise.resolve().then(updateTickerCurrentTime);
  6945. return this.playerProgressChanged32_.apply(this, arguments);
  6946. };
  6947.  
  6948. }
  6949.  
  6950. // console.log("[End]");
  6951. // groupEnd();
  6952.  
  6953.  
  6954. };
  6955. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  6956.  
  6957.  
  6958. // console.log('ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION 0002')
  6959.  
  6960. // getLCRDummy() must be called for injection
  6961. getLCRDummy().then(lcrFn2);
  6962.  
  6963. }
  6964.  
  6965. const stackDM = (()=>{
  6966.  
  6967. let cm, stack, mo;
  6968.  
  6969. let firstRun = ()=>{
  6970. cm = mockCommentElement(document.createComment('1'));
  6971. stack = new Set();
  6972. mo = new MutationObserver(()=>{
  6973. const stack_ = stack;
  6974. stack = new Set();
  6975. // for(const value of stack_){
  6976. // Promise.resolve(value).then(f=>f());
  6977. // }
  6978. for(const value of stack_){
  6979. value();
  6980. }
  6981. stack_.clear();
  6982. });
  6983. mo.observe(cm, {characterData: true});
  6984.  
  6985. }
  6986.  
  6987.  
  6988. const stackDM = (f) => {
  6989.  
  6990. if (firstRun) firstRun = firstRun();
  6991. stack.add(f);
  6992. cm.data = `${(cm.data & 1) + 1}`;
  6993. }
  6994. return stackDM;
  6995. })();
  6996. window.stackDM = stackDM;
  6997.  
  6998.  
  6999. const widthReq = (()=>{
  7000.  
  7001. let widthIORes;
  7002. let widthIO;
  7003.  
  7004. let firstRun = () => {
  7005. widthIORes = new WeakMap();
  7006. widthIO = new IntersectionObserver((mutations) => {
  7007. const r = new Map();
  7008. for (const mutation of mutations) {
  7009. r.set(mutation.target, mutation.boundingClientRect);
  7010. }
  7011.  
  7012. for (const [elm, rect] of r) {
  7013. widthIO.unobserve(elm);
  7014. const o = widthIORes.get(elm);
  7015. o && widthIORes.delete(elm);
  7016. const { promise, values } = o || {};
  7017. if (promise && values) {
  7018. values.width = rect.width;
  7019. promise.resolve(values);
  7020. }
  7021. }
  7022. });
  7023. };
  7024.  
  7025. const widthReq = (elm) => {
  7026.  
  7027. if (firstRun) firstRun = firstRun();
  7028.  
  7029. {
  7030. const { promise, values } = widthIORes.get(elm) || {};
  7031. if (promise) return promise;
  7032. }
  7033.  
  7034. const promise = new PromiseExternal();
  7035. widthIORes.set(elm, { promise, values: {} });
  7036. widthIO.unobserve(elm);
  7037. widthIO.observe(elm);
  7038.  
  7039. return promise;
  7040.  
  7041. }
  7042. return widthReq;
  7043. })();
  7044.  
  7045.  
  7046.  
  7047.  
  7048. customElements.whenDefined('yt-live-chat-item-list-renderer').then(() => {
  7049.  
  7050.  
  7051. const tag = "yt-live-chat-item-list-renderer"
  7052. const dummy = document.createElement(tag);
  7053.  
  7054. const cProto = getProto(dummy);
  7055. if (!cProto || !cProto.attached) {
  7056. console.warn(`proto.attached for ${tag} is unavailable.`);
  7057. return;
  7058. }
  7059.  
  7060. mightFirstCheckOnYtInit();
  7061. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-item-list-renderer hacks");
  7062. console1.log("[Begin]");
  7063.  
  7064. const mclp = cProto;
  7065. const _flag0281_ = window._flag0281_;
  7066.  
  7067. try {
  7068. assertor(() => typeof mclp.scrollToBottom_ === 'function');
  7069. assertor(() => typeof mclp.flushActiveItems_ === 'function');
  7070. assertor(() => typeof mclp.canScrollToBottom_ === 'function');
  7071. assertor(() => typeof mclp.setAtBottom === 'function');
  7072. assertor(() => typeof mclp.scrollToBottom66_ === 'undefined');
  7073. assertor(() => typeof mclp.flushActiveItems66_ === 'undefined');
  7074. } catch (e) { }
  7075.  
  7076.  
  7077. try {
  7078. assertor(() => typeof mclp.attached === 'function');
  7079. assertor(() => typeof mclp.detached === 'function');
  7080. assertor(() => typeof mclp.canScrollToBottom_ === 'function');
  7081. assertor(() => typeof mclp.isSmoothScrollEnabled_ === 'function');
  7082. assertor(() => typeof mclp.maybeResizeScrollContainer_ === 'function');
  7083. assertor(() => typeof mclp.refreshOffsetContainerHeight_ === 'function');
  7084. assertor(() => typeof mclp.smoothScroll_ === 'function');
  7085. assertor(() => typeof mclp.resetSmoothScroll_ === 'function');
  7086. } catch (e) { }
  7087.  
  7088. mclp.prDelay171 = null;
  7089.  
  7090. let myk = 0; // showNewItems77_
  7091. let mlf = 0; // flushActiveItems77_
  7092. let myw = 0; // onScrollItems77_
  7093. let mzt = 0; // handleLiveChatActions77_
  7094. let mlg = 0; // delayFlushActiveItemsAfterUserAction11_
  7095. let zarr = null;
  7096.  
  7097. if ((_flag0281_ & 0x2000) == 0) {
  7098.  
  7099. if ((mclp.clearList || 0).length === 0) {
  7100. (_flag0281_ & 0x2) == 0 && assertor(() => fnIntegrity(mclp.clearList, '0.106.50'));
  7101. mclp.clearList66 = mclp.clearList;
  7102. mclp.clearList = function () {
  7103. myk = (myk & 1073741823) + 1;
  7104. mlf = (mlf & 1073741823) + 1;
  7105. myw = (myw & 1073741823) + 1;
  7106. mzt = (mzt & 1073741823) + 1;
  7107. mlg = (mlg & 1073741823) + 1;
  7108. zarr = null;
  7109. this.prDelay171 = null;
  7110. this.clearList66();
  7111. };
  7112. console1.log("clearList", "OK");
  7113. } else {
  7114. console1.log("clearList", "NG");
  7115. }
  7116.  
  7117. }
  7118.  
  7119.  
  7120.  
  7121. let onListRendererAttachedDone = false;
  7122.  
  7123. function setList(itemOffset, items) {
  7124.  
  7125. const isFirstTime = onListRendererAttachedDone === false;
  7126.  
  7127. if (isFirstTime) {
  7128. onListRendererAttachedDone = true;
  7129. Promise.resolve().then(watchUserCSS);
  7130. addCssManaged();
  7131.  
  7132. const isBoostChatEnabled = (window._flag0281_ & 0x40000) === 0x40000;
  7133. if (!isBoostChatEnabled) setupEvents();
  7134. }
  7135.  
  7136. setupStyle(itemOffset, items);
  7137.  
  7138. setupMutObserver(items);
  7139.  
  7140. console.log('[yt-chat] setupMutObserver DONE')
  7141. }
  7142.  
  7143.  
  7144. const deferSeqFns = []; // ensure correct sequence
  7145. let deferSeqFnI = 0;
  7146. const deferCallbackLooper = entry => {
  7147. nextBrowserTick_(() => {
  7148. const { a, b } = entry;
  7149. const cnt = kRef(a);
  7150. if (cnt && b) b.call(cnt);
  7151. entry.a = entry.b = null;
  7152. });
  7153. }
  7154. const deferCallback = async (cnt, callback) => {
  7155. const a = cnt.__weakRef9441__ || (cnt.__weakRef9441__ = mWeakRef(cnt));
  7156. deferSeqFns[deferSeqFnI++] = { a, b: callback };
  7157. if (deferSeqFnI > 1) return;
  7158. const pr288 = cnt.prDelay288;
  7159. await pr288;
  7160. wme.data = `${(wme.data & 7) + 1}`;
  7161. await wmp;
  7162. const l = deferSeqFnI;
  7163. deferSeqFnI = 0;
  7164. for (let i = 0; i < l; i++) {
  7165. const o = deferSeqFns[i];
  7166. deferSeqFns[i] = null;
  7167. Promise.resolve(o).then(deferCallbackLooper);
  7168. }
  7169. };
  7170.  
  7171. let showMoreBtnTransitionTrigg = null;
  7172.  
  7173. mclp.__showMoreBtn_transitionstart011__ = function (evt) {
  7174. showMoreBtnTransitionTrigg = true;
  7175. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7176. if (newVisibility === "visible") {
  7177. const btn = evt.target;
  7178. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7179. }
  7180. };
  7181.  
  7182.  
  7183. mclp.__showMoreBtn_transitionend011__ = function (evt) {
  7184. showMoreBtnTransitionTrigg = true;
  7185. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7186. if (newVisibility === "hidden") {
  7187. const btn = evt.target;
  7188. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7189. }
  7190. };
  7191. mclp.attached419 = async function () {
  7192.  
  7193. if (!this.isAttached) return;
  7194.  
  7195. let maxTrial = 16;
  7196. while (!this.$ || !this.$['item-scroller'] || !this.$['item-offset'] || !this.$['items']) {
  7197. if (--maxTrial < 0 || !this.isAttached) return;
  7198. await nextBrowserTick_();
  7199. // await new Promise(requestAnimationFrame);
  7200. }
  7201.  
  7202. if (this.isAttached !== true) return;
  7203.  
  7204. if (!this.$) {
  7205. console.warn("!this.$");
  7206. return;
  7207. }
  7208. if (!this.$) return;
  7209. /** @type {HTMLElement | null} */
  7210. const itemScroller = this.$['item-scroller'];
  7211. /** @type {HTMLElement | null} */
  7212. const itemOffset = this.$['item-offset'];
  7213. /** @type {HTMLElement | null} */
  7214. const items = this.$['items'];
  7215.  
  7216. if (!itemScroller || !itemOffset || !items) {
  7217. console.warn("items.parentNode !== itemOffset");
  7218. return;
  7219. }
  7220.  
  7221. if (nodeParent(items) !== itemOffset) {
  7222.  
  7223. console.warn("items.parentNode !== itemOffset");
  7224. return;
  7225. }
  7226.  
  7227.  
  7228. if (items.id !== 'items' || itemOffset.id !== "item-offset") {
  7229.  
  7230. console.warn("id incorrect");
  7231. return;
  7232. }
  7233.  
  7234. 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')
  7235.  
  7236. if (!isTargetItems) {
  7237. console.warn("!isTargetItems");
  7238. return;
  7239. }
  7240.  
  7241. setList(itemOffset, items);
  7242.  
  7243. if (WITH_SCROLL_ANCHOR) this.__itemAnchorColl011__ = itemOffset.getElementsByTagName('item-anchor');
  7244. else this.__itemAnchorColl011__ = null;
  7245.  
  7246.  
  7247.  
  7248. // btn-show-more-transition
  7249. const btn = this.$['show-more'];
  7250. if (btn) {
  7251. if (!this.__showMoreBtn_transitionstart012__) this.__showMoreBtn_transitionstart012__ = this.__showMoreBtn_transitionstart011__.bind(this);
  7252. if (!this.__showMoreBtn_transitionend012__) this.__showMoreBtn_transitionend012__ = this.__showMoreBtn_transitionend011__.bind(this);
  7253. btn.addEventListener('transitionrun', this.__showMoreBtn_transitionstart012__, false);
  7254. btn.addEventListener('transitionstart', this.__showMoreBtn_transitionstart012__, false);
  7255. btn.addEventListener('transitionend', this.__showMoreBtn_transitionend012__, false);
  7256. btn.addEventListener('transitioncancel', this.__showMoreBtn_transitionend012__, false);
  7257. }
  7258.  
  7259. // fix panel height changing issue (ENABLE_OVERFLOW_ANCHOR only)
  7260. if (itemScrollerResizeObserver) itemScrollerResizeObserver.observe(this.itemScroller || this.$['item-scroller']);
  7261.  
  7262. }
  7263.  
  7264. mclp.attached331 = mclp.attached;
  7265. mclp.attached = function () {
  7266. this.attached419 && this.attached419();
  7267. return this.attached331();
  7268. }
  7269.  
  7270. mclp.detached331 = mclp.detached;
  7271.  
  7272. mclp.detached = function () {
  7273. setupMutObserver();
  7274. return this.detached331();
  7275. }
  7276.  
  7277. const t29s = document.querySelectorAll("yt-live-chat-item-list-renderer");
  7278. for (const t29 of t29s) {
  7279. const cnt = insp(t29);
  7280. if (cnt.isAttached === true) {
  7281. cnt.attached419();
  7282. }
  7283. }
  7284.  
  7285. if ((mclp.async || 0).length === 2 && (mclp.cancelAsync || 0).length === 1) {
  7286.  
  7287. assertor(() => fnIntegrity(mclp.async, '2.24.15'));
  7288. assertor(() => fnIntegrity(mclp.cancelAsync, '1.15.8'));
  7289.  
  7290. /** @type {Map<number, any>} */
  7291. const aMap = new Map();
  7292. const mcid = setTimeout(() => 0, 0.625);
  7293. const maid = requestAnimationFrame(() => 0);
  7294. clearTimeout(mcid);
  7295. cancelAnimationFrame(maid);
  7296. const count0 = mcid + maid + 1740;
  7297. let count = count0;
  7298. mclp.async66 = mclp.async;
  7299. mclp.async = function (e, f) {
  7300. // ensure the previous operation is done
  7301. // .async is usually after the time consuming functions like flushActiveItems_ and scrollToBottom_
  7302. const hasF = arguments.length === 2;
  7303. if (count > 1e9) count = count0 + 9;
  7304. const resId = ++count;
  7305. aMap.set(resId, e);
  7306. const pr1 = Promise.all([this.prDelay288, wmp, this.prDelay171, Promise.resolve()]);
  7307. const pr2 = autoTimerFn();
  7308. Promise.race([pr1, pr2]).then(() => {
  7309. const rp = aMap.get(resId);
  7310. if (typeof rp !== 'function') {
  7311. return;
  7312. }
  7313. const asyncEn = function () {
  7314. return aMap.delete(resId) && rp.apply(this, arguments);
  7315. };
  7316. aMap.set(resId, hasF ? this.async66(asyncEn, f) : this.async66(asyncEn));
  7317. });
  7318.  
  7319. return resId;
  7320. }
  7321.  
  7322. mclp.cancelAsync66 = mclp.cancelAsync;
  7323. mclp.cancelAsync = function (resId) {
  7324. if (resId <= count0) {
  7325. this.cancelAsync66(resId);
  7326. } else if (aMap.has(resId)) {
  7327. const rp = aMap.get(resId);
  7328. aMap.delete(resId);
  7329. if (typeof rp !== 'function') {
  7330. this.cancelAsync66(rp);
  7331. }
  7332. }
  7333. }
  7334.  
  7335. console1.log("async", "OK");
  7336. } else {
  7337. console1.log("async", "NG");
  7338. }
  7339.  
  7340.  
  7341. if ((_flag0281_ & 0x2) == 0) {
  7342. if ((mclp.showNewItems_ || 0).length === 0 && ENABLE_NO_SMOOTH_TRANSFORM) {
  7343.  
  7344. assertor(() => fnIntegrity(mclp.showNewItems_, '0.170.79'));
  7345. mclp.showNewItems66_ = mclp.showNewItems_;
  7346. mclp.showNewItems_ = function () {
  7347. //
  7348. }
  7349.  
  7350. console1.log("showNewItems_", "OK");
  7351. } else {
  7352. console1.log("showNewItems_", "NG");
  7353. }
  7354.  
  7355. }
  7356.  
  7357.  
  7358.  
  7359. if ((_flag0281_ & 0x2) == 0) {
  7360. if ((mclp.onScrollItems_ || 0).length === 1) {
  7361.  
  7362. if (mclp.onScrollItems3641_) {
  7363.  
  7364. } else {
  7365. assertor(() => fnIntegrity(mclp.onScrollItems_, '1.17.9'));
  7366.  
  7367. }
  7368.  
  7369. if (typeof mclp.setAtBottom === 'function' && mclp.setAtBottom.length === 0) {
  7370.  
  7371. mclp.setAtBottom217 = mclp.setAtBottom;
  7372. mclp.setAtBottom = function () {
  7373. const v = this.ec217;
  7374. if (typeof v !== 'boolean') return this.setAtBottom217();
  7375. const u = this.atBottom;
  7376. if (u !== v && typeof u === 'boolean') this.atBottom = v;
  7377. // this.atBottom = a.scrollTop >= a.scrollHeight - a.clientHeight - 15
  7378. }
  7379.  
  7380. let lastScrollTarget = null;
  7381. mclp.onScrollItems66_ = mclp.onScrollItems_;
  7382. let callback = () => { };
  7383.  
  7384. // let itemScrollerWR = null;
  7385. let lastEvent = null;
  7386.  
  7387. let io2 = null, io1 = null;
  7388. const io2f = (entries, observer) => {
  7389. const entry = entries[entries.length - 1];
  7390. if (entry.target !== lastScrollTarget) return;
  7391. callback(entry);
  7392. };
  7393. const io1f = (entries, observer) => {
  7394. const entry = entries[entries.length - 1];
  7395. observer.unobserve(entry.target);
  7396. if (entry.target !== lastScrollTarget) return;
  7397. lastScrollTarget = null;
  7398. callback(entry);
  7399. };
  7400. mclp.onScrollItems3885cb2_ = function (entry) {
  7401. const v = (entry.isIntersecting === true);
  7402. this.ec217 = v;
  7403. this.onScrollItems66_(lastEvent);
  7404. this.ec217 = null;
  7405. }
  7406. mclp.onScrollItems3885cb1_ = function (entry) {
  7407. const v = (entry.intersectionRatio > 0.98);
  7408. this.ec217 = v;
  7409. this.onScrollItems66_(lastEvent);
  7410. this.ec217 = null;
  7411. };
  7412.  
  7413. mclp.onScrollItems_ = function (evt) {
  7414.  
  7415. if (evt === lastEvent) return;
  7416. if (evt && lastEvent && evt.timeStamp === lastEvent.timeStamp) return;
  7417. lastEvent = evt;
  7418. const ytRendererBehavior = this.ytRendererBehavior || 0;
  7419. if (typeof ytRendererBehavior.onScroll === 'function') ytRendererBehavior.onScroll(evt);
  7420. const coll = this.__itemAnchorColl011__;
  7421. if (coll) {
  7422. const anchorElement = coll.length === 1 ? coll[0] : null;
  7423. if (lastScrollTarget !== anchorElement) {
  7424. if (io2) io2.disconnect();
  7425. lastScrollTarget = anchorElement;
  7426. if (anchorElement) {
  7427. if (!this.onScrollItems3886cb2_) this.onScrollItems3886cb2_ = this.onScrollItems3885cb2_.bind(this);
  7428. callback = this.onScrollItems3886cb2_;
  7429. if (!io2) io2 = new IntersectionObserver(io2f);
  7430. io2.observe(anchorElement);
  7431. }
  7432. }
  7433. } else {
  7434. const items = this.$.items;
  7435. if (!items) return this.onScrollItems66_();
  7436. const lastComponent = lastComponentChildFn(items);
  7437. if (!lastComponent) return this.onScrollItems66_();
  7438. if (lastScrollTarget === lastComponent) return;
  7439. lastScrollTarget = lastComponent;
  7440.  
  7441. if (io1) io1.disconnect();
  7442. if (!this.onScrollItems3886cb1_) this.onScrollItems3886cb1_ = this.onScrollItems3885cb1_.bind(this);
  7443. callback = this.onScrollItems3886cb1_;
  7444. if (!io1) io1 = new IntersectionObserver(io1f);
  7445. io1.observe(lastComponent);
  7446. }
  7447. };
  7448.  
  7449. }
  7450.  
  7451. console1.log("onScrollItems_", "OK");
  7452. } else {
  7453. console1.log("onScrollItems_", "NG");
  7454. }
  7455. }
  7456.  
  7457.  
  7458. if ((_flag0281_ & 0x40) == 0) {
  7459.  
  7460. if (ENABLE_NO_SMOOTH_TRANSFORM && SUPPRESS_refreshOffsetContainerHeight_ && typeof mclp.refreshOffsetContainerHeight_ === 'function' && !mclp.refreshOffsetContainerHeight26_ && mclp.refreshOffsetContainerHeight_.length === 0) {
  7461. assertor(() => fnIntegrity(mclp.refreshOffsetContainerHeight_, '0.31.21'));
  7462. mclp.refreshOffsetContainerHeight26_ = mclp.refreshOffsetContainerHeight_;
  7463. mclp.refreshOffsetContainerHeight_ = function () {
  7464. // var a = this.itemScroller.clientHeight;
  7465. // this.itemOffset.style.height = this.items.clientHeight + "px";
  7466. // this.bottomAlignMessages && (this.itemOffset.style.minHeight = a + "px")
  7467. }
  7468. console1.log("refreshOffsetContainerHeight_", "OK");
  7469. } else {
  7470. console1.log("refreshOffsetContainerHeight_", "NG");
  7471. }
  7472.  
  7473. }
  7474.  
  7475. if ((_flag0281_ & 0x2000) == 0) {
  7476. if ((mclp.flushActiveItems_ || 0).length === 0) {
  7477.  
  7478. if ((_flag0281_ & 0x2) == 0) {
  7479.  
  7480. const sfi = fnIntegrity(mclp.flushActiveItems_);
  7481.  
  7482. if (sfi === '0.156.86') {
  7483.  
  7484. // https://www.youtube.com/s/desktop/2cf5dafc/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  7485.  
  7486.  
  7487. // f.flushActiveItems_ = function() {
  7488. // var a = this;
  7489. // if (this.activeItems_.length > 0)
  7490. // if (this.canScrollToBottom_()) {
  7491. // var b = Math.max(this.visibleItems.length + this.activeItems_.length - this.data.maxItemsToDisplay, 0);
  7492. // b && this.splice("visibleItems", 0, b);
  7493. // if (this.isSmoothScrollEnabled_() || this.dockableMessages.length)
  7494. // this.preinsertHeight_ = this.items.clientHeight;
  7495. // this.activeItems_.unshift("visibleItems");
  7496. // try {
  7497. // this.push.apply(this, this.activeItems_)
  7498. // } catch (c) {
  7499. // $m(c)
  7500. // }
  7501. // this.activeItems_ = [];
  7502. // this.isSmoothScrollEnabled_() ? this.canScrollToBottom_() && wy(function() {
  7503. // a.showNewItems_()
  7504. // }) : wy(function() {
  7505. // a.refreshOffsetContainerHeight_();
  7506. // a.maybeScrollToBottom_()
  7507. // })
  7508. // } else
  7509. // this.activeItems_.length > this.data.maxItemsToDisplay && this.activeItems_.splice(0, this.activeItems_.length - this.data.maxItemsToDisplay)
  7510. // }
  7511. } else if (sfi === '0.150.84') {
  7512. // https://www.youtube.com/s/desktop/e4d15d2c/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  7513. // var b = Math.max(this.visibleItems.length + this.activeItems_.length - this.data.maxItemsToDisplay, 0);
  7514. // b && this.splice("visibleItems", 0, b);
  7515. // if (this.isSmoothScrollEnabled_() || this.dockableMessages.length)
  7516. // this.preinsertHeight_ = this.items.clientHeight;
  7517. // this.activeItems_.unshift("visibleItems");
  7518. // try {
  7519. // this.push.apply(this, this.activeItems_)
  7520. // } catch (c) {
  7521. // nm(c)
  7522. // }
  7523. // this.activeItems_ = [];
  7524. // this.isSmoothScrollEnabled_() ? this.canScrollToBottom_() && zQ(function() {
  7525. // a.showNewItems_()
  7526. // }) : zQ(function() {
  7527. // a.maybeScrollToBottom_()
  7528. // })
  7529. } else if (sfi === '0.137.81' || sfi === '0.138.81') {
  7530. // e.g. https://www.youtube.com/yts/jsbin/live_chat_polymer-vflCyWEBP/live_chat_polymer.js
  7531. } else {
  7532. assertor(() => fnIntegrity(mclp.flushActiveItems_, '0.157.86'))
  7533. || logFn('mclp.flushActiveItems_', mclp.flushActiveItems_)();
  7534. }
  7535. }
  7536.  
  7537. let hasMoreMessageState = !ENABLE_SHOW_MORE_BLINKER ? -1 : 0;
  7538.  
  7539. mclp.flushActiveItems66a_ = mclp.flushActiveItems_;
  7540. // let lastLastRow = null;
  7541.  
  7542.  
  7543. const preloadFn = (acItems) => {
  7544. let waitFor = [];
  7545. /** @type {Set<string>} */
  7546. const imageLinks = new Set();
  7547. imageLinks.add = imageLinks.addOriginal || imageLinks.add;
  7548.  
  7549. if (ENABLE_PRELOAD_THUMBNAIL || EMOJI_IMAGE_SINGLE_THUMBNAIL || AUTHOR_PHOTO_SINGLE_THUMBNAIL) {
  7550. for (const item of acItems) {
  7551. fixLiveChatItem(item, imageLinks);
  7552. }
  7553. }
  7554. if (ENABLE_PRELOAD_THUMBNAIL && kptPF !== null && (kptPF & (8 | 4)) && imageLinks.size > 0) {
  7555.  
  7556. // reference: https://github.com/Yuanfang-fe/Blog-X/issues/34
  7557. const rel = kptPF & 8 ? 'subresource' : kptPF & 16 ? 'preload' : kptPF & 4 ? 'prefetch' : '';
  7558. // preload performs the high priority fetching.
  7559. // prefetch delays the chat display if the video resoruce is demanding.
  7560.  
  7561. if (rel) {
  7562.  
  7563. imageLinks.forEach(imageLink => {
  7564. let d = false;
  7565. if (SKIP_PRELOAD_EMOJI && imageLink.includes('.ggpht.com/')) return;
  7566. const isEmoji = imageLink.includes('/emoji/');
  7567. const pretechedSet = isEmoji ? emojiPrefetched : authorPhotoPrefetched;
  7568. if (!pretechedSet.has(imageLink)) {
  7569. pretechedSet.add(imageLink);
  7570. d = true;
  7571. }
  7572. if (d) {
  7573. waitFor.push(linker(null, rel, imageLink, 'image'));
  7574.  
  7575. }
  7576. })
  7577.  
  7578. }
  7579.  
  7580. }
  7581. imageLinks.clear();
  7582.  
  7583. return async () => {
  7584. if (waitFor.length > 0) {
  7585. await Promise.race([new Promise(r => setTimeout(r, 250)), Promise.all(waitFor)]);
  7586. }
  7587. waitFor.length = 0;
  7588. waitFor = null;
  7589. };
  7590.  
  7591. };
  7592.  
  7593. if (ENABLE_CHAT_MESSAGES_BOOSTED_STAMPING && `${mclp.flushActiveItems_}`.includes("this.push.apply(this,this.activeItems_)") && `${mclp.flushActiveItems_}`.includes(`this.splice("visibleItems",0,`)
  7594. && !cProto.notifyPath371 && !cProto.proceedStampDomArraySplices381_
  7595. && !cProto.stampDomArraySplices381_ && !cProto.push377 && !cProto.splice377) {
  7596.  
  7597. {
  7598.  
  7599. rendererStamperFactory(cProto, {
  7600. key: 'proceedStampDomArraySplices381_',
  7601. stamperDomClass: 'style-scope yt-live-chat-item-list-renderer yt-live-chat-item-list-stampdom',
  7602. preloadFn
  7603. });
  7604. cProto.notifyPath371 = cProto.notifyPath;
  7605.  
  7606. cProto.stampDomArraySplices381_ = cProto.stampDomArraySplices_;
  7607.  
  7608. if (typeof cProto.stampDomArraySplices381_ === 'function' && cProto.stampDomArraySplices381_.length >= 3) {
  7609.  
  7610. cProto.stampDomArraySplices_ = function (a, b, c) {
  7611. if (a === 'visibleItems' && b === 'items' && (c || 0).indexSplices) {
  7612. // if (this.ec388) {
  7613. const indexSplices = c.indexSplices;
  7614. if (indexSplices.length === 1 || typeof indexSplices.length === "undefined") {
  7615. const indexSplice = indexSplices[0] || indexSplices;
  7616. if (indexSplice.type === 'splice' && (indexSplice.addedCount >= 1 || (indexSplice.removed || []).length >= 1)) {
  7617. // console.log(1059, a, b, indexSplice);
  7618. if (this.proceedStampDomArraySplices381_(a, b, indexSplice)) return;
  7619. }
  7620. }
  7621. // } else {
  7622. // console.warn('stampDomArraySplices_ warning', ...arguments);
  7623. // }
  7624. }
  7625. return this.stampDomArraySplices381_(...arguments);
  7626. }
  7627. } else {
  7628. console.warn('0xF0230 Function Signature Changed');
  7629. }
  7630.  
  7631. cProto.stampDomArray366_ = cProto.stampDomArray_;
  7632.  
  7633. if (typeof cProto.stampDomArray366_ === 'function' && cProto.stampDomArray366_.length >= 5) {
  7634. cProto.stampDomArray_ = function (items, containerId, componentConfig, rxConfig, shouldCallback, isStableList) {
  7635. const isTickerRendering = items === this.tickerItems && containerId === 'ticker-items';
  7636. const isMessageListRendering = items === this.visibleItems && containerId === 'items';
  7637.  
  7638. if (!isTickerRendering && !isMessageListRendering) {
  7639. console.log('stampDomArray_ warning 0xF501', ...arguments)
  7640. return this.stampDomArray366_(...arguments);
  7641. }
  7642.  
  7643. const container = (this.$ || 0)[containerId];
  7644. if (!container) {
  7645. console.log('stampDomArray_ warning 0xF502', ...arguments)
  7646. return this.stampDomArray366_(...arguments);
  7647. }
  7648.  
  7649. if (container[sFirstElementChild] === null && items.length === 0) {
  7650.  
  7651. } else {
  7652. const cTag = isTickerRendering ? 'tickerItems' : 'visibleItems';
  7653. this.proceedStampDomArraySplices381_(cTag, containerId, {
  7654. addedCount: items.length,
  7655. removedCount: container.childElementCount
  7656. });
  7657. }
  7658.  
  7659. const f = () => {
  7660. this.markDirty && this.markDirty();
  7661. const detail = {
  7662. container
  7663. };
  7664. shouldCallback && this.hostElement.dispatchEvent(new CustomEvent("yt-rendererstamper-finished", {
  7665. bubbles: !0,
  7666. cancelable: !1,
  7667. composed: !0,
  7668. detail
  7669. }));
  7670. detail.container = null;
  7671. };
  7672.  
  7673. if (this.ec389pr) {
  7674. this.ec389pr.then(f)
  7675. } else {
  7676. f();
  7677. }
  7678.  
  7679. };
  7680. } else {
  7681. console.warn('0xF0230 Function Signature Changed');
  7682. }
  7683.  
  7684. mclp.push377 = mclp.push;
  7685. mclp.splice377 = mclp.splice;
  7686.  
  7687. const emptyArr = [];
  7688. emptyArr.push = () => 0;
  7689. emptyArr.unshift = () => 0;
  7690. emptyArr.pop = () => void 0;
  7691. emptyArr.shift = () => void 0;
  7692. emptyArr.splice = () => void 0;
  7693. emptyArr.slice = function () { return this };
  7694.  
  7695. if (typeof mclp.push377 === 'function' && mclp.push377.length >= 1) {
  7696. mclp.push = function (cTag, ...fnArgs) {
  7697. if (cTag !== 'visibleItems' || !fnArgs.length || !fnArgs[0]) return this.push377(...arguments);
  7698. const arr = this.visibleItems;
  7699. const len = arr.length;
  7700. const newTotalLen = arr.push(...fnArgs);
  7701. const addedCount = fnArgs.length;
  7702. // console.log('push')
  7703. this.proceedStampDomArraySplices381_('visibleItems', 'items', {
  7704. index: len, addedCount: addedCount, removedCount: 0
  7705. })
  7706. return newTotalLen;
  7707. }
  7708. } else {
  7709. console.warn('0xF0230 Function Signature Changed');
  7710. }
  7711.  
  7712. if (typeof mclp.splice377 === 'function' && mclp.splice377.length >= 1) {
  7713. mclp.splice = function (cTag, ...fnArgs) {
  7714. if (cTag !== 'visibleItems' || !fnArgs.length || (fnArgs.length === 2 && !fnArgs[1]) || (fnArgs.length > 2 && !fnArgs[2])) return this.splice377(...arguments);
  7715. const arr = this.visibleItems;
  7716. const removed = arr.splice(...fnArgs);
  7717. const removedCount = removed.length;
  7718. const addedCount = (fnArgs.length > 2 ? fnArgs.length - 2 : 0);
  7719. if (fnArgs.length >= 2 && removedCount !== fnArgs[1]) {
  7720. console.warn(`incorrect splice count. expected = ${fnArgs[1]}; actual = ${removedCount}`);
  7721. }
  7722. // console.log('splice')
  7723. this.proceedStampDomArraySplices381_('visibleItems', 'items', {
  7724. index: fnArgs[0], addedCount: addedCount, removedCount
  7725. })
  7726. return removed;
  7727. }
  7728. } else {
  7729. console.warn('0xF0230 Function Signature Changed');
  7730. }
  7731.  
  7732. }
  7733.  
  7734. mclp.flushActiveItemsFix001_ = function () {
  7735.  
  7736. // fix YouTube wrong code
  7737. // var b = Math.max(this.visibleItems.length + this.activeItems_.length - this.data.maxItemsToDisplay, 0);
  7738. // b && this.splice("visibleItems", 0, b);
  7739. // e.g. 0 + 99 - 90 = 9
  7740.  
  7741. const data = this.data;
  7742. if (!data) return;
  7743. const visibleItems = this.visibleItems;
  7744. const activeItems_ = this.activeItems_;
  7745. if (!visibleItems || !activeItems_) return;
  7746. const viLen = visibleItems.length;
  7747. const aiLen = activeItems_.length;
  7748. const maxDisplayLen = data.maxItemsToDisplay;
  7749. if (!maxDisplayLen) return;
  7750. if (viLen + aiLen > maxDisplayLen) {
  7751. if (aiLen > maxDisplayLen) activeItems_.splice(0, aiLen - maxDisplayLen);
  7752. // visibleItems splice done by original flushActiveItems_
  7753. }
  7754. }
  7755.  
  7756. mclp.flushActiveItems3641_ = mclp.flushActiveItems_;
  7757.  
  7758. mclp.__moreItemButtonBlinkingCheck183__ = function () {
  7759. const hasPendingItems = (this.activeItems_ && this.activeItems_.length > 0) ? 1 : 0;
  7760. const shouldChange = (hasMoreMessageState === (1 - hasPendingItems));
  7761. if (shouldChange) {
  7762. hasMoreMessageState = hasPendingItems;
  7763. const showMore = (this.$ || 0)['show-more'];
  7764. if (showMore) {
  7765. showMore.classList.toggle('has-new-messages-miuzp', hasPendingItems ? true : false);
  7766. }
  7767. }
  7768. }
  7769.  
  7770. let ps00 = false;
  7771. mclp.flushActiveItems_ = function () {
  7772. if (ps00) return;
  7773. // console.log('flushActiveItems_')
  7774. ps00 = true;
  7775. deferCallback(this, () => {
  7776. ps00 = false;
  7777. // console.log('flushActiveItems3641_')
  7778. if (this.activeItems_.length > 0) {
  7779. const data = this.data;
  7780. if (data) {
  7781. if (data.maxItemsToDisplay > MAX_ITEMS_FOR_TOTAL_DISPLAY) data.maxItemsToDisplay = MAX_ITEMS_FOR_TOTAL_DISPLAY;
  7782. this.flushActiveItemsFix001_(); // bug fix
  7783. this.flushActiveItems3641_();
  7784. if (ENABLE_SHOW_MORE_BLINKER) {
  7785. this.__moreItemButtonBlinkingCheck183__(); // blink the button if there are activeItems remaining.
  7786. }
  7787. }
  7788. }
  7789. }).catch(console.warn);
  7790. };
  7791.  
  7792. mclp.showNewItems3641_ = mclp.showNewItems_;
  7793. mclp.refreshOffsetContainerHeight3641_ = mclp.refreshOffsetContainerHeight_;
  7794. mclp.maybeScrollToBottom3641_ = mclp.maybeScrollToBottom_;
  7795.  
  7796. let ps01 = false;
  7797. mclp.showNewItems_ = function () {
  7798. if (ps01) return;
  7799. // console.log('showNewItems_')
  7800. ps01 = true;
  7801. deferCallback(this, () => {
  7802. ps01 = false;
  7803. this.showNewItems3641_();
  7804. }).catch(console.warn);
  7805. };
  7806.  
  7807. if (!ENABLE_NO_SMOOTH_TRANSFORM && !mclp.refreshOffsetContainerHeight26_) {
  7808. let ps02 = false;
  7809. mclp.refreshOffsetContainerHeight_ = function () {
  7810. if (ps02) return;
  7811. // console.log('refreshOffsetContainerHeight_')
  7812. ps02 = true;
  7813. deferCallback(this, () => {
  7814. ps02 = false;
  7815. this.refreshOffsetContainerHeight3641_();
  7816. }).catch(console.warn);
  7817. };
  7818. }
  7819.  
  7820.  
  7821. let ps03 = false;
  7822. mclp.maybeScrollToBottom_ = function () {
  7823. if (ps03) return;
  7824. // console.log('maybeScrollToBottom_')
  7825. ps03 = true;
  7826. deferCallback(this, () => {
  7827. ps03 = false;
  7828. if (this.atBottom === true) {
  7829.  
  7830. // if (itemsResizeObserverAttached !== true && this.atBottom === true) {
  7831. // // fallback for old browser
  7832. // const itemScroller = this.itemScroller || this.$['item-scroller'] || this.querySelector('#item-scroller') || 0;
  7833. // if (itemScroller.scrollTop === 0) {
  7834. // resizeObserverFallback.observe(itemScroller);
  7835. // }
  7836. // }
  7837. } else {
  7838.  
  7839. this.maybeScrollToBottom3641_();
  7840. }
  7841. }).catch(console.warn);
  7842. };
  7843.  
  7844. mclp.onScrollItems3641_ = mclp.onScrollItems_;
  7845. mclp.maybeResizeScrollContainer3641_ = mclp.maybeResizeScrollContainer_;
  7846. mclp.handleLiveChatActions3641_ = mclp.handleLiveChatActions_;
  7847.  
  7848. let ps11 = false;
  7849. mclp.onScrollItems_ = function (a) {
  7850. if (ps11) return;
  7851. // console.log('onScrollItems_')
  7852. ps11 = true;
  7853. deferCallback(this, () => {
  7854. ps11 = false;
  7855. this.onScrollItems3641_(a);
  7856. }).catch(console.warn);
  7857. };
  7858.  
  7859. if (!ENABLE_NO_SMOOTH_TRANSFORM) { // no function for ENABLE_NO_SMOOTH_TRANSFORM
  7860. let ps12 = false;
  7861. mclp.maybeResizeScrollContainer_ = function (a) {
  7862. if (ps12) return;
  7863. // console.log('maybeResizeScrollContainer_')
  7864. ps12 = true;
  7865. deferCallback(this, () => {
  7866. ps12 = false;
  7867. this.maybeResizeScrollContainer3641_(a);
  7868. }).catch(console.warn);
  7869. };
  7870. }
  7871.  
  7872. }
  7873.  
  7874. console1.log("flushActiveItems_", "OK");
  7875. } else {
  7876. console1.log("flushActiveItems_", "NG");
  7877. }
  7878. }
  7879.  
  7880.  
  7881. if ((_flag0281_ & 0x40) == 0 ) {
  7882.  
  7883.  
  7884. let showBtnLastState = null;
  7885. let lastAtBottomState = null;
  7886. // let showMoreBtnTransitionTrigg = false;
  7887. mclp.atBottomChanged314_ = mclp.atBottomChanged_;
  7888. mclp.atBottomChanged_ = function () {
  7889.  
  7890. const currentAtBottomState = this.atBottom;
  7891. if(lastAtBottomState === currentAtBottomState) return;
  7892. lastAtBottomState = currentAtBottomState;
  7893.  
  7894. // console.log(1289, showMoreBtnTransitionTrigg)
  7895.  
  7896. /*
  7897. if (!this.___btn3848___) {
  7898. this.___btn3848___ = true;
  7899. const btn = ((this || 0).$ || 0)["show-more"] || 0;
  7900. if (btn) {
  7901. btn.addEventListener('transitionstart', (evt) => {
  7902. showMoreBtnTransitionTrigg = true;
  7903. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7904. if (newVisibility === "visible") {
  7905. const btn = evt.target;
  7906. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7907. }
  7908. });
  7909. btn.addEventListener('transitionend', (evt) => {
  7910. showMoreBtnTransitionTrigg = true;
  7911. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7912. if (newVisibility === "hidden") {
  7913. const btn = evt.target;
  7914. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7915. }
  7916. });
  7917. btn.addEventListener('transitioncancel', (evt) => {
  7918. showMoreBtnTransitionTrigg = true;
  7919. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7920. if (newVisibility === "hidden") {
  7921. const btn = evt.target;
  7922. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7923. }
  7924. });
  7925. }
  7926. }
  7927. */
  7928.  
  7929. // btn-show-more-transition
  7930. if (showMoreBtnTransitionTrigg) return;
  7931.  
  7932. const btn = ((this || 0).$ || 0)["show-more"] || 0;
  7933. if (!btn) return this.atBottomChanged314_();
  7934.  
  7935. const showBtnCurrentState = btn.hasAttribute('disabled');
  7936. if (showBtnLastState === showBtnCurrentState) return;
  7937. showBtnLastState = showBtnCurrentState;
  7938.  
  7939. if (this.visibleItems.length === 0) {
  7940. if (this.atBottom === true) {
  7941. btn.setAttribute('disabled', '');
  7942. showBtnLastState = true;
  7943. }
  7944. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7945. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7946. return;
  7947. }
  7948.  
  7949. nextBrowserTick_(() => {
  7950.  
  7951. if (showMoreBtnTransitionTrigg) return;
  7952.  
  7953. // fallback
  7954.  
  7955. // const isAtBottom = this.atBottom === true;
  7956. // if (isAtBottom) {
  7957. // if (!this.hideShowMoreAsync_) {
  7958. // this.hideShowMoreAsync_ = setTimeoutX0(function () {
  7959. // const btn = ((this || 0).$ || 0)["#show-more"] || 0;
  7960. // if (btn) btn.style.visibility = "hidden";
  7961. // }, 200 - 0.125);
  7962. // }
  7963. // } else {
  7964. // if (this.hideShowMoreAsync_) {
  7965. // clearTimeoutX0(this.hideShowMoreAsync_);
  7966. // this.hideShowMoreAsync_ = null;
  7967. // }
  7968. // const btn = ((this || 0).$ || 0)["#show-more"] || 0;
  7969. // if (btn) btn.style.visibility = "visible";
  7970. // }
  7971.  
  7972. const btn = ((this || 0).$ || 0)["show-more"] || 0;
  7973. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7974.  
  7975. if (newVisibility === "hidden") {
  7976. console.warn('show-more-btn no transition')
  7977. }
  7978.  
  7979. if (btn && btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7980.  
  7981. });
  7982.  
  7983. };
  7984.  
  7985. }
  7986.  
  7987.  
  7988.  
  7989. if ((_flag0281_ & 0x2) == 0) {
  7990. if ((mclp.handleLiveChatActions_ || 0).length === 1) {
  7991.  
  7992. const sfi = fnIntegrity(mclp.handleLiveChatActions_);
  7993. // handleLiveChatActions66_
  7994. if (sfi === '1.40.20') {
  7995. // https://www.youtube.com/s/desktop/c01ea7e3/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  7996.  
  7997.  
  7998. // f.handleLiveChatActions_ = function(a) {
  7999. // var b = this;
  8000. // a.length && (a.forEach(this.handleLiveChatAction_, this),
  8001. // this.maybeResizeScrollContainer_(a),
  8002. // this.flushActiveItems_(),
  8003. // $u(function() {
  8004. // b.maybeScrollToBottom_()
  8005. // }))
  8006. // }
  8007.  
  8008. } else if (sfi === '1.39.20') {
  8009. // TBC
  8010. } else if (sfi === '1.31.17') {
  8011. // original
  8012. } else if (mclp.handleLiveChatActions3641_){
  8013. } else {
  8014. assertor(() => fnIntegrity(mclp.handleLiveChatActions_, '1.40.20'))
  8015. || logFn('mclp.handleLiveChatActions_', mclp.handleLiveChatActions_)();
  8016. }
  8017.  
  8018. mclp.handleLiveChatActions66_ = mclp.handleLiveChatActions_;
  8019.  
  8020. mclp.handleLiveChatActions_ = function (arr) {
  8021.  
  8022. try {
  8023. preprocessChatLiveActions(arr);
  8024. } catch (e) {
  8025. console.warn(e);
  8026. }
  8027.  
  8028. this.handleLiveChatActions66_(arr);
  8029.  
  8030. resistanceUpdateFn_(true);
  8031. }
  8032. console1.log("handleLiveChatActions_", "OK");
  8033. } else {
  8034. console1.log("handleLiveChatActions_", "NG");
  8035. }
  8036. }
  8037.  
  8038. // we do not need to do user interaction check for Boost Chat (0x40000)
  8039. const noScrollToBottomCheckForBoostChat = (_flag0281_ & 0x40000) === 0x40000;
  8040.  
  8041. if (noScrollToBottomCheckForBoostChat === false) {
  8042.  
  8043. mclp.hasUserJustInteracted11_ = () => {
  8044. const t = dateNow();
  8045. return (t - lastWheel < 80) || currentMouseDown || currentTouchDown || (t - lastUserInteraction < 80);
  8046. }
  8047.  
  8048. if ((mclp.canScrollToBottom_ || 0).length === 0 && !mclp.canScrollToBottom157_) {
  8049.  
  8050. assertor(() => fnIntegrity(mclp.canScrollToBottom_, '0.9.5'));
  8051.  
  8052. mclp.canScrollToBottom157_ = mclp.canScrollToBottom_;
  8053. mclp.canScrollToBottom_ = function () {
  8054. return this.canScrollToBottom157_() && !this.hasUserJustInteracted11_();
  8055. }
  8056.  
  8057. console1.log("canScrollToBottom_", "OK");
  8058.  
  8059.  
  8060. } else {
  8061. console1.log("canScrollToBottom_", "NG");
  8062. }
  8063.  
  8064. }
  8065.  
  8066. if (ENABLE_NO_SMOOTH_TRANSFORM) {
  8067.  
  8068. mclp.isSmoothScrollEnabled_ = function () {
  8069. return false;
  8070. }
  8071.  
  8072. mclp.maybeResizeScrollContainer_ = function () {
  8073. //
  8074. }
  8075.  
  8076. mclp.refreshOffsetContainerHeight_ = function () {
  8077. //
  8078. }
  8079.  
  8080. mclp.smoothScroll_ = function () {
  8081. //
  8082. }
  8083.  
  8084. mclp.resetSmoothScroll_ = function () {
  8085. //
  8086. }
  8087. console1.log("ENABLE_NO_SMOOTH_TRANSFORM", "OK");
  8088. } else {
  8089. console1.log("ENABLE_NO_SMOOTH_TRANSFORM", "NG");
  8090. }
  8091.  
  8092. if ((_flag0281_ & 0x8) == 0) {
  8093.  
  8094.  
  8095. if (typeof mclp.forEachItem_ === 'function' && !mclp.forEachItem66_ && skipErrorForhandleAddChatItemAction_ && mclp.forEachItem_.length === 1) {
  8096.  
  8097. mclp.forEachItem66_ = mclp.forEachItem_;
  8098. mclp.forEachItem_ = function (a) {
  8099.  
  8100. if ((this._flag0281_ & 0x8) == 0x8) return this.forEachItem66_(a);
  8101.  
  8102. // ƒ (a){this.visibleItems.forEach(a.bind(this,"visibleItems"));this.activeItems_.forEach(a.bind(this,"activeItems_"))}
  8103.  
  8104. try {
  8105.  
  8106. let items801 = false;
  8107. if (typeof a === 'function') {
  8108. const items = this.items;
  8109. if (items instanceof HTMLDivElement) {
  8110. const ev = this.visibleItems;
  8111. const ea = this.activeItems_;
  8112. if (ev && ea && ev.length >= 0 && ea.length >= 0) {
  8113. items801 = items;
  8114. }
  8115. }
  8116. }
  8117.  
  8118. if (items801) {
  8119. items801.__children801__ = 1;
  8120. const res = this.forEachItem66_(a);
  8121. items801.__children801__ = 0;
  8122. return res;
  8123. }
  8124.  
  8125. } catch (e) { }
  8126. return this.forEachItem66_(a);
  8127.  
  8128.  
  8129. // this.visibleItems.forEach((val, idx, arr)=>{
  8130. // a.call(this, 'visibleItems', val, idx, arr);
  8131. // });
  8132.  
  8133. // this.activeItems_.forEach((val, idx, arr)=>{
  8134. // a.call(this, 'activeItems_', val, idx, arr);
  8135. // });
  8136.  
  8137.  
  8138.  
  8139. }
  8140.  
  8141.  
  8142. }
  8143.  
  8144. }
  8145.  
  8146. if (typeof mclp.handleAddChatItemAction_ === 'function' && !mclp.handleAddChatItemAction66_ && FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION && (EMOJI_IMAGE_SINGLE_THUMBNAIL || AUTHOR_PHOTO_SINGLE_THUMBNAIL)) {
  8147.  
  8148. mclp.handleAddChatItemAction66_ = mclp.handleAddChatItemAction_;
  8149. mclp.handleAddChatItemAction_ = function (a) {
  8150. try {
  8151. if (a && typeof a === 'object' && !('length' in a)) {
  8152. fixLiveChatItem(a.item, null);
  8153. console.assert(arguments[0] === a);
  8154. }
  8155. } catch (e) { console.warn(e) }
  8156. let res;
  8157. if (skipErrorForhandleAddChatItemAction_) { // YouTube Native Engine Issue
  8158. try {
  8159. res = this.handleAddChatItemAction66_.apply(this, arguments);
  8160. } catch (e) {
  8161. if (e && (e.message || '').includes('.querySelector(')) {
  8162. console.log("skipErrorForhandleAddChatItemAction_", e.message);
  8163. } else {
  8164. throw e;
  8165. }
  8166. }
  8167. } else {
  8168. res = this.handleAddChatItemAction66_.apply(this, arguments);
  8169. }
  8170. return res;
  8171. }
  8172.  
  8173. if (FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION) console1.log("handleAddChatItemAction_ [ FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION ]", "OK");
  8174. } else {
  8175.  
  8176. if (FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION) console1.log("handleAddChatItemAction_ [ FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION ]", "OK");
  8177. }
  8178.  
  8179.  
  8180. if (typeof mclp.handleReplaceChatItemAction_ === 'function' && !mclp.handleReplaceChatItemAction66_ && FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT && (EMOJI_IMAGE_SINGLE_THUMBNAIL || AUTHOR_PHOTO_SINGLE_THUMBNAIL)) {
  8181.  
  8182. mclp.handleReplaceChatItemAction66_ = mclp.handleReplaceChatItemAction_;
  8183. mclp.handleReplaceChatItemAction_ = function (a) {
  8184. try {
  8185. if (a && typeof a === 'object' && !('length' in a)) {
  8186. fixLiveChatItem(a.replacementItem, null);
  8187. console.assert(arguments[0] === a);
  8188. }
  8189. } catch (e) { console.warn(e) }
  8190. return this.handleReplaceChatItemAction66_.apply(this, arguments);
  8191. }
  8192.  
  8193. if (FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT) console1.log("handleReplaceChatItemAction_ [ FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT ]", "OK");
  8194. } else {
  8195.  
  8196. if (FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT) console1.log("handleReplaceChatItemAction_ [ FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT ]", "OK");
  8197. }
  8198.  
  8199. console1.log("[End]");
  8200. groupEnd();
  8201.  
  8202. }).catch(console.warn);
  8203.  
  8204.  
  8205. const tickerContainerSetAttribute = function (attrName, attrValue) { // ensure '14.30000001%'.toFixed(1)
  8206.  
  8207. let yd = (this.__dataHost || insp(this).__dataHost || 0).__data;
  8208.  
  8209. if (arguments.length === 2 && attrName === 'style' && yd && attrValue) {
  8210.  
  8211. // let v = yd.containerStyle.privateDoNotAccessOrElseSafeStyleWrappedValue_;
  8212. let v = `${attrValue}`;
  8213. // conside a ticker is 101px width
  8214. // 1% = 1.01px
  8215. // 0.2% = 0.202px
  8216.  
  8217.  
  8218. const ratio1 = (yd.ratio * 100);
  8219. if (ratio1 > -1) { // avoid NaN
  8220.  
  8221. // countdownDurationMs
  8222. // 600000 - 0.2% <1% = 6s> <0.2% = 1.2s>
  8223. // 300000 - 0.5% <1% = 3s> <0.5% = 1.5s>
  8224. // 150000 - 1% <1% = 1.5s>
  8225. // 75000 - 2% <1% =0.75s > <2% = 1.5s>
  8226. // 30000 - 5% <1% =0.3s > <5% = 1.5s>
  8227.  
  8228. // 99px * 5% = 4.95px
  8229.  
  8230. // 15000 - 10% <1% =0.15s > <10% = 1.5s>
  8231.  
  8232.  
  8233. // 1% Duration
  8234.  
  8235. let ratio2 = ratio1;
  8236.  
  8237. const ydd = yd.data;
  8238. if (ydd) {
  8239.  
  8240. const d1 = ydd.durationSec;
  8241. const d2 = ydd.fullDurationSec;
  8242.  
  8243. // @ step timing [min. 0.2%]
  8244. let numOfSteps = 500;
  8245. if ((d1 === d2 || (d1 + 1 === d2)) && d1 > 1) {
  8246. if (d2 > 400) numOfSteps = 500; // 0.2%
  8247. else if (d2 > 200) numOfSteps = 200; // 0.5%
  8248. else if (d2 > 100) numOfSteps = 100; // 1%
  8249. else if (d2 > 50) numOfSteps = 50; // 2%
  8250. else if (d2 > 25) numOfSteps = 20; // 5% (max => 99px * 5% = 4.95px)
  8251. else numOfSteps = 20;
  8252. }
  8253. if (numOfSteps > TICKER_MAX_STEPS_LIMIT) numOfSteps = TICKER_MAX_STEPS_LIMIT;
  8254. if (numOfSteps < 5) numOfSteps = 5;
  8255.  
  8256. const rd = numOfSteps / 100.0;
  8257.  
  8258. ratio2 = Math.round(ratio2 * rd) / rd;
  8259.  
  8260. // ratio2 = Math.round(ratio2 * 5) / 5;
  8261. ratio2 = ratio2.toFixed(1);
  8262. v = v.replace(`${ratio1}%`, `${ratio2}%`).replace(`${ratio1}%`, `${ratio2}%`);
  8263.  
  8264. if (yd.__style_last__ === v) return;
  8265. yd.__style_last__ = v;
  8266. // do not consider any delay here.
  8267. // it shall be inside the looping for all properties changes. all the css background ops are in the same microtask.
  8268.  
  8269. }
  8270. }
  8271.  
  8272. HTMLElement_.prototype.setAttribute.call(dr(this), attrName, v);
  8273.  
  8274.  
  8275. } else {
  8276. HTMLElement_.prototype.setAttribute.apply(dr(this), arguments);
  8277. }
  8278.  
  8279. };
  8280.  
  8281.  
  8282. const fpTicker = (renderer) => {
  8283. const cnt = insp(renderer);
  8284. assertor(() => typeof (cnt || 0).is === 'string');
  8285. assertor(() => ((cnt || 0).hostElement || 0).nodeType === 1);
  8286. const container = (cnt.$ || 0).container;
  8287. if (container) {
  8288. assertor(() => (container || 0).nodeType === 1);
  8289. assertor(() => typeof container.setAttribute === 'function');
  8290. container.setAttribute = tickerContainerSetAttribute;
  8291. } else {
  8292. console.warn(`"container" does not exist in ${cnt.is}`);
  8293. }
  8294. };
  8295.  
  8296.  
  8297. const tags = [
  8298. "yt-live-chat-ticker-renderer",
  8299. "yt-live-chat-ticker-paid-message-item-renderer",
  8300. "yt-live-chat-ticker-paid-sticker-item-renderer",
  8301. "yt-live-chat-ticker-sponsor-item-renderer"
  8302. ];
  8303.  
  8304. const tagsItemRenderer = [
  8305. "yt-live-chat-ticker-renderer",
  8306. "yt-live-chat-ticker-paid-message-item-renderer",
  8307. "yt-live-chat-ticker-paid-sticker-item-renderer",
  8308. "yt-live-chat-ticker-sponsor-item-renderer"
  8309. ];
  8310.  
  8311. // const wmList = new Set;
  8312.  
  8313. true && (new MutationObserver((mutations) => {
  8314.  
  8315. const s = new Set();
  8316. for (const mutation of mutations) {
  8317. if (mutation.type === 'attributes') {
  8318. s.add(mutation.target);
  8319. }
  8320. }
  8321. for (const target of s) {
  8322. const p = target && target.isConnected === true ? target.getAttribute('q92wb') : '';
  8323. if (p === '1') {
  8324. target.setAttribute('q92wb', '2');
  8325. const cnt = insp(target);
  8326. const dataId = ((cnt || 0).data || 0).id;
  8327. if (cnt && typeof cnt.requestRemoval49 === 'function' && dataId) {
  8328. target.id = dataId;
  8329. cnt.requestRemoval49();
  8330. target.setAttribute('q92wb', '3');
  8331. }
  8332. } else if (p === '3') {
  8333. target.setAttribute('q92wb', '4');
  8334. const cnt = insp(target);
  8335. const dataId = ((cnt || 0).data || 0).id;
  8336. if (cnt && typeof cnt.requestRemoval49 === 'function' && dataId) {
  8337. target.id = dataId;
  8338. const parentComponent = target.closest('yt-live-chat-ticker-renderer') || cnt.parentComponent;
  8339. const parentCnt = insp(parentComponent);
  8340. if(parentComponent && parentCnt && parentCnt.removeTickerItemById){
  8341. parentCnt.removeTickerItemById(dataId);
  8342. target.setAttribute('q92wb', '5');
  8343. }
  8344. }
  8345. }
  8346. }
  8347. s.clear();
  8348.  
  8349. })).observe(document, { attributes: true, attributeFilter: ['q92wb'], subtree: true });
  8350.  
  8351. Promise.all(tags.map(tag => customElements.whenDefined(tag))).then(() => {
  8352.  
  8353. mightFirstCheckOnYtInit();
  8354. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-ticker-... hacks");
  8355. console1.log("[Begin]");
  8356.  
  8357.  
  8358. let tickerAttachmentId = 0;
  8359.  
  8360.  
  8361. const __requestRemoval__ = function (cnt) {
  8362. if (cnt.hostElement && typeof cnt.requestRemoval === 'function') {
  8363. try {
  8364. const id = (cnt.data || 0).id;
  8365. if (!id) cnt.data = { id: 1 };
  8366. } catch (e) { }
  8367. try {
  8368. cnt.requestRemoval();
  8369. return true;
  8370. } catch (e) { }
  8371. }
  8372. return false;
  8373. }
  8374.  
  8375.  
  8376. const overlayBgMap = new WeakMap();
  8377.  
  8378. const dProto = {
  8379.  
  8380.  
  8381. /**
  8382. *
  8383.  
  8384. f.updateStatsBarAndMaybeShowAnimation = function(a, b, c) {
  8385. var d = this;
  8386. a || c();
  8387. a && this.statsBar && this.username && this.textContent && (this.isMouseOver ? (b(),
  8388. c()) : (a = this.animateShowStats(),
  8389. this.data.animationOrigin && this.data.trackingParams && aB().stateChanged(this.data.trackingParams, {
  8390. animationEventData: {
  8391. origin: this.data.animationOrigin
  8392. }
  8393. }),
  8394. a.finished.then(function() {
  8395. var e;
  8396. setTimeout(function() {
  8397. b();
  8398. c();
  8399. if (!d.isMouseOver) {
  8400. var g, k;
  8401. d.animateHideStats(((g = d.data) == null ? void 0 : g.dynamicStateData.stateSlideDurationMs) || 0, ((k = d.data) == null ? void 0 : k.dynamicStateData.stateUpdateDelayAfterMs) || 0)
  8402. }
  8403. }, ((e = d.data) == null ? void 0 : e.dynamicStateData.stateUpdateDelayBeforeMs) || 0)
  8404. })))
  8405. }
  8406.  
  8407. *
  8408. */
  8409.  
  8410.  
  8411.  
  8412. /**
  8413. *
  8414. *
  8415.  
  8416. f.animateShowStats = function() {
  8417. var a = this.textContent.animate({
  8418. transform: "translateY(-30px)"
  8419. }, {
  8420. duration: this.data.dynamicStateData.stateSlideDurationMs,
  8421. fill: "forwards"
  8422. });
  8423. this.username.animate({
  8424. opacity: 0
  8425. }, {
  8426. duration: 500,
  8427. fill: "forwards"
  8428. });
  8429. this.statsBar.animate({
  8430. opacity: 1
  8431. }, {
  8432. duration: 500,
  8433. fill: "forwards"
  8434. });
  8435. return a
  8436. }
  8437. ;
  8438. f.animateHideStats = function(a, b) {
  8439. this.textContent.animate({
  8440. transform: "translateY(0)"
  8441. }, {
  8442. duration: a,
  8443. fill: "forwards",
  8444. delay: b
  8445. });
  8446. this.username.animate({
  8447. opacity: 1
  8448. }, {
  8449. duration: 300,
  8450. fill: "forwards",
  8451. delay: b
  8452. });
  8453. this.statsBar.animate({
  8454. opacity: 0
  8455. }, {
  8456. duration: 300,
  8457. fill: "forwards",
  8458. delay: b
  8459. })
  8460. }
  8461. *
  8462. */
  8463.  
  8464. updateStatsBarAndMaybeShowAnimationRevised: function (a, b, c) {
  8465. // prevent memory leakage due to d.data was asked in a.finished.then
  8466. try{
  8467. // console.log('updateStatsBarAndMaybeShowAnimation called', this.is)
  8468. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8469. return this.updateStatsBarAndMaybeShowAnimation38.call(this.__proxySelf0__, a, b, c);
  8470. }catch(e){
  8471. console.log('updateStatsBarAndMaybeShowAnimationRevised ERROR');
  8472. console.error(e);
  8473. }
  8474. },
  8475.  
  8476. detachedForMemoryLeakage: function () {
  8477.  
  8478. try{
  8479.  
  8480. this.actionHandlerBehavior.unregisterActionMap(this.behaviorActionMap)
  8481.  
  8482. // this.behaviorActionMap = 0;
  8483. // this.isVisibilityRoot = 0;
  8484.  
  8485.  
  8486. }catch(e){}
  8487.  
  8488. return this.detached582MemoryLeak();
  8489. },
  8490.  
  8491. detachedForTickerInit: function () {
  8492.  
  8493. Promise.resolve(this).then((cnt) => {
  8494. if (cnt.isAttached) return;
  8495. cnt.isAttached === false && ((cnt.$ || 0).container || 0).isConnected === false && __requestRemoval__(cnt);
  8496. cnt.rafId > 1 && rafHub.cancel(cnt.rafId);
  8497. }).catch(console.warn);
  8498.  
  8499.  
  8500. const hostElement = (this || 0).hostElement;
  8501. if (USE_ADVANCED_TICKING && (this || 0).__isTickerItem58__ && hostElement instanceof HTMLElement_) {
  8502. // otherwise the startCountDown not working
  8503. hostElement.style.removeProperty('--ticker-start-time');
  8504. hostElement.style.removeProperty('--ticker-duration-time');
  8505.  
  8506. if (kRef(qWidthAdjustable) === hostElement) {
  8507.  
  8508. // need to update the first ticker
  8509. const q = document.querySelector('.r6-width-adjustable');
  8510. if (q instanceof HTMLElement_ && q.classList.contains('r6-width-adjustable-f')) {
  8511. q.classList.remove('r6-width-adjustable-f');
  8512. }
  8513. qWidthAdjustable = mWeakRef(q);
  8514.  
  8515. }
  8516. }
  8517.  
  8518. let r;
  8519. try {
  8520. r = this.detached77();
  8521. } catch (e) {
  8522. console.warn(e);
  8523. }
  8524. this.__ticker_attachmentId__ = 0;
  8525. return r;
  8526. },
  8527.  
  8528. attachedForTickerInit: function () {
  8529. this.__ticker_attachmentId__ = tickerAttachmentId = (tickerAttachmentId & 1073741823) + 1;
  8530.  
  8531. const hostElement = (this || 0).hostElement;
  8532. if (USE_ADVANCED_TICKING && (this || 0).__isTickerItem58__ && hostElement instanceof HTMLElement_) {
  8533. const prevElement = kRef(qWidthAdjustable);
  8534. if (prevElement instanceof HTMLElement_) {
  8535. prevElement.classList.add('r6-width-adjustable-f');
  8536. }
  8537. if (hostElement.__fgvm573__) {
  8538. hostElement.classList.remove('r6-closing-ticker');
  8539. hostElement.classList.remove('r6-width-adjustable-f');
  8540. } else {
  8541. hostElement.__fgvm573__ = 1;
  8542. hostElement.classList.add('r6-width-adjustable');
  8543. }
  8544. qWidthAdjustable = mWeakRef(hostElement);
  8545. }
  8546.  
  8547.  
  8548. fpTicker(hostElement || this);
  8549. return this.attached77();
  8550.  
  8551. },
  8552.  
  8553.  
  8554.  
  8555. setContainerWidthNoSelfLeakage: function(){
  8556. // prevent memory leakage due ot delay function
  8557. try{
  8558. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8559. return this.setContainerWidth55.call(this.__proxySelf0__);
  8560. }catch(e){
  8561. console.log('setContainerWidthNoSelfLeakage ERROR');
  8562. console.error(e);
  8563. }
  8564.  
  8565. },
  8566.  
  8567. slideDownNoSelfLeakage: function(){
  8568. // prevent memory leakage due ot delay function
  8569. try{
  8570. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8571. return this.slideDown55.call(this.__proxySelf0__);
  8572. }catch(e){
  8573. console.log('slideDownNoSelfLeakage ERROR');
  8574. console.error(e);
  8575. }
  8576.  
  8577. },
  8578.  
  8579. collapseNoSelfLeakage: function(){
  8580. // prevent memory leakage due ot delay function
  8581. try{
  8582. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8583. return this.collapse55.call(this.__proxySelf0__);
  8584. }catch(e){
  8585. console.log('collapseNoSelfLeakage ERROR');
  8586. console.error(e);
  8587. }
  8588. },
  8589.  
  8590. deletedChangedNoSelfLeakage: function(){
  8591. // prevent memory leakage due ot delay function
  8592. try{
  8593. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8594. return this.deletedChanged55.call(this.__proxySelf0__);
  8595. }catch(e){
  8596. console.log('deletedChangedNoSelfLeakage ERROR');
  8597. console.error(e);
  8598. }
  8599.  
  8600. },
  8601.  
  8602.  
  8603.  
  8604.  
  8605. /** @type {()} */
  8606. handlePauseReplayForPlaybackProgressState: function () {
  8607. if (!playerEventsByIframeRelay) return this.handlePauseReplay66.apply(this, arguments);
  8608.  
  8609. const attachementId = this.__ticker_attachmentId__;
  8610. if(!attachementId) return;
  8611.  
  8612. const jr = mWeakRef(this);
  8613.  
  8614. if (onPlayStateChangePromise) {
  8615.  
  8616. const tid = this._Y7rtu = (this._Y7rtu & 1073741823) + 1;
  8617.  
  8618. onPlayStateChangePromise.then(() => {
  8619. const cnt = kRef(jr) || 0;
  8620. if (attachementId !== cnt.__ticker_attachmentId__) return;
  8621. if (cnt.isAttached) {
  8622. if (tid === cnt._Y7rtu && !onPlayStateChangePromise && typeof cnt.handlePauseReplay === 'function' && cnt.hostElement) cnt.handlePauseReplay.apply(cnt, arguments);
  8623. // this.handlePauseReplay can be undefined if it is memory cleaned
  8624. }
  8625. });
  8626.  
  8627. return;
  8628. }
  8629.  
  8630. if (playerState !== 2) return;
  8631. if (this.isAttached) {
  8632. const tid = this._Y7rtk = (this._Y7rtk & 1073741823) + 1;
  8633. const tc = relayCount;
  8634. foregroundPromiseFn().then(() => {
  8635. const cnt = kRef(jr);
  8636. if (attachementId !== (cnt || 0).__ticker_attachmentId__) return;
  8637. if (cnt.isAttached) {
  8638. if (tid === cnt._Y7rtk && tc === relayCount && playerState === 2 && _playerState === playerState && cnt.hostElement) {
  8639. cnt.handlePauseReplay66();
  8640. }
  8641. }
  8642. })
  8643. }
  8644. },
  8645.  
  8646. /** @type {()} */
  8647. handleResumeReplayForPlaybackProgressState: function () {
  8648. if (!playerEventsByIframeRelay) return this.handleResumeReplay66.apply(this, arguments);
  8649.  
  8650. const attachementId = this.__ticker_attachmentId__;
  8651. if(!attachementId) return;
  8652.  
  8653. const jr = mWeakRef(this);
  8654. if (onPlayStateChangePromise) {
  8655.  
  8656. const tid = this._Y7rtv = (this._Y7rtv & 1073741823) + 1;
  8657.  
  8658. onPlayStateChangePromise.then(() => {
  8659. const cnt = kRef(jr);
  8660. if(attachementId !== (cnt || 0).__ticker_attachmentId__) return;
  8661. if (tid === cnt._Y7rtv && !onPlayStateChangePromise && typeof cnt.handleResumeReplay === 'function' && cnt.hostElement) cnt.handleResumeReplay.apply(cnt, arguments);
  8662. // this.handleResumeReplay can be undefined if it is memory cleaned
  8663. });
  8664.  
  8665. return;
  8666. }
  8667.  
  8668.  
  8669. if (playerState !== 1) return;
  8670. if (this.isAttached) {
  8671. const tc = relayCount;
  8672.  
  8673. relayPromise = relayPromise || new PromiseExternal();
  8674. relayPromise.then(() => {
  8675. const cnt = kRef(jr);
  8676. if(attachementId !== (cnt || 0).__ticker_attachmentId__) return;
  8677. if (relayCount > tc && playerState === 1 && _playerState === playerState && cnt.hostElement) {
  8678. cnt.handleResumeReplay66();
  8679. }
  8680. });
  8681. }
  8682. },
  8683.  
  8684. /** @type {(a,)} */
  8685. handleReplayProgressForPlaybackProgressState: function (a) {
  8686. if (this.isAttached) {
  8687. const attachementId = this.__ticker_attachmentId__;
  8688. if(!attachementId) return;
  8689. const tid = this._Y7rtk = (this._Y7rtk & 1073741823) + 1;
  8690. const jr = mWeakRef(kRef(this));
  8691. foregroundPromiseFn().then(() => {
  8692. const cnt = kRef(jr);
  8693. if(attachementId !== (cnt || 0).__ticker_attachmentId__) return;
  8694. if (cnt.isAttached) {
  8695. if (tid === cnt._Y7rtk && cnt.hostElement) {
  8696. cnt.handleReplayProgress66(a);
  8697. }
  8698. }
  8699. })
  8700. }
  8701. }
  8702.  
  8703.  
  8704. }
  8705.  
  8706.  
  8707.  
  8708. const isTickerItemsScrolling = function () {
  8709. const elm = document.querySelector('#ticker-bar.yt-live-chat-ticker-renderer');
  8710. if (!elm) return false;
  8711. return (elm.scrollLeft > 0);
  8712. }
  8713.  
  8714.  
  8715.  
  8716.  
  8717. const u37fn = function (cnt) {
  8718.  
  8719. if (cnt.__dataEnabled === false || cnt.__dataInvalid === true) return;
  8720.  
  8721. if (!__LCRInjection__) {
  8722. console.error('[yt-chat] USE_ADVANCED_TICKING fails because of no __LCRInjection__');
  8723. }
  8724.  
  8725. const cntData = ((cnt || 0).__data || 0).data || (cnt || 0).data || 0;
  8726. if (!cntData) return;
  8727. const cntElement = cnt.hostElement;
  8728. if (!(cntElement instanceof HTMLElement_)) return;
  8729.  
  8730. const duration = (cntData.fullDurationSec || cntData.durationSec || 0);
  8731.  
  8732. let ct;
  8733.  
  8734. if (__LCRInjection__ && cntData && duration > 0 && !('__progressAt__' in cntData)) {
  8735. ct = Date.now();
  8736.  
  8737. if (!cntData.__timestampActionRequest__) {
  8738. console.log(' 5688001 ');
  8739. // console.log(`(5688001) ${new Error().stack}`);
  8740. }
  8741. cntData.__liveTimestamp__ = (((cntData.__timestampActionRequest__ || ct) - timeOriginDT) / 1000) || Number.MIN_VALUE;
  8742. timestampUnderLiveMode = true;
  8743. } else if (__LCRInjection__ && cntData && duration > 0 && cntData.__progressAt__ > 0) {
  8744. timestampUnderLiveMode = false;
  8745. }
  8746. // console.log(48117007, cntData)
  8747.  
  8748. let tk = cntData.__progressAt__ || cntData.__liveTimestamp__;
  8749.  
  8750. if (!tk) {
  8751. console.log('time property is not found', !!__LCRInjection__, !!cntData, !!(duration > 0), !('__progressAt__' in cntData), cntData.__progressAt__, cntData.__liveTimestamp__);
  8752. return;
  8753. }
  8754.  
  8755.  
  8756.  
  8757. const liveOffsetMs = ct > 0 && cntData.__timestampActionRequest__ > 0 ? ct - cntData.__timestampActionRequest__ : 0;
  8758.  
  8759. // console.log(1237, liveOffsetMs, cntData.durationSec)
  8760.  
  8761. if (liveOffsetMs > 0) {
  8762. cntData.durationSec -= Math.floor(liveOffsetMs / 1000);
  8763. if (cntData.durationSec < 0) cntData.durationSec = 0;
  8764. // console.log(1238, liveOffsetMs, cntData.durationSec)
  8765. if (!cntData.durationSec) {
  8766. try {
  8767. cnt.requestRemoval();
  8768. } catch (e) { }
  8769. return;
  8770. }
  8771. }
  8772.  
  8773.  
  8774. let offset = cntData.fullDurationSec - cntData.durationSec; // consider this is live replay video, offset can be > 0
  8775. if (offset > 0) tk -= offset;
  8776. // in livestreaming. tk can be negative as we use performance.timeOrigin for t=0s time frame
  8777.  
  8778.  
  8779.  
  8780. const existingOverlaySelector = `ticker-bg-overlay[ticker-id="${cnt.__ticker_attachmentId__}"]`;
  8781.  
  8782. const q = kRef(overlayBgMap.get(cnt));
  8783.  
  8784. let r = valAssign(cntElement, '--ticker-start-time', tk);
  8785.  
  8786. if ((r || !q || q.isConnected === false) && duration > 0) {
  8787.  
  8788. // t0 ...... 1 ... fullDurationSec
  8789. // tk ...... k ... fullDurationSec-durationSec
  8790. // t0-fullDurationSec ...... 0 ... 0
  8791.  
  8792. // now - (fullDurationSec-durationSec)
  8793.  
  8794.  
  8795. // update dntElementWeak
  8796. const dnt = cnt.parentComponent;
  8797. const dntElement = dnt ? dnt.hostElement || dnt : 0;
  8798. if (dntElement) {
  8799. dntElementWeak = mWeakRef(dntElement);
  8800. resistanceUpdateBusy = false;
  8801. if (!startResistanceUpdaterStarted) startResistanceUpdater();
  8802. else updateTickerCurrentTime();
  8803. }
  8804.  
  8805.  
  8806. // create overlay if needed
  8807. if (!cntElement.querySelector(existingOverlaySelector)) {
  8808.  
  8809. // remove if any
  8810. const oldElement = cntElement.querySelector('ticker-bg-overlay');
  8811. if (oldElement) oldElement.remove();
  8812.  
  8813. // use advancedTicking, ticker enabled
  8814. cnt.__advancedTicking038__ = 1;
  8815.  
  8816. const em = q || document.createElement('ticker-bg-overlay');
  8817.  
  8818. overlayBgMap.set(cnt, mWeakRef(em));
  8819. // const ey = document.createElement('ticker-bg-overlay-end');
  8820. const wy = document.createElement('ticker-bg-overlay-end2');
  8821.  
  8822. const cr1 = cnt.colorFromDecimal(cntData.startBackgroundColor);
  8823. const cr2 = cnt.colorFromDecimal(cntData.endBackgroundColor);
  8824.  
  8825. const container = cnt.$.container;
  8826.  
  8827. em.setAttribute('ticker-id', `${cnt.__ticker_attachmentId__}`);
  8828.  
  8829. const tid = `ticker-${cnt.__ticker_attachmentId__}-${Math.floor(Math.random() * 314159265359 + 314159265359).toString(36)}`;
  8830.  
  8831. em.id = `${tid}-b`;
  8832. em.style.background = `linear-gradient(90deg, ${cr1},${cr1} 50%,${cr2} 50%,${cr2})`;
  8833.  
  8834. if (!(container instanceof HTMLElement_)) {
  8835. // em.insertBefore(ey, em.firstChild);
  8836. insertBeforeNaFn(cntElement, em, cntElement.firstChild); // cntElement.insertBefore(em, cntElement.firstChild);
  8837. cntElement.style.borderRadius = '16px';
  8838. container.style.borderRadius = 'initial';
  8839. } else {
  8840. // em.insertBefore(ey, em.firstChild);
  8841. insertBeforeNaFn(container, em, container.firstChild); // container.insertBefore(em, container.firstChild);
  8842. }
  8843.  
  8844. // em.style.left = '-50%';
  8845. // em.style.left = "clamp(-100%, calc( -100% * ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) ), 0%)";
  8846.  
  8847. if (container instanceof HTMLElement_) {
  8848.  
  8849. container.style.background = 'transparent';
  8850. container.style.backgroundColor = 'transparent';
  8851. // container.style.zIndex = '1';
  8852. }
  8853. // em.style.zIndex = '-1';
  8854. valAssign(cntElement, '--ticker-duration-time', duration)
  8855.  
  8856. valAssign(wy, '--ticker-start-time', tk);
  8857. valAssign(wy, '--ticker-duration-time', duration);
  8858. wy.id = `${tid}-e`;
  8859.  
  8860. appendChildNaFn(dntElement, wy);
  8861.  
  8862. // if (wio instanceof IntersectionObserver) {
  8863. // wio.observe(ey);
  8864. // }
  8865.  
  8866. const wio2 = dProto.wio2;
  8867. if (wio2 instanceof IntersectionObserver) {
  8868. wio2.observe(wy);
  8869. }
  8870.  
  8871. }
  8872. }
  8873. };
  8874.  
  8875.  
  8876.  
  8877. const timeFn749 = (cnt) => {
  8878. cnt = kRef(cnt);
  8879. if (!cnt) return;
  8880. cnt.__startCountdownAdv477__ = Date.now();
  8881.  
  8882. if (
  8883. cnt
  8884. && (cnt.hostElement && cnt.isAttached && cnt.hostElement.isConnected)
  8885. && cnt.parentComponent // startCountdown is triggered by dataChanged; // not yet attached to the actual dom tree
  8886. && cnt.__ticker_attachmentId__
  8887. ) {
  8888.  
  8889. const data = cnt.data;
  8890. const dataId = data ? ((cnt || 0).data || 0).id : null;
  8891. const elemId = ((cnt || 0).hostElement || 0).id;
  8892.  
  8893. if (dataId && dataId === elemId) {
  8894.  
  8895. const attachId = cnt.__ticker_attachmentId__;
  8896. const uid = `${attachId}!${dataId}`;
  8897.  
  8898. if (data.__wsi6c__ !== uid) {
  8899. data.__wsi6c__ = uid;
  8900. Promise.resolve(cnt).then(u37fn);
  8901. return true;
  8902. }
  8903.  
  8904. }
  8905.  
  8906. }
  8907.  
  8908. return false;
  8909. }
  8910.  
  8911. let tagI = 0;
  8912. for (const tag of tagsItemRenderer) { // ##tag##
  8913.  
  8914. tagI++;
  8915.  
  8916. const dummy = document.createElement(tag);
  8917.  
  8918. const cProto = getProto(dummy);
  8919. if (!cProto || !cProto.attached) {
  8920. console1.warn(`proto.attached for ${tag} is unavailable.`);
  8921. continue;
  8922. }
  8923.  
  8924. if (FIX_MEMORY_LEAKAGE_TICKER_ACTIONMAP && typeof cProto.detached582MemoryLeak !== 'function' && typeof cProto.detached === 'function') {
  8925. cProto.detached582MemoryLeak = cProto.detached;
  8926. cProto.detached = dProto.detachedForMemoryLeakage;
  8927. }
  8928.  
  8929. cProto.detached77 = cProto.detached;
  8930. cProto.detached = dProto.detachedForTickerInit;
  8931.  
  8932. cProto.attached77 = cProto.attached;
  8933.  
  8934. cProto.attached = dProto.attachedForTickerInit;
  8935.  
  8936. let flgLeakageFixApplied = 0;
  8937.  
  8938. if (FIX_MEMORY_LEAKAGE_TICKER_STATSBAR && typeof cProto.updateStatsBarAndMaybeShowAnimation === 'function' && !cProto.updateStatsBarAndMaybeShowAnimation38 && cProto.updateStatsBarAndMaybeShowAnimation.length === 3) {
  8939.  
  8940. cProto.updateStatsBarAndMaybeShowAnimation38 = cProto.updateStatsBarAndMaybeShowAnimation;
  8941. cProto.updateStatsBarAndMaybeShowAnimation = dProto.updateStatsBarAndMaybeShowAnimationRevised;
  8942.  
  8943. flgLeakageFixApplied |= 2;
  8944. } else {
  8945. // the function is only in yt-live-chat-ticker-paid-message-item-renderer
  8946. }
  8947.  
  8948.  
  8949. // ------------- withTimerFn_ -------------
  8950.  
  8951. let withTimerFn_ = 0;
  8952. if (typeof cProto.startCountdown === 'function' && typeof cProto.updateTimeout === 'function' && typeof cProto.isAnimationPausedChanged === 'function') {
  8953.  
  8954. // console.log('startCountdown', typeof cProto.startCountdown)
  8955. // console.log('updateTimeout', typeof cProto.updateTimeout)
  8956. // console.log('isAnimationPausedChanged', typeof cProto.isAnimationPausedChanged)
  8957.  
  8958. // <<< to be reviewed cProto.updateTimeout --- isTimingFunctionHackable -- doHack >>>
  8959. const isTimingFunctionHackable = fnIntegrity(cProto.startCountdown, '2.66.37') && fnIntegrity(cProto.updateTimeout, '1.76.45') && fnIntegrity(cProto.isAnimationPausedChanged, '2.56.30')
  8960. if (!isTimingFunctionHackable) console1.log('isTimingFunctionHackable = false');
  8961. withTimerFn_ = isTimingFunctionHackable ? 2 : 1;
  8962. } else {
  8963. let flag = 0;
  8964. if (typeof cProto.startCountdown === 'function') flag |= 1;
  8965. if (typeof cProto.updateTimeout === 'function') flag |= 2;
  8966. if (typeof cProto.isAnimationPausedChanged === 'function') flag |= 4;
  8967.  
  8968. console1.log(`Skip Timing Function Modification[#${tagI}]: ${flag} / ${1 + 2 + 4}`, ` ${tag}`);
  8969. // console.log(Object.getOwnPropertyNames(cProto))
  8970. // continue;
  8971. }
  8972.  
  8973. // ------------- withTimerFn_ -------------
  8974.  
  8975. // ------------- ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX -------------
  8976.  
  8977. let urt = 0;
  8978.  
  8979. if (ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX) {
  8980.  
  8981.  
  8982. /**
  8983. *
  8984. f.handlePauseReplay = function() {
  8985. this.isAnimationPaused = !0;
  8986. this.detlaSincePausedSecs = 0
  8987. }
  8988. */
  8989.  
  8990. /**
  8991. *
  8992.  
  8993. f.handlePauseReplay = function() {
  8994. this.isReplayPaused = !0
  8995. }
  8996. *
  8997. */
  8998.  
  8999. if (typeof cProto.handlePauseReplay === 'function' && !cProto.handlePauseReplay66 && cProto.handlePauseReplay.length === 0) {
  9000. const fi = fnIntegrity(cProto.handlePauseReplay);
  9001. urt++;
  9002. if (fi === '0.8.2' || fi === '0.12.4') {
  9003. } else {
  9004. assertor(() => fnIntegrity(cProto.handlePauseReplay, '0.8.2'));
  9005. }
  9006. } else {
  9007. if (withTimerFn_ > 0) console1.log('Error for setting cProto.handlePauseReplay', tag)
  9008. }
  9009.  
  9010. if (typeof cProto.handleResumeReplay === 'function' && !cProto.handleResumeReplay66 && cProto.handleResumeReplay.length === 0) {
  9011. urt++;
  9012. assertor(() => fnIntegrity(cProto.handleResumeReplay, '0.8.2'));
  9013. } else {
  9014. if (withTimerFn_ > 0) console1.log('Error for setting cProto.handleResumeReplay', tag)
  9015. }
  9016.  
  9017. if (typeof cProto.handleReplayProgress === 'function' && !cProto.handleReplayProgress66 && cProto.handleReplayProgress.length === 1) {
  9018. urt++;
  9019. assertor(() => fnIntegrity(cProto.handleReplayProgress, '1.16.13'));
  9020. } else {
  9021. if (withTimerFn_ > 0) console1.log('Error for setting cProto.handleReplayProgress', tag)
  9022. }
  9023.  
  9024.  
  9025.  
  9026. }
  9027.  
  9028. 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);
  9029. cProto.__ENABLE_VIDEO_PROGRESS_STATE_FIX_AND_URT_PASSED__ = ENABLE_VIDEO_PROGRESS_STATE_FIX_AND_URT_PASSED;
  9030.  
  9031. if (ENABLE_VIDEO_PROGRESS_STATE_FIX_AND_URT_PASSED) {
  9032.  
  9033. cProto._Y7rtk = 0;
  9034. cProto._Y7rtu = 0;
  9035. cProto._Y7rtv = 0;
  9036.  
  9037. cProto.handlePauseReplay66 = cProto.handlePauseReplay;
  9038. cProto.handlePauseReplay = dProto.handlePauseReplayForPlaybackProgressState;
  9039.  
  9040. cProto.handleResumeReplay66 = cProto.handleResumeReplay;
  9041. cProto.handleResumeReplay = dProto.handleResumeReplayForPlaybackProgressState;
  9042.  
  9043. cProto.handleReplayProgress66 = cProto.handleReplayProgress;
  9044. cProto.handleReplayProgress = dProto.handleReplayProgressForPlaybackProgressState;
  9045.  
  9046. }
  9047.  
  9048. // ------------- ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX -------------
  9049.  
  9050. // ------------- FIX_MEMORY_LEAKAGE_TICKER_TIMER -------------
  9051.  
  9052. if (FIX_MEMORY_LEAKAGE_TICKER_TIMER) {
  9053. if (!USE_ADVANCED_TICKING && typeof cProto.setContainerWidth === 'function' && !cProto.setContainerWidth55 && cProto.setContainerWidth.length === 0) {
  9054. cProto.setContainerWidth55 = cProto.setContainerWidth;
  9055. cProto.setContainerWidth = dProto.setContainerWidthNoSelfLeakage;
  9056. flgLeakageFixApplied |= 4;
  9057. }
  9058. if (!USE_ADVANCED_TICKING && typeof cProto.slideDown === 'function' && !cProto.slideDown55 && cProto.slideDown.length === 0) {
  9059. cProto.slideDown55 = cProto.slideDown;
  9060. cProto.slideDown = dProto.slideDownNoSelfLeakage;
  9061. flgLeakageFixApplied |= 8;
  9062. }
  9063. if (!USE_ADVANCED_TICKING && typeof cProto.collapse === 'function' && !cProto.collapse55 && cProto.collapse.length === 0) {
  9064. cProto.collapse55 = cProto.collapse;
  9065. cProto.collapse = dProto.collapseNoSelfLeakage;
  9066. flgLeakageFixApplied |= 16;
  9067. }
  9068. if (typeof cProto.deletedChanged === 'function' && !cProto.deletedChanged55 && cProto.deletedChanged.length === 0) {
  9069.  
  9070. cProto.deletedChanged55 = cProto.deletedChanged;
  9071. cProto.deletedChanged = dProto.deletedChangedNoSelfLeakage;
  9072. flgLeakageFixApplied |= 32;
  9073. }
  9074.  
  9075. }
  9076.  
  9077. const flgTotal = USE_ADVANCED_TICKING ? 1 + 2 + 32 : 1 + 2 + 4 + 8 + 16 + 32;
  9078.  
  9079. console1.log(`FIX_MEMORY_LEAKAGE_TICKER_[#${tagI}]: ${flgLeakageFixApplied} / ${flgTotal}`, cProto.is);
  9080.  
  9081. // ------------- FIX_MEMORY_LEAKAGE_TICKER_TIMER -------------
  9082.  
  9083.  
  9084.  
  9085. const canDoAdvancedTicking = 1 &&
  9086. ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION &&
  9087. typeof cProto.startCountdown === 'function' && !cProto.startCountdown49 && cProto.startCountdown.length === 2 &&
  9088. typeof cProto.updateTimeout === 'function' && !cProto.updateTimeout49 && cProto.updateTimeout.length === 1 &&
  9089. typeof cProto.isAnimationPausedChanged === 'function' && !cProto.isAnimationPausedChanged49 && cProto.isAnimationPausedChanged.length === 2 &&
  9090. typeof cProto.setContainerWidth === 'function' && cProto.setContainerWidth.length === 0 &&
  9091. typeof cProto.requestRemoval === 'function' && !cProto.requestRemoval49 && cProto.requestRemoval.length === 0
  9092. CSS.supports("left","clamp(-100%, calc( -100% * ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) ), 0%)");
  9093.  
  9094.  
  9095.  
  9096. if (USE_ADVANCED_TICKING && canDoAdvancedTicking && ENABLE_TICKERS_BOOSTED_STAMPING) {
  9097. // startResistanceUpdater();
  9098. // live replay video -> 48117005 -> 48117006 keep fire. ->48117007 0 -> 48117007 {...}
  9099. // live stream video -> 48117007 0 -> 48117007 YES
  9100.  
  9101. document.documentElement.setAttribute('r6-advanced-ticking', '');
  9102. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::START`)
  9103.  
  9104. const wio2 = dProto.wio2 || (dProto.wio2 = new IntersectionObserver((mutations) => {
  9105.  
  9106. for (const mutation of mutations) {
  9107. if (mutation.isIntersecting) {
  9108.  
  9109. const marker = mutation.target;
  9110. let endId = marker.id
  9111. if (!endId) continue;
  9112. let tid = endId.substring(0, endId.length - 2);
  9113. if (!tid) continue;
  9114. // let bId = `${tid}-b`;
  9115. const bgElm = document.querySelector(`#${tid}-b`);
  9116. if (!bgElm) continue;
  9117. const overlay = bgElm;
  9118.  
  9119. wio2.unobserve(marker);
  9120. marker.remove();
  9121. let p = overlay || 0;
  9122. let cn = 4;
  9123. while ((p = p.parentElement) instanceof HTMLElement_) {
  9124. if (p instanceof HTMLElement_) {
  9125. const cnt = insp(p);
  9126. if (cnt && typeof cnt.slideDown === 'function' && typeof cnt.setContainerWidth === 'function' && cnt.__advancedTicking038__ === 1) {
  9127.  
  9128. cnt.__advancedTicking038__ = 2;
  9129.  
  9130. let deletionMode = false;
  9131. const cntData = ((cnt || 0).__data || 0).data || (cnt || 0).data || 0;
  9132. if (timestampUnderLiveMode && cntData && cntData.durationSec > 0 && cntData.__timestampActionRequest__ > 0) {
  9133.  
  9134. // time choose - 0.2s for transition (slideDown sliding-down)
  9135. // 60hz = 17ms
  9136. // choose 0.28s
  9137. const targetFutureTime = cntData.__timestampActionRequest__ + cntData.durationSec * 1000;
  9138. // check whether the targetFutureTime is already the past
  9139. if (targetFutureTime + 280 < Date.now()) {
  9140. // just dispose
  9141. deletionMode = true;
  9142. }
  9143. } else if (__LCRInjection__ && !timestampUnderLiveMode && cntData && cntData.durationSec > 0 && cntData.__progressAt__ > 0) {
  9144.  
  9145. const targetFutureTime = (cntData.__progressAt__ + cntData.durationSec);
  9146. // check whether the targetFutureTime is already the past
  9147. if (targetFutureTime + 0.28 < playerProgressChangedArg1) {
  9148. // just dispose
  9149. deletionMode = true;
  9150. }
  9151.  
  9152.  
  9153. }
  9154.  
  9155.  
  9156. if (deletionMode) {
  9157. __requestRemoval__(cnt);
  9158. } else {
  9159.  
  9160. const w = cnt.hostElement.style.width;
  9161. if (w === "auto" || w === "") cnt.setContainerWidth();
  9162. cnt.slideDown();
  9163. }
  9164.  
  9165. break;
  9166. }
  9167. }
  9168. cn--;
  9169. if (!cn) {
  9170. console.log('cnt not found for ticker-bg-overlay');
  9171. break;
  9172. }
  9173. }
  9174.  
  9175.  
  9176. }
  9177. }
  9178.  
  9179. // console.log(mutations);
  9180. }, {
  9181.  
  9182. rootMargin: '0px',
  9183. threshold: [1]
  9184.  
  9185. }));
  9186.  
  9187.  
  9188.  
  9189. cProto.__isTickerItem58__ = 1;
  9190. cProto.attached747 = cProto.attached;
  9191. cProto.attached = function () {
  9192. const hostElement = (this || 0).hostElement;
  9193. if (hostElement && hostElement.hasAttribute('q92wb')) hostElement.removeAttribute('q92wb');
  9194. if (hostElement && hostElement.__requestRemovalAt003__) hostElement.__requestRemovalAt003__ = 0;
  9195. Promise.resolve().then(() => {
  9196. if (this.hostElement && this.isAttached && this.hostElement.isConnected && this.parentComponent) {
  9197. if (this.__startCountdownAdv477__) Promise.resolve(this).then(timeFn749);
  9198. }
  9199. }).catch(console.warn);
  9200. return this.attached747();
  9201. };
  9202. cProto.startCountdown = dProto.startCountdownAdv || (dProto.startCountdownAdv = function (a, b) {
  9203.  
  9204.  
  9205. timeFn749(this);
  9206.  
  9207.  
  9208. });
  9209.  
  9210. cProto.updateTimeout = dProto.updateTimeoutAdv || (dProto.updateTimeoutAdv = function (a) {
  9211.  
  9212.  
  9213.  
  9214. });
  9215.  
  9216. cProto.isAnimationPausedChanged = dProto.isAnimationPausedChangedAdv || (dProto.isAnimationPausedChangedAdv = function (a, b) {
  9217.  
  9218.  
  9219.  
  9220. });
  9221.  
  9222.  
  9223. if (typeof cProto.slideDown === 'function' && !cProto.slideDown43 && cProto.slideDown.length === 0) {
  9224.  
  9225. cProto.slideDown43 = cProto.slideDown;
  9226. cProto.slideDown = dProto.slideDownAdv || (dProto.slideDownAdv = async function () {
  9227.  
  9228. // console.log('calling slideDown', Date.now())
  9229. if (this.__advancedTicking038__) {
  9230.  
  9231. if (this.__advancedTicking038__ === 1) this.__advancedTicking038__ = 2; // ignore intersectionobserver detection
  9232.  
  9233.  
  9234. const hostElement = this.hostElement;
  9235. const container = this.$.container;
  9236.  
  9237. const parentComponentCnt = insp(this.parentComponent);
  9238. const parentComponentElm = parentComponentCnt? parentComponentCnt.hostElement : null;
  9239.  
  9240. if (hostElement instanceof HTMLElement_ && container instanceof HTMLElement_ && parentComponentElm instanceof HTMLElement_) {
  9241. // const prevTransitionClosingElm = kRef(prevTransitionClosing);
  9242. // if (prevTransitionClosingElm !== hostElement) {
  9243. // prevTransitionClosingElm && prevTransitionClosingElm.classList.add('ticker-no-transition-time');
  9244. // prevTransitionClosing = mWeakRef(hostElement);
  9245. // }
  9246. // if (hostElement.classList.contains('ticker-no-transition-time')) hostElement.classList.remove('ticker-no-transition-time');
  9247. hostElement.classList.add('r6-closing-ticker');
  9248.  
  9249. if (!transitionEndHooks.has(parentComponentElm)) {
  9250. transitionEndHooks.add(parentComponentElm);
  9251. document.addEventListener('transitionend', transitionEndAfterFn, passiveCapture);
  9252. }
  9253.  
  9254. const pr = new PromiseExternal();
  9255. transitionEndAfterFnSimple.set(hostElement, pr);
  9256. transitionEndAfterFnSimple.set(container, pr);
  9257. transitionEndAfterFnSimpleEnable++;
  9258. hostElement.classList.add("sliding-down");
  9259. await pr.then();
  9260. transitionEndAfterFnSimpleEnable--;
  9261. transitionEndAfterFnSimple.delete(hostElement);
  9262. transitionEndAfterFnSimple.delete(container);
  9263. if (this && this.hostElement instanceof HTMLElement_) {
  9264.  
  9265. this.collapse();
  9266. }
  9267. return;
  9268. }
  9269. }
  9270. this.slideDown43();
  9271.  
  9272. });
  9273.  
  9274.  
  9275. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::slideDown - OK`)
  9276. } else {
  9277.  
  9278. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::slideDown - NG`)
  9279. }
  9280.  
  9281.  
  9282. if (typeof cProto.collapse === 'function' && !cProto.collapse43 && cProto.collapse.length === 0) {
  9283. cProto.collapse43 = cProto.collapse;
  9284. cProto.collapse = dProto.collapseAdv || (dProto.collapseAdv = async function () {
  9285.  
  9286.  
  9287. if (this.__advancedTicking038__) {
  9288.  
  9289.  
  9290. if (this.__advancedTicking038__ === 1) this.__advancedTicking038__ = 2; // ignore intersectionobserver detection
  9291.  
  9292.  
  9293. const hostElement = this.hostElement;
  9294. const container = this.$.container;
  9295.  
  9296. const parentComponentCnt = insp(this.parentComponent);
  9297. const parentComponentElm = parentComponentCnt ? parentComponentCnt.hostElement : null;
  9298.  
  9299. if (hostElement instanceof HTMLElement_ && container instanceof HTMLElement_ && parentComponentElm instanceof HTMLElement_) {
  9300. // const prevTransitionClosingElm = kRef(prevTransitionClosing);
  9301. // if (prevTransitionClosingElm !== hostElement) {
  9302. // prevTransitionClosingElm && prevTransitionClosingElm.classList.add('ticker-no-transition-time');
  9303. // prevTransitionClosing = mWeakRef(hostElement);
  9304. // }
  9305. // if (hostElement.classList.contains('ticker-no-transition-time')) hostElement.classList.remove('ticker-no-transition-time');
  9306. hostElement.classList.add('r6-closing-ticker');
  9307.  
  9308. if (!transitionEndHooks.has(parentComponentElm)) {
  9309. transitionEndHooks.add(parentComponentElm);
  9310. document.addEventListener('transitionend', transitionEndAfterFn, passiveCapture);
  9311. }
  9312.  
  9313. const pr = new PromiseExternal();
  9314. transitionEndAfterFnSimple.set(hostElement, pr);
  9315. transitionEndAfterFnSimple.set(container, pr);
  9316. transitionEndAfterFnSimpleEnable++;
  9317. hostElement.classList.add("collapsing");
  9318. hostElement.style.width = "0";
  9319. await pr.then();
  9320. transitionEndAfterFnSimpleEnable--;
  9321. transitionEndAfterFnSimple.delete(hostElement);
  9322. transitionEndAfterFnSimple.delete(container);
  9323. if (this && this.hostElement instanceof HTMLElement_) {
  9324.  
  9325. this.requestRemoval();
  9326. }
  9327.  
  9328. return;
  9329. }
  9330.  
  9331.  
  9332. }
  9333. this.collapse43();
  9334.  
  9335.  
  9336. });
  9337.  
  9338. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::collapse - OK`)
  9339. } else {
  9340.  
  9341. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::collapse - NG`)
  9342. }
  9343.  
  9344.  
  9345.  
  9346. if (typeof cProto.requestRemoval === 'function' && !cProto.requestRemoval49 && cProto.requestRemoval.length === 0) {
  9347.  
  9348. cProto.requestRemoval49 = cProto.requestRemoval;
  9349. cProto.requestRemoval = dProto.requestRemovalAdv || (dProto.requestRemovalAdv = function () {
  9350.  
  9351. const hostElement = this.hostElement;
  9352. hostElement.__requestRemovalAt003__ = Date.now();
  9353. if (this.__advancedTicking038__) {
  9354. try {
  9355. const overlayBg = hostElement.querySelector('ticker-bg-overlay[id]');
  9356. if (overlayBg) {
  9357. const overlayBgId = overlayBg.id;
  9358. const tid = overlayBgId ? overlayBgId.substring(0, overlayBgId.length - 2) : '';
  9359. const endElm = tid ? document.querySelector(`#${tid}-e`) : null;
  9360. if (endElm) {
  9361. wio2.unobserve(endElm);
  9362. endElm.remove();
  9363. }
  9364. }
  9365. } catch (e) { }
  9366. this.__advancedTicking038__ = 2;
  9367. // console.log('requestRemoval!!')
  9368. if (hostElement instanceof HTMLElement_) {
  9369. // otherwise the startCountDown not working
  9370. hostElement.style.removeProperty('--ticker-start-time');
  9371. hostElement.style.removeProperty('--ticker-duration-time');
  9372. }
  9373. if (REUSE_TICKER) {
  9374. const cntData = this.data;
  9375. if (hostElement instanceof HTMLElement_ && cntData.id && cntData.fullDurationSec && !hostElement.hasAttribute('__reuseid__')) {
  9376. hostElement.setAttribute('__reuseid__', reuseId);
  9377. hostElement.setAttribute('__nogc__', ''); // provided to leakage detection script
  9378. // this.__markReuse13__ = true;
  9379. reuseStore.set(`<${this.is}>${cntData.id}:${cntData.fullDurationSec}`, mWeakRef(this));
  9380. }
  9381. }
  9382. }
  9383. if (hostElement instanceof HTMLElement_) {
  9384. // try {
  9385. // // hostElement.remove();
  9386.  
  9387. // if (!hostElement.classList.contains('ticker-no-transition-time')) hostElement.classList.add('ticker-no-transition-time');
  9388. // } catch (e) { }
  9389.  
  9390. try {
  9391.  
  9392. hostElement.classList.remove('r6-closing-ticker');
  9393. hostElement.classList.remove('r6-width-adjustable-f');
  9394. } catch (e) { }
  9395.  
  9396. // if(ADVANCED_TICKING_MEMORY_CLEAN_FOR_REMOVAL){
  9397. // const wr = mWeakRef(hostElement);
  9398. // const wf = ()=>{
  9399. // const element = kRef(wr);
  9400. // if(!element) {
  9401. // console.log('[yt-chat-removalrequest] element was memory cleaned.');
  9402. // return;
  9403. // }
  9404.  
  9405. // setTimeout(wf, 8000);
  9406. // if(element.isConnected){
  9407. // console.log('[yt-chat-removalrequest] element is still connected to DOM Tree.');
  9408. // return;
  9409. // }
  9410.  
  9411. // const cnt = insp(element)
  9412. // if(typeof cnt.requestRemoval !== 'function'){
  9413.  
  9414. // console.log('[yt-chat-removalrequest] element is not connected to cnt.');
  9415. // return;
  9416. // }
  9417. // console.log('[yt-chat-removalrequest] element is not GC.');
  9418. // try{
  9419. // cnt.data = null;
  9420. // }catch(e){}
  9421.  
  9422. // Object.setPrototypeOf(cnt, Object.prototype);
  9423. // for(const k of Object.getOwnPropertyNames(cnt)){
  9424. // try{
  9425. // cnt[k] = null;
  9426. // }catch(e){}
  9427.  
  9428. // try{
  9429. // delete cnt[k];
  9430. // }catch(e){}
  9431. // }
  9432.  
  9433.  
  9434. // for(const k of Object.getOwnPropertySymbols(cnt)){
  9435. // try{
  9436. // cnt[k] = null;
  9437. // }catch(e){}
  9438.  
  9439. // try{
  9440. // delete cnt[k];
  9441. // }catch(e){}
  9442. // }
  9443.  
  9444. // }
  9445. // setTimeout(wf, 8000);
  9446. // }
  9447.  
  9448. hostElement.setAttribute('q92wb', '1');
  9449. }
  9450. });
  9451.  
  9452.  
  9453. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::requestRemoval - OK`)
  9454. } else {
  9455.  
  9456. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::requestRemoval - NG`)
  9457. }
  9458.  
  9459.  
  9460. if (typeof cProto.computeContainerStyle === 'function' && !cProto.computeContainerStyle49 && cProto.computeContainerStyle.length === 2) {
  9461. cProto.computeContainerStyle49 = cProto.computeContainerStyle;
  9462. cProto.computeContainerStyle = dProto.computeContainerStyleAdv || (dProto.computeContainerStyleAdv = function (a, b) {
  9463. if (this.__advancedTicking038__) {
  9464. return "";
  9465. }
  9466. return this.computeContainerStyle49(a, b);
  9467. });
  9468.  
  9469.  
  9470. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::computeContainerStyle - OK`)
  9471. } else {
  9472.  
  9473. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::computeContainerStyle - NG`)
  9474. }
  9475.  
  9476.  
  9477.  
  9478. if(ENABLE_TICKERS_BOOSTED_STAMPING && DISABLE_DYNAMIC_TICKER_WIDTH && typeof cProto.updateWidthOnDataChanged === 'function' && cProto.updateWidthOnDataChanged.length === 0 && !cProto.updateWidthOnDataChanged41){
  9479.  
  9480. cProto.updateWidthOnDataChanged41 = cProto.updateWidthOnDataChanged;
  9481. cProto.updateWidthOnDataChanged = dProto.updateWidthOnDataChangedAdv || (dProto.updateWidthOnDataChangedAdv = function(){
  9482. const style = this.hostElement.style;
  9483. style.width = "";
  9484. style.overflow = "";
  9485. });
  9486.  
  9487. }
  9488.  
  9489.  
  9490. if (!cProto.setStandardContainerWidth8447) {
  9491. cProto.setStandardContainerWidth8447 = dProto.setStandardContainerWidthAdv || (dProto.setStandardContainerWidthAdv = async function (kName) {
  9492.  
  9493. if (this.__startCountdownAdv477__) Promise.resolve(this).then(timeFn749);
  9494.  
  9495. const hostElement = (this || 0).hostElement;
  9496. const container = this.$.container;
  9497.  
  9498. let qw = null;
  9499. let qt = '';
  9500.  
  9501. {
  9502.  
  9503. let maxC = 4;
  9504.  
  9505. for (let p = qt = hostElement.getAttribute('r6-ticker-width') || ''; maxC--;) {
  9506.  
  9507. const ed = `${hostElement.id}`
  9508. if (!p || !p.startsWith(`${ed}::`)) {
  9509.  
  9510. const w = hostElement.style.width;
  9511. if (w !== '' && w !== 'auto') hostElement.style.width = 'auto';
  9512.  
  9513. const res = await widthReq(container);
  9514.  
  9515. if (res.width < 1 || !Number.isFinite(res.width)) {
  9516. // just skip due to iron-page hidden
  9517. return;
  9518. }
  9519.  
  9520. hostElement.setAttribute('r6-ticker-width', p = qt = `${ed}::${(res.width).toFixed(2)}`);
  9521.  
  9522. } else {
  9523. qw = p.split('::');
  9524. break;
  9525. }
  9526.  
  9527. }
  9528.  
  9529. }
  9530.  
  9531. if (!qw) {
  9532.  
  9533. console.log('container width failure');
  9534. if(kName === 'setContainerWidth') this.setContainerWidth41(); else this.setRevampContainerWidth41();
  9535. return; // failure
  9536. }
  9537.  
  9538.  
  9539. const shouldAnimateIn = ((this || 0).ytLiveChatTickerItemBehavior || 0).shouldAnimateIn || (this || 0).shouldAnimateIn || false;
  9540. if (shouldAnimateIn) {
  9541.  
  9542. stackDM(async () => {
  9543.  
  9544. if (hostElement.getAttribute('r6-ticker-width') !== qt || hostElement.isConnected !== true) return;
  9545. if (hostElement.previousElementSibling || isTickerItemsScrolling()) {
  9546.  
  9547. hostElement.style.width = `${qw[1]}px`;
  9548.  
  9549. } else {
  9550.  
  9551. const w = hostElement.style.width;
  9552. if (w !== '0px' && w !== '0') hostElement.style.width = '0';
  9553.  
  9554. await widthReq(container);
  9555.  
  9556. hostElement.style.width = `${qw[1]}px`;
  9557. }
  9558.  
  9559.  
  9560. });
  9561.  
  9562.  
  9563. } else {
  9564.  
  9565.  
  9566. stackDM(async () => {
  9567.  
  9568.  
  9569.  
  9570. if (hostElement.getAttribute('r6-ticker-width') !== qt || hostElement.isConnected !== true) return;
  9571.  
  9572. hostElement.style.width = `${qw[1]}px`;
  9573.  
  9574. });
  9575. }
  9576.  
  9577.  
  9578.  
  9579. });
  9580. }
  9581.  
  9582. if (typeof cProto.setRevampContainerWidth === 'function' && !cProto.setRevampContainerWidth41 && cProto.setRevampContainerWidth.length === 0 && typeof cProto.setStandardContainerWidth8447 === 'function' && cProto.setStandardContainerWidth8447.length === 1) {
  9583. cProto.setRevampContainerWidth41 = cProto.setRevampContainerWidth;
  9584. if (ENABLE_TICKERS_BOOSTED_STAMPING && DISABLE_DYNAMIC_TICKER_WIDTH) {
  9585.  
  9586. cProto.setRevampContainerWidth = dProto.setRevampContainerWidthAdv || (dProto.setRevampContainerWidthAdv = async function () {
  9587. const hostElement = this.hostElement;
  9588. if (((hostElement || 0).style || 0).width) hostElement.style.width = '';
  9589. return;
  9590. });
  9591.  
  9592. } else {
  9593.  
  9594.  
  9595.  
  9596. cProto.setRevampContainerWidth = dProto.setRevampContainerWidthAdv || (dProto.setRevampContainerWidthAdv = async function () {
  9597.  
  9598. // not sure the reason for auto instead of pixel.
  9599. // this is a new function in Dec 2024, but not mainly adopted in the coding yet
  9600.  
  9601. /*
  9602. var a = this;
  9603. (R(this.hostElement).querySelector("#container").clientWidth || 0) === 0 ? (this.hostElement.style.overflow = "visible",
  9604. this.hostElement.style.width = "auto") : (this.hostElement.style.overflow = "hidden",
  9605. this.ytLiveChatTickerItemBehavior.shouldAnimateIn ? (this.hostElement.style.width = "0",
  9606. Zu(function() {
  9607. a.hostElement.style.width = "auto"
  9608. }, 1)) : this.hostElement.style.width = "auto")
  9609. */
  9610.  
  9611.  
  9612. return this.setStandardContainerWidth8447('setRevampContainerWidth');
  9613.  
  9614. });
  9615. }
  9616.  
  9617.  
  9618. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::setRevampContainerWidth - OK`)
  9619. } else {
  9620.  
  9621. DEBUG_skipLog001 || console1.log(`USE_ADVANCED_TICKING[#${tagI}]::setRevampContainerWidth - NG (acceptable)`)
  9622. }
  9623.  
  9624.  
  9625. if (typeof cProto.setContainerWidth === 'function' && !cProto.setContainerWidth41 && cProto.setContainerWidth.length === 0 && typeof cProto.setStandardContainerWidth8447 === 'function' && cProto.setStandardContainerWidth8447.length === 1) {
  9626. cProto.setContainerWidth41 = cProto.setContainerWidth;
  9627.  
  9628. if (ENABLE_TICKERS_BOOSTED_STAMPING && DISABLE_DYNAMIC_TICKER_WIDTH) {
  9629.  
  9630. cProto.setContainerWidth = dProto.setContainerWidthAdv || (dProto.setContainerWidthAdv = async function () {
  9631. const hostElement = this.hostElement;
  9632. if (((hostElement || 0).style || 0).width) hostElement.style.width = '';
  9633. return;
  9634. });
  9635.  
  9636. } else {
  9637.  
  9638. cProto.setContainerWidth = dProto.setContainerWidthAdv || (dProto.setContainerWidthAdv = async function () {
  9639.  
  9640.  
  9641.  
  9642. /*
  9643. var a = this
  9644. , b = R(this.hostElement).querySelector("#container").clientWidth || 0;
  9645. b === 0 ? (this.hostElement.style.overflow = "visible",
  9646. this.hostElement.style.width = "auto") : (this.hostElement.style.overflow = "hidden",
  9647. this.shouldAnimateIn ? (this.hostElement.style.width = "0",
  9648. Zu(function() {
  9649. a.hostElement.style.width = b + "px"
  9650. }, 1)) : this.hostElement.style.width = b + "px")
  9651. */
  9652. return this.setStandardContainerWidth8447('setContainerWidth');
  9653.  
  9654. });
  9655.  
  9656. }
  9657.  
  9658.  
  9659.  
  9660. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::setContainerWidth - OK`)
  9661. } else {
  9662.  
  9663.  
  9664. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::setContainerWidth - NG`)
  9665. }
  9666.  
  9667.  
  9668.  
  9669.  
  9670. } else if (USE_ADVANCED_TICKING) {
  9671. console1.log(`USE_ADVANCED_TICKING[#${tagI}] is not injected.`);
  9672. }
  9673.  
  9674.  
  9675.  
  9676. }
  9677.  
  9678. const selector = tags.join(', ');
  9679. const elements = document.querySelectorAll(selector);
  9680. if (elements.length >= 1) {
  9681. for (const elm of elements) {
  9682. if (insp(elm).isAttached === true) {
  9683. fpTicker(elm);
  9684. }
  9685. }
  9686. }
  9687.  
  9688. console1.log("[End]");
  9689. groupEnd();
  9690.  
  9691.  
  9692. }).catch(console.warn);
  9693.  
  9694. if(FIX_MEMORY_LEAKAGE_TICKER_DATACHANGED_setContainerWidth){
  9695.  
  9696. /**
  9697. *
  9698. *
  9699. *
  9700. *
  9701. cT.prototype.dataChanged = function() {
  9702. var a = this;
  9703. this.data && (Q(this.hostElement).querySelector("#content").style.color = this.ytLiveChatTickerItemBehavior.colorFromDecimal(this.data.detailTextColor),
  9704. this.hostElement.ariaLabel = this.computeAriaLabel(this.data),
  9705. this.ytLiveChatTickerItemBehavior.startCountdown(this.data.durationSec, this.data.fullDurationSec),
  9706. qw(function() {
  9707. a.ytLiveChatTickerItemBehavior.setContainerWidth()
  9708. }))
  9709. }
  9710.  
  9711.  
  9712. znb.prototype.dataChanged = function(a) {
  9713. var b = this;
  9714. a && (a.tickerThumbnails.length > 1 && Q(this.hostElement).querySelector("#content").classList.add("multiple-thumbnails"),
  9715. this.ytLiveChatTickerItemBehavior.startCountdown(a.durationSec, a.fullDurationSec),
  9716. qw(function() {
  9717. b.ytLiveChatTickerItemBehavior.setContainerWidth()
  9718. }))
  9719. }
  9720.  
  9721. *
  9722. */
  9723.  
  9724. const dProto = {
  9725. dataChanged54500: function () {
  9726. // prevent memory leakage due to _.ytLiveChatTickerItemBehavior.setContainerWidth() in _.dataChanged
  9727. if (typeof (this.ytLiveChatTickerItemBehavior || 0).setContainerWidth === 'function') {
  9728. try {
  9729. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  9730. return this.dataChanged544.call(this.__proxySelf0__);
  9731. } catch (e) {
  9732. console.log('dataChanged54500 ERROR');
  9733. console.error(e);
  9734. }
  9735. } else {
  9736. return this.dataChanged544();
  9737. }
  9738. },
  9739. dataChanged54501: function (a) {
  9740. // prevent memory leakage due to _.ytLiveChatTickerItemBehavior.setContainerWidth() in _.dataChanged
  9741. if (typeof (this.ytLiveChatTickerItemBehavior || 0).setContainerWidth === 'function') {
  9742. try {
  9743. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  9744. return this.dataChanged544.call(this.__proxySelf0__, a);
  9745. } catch (e) {
  9746. console.log('dataChanged54501 ERROR');
  9747. console.error(e);
  9748. }
  9749. } else {
  9750. return this.dataChanged544(a);
  9751. }
  9752. },
  9753. }
  9754.  
  9755. for (const sto of [
  9756. 'yt-live-chat-ticker-sponsor-item-renderer',
  9757. 'yt-live-chat-ticker-paid-sticker-item-renderer'
  9758. ].map(tag => [tag, customElements.whenDefined(tag)])) {
  9759.  
  9760. const [tag, promise] = sto;
  9761.  
  9762. promise.then(()=>{
  9763.  
  9764. const dummy = document.createElement(tag);
  9765.  
  9766. const cProto = getProto(dummy);
  9767. if (!cProto || !cProto.attached) {
  9768. console.warn(`proto.attached for ${tag} is unavailable.`);
  9769. return;
  9770. }
  9771.  
  9772. if (!cProto.dataChanged || cProto.dataChanged544 || typeof cProto.dataChanged !== 'function' || !(cProto.dataChanged.length >= 0 && cProto.dataChanged.length <= 1)) return;
  9773.  
  9774. cProto.dataChanged544 = cProto.dataChanged;
  9775.  
  9776. if (cProto.dataChanged.length === 0) cProto.dataChanged = dProto.dataChanged54500;
  9777. else if (cProto.dataChanged.length === 1) cProto.dataChanged = dProto.dataChanged54501;
  9778.  
  9779.  
  9780.  
  9781. })
  9782.  
  9783.  
  9784. }
  9785.  
  9786. }
  9787.  
  9788. customElements.whenDefined('yt-live-chat-ticker-renderer').then(() => {
  9789.  
  9790. mightFirstCheckOnYtInit();
  9791. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-ticker-renderer hacks");
  9792. console1.log("[Begin]");
  9793. (() => {
  9794.  
  9795. /* pending!!
  9796.  
  9797. handleLiveChatAction
  9798.  
  9799. removeTickerItemById
  9800.  
  9801. _itemsChanged
  9802. itemsChanged
  9803.  
  9804. handleMarkChatItemAsDeletedAction
  9805. handleMarkChatItemsByAuthorAsDeletedAction
  9806. handleRemoveChatItemByAuthorAction
  9807.  
  9808.  
  9809. */
  9810.  
  9811. const tag = "yt-live-chat-ticker-renderer"
  9812. const dummy = document.createElement(tag);
  9813.  
  9814. const cProto = getProto(dummy);
  9815. if (!cProto || !cProto.attached) {
  9816. console1.warn(`proto.attached for ${tag} is unavailable.`);
  9817. return;
  9818. }
  9819.  
  9820. if (FIX_REMOVE_TICKER_ITEM_BY_ID && typeof cProto.splice === 'function' && typeof cProto.markDirty === 'function' && typeof cProto.removeTickerItemById === 'function' && !cProto.removeTickerItemById737) {
  9821. cProto.removeTickerItemById737 = cProto.removeTickerItemById;
  9822. cProto.removeTickerItemById = function (a) {
  9823. // console.log('removeTickerItemById#01', a);
  9824. if (this.tickerItemsQuery !== '#ticker-items' || typeof (a || 0) !== 'string') return this.removeTickerItemById737(a);
  9825. // console.log('removeTickerItemById#02', a);
  9826. const hostElement = this.hostElement;
  9827. if (!hostElement || !a) return this.removeTickerItemById737(a);
  9828. // console.log('removeTickerItemById#03', a);
  9829. const arr = hostElement.querySelectorAll(`[id="${a}"]`);
  9830. const s = new Set();
  9831. if (typeof (a || 0) === 'string') s.add(a);
  9832. for (const elem of arr) {
  9833. if (!elem) continue;
  9834. const elemId = elem.id;
  9835. if (!elemId) continue;
  9836. s.add(elemId);
  9837. const data = (insp(elem).data || 0);
  9838. if (data) {
  9839. const u = data.id;
  9840. if (u) s.add(u);
  9841. else data.id = elemId;
  9842. }
  9843. }
  9844. const tickerItems = this.tickerItems;
  9845. let deleteCount = 0;
  9846. for (let i = tickerItems.length - 1; i >= 0; i--) {
  9847. const obj = tickerItems[i];
  9848. if (!obj || typeof obj !== 'object') continue;
  9849. const key = firstObjectKey(obj);
  9850. if (!key) continue;
  9851. const dataObj = obj[key];
  9852. const dataId = (dataObj || 0).id;
  9853. if (s.has(dataId)) {
  9854. this.splice("tickerItems", i, 1);
  9855. this.markDirty();
  9856. deleteCount++;
  9857. }
  9858. }
  9859. // console.log('removeTickerItemById#06', a, deleteCount);
  9860. s.has(this.highlightId) && (this.highlightId = void 0);
  9861. // console.log('removeTickerItemById#07', a, deleteCount);
  9862. }
  9863. }
  9864.  
  9865. // const imgCollection = document.getElementsByTagName('IMG');
  9866.  
  9867. if (ENABLE_TICKERS_BOOSTED_STAMPING && typeof cProto.notifyPath === 'function' && cProto.notifyPath.length === 2 && typeof cProto.stampDomArraySplices_ === 'function' && cProto.stampDomArraySplices_.length === 3
  9868. && !cProto.notifyPath371 && !cProto.proceedStampDomArraySplices371_
  9869. && !cProto.stampDomArraySplices371_ && !cProto.stampDomArray366_) {
  9870.  
  9871. rendererStamperFactory(cProto, {
  9872. key: 'proceedStampDomArraySplices371_',
  9873. stamperDomClass: 'style-scope yt-live-chat-ticker-renderer yt-live-chat-ticker-stampdom'
  9874. });
  9875.  
  9876. cProto.notifyPath371 = cProto.notifyPath;
  9877.  
  9878. cProto.stampDomArraySplices371_ = cProto.stampDomArraySplices_;
  9879.  
  9880. if (typeof cProto.stampDomArraySplices371_ === 'function' && cProto.stampDomArraySplices371_.length >= 3) {
  9881. cProto.stampDomArraySplices_ = function (a, b, c) {
  9882. if (a === 'tickerItems' && b === 'ticker-items' && (c || 0).indexSplices) {
  9883. // if (this.ec388) {
  9884. const indexSplices = c.indexSplices;
  9885. if (indexSplices.length === 1 || typeof indexSplices.length === "undefined") {
  9886. const indexSplice = indexSplices[0] || indexSplices;
  9887. if (indexSplice.type === 'splice' && (indexSplice.addedCount >= 1 || (indexSplice.removed || 0).length >= 1)) {
  9888. // console.log(1059, a, b, indexSplice);
  9889. if (this.proceedStampDomArraySplices371_(a, b, indexSplice)) return;
  9890. }
  9891. }
  9892. // } else {
  9893. // console.warn('stampDomArraySplices_ warning', ...arguments);
  9894. // }
  9895. }
  9896. return this.stampDomArraySplices371_(...arguments);
  9897. };
  9898. } else {
  9899. console.warn('0xF0230 Function Signature Changed');
  9900. }
  9901.  
  9902. cProto.stampDomArray366_ = cProto.stampDomArray_;
  9903. if (typeof cProto.stampDomArray366_ === 'function' && cProto.stampDomArray366_.length >= 5) {
  9904. cProto.stampDomArray_ = function (items, containerId, componentConfig, rxConfig, shouldCallback, isStableList) {
  9905. const isTickerRendering = items === this.tickerItems && containerId === 'ticker-items';
  9906. const isMessageListRendering = items === this.visibleItems && containerId === 'items';
  9907.  
  9908. if (!isTickerRendering && !isMessageListRendering) {
  9909. console.log('stampDomArray_ warning 0xF501', ...arguments)
  9910. return this.stampDomArray366_(...arguments);
  9911. }
  9912.  
  9913. const container = (this.$ || 0)[containerId];
  9914. if (!container) {
  9915. console.log('stampDomArray_ warning 0xF502', ...arguments)
  9916. return this.stampDomArray366_(...arguments);
  9917. }
  9918.  
  9919. if (container[sFirstElementChild] === null && items.length === 0) {
  9920.  
  9921. } else {
  9922. const cTag = isTickerRendering ? 'tickerItems' : 'visibleItems';
  9923. this.proceedStampDomArraySplices371_(cTag, containerId, {
  9924. addedCount: items.length,
  9925. removedCount: container.childElementCount
  9926. });
  9927. }
  9928.  
  9929. const f = () => {
  9930. this.markDirty && this.markDirty();
  9931. const detail = {
  9932. container
  9933. };
  9934. shouldCallback && this.hostElement.dispatchEvent(new CustomEvent("yt-rendererstamper-finished", {
  9935. bubbles: !0,
  9936. cancelable: !1,
  9937. composed: !0,
  9938. detail
  9939. }));
  9940. detail.container = null;
  9941. };
  9942.  
  9943. if (this.ec389pr) {
  9944. this.ec389pr.then(f)
  9945. } else {
  9946. f();
  9947. }
  9948.  
  9949. };
  9950. } else {
  9951. console.warn('0xF0230 Function Signature Changed');
  9952. }
  9953.  
  9954. }
  9955.  
  9956. if (typeof cProto.createComponent_ === 'function' && cProto.createComponent_.length === 3 && !cProto.createComponent58_) {
  9957.  
  9958. cProto.createComponent58_ = cProto.createComponent_;
  9959. cProto.createComponent_ = function (a, b, c) {
  9960.  
  9961. const z = customCreateComponent(a, b, c);
  9962. if (z !== undefined) return z;
  9963. const r = this.createComponent58_(a, b, c);
  9964. return r;
  9965.  
  9966. }
  9967.  
  9968. } else {
  9969. console.warn('0xF0230 Function Signature Changed');
  9970. }
  9971.  
  9972.  
  9973. /* Dec 2024 */
  9974.  
  9975. /*
  9976.  
  9977.  
  9978. f.handleLiveChatActions = function(a) {
  9979. a.length && (a.forEach(this.handleLiveChatAction, this),
  9980. this.updateHighlightedItem(),
  9981. this.shouldAnimateIn = !0)
  9982. }
  9983. ;
  9984. f.handleLiveChatAction = function(a) {
  9985. var b = z(a, fL)
  9986. , c = z(a, gL)
  9987. , d = z(a, eL)
  9988. , e = z(a, gdb)
  9989. , g = z(a, rdb)
  9990. , k = z(a, Deb);
  9991. a = z(a, Ceb);
  9992. 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)
  9993. }
  9994. */
  9995.  
  9996.  
  9997. if (USE_ADVANCED_TICKING && !cProto.handleLiveChatActions47 && typeof cProto.handleLiveChatActions === 'function' && cProto.handleLiveChatActions.length === 1) {
  9998.  
  9999. cProto.handleLiveChatActions47 = cProto.handleLiveChatActions;
  10000.  
  10001. cProto.handleLiveChatActions = function (a) {
  10002.  
  10003. // first loading in livestream. so this is required for sorting.
  10004.  
  10005. try {
  10006. preprocessChatLiveActions(a);
  10007. } catch (e) {
  10008. console.warn(e);
  10009. }
  10010. return this.handleLiveChatActions47(a);
  10011.  
  10012. }
  10013.  
  10014. console1.log("USE_ADVANCED_TICKING::handleLiveChatActions - OK");
  10015.  
  10016. } else if (USE_ADVANCED_TICKING) {
  10017.  
  10018.  
  10019. console1.log("USE_ADVANCED_TICKING::handleLiveChatActions - NG");
  10020.  
  10021. }
  10022.  
  10023. // yt-live-chat-ticker-renderer hacks
  10024.  
  10025.  
  10026. if (RAF_FIX_keepScrollClamped) {
  10027.  
  10028. // to be improved
  10029.  
  10030. if (typeof cProto.keepScrollClamped === 'function' && !cProto.keepScrollClamped72 && fnIntegrity(cProto.keepScrollClamped) === '0.17.10') {
  10031.  
  10032. cProto.keepScrollClamped72 = cProto.keepScrollClamped;
  10033. cProto.keepScrollClamped = function () {
  10034.  
  10035. const cnt = kRef(this);
  10036. if (!cnt) return;
  10037. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10038.  
  10039. cnt._bound_keepScrollClamped = cnt._bound_keepScrollClamped || cnt.keepScrollClamped.bind(mWeakRef(cnt));
  10040. cnt.scrollClampRaf = requestAnimationFrame(cnt._bound_keepScrollClamped);
  10041. cnt.maybeClampScroll()
  10042. }
  10043.  
  10044. console1.log('RAF_FIX: keepScrollClamped', tag, "OK")
  10045. } else {
  10046.  
  10047. assertor(() => fnIntegrity(cProto.keepScrollClamped, '0.17.10'));
  10048. console1.log('RAF_FIX: keepScrollClamped', tag, "NG")
  10049. }
  10050.  
  10051. }
  10052.  
  10053.  
  10054. if (RAF_FIX_scrollIncrementally && typeof cProto.startScrolling === 'function' && typeof cProto.scrollIncrementally === 'function'
  10055. && '|1.43.31|1.44.31|'.indexOf('|' + fnIntegrity(cProto.startScrolling) + '|') >= 0
  10056. && '|1.78.45|1.82.43|1.43.31|'.indexOf('|' + fnIntegrity(cProto.scrollIncrementally) + '|') >= 0) {
  10057. // to be replaced by animator
  10058.  
  10059. cProto.startScrolling = function (a) {
  10060.  
  10061. const cnt = kRef(this);
  10062. if (!cnt) return;
  10063. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10064.  
  10065. cnt.scrollStopHandle && cnt.cancelAsync(cnt.scrollStopHandle);
  10066. cnt.asyncHandle && cancelAnimationFrame(cnt.asyncHandle);
  10067. cnt.lastFrameTimestamp = cnt.scrollStartTime = performance.now();
  10068. cnt.scrollRatePixelsPerSecond = a;
  10069. cnt._bound_scrollIncrementally = cnt._bound_scrollIncrementally || cnt.scrollIncrementally.bind(mWeakRef(cnt));
  10070. cnt.asyncHandle = requestAnimationFrame(cnt._bound_scrollIncrementally)
  10071. };
  10072.  
  10073. // related functions: startScrollBack, startScrollingLeft, startScrollingRight, etc.
  10074.  
  10075. /**
  10076. *
  10077. * // 2024.12.17
  10078. * // https://www.youtube.com/s/desktop/f7495da0/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  10079.  
  10080. f.startScrolling = function(a) {
  10081. this.scrollStopHandle && $u(this.scrollStopHandle);
  10082. this.asyncHandle && window.cancelAnimationFrame(this.asyncHandle);
  10083. this.scrollStartTime = performance.now();
  10084. this.lastFrameTimestamp = performance.now();
  10085. this.scrollRatePixelsPerSecond = a;
  10086. this.asyncHandle = window.requestAnimationFrame(this.scrollIncrementally.bind(this))
  10087. }
  10088. ;
  10089. f.scrollIncrementally = function(a) {
  10090. var b = a - (this.lastFrameTimestamp || 0);
  10091. R(this.hostElement).querySelector(this.tickerBarQuery).scrollLeft += b / 1E3 * (this.scrollRatePixelsPerSecond || 0);
  10092. this.maybeClampScroll();
  10093. this.updateArrows();
  10094. this.lastFrameTimestamp = a;
  10095. R(this.hostElement).querySelector(this.tickerBarQuery).scrollLeft > 0 || this.scrollRatePixelsPerSecond && this.scrollRatePixelsPerSecond > 0 ? this.asyncHandle = window.requestAnimationFrame(this.scrollIncrementally.bind(this)) : this.stopScrolling()
  10096. }
  10097. ;
  10098. *
  10099. */
  10100.  
  10101. /**
  10102. *
  10103. // 2024.12.20
  10104.  
  10105.  
  10106.  
  10107. f.startScrolling = function(a) {
  10108. this.scrollStopHandle && av(this.scrollStopHandle);
  10109. this.asyncHandle && window.cancelAnimationFrame(this.asyncHandle);
  10110. this.scrollStartTime = performance.now();
  10111. this.lastFrameTimestamp = performance.now();
  10112. this.scrollRatePixelsPerSecond = a;
  10113. this.asyncHandle = window.requestAnimationFrame(this.scrollIncrementally.bind(this))
  10114. }
  10115.  
  10116. *
  10117. *
  10118. */
  10119.  
  10120. cProto.__getTickerBarQuery__ = function () {
  10121. const tickerBarQuery = this.tickerBarQuery === '#items' ? this.$.items : this.hostElement.querySelector(this.tickerBarQuery);
  10122. return tickerBarQuery;
  10123. }
  10124.  
  10125. cProto.scrollIncrementally = (RAF_FIX_scrollIncrementally === 2) ? function (a) {
  10126.  
  10127. const cnt = kRef(this);
  10128. if (!cnt) return;
  10129. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10130.  
  10131. const b = a - (cnt.lastFrameTimestamp || 0);
  10132. const rate = cnt.scrollRatePixelsPerSecond
  10133. const q = b / 1E3 * (rate || 0);
  10134.  
  10135. const tickerBarQuery = cnt.__getTickerBarQuery__();
  10136. if (!tickerBarQuery) return; // memory leakage. to be reviewed
  10137. const sl = tickerBarQuery.scrollLeft;
  10138. // console.log(rate, sl, q)
  10139. if (cnt.lastFrameTimestamp == cnt.scrollStartTime) {
  10140.  
  10141. } else if (q > -1e-5 && q < 1e-5) {
  10142.  
  10143. } else {
  10144. let cond1 = sl > 0 && rate > 0 && q > 0;
  10145. let cond2 = sl > 0 && rate < 0 && q < 0;
  10146. let cond3 = sl < 1e-5 && sl > -1e-5 && rate > 0 && q > 0;
  10147. if (cond1 || cond2 || cond3) {
  10148. tickerBarQuery.scrollLeft += q;
  10149. cnt.maybeClampScroll();
  10150. cnt.updateArrows();
  10151. }
  10152. }
  10153.  
  10154. cnt.lastFrameTimestamp = a;
  10155. cnt._bound_scrollIncrementally = cnt._bound_scrollIncrementally || cnt.scrollIncrementally.bind(mWeakRef(cnt));
  10156. 0 < tickerBarQuery.scrollLeft || rate && 0 < rate ? cnt.asyncHandle = requestAnimationFrame(cnt._bound_scrollIncrementally) : cnt.stopScrolling()
  10157. } : function (a) {
  10158.  
  10159. const cnt = kRef(this);
  10160. if (!cnt) return;
  10161. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10162.  
  10163. const b = a - (cnt.lastFrameTimestamp || 0);
  10164. const tickerBarQuery = cnt.__getTickerBarQuery__();
  10165. if (!tickerBarQuery) return; // memory leakage. to be reviewed
  10166. tickerBarQuery.scrollLeft += b / 1E3 * (cnt.scrollRatePixelsPerSecond || 0);
  10167. cnt.maybeClampScroll();
  10168. cnt.updateArrows();
  10169. cnt.lastFrameTimestamp = a;
  10170. cnt._bound_scrollIncrementally = cnt._bound_scrollIncrementally || cnt.scrollIncrementally.bind(mWeakRef(cnt));
  10171. 0 < tickerBarQuery.scrollLeft || cnt.scrollRatePixelsPerSecond && 0 < cnt.scrollRatePixelsPerSecond ? cnt.asyncHandle = requestAnimationFrame(cnt._bound_scrollIncrementally) : cnt.stopScrolling()
  10172. };
  10173.  
  10174. console1.log(`RAF_FIX: scrollIncrementally${RAF_FIX_scrollIncrementally}`, tag, "OK")
  10175. } else {
  10176. assertor(() => fnIntegrity(cProto.startScrolling, '1.43.31'))
  10177. || logFn('cProto.startScrolling', cProto.startScrolling)();
  10178. assertor(() => fnIntegrity(cProto.scrollIncrementally, '1.78.45'))
  10179. || logFn('cProto.scrollIncrementally', cProto.scrollIncrementally)();
  10180. console1.log('RAF_FIX: scrollIncrementally', tag, "NG")
  10181. }
  10182.  
  10183.  
  10184. if (CLOSE_TICKER_PINNED_MESSAGE_WHEN_HEADER_CLICKED && typeof cProto.attached === 'function' && !cProto.attached37 && typeof cProto.detached === 'function' && !cProto.detached37) {
  10185.  
  10186. cProto.attached37 = cProto.attached;
  10187. cProto.detached37 = cProto.detached;
  10188.  
  10189. let naohzId = 0;
  10190. cProto.__naohzId__ = 0;
  10191. cProto.attached = function () {
  10192. Promise.resolve(this).then((cnt) => {
  10193.  
  10194. const hostElement = cnt.hostElement || cnt;
  10195. if (!(hostElement instanceof HTMLElement_)) return;
  10196. if (!HTMLElement_.prototype.matches.call(hostElement, '.yt-live-chat-renderer')) return;
  10197. const ironPage = HTMLElement_.prototype.closest.call(hostElement, 'iron-pages.yt-live-chat-renderer');
  10198. // or #chat-messages
  10199. if (!ironPage) return;
  10200.  
  10201. if (cnt.__naohzId__) removeEventListener.call(ironPage, 'click', cnt.messageBoxClickHandlerForFade, { capture: false, passive: true });
  10202. cnt.__naohzId__ = naohzId = (naohzId & 1073741823) + 1;
  10203. ironPage.setAttribute('naohz', `${+cnt.__naohzId__}`);
  10204.  
  10205. addEventListener.call(ironPage, 'click', cnt.messageBoxClickHandlerForFade, { capture: false, passive: true });
  10206.  
  10207. cnt = null;
  10208.  
  10209. });
  10210. return this.attached37.apply(this, arguments);
  10211. };
  10212. cProto.detached = function () {
  10213. Promise.resolve(this).then((cnt) => {
  10214.  
  10215. const ironPage = document.querySelector(`iron-pages[naohz="${+cnt.__naohzId__}"]`);
  10216. if (!ironPage) return;
  10217.  
  10218. removeEventListener.call(ironPage, 'click', cnt.messageBoxClickHandlerForFade, { capture: false, passive: true });
  10219.  
  10220. cnt = null;
  10221.  
  10222. });
  10223. return this.detached37.apply(this, arguments);
  10224. };
  10225.  
  10226. const clickFade = (u) => {
  10227. u.click();
  10228. };
  10229. cProto.messageBoxClickHandlerForFade = async (evt) => {
  10230.  
  10231. const target = (evt || 0).target || 0;
  10232. if (!target) return;
  10233.  
  10234. for (let p = target; p instanceof HTMLElement_; p = nodeParent(p)) {
  10235. const is = p.is;
  10236. if (typeof is === 'string' && is) {
  10237.  
  10238. if (is === 'yt-live-chat-pinned-message-renderer') {
  10239. return;
  10240. }
  10241. if (is === 'iron-pages' || is === 'yt-live-chat-renderer' || is === 'yt-live-chat-app') {
  10242. const fade = HTMLElement_.prototype.querySelector.call(p, 'yt-live-chat-pinned-message-renderer:not([hidden]) #fade');
  10243. if (fade) {
  10244. Promise.resolve(fade).then(clickFade);
  10245. evt && evt.stopPropagation();
  10246. }
  10247. return;
  10248. }
  10249. if (is !== 'yt-live-chat-ticker-renderer') {
  10250. if (is.startsWith('yt-live-chat-ticker-')) return;
  10251. if (!is.endsWith('-renderer')) return;
  10252. }
  10253.  
  10254. } else {
  10255. if ((p.nodeName || '').includes('BUTTON')) return;
  10256. }
  10257.  
  10258. }
  10259. };
  10260.  
  10261. console1.log("CLOSE_TICKER_PINNED_MESSAGE_WHEN_HEADER_CLICKED - OK")
  10262.  
  10263. } else {
  10264. console1.log("CLOSE_TICKER_PINNED_MESSAGE_WHEN_HEADER_CLICKED - NG")
  10265. }
  10266.  
  10267.  
  10268. })();
  10269.  
  10270. console1.log("[End]");
  10271.  
  10272. groupEnd();
  10273.  
  10274. }).catch(console.warn);
  10275.  
  10276.  
  10277.  
  10278. if (ENABLE_RAF_HACK_INPUT_RENDERER || DELAY_FOCUSEDCHANGED) {
  10279.  
  10280. customElements.whenDefined("yt-live-chat-message-input-renderer").then(() => {
  10281.  
  10282. mightFirstCheckOnYtInit();
  10283. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-message-input-renderer hacks");
  10284. console1.log("[Begin]");
  10285. (() => {
  10286.  
  10287.  
  10288.  
  10289. const tag = "yt-live-chat-message-input-renderer"
  10290. const dummy = document.createElement(tag);
  10291.  
  10292. const cProto = getProto(dummy);
  10293. if (!cProto || !cProto.attached) {
  10294. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10295. return;
  10296. }
  10297.  
  10298.  
  10299. if (ENABLE_RAF_HACK_INPUT_RENDERER && rafHub !== null) {
  10300.  
  10301. let doHack = false;
  10302. if (typeof cProto.handleTimeout === 'function' && typeof cProto.updateTimeout === 'function') {
  10303.  
  10304. // not cancellable
  10305.  
  10306. // <<< to be reviewed cProto.updateTimeout --- isTimingFunctionHackable -- doHack >>>
  10307.  
  10308. doHack = fnIntegrity(cProto.handleTimeout, '1.27.16') && fnIntegrity(cProto.updateTimeout, '1.50.33');
  10309.  
  10310. if (!doHack) console1.log('doHack = false')
  10311.  
  10312. }
  10313. // doHack = false; // M55
  10314.  
  10315. if (doHack) {
  10316.  
  10317. cProto.handleTimeout = function (a) {
  10318.  
  10319. const cnt = kRef(this);
  10320. if (!cnt) return;
  10321. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10322.  
  10323. console.log('cProto.handleTimeout', tag)
  10324. if (!cnt.boundUpdateTimeout38_) cnt.boundUpdateTimeout38_ = cnt.updateTimeout.bind(mWeakRef(cnt));
  10325. cnt.timeoutDurationMs = cnt.timeoutMs = a;
  10326. cnt.countdownRatio = 1;
  10327. 0 === cnt.lastTimeoutTimeMs && rafHub.request(cnt.boundUpdateTimeout38_)
  10328. };
  10329. cProto.updateTimeout = function (a) {
  10330.  
  10331. const cnt = kRef(this);
  10332. if (!cnt) return;
  10333. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10334.  
  10335. console.log('cProto.updateTimeout', tag)
  10336. if (!cnt.boundUpdateTimeout38_) cnt.boundUpdateTimeout38_ = cnt.updateTimeout.bind(mWeakRef(cnt));
  10337. cnt.lastTimeoutTimeMs && (cnt.timeoutMs = Math.max(0, cnt.timeoutMs - (a - cnt.lastTimeoutTimeMs)),
  10338. cnt.countdownRatio = cnt.timeoutMs / cnt.timeoutDurationMs);
  10339. cnt.isAttached && cnt.timeoutMs ? (cnt.lastTimeoutTimeMs = a,
  10340. rafHub.request(cnt.boundUpdateTimeout38_)) : cnt.lastTimeoutTimeMs = 0
  10341. };
  10342.  
  10343. console1.log('RAF_HACK_INPUT_RENDERER', tag, "OK")
  10344. } else {
  10345.  
  10346. console1.log('typeof handleTimeout', typeof cProto.handleTimeout)
  10347. console1.log('typeof updateTimeout', typeof cProto.updateTimeout)
  10348.  
  10349. console1.log('RAF_HACK_INPUT_RENDERER', tag, "NG")
  10350. }
  10351.  
  10352.  
  10353. }
  10354.  
  10355. if (DELAY_FOCUSEDCHANGED && typeof cProto.onFocusedChanged === 'function' && cProto.onFocusedChanged.length === 1 && !cProto.onFocusedChanged372) {
  10356. cProto.onFocusedChanged372 = cProto.onFocusedChanged;
  10357. cProto.onFocusedChanged = function (a) {
  10358. Promise.resolve(this).then((cnt) => {
  10359. if (cnt.isAttached === true) cnt.onFocusedChanged372(a);
  10360. cnt = null;
  10361. }).catch(console.warn);
  10362. }
  10363. }
  10364.  
  10365. })();
  10366.  
  10367. console1.log("[End]");
  10368.  
  10369. groupEnd();
  10370.  
  10371.  
  10372. })
  10373.  
  10374. }
  10375.  
  10376.  
  10377. if (ENABLE_RAF_HACK_EMOJI_PICKER && rafHub !== null) {
  10378.  
  10379. customElements.whenDefined("yt-emoji-picker-renderer").then(() => {
  10380.  
  10381. mightFirstCheckOnYtInit();
  10382. groupCollapsed("YouTube Super Fast Chat", " | yt-emoji-picker-renderer hacks");
  10383. console1.log("[Begin]");
  10384. (() => {
  10385.  
  10386. const tag = "yt-emoji-picker-renderer"
  10387. const dummy = document.createElement(tag);
  10388.  
  10389. const cProto = getProto(dummy);
  10390. if (!cProto || !cProto.attached) {
  10391. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10392. return;
  10393. }
  10394.  
  10395. let doHack = false;
  10396. if (typeof cProto.animateScroll_ === 'function') {
  10397.  
  10398. // not cancellable
  10399. console1.log('animateScroll_: function - OK')
  10400.  
  10401. doHack = fnIntegrity(cProto.animateScroll_, '1.102.49')
  10402.  
  10403. } else {
  10404.  
  10405. console1.log('animateScroll_', typeof cProto.animateScroll_)
  10406. }
  10407.  
  10408. if (doHack) {
  10409.  
  10410. const querySelector = HTMLElement_.prototype.querySelector;
  10411. const U = (element) => ({
  10412. querySelector: (selector) => querySelector.call(element, selector)
  10413. });
  10414.  
  10415. cProto.animateScroll_ = function (a) {
  10416.  
  10417. const cnt = kRef(this);
  10418. if (!cnt) return;
  10419. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10420.  
  10421. // console.log('cProto.animateScroll_', tag) // yt-emoji-picker-renderer
  10422. if (!cnt.boundAnimateScroll39_) cnt.boundAnimateScroll39_ = cnt.animateScroll_.bind(mWeakRef(cnt));
  10423. cnt.lastAnimationTime_ || (cnt.lastAnimationTime_ = a);
  10424. a -= cnt.lastAnimationTime_;
  10425. 200 > a ? (U(cnt.hostElement).querySelector("#categories").scrollTop = cnt.animationStart_ + (cnt.animationEnd_ - cnt.animationStart_) * a / 200,
  10426. rafHub.request(cnt.boundAnimateScroll39_)) : (null != cnt.animationEnd_ && (U(cnt.hostElement).querySelector("#categories").scrollTop = cnt.animationEnd_),
  10427. cnt.animationEnd_ = cnt.animationStart_ = null,
  10428. cnt.lastAnimationTime_ = 0);
  10429. cnt.updateButtons_()
  10430. }
  10431.  
  10432. console1.log('ENABLE_RAF_HACK_EMOJI_PICKER', tag, "OK")
  10433. } else {
  10434.  
  10435. console1.log('ENABLE_RAF_HACK_EMOJI_PICKER', tag, "NG")
  10436. }
  10437.  
  10438. })();
  10439.  
  10440. console1.log("[End]");
  10441.  
  10442. groupEnd();
  10443. });
  10444. }
  10445.  
  10446. if (ENABLE_RAF_HACK_DOCKED_MESSAGE && rafHub !== null) {
  10447.  
  10448. customElements.whenDefined("yt-live-chat-docked-message").then(() => {
  10449.  
  10450. mightFirstCheckOnYtInit();
  10451. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-docked-message hacks");
  10452. console1.log("[Begin]");
  10453. (() => {
  10454.  
  10455. const tag = "yt-live-chat-docked-message"
  10456. const dummy = document.createElement(tag);
  10457.  
  10458. const cProto = getProto(dummy);
  10459. if (!cProto || !cProto.attached) {
  10460. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10461. return;
  10462. }
  10463.  
  10464. let doHack = false;
  10465. if (typeof cProto.detached === 'function' && typeof cProto.checkIntersections === 'function' && typeof cProto.onDockableMessagesChanged === 'function' && typeof cProto.boundCheckIntersections === 'undefined') {
  10466.  
  10467. // cancelable - this.intersectRAF <detached>
  10468. // yt-live-chat-docked-message
  10469. // boundCheckIntersections <-> checkIntersections
  10470. // onDockableMessagesChanged
  10471. // this.intersectRAF = window.requestAnimationFrame(this.boundCheckIntersections);
  10472.  
  10473. console1.log(`detached: function - OK`)
  10474. console1.log('checkIntersections: function - OK')
  10475. console1.log('onDockableMessagesChanged: function - OK')
  10476.  
  10477. doHack = fnIntegrity(cProto.detached, '0.32.22') && fnIntegrity(cProto.checkIntersections, '0.128.85') && fnIntegrity(cProto.onDockableMessagesChanged, '0.20.11')
  10478.  
  10479. } else {
  10480.  
  10481. console1.log('detached', typeof cProto.detached, 'NG')
  10482. console1.log('checkIntersections', typeof cProto.checkIntersections, 'NG')
  10483. console1.log('onDockableMessagesChanged', typeof cProto.onDockableMessagesChanged, 'NG')
  10484. }
  10485.  
  10486. if (doHack) {
  10487.  
  10488. cProto.__boundCheckIntersectionsSubstitutionFn__ = function () {
  10489. const cnt = this;
  10490. if (!cnt.i5zmk && typeof cnt.boundCheckIntersections === 'function' && typeof cnt.checkIntersections === 'function') {
  10491. cnt.i5zmk = 1
  10492. cnt.boundCheckIntersections = cnt.checkIntersections.bind(mWeakRef(cnt));
  10493. }
  10494. }
  10495.  
  10496. cProto.checkIntersections = function () {
  10497.  
  10498. const cnt = kRef(this);
  10499. if (!cnt) return;
  10500. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10501.  
  10502. if(typeof cnt.__boundCheckIntersectionsSubstitutionFn__ === 'function') cnt.__boundCheckIntersectionsSubstitutionFn__();
  10503.  
  10504. // console.log('cProto.checkIntersections', tag)
  10505. if (cnt.dockableMessages.length) {
  10506. cnt.intersectRAF = rafHub.request(cnt.boundCheckIntersections);
  10507. let a = cnt.dockableMessages[0]
  10508. , b = cnt.hostElement.getBoundingClientRect();
  10509. a = a.getBoundingClientRect();
  10510. let c = a.top - b.top
  10511. , d = 8 >= c;
  10512. c = 8 >= c - cnt.hostElement.clientHeight;
  10513. if (d) {
  10514. let e;
  10515. for (; d;) {
  10516. e = cnt.dockableMessages.shift();
  10517. d = cnt.dockableMessages[0];
  10518. if (!d)
  10519. break;
  10520. d = d.getBoundingClientRect();
  10521. c = d.top - b.top;
  10522. let f = 8 >= c;
  10523. if (8 >= c - a.height)
  10524. if (f)
  10525. a = d;
  10526. else
  10527. return;
  10528. d = f
  10529. }
  10530. cnt.dock(e)
  10531. } else
  10532. c && cnt.dockedItem && cnt.clear()
  10533. } else
  10534. cnt.intersectRAF = 0
  10535. }
  10536.  
  10537. cProto.onDockableMessagesChanged = function () {
  10538. const cnt = this;
  10539. if(typeof cnt.__boundCheckIntersectionsSubstitutionFn__ === 'function') cnt.__boundCheckIntersectionsSubstitutionFn__();
  10540. // console.log('cProto.onDockableMessagesChanged', tag) // yt-live-chat-docked-message
  10541. cnt.dockableMessages.length && !cnt.intersectRAF && (cnt.intersectRAF = rafHub.request(cnt.boundCheckIntersections))
  10542. }
  10543.  
  10544. cProto.detached = function () {
  10545. this.intersectRAF && rafHub.cancel(this.intersectRAF)
  10546. }
  10547.  
  10548. console1.log('ENABLE_RAF_HACK_DOCKED_MESSAGE', tag, "OK")
  10549. } else {
  10550.  
  10551. console1.log('ENABLE_RAF_HACK_DOCKED_MESSAGE', tag, "NG")
  10552. }
  10553.  
  10554. })();
  10555.  
  10556. console1.log("[End]");
  10557.  
  10558. groupEnd();
  10559.  
  10560. }).catch(console.warn);
  10561.  
  10562. }
  10563.  
  10564. if (FIX_SETSRC_AND_THUMBNAILCHANGE_) {
  10565.  
  10566. customElements.whenDefined("yt-img-shadow").then(() => {
  10567.  
  10568. mightFirstCheckOnYtInit();
  10569. groupCollapsed("YouTube Super Fast Chat", " | yt-img-shadow hacks");
  10570. console1.log("[Begin]");
  10571. (() => {
  10572.  
  10573. const tag = "yt-img-shadow"
  10574. const dummy = document.createElement(tag);
  10575.  
  10576. const cProto = getProto(dummy);
  10577. if (!cProto || !cProto.attached) {
  10578. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10579. return;
  10580. }
  10581.  
  10582. if (typeof cProto.thumbnailChanged_ === 'function' && !cProto.thumbnailChanged66_) {
  10583.  
  10584. cProto.thumbnailChanged66_ = cProto.thumbnailChanged_;
  10585. cProto.thumbnailChanged_ = function (a) {
  10586.  
  10587. if (this.oldThumbnail_ && this.thumbnail && this.oldThumbnail_.thumbnails === this.thumbnail.thumbnails) return;
  10588. if (!this.oldThumbnail_ && !this.thumbnail) return;
  10589.  
  10590. return this.thumbnailChanged66_.apply(this, arguments)
  10591.  
  10592. }
  10593. console1.log("cProto.thumbnailChanged_ - OK");
  10594.  
  10595. } else {
  10596. console1.log("cProto.thumbnailChanged_ - NG");
  10597.  
  10598. }
  10599. if (typeof cProto.setSrc_ === 'function' && !cProto.setSrc66_) {
  10600.  
  10601. cProto.setSrc66_ = cProto.setSrc_;
  10602. cProto.setSrc_ = function (a) {
  10603. if ((((this || 0).$ || 0).img || 0).src === a) return;
  10604. return this.setSrc66_.apply(this, arguments)
  10605. }
  10606.  
  10607. console1.log("cProto.setSrc_ - OK");
  10608. } else {
  10609.  
  10610. console1.log("cProto.setSrc_ - NG");
  10611. }
  10612.  
  10613. })();
  10614.  
  10615. console1.log("[End]");
  10616.  
  10617. groupEnd();
  10618.  
  10619. }).catch(console.warn);
  10620.  
  10621. }
  10622.  
  10623. if (FIX_THUMBNAIL_DATACHANGED) {
  10624.  
  10625. customElements.whenDefined("yt-live-chat-author-badge-renderer").then(() => {
  10626.  
  10627. mightFirstCheckOnYtInit();
  10628. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-author-badge-renderer hacks");
  10629. console1.log("[Begin]");
  10630. (() => {
  10631.  
  10632. const tag = "yt-live-chat-author-badge-renderer"
  10633. const dummy = document.createElement(tag);
  10634.  
  10635. const cProto = getProto(dummy);
  10636. if (!cProto || !cProto.attached) {
  10637. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10638. return;
  10639. }
  10640.  
  10641. if (typeof cProto.dataChanged === 'function' && !cProto.dataChanged86 && '|0.169.106|'.includes(`|${fnIntegrity(cProto.dataChanged)}|`)) {
  10642.  
  10643. cProto.dataChanged86 = cProto.dataChanged;
  10644. cProto.dataChanged = function () {
  10645.  
  10646. /* 2024.12.15 */
  10647. /*
  10648. zO.prototype.dataChanged = function() {
  10649. for (var a = Ov(R(this.hostElement).querySelector("#image")); a.firstChild; )
  10650. a.removeChild(a.firstChild);
  10651. if (this.data)
  10652. if (this.data.icon) {
  10653. var b = document.createElement("yt-icon");
  10654. this.data.icon.iconType === "MODERATOR" && this.enableNewModeratorBadge ? (b.polymerController.icon = "yt-sys-icons:shield-filled",
  10655. b.polymerController.defaultToFilled = !0) : b.polymerController.icon = "live-chat-badges:" + this.data.icon.iconType.toLowerCase();
  10656. a.appendChild(b)
  10657. } else if (this.data.customThumbnail) {
  10658. b = document.createElement("img");
  10659. var c;
  10660. (c = (c = UA(this.data.customThumbnail.thumbnails, 16)) ? Yb(kc(c)) : null) ? (b.src = c,
  10661. a.appendChild(b),
  10662. b.setAttribute("alt", this.hostElement.ariaLabel || "")) : Fq(new Zn("Could not compute URL for thumbnail",this.data.customThumbnail))
  10663. }
  10664. }
  10665. */
  10666.  
  10667. const a = (this || 0).data;
  10668. const image = ((this || 0).$ || 0).image;
  10669. if (image && a && image.firstElementChild) {
  10670. const exisiting = image.firstElementChild;
  10671. if (exisiting === image.lastElementChild) {
  10672.  
  10673. if (a.icon && exisiting.nodeName.toUpperCase() === 'YT-ICON') {
  10674.  
  10675. const c = exisiting;
  10676. const t = insp(c);
  10677. const w = ('icon' in t || 'defaultToFilled' in t) ? t : c;
  10678. if ("MODERATOR" === a.icon.iconType && this.enableNewModeratorBadge) {
  10679. if (w.icon !== "yt-sys-icons:shield-filled") w.icon = "yt-sys-icons:shield-filled";
  10680. if (w.defaultToFilled !== true) w.defaultToFilled = true;
  10681. } else {
  10682. const p = "live-chat-badges:" + a.icon.iconType.toLowerCase();;
  10683. if (w.icon !== p) w.icon = p;
  10684. if (w.defaultToFilled !== false) w.defaultToFilled = false;
  10685. }
  10686. return;
  10687.  
  10688.  
  10689. } else if (a.customThumbnail && exisiting.nodeName.toUpperCase() == 'IMG') {
  10690.  
  10691. const c = exisiting;
  10692. if (a.customThumbnail.thumbnails.map(e => e.url).includes(c.src)) {
  10693.  
  10694. c.setAttribute("alt", this.hostElement.ariaLabel || "");
  10695. return;
  10696. }
  10697. /*
  10698.  
  10699. var d;
  10700. (d = (d = KC(a.customThumbnail.thumbnails, 16)) ? lc(oc(d)) : null) ? (c.src = d,
  10701.  
  10702. c.setAttribute("alt", this.hostElement.ariaLabel || "")) : lq(new tm("Could not compute URL for thumbnail", a.customThumbnail))
  10703. */
  10704. }
  10705.  
  10706. }
  10707. }
  10708. return this.dataChanged86.apply(this, arguments)
  10709.  
  10710. }
  10711. console1.log("cProto.dataChanged - OK");
  10712.  
  10713. } else if (typeof cProto.dataChanged === 'function' && !cProto.dataChanged86 && '|1.163.100|1.162.100|1.160.97|1.159.97|'.includes(`|${fnIntegrity(cProto.dataChanged)}|`)) {
  10714.  
  10715. cProto.dataChanged86 = cProto.dataChanged;
  10716. cProto.dataChanged = function (a) {
  10717.  
  10718. /*
  10719.  
  10720. for (var b = xC(Z(this.hostElement).querySelector("#image")); b.firstChild; )
  10721. b.removeChild(b.firstChild);
  10722. if (a)
  10723. if (a.icon) {
  10724. var c = document.createElement("yt-icon");
  10725. "MODERATOR" === a.icon.iconType && this.enableNewModeratorBadge ? (c.icon = "yt-sys-icons:shield-filled",
  10726. c.defaultToFilled = !0) : c.icon = "live-chat-badges:" + a.icon.iconType.toLowerCase();
  10727. b.appendChild(c)
  10728. } else if (a.customThumbnail) {
  10729. c = document.createElement("img");
  10730. var d;
  10731. (d = (d = KC(a.customThumbnail.thumbnails, 16)) ? lc(oc(d)) : null) ? (c.src = d,
  10732. b.appendChild(c),
  10733. c.setAttribute("alt", this.hostElement.ariaLabel || "")) : lq(new tm("Could not compute URL for thumbnail",a.customThumbnail))
  10734. }
  10735.  
  10736. */
  10737.  
  10738.  
  10739. /* 2024.04.20 */
  10740. /*
  10741. for (var b = Tx(N(this.hostElement).querySelector("#image")); b.firstChild; )
  10742. b.removeChild(b.firstChild);
  10743. if (a)
  10744. if (a.icon) {
  10745. var c = document.createElement("yt-icon");
  10746. "MODERATOR" === a.icon.iconType && this.enableNewModeratorBadge ? (c.polymerController.icon = "yt-sys-icons:shield-filled",
  10747. c.polymerController.defaultToFilled = !0) : c.polymerController.icon = "live-chat-badges:" + a.icon.iconType.toLowerCase();
  10748. b.appendChild(c)
  10749. } else if (a.customThumbnail) {
  10750. c = document.createElement("img");
  10751. var d;
  10752. (d = (d = WD(a.customThumbnail.thumbnails, 16)) ? Sb(ec(d)) : null) ? (c.src = d,
  10753. b.appendChild(c),
  10754. c.setAttribute("alt", this.hostElement.ariaLabel || "")) : nr(new mn("Could not compute URL for thumbnail",a.customThumbnail))
  10755. }
  10756. */
  10757.  
  10758. const image = ((this || 0).$ || 0).image
  10759. if (image && a && image.firstElementChild) {
  10760. const exisiting = image.firstElementChild;
  10761. if (exisiting === image.lastElementChild) {
  10762.  
  10763. if (a.icon && exisiting.nodeName.toUpperCase() === 'YT-ICON') {
  10764.  
  10765. const c = exisiting;
  10766. const t = insp(c);
  10767. const w = ('icon' in t || 'defaultToFilled' in t) ? t : c;
  10768. if ("MODERATOR" === a.icon.iconType && this.enableNewModeratorBadge) {
  10769. if (w.icon !== "yt-sys-icons:shield-filled") w.icon = "yt-sys-icons:shield-filled";
  10770. if (w.defaultToFilled !== true) w.defaultToFilled = true;
  10771. } else {
  10772. const p = "live-chat-badges:" + a.icon.iconType.toLowerCase();;
  10773. if (w.icon !== p) w.icon = p;
  10774. if (w.defaultToFilled !== false) w.defaultToFilled = false;
  10775. }
  10776. return;
  10777.  
  10778.  
  10779. } else if (a.customThumbnail && exisiting.nodeName.toUpperCase() == 'IMG') {
  10780.  
  10781. const c = exisiting;
  10782. if (a.customThumbnail.thumbnails.map(e => e.url).includes(c.src)) {
  10783.  
  10784. c.setAttribute("alt", this.hostElement.ariaLabel || "");
  10785. return;
  10786. }
  10787. /*
  10788.  
  10789. var d;
  10790. (d = (d = KC(a.customThumbnail.thumbnails, 16)) ? lc(oc(d)) : null) ? (c.src = d,
  10791.  
  10792. c.setAttribute("alt", this.hostElement.ariaLabel || "")) : lq(new tm("Could not compute URL for thumbnail", a.customThumbnail))
  10793. */
  10794. }
  10795.  
  10796. }
  10797. }
  10798. return this.dataChanged86.apply(this, arguments)
  10799.  
  10800. }
  10801. console1.log("cProto.dataChanged - OK");
  10802.  
  10803. } else {
  10804. assertor(() => fnIntegrity(cProto.dataChanged, '0.169.106'));
  10805. console1.log("cProto.dataChanged - NG");
  10806.  
  10807. }
  10808.  
  10809. })();
  10810.  
  10811. console1.log("[End]");
  10812.  
  10813. groupEnd();
  10814.  
  10815. }).catch(console.warn);
  10816.  
  10817.  
  10818. }
  10819.  
  10820. if (USE_ADVANCED_TICKING) {
  10821. // leading the emoji cannot be rendered.
  10822.  
  10823. // const qz38 = lcrPromiseFn();
  10824.  
  10825. // qz38.then((lcrGet) => {
  10826.  
  10827. // const tag = "yt-live-chat-renderer"
  10828. // const dummy = lcrGet();
  10829.  
  10830. const lcrFn2 = (lcrDummy) => {
  10831.  
  10832. const tag = "yt-live-chat-renderer"
  10833. const dummy = lcrDummy;
  10834.  
  10835.  
  10836. const cProto = getProto(dummy);
  10837.  
  10838. // dummy.usePatchedLifecycles = false;
  10839. // dummy.data = null;
  10840. // dummy.__data = null;
  10841. // Object.setPrototypeOf(dummy, Object.prototype);
  10842. if (!cProto || !cProto.attached) {
  10843. console.warn(`proto.attached for ${tag} is unavailable.`);
  10844. return;
  10845. }
  10846.  
  10847. /*
  10848. <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;
  10849. */
  10850.  
  10851. if (cProto && typeof cProto.immediatelyApplyLiveChatActions === 'function' && cProto.immediatelyApplyLiveChatActions.length === 1 && !cProto.immediatelyApplyLiveChatActions82) {
  10852. cProto.immediatelyApplyLiveChatActions82 = cProto.immediatelyApplyLiveChatActions;
  10853. cProto.immediatelyApplyLiveChatActions = function (arr) {
  10854.  
  10855.  
  10856. // console.log(1237)
  10857. try {
  10858. preprocessChatLiveActions(arr);
  10859. } catch (e) {
  10860. console.warn(e);
  10861. }
  10862. return this.immediatelyApplyLiveChatActions82(arr);
  10863. };
  10864. }
  10865.  
  10866.  
  10867. if (cProto && typeof cProto.preprocessActions_ === 'function' && cProto.preprocessActions_.length === 1 && !cProto.preprocessActions82_) {
  10868. cProto.preprocessActions82_ = cProto.preprocessActions_;
  10869. cProto.preprocessActions_ = function (arr) {
  10870.  
  10871. const ct_ = Date.now();
  10872.  
  10873. arr = this.preprocessActions82_(arr);
  10874.  
  10875. try {
  10876. preprocessChatLiveActions(arr, ct_);
  10877. } catch (e) {
  10878. console.warn(e);
  10879. }
  10880. return arr;
  10881. };
  10882. }
  10883.  
  10884.  
  10885.  
  10886. };
  10887. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  10888. getLCRDummy().then(lcrFn2);
  10889. }
  10890.  
  10891. if (MODIFY_EMIT_MESSAGES_FOR_BOOST_CHAT) {
  10892.  
  10893. const lcrFn2 = (lcrDummy) => {
  10894.  
  10895. const tag = "yt-live-chat-renderer"
  10896. const dummy = lcrDummy;
  10897.  
  10898.  
  10899. const cProto = getProto(dummy);
  10900.  
  10901. // dummy.usePatchedLifecycles = false;
  10902. // dummy.data = null;
  10903. // dummy.__data = null;
  10904. // Object.setPrototypeOf(dummy, Object.prototype);
  10905. if (!cProto || !cProto.attached) {
  10906. console.warn(`proto.attached for ${tag} is unavailable.`);
  10907. return;
  10908. }
  10909.  
  10910. /*
  10911.  
  10912. // https://www.youtube.com/s/desktop/c01ea7e3/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  10913.  
  10914.  
  10915. YP.prototype.emitSmoothedMessages = function() {
  10916. this.JSC$10797_nextUpdateId = null;
  10917. if (this.JSC$10797_messageQueue.length) {
  10918. var a = 1E4;
  10919. this.JSC$10797_estimatedUpdateInterval !== null && this.JSC$10797_lastUpdateTime !== null && (a = this.JSC$10797_estimatedUpdateInterval - Date.now() + this.JSC$10797_lastUpdateTime);
  10920. var b = this.JSC$10797_messageQueue.length < a / 80 ? 1 : Math.ceil(this.JSC$10797_messageQueue.length / (a / 80));
  10921. var c = aba(this.JSC$10797_messageQueue.splice(0, b));
  10922. this.callback && this.callback(c);
  10923. this.JSC$10797_messageQueue.length && (b === 1 ? (b = a / this.JSC$10797_messageQueue.length,
  10924. b *= Math.random() + .5,
  10925. b = Math.min(1E3, b),
  10926. b = Math.max(80, b)) : b = 80,
  10927. this.JSC$10797_nextUpdateId = window.setTimeout(this.emitSmoothedMessages.bind(this), b))
  10928. }
  10929. }
  10930. // emitSmoothedMessages: say b = 1000, 858.24, 529.49, 357.15, 194.96, 82.12, 80, 80, 80 ....
  10931.  
  10932. */
  10933.  
  10934.  
  10935. const _flag0281_ = window._flag0281_;
  10936.  
  10937.  
  10938. if ((_flag0281_ & 0x40000) === 0x40000 && cProto && typeof cProto.preprocessActions_ === 'function' && cProto.preprocessActions_.length === 1 && !cProto.preprocessActions92_) {
  10939. // we can disable smooth message emitting if boost chat is enabled (0x40000)
  10940. let byPass = false;
  10941. let q33 = false;
  10942. let key_estimatedUpdateInterval = '';
  10943. let key_lastUpdateTime = '';
  10944. let key_messageQueue = '';
  10945. const emitSmoothedMessagesInstantFn = function () {
  10946. if (byPass) return this.emitSmoothedMessages018();
  10947. byPass = true;
  10948. try {
  10949. if (!q33) {
  10950. const keys = Object.getOwnPropertyNames(this);
  10951. for (const key of keys) {
  10952. if (`${key}`.endsWith('_estimatedUpdateInterval')) key_estimatedUpdateInterval = key;
  10953. else if (`${key}`.endsWith('_lastUpdateTime')) key_lastUpdateTime = key;
  10954. else if (`${key}`.endsWith('_messageQueue')) key_messageQueue = key;
  10955. else continue;
  10956. if (key_estimatedUpdateInterval && key_lastUpdateTime && key_messageQueue) break;
  10957. }
  10958. if (key_estimatedUpdateInterval && key_lastUpdateTime && key_messageQueue) {
  10959. q33 = true;
  10960. }
  10961. }
  10962. if (key_estimatedUpdateInterval && key_lastUpdateTime) {
  10963. this[key_estimatedUpdateInterval] = 78; // 80 - 2
  10964. this[key_lastUpdateTime] = Date.now() - 1;
  10965. }
  10966. } catch (e) { }
  10967. // console.log(19893,key_estimatedUpdateInterval, key_lastUpdateTime)
  10968. // make a = this.JSC$10797_estimatedUpdateInterval - Date.now() + this.JSC$10797_lastUpdateTime small
  10969.  
  10970. // this.JSC$10797_estimatedUpdateInterval = Date.now() + 1
  10971. // this.JSC$10797_lastUpdateTime = Date.now()
  10972.  
  10973. // if (!window.setTimeout837) {
  10974. // window.setTimeout837 = window.setTimeout;
  10975. // window.setTimeout838 = function (f, d) {
  10976. // if (arguments.length !== 2) return window.setTimeout837(...arguments);
  10977. // console.log(12883, d)
  10978. // return window.setTimeout837(f, d > 80 ? 80 : d)
  10979. // }
  10980. // }
  10981. // else if (window.setTimeout837 !== window.setTimeout) {
  10982. // window.setTimeout837 = window.setTimeout;
  10983. // }
  10984. // let r;
  10985. // if (window.setTimeout837 && window.setTimeout838) {
  10986. // window.setTimeout = window.setTimeout838;
  10987. // r = this.emitSmoothedMessages018();
  10988. // window.setTimeout = window.setTimeout837;
  10989. // } else {
  10990. // r = this.emitSmoothedMessages018();
  10991. // }
  10992. let doInNextCall = false;
  10993. try {
  10994. const messageQueue = key_messageQueue ? this[key_messageQueue] : null;
  10995. if (!messageQueue || !messageQueue.length) {
  10996.  
  10997. } else if (messageQueue.length > 255) {
  10998.  
  10999. } else if (!document.hidden) {
  11000.  
  11001. } else {
  11002. doInNextCall = true;
  11003. }
  11004. } catch (e) { }
  11005.  
  11006. let r;
  11007. if (doInNextCall) {
  11008. setTimeout_(() => this.emitSmoothedMessages019(), 250);
  11009. } else {
  11010. r = this.emitSmoothedMessages018();
  11011. }
  11012. byPass = false;
  11013. return r;
  11014. };
  11015. cProto.preprocessActions92_ = cProto.preprocessActions_;
  11016. cProto.preprocessActions_ = function (arr) {
  11017.  
  11018. arr = this.preprocessActions92_(arr);
  11019.  
  11020. try {
  11021.  
  11022. const smoothedQueue_ = this.smoothedQueue_;
  11023. if (smoothedQueue_ && !smoothedQueue_.__fix018__) {
  11024. smoothedQueue_.__fix018__ = true;
  11025. if (!smoothedQueue_.emitSmoothedMessages018 && typeof smoothedQueue_.emitSmoothedMessages === 'function' && smoothedQueue_.emitSmoothedMessages.length === 0) {
  11026. smoothedQueue_.emitSmoothedMessages018 = smoothedQueue_.emitSmoothedMessages;
  11027. smoothedQueue_.emitSmoothedMessages019 = emitSmoothedMessagesInstantFn;
  11028. smoothedQueue_.emitSmoothedMessages = emitSmoothedMessagesInstantFn;
  11029. }
  11030. }
  11031. } catch (e) {
  11032. console.warn(e);
  11033. }
  11034. return arr;
  11035. };
  11036. }
  11037.  
  11038.  
  11039.  
  11040.  
  11041. };
  11042. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  11043. getLCRDummy().then(lcrFn2);
  11044. }
  11045.  
  11046.  
  11047. if (FIX_TOOLTIP_DISPLAY) {
  11048.  
  11049. // ----------------------------------------------------------------------------------------------------
  11050.  
  11051. const checkPDGet = (pd) => {
  11052. return pd && pd.get && !pd.set && pd.enumerable && pd.configurable;
  11053. }
  11054.  
  11055. const tooltipUIWM = new WeakMap();
  11056. const tooltipInitProps = {};
  11057. const createTooltipIfRequired_ = function () {
  11058. let r;
  11059. if (tooltipUIWM.get(this) === void 0) {
  11060. const w = document.createElement;
  11061. let EU = null;
  11062. tooltipUIWM.set(this, null);
  11063. document.createElement = function () {
  11064. let r = w.apply(this, arguments);
  11065. EU = r;
  11066. return r;
  11067. };
  11068. r = this.createTooltipIfRequired14_();
  11069. document.createElement = w;
  11070. if (EU instanceof HTMLElement_ && EU.is) {
  11071. tooltipUIWM.set(this, EU);
  11072. EU.setAttribute('__nogc__', ''); // avoid gc process script
  11073.  
  11074. if (typeof EU.offset === 'number') tooltipInitProps['offset'] = EU.offset;
  11075. if (typeof EU.fitToVisibleBounds === 'boolean') tooltipInitProps['fitToVisibleBounds'] = EU.fitToVisibleBounds;
  11076. if (typeof EU.position === 'string') tooltipInitProps['position'] = EU.position;
  11077. if (typeof EU.for === 'string') tooltipInitProps['for'] = EU.for;
  11078.  
  11079. // this.__mcT__ = EU.outerHTML;
  11080. // EU.__dataX = JSON.stringify(EU.__data);
  11081. // EU.__dataY = Object.entries(EU);
  11082.  
  11083. // <<< FOR DEBUG >>>
  11084. // let kx;
  11085. // Object.defineProperty(EU, '_target', {
  11086. // get(){
  11087. // return kx;
  11088. // },
  11089. // set(nv){
  11090. // kx= nv;
  11091. // debugger;
  11092. // return true;
  11093. // }
  11094. // });
  11095. // <<< FOR DEBUG >>>
  11096.  
  11097. if (typeof Polymer !== 'undefined' && Polymer.__fixedGetOwnerRoot__ && Polymer.__fixedQuerySelector__) {
  11098.  
  11099. } else {
  11100. let eProto = null;
  11101. const euCnt = insp(EU);
  11102. if (checkPDGet(Object.getOwnPropertyDescriptor(euCnt.constructor.prototype || {}, 'target'))) {
  11103.  
  11104. eProto = euCnt.constructor.prototype;
  11105. } else if (checkPDGet(Object.getOwnPropertyDescriptor(EU.constructor.prototype || {}, 'target'))) {
  11106.  
  11107. eProto = EU.constructor.prototype;
  11108. }
  11109. if (eProto) {
  11110. delete eProto.target;
  11111. /*
  11112.  
  11113. get target() {
  11114. var a = Pv(this).parentNode, b = Pv(this).getOwnerRoot(), c;
  11115. this.for ? c = Pv(b).querySelector("#" + this.for) : c = a.nodeType == Node.DOCUMENT_FRAGMENT_NODE ? b.host : a;
  11116. return c
  11117. },
  11118. */
  11119. Object.defineProperty(eProto, 'target', {
  11120. get() {
  11121. const cnt = insp(this);
  11122. const hostElement = cnt.hostElement || cnt;
  11123. let a = hostElement.parentNode, b = hostElement.getRootNode();
  11124. const fr = cnt.for || hostElement.for;
  11125. return (fr ? b.querySelector("#" + fr) : a)
  11126. }
  11127. })
  11128. }
  11129. }
  11130. // setInterval(()=>EU.updatePosition(), 100)
  11131.  
  11132. } else {
  11133. tooltipUIWM.set(this, null);
  11134. }
  11135. } else {
  11136. r = this.createTooltipIfRequired14_();
  11137. }
  11138.  
  11139. const EU = tooltipUIWM.get(this);
  11140. if (EU) {
  11141. EU.remove();
  11142. if (typeof tooltipInitProps.offset === 'number') EU['offset'] = tooltipInitProps.offset;
  11143. if (typeof tooltipInitProps.fitToVisibleBounds === 'boolean') EU['fitToVisibleBounds'] = tooltipInitProps.fitToVisibleBounds;
  11144. try {
  11145. if (typeof tooltipInitProps.position === 'string') EU['position'] = tooltipInitProps.position;
  11146. if (typeof tooltipInitProps.for === 'string') EU['for'] = tooltipInitProps.for; else delete EU.for;
  11147. } catch (e) { }
  11148. }
  11149.  
  11150. // 2025.01.10 fix
  11151. const CS = EU;
  11152. if (!CS._showing && CS.__shady_parentNode && CS.__shady_parentNode !== CS.parentNode) {
  11153. if (CS.__shady_parentNode) {
  11154. try {
  11155. CS.__shady_parentNode.__shady_removeChild(CS);
  11156. } catch (e) { }
  11157. }
  11158. if (CS.__shady_parentNode) {
  11159. try {
  11160. CS.__shady_parentNode.removeChild(CS);
  11161. } catch (e) { }
  11162. }
  11163. if (CS.__shady_parentNode) {
  11164. try {
  11165. CS.__shady_parentNode.__shady_native_removeChild(CS);
  11166. } catch (e) { }
  11167. }
  11168. if (CS.__shady_parentNode) {
  11169. try {
  11170. __shady_native_removeChild.call(CS.__shady_parentNode, CS);
  11171. } catch (e) { }
  11172. }
  11173. if (CS.parentNode && !CS.__shady_parentNode) {
  11174. try {
  11175. __shady_native_removeChild.call(CS.parentNode, CS);
  11176. } catch (e) { }
  11177. }
  11178. }
  11179.  
  11180. return r;
  11181. };
  11182.  
  11183.  
  11184. // added in 2024.05.02
  11185. const lcrFn2 = (lcrDummy) => {
  11186.  
  11187. // console.log(8171, 99);
  11188. const tag = "yt-live-chat-renderer"
  11189. const dummy = lcrDummy;
  11190.  
  11191. const cProto = getProto(dummy);
  11192. if (!cProto || !cProto.attached) {
  11193. console.warn(`proto.attached for ${tag} is unavailable.`);
  11194. return;
  11195. }
  11196.  
  11197. /*
  11198. <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;
  11199. */
  11200.  
  11201. if (cProto && typeof cProto.createTooltipIfRequired_ === 'function' && cProto.createTooltipIfRequired_.length === 0 && !cProto.createTooltipIfRequired14_) {
  11202. cProto.createTooltipIfRequired14_ = cProto.createTooltipIfRequired_;
  11203. cProto.createTooltipIfRequired_ = createTooltipIfRequired_;
  11204. }
  11205.  
  11206. };
  11207. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  11208. getLCRDummy().then(lcrFn2);
  11209.  
  11210. // ----------------------------------------------------------------------------------------------------
  11211.  
  11212. customElements.whenDefined("tp-yt-paper-tooltip").then(() => {
  11213.  
  11214. mightFirstCheckOnYtInit();
  11215. groupCollapsed("YouTube Super Fast Chat", " | tp-yt-paper-tooltip hacks");
  11216. console1.log("[Begin]");
  11217. (() => {
  11218.  
  11219. const tag = "tp-yt-paper-tooltip"
  11220. const dummy = document.createElement(tag);
  11221.  
  11222. const cProto = getProto(dummy);
  11223. if (!cProto || !cProto.attached) {
  11224. console1.warn(`proto.attached for ${tag} is unavailable.`);
  11225. return;
  11226. }
  11227.  
  11228. if (typeof cProto.attached === 'function' && typeof cProto.detached === 'function' && cProto._readyClients && cProto._attachDom && cProto.ready && !cProto._readyClients43) {
  11229.  
  11230. cProto._readyClients43 = cProto._readyClients;
  11231. cProto._readyClients = function () {
  11232. // console.log(1238)
  11233.  
  11234. let r = cProto._readyClients43.apply(this, arguments);
  11235. if (this.$ && this.$$ && this.$.tooltip) this.root = null; // fix this.root = null != (b = a.root) ? b : this.host
  11236. return r;
  11237. }
  11238.  
  11239. console1.log("_readyClients - OK");
  11240.  
  11241. } else {
  11242. console1.log("_readyClients - NG");
  11243.  
  11244. }
  11245.  
  11246. if (typeof cProto.show === 'function' && !cProto.show17) {
  11247. cProto.show17 = cProto.show;
  11248. cProto.show = function () {
  11249.  
  11250. let r = this.show17.apply(this, arguments);
  11251. this._showing === true && Promise.resolve(this).then((cnt) => {
  11252. const tooltip = (cnt.$ || 0).tooltip;
  11253.  
  11254. if (tooltip && tooltip.firstElementChild === null) {
  11255. let text = tooltip.textContent;
  11256. if (typeof text === 'string' && text.length >= 2) {
  11257. tooltip.textContent = text.trim();
  11258. }
  11259. }
  11260. cnt = null;
  11261. }).catch(console.warn)
  11262. return r;
  11263. }
  11264.  
  11265. console1.log("trim tooltip content - OK");
  11266.  
  11267. } else {
  11268. console1.log("trim tooltip content - NG");
  11269.  
  11270. }
  11271.  
  11272.  
  11273. })();
  11274.  
  11275. console1.log("[End]");
  11276.  
  11277. groupEnd();
  11278.  
  11279. }).catch(console.warn);
  11280.  
  11281. }
  11282.  
  11283.  
  11284. if (FIX_CLICKING_MESSAGE_MENU_DISPLAY_ON_MOUSE_CLICK) {
  11285.  
  11286. const hookDocumentMouseDownSetupFn = () => {
  11287.  
  11288. let muzTimestamp = 0;
  11289. let nszDropdown = null;
  11290.  
  11291. const handlerObject = {
  11292.  
  11293. muHandler282: function (evt) {
  11294. // console.log(evt, 7, document.querySelector('tp-yt-iron-dropdown[focused].style-scope.yt-live-chat-app'))
  11295. if (!evt || !evt.isTrusted || !muzTimestamp) return;
  11296. const dropdown = nszDropdown;
  11297. muzTimestamp = 0;
  11298. nszDropdown = null;
  11299.  
  11300. const kurMPCe = kRef(currentMenuPivotWR) || 0;
  11301. const hostElement = kurMPCe.hostElement || kurMPCe; // should be always hostElement === kurMPCe ?
  11302. if (!hostElement.hasAttribute('menu-visible')) return;
  11303.  
  11304. const chatBanner = HTMLElement_.prototype.closest.call(hostElement, 'yt-live-chat-banner-renderer') || 0;
  11305. if (chatBanner) return;
  11306.  
  11307. if (dropdown && dropdown.positionTarget && hostElement.contains(dropdown.positionTarget)) {
  11308. muzTimestamp = Date.now();
  11309. evt.stopImmediatePropagation();
  11310. evt.stopPropagation();
  11311. Promise.resolve(dropdown).then((dropdown) => {
  11312. dropdown.cancel();
  11313. dropdown = null;
  11314. });
  11315. }
  11316.  
  11317. },
  11318.  
  11319. mlHandler282: function (evt) {
  11320. muzTimestamp = 0;
  11321. nszDropdown = null;
  11322. },
  11323.  
  11324. ckHandler282: function (evt) {
  11325. if (!evt || !evt.isTrusted || !muzTimestamp) return;
  11326. if (Date.now() - muzTimestamp < 40) {
  11327. muzTimestamp = Date.now();
  11328. evt.stopImmediatePropagation();
  11329. evt.stopPropagation();
  11330. }
  11331. },
  11332.  
  11333. tapHandler282: function (evt) {
  11334. if (!evt || !evt.isTrusted || !muzTimestamp) return;
  11335. if (Date.now() - muzTimestamp < 40) {
  11336. muzTimestamp = Date.now();
  11337. evt.stopImmediatePropagation();
  11338. evt.stopPropagation();
  11339. }
  11340. },
  11341.  
  11342. handleEvent(evt) {
  11343. if (evt) {
  11344. const kurMPCe = kRef(currentMenuPivotWR) || 0;
  11345. const kurMPCc = insp(kurMPCe);
  11346. const hostElement = kurMPCc.hostElement || kurMPCc;
  11347. if (!kurMPCc || kurMPCc.isAttached !== true || hostElement.isConnected !== true) return;
  11348. switch (evt.type) {
  11349. case 'mouseup':
  11350. return this.muHandler282(evt);
  11351. case 'mouseleave':
  11352. return this.mlHandler282(evt);
  11353. case 'tap':
  11354. return this.tapHandler282(evt);
  11355. case 'click':
  11356. return this.ckHandler282(evt);
  11357. }
  11358. }
  11359. }
  11360.  
  11361. }
  11362.  
  11363. document.addEventListener('mousedown', function (evt) {
  11364.  
  11365. if (!evt || !evt.isTrusted || !evt.target) return;
  11366.  
  11367. muzTimestamp = 0;
  11368. nszDropdown = null;
  11369.  
  11370. /** @type {HTMLElement | null} */
  11371. const kurMP = kRef(currentMenuPivotWR);
  11372. if (!kurMP) return;
  11373. const kurMPCe = HTMLElement_.prototype.closest.call(kurMP, '[menu-visible]') || 0; // element
  11374.  
  11375. if (!kurMPCe || !kurMPCe.hasAttribute('whole-message-clickable')) return;
  11376.  
  11377. const kurMPCc = insp(kurMPCe); // controller
  11378.  
  11379. if (!kurMPCc.isClickableChatRow111 || !kurMPCc.isClickableChatRow111() || !HTMLElement_.prototype.contains.call(kurMPCe, evt.target)) return;
  11380.  
  11381. const chatBanner = HTMLElement_.prototype.closest.call(kurMPCe, 'yt-live-chat-banner-renderer') || 0;
  11382. if (chatBanner) return;
  11383.  
  11384. let targetDropDown = null;
  11385. for (const dropdown of document.querySelectorAll('tp-yt-iron-dropdown.style-scope.yt-live-chat-app')) {
  11386. if (dropdown && dropdown.positionTarget === kurMP) {
  11387. targetDropDown = dropdown;
  11388. }
  11389. }
  11390.  
  11391. if (!targetDropDown) return;
  11392.  
  11393. if (evt.target.closest('ytd-menu-popup-renderer')) return;
  11394.  
  11395. if ((nszDropdown = targetDropDown)) {
  11396. muzTimestamp = Date.now();
  11397. evt.stopImmediatePropagation();
  11398. evt.stopPropagation();
  11399. currentMenuPivotWR = mWeakRef(kurMPCe);
  11400.  
  11401. const listenOpts = { capture: true, passive: false, once: true };
  11402.  
  11403. // remove unexcecuted eventHandler
  11404. document.removeEventListener('mouseup', handlerObject, listenOpts);
  11405. document.removeEventListener('mouseleave', handlerObject, listenOpts);
  11406. document.removeEventListener('tap', handlerObject, listenOpts);
  11407. document.removeEventListener('click', handlerObject, listenOpts);
  11408.  
  11409. // inject one time eventHandler to by pass events
  11410. document.addEventListener('mouseup', handlerObject, listenOpts);
  11411. document.addEventListener('mouseleave', handlerObject, listenOpts);
  11412. document.addEventListener('tap', handlerObject, listenOpts);
  11413. document.addEventListener('click', handlerObject, listenOpts);
  11414.  
  11415. }
  11416.  
  11417. }, true);
  11418.  
  11419. }
  11420.  
  11421.  
  11422. // yt-live-chat-paid-message-renderer ??
  11423.  
  11424. /*
  11425.  
  11426. [...(new Set([...document.querySelectorAll('*')].filter(e=>e.is&&('shouldSupportWholeItemClick' in e)).map(e=>e.is))).keys()]
  11427.  
  11428.  
  11429. "yt-live-chat-ticker-paid-message-item-renderer"
  11430. "yt-live-chat-ticker-paid-sticker-item-renderer"
  11431. "yt-live-chat-paid-message-renderer"
  11432. "yt-live-chat-text-message-renderer"
  11433. "yt-live-chat-paid-sticker-renderer"
  11434.  
  11435. */
  11436.  
  11437.  
  11438. whenDefinedMultiple([
  11439.  
  11440. "yt-live-chat-paid-message-renderer",
  11441. "yt-live-chat-membership-item-renderer",
  11442. "yt-live-chat-paid-sticker-renderer",
  11443. "yt-live-chat-text-message-renderer",
  11444. "yt-live-chat-auto-mod-message-renderer",
  11445.  
  11446. /*
  11447. "yt-live-chat-ticker-paid-message-item-renderer",
  11448. "yt-live-chat-ticker-paid-sticker-item-renderer",
  11449. "yt-live-chat-paid-message-renderer",
  11450. "yt-live-chat-text-message-renderer",
  11451. "yt-live-chat-paid-sticker-renderer",
  11452.  
  11453. "yt-live-chat-ticker-sponsor-item-renderer",
  11454. "yt-live-chat-banner-header-renderer",
  11455. "ytd-sponsorships-live-chat-gift-purchase-announcement-renderer",
  11456. "ytd-sponsorships-live-chat-header-renderer",
  11457. "ytd-sponsorships-live-chat-gift-redemption-announcement-renderer",
  11458.  
  11459.  
  11460.  
  11461.  
  11462. "yt-live-chat-auto-mod-message-renderer",
  11463. "yt-live-chat-text-message-renderer",
  11464. "yt-live-chat-paid-message-renderer",
  11465.  
  11466. "yt-live-chat-legacy-paid-message-renderer",
  11467. "yt-live-chat-membership-item-renderer",
  11468. "yt-live-chat-paid-sticker-renderer",
  11469. "yt-live-chat-donation-announcement-renderer",
  11470. "yt-live-chat-moderation-message-renderer",
  11471. "ytd-sponsorships-live-chat-gift-purchase-announcement-renderer",
  11472. "ytd-sponsorships-live-chat-gift-redemption-announcement-renderer",
  11473. "yt-live-chat-viewer-engagement-message-renderer",
  11474.  
  11475. */
  11476.  
  11477.  
  11478. ]).then(sTags => {
  11479. // return; // M33
  11480.  
  11481. mightFirstCheckOnYtInit();
  11482. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-message-renderer(s)... hacks");
  11483. console1.log("[Begin]");
  11484. let doMouseHook = false;
  11485.  
  11486. const dProto = {
  11487. isClickableChatRow111: function () {
  11488. return (
  11489. this.data && typeof this.shouldSupportWholeItemClick === 'function' && typeof this.hasModerationOverlayVisible === 'function' &&
  11490. this.data.contextMenuEndpoint && this.wholeMessageClickable && this.shouldSupportWholeItemClick() && !this.hasModerationOverlayVisible()
  11491. ); // follow .onItemTap(a)
  11492. }
  11493. };
  11494.  
  11495. for (const sTag of sTags) { // ##tag##
  11496.  
  11497.  
  11498. (() => {
  11499.  
  11500. const tag = sTag;
  11501. const dummy = document.createElement(tag);
  11502.  
  11503. const cProto = getProto(dummy);
  11504. if (!cProto || !cProto.attached) {
  11505. console1.warn(`proto.attached for ${tag} is unavailable.`);
  11506. return;
  11507. }
  11508.  
  11509. const dCnt = insp(dummy);
  11510. if ('wholeMessageClickable' in dCnt && typeof dCnt.hasModerationOverlayVisible === 'function' && typeof dCnt.shouldSupportWholeItemClick === 'function') {
  11511.  
  11512. cProto.isClickableChatRow111 = dProto.isClickableChatRow111;
  11513.  
  11514. const toHookDocumentMouseDown = typeof cProto.shouldSupportWholeItemClick === 'function' && typeof cProto.hasModerationOverlayVisible === 'function';
  11515.  
  11516. if (toHookDocumentMouseDown) {
  11517. doMouseHook = true;
  11518. }
  11519.  
  11520. console1.log("shouldSupportWholeItemClick - OK", tag);
  11521.  
  11522. } else {
  11523.  
  11524. console1.log("shouldSupportWholeItemClick - NG", tag);
  11525. }
  11526.  
  11527.  
  11528. })();
  11529.  
  11530. }
  11531.  
  11532.  
  11533. if (doMouseHook) {
  11534.  
  11535. hookDocumentMouseDownSetupFn();
  11536.  
  11537. console1.log("FIX_CLICKING_MESSAGE_MENU_DISPLAY_ON_MOUSE_CLICK - Doc MouseEvent OK");
  11538. }
  11539.  
  11540. console1.log("[End]");
  11541.  
  11542. groupEnd();
  11543.  
  11544.  
  11545. }).catch(console.warn);
  11546.  
  11547.  
  11548. // https://www.youtube.com/watch?v=oQzFi1NO7io
  11549.  
  11550.  
  11551. }
  11552.  
  11553. if (NO_ITEM_TAP_FOR_NON_STATIONARY_TAP) {
  11554. let targetElementCntWR = null;
  11555. let _e0 = null;
  11556. document.addEventListener('mousedown', (e) => {
  11557. if (!e || !e.isTrusted) return;
  11558. let element = e.target;
  11559. for (; element instanceof HTMLElement_; element = element.parentNode) {
  11560. if (element.is) break;
  11561. }
  11562. if (!element || !element.is) return;
  11563. if (element.closest('ytd-menu-popup-renderer')) return;
  11564. const cnt = insp(element);
  11565. if (typeof cnt.onItemTap === 'function') {
  11566. cnt._onItemTap_isNonStationary = 0;
  11567. const cProto = getProto(element);
  11568. if (!cProto.onItemTap366 && typeof cProto.onItemTap === 'function' && cProto.onItemTap.length === 1) {
  11569. cProto.onItemTap366 = cProto.onItemTap; // note: [onItemTap] .some(function(){...})
  11570. cProto.onItemTap = function (a) {
  11571. const t = this._onItemTap_isNonStationary;
  11572. this._onItemTap_isNonStationary = 0;
  11573. if (t > Date.now()) return;
  11574. return this.onItemTap366.apply(this, arguments)
  11575. }
  11576. }
  11577. _e0 = e;
  11578. targetElementCntWR = mWeakRef(cnt);
  11579. } else {
  11580. _e0 = null;
  11581. targetElementCntWR = null;
  11582. }
  11583. }, { capture: true, passive: true });
  11584.  
  11585. document.addEventListener('mouseup', (e) => {
  11586. if (!e || !e.isTrusted) return;
  11587. const e0 = _e0;
  11588. _e0 = null;
  11589. if (!e0) return;
  11590. const cnt = kRef(targetElementCntWR);
  11591. targetElementCntWR = null;
  11592. if (!cnt) return;
  11593. if (e.timeStamp - e0.timeStamp > TAP_ACTION_DURATION) {
  11594. cnt._onItemTap_isNonStationary = Date.now() + 40;
  11595. } else if (`${window.getSelection()}`.trim().replace(/[\u2000-\u200a\u202f\u2800\u200B\u200C\u200D\uFEFF]+/g, '').length >= 1) {
  11596. cnt._onItemTap_isNonStationary = Date.now() + 40;
  11597. } else {
  11598. const dx = e.clientX - e0.clientX;
  11599. const dy = e.clientY - e0.clientY;
  11600. const dd = Math.sqrt(dx * dx + dy * dy);
  11601. const ddmm = px2mm(dd);
  11602. if (ddmm > 1.0) {
  11603. cnt._onItemTap_isNonStationary = Date.now() + 40;
  11604. } else {
  11605. cnt._onItemTap_isNonStationary = 0;
  11606. }
  11607. }
  11608. }, { capture: true, passive: true });
  11609.  
  11610. }
  11611.  
  11612.  
  11613. const __showContextMenu_assign_lock_with_external_unlock_ = function (targetCnt) {
  11614.  
  11615. let rr = null;
  11616. const p1 = new Promise(resolve => {
  11617. rr = resolve;
  11618. });
  11619.  
  11620. const p1unlock = () => {
  11621. const f = rr;
  11622. if (f) {
  11623. rr = null;
  11624. f();
  11625. }
  11626. }
  11627.  
  11628. return {
  11629. p1,
  11630. p1unlock,
  11631. assignLock: (targetCnt, timeout) => {
  11632. targetCnt.__showContextMenu_assign_lock__(p1);
  11633. if (timeout) setTimeout(p1unlock, timeout);
  11634. }
  11635. }
  11636.  
  11637. }
  11638.  
  11639. if (PREREQUEST_CONTEXT_MENU_ON_MOUSE_DOWN) {
  11640.  
  11641. document.addEventListener('mousedown', function (evt) {
  11642.  
  11643. const maxloopDOMTreeElements = 4;
  11644. const maxloopYtCompontents = 4;
  11645. let j1 = 0;
  11646. let j2 = 0;
  11647. let target = (evt || 0).target || 0;
  11648. if (!target) return;
  11649. if (target.closest('ytd-menu-popup-renderer')) return;
  11650.  
  11651. while (target instanceof HTMLElement_) {
  11652. if (++j1 > maxloopDOMTreeElements) break;
  11653. if (typeof (target.is || insp(target).is || null) === 'string') break;
  11654. target = nodeParent(target);
  11655. }
  11656. const components = [];
  11657. while (target instanceof HTMLElement_) {
  11658. if (++j2 > maxloopYtCompontents) break;
  11659. const cnt = insp(target);
  11660. if (typeof (target.is || cnt.is || null) === 'string') {
  11661. components.push(target);
  11662. }
  11663. if (typeof cnt.showContextMenu === 'function') break;
  11664. target = target.parentComponent || cnt.parentComponent || null;
  11665. }
  11666. if (!(target instanceof HTMLElement_)) return;
  11667. const targetCnt = insp(target);
  11668. if (typeof targetCnt.handleGetContextMenuResponse_ !== 'function' || typeof targetCnt.handleGetContextMenuError !== 'function') {
  11669. console.log('Error Found: handleGetContextMenuResponse_ OR handleGetContextMenuError is not defined on a component with showContextMenu')
  11670. return;
  11671. }
  11672.  
  11673. const endpoint = (targetCnt.data || 0).contextMenuEndpoint
  11674. if (!endpoint) return;
  11675. if (targetCnt.opened || !targetCnt.isAttached) return;
  11676.  
  11677. if (typeof targetCnt.__cacheResolvedEndpointData__ !== 'function') {
  11678. console.log(`preRequest for showContextMenu in ${targetCnt.is} is not yet supported.`)
  11679. }
  11680.  
  11681. const targetDollar = indr(target);
  11682.  
  11683. let doPreRequest = false;
  11684. if (components.length >= 2 && components[0].id === 'menu-button' && (targetDollar || 0)['menu-button'] === components[0]) {
  11685. doPreRequest = true;
  11686. } else if (components.length === 1 && components[0] === target) {
  11687. doPreRequest = true;
  11688. } else if (components.length >= 2 && components[0].id === 'author-photo' && (targetDollar || 0)['author-photo'] === components[0]) {
  11689. doPreRequest = true;
  11690. }
  11691. if (doPreRequest === false) {
  11692. console.log('doPreRequest = fasle on showContextMenu', components);
  11693. return;
  11694. }
  11695.  
  11696. if (typeof targetCnt.__getCachedEndpointData__ !== 'function' || targetCnt.__getCachedEndpointData__(endpoint)) return;
  11697.  
  11698. if ((typeof targetCnt.__showContextMenu_mutex_unlock_isEmpty__ === 'function') && !targetCnt.__showContextMenu_mutex_unlock_isEmpty__()) {
  11699. console.log('preRequest on showContextMenu aborted due to stacked network request');
  11700. return;
  11701. }
  11702.  
  11703.  
  11704. const onSuccess = (a) => {
  11705. /*
  11706.  
  11707. dQ() && (a = a.response);
  11708. a.liveChatItemContextMenuSupportedRenderers && a.liveChatItemContextMenuSupportedRenderers.menuRenderer && this.showContextMenu_(a.liveChatItemContextMenuSupportedRenderers.menuRenderer);
  11709. a.actions && Eu(this.hostElement, "yt-live-chat-actions", [a.actions])
  11710.  
  11711. */
  11712.  
  11713. a = a.response || a;
  11714.  
  11715. if (!a) {
  11716. console.log('unexpected error in prerequest for showContextMenu.onSuccess');
  11717. return;
  11718. }
  11719.  
  11720. let z = null;
  11721. a.liveChatItemContextMenuSupportedRenderers && a.liveChatItemContextMenuSupportedRenderers.menuRenderer && (z = a.liveChatItemContextMenuSupportedRenderers.menuRenderer);
  11722.  
  11723. if (z) {
  11724. a = z;
  11725. targetCnt.__cacheResolvedEndpointData__(endpoint, a, true);
  11726. }
  11727.  
  11728. };
  11729. const onFailure = (a) => {
  11730.  
  11731. /*
  11732.  
  11733. if (a instanceof Error || a instanceof Object || a instanceof String)
  11734. var b = a;
  11735. hq(new xm("Error encountered calling GetLiveChatItemContextMenu",b))
  11736.  
  11737. */
  11738.  
  11739. targetCnt.__cacheResolvedEndpointData__(endpoint, null);
  11740. // console.log('onFailure', a)
  11741.  
  11742. };
  11743.  
  11744. if (doPreRequest) {
  11745.  
  11746. let propertyCounter = 0;
  11747. const pm1 = __showContextMenu_assign_lock_with_external_unlock_(targetCnt);
  11748. const p1Timeout = 800;
  11749. const proxyKey = '__$$__proxy_to_this__$$__' + Date.now();
  11750.  
  11751. try {
  11752.  
  11753. const onSuccessHelperFn = function () {
  11754. pm1.p1unlock();
  11755. if (propertyCounter !== 5) {
  11756. console.log('Error in prerequest for showContextMenu.onSuccessHelperFn')
  11757. return;
  11758. }
  11759. if (this[proxyKey] !== targetCnt) {
  11760. console.log('Error in prerequest for showContextMenu.this');
  11761. return;
  11762. }
  11763. onSuccess(...arguments);
  11764. };
  11765. const onFailureHelperFn = function () {
  11766. pm1.p1unlock();
  11767. if (propertyCounter !== 5) {
  11768. console.log('Error in prerequest for showContextMenu.onFailureHelperFn')
  11769. return;
  11770. }
  11771. if (this[proxyKey] !== targetCnt) {
  11772. console.log('Error in prerequest for showContextMenu.this');
  11773. return;
  11774. }
  11775. onFailure(...arguments);
  11776.  
  11777. }
  11778. const fakeTargetCnt = new Proxy({
  11779. __showContextMenu_forceNativeRequest__: 1,
  11780. get handleGetContextMenuResponse_() {
  11781. propertyCounter += 2;
  11782. return onSuccessHelperFn;
  11783. },
  11784. get handleGetContextMenuError() {
  11785. propertyCounter += 3;
  11786. return onFailureHelperFn;
  11787. }
  11788. }, {
  11789. get(_, key, receiver) {
  11790. if (key in _) return _[key];
  11791. if (key === proxyKey) return targetCnt;
  11792.  
  11793. let giveNative = false;
  11794. if (key in targetCnt) {
  11795. if (key === 'data') giveNative = true;
  11796. else if (typeof targetCnt[key] === 'function') giveNative = true;
  11797. }
  11798. if (giveNative) return targetCnt[key];
  11799. }
  11800. });
  11801.  
  11802. const fakeEvent = (() => {
  11803. const { target, bubbles, cancelable, cancelBubble, srcElement, timeStamp, defaultPrevented, currentTarget, composed } = evt;
  11804. const nf = function () { }
  11805. const [stopPropagation, stopImmediatePropagation, preventDefault] = [nf, nf, nf];
  11806.  
  11807. return {
  11808. type: 'tap',
  11809. eventPhase: 0,
  11810. isTrusted: false,
  11811. __composed: true,
  11812. bubbles, cancelable, cancelBubble, timeStamp,
  11813. target, srcElement, defaultPrevented, currentTarget, composed,
  11814. stopPropagation, stopImmediatePropagation, preventDefault
  11815. };
  11816. })(evt);
  11817. targetCnt.showContextMenu.call(fakeTargetCnt, fakeEvent);
  11818.  
  11819.  
  11820. } catch (e) {
  11821. console.warn(e);
  11822. propertyCounter = 7;
  11823.  
  11824. }
  11825. if (propertyCounter !== 5) {
  11826. console.log('Error in prerequest for showContextMenu', propertyCounter);
  11827. return;
  11828. }
  11829.  
  11830. pm1.assignLock(targetCnt, p1Timeout);
  11831.  
  11832. }
  11833.  
  11834.  
  11835.  
  11836.  
  11837.  
  11838.  
  11839. }, true);
  11840.  
  11841.  
  11842. }
  11843.  
  11844.  
  11845.  
  11846. /*
  11847.  
  11848. const w=new Set(); for(const a of document.getElementsByTagName('*')) if(a.showContextMenu && a.showContextMenu_) w.add(a.is||''); console.log([...w.keys()])
  11849.  
  11850. */
  11851.  
  11852. whenDefinedMultiple([
  11853. "yt-live-chat-ticker-sponsor-item-renderer",
  11854. "yt-live-chat-ticker-paid-message-item-renderer",
  11855.  
  11856. "yt-live-chat-banner-header-renderer",
  11857. "yt-live-chat-text-message-renderer",
  11858. "ytd-sponsorships-live-chat-gift-purchase-announcement-renderer",
  11859. "ytd-sponsorships-live-chat-header-renderer",
  11860. "ytd-sponsorships-live-chat-gift-redemption-announcement-renderer",
  11861.  
  11862. "yt-live-chat-paid-sticker-renderer",
  11863. "yt-live-chat-viewer-engagement-message-renderer",
  11864. "yt-live-chat-paid-message-renderer"
  11865.  
  11866.  
  11867.  
  11868.  
  11869. ]).then(sTags => {
  11870.  
  11871. mightFirstCheckOnYtInit();
  11872. groupCollapsed("YouTube Super Fast Chat", " | fixShowContextMenu");
  11873. console1.log("[Begin]");
  11874.  
  11875.  
  11876. const __showContextMenu_mutex__ = new Mutex();
  11877. let __showContextMenu_mutex_unlock__ = null;
  11878. let lastShowMenuTarget = null;
  11879.  
  11880.  
  11881.  
  11882.  
  11883. const wm37 = new WeakMap();
  11884.  
  11885. const dProto = {
  11886.  
  11887.  
  11888. // CACHE_SHOW_CONTEXT_MENU_FOR_REOPEN
  11889.  
  11890. __cacheResolvedEndpointData__: (endpoint, a, doDeepCopy) => {
  11891. if (a) {
  11892. if (doDeepCopy) a = deepCopy(a);
  11893. wm37.set(endpoint, a);
  11894. } else {
  11895. wm37.remove(endpoint);
  11896. }
  11897. },
  11898. __getCachedEndpointData__: function (endpoint) {
  11899. endpoint = endpoint || (this.data || 0).contextMenuEndpoint || 0;
  11900. if (endpoint) return wm37.get(endpoint);
  11901. return null;
  11902. },
  11903. /** @type {(resolvedEndpoint: any) => void 0} */
  11904. __showCachedContextMenu__: function (resolvedEndpoint) { // non-null
  11905.  
  11906. resolvedEndpoint = deepCopy(resolvedEndpoint);
  11907. // let b = deepCopy(resolvedEndpoint, ['trackingParams', 'clickTrackingParams'])
  11908. Promise.resolve(resolvedEndpoint).then((resolvedEndpoint) => {
  11909. this.__showContextMenu_skip_cacheResolvedEndpointData__ = 1;
  11910. this.showContextMenu_(resolvedEndpoint);
  11911. this.__showContextMenu_skip_cacheResolvedEndpointData__ = 0;
  11912. resolvedEndpoint = null;
  11913. });
  11914.  
  11915.  
  11916. },
  11917.  
  11918.  
  11919.  
  11920. showContextMenuForCacheReopen: function (a) {
  11921. if (this && this.__showContextMenu_forceNativeRequest__) return this.showContextMenu37(a);
  11922. if (!this || !this.isAttached) return; // in case; avoid Error: No provider for: InjectionToken(NETWORK_TOKEN) in _.showContextMenu
  11923. if (!this.__showContextMenu_forceNativeRequest__) {
  11924. const endpoint = (this.data || 0).contextMenuEndpoint || 0;
  11925. if (endpoint) {
  11926. const resolvedEndpoint = this.__getCachedEndpointData__(endpoint);
  11927. if (resolvedEndpoint) {
  11928. this.__showCachedContextMenu__(resolvedEndpoint);
  11929. a && a.stopPropagation()
  11930. return;
  11931. }
  11932. }
  11933. }
  11934. return this.showContextMenu37(a);
  11935. },
  11936.  
  11937. showContextMenuForCacheReopen_: function (a) {
  11938. if (this && this.__showContextMenu_forceNativeRequest__) return this.showContextMenu37_(a);
  11939. if (!this || !this.isAttached) return; // in case; avoid Error: No provider for: InjectionToken(NETWORK_TOKEN) in _.showContextMenu
  11940. if (!this.__showContextMenu_skip_cacheResolvedEndpointData__) {
  11941. const endpoint = (this.data || 0).contextMenuEndpoint || 0;
  11942. if (endpoint) {
  11943. const f = this.__cacheResolvedEndpointData__;
  11944. if (typeof f === 'function') f(endpoint, a, true);
  11945. }
  11946. }
  11947. return this.showContextMenu37_(a);
  11948. },
  11949.  
  11950. // ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU
  11951.  
  11952. showContextMenuWithDisableScroll: function (a) {
  11953.  
  11954. const endpoint = (this.data || 0).contextMenuEndpoint || 0;
  11955. if (endpoint && typeof this.is === 'string' && this.menuVisible === false && this.menuOpen === false) {
  11956.  
  11957. const parentComponent = this.parentComponent;
  11958. if (parentComponent && parentComponent.is === 'yt-live-chat-item-list-renderer' && parentComponent.contextMenuOpen === false && parentComponent.allowScroll === true) {
  11959. parentComponent.contextMenuOpen = true; // computeAllowScroll_(contextMenuOpen, moderationModeEnabled): allowScroll = !(contextMenuOpen || moderationModeEnabled)
  11960. }
  11961. }
  11962.  
  11963. return this.showContextMenu48.apply(this, arguments);
  11964.  
  11965. },
  11966.  
  11967. // ENABLE_MUTEX_FOR_SHOW_CONTEXT_MENU
  11968.  
  11969. __showContextMenu_mutex_unlock_isEmpty__: () => {
  11970. return __showContextMenu_mutex_unlock__ === null;
  11971. },
  11972.  
  11973. __showContextMenu_assign_lock__: function (p) {
  11974.  
  11975. const mutex = __showContextMenu_mutex__;
  11976.  
  11977. mutex.lockWith(unlock => {
  11978. p.then(unlock);
  11979. p = null;
  11980. unlock = null;
  11981. });
  11982.  
  11983. },
  11984.  
  11985. showContextMenuWithMutex: function (a) {
  11986. if (this.__showContextMenu_forceNativeRequest__) return this.showContextMenu47(a);
  11987. if (!this || !this.isAttached) return; // in case; avoid Error: No provider for: InjectionToken(NETWORK_TOKEN) in _.showContextMenu
  11988. lastShowMenuTarget = this;
  11989. const wNode = mWeakRef(this);
  11990.  
  11991.  
  11992. const mutex = __showContextMenu_mutex__;
  11993.  
  11994. mutex.lockWith(unlock => {
  11995. const cnt = kRef(wNode);
  11996. if (lastShowMenuTarget !== cnt || !cnt) {
  11997. unlock();
  11998. return;
  11999. }
  12000.  
  12001. setTimeout(unlock, 800); // in case network failure
  12002. __showContextMenu_mutex_unlock__ = unlock;
  12003. try {
  12004. cnt.showContextMenu47(a);
  12005. } catch (e) {
  12006. console.warn(e);
  12007. unlock(); // in case function script error
  12008. }
  12009.  
  12010. });
  12011.  
  12012.  
  12013. },
  12014.  
  12015. showContextMenuWithMutex_: function (a) {
  12016.  
  12017. if (__showContextMenu_mutex_unlock__ && this === lastShowMenuTarget) {
  12018. __showContextMenu_mutex_unlock__();
  12019. __showContextMenu_mutex_unlock__ = null;
  12020. }
  12021. return this.showContextMenu47_(a);
  12022.  
  12023. }
  12024.  
  12025. }
  12026.  
  12027. for (const tag of sTags) { // ##tag##
  12028.  
  12029. (() => {
  12030.  
  12031. const dummy = document.createElement(tag);
  12032.  
  12033. const cProto = getProto(dummy);
  12034. if (!cProto || !cProto.attached) {
  12035. console1.warn(`proto.attached for ${tag} is unavailable.`);
  12036. return;
  12037. }
  12038.  
  12039.  
  12040. 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) {
  12041. cProto.showContextMenu37_ = cProto.showContextMenu_;
  12042. cProto.showContextMenu37 = cProto.showContextMenu;
  12043. cProto.__showContextMenu_forceNativeRequest__ = 0;
  12044. cProto.__cacheResolvedEndpointData__ = dProto.__cacheResolvedEndpointData__
  12045. cProto.__getCachedEndpointData__ = dProto.__getCachedEndpointData__
  12046. cProto.__showCachedContextMenu__ = dProto.__showCachedContextMenu__
  12047. cProto.showContextMenu = dProto.showContextMenuForCacheReopen;
  12048. cProto.showContextMenu_ = dProto.showContextMenuForCacheReopen_;
  12049. console1.log("CACHE_SHOW_CONTEXT_MENU_FOR_REOPEN - OK", tag);
  12050. } else {
  12051. console1.log("CACHE_SHOW_CONTEXT_MENU_FOR_REOPEN - NG", tag);
  12052. }
  12053.  
  12054. 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) {
  12055. cProto.showContextMenu48 = cProto.showContextMenu;
  12056. cProto.showContextMenu = dProto.showContextMenuWithDisableScroll;
  12057. console1.log("ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU - OK", tag);
  12058. } else if (!ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU) {
  12059. DEBUG_skipLog001 || console1.log("ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU - N/A", tag);
  12060. } else {
  12061. console1.log("ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU - NG", tag);
  12062. }
  12063.  
  12064.  
  12065. 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) {
  12066. cProto.showContextMenu47_ = cProto.showContextMenu_;
  12067. cProto.showContextMenu47 = cProto.showContextMenu;
  12068. cProto.__showContextMenu_mutex_unlock_isEmpty__ = dProto.__showContextMenu_mutex_unlock_isEmpty__;
  12069. cProto.__showContextMenu_assign_lock__ = dProto.__showContextMenu_assign_lock__;
  12070. cProto.showContextMenu = dProto.showContextMenuWithMutex;
  12071. cProto.showContextMenu_ = dProto.showContextMenuWithMutex_;
  12072. console1.log("ENABLE_MUTEX_FOR_SHOW_CONTEXT_MENU - OK", tag);
  12073. } else {
  12074. console1.log("ENABLE_MUTEX_FOR_SHOW_CONTEXT_MENU - NG", tag);
  12075. }
  12076.  
  12077. })();
  12078.  
  12079. }
  12080.  
  12081. console1.log("[End]");
  12082.  
  12083. groupEnd();
  12084.  
  12085. }).catch(console.warn);
  12086.  
  12087.  
  12088.  
  12089. if (FIX_UNKNOWN_BUG_FOR_OVERLAY) {
  12090. // this is to fix " TypeError: this.backdropElement.prepare is not a function "
  12091.  
  12092. customElements.whenDefined('tp-yt-paper-dialog').then(() => {
  12093.  
  12094.  
  12095. mightFirstCheckOnYtInit();
  12096. groupCollapsed("YouTube Super Fast Chat", " | tp-yt-paper-dialog hacks");
  12097. console1.log("[Begin]");
  12098. (() => {
  12099.  
  12100. const tag = "tp-yt-paper-dialog";
  12101. const dummy = document.createElement(tag);
  12102.  
  12103. const cProto = getProto(dummy);
  12104. if (!cProto || !cProto.attached) {
  12105. console1.warn(`proto.attached for ${tag} is unavailable.`);
  12106. return;
  12107. }
  12108.  
  12109. if (typeof cProto.__openedChanged === 'function' && !cProto.__openedChanged49 && cProto.__openedChanged.length === 0) {
  12110.  
  12111.  
  12112. cProto.__openedChanged49 = cProto.__openedChanged;
  12113.  
  12114. cProto.__openedChanged = function () {
  12115. const manager = (this || 0)._manager || 0;
  12116. if (manager && !manager.trackBackdrop49 && manager.trackBackdrop) {
  12117. manager.trackBackdrop49 = manager.trackBackdrop;
  12118. if (manager.trackBackdrop.length === 0) {
  12119. manager.trackBackdrop = function () {
  12120. try {
  12121. return this.trackBackdrop49();
  12122. } catch (e) {
  12123. let showMessage = true;
  12124. if (e instanceof TypeError && e.message === 'this.backdropElement.prepare is not a function') {
  12125. // this is well known issue.
  12126. showMessage = false;
  12127. }
  12128. showMessage && console.log('manager.trackBackdrop', e);
  12129. }
  12130. }
  12131. }
  12132. }
  12133. return this.__openedChanged49();
  12134. };
  12135.  
  12136.  
  12137. }
  12138.  
  12139.  
  12140. })();
  12141.  
  12142.  
  12143. console1.log("[End]");
  12144.  
  12145. groupEnd();
  12146.  
  12147.  
  12148. }).catch(console.warn);
  12149.  
  12150. }
  12151.  
  12152.  
  12153. customElements.whenDefined('tp-yt-iron-dropdown').then(() => {
  12154.  
  12155. mightFirstCheckOnYtInit();
  12156. groupCollapsed("YouTube Super Fast Chat", " | tp-yt-iron-dropdown hacks");
  12157. console1.log("[Begin]");
  12158. (() => {
  12159.  
  12160. const tag = "tp-yt-iron-dropdown";
  12161. const dummy = document.createElement(tag);
  12162.  
  12163. const cProto = getProto(dummy);
  12164. if (!cProto || !cProto.attached) {
  12165. console1.warn(`proto.attached for ${tag} is unavailable.`);
  12166. return;
  12167. }
  12168.  
  12169. if (USE_VANILLA_DEREF && typeof cProto.__deraf === 'function' && cProto.__deraf.length === 2 && !cProto.__deraf34 && fnIntegrity(cProto.__deraf) === '2.42.24') {
  12170. cProto.__deraf_hn__ = function (sId, fn) {
  12171. const rhKey = `_rafHandler_${sId}`;
  12172. const m = this[rhKey] || (this[rhKey] = new WeakMap());
  12173. if (m.has(fn)) return m.get(fn);
  12174. const resFn = () => {
  12175. this.__rafs[sId] = null;
  12176. fn.call(this)
  12177. };
  12178. m.set(fn, resFn);
  12179. m.set(resFn, resFn);
  12180. return resFn;
  12181. };
  12182. cProto.__deraf34 = cProto.__deraf;
  12183. cProto.__deraf = function (a, b) { // sId, fn
  12184. let c = this.__rafs;
  12185. null !== c[a] && cancelAnimationFrame(c[a]);
  12186. c[a] = requestAnimationFrame(this.__deraf_hn__(a, b));
  12187. };
  12188. console1.log("USE_VANILLA_DEREF - OK");
  12189. } else {
  12190. console1.log("USE_VANILLA_DEREF - NG");
  12191. }
  12192.  
  12193. if (FIX_DROPDOWN_DERAF && typeof cProto.__deraf === 'function' && cProto.__deraf.length === 2 && !cProto.__deraf66) {
  12194. cProto.__deraf66 = cProto.__deraf;
  12195. cProto.__deraf = function (sId, fn) {
  12196. if (this.__byPassRAF__) {
  12197. Promise.resolve(this).then((cnt) => {
  12198. fn.call(cnt);
  12199. cnt = null;
  12200. });
  12201. }
  12202. let r = this.__deraf66.apply(this, arguments);
  12203. return r;
  12204. }
  12205. console1.log("FIX_DROPDOWN_DERAF - OK");
  12206. } else {
  12207. console1.log("FIX_DROPDOWN_DERAF - NG");
  12208. }
  12209.  
  12210.  
  12211. if (BOOST_MENU_OPENCHANGED_RENDERING && typeof cProto.__openedChanged === 'function' && !cProto.__mtChanged__ && fnIntegrity(cProto.__openedChanged) === '0.46.20') {
  12212.  
  12213. let lastClose = null;
  12214. let lastOpen = null;
  12215. let cid = 0;
  12216.  
  12217. cProto.__mtChanged__ = function (b) {
  12218.  
  12219. Promise.resolve(this).then((cnt) => {
  12220. cnt._applyFocus();
  12221. return cnt;
  12222. }).then((cnt) => {
  12223. b ? cnt._renderOpened() : cnt._renderClosed();
  12224. cnt = null;
  12225. }).catch(console.warn);
  12226.  
  12227. };
  12228.  
  12229. const __moChanged__ = () => {
  12230. if (!cid) return;
  12231. // console.log(553, !!lastOpen, !!lastClose);
  12232. cid = 0;
  12233. if (lastOpen && !lastClose && lastOpen.isAttached) {
  12234. lastOpen.__mtChanged__(1)
  12235. } else if (lastClose && !lastOpen && lastClose.isAttached) {
  12236. lastClose.__mtChanged__(0);
  12237. }
  12238. lastOpen = null;
  12239. lastClose = null;
  12240. };
  12241.  
  12242.  
  12243. if (typeof cProto._openedChanged === 'function' && !cProto._openedChanged66) {
  12244. cProto._openedChanged66 = cProto._openedChanged;
  12245. cProto._openedChanged = function () {
  12246. // this.__byPassRAF__ = !lastOpen ? true : false; // or just true?
  12247. this.__byPassRAF__ = true;
  12248. let r = this._openedChanged66.apply(this, arguments);
  12249. this.__byPassRAF__ = false;
  12250. return r;
  12251. }
  12252. }
  12253.  
  12254. const pSetGet = (key, pdThis, pdBase) => {
  12255. // note: this is not really a standard way for the getOwnPropertyDescriptors; but it is sufficient to make the job done
  12256. return {
  12257. get: (pdThis[key] || 0).get || (pdBase[key] || 0).get,
  12258. set: (pdThis[key] || 0).set || (pdBase[key] || 0).set
  12259. };
  12260. };
  12261.  
  12262. cProto.__modifiedMenuPropsFn__ = function () {
  12263. const pdThis = Object.getOwnPropertyDescriptors(this.constructor.prototype)
  12264. const pdBase = Object.getOwnPropertyDescriptors(this)
  12265.  
  12266. const pdAutoFitOnAttach = pSetGet('autoFitOnAttach', pdThis, pdBase);
  12267. const pdExpandSizingTargetForScrollbars = pSetGet('expandSizingTargetForScrollbars', pdThis, pdBase);
  12268. const pdAllowOutsideScroll = pSetGet('allowOutsideScroll', pdThis, pdBase);
  12269.  
  12270. if (pdAutoFitOnAttach.get || pdAutoFitOnAttach.set) {
  12271. console.warn('there is setter/getter for autoFitOnAttach');
  12272. return;
  12273. }
  12274. if (pdExpandSizingTargetForScrollbars.get || pdExpandSizingTargetForScrollbars.set) {
  12275. console.warn('there is setter/getter for expandSizingTargetForScrollbars');
  12276. return;
  12277. }
  12278. if (!pdAllowOutsideScroll.get || !pdAllowOutsideScroll.set) {
  12279. console.warn('there is NO setter-getter for allowOutsideScroll');
  12280. return;
  12281. }
  12282.  
  12283. let { autoFitOnAttach, expandSizingTargetForScrollbars, allowOutsideScroll } = this;
  12284.  
  12285. this.__AllowOutsideScrollPD__ = pdAllowOutsideScroll;
  12286.  
  12287. const fitEnable = CHAT_MENU_REFIT_ALONG_SCROLLING === 2;
  12288.  
  12289. Object.defineProperties(this, {
  12290. autoFitOnAttach: {
  12291. get() {
  12292. if (fitEnable && this._modifiedMenuPropOn062__) return true;
  12293. return autoFitOnAttach;
  12294. },
  12295. set(nv) {
  12296. autoFitOnAttach = nv;
  12297. return true;
  12298. },
  12299. enumerable: true,
  12300. configurable: true
  12301. }, expandSizingTargetForScrollbars: {
  12302. get() {
  12303. if (fitEnable && this._modifiedMenuPropOn062__) return true;
  12304. return expandSizingTargetForScrollbars;
  12305. },
  12306. set(nv) {
  12307. expandSizingTargetForScrollbars = nv;
  12308. return true;
  12309. },
  12310. enumerable: true,
  12311. configurable: true
  12312. }, allowOutsideScroll: {
  12313. get() {
  12314. if (this._modifiedMenuPropOn062__) return true;
  12315. return allowOutsideScroll;
  12316. },
  12317. set(nv) {
  12318. allowOutsideScroll = nv;
  12319. this.__AllowOutsideScrollPD__.set.call(this, nv);
  12320. return true;
  12321. },
  12322. enumerable: true,
  12323. configurable: true
  12324. }
  12325. })
  12326. };
  12327.  
  12328. /*
  12329. // ***** position() to be changed. *****
  12330. tp-yt-iron-dropdown[class], tp-yt-iron-dropdown[class] #contentWrapper, tp-yt-iron-dropdown[class] ytd-menu-popup-renderer[class] {
  12331.  
  12332. overflow: visible !important;
  12333. min-width: max-content !important;
  12334. max-width: max-content !important;
  12335. max-height: max-content !important;
  12336. min-height: max-content !important;
  12337. white-space: nowrap;
  12338. }
  12339.  
  12340. */
  12341. if (FIX_MENU_POSITION_N_SIZING_ON_SHOWN && typeof cProto.position === 'function' && !cProto.position34 && typeof cProto.refit === 'function') {
  12342.  
  12343. let m34 = 0;
  12344. cProto.__refitByPosition__ = function () {
  12345. m34++;
  12346. if (m34 <= 0) m34 = 0;
  12347. if (m34 !== 1) return;
  12348. const hostElement = this.hostElement || this;
  12349. if (document.visibilityState === 'visible') {
  12350. const sizingTarget = this.sizingTarget;
  12351. if (!sizingTarget) {
  12352. m34 = 0;
  12353. return;
  12354. }
  12355. hostElement.setAttribute('rNgzQ', '');
  12356. sizingTarget.setAttribute('rNgzQ', '');
  12357.  
  12358. const gn = () => {
  12359. hostElement.removeAttribute('rNgzQ');
  12360. sizingTarget.removeAttribute('rNgzQ');
  12361. }
  12362.  
  12363. const an = async () => {
  12364. while (m34 >= 1) {
  12365. await renderReadyPn(sizingTarget);
  12366. if (this.opened && this.isAttached && sizingTarget.isConnected === true && sizingTarget === this.sizingTarget) {
  12367. if (sizingTarget.matches('ytd-menu-popup-renderer[slot="dropdown-content"].yt-live-chat-app')) this.refit();
  12368. }
  12369. m34--;
  12370. }
  12371. m34 = 0;
  12372. Promise.resolve().then(gn);
  12373. }
  12374. setTimeout(an, 4); // wait those resizing function calls
  12375.  
  12376.  
  12377. } else {
  12378. m34 = 0;
  12379. }
  12380. }
  12381. cProto.position34 = cProto.position
  12382. cProto.position = function () {
  12383. if (this._positionInitialize_) {
  12384. this._positionInitialize_ = 0;
  12385. this.__refitByPosition__();
  12386. }
  12387. let r = cProto.position34.apply(this, arguments);
  12388. return r;
  12389. }
  12390. console1.log("FIX_MENU_POSITION_ON_SHOWN - OK");
  12391.  
  12392. } else {
  12393.  
  12394. console1.log("FIX_MENU_POSITION_ON_SHOWN - NG");
  12395.  
  12396. }
  12397.  
  12398.  
  12399.  
  12400. cProto.__openedChanged = function () {
  12401. // console.log(123445)
  12402. this._positionInitialize_ = 1;
  12403. // this.removeAttribute('horizontal-align')
  12404. // this.removeAttribute('vertical-align')
  12405. if (typeof this.__menuTypeCheck__ !== 'boolean') {
  12406. this.__menuTypeCheck__ = true;
  12407. if (CHAT_MENU_SCROLL_UNLOCKING) {
  12408. this._modifiedMenuPropOn062__ = false;
  12409. // console.log(513, this.positionTarget && this.positionTarget.classList.contains('yt-live-chat-text-message-renderer'))
  12410. // this.autoFitOnAttach = true;
  12411. // this.expandSizingTargetForScrollbars = true;
  12412. // this.allowOutsideScroll = true;
  12413. // console.log(519,Object.getOwnPropertyDescriptors(this.constructor.prototype))
  12414. this.__modifiedMenuPropsFn__();
  12415. // this.constrain= function(){}
  12416. // this.position= function(){}
  12417.  
  12418. // this.autoFitOnAttach = true;
  12419. // this.expandSizingTargetForScrollbars = true;
  12420. // this.allowOutsideScroll = true;
  12421. }
  12422. }
  12423. if (CHAT_MENU_SCROLL_UNLOCKING && this.opened) {
  12424. let newValue = null;
  12425. const positionTarget = this.positionTarget;
  12426. if (positionTarget && positionTarget.classList.contains('yt-live-chat-text-message-renderer')) {
  12427. if (this._modifiedMenuPropOn062__ === false) {
  12428. newValue = true;
  12429. }
  12430. } else if (this._modifiedMenuPropOn062__ === true) {
  12431. newValue = false;
  12432. }
  12433. if (newValue !== null) {
  12434. const beforeAllowOutsideScroll = this.allowOutsideScroll;
  12435. this._modifiedMenuPropOn062__ = newValue;
  12436. const afterAllowOutsideScroll = this.allowOutsideScroll;
  12437. if (beforeAllowOutsideScroll !== afterAllowOutsideScroll) this.__AllowOutsideScrollPD__.set.call(this, afterAllowOutsideScroll);
  12438. }
  12439. }
  12440.  
  12441. if (this.opened) {
  12442.  
  12443. Promise.resolve().then(() => {
  12444.  
  12445. this._prepareRenderOpened();
  12446. }).then(() => {
  12447. // console.log('[yt-chat-dialog]', this._manager)
  12448. try{
  12449. this._manager.addOverlay(this);
  12450. }catch(e){
  12451. console.log('this._manager.addOverlay(this) fails.')
  12452. }
  12453. if (this._manager._overlays.length === 1) {
  12454. lastOpen = this;
  12455. lastClose = null;
  12456. } else {
  12457. return 1;
  12458. }
  12459. // if (cid) {
  12460. // clearTimeout(cid);
  12461. // cid = -1;
  12462. // this.__moChanged__();
  12463. // cid = 0;
  12464. // } else {
  12465. // cid = -1;
  12466. // this.__moChanged__();
  12467. // cid = 0;
  12468. // }
  12469. // cid = cid > 0 ? clearTimeout(cid) : 0;
  12470. // console.log(580, this.positionTarget && this.positionTarget.classList.contains('yt-live-chat-text-message-renderer'))
  12471. // cid = cid || setTimeout(__moChanged__, delay1);
  12472. cid = cid || requestAnimationFrame(__moChanged__);
  12473. }).then((r) => {
  12474.  
  12475. if (r) this.__mtChanged__(1);
  12476. }).catch(console.warn);
  12477.  
  12478. } else {
  12479. Promise.resolve().then(() => {
  12480. // console.log('[yt-chat-dialog]', this._manager)
  12481. try{
  12482. this._manager.removeOverlay(this);
  12483. }catch(e){
  12484. console.log('this._manager.removeOverlay(this) fails.')
  12485. }
  12486. if (this._manager._overlays.length === 0) {
  12487. lastClose = this;
  12488. lastOpen = null;
  12489. } else {
  12490. return 1;
  12491. }
  12492. // cid = cid > 0 ? clearTimeout(cid) : 0;
  12493. // console.log(581, this.positionTarget && this.positionTarget.classList.contains('yt-live-chat-text-message-renderer'))
  12494. // cid = cid || setTimeout(__moChanged__, delay1);
  12495. cid = cid || requestAnimationFrame(__moChanged__);
  12496. }).then((r) => {
  12497. if (r) this.__mtChanged__(0);
  12498. }).catch(console.warn);
  12499.  
  12500. }
  12501.  
  12502. }
  12503. console1.log("BOOST_MENU_OPENCHANGED_RENDERING - OK");
  12504.  
  12505. } else {
  12506.  
  12507. assertor(() => fnIntegrity(cProto.__openedChanged, '0.46.20'));
  12508. console1.log("FIX_MENU_REOPEN_RENDER_PERFORMANC_1 - NG");
  12509.  
  12510. }
  12511.  
  12512.  
  12513. if (FIX_CLICKING_MESSAGE_MENU_DISPLAY_ON_MOUSE_CLICK && typeof cProto.__openedChanged === 'function' && !cProto.__openedChanged82) {
  12514.  
  12515. cProto.__openedChanged82 = cProto.__openedChanged;
  12516.  
  12517.  
  12518. cProto.__openedChanged = function () {
  12519. const positionTarget = this.positionTarget;
  12520. currentMenuPivotWR = positionTarget ? mWeakRef(positionTarget) : null;
  12521. return this.__openedChanged82.apply(this, arguments);
  12522. }
  12523. }
  12524.  
  12525.  
  12526. })();
  12527.  
  12528. console1.log("[End]");
  12529.  
  12530. groupEnd();
  12531.  
  12532. }).catch(console.warn);
  12533.  
  12534.  
  12535.  
  12536. FIX_ToggleRenderPolymerControllerExtractionBug && customElements.whenDefined('yt-live-chat-toggle-renderer').then(() => {
  12537.  
  12538. mightFirstCheckOnYtInit();
  12539. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-toggle-renderer hacks");
  12540. console1.log("[Begin]");
  12541. (() => {
  12542.  
  12543. const tag = "yt-live-chat-toggle-renderer";
  12544. const dummy = document.createElement(tag);
  12545.  
  12546. const cProto = getProto(dummy);
  12547. if (!cProto || !cProto.attached) {
  12548. console1.warn(`proto.attached for ${tag} is unavailable.`);
  12549. return;
  12550. }
  12551.  
  12552. })();
  12553.  
  12554. console1.log("[End]");
  12555. groupEnd();
  12556.  
  12557. });
  12558.  
  12559. FIX_MOUSEOVER_FN && (() => {
  12560.  
  12561. // this is to show tooltip for emoji
  12562.  
  12563.  
  12564. let lastShow = 0;
  12565.  
  12566. const wm = new WeakSet();
  12567. const mo1 = new MutationObserver((mutations) => {
  12568.  
  12569. for (const p of document.querySelectorAll('[shared-tooltip-text]:not([__a6cwm__])')) {
  12570. p.setAttribute('__a6cwm__', '');
  12571. }
  12572.  
  12573. });
  12574. mo1.observe(document, { subtree: true, attributes: true, attributeFilter: ['shared-tooltip-text'], childList: true });
  12575.  
  12576. const mo2 = new MutationObserver((mutations) => {
  12577.  
  12578. for (const mutation of mutations) {
  12579. const p = mutation.target;
  12580. if (mutation.attributeName) {
  12581. if (p.getAttribute('shared-tooltip-text')) { // allow hack
  12582. wm.add(p);
  12583. for (const e of p.getElementsByTagName('*')) {
  12584. wm.add(e);
  12585. }
  12586. } else {
  12587. if (wm.has(p)) {
  12588. wm.remove(p);
  12589. for (const e of p.getElementsByTagName('*')) {
  12590. wm.remove(e);
  12591. }
  12592. }
  12593. }
  12594. }
  12595. }
  12596. });
  12597. mo2.observe(document, { subtree: true, attributes: true, attributeFilter: ['__a6cwm__', 'shared-tooltip-text'], childList: false });
  12598.  
  12599.  
  12600. let done = 0;
  12601. // lcrFn2 will run twice to ensure the method is successfully injected.
  12602. const lcrFn2 = (lcrDummy) => {
  12603. // make minimal function overhead by pre-defining all possible outside.
  12604.  
  12605. const tag = "yt-live-chat-renderer"
  12606. const dummy = lcrDummy;
  12607.  
  12608. const cProto = getProto(dummy);
  12609. if (!cProto || !cProto.attached) {
  12610. console.warn(`proto.attached for ${tag} is unavailable.`);
  12611. return;
  12612. }
  12613.  
  12614. // mightFirstCheckOnYtInit();
  12615. // groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-renderer hacks");
  12616. // console.log("[Begin]");
  12617.  
  12618.  
  12619.  
  12620. if (done !== 1 && typeof cProto.onMouseOver_ === 'function' && !cProto.onMouseOver37_ && typeof cProto.createTooltipIfRequired_ === 'function' && cProto.createTooltipIfRequired_.length === 0) {
  12621.  
  12622. done = 1;
  12623. const onMouseOver37_ = cProto.onMouseOver37_ = cProto.onMouseOver_;
  12624.  
  12625. const checkMatch = (() => {
  12626.  
  12627.  
  12628. let accessList = [];
  12629. let withError = false;
  12630. try {
  12631.  
  12632. onMouseOver37_.call(lcrDummy, {
  12633. type: 'mouseover',
  12634. target: new Proxy({
  12635. nodeName: 'DIV',
  12636. tagName: 'DIV',
  12637. getAttribute: function () { },
  12638. parentNode: null
  12639. }, {
  12640. get(target, p) {
  12641. accessList.push(`getter:${p}`);
  12642. if (!(p in target)) throw Error(`getter ${p} is not found`);
  12643. },
  12644. set(target, p, v) {
  12645. accessList.push(`setter:${p}`);
  12646. throw Error(`setter ${p} is not found`);
  12647. }
  12648. })
  12649. });
  12650. } catch (e) {
  12651. withError = true;
  12652. // console.warn(e);
  12653. }
  12654.  
  12655. if (withError) return false;
  12656.  
  12657. if (accessList.join(',') !== 'getter:getAttribute,getter:parentNode') return false;
  12658.  
  12659. accessList.length = 0;
  12660.  
  12661. let parent;
  12662. try {
  12663.  
  12664. parent = new Proxy({
  12665. nodeName: 'DIV',
  12666. tagName: 'DIV',
  12667. getAttribute: function (e) {
  12668.  
  12669. accessList.push(`getter:getAttribute(${e})`);
  12670. return e === 'shared-tooltip-text' ? ':cherry_blossom:' : null;
  12671.  
  12672. },
  12673. parentNode: null
  12674. }, {
  12675. get(target, p) {
  12676. accessList.push(`getter:${p}`);
  12677. if (!(p in target)) throw Error(`getter ${p} is not found`);
  12678. return target[p]
  12679. },
  12680. set(target, p, v) {
  12681. accessList.push(`setter:${p}`);
  12682. throw Error(`setter ${p} is not found`);
  12683. }
  12684. });
  12685.  
  12686. onMouseOver37_.call(lcrDummy, {
  12687. type: 'mouseover',
  12688. target: new Proxy({
  12689. nodeName: 'IMG',
  12690. tagName: 'IMG',
  12691. id: 'img',
  12692. getAttribute: function (e) {
  12693.  
  12694. accessList.push(`getter:getAttribute(${e})`);
  12695. return e === 'shared-tooltip-text' ? ':cherry_blossom:' : null;
  12696.  
  12697. },
  12698. get parentNode() {
  12699. return parent
  12700. },
  12701. get parentElement() {
  12702. return parent
  12703. }
  12704. }, {
  12705. get(target, p) {
  12706. accessList.push(`getter:${p}`);
  12707. if (!(p in target)) throw Error(`getter ${p} is not found`);
  12708. return target[p]
  12709. },
  12710. set(target, p, v) {
  12711. accessList.push(`setter:${p}`);
  12712. throw Error(`setter ${p} is not found`);
  12713. }
  12714. })
  12715. });
  12716. } catch (e) {
  12717. withError = true;
  12718. // console.warn(e);
  12719. }
  12720. parent = null;
  12721.  
  12722. 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:$$') {
  12723. return true;
  12724. }
  12725.  
  12726.  
  12727.  
  12728. })();
  12729. if (checkMatch) {
  12730.  
  12731. cProto.onMouseOver_ = function (evt) {
  12732. const p = (evt || 0).target || 0;
  12733. if (p.nodeType === 1 && wm.has(p)) {
  12734. const ct = Date.now();
  12735. if (lastShow + 18 > ct) return;
  12736. const cnt = insp(this);
  12737. lastShow = ct;
  12738. try {
  12739. cnt.onMouseOver37_.call(this, evt);
  12740. } catch (e) {
  12741. console.warn(e);
  12742. }
  12743. }
  12744. };
  12745.  
  12746. const lcrs = toUniqueArr([lcrDummy, ...document.querySelectorAll('yt-live-chat-renderer')]);
  12747. for (const lcr of lcrs) {
  12748. const cnt = insp(lcr);
  12749. const hostElement = cnt.hostElement;
  12750. if (hostElement && cnt.isAttached === true && cnt.onMouseOver37_ === cProto.onMouseOver37_ && typeof cProto.onMouseOver_ === 'function' && cProto.onMouseOver_ !== cProto.onMouseOver37_ && cnt.onMouseOver_ === cProto.onMouseOver_) {
  12751. hostElement.removeEventListener("mouseover", cProto.onMouseOver37_, !0)
  12752. hostElement.addEventListener("mouseover", cProto.onMouseOver_, !0)
  12753. }
  12754. }
  12755.  
  12756. console.log('[yt-chat-lcr] FIX_MOUSEOVER_FN - OK')
  12757.  
  12758. } else {
  12759.  
  12760. console.log('[yt-chat-lcr] FIX_MOUSEOVER_FN - NG')
  12761.  
  12762. }
  12763.  
  12764. } else if (done !== 1) {
  12765. done = 2;
  12766. console.log('[yt-chat-lcr] FIX_MOUSEOVER_FN - NG')
  12767. }
  12768.  
  12769. // console.log("[End]");
  12770. // groupEnd();
  12771.  
  12772.  
  12773. };
  12774. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  12775. // getLCRDummy() must be called for injection
  12776. getLCRDummy().then(lcrFn2);
  12777.  
  12778. })();
  12779.  
  12780.  
  12781. /*
  12782.  
  12783.  
  12784.  
  12785.  
  12786.  
  12787. var FU = function() {
  12788. var a = this;
  12789. this.nextHandle_ = 1;
  12790. this.clients_ = {};
  12791. this.JSC$10323_callbacks_ = {};
  12792. this.unsubscribeAsyncHandles_ = {};
  12793. this.subscribe = vl(function(b, c, d) {
  12794. var e = Geb(b);
  12795. if (e in a.clients_)
  12796. e in a.unsubscribeAsyncHandles_ && Jq.cancel(a.unsubscribeAsyncHandles_[e]);
  12797. else {
  12798. a: {
  12799. var h = Geb(b), l;
  12800. for (l in a.unsubscribeAsyncHandles_) {
  12801. var m = a.clients_[l];
  12802. if (m instanceof KO) {
  12803. delete a.clients_[l];
  12804. delete a.JSC$10323_callbacks_[l];
  12805. Jq.cancel(a.unsubscribeAsyncHandles_[l]);
  12806. delete a.unsubscribeAsyncHandles_[l];
  12807. i6a(m);
  12808. m.objectId_ = new FQa(h);
  12809. m.register();
  12810. d = m;
  12811. break a
  12812. }
  12813. }
  12814. d.objectSource = b.invalidationId.objectSource;
  12815. d.objectId = h;
  12816. if (b = b.webAuthConfigurationData)
  12817. b.multiUserSessionIndex && (d.sessionIndex = parseInt(b.multiUserSessionIndex, 10)),
  12818. b.pageId && (d.pageId = b.pageId);
  12819. d = new KO(d,a.handleInvalidationData_.bind(a));
  12820. d.register()
  12821. }
  12822. a.clients_[e] = d;
  12823. a.JSC$10323_callbacks_[e] = {}
  12824. }
  12825. d = a.nextHandle_++;
  12826. a.JSC$10323_callbacks_[e][d] = c;
  12827. return d
  12828. })
  12829. };
  12830. FU.prototype.unsubscribe = function(a, b) {
  12831. var c = Geb(a);
  12832. if (c in this.JSC$10323_callbacks_ && (delete this.JSC$10323_callbacks_[c][b],
  12833. !this.JSC$10323_callbacks_[c].length)) {
  12834. var d = this.clients_[c];
  12835. b = Jq.run(function() {
  12836. ei(d);
  12837. delete this.clients_[c];
  12838. delete this.unsubscribeAsyncHandles_[c]
  12839. }
  12840. .bind(this));
  12841. this.unsubscribeAsyncHandles_[c] = b
  12842. }
  12843. }
  12844. ;
  12845.  
  12846.  
  12847. */
  12848.  
  12849.  
  12850. const onManagerFound = (dummyManager) => {
  12851. if (!dummyManager || typeof dummyManager !== 'object') return;
  12852.  
  12853. const mgrProto = dummyManager.constructor.prototype;
  12854.  
  12855. let keyCallbackStore = '';
  12856. for (const [key, v] of Object.entries(dummyManager)) {
  12857. if (key.includes('_callbacks_')) keyCallbackStore = key;
  12858. }
  12859.  
  12860. if (!keyCallbackStore || typeof mgrProto.unsubscribe !== 'function' || mgrProto.unsubscribe.length !== 2) return;
  12861.  
  12862. if (mgrProto.unsubscribe16) return;
  12863.  
  12864. mgrProto.unsubscribe16 = mgrProto.unsubscribe;
  12865.  
  12866. groupCollapsed("YouTube Super Fast Chat", " | *live-chat-manager* hacks");
  12867. console1.log("[Begin]");
  12868.  
  12869. const idMapper = new Map();
  12870.  
  12871. const convertId = function (objectId) {
  12872. if (!objectId || typeof objectId !== 'string') return null;
  12873.  
  12874. let result = idMapper.get(objectId)
  12875. if (result) return result;
  12876. result = atob(objectId.replace(/-/g, "+").replace(/_/g, "/"));
  12877. idMapper.set(objectId, result)
  12878. return result;
  12879. }
  12880.  
  12881.  
  12882. const rafHandleHolder = [];
  12883.  
  12884. let pzw = 0;
  12885. let lza = 0;
  12886. const rafHandlerFn = () => {
  12887. pzw = 0;
  12888. if (rafHandleHolder.length === 1) {
  12889. const f = rafHandleHolder[0];
  12890. rafHandleHolder.length = 0;
  12891. f();
  12892. } else if (rafHandleHolder.length > 1) {
  12893. const arr = rafHandleHolder.slice(0);
  12894. rafHandleHolder.length = 0;
  12895. for (const fn of arr) fn();
  12896. }
  12897. };
  12898.  
  12899.  
  12900. if (CHANGE_MANAGER_UNSUBSCRIBE) {
  12901.  
  12902. const checkIntegrityForSubscribe = (mgr) => {
  12903. if (mgr
  12904. && typeof mgr.unsubscribe16 === 'function' && mgr.unsubscribe16.length === 2
  12905. && typeof mgr.subscribe18 === 'function' && (mgr.subscribe18.length === 0 || mgr.subscribe18.length === 3)) {
  12906.  
  12907. const ns = new Set(Object.keys(mgr));
  12908. const ms = new Set(Object.keys(mgr.constructor.prototype));
  12909.  
  12910. if (ns.size >= 6 && ms.size >= 4) {
  12911. // including 'subscribe18'
  12912. // 'unsubscribe16', 'subscribe19'
  12913.  
  12914. let r = 0;
  12915. for (const k of ['nextHandle_', 'clients_', keyCallbackStore, 'unsubscribeAsyncHandles_', 'subscribe', 'subscribe18']) {
  12916. r += ns.has(k) ? 1 : 0;
  12917. }
  12918. for (const k of ['unsubscribe', 'handleInvalidationData_', 'unsubscribe16', 'subscribe19']) {
  12919. r += ms.has(k) ? 1 : 0;
  12920. }
  12921. if (r === 10) {
  12922. const isObject = (c) => (c || 0).constructor === Object;
  12923.  
  12924. if (isObject(mgr['clients_']) && isObject(mgr[keyCallbackStore]) && isObject(mgr['unsubscribeAsyncHandles_'])) {
  12925.  
  12926. return true;
  12927. }
  12928.  
  12929.  
  12930. }
  12931.  
  12932. }
  12933.  
  12934.  
  12935. }
  12936. return false;
  12937. }
  12938.  
  12939. mgrProto.subscribe19 = function (o, f, opts) {
  12940.  
  12941. const ct_clients_ = this.clients_ || 0;
  12942. const ct_handles_ = this.unsubscribeAsyncHandles_ || 0;
  12943.  
  12944. if (this.__doCustomSubscribe__ !== true || !ct_clients_ || !ct_handles_) return this.subscribe18.apply(this, arguments);
  12945.  
  12946. let objectId = ((o || 0).invalidationId || 0).objectId;
  12947. if (!objectId) return this.subscribe18.apply(this, arguments);
  12948. objectId = convertId(objectId);
  12949.  
  12950. // console.log('subscribe', objectId, ct_clients_[objectId], arguments);
  12951.  
  12952. if (ct_clients_[objectId]) {
  12953. if (ct_handles_[objectId] < 0) delete ct_handles_[objectId];
  12954. }
  12955.  
  12956. return this.subscribe18.apply(this, arguments);
  12957. }
  12958.  
  12959. mgrProto.unsubscribe = function (o, d) {
  12960. if (!this.subscribe18 && typeof this.subscribe === 'function') {
  12961. this.subscribe18 = this.subscribe;
  12962. this.subscribe = this.subscribe19;
  12963. this.__doCustomSubscribe__ = checkIntegrityForSubscribe(this);
  12964. }
  12965. const ct_clients_ = this.clients_;
  12966. const ct_handles_ = this.unsubscribeAsyncHandles_;
  12967. if (this.__doCustomSubscribe__ !== true || !ct_clients_ || !ct_handles_) return this.unsubscribe16.apply(this, arguments);
  12968.  
  12969. let objectId = ((o || 0).invalidationId || 0).objectId;
  12970. if (!objectId) return this.unsubscribe16.apply(this, arguments);
  12971.  
  12972. objectId = convertId(objectId);
  12973.  
  12974.  
  12975. // console.log('unsubscribe', objectId, ct_clients_[objectId], arguments);
  12976.  
  12977. const callbacks = this[keyCallbackStore] || 0;
  12978. const callbackObj = callbacks[objectId] || 0;
  12979.  
  12980.  
  12981. if (callbackObj && (delete callbackObj[d], isEmptyObject(callbackObj))) {
  12982. const w = ct_clients_[objectId];
  12983. lza = (lza & 1073741823) + 1;
  12984. const qta = -lza;
  12985. rafHandleHolder.push(() => {
  12986. if (qta === ct_handles_[objectId]) {
  12987. const o = {
  12988. callbacks, callbackObj,
  12989. client: ct_clients_[objectId],
  12990. handle: ct_handles_[objectId]
  12991. };
  12992. let p = 0;
  12993. try {
  12994. if (ct_clients_[objectId] === w) {
  12995. w && "function" === typeof w.dispose && w.dispose();
  12996. delete ct_clients_[objectId];
  12997. delete ct_handles_[objectId];
  12998. p = 1;
  12999. } else {
  13000. // w && "function" === typeof w.dispose && w.dispose();
  13001. // delete ct_clients_[objectId];
  13002. // delete ct_handles_[objectId];
  13003. p = 2;
  13004. }
  13005. } catch (e) {
  13006. console.warn(e);
  13007. }
  13008. console.log(`unsubscribed: ${p}`, this, o);
  13009. }
  13010. });
  13011. ct_handles_[objectId] = qta;
  13012. if (pzw === 0) {
  13013. pzw = requestAnimationFrame(rafHandlerFn);
  13014. }
  13015. }
  13016. }
  13017.  
  13018.  
  13019. console1.log("CHANGE_MANAGER_UNSUBSCRIBE - OK")
  13020.  
  13021. } else {
  13022.  
  13023. console1.log("CHANGE_MANAGER_UNSUBSCRIBE - NG")
  13024. }
  13025.  
  13026. console1.log("[End]");
  13027.  
  13028. groupEnd();
  13029.  
  13030. }
  13031.  
  13032.  
  13033.  
  13034. /*
  13035.  
  13036.  
  13037. a.prototype.async = function(e, h) {
  13038. return 0 < h ? Iq.run(e.bind(this), h) : ~Kq.run(e.bind(this))
  13039. }
  13040. ;
  13041. a.prototype.cancelAsync = function(e) {
  13042. 0 > e ? Kq.cancel(~e) : Iq.cancel(e)
  13043. }
  13044.  
  13045. */
  13046.  
  13047.  
  13048. (FASTER_ICON_RENDERING && Promise.all(
  13049. [
  13050. customElements.whenDefined("yt-icon-shape"),
  13051. customElements.whenDefined("yt-icon")
  13052. // document.createElement('icon-shape'),
  13053. ]
  13054. )).then(() => {
  13055. let cq = 0;
  13056. let dummys = [document.createElement('yt-icon-shape'), document.createElement('yt-icon')]
  13057. for (const dummy of dummys) {
  13058. let cProto = getProto(dummy);
  13059. if (cProto && typeof cProto.shouldRenderIconShape === 'function' && !cProto.shouldRenderIconShape571 && cProto.shouldRenderIconShape.length === 1) {
  13060. assertor(() => fnIntegrity(cProto.shouldRenderIconShape, '1.70.38'));
  13061. cq++;
  13062. cProto.shouldRenderIconShape571 = cProto.shouldRenderIconShape;
  13063. cProto.shouldRenderIconShape = function (a) {
  13064. if (this.isAnimatedIcon) return this.shouldRenderIconShape571(a);
  13065. if (!this.iconType || !this.iconShapeData) return this.shouldRenderIconShape571(a);
  13066. if (!this.iconName) return this.shouldRenderIconShape571(a);
  13067. return false;
  13068. // console.log(1051, this.iconType)
  13069. // console.log(1052, this.iconShapeData)
  13070. // console.log(1053, this.isAnimatedIcon)
  13071. }
  13072. }
  13073. // if(cProto && cProto.switchTemplateAtRegistration){
  13074. // cProto.switchTemplateAtRegistration = false;
  13075. // }
  13076. }
  13077. if (cq === 1) {
  13078. console.log("modified shouldRenderIconShape - Y")
  13079. } else {
  13080. console.log("modified shouldRenderIconShape - N", cq)
  13081. }
  13082. });
  13083.  
  13084. customElements.whenDefined("yt-invalidation-continuation").then(() => {
  13085.  
  13086. let __dummyManager__ = null;
  13087.  
  13088. mightFirstCheckOnYtInit();
  13089. groupCollapsed("YouTube Super Fast Chat", " | yt-invalidation-continuation hacks");
  13090. console1.log("[Begin]");
  13091. (() => {
  13092.  
  13093. const tag = "yt-invalidation-continuation"
  13094. const dummy = document.createElement(tag);
  13095.  
  13096. const cProto = getProto(dummy);
  13097. if (!cProto || !cProto.attached) {
  13098. console1.warn(`proto.attached for ${tag} is unavailable.`);
  13099. return;
  13100. }
  13101.  
  13102. const dummyManager = insp(dummy).manager_ || 0;
  13103. __dummyManager__ = dummyManager;
  13104.  
  13105.  
  13106. })();
  13107.  
  13108. console1.log("[End]");
  13109.  
  13110. groupEnd();
  13111.  
  13112.  
  13113.  
  13114. onManagerFound(__dummyManager__);
  13115.  
  13116. }).catch(console.warn);
  13117.  
  13118.  
  13119. if (INTERACTIVITY_BACKGROUND_ANIMATION >= 1) {
  13120.  
  13121. customElements.whenDefined("yt-live-interactivity-component-background").then(() => {
  13122.  
  13123. mightFirstCheckOnYtInit();
  13124. groupCollapsed("YouTube Super Fast Chat", " | yt-live-interactivity-component-background hacks");
  13125. console1.log("[Begin]");
  13126. (() => {
  13127.  
  13128. const tag = "yt-live-interactivity-component-background"
  13129. const dummy = document.createElement(tag);
  13130.  
  13131. const cProto = getProto(dummy);
  13132. if (!cProto || !cProto.attached) {
  13133. console1.warn(`proto.attached for ${tag} is unavailable.`);
  13134. return;
  13135. }
  13136.  
  13137. cProto.__toStopAfterRun__ = function (hostElement) {
  13138. let mo = new MutationObserver(() => {
  13139. mo.disconnect();
  13140. mo.takeRecords();
  13141. mo = null;
  13142. this.lottieAnimation && this.lottieAnimation.stop(); // primary
  13143. foregroundPromiseFn().then(() => { // if the lottieAnimation is started with rAf triggering
  13144. this.lottieAnimation && this.lottieAnimation.stop(); // fallback
  13145. });
  13146. });
  13147. mo.observe(hostElement, { subtree: true, childList: true });
  13148. }
  13149.  
  13150. if (INTERACTIVITY_BACKGROUND_ANIMATION >= 1 && typeof cProto.maybeLoadAnimationBackground === 'function' && !cProto.maybeLoadAnimationBackground77 && cProto.maybeLoadAnimationBackground.length === 0) {
  13151.  
  13152. cProto.maybeLoadAnimationBackground77 = cProto.maybeLoadAnimationBackground;
  13153. cProto.maybeLoadAnimationBackground = function () {
  13154. let toRun = true;
  13155. let stopAfterRun = false;
  13156. if (!this.__bypassDisableAnimationBackground__) {
  13157. let doFix = false;
  13158. if (INTERACTIVITY_BACKGROUND_ANIMATION === 1) {
  13159. if (!this.lottieAnimation) {
  13160. doFix = true;
  13161. }
  13162. } else if (INTERACTIVITY_BACKGROUND_ANIMATION === 2) {
  13163. doFix = true;
  13164. }
  13165. if (doFix) {
  13166. if (this.useAnimationBackground === true) {
  13167. console.log('DISABLE_INTERACTIVITY_BACKGROUND_ANIMATION', this.lottieAnimation);
  13168. }
  13169. toRun = true;
  13170. stopAfterRun = true;
  13171. }
  13172. }
  13173. if (toRun) {
  13174. if (stopAfterRun && (this.hostElement instanceof HTMLElement_)) {
  13175. this.__toStopAfterRun__(this.hostElement); // primary
  13176. }
  13177. const r = this.maybeLoadAnimationBackground77.apply(this, arguments);
  13178. if (stopAfterRun && this.lottieAnimation) {
  13179. this.lottieAnimation.stop(); // fallback if no mutation
  13180. }
  13181. return r;
  13182. }
  13183. }
  13184.  
  13185. console1.log(`INTERACTIVITY_BACKGROUND_ANIMATION(${INTERACTIVITY_BACKGROUND_ANIMATION}) - OK`);
  13186.  
  13187. } else {
  13188. console1.log(`INTERACTIVITY_BACKGROUND_ANIMATION(${INTERACTIVITY_BACKGROUND_ANIMATION}) - NG`);
  13189.  
  13190. }
  13191.  
  13192. })();
  13193.  
  13194. console1.log("[End]");
  13195.  
  13196. groupEnd();
  13197.  
  13198.  
  13199. }).catch(console.warn);
  13200.  
  13201. }
  13202.  
  13203.  
  13204. if (DELAY_FOCUSEDCHANGED) {
  13205.  
  13206. customElements.whenDefined("yt-live-chat-text-input-field-renderer").then(() => {
  13207.  
  13208.  
  13209. mightFirstCheckOnYtInit();
  13210. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-text-input-field-renderer hacks");
  13211. console1.log("[Begin]");
  13212. (() => {
  13213.  
  13214. const tag = "yt-live-chat-text-input-field-renderer"
  13215. const dummy = document.createElement(tag);
  13216.  
  13217. const cProto = getProto(dummy);
  13218. if (!cProto || !cProto.attached) {
  13219. console1.warn(`proto.attached for ${tag} is unavailable.`);
  13220. return;
  13221. }
  13222.  
  13223. if (DELAY_FOCUSEDCHANGED && typeof cProto.focusedChanged === 'function' && cProto.focusedChanged.length === 0 && !cProto.focusedChanged372) {
  13224. cProto.focusedChanged372 = cProto.focusedChanged;
  13225. cProto.focusedChanged = function () {
  13226. Promise.resolve(this).then((cnt) => {
  13227. if (cnt.isAttached === true) cnt.focusedChanged372();
  13228. });
  13229. }
  13230. }
  13231.  
  13232. })();
  13233.  
  13234. console1.log("[End]");
  13235.  
  13236. groupEnd();
  13237.  
  13238. });
  13239.  
  13240. }
  13241.  
  13242. }
  13243.  
  13244.  
  13245.  
  13246.  
  13247. promiseForCustomYtElementsReady.then(onRegistryReadyForDOMOperations);
  13248.  
  13249. const fixJsonParse = () => {
  13250.  
  13251. let p1 = window.onerror;
  13252.  
  13253. try {
  13254. JSON.parse("{}");
  13255. } catch (e) {
  13256. console.warn(e);
  13257. }
  13258.  
  13259. let p2 = window.onerror;
  13260.  
  13261. if (p1 !== p2) {
  13262.  
  13263.  
  13264. console.groupCollapsed(`%c${"YouTube Super Fast Chat"}%c${" | JS Engine Issue Found"}`,
  13265. "background-color: #010502; color: #fe806a; font-weight: 700; padding: 2px;",
  13266. "background-color: #010502; color: #fe806a; font-weight: 300; padding: 2px;"
  13267. );
  13268.  
  13269. 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://gf.qytechs.cn/scripts/473972-youtube-js-engine-tamer to fix the issue.\n");
  13270.  
  13271. console.groupEnd();
  13272.  
  13273. }
  13274.  
  13275. }
  13276.  
  13277. if (CHECK_JSONPRUNE) {
  13278. promiseForCustomYtElementsReady.then(fixJsonParse);
  13279. }
  13280.  
  13281. });
  13282.  
  13283.  
  13284.  
  13285. })({ IntersectionObserver });

QingJ © 2025

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