YouTube 超快聊天

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

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

  1. // ==UserScript==
  2. // @name YouTube Super Fast Chat
  3. // @version 0.102.8
  4. // @license MIT
  5. // @name:ja YouTube スーパーファーストチャット
  6. // @name:zh-TW YouTube 超快聊天
  7. // @name:zh-CN YouTube 超快聊天
  8. // @icon https://raw.githubusercontent.com/cyfung1031/userscript-supports/main/icons/super-fast-chat.png
  9. // @namespace UserScript
  10. // @match https://www.youtube.com/live_chat*
  11. // @match https://www.youtube.com/live_chat_replay*
  12. // @author CY Fung
  13. // @run-at document-start
  14. // @grant none
  15. // @unwrap
  16. // @allFrames true
  17. // @inject-into page
  18. // @require https://update.greasyfork.org/scripts/475632/1361351/ytConfigHacks.js
  19. // @require https://cdn.jsdelivr.net/gh/cyfung1031/userscript-supports@c2b707e4977f77792042d4a5015fb188aae4772e/library/nextBrowserTick.min.js
  20. //
  21. // @compatible firefox Violentmonkey
  22. // @compatible firefox Tampermonkey
  23. // @compatible firefox FireMonkey
  24. // @compatible chrome Violentmonkey
  25. // @compatible chrome Tampermonkey
  26. // @compatible opera Violentmonkey
  27. // @compatible opera Tampermonkey
  28. // @compatible safari Stay
  29. // @compatible edge Violentmonkey
  30. // @compatible edge Tampermonkey
  31. // @compatible brave Violentmonkey
  32. // @compatible brave Tampermonkey
  33. //
  34. // @description Ultimate Performance Boost for YouTube Live Chats
  35. // @description:ja YouTubeのライブチャットの究極のパフォーマンスブースト
  36. // @description:zh-TW YouTube直播聊天的終極性能提升
  37. // @description:zh-CN YouTube直播聊天的终极性能提升
  38. //
  39. // ==/UserScript==
  40.  
  41. ((__CONTEXT__) => {
  42. 'use strict';
  43.  
  44. /** @type {WeakMapConstructor} */
  45. const WeakMap = window.WeakMapOriginal || window.WeakMap;
  46.  
  47. const DEBUG_LOG_GROUP_EXPAND = +localStorage.__debugSuperFastChat__ > 0;
  48. const DEBUG_LOG_HIDE_OK = true;
  49. const DEBUG_skipLog001 = true;
  50. const DEBUG_preprocessChatLiveActions = false;
  51. const DEBUG_customCreateComponent = false;
  52. // const SHOW_DEVTOOL_DEBUG = true; // for debug use
  53. const SHOW_DEVTOOL_DEBUG = typeof ResizeObserver === 'function' && CSS.supports('position-area:center');
  54.  
  55. // *********** DON'T REPORT NOT WORKING DUE TO THE CHANGED SETTINGS ********************
  56. // The settings are FIXED! You might change them to try but if the script does not work due to your change, please, don't report them as issues
  57.  
  58. /// -------------------------------------------------------------------------
  59.  
  60. const USE_ADVANCED_TICKING = true; // DONT CHANGE
  61. // << if USE_ADVANCED_TICKING >>
  62. const FIX_TIMESTAMP_FOR_REPLAY = true;
  63. const ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION = true; // MUST BE true
  64. const REUSE_TICKER = true; // for better memory control; currently it is only available in ADVANCED_TICKING; to be further reviewed << NO EFFECT SINCE ENABLE_TICKERS_BOOSTED_STAMPING IS USED >>
  65. // << end >>
  66.  
  67. const ENABLE_CHAT_MESSAGES_BOOSTED_STAMPING = true; // TRUE to boost chat messages rendering (DONT CHANGE)
  68. const ENABLE_TICKERS_BOOSTED_STAMPING = true; // TRUE to boost chat messages rendering (DONT CHANGE)
  69. const DISABLE_DYNAMIC_TICKER_WIDTH = true; // We use the opacity change instead
  70. const FIX_REMOVE_TICKER_ITEM_BY_ID = true; // TRUE by default
  71.  
  72. /// -------------------------------------------------------------------------
  73.  
  74. // ENABLE_REDUCED_MAXITEMS_FOR_FLUSH and MAX_ITEMS_FOR_FULL_FLUSH are removed due to ENABLE_CHAT_MESSAGES_BOOSTED_STAMPING is introduced
  75.  
  76. // const ENABLE_REDUCED_MAXITEMS_FOR_FLUSH = true; // TRUE to enable trimming down to MAX_ITEMS_FOR_FULL_FLUSH (25) messages when there are too many unrendered messages
  77. const MAX_ITEMS_FOR_TOTAL_DISPLAY = 90; // By default, 250 latest messages will be displayed, but displaying MAX_ITEMS_FOR_TOTAL_DISPLAY (90) messages is already sufficient. (not exceeding 900)
  78. // const MAX_ITEMS_FOR_FULL_FLUSH = 25; // If there are too many new (stacked) messages not yet rendered, clean all and flush MAX_ITEMS_FOR_FULL_FLUSH (25) latest messages then incrementally added back to MAX_ITEMS_FOR_TOTAL_DISPLAY (90) messages. (not exceeding 900)
  79.  
  80. const ENABLE_NO_SMOOTH_TRANSFORM = true; // Depends on whether you want the animation effect for new chat messages <<< DON'T CHANGE >>>
  81. // const USE_OPTIMIZED_ON_SCROLL_ITEMS = true; // TRUE for the majority
  82. const ENABLE_OVERFLOW_ANCHOR_PREFERRED = true; // Enable `overflow-anchor: auto` to lock the scroll list at the bottom for no smooth transform. (Safari is not supported)
  83.  
  84. const FIX_SHOW_MORE_BUTTON_LOCATION = true; // When there are voting options (bottom panel), move the "show more" button to the top.
  85. const FIX_INPUT_PANEL_OVERFLOW_ISSUE = true; // When the super chat button is flicking with color, the scrollbar might come out.
  86. const FIX_INPUT_PANEL_BORDER_ISSUE = true; // No border should be allowed if there is an empty input panel.
  87. const SET_CONTAIN_FOR_CHATROOM = true; // Rendering hacks (`contain`) for chatroom elements. [ General ]
  88.  
  89. const FORCE_CONTENT_VISIBILITY_UNSET = true; // Content-visibility should be always VISIBLE for high performance and great rendering.
  90. const FORCE_WILL_CHANGE_UNSET = true; // Will-change should be always UNSET (auto) for high performance and low energy impact.
  91.  
  92. // Replace requestAnimationFrame timers with custom implementation
  93. const ENABLE_RAF_HACK_TICKERS = true; // When there is a ticker
  94. const ENABLE_RAF_HACK_DOCKED_MESSAGE = true; // To be confirmed
  95. const ENABLE_RAF_HACK_INPUT_RENDERER = true; // To be confirmed
  96. const ENABLE_RAF_HACK_EMOJI_PICKER = true; // When changing the page of the emoji picker
  97.  
  98. // Force rendering all the character subsets of the designated font(s) before messages come (Pre-Rendering of Text)
  99. const ENABLE_FONT_PRE_RENDERING_PREFERRED = 1 | 2 | 4 | 8 | 16;
  100.  
  101. // Backdrop `filter: blur(4px)` inside the iframe can extend to the whole page, causing a negative visual impact on the video you are watching.
  102. const NO_BACKDROP_FILTER_WHEN_MENU_SHOWN = true;
  103.  
  104. // Data Manipulation for Participants (Participant List)
  105. // << if DO_PARTICIPANT_LIST_HACKS >>
  106. const DO_PARTICIPANT_LIST_HACKS = true; // TRUE for the majority
  107. const SHOW_PARTICIPANT_CHANGES_IN_CONSOLE = false; // Just too annoying to show them all in popular chat
  108. const CHECK_CHANGE_TO_PARTICIPANT_RENDERER_CONTENT = true; // Only consider changes in renderable content (not concerned with the last chat message of the participants)
  109. const PARTICIPANT_UPDATE_ONLY_ONLY_IF_MODIFICATION_DETECTED = true;
  110. // << end >>
  111.  
  112. // show more button
  113. const ENABLE_SHOW_MORE_BLINKER = true; // BLINK WHEN NEW MESSAGES COME
  114.  
  115. // faster stampDomArray_ for participants list creation
  116. const ENABLE_FLAGS_MAINTAIN_STABLE_LIST_VAL = 1; // 0 - OFF; 1 - ON; 2 - ON(PARTICIPANTS_LIST ONLY)
  117. const USE_MAINTAIN_STABLE_LIST_ONLY_WHEN_KS_FLAG_IS_SET = false;
  118.  
  119. // reuse yt components
  120. const ENABLE_FLAGS_REUSE_COMPONENTS = true;
  121.  
  122. // ShadyDom Free is buggy
  123. const DISABLE_FLAGS_SHADYDOM_FREE = true;
  124.  
  125. // images <Group#I01>
  126. const AUTHOR_PHOTO_SINGLE_THUMBNAIL = 1; // 0 - disable; 1- smallest; 2- largest
  127. const EMOJI_IMAGE_SINGLE_THUMBNAIL = 1; // 0 - disable; 1- smallest; 2- largest
  128. const LEAST_IMAGE_SIZE = 48; // minium size = 48px
  129.  
  130. const DO_LINK_PREFETCH = true; // DO NOT CHANGE
  131. // << if DO_LINK_PREFETCH >>
  132. const ENABLE_BASE_PREFETCHING = true; // (SUB-)DOMAIN | dns-prefetch & preconnect
  133. const ENABLE_PRELOAD_THUMBNAIL = true; // subresource (prefetch) [LINK for Images]
  134. const SKIP_PRELOAD_EMOJI = true;
  135. const PREFETCH_LIMITED_SIZE_EMOJI = 512; // DO NOT CHANGE THIS
  136. const PREFETCH_LIMITED_SIZE_AUTHOR_PHOTO = 68; // DO NOT CHANGE THIS
  137. // << end >>
  138.  
  139. const FIX_SETSRC_AND_THUMBNAILCHANGE_ = true; // Function Replacement for yt-img-shadow....
  140. const FIX_THUMBNAIL_DATACHANGED = true; // Function Replacement for yt-live-chat-author-badge-renderer..dataChanged
  141. // const REMOVE_PRELOADAVATARFORADDACTION = false; // Function Replacement for yt-live-chat-renderer..preloadAvatarForAddAction
  142.  
  143. const FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION = true; // important [depends on <Group#I01>]
  144. const FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT = true; // [depends on <Group#I01>]
  145.  
  146. // BROWSER SUPPORT: Chrome 75+, Edge 79+, Safari 13.1+, Firefox 63+, Opera 62+
  147. const TICKER_MAX_STEPS_LIMIT = 500; // NOT LESS THAN 5 STEPS!!
  148. // (( KEEP AS ALTERNATIVE IF USE_ADVANCED_TICKING NOT WORKING ))
  149. // [limiting 500 max steps] is recommended for "confortable visual change"
  150. // min. step increment 0.2% => max steps: 500 => 800ms per each update
  151. // min. step increment 0.5% => max steps: 200 => 1000ms per each update
  152. // min. step increment 1.0% => max steps: 100 => 1000ms per each update
  153. // min. step increment 2.5% => max steps: 40 => 1000ms per each update
  154. // min. step increment 5.0% => max steps: 20 => 1250ms per each update
  155. const ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX = true; // for video playback's ticker issue. [ Playback Replay - Pause at Middle - Backwards Seeking ]
  156. const SKIP_VIDEO_PLAYBACK_PROGRESS_STATE_FIX_FOR_NO_TIMEFX = false; // debug use; yt-live-chat-ticker-renderer might not require ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX
  157. // << end >>
  158.  
  159. const FIX_TOOLTIP_DISPLAY = true; // changed in 2024.05.02; updated in 2025.01.10
  160. const USE_VANILLA_DEREF = true;
  161. const FIX_DROPDOWN_DERAF = true; // DONT CHANGE
  162.  
  163.  
  164. const CACHE_SHOW_CONTEXT_MENU_FOR_REOPEN = true; // cache the menu data and used for the next reopen
  165. const ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU = false; // pause auto scroll faster when the context menu is about to show
  166. const ENABLE_MUTEX_FOR_SHOW_CONTEXT_MENU = true; // avoid multiple requests on the same time
  167.  
  168. const BOOST_MENU_OPENCHANGED_RENDERING = true;
  169. const FIX_CLICKING_MESSAGE_MENU_DISPLAY_ON_MOUSE_CLICK = true; // click again = close
  170. const NO_ITEM_TAP_FOR_NON_STATIONARY_TAP = true; // dont open the menu (e.g. text message) if cursor is moved or long press
  171. const TAP_ACTION_DURATION = 280; // exceeding 280ms would not consider as a tap action
  172. const PREREQUEST_CONTEXT_MENU_ON_MOUSE_DOWN = true; // require CACHE_SHOW_CONTEXT_MENU_FOR_REOPEN = true
  173. // const FIX_MENU_CAPTURE_SCROLL = true;
  174. const CHAT_MENU_REFIT_ALONG_SCROLLING = 0; // 0 for locking / default; 1 for unlocking only; 2 for unlocking and refit
  175.  
  176. const RAF_FIX_keepScrollClamped = true;
  177. const RAF_FIX_scrollIncrementally = 2; // 0: no action; 1: basic fix; 2: also fix scroll position
  178.  
  179. // << if BOOST_MENU_OPENCHANGED_RENDERING >>
  180. const FIX_MENU_POSITION_N_SIZING_ON_SHOWN = 1; // correct size and position when the menu dropdown opens
  181.  
  182. const CHECK_JSONPRUNE = true; // This is a bug in Brave
  183. // << end >>
  184.  
  185. // const LIVE_CHAT_FLUSH_ON_FOREGROUND_ONLY = false;
  186.  
  187. const CHANGE_MANAGER_UNSUBSCRIBE = true;
  188.  
  189. const INTERACTIVITY_BACKGROUND_ANIMATION = 1; // mostly for pinned message
  190. // 0 = default Yt animation background [= no fix];
  191. // 1 = disable default animation background [= keep special animation];
  192. // 2 = disable all animation backgrounds [= no animation backbround]
  193.  
  194. const CLOSE_TICKER_PINNED_MESSAGE_WHEN_HEADER_CLICKED = true;
  195.  
  196. const MAX_TOOLTIP_NO_WRAP_WIDTH = '72vw'; // '' for disable; accept values like '60px', '25vw'
  197.  
  198. const DISABLE_Translation_By_Google = true;
  199.  
  200. const FASTER_ICON_RENDERING = true;
  201.  
  202. const DELAY_FOCUSEDCHANGED = true;
  203.  
  204. const skipErrorForhandleAddChatItemAction_ = true; // currently depends on ENABLE_NO_SMOOTH_TRANSFORM
  205. const fixChildrenIssue801 = true; // if __children801__ is set [fix polymer controller method extration for `.set()`]
  206.  
  207. const SUPPRESS_refreshOffsetContainerHeight_ = true; // added in FEB 2024; true for default layout options; no effect if ENABLE_NO_SMOOTH_TRANSFORM is false
  208.  
  209. const NO_FILTER_DROPDOWN_BORDER = true; // added in 2024.03.02
  210.  
  211. const FIX_ANIMATION_TICKER_TEXT_POSITION = true; // CSS fix; experimental; added in 2024.04.07
  212. const FIX_AUTHOR_CHIP_BADGE_POSITION = true;
  213.  
  214. const FIX_ToggleRenderPolymerControllerExtractionBug = false; // to be reviewed
  215.  
  216. const REACTION_ANIMATION_PANEL_CSS_FIX = true;
  217.  
  218. const FIX_UNKNOWN_BUG_FOR_OVERLAY = true; // no .prepare() in backdrop element. reason is unknown.
  219.  
  220. const FIX_MOUSEOVER_FN = true; // avoid onMouseOver_ being triggerd quite a lot
  221.  
  222. // -------------------------------
  223.  
  224. const USE_OBTAIN_LCR_BY_BOTH_METHODS = false; // true for play safe
  225.  
  226. const FIX_MEMORY_LEAKAGE_TICKER_ACTIONMAP = true; // To fix Memory Leakage in yt-live-chat-ticker-...-item-renderer
  227. const FIX_MEMORY_LEAKAGE_TICKER_STATSBAR = true; // To fix Memory Leakage in updateStatsBarAndMaybeShowAnimation
  228. const FIX_MEMORY_LEAKAGE_TICKER_TIMER = true; // To fix Memory Leakage in setContainerWidth, slideDown, collapse // Dec 2024 fix in advance tickering
  229. const FIX_MEMORY_LEAKAGE_TICKER_DATACHANGED_setContainerWidth = true; // To fix Memory Leakage due to _.ytLiveChatTickerItemBehavior.setContainerWidth()
  230.  
  231.  
  232. // const USE_RM_ON_FOUNTAIN_MODEL = false; // No longer working since 2025.04.15
  233. // const DEBUG_RM_ON_FOUNTAIN_MODEL = false;
  234. // const FOUNTAIN_MODEL_TIME_CONFIRM = 1600; // 800 not sufficient; re-adding?
  235. const MODIFY_EMIT_MESSAGES_FOR_BOOST_CHAT = true; // enabled for boost chat only; instant emit & no background flush
  236.  
  237. /**
  238. *
  239. *
  240. *
  241. *
  242. *
  243. rendererStamperObserver_: function(a, b, c) {
  244. if (c.path == a) {
  245. if (c.value === void 0 && !this.hasDataPath_[a])
  246. return;
  247. this.hasDataPath_[a] = c.value !== void 0
  248. }
  249. this.rendererStamperApplyChangeRecord_(a, b, c)
  250. },
  251.  
  252.  
  253. addStampDomObserverFns_: function() {
  254. for (var a in this.stampDom) {
  255. var b = this.stampDom[a];
  256. b.id ? (this[SQa(b.id)] = this.rendererStamperObserver_.bind(this, a, b.id),
  257. this.hasDataPath_[a] = !1) : Er(new Dn("Bad rendererstamper config",this.is + ":" + a))
  258. }
  259. },
  260. *
  261. *
  262. *
  263. *
  264. *
  265. */
  266.  
  267.  
  268.  
  269.  
  270.  
  271.  
  272. // <<<<< FOR MEMORY LEAKAGE >>>>
  273.  
  274. // ========= EXPLANTION FOR 0.2% @ step timing [min. 0.2%] ===========
  275. /*
  276.  
  277. ### Time Approach
  278.  
  279. // all below values can make the time interval > 250ms
  280. // 250ms (practical value) refers to the minimum frequency for timeupdate in most browsers (typically, shorter timeupdate interval in modern browsers)
  281. if (totalDuration > 400000) stepInterval = 0.2; // 400000ms with 0.2% increment => 800ms
  282. else if (totalDuration > 200000) stepInterval = 0.5; // 200000ms with 0.5% increment => 1000ms
  283. else if (totalDuration > 100000) stepInterval = 1; // 100000ms with 1% increment => 1000ms
  284. else if (totalDuration > 50000) stepInterval = 2; // 50000ms with 2% increment => 1000ms
  285. else if (totalDuration > 25000) stepInterval = 5; // 25000ms with 5% increment => 1250ms
  286.  
  287. ### Pixel Check
  288. // Target Max Pixel Increment < 5px for Short Period Ticker (Rapid Background Change)
  289. // Assume total width <= 99px for short period ticker, like small donation & member welcome
  290. 99px * 5% = 4.95px < 5px [Condition Fulfilled]
  291.  
  292. ### Example - totalDuration = 280000
  293. totalDuration 280000
  294. stepInterval 0.5
  295. numOfSteps = Math.round(100 / stepInterval) = 200
  296. time interval = 280000 / 200 = 1400ms <acceptable>
  297.  
  298. ### Example - totalDuration = 18000
  299. totalDuration 18000
  300. stepInterval 5
  301. numOfSteps = Math.round(100 / stepInterval) = 20
  302. time interval = 18000 / 20 = 900ms <acceptable>
  303.  
  304. ### Example - totalDuration = 5000
  305. totalDuration 5000
  306. stepInterval 5
  307. numOfSteps = Math.round(100 / stepInterval) = 20
  308. time interval = 5000 / 20 = 250ms <threshold value>
  309.  
  310. ### Example - totalDuration = 3600
  311. totalDuration 3600
  312. stepInterval 5
  313. numOfSteps = Math.round(100 / stepInterval) = 20
  314. time interval = 3600 / 20 = 180ms <reasonable for 3600ms ticker>
  315.  
  316. */
  317.  
  318. // =======================================================================================================
  319.  
  320. // AUTOMAICALLY DETERMINED
  321. const ENABLE_FLAGS_MAINTAIN_STABLE_LIST = ENABLE_FLAGS_MAINTAIN_STABLE_LIST_VAL === 1;
  322. const ENABLE_FLAGS_MAINTAIN_STABLE_LIST_FOR_PARTICIPANTS_LIST = ENABLE_FLAGS_MAINTAIN_STABLE_LIST_VAL >= 1;
  323. const CHAT_MENU_SCROLL_UNLOCKING = CHAT_MENU_REFIT_ALONG_SCROLLING >= 1;
  324.  
  325.  
  326. // image sizing code
  327. // (d = (d = KC(a.customThumbnail.thumbnails, 16)) ? lc(oc(d)) : null)
  328.  
  329.  
  330. // function KC(a, b, c, d) {
  331. // d = void 0 === d ? "width" : d;
  332. // if (!a || !a.length)
  333. // return null;
  334. // if (z("kevlar_tuner_should_always_use_device_pixel_ratio")) {
  335. // var e = window.devicePixelRatio;
  336. // z("kevlar_tuner_should_clamp_device_pixel_ratio") ? e = Math.min(e, zl("kevlar_tuner_clamp_device_pixel_ratio")) : z("kevlar_tuner_should_use_thumbnail_factor") && (e = zl("kevlar_tuner_thumbnail_factor"));
  337. // HC = e
  338. // } else
  339. // HC || (HC = window.devicePixelRatio);
  340. // e = HC;
  341. // z("kevlar_tuner_should_always_use_device_pixel_ratio") ? b *= e : 1 < e && (b *= e);
  342. // if (z("kevlar_tuner_min_thumbnail_quality"))
  343. // return a[0].url || null;
  344. // e = a.length;
  345. // if (z("kevlar_tuner_max_thumbnail_quality"))
  346. // return a[e - 1].url || null;
  347. // if (c)
  348. // for (var h = 0; h < e; h++)
  349. // if (0 <= a[h].url.indexOf(c))
  350. // return a[h].url || null;
  351. // for (c = 0; c < e; c++)
  352. // if (a[c][d] >= b)
  353. // return a[c].url || null;
  354. // for (b = e - 1; 0 < b; b--)
  355. // if (a[b][d])
  356. // return a[b].url || null;
  357. // return a[0].url || null
  358. // }
  359.  
  360.  
  361. /// ------
  362.  
  363. // https://www.youtube.com/watch?v=byyvH5t0hKc
  364. // yt-live-chat-ticker-creator-goal-view-model
  365. // no ticker effect on timing
  366.  
  367. /*
  368.  
  369.  
  370. {
  371. "id": "ChwKGkNQS0pyNV9NdG9vREZVYlB6Z2FkRHWFUv2E",
  372. "initialTickerText": {
  373. "content": "Goal",
  374. "styleRuns": [
  375. {
  376. "startIndex": 0,
  377. "length": 4
  378. }
  379. ]
  380. },
  381. "tickerIcon": {
  382. "sources": [
  383. {
  384. "clientResource": {
  385. "imageName": "TARGET_ADD"
  386. }
  387. }
  388. ]
  389. },
  390. "showGoalStatusCommand": {
  391. "innertubeCommand": {
  392. "clickTrackingParams": "CCQQ7NANIhMI58DT_ef5rhMVxMW1Cx4qBzTz",
  393. "showEngagementPanelEndpoint": {
  394. "engagementPanel": {
  395. "engagementPanelSectionListRenderer": {
  396. "header": {
  397. "engagementPanelTitleHeaderRenderer": {
  398. "actionButton": {
  399. "buttonRenderer": {
  400. "icon": {
  401. "iconType": "QUESTION_CIRCLE"
  402. },
  403. "trackingParams": "CCgQ8FsiEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  404. "command": {
  405. "clickTrackingParams": "CCgQ8FsiEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  406. "commandExecutorCommand": {
  407. "commands": [
  408. {
  409. "clickTrackingParams": "CCgQ8FsiEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  410. "liveChatDialogEndpoint": {
  411. "content": {
  412. "liveChatDialogRenderer": {
  413. "trackingParams": "CCkQzS8iEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  414. "title": {
  415. "runs": [
  416. {
  417. "text": "Super Chat Goal"
  418. }
  419. ]
  420. },
  421. "dialogMessages": [
  422. {
  423. "runs": [
  424. {
  425. "text": "Join the fun by participating in the goal! "
  426. },
  427. {
  428. "text": "Learn more.\n",
  429. "navigationEndpoint": {
  430. "clickTrackingParams": "CCkQzS8iEwjm0Iz72rbKBxXT1EQBJekHNQM="
  431. }
  432. }
  433. ]
  434. },
  435. {
  436. "runs": [
  437. {
  438. "text": "How to participate",
  439. "bold": true,
  440. "textColor": 4294967295
  441. },
  442. {
  443. "text": "\n"
  444. },
  445. {
  446. "text": "1. Press \"Continue\"\n2. Purchase a Super Chat \n3. Watch the progress towards the goal\n4. Celebrate achieving it with the community!",
  447. "textColor": 4294967295
  448. }
  449. ]
  450. }
  451. ],
  452. "confirmButton": {
  453. "buttonRenderer": {
  454. "style": "STYLE_MONO_FILLED",
  455. "size": "SIZE_DEFAULT",
  456. "isDisabled": false,
  457. "text": {
  458. "simpleText": "Got it"
  459. },
  460. "trackingParams": "CCoQ8FsiEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  461. "accessibilityData": {
  462. "accessibilityData": {
  463. "label": "Got it"
  464. }
  465. }
  466. }
  467. }
  468. }
  469. }
  470. }
  471. },
  472. {
  473. "clickTrackingParams": "CCgQ8FsiEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  474. "hideEngagementPanelEndpoint": {
  475. "identifier": {
  476. "surface": "ENGAGEMENT_PANEL_SURFACE_LIVE_CHAT",
  477. "tag": "creator_goal_progress_engagement_panel"
  478. }
  479. }
  480. }
  481. ]
  482. }
  483. }
  484. }
  485. },
  486. "trackingParams": "CCUQ040EIhMI58DT_ef5rhMVxMW1Cx4qBzTz"
  487. }
  488. },
  489. "content": {
  490. "sectionListRenderer": {
  491. "contents": [
  492. {
  493. "creatorGoalProgressFlowViewModel": {
  494. "creatorGoalEntityKey": "EgtieXl2SDV0MGhLYyG7BzhF",
  495. "progressFlowButton": {
  496. "buttonViewModel": {
  497. "onTap": {
  498. "innertubeCommand": {
  499. "clickTrackingParams": "CCcQ8FsiEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  500. "commandMetadata": {
  501. "webCommandMetadata": {
  502. "ignoreNavigation": true
  503. }
  504. },
  505. "liveChatPurchaseMessageEndpoint": {
  506. "params": "Q2lrcUp3b1lWVU14ZFdObmIwTmZjMGQzZDE5RmRYVTFhVTF4Y0ZGM0VndGllWGwyU0RWME1HaExZeEFCSUFFNEFFSUNDQUUlM0Q="
  507. }
  508. }
  509. },
  510. "style": "BUTTON_VIEW_MODEL_STYLE_MONO",
  511. "trackingParams": "CCcQ8FsiEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  512. "type": "BUTTON_VIEW_MODEL_TYPE_FILLED",
  513. "titleFormatted": {
  514. "content": "Continue",
  515. "styleRuns": [
  516. {
  517. "startIndex": 0,
  518. "length": 8
  519. }
  520. ]
  521. }
  522. }
  523. },
  524. "progressCountA11yLabel": "Super Chat goal progress: $0 out of $1"
  525. }
  526. }
  527. ],
  528. "trackingParams": "CCYQui8iEwjm0Iz72rbKBxXT1EQBJekHNQM="
  529. }
  530. },
  531. "identifier": {
  532. "surface": "ENGAGEMENT_PANEL_SURFACE_LIVE_CHAT",
  533. "tag": "creator_goal_progress_engagement_panel"
  534. }
  535. }
  536. },
  537. "identifier": {
  538. "surface": "ENGAGEMENT_PANEL_SURFACE_LIVE_CHAT",
  539. "tag": "creator_goal_progress_engagement_panel"
  540. },
  541. "engagementPanelPresentationConfigs": {
  542. "engagementPanelPopupPresentationConfig": {
  543. "popupType": "PANEL_POPUP_TYPE_DIALOG"
  544. }
  545. }
  546. }
  547. }
  548. },
  549. "creatorGoalEntityKey": "EgtieXl2SDV0MGhLYyG7BzhF",
  550. "shouldShowSetUpFlowOnMobile": true,
  551. "a11yLabel": "See Super Chat goal",
  552. "loggingDirectives": {
  553. "trackingParams": "CCQQ7NANIhMI58DT_ef5rhMVxMW1Cx4qBzTz",
  554. "visibility": {
  555. "types": "12"
  556. }
  557. }
  558. }
  559.  
  560.  
  561. */
  562.  
  563.  
  564. // ------
  565.  
  566. const { IntersectionObserver } = __CONTEXT__;
  567. let _x69;
  568. try {
  569. _x69 = document.createAttributeNS("http://www.w3.org/2000/svg", "nil").addEventListener;
  570. } catch (e) { }
  571. const pureAddEventListener = _x69;
  572. if (!pureAddEventListener) return console.warn("pureAddEventListener cannot be obtained.");
  573.  
  574. /** @type {globalThis.PromiseConstructor} */
  575. const Promise = (async () => { })().constructor; // YouTube hacks Promise in WaterFox Classic and "Promise.resolve(0)" nevers resolve.
  576. const [setTimeout_] = [setTimeout];
  577. // let jsonParseFix = null;
  578. const Image_ = Image;
  579. /** @type {typeof HTMLElement} */
  580. const HTMLElement_ = Reflect.getPrototypeOf(HTMLTitleElement);
  581.  
  582. const nextBrowserTick_ = nextBrowserTick;
  583. if (typeof nextBrowserTick_ !== "function" || (nextBrowserTick_.version || 0) < 2) {
  584. console.log('nextBrowserTick is not found.');
  585. return;
  586. }
  587.  
  588. if (!IntersectionObserver) return console.warn("Your browser does not support IntersectionObserver.\nPlease upgrade to the latest version.");
  589. if (typeof WebAssembly !== 'object') return console.warn("Your browser is too old.\nPlease upgrade to the latest version."); // for passive and once
  590.  
  591. if (typeof CSS === 'undefined' || typeof (CSS || 0).supports !== 'function' || !CSS.supports('left', 'clamp(-100%, calc( -100% * 0.5 ), 0%)')) {
  592. return console.warn("Your browser is too old.\nPlease upgrade to the latest version."); // for advanced tickering
  593. }
  594.  
  595.  
  596. // necessity of cssText3_smooth_transform_position to be checked.
  597. const cssText3_smooth_transform_position = ENABLE_NO_SMOOTH_TRANSFORM ? `
  598.  
  599. #item-offset.style-scope.yt-live-chat-item-list-renderer > #items.style-scope.yt-live-chat-item-list-renderer {
  600. position: static !important;
  601. }
  602.  
  603. `: '';
  604.  
  605. // fallback if dummy style fn fails
  606. const cssText4_smooth_transform_forced_props = ENABLE_NO_SMOOTH_TRANSFORM ? `
  607.  
  608. /* optional */
  609. #item-offset.style-scope.yt-live-chat-item-list-renderer {
  610. height: auto !important;
  611. min-height: unset !important;
  612. }
  613.  
  614. #items.style-scope.yt-live-chat-item-list-renderer {
  615. transform: translateY(0px) !important;
  616. }
  617.  
  618. /* optional */
  619.  
  620. `: '';
  621.  
  622. const cssText5 = SET_CONTAIN_FOR_CHATROOM ? `
  623.  
  624. /* ------------------------------------------------------------------------------------------------------------- */
  625.  
  626. yt-live-chat-author-chip #chat-badges.yt-live-chat-author-chip, yt-live-chat-author-chip #chat-badges.yt-live-chat-author-chip yt-live-chat-author-badge-renderer, yt-live-chat-author-chip #chat-badges.yt-live-chat-author-chip yt-live-chat-author-badge-renderer #image, yt-live-chat-author-chip #chat-badges.yt-live-chat-author-chip yt-live-chat-author-badge-renderer #image img {
  627. contain: layout style;
  628. }
  629.  
  630. #items.style-scope.yt-live-chat-item-list-renderer {
  631. contain: layout paint style;
  632. }
  633.  
  634. #item-offset.style-scope.yt-live-chat-item-list-renderer {
  635. contain: style;
  636. }
  637.  
  638. #item-scroller.style-scope.yt-live-chat-item-list-renderer {
  639. contain: size style;
  640. }
  641.  
  642. #contents.style-scope.yt-live-chat-item-list-renderer, #chat.style-scope.yt-live-chat-renderer, img.style-scope.yt-img-shadow[width][height] {
  643. contain: size layout paint style;
  644. }
  645.  
  646. .style-scope.yt-live-chat-ticker-renderer[role="button"][aria-label], .style-scope.yt-live-chat-ticker-renderer[role="button"][aria-label] > #container {
  647. contain: layout paint style;
  648. }
  649.  
  650. yt-live-chat-text-message-renderer.style-scope.yt-live-chat-item-list-renderer, yt-live-chat-membership-item-renderer.style-scope.yt-live-chat-item-list-renderer, yt-live-chat-paid-message-renderer.style-scope.yt-live-chat-item-list-renderer, yt-live-chat-banner-manager.style-scope.yt-live-chat-item-list-renderer {
  651. contain: layout style;
  652. }
  653.  
  654. tp-yt-paper-tooltip[style*="inset"][role="tooltip"] {
  655. contain: layout paint style;
  656. }
  657.  
  658. /* ------------------------------------------------------------------------------------------------------------- */
  659.  
  660. ` : '';
  661.  
  662. const cssText6b_show_more_button = FIX_SHOW_MORE_BUTTON_LOCATION ? `
  663.  
  664. yt-live-chat-renderer[has-action-panel-renderer] #show-more.yt-live-chat-item-list-renderer{
  665. top: 4px;
  666. transition-property: top;
  667. bottom: unset;
  668. }
  669.  
  670. yt-live-chat-renderer[has-action-panel-renderer] #show-more.yt-live-chat-item-list-renderer[disabled]{
  671. top: -42px;
  672. }
  673.  
  674. `: '';
  675.  
  676. const cssText6c_input_panel_overflow = FIX_INPUT_PANEL_OVERFLOW_ISSUE ? `
  677.  
  678. #input-panel #picker-buttons yt-live-chat-icon-toggle-button-renderer#product-picker {
  679. contain: layout style;
  680. }
  681.  
  682. #chat.yt-live-chat-renderer ~ #panel-pages.yt-live-chat-renderer {
  683. overflow: visible;
  684. }
  685.  
  686. `: '';
  687.  
  688. const cssText6d_input_panel_border = FIX_INPUT_PANEL_BORDER_ISSUE ? `
  689.  
  690. html #panel-pages.yt-live-chat-renderer > #input-panel.yt-live-chat-renderer:not(:empty) {
  691. --yt-live-chat-action-panel-top-border: none;
  692. }
  693.  
  694. html #panel-pages.yt-live-chat-renderer > #input-panel.yt-live-chat-renderer.iron-selected > *:first-child {
  695. border-top: 1px solid var(--yt-live-chat-panel-pages-border-color);
  696. }
  697.  
  698. html #panel-pages.yt-live-chat-renderer {
  699. border-top: 0;
  700. border-bottom: 0;
  701. }
  702.  
  703. `: '';
  704.  
  705. const cssText7b_content_visibility_unset = FORCE_CONTENT_VISIBILITY_UNSET ? `
  706.  
  707. img,
  708. yt-img-shadow[height][width],
  709. yt-img-shadow {
  710. content-visibility: visible !important;
  711. }
  712.  
  713. ` : '';
  714.  
  715. const cssText7c_will_change_unset = FORCE_WILL_CHANGE_UNSET ? `
  716.  
  717. /* remove YouTube constant will-change */
  718. /* constant value will slow down the performance; default auto */
  719.  
  720. /* www-player.css */
  721. html .ytp-contextmenu,
  722. html .ytp-settings-menu {
  723. will-change: unset;
  724. }
  725.  
  726. /* frequently matched elements */
  727. html .fill.yt-interaction,
  728. html .stroke.yt-interaction,
  729. html .yt-spec-touch-feedback-shape__fill,
  730. html .yt-spec-touch-feedback-shape__stroke {
  731. will-change: unset;
  732. }
  733.  
  734. /* live_chat_polymer.js */
  735. /*
  736. html .toggle-button.tp-yt-paper-toggle-button,
  737. html #primaryProgress.tp-yt-paper-progress,
  738. html #secondaryProgress.tp-yt-paper-progress,
  739. html #onRadio.tp-yt-paper-radio-button,
  740. html .fill.yt-interaction,
  741. html .stroke.yt-interaction,
  742. html .yt-spec-touch-feedback-shape__fill,
  743. html .yt-spec-touch-feedback-shape__stroke {
  744. will-change: unset;
  745. }
  746. */
  747.  
  748. /* desktop_polymer_enable_wil_icons.js */
  749. /* html .fill.yt-interaction,
  750. html .stroke.yt-interaction, */
  751. html tp-yt-app-header::before,
  752. html tp-yt-iron-list,
  753. html #items.tp-yt-iron-list > *,
  754. html #onRadio.tp-yt-paper-radio-button,
  755. html .toggle-button.tp-yt-paper-toggle-button,
  756. html ytd-thumbnail-overlay-toggle-button-renderer[use-expandable-tooltip] #label.ytd-thumbnail-overlay-toggle-button-renderer,
  757. html #items.ytd-post-multi-image-renderer,
  758. html #items.ytd-horizontal-card-list-renderer,
  759. html #items.yt-horizontal-list-renderer,
  760. html #left-arrow.yt-horizontal-list-renderer,
  761. html #right-arrow.yt-horizontal-list-renderer,
  762. html #items.ytd-video-description-infocards-section-renderer,
  763. html #items.ytd-video-description-music-section-renderer,
  764. html #chips.ytd-feed-filter-chip-bar-renderer,
  765. html #chips.yt-chip-cloud-renderer,
  766. html #items.ytd-merch-shelf-renderer,
  767. html #items.ytd-product-details-image-carousel-renderer,
  768. html ytd-video-preview,
  769. html #player-container.ytd-video-preview,
  770. html #primaryProgress.tp-yt-paper-progress,
  771. html #secondaryProgress.tp-yt-paper-progress,
  772. html ytd-miniplayer[enabled] /* ,
  773. html .yt-spec-touch-feedback-shape__fill,
  774. html .yt-spec-touch-feedback-shape__stroke */ {
  775. will-change: unset;
  776. }
  777.  
  778. /* other */
  779. .ytp-videowall-still-info-content[class],
  780. .ytp-suggestion-image[class] {
  781. will-change: unset !important;
  782. }
  783.  
  784. ` : '';
  785.  
  786. const ENABLE_FONT_PRE_RENDERING = typeof HTMLElement_.prototype.append === 'function' ? (ENABLE_FONT_PRE_RENDERING_PREFERRED || 0) : 0;
  787. const cssText8_fonts_pre_render = ENABLE_FONT_PRE_RENDERING ? `
  788.  
  789. elzm-fonts {
  790. visibility: collapse;
  791. position: fixed;
  792. top: -10px;
  793. left: -10px;
  794. font-size: 10pt;
  795. line-height: 100%;
  796. width: 100px;
  797. height: 100px;
  798. transform: scale(0.1);
  799. transform: scale(0.01);
  800. transform: scale(0.001);
  801. transform-origin: 0 0;
  802. contain: strict;
  803. display: block;
  804.  
  805. pointer-events: none !important;
  806. user-select: none !important;
  807. }
  808.  
  809. elzm-fonts[id]#elzm-fonts-yk75g {
  810. user-select: none !important;
  811. pointer-events: none !important;
  812. }
  813.  
  814. elzm-font {
  815. visibility: collapse;
  816. position: absolute;
  817. line-height: 100%;
  818. width: 100px;
  819. height: 100px;
  820. contain: strict;
  821. display: block;
  822.  
  823. user-select: none !important;
  824. pointer-events: none !important;
  825. }
  826.  
  827. elzm-font::before {
  828. visibility: collapse;
  829. position: absolute;
  830. line-height: 100%;
  831. width: 100px;
  832. height: 100px;
  833. contain: strict;
  834. display: block;
  835.  
  836. content: '0aZ!@#$~^&*()_-+[]{}|;:><?\\0460\\0301\\0900\\1F00\\0370\\0102\\0100\\28EB2\\28189\\26DA0\\25A9C\\249BB\\23F61\\22E8B\\21927\\21076\\2048E\\1F6F5\\FF37\\F94F\\F0B2\\9F27\\9D9A\\9BEA\\9A6B\\98EC\\9798\\9602\\949D\\9370\\926B\\913A\\8FA9\\8E39\\8CC1\\8B26\\8983\\8804\\8696\\8511\\83BC\\828D\\8115\\7F9A\\7E5B\\7D07\\7B91\\7A2C\\78D2\\776C\\7601\\74AA\\73B9\\7265\\70FE\\6FBC\\6E88\\6D64\\6C3F\\6A9C\\6957\\67FE\\66B3\\6535\\63F2\\628E\\612F\\5FE7\\5E6C\\5CEE\\5B6D\\5A33\\58BC\\575B\\5611\\54BF\\536E\\51D0\\505D\\4F22\\4AD1\\41DB\\3B95\\3572\\2F3F\\26FD\\25A1\\2477\\208D\\1D0A\\1FB\\A1\\A3\\B4\\2CB\\60\\10C\\E22\\A5\\4E08\\B0\\627\\2500\\5E\\201C\\3C\\B7\\23\\26\\3E\\D\\20\\25EE8\\1F235\\FFD7\\FA10\\F92D\\9E8B\\9C3E\\9AE5\\98EB\\971D\\944A\\92BC\\9143\\8F52\\8DC0\\8B2D\\8973\\87E2\\8655\\84B4\\82E8\\814A\\7F77\\7D57\\7BC8\\7A17\\7851\\768C\\7511\\736C\\7166\\6F58\\6D7C\\6B85\\69DD\\6855\\667E\\64D2\\62CF\\6117\\5F6C\\5D9B\\5BBC\\598B\\57B3\\5616\\543F\\528D\\50DD\\4F57\\4093\\3395\\32B5\\31C8\\3028\\2F14\\25E4\\24D1\\2105\\2227\\A8\\2D9\\2CA\\2467\\B1\\2020\\2466\\251C\\266B\\AF\\4E91\\221E\\2464\\2266\\2207\\4E32\\25B3\\2463\\2010\\2103\\3014\\25C7\\24\\25BD\\4E18\\2460\\21D2\\2015\\2193\\4E03\\7E\\25CB\\2191\\25BC\\3D\\500D\\4E01\\25\\30F6\\2605\\266A\\40\\2B\\4E16\\7C\\A9\\4E\\21\\1F1E9\\FEE3\\F0A7\\9F3D\\9DFA\\9C3B\\9A5F\\98C8\\972A\\95B9\\94E7\\9410\\92B7\\914C\\8FE2\\8E2D\\8CAF\\8B5E\\8A02\\8869\\86E4\\8532\\83B4\\82A9\\814D\\7FFA\\7ED7\\7DC4\\7CCC\\7BC3\\7ACA\\797C\\783E\\770F\\760A\\74EF\\73E7\\72DD\\719C\\7005\\6ED8\\6DC3\\6CB2\\6A01\\68E1\\6792\\663A\\64F8\\63BC\\623B\\60FA\\5FD1\\5EA3\\5D32\\5BF5\\5AB2\\5981\\5831\\570A\\5605\\5519\\53FB\\52A2\\5110\\4FE3\\4EB8\\3127\\279C\\2650\\254B\\23E9\\207B\\1D34\\2AE\\176\\221A\\161\\200B\\300C\\4E4C\\1F921\\FF78\\FA0A\\F78A\\9EB9\\9D34\\9BD3\\9A6F\\9912\\97C6\\964E\\950C\\93E4\\92E5\\91F0\\90BB\\8F68\\8E18\\8B6C\\89F6\\889B\\874C\\8602\\84B1\\8378\\826E\\8113\\7FB1\\7EAF\\7D89\\7C20\\7AFB\\7988\\7840\\7705\\75CC\\749A\\73B3\\727F\\7113\\6FE8\\6ED6\\6DD3\\6CDA\\6BBB\\6A31\\6900\\67D9\\66A7\\655D\\6427\\630D\\61C6\\60AC\\5F78\\5E34\\5CE0\\5B80\\5A51\\590B\\57A1\\566F\\5551\\543D\\52DB\\518F\\5032\\3A17\\305C\\2749\\264A\\2567\\2476\\2139\\1EC0\\11AF\\2C8\\1AF\\E17\\2190\\2022\\2502\\2312\\2025\\50';
  837.  
  838. user-select: none !important;
  839. pointer-events: none !important;
  840. }
  841.  
  842. `: '';
  843.  
  844. const cssText9_no_backdrop_filter_when_menu_shown = NO_BACKDROP_FILTER_WHEN_MENU_SHOWN ? `
  845. tp-yt-iron-dropdown.yt-live-chat-app ytd-menu-popup-renderer {
  846. -webkit-backdrop-filter: none;
  847. backdrop-filter: none;
  848. }
  849. `: '';
  850.  
  851. const cssText10_show_more_blinker = ENABLE_SHOW_MORE_BLINKER ? `
  852.  
  853. @keyframes blinker-miuzp {
  854. 0%, 60%, 100% {
  855. opacity: 1;
  856. }
  857. 30% {
  858. opacity: 0.6;
  859. }
  860. }
  861.  
  862. yt-icon-button#show-more.has-new-messages-miuzp {
  863. animation: blinker-miuzp 1.74s linear infinite;
  864. }
  865.  
  866. `: '';
  867.  
  868. const cssText11_entire_message_clickable = FIX_CLICKING_MESSAGE_MENU_DISPLAY_ON_MOUSE_CLICK ? `
  869.  
  870. yt-live-chat-paid-message-renderer.yt-live-chat-item-list-renderer[whole-message-clickable] #menu.style-scope[class] {
  871. pointer-events: none !important;
  872. }
  873.  
  874. yt-live-chat-membership-item-renderer.yt-live-chat-item-list-renderer[whole-message-clickable] #menu.style-scope[class] {
  875. pointer-events: none !important;
  876. }
  877.  
  878. yt-live-chat-paid-sticker-renderer.yt-live-chat-item-list-renderer[whole-message-clickable] #menu.style-scope[class] {
  879. pointer-events: none !important;
  880. }
  881.  
  882. yt-live-chat-text-message-renderer.yt-live-chat-item-list-renderer[whole-message-clickable] #menu.style-scope[class] {
  883. pointer-events: none !important; /* TO_BE_REVIEWED */
  884. }
  885.  
  886. yt-live-chat-auto-mod-message-renderer.yt-live-chat-item-list-renderer[whole-message-clickable] #menu.style-scope[class] {
  887. pointer-events: none !important;
  888. }
  889.  
  890. `: '';
  891.  
  892. const cssText12_nowrap_tooltip = MAX_TOOLTIP_NO_WRAP_WIDTH && typeof MAX_TOOLTIP_NO_WRAP_WIDTH === 'string' ? `
  893.  
  894.  
  895. tp-yt-paper-tooltip[role="tooltip"] {
  896. box-sizing: content-box !important;
  897. margin: 0px !important;
  898. padding: 0px !important;
  899. contain: none !important;
  900. }
  901.  
  902. tp-yt-paper-tooltip[role="tooltip"] #tooltip[style-target="tooltip"] {
  903. box-sizing: content-box !important;
  904. display: inline-block;
  905. contain: none !important;
  906. }
  907.  
  908.  
  909. tp-yt-paper-tooltip[role="tooltip"] #tooltip[style-target="tooltip"]{
  910. max-width: ${MAX_TOOLTIP_NO_WRAP_WIDTH};
  911. width: max-content;
  912. text-overflow: ellipsis;
  913. overflow: hidden;
  914. white-space: nowrap;
  915. }
  916.  
  917.  
  918. `: '';
  919.  
  920.  
  921. const cssText13_no_text_select_when_menu_visible = `
  922. [menu-visible] {
  923. --sfc47-text-select: none;
  924. }
  925. [menu-visible] #header[id][class],
  926. [menu-visible] #content[id][class],
  927. [menu-visible] #header[id][class] *,
  928. [menu-visible] #content[id][class] * {
  929. user-select: var(--sfc47-text-select) !important;
  930. }
  931. [menu-visible] #menu {
  932. --sfc47-text-select: inherit;
  933. }
  934. `;
  935.  
  936. const cssText14_NO_FILTER_DROPDOWN_BORDER = NO_FILTER_DROPDOWN_BORDER ? `
  937. yt-live-chat-header-renderer.yt-live-chat-renderer #label.yt-dropdown-menu::before {
  938. border:0;
  939. }
  940. ` : '';
  941.  
  942. const cssText15_FIX_ANIMATION_TICKER_TEXT_POSITION = FIX_ANIMATION_TICKER_TEXT_POSITION ? `
  943. .style-scope.yt-live-chat-ticker-renderer #animation-container[id][class] {
  944. position: relative;
  945. display: grid;
  946. grid-auto-columns: 1fr;
  947. grid-auto-rows: 1fr;
  948. grid-template-columns: repeat(1, 1fr);
  949. gap: 7px;
  950. padding-bottom: 0;
  951. margin-bottom: 0;
  952. padding-top: 0;
  953. align-self: flex-start;
  954. flex-wrap: nowrap;
  955. margin-top: 1px;
  956. }
  957.  
  958. .style-scope.yt-live-chat-ticker-renderer #animation-container > [id][class] {
  959. margin-top: 0px;
  960. margin-bottom: 0px;
  961. flex-direction: row;
  962. flex-wrap: nowrap;
  963. align-items: center;
  964. justify-content: flex-start;
  965. }
  966.  
  967. .style-scope.yt-live-chat-ticker-renderer #animation-container > [id][class]:first-child::after {
  968. content: '補';
  969. visibility: collapse;
  970. display: inline-block;
  971. position: relative;
  972. width: 0;
  973. line-height: 22px;
  974. }
  975.  
  976. ` : '';
  977.  
  978. const cssText16_FIX_AUTHOR_CHIP_BADGE_POSITION = FIX_AUTHOR_CHIP_BADGE_POSITION ? `
  979. #card #author-name-chip > yt-live-chat-author-chip[single-line] {
  980. flex-wrap: nowrap;
  981. white-space: nowrap;
  982. display: inline-flex;
  983. flex-direction: row;
  984. text-wrap: nowrap;
  985. flex-shrink: 0;
  986. align-items: center;
  987. }
  988.  
  989. #card #author-name-chip {
  990. display: inline-flex;
  991. flex-direction: row;
  992. align-items: flex-start;
  993. }
  994. `: '';
  995.  
  996.  
  997. // Example: https://www.youtube.com/watch?v=Xfytz-igsuc
  998. const cssText17_FIX_overwidth_banner_message = `
  999. yt-live-chat-banner-manager#live-chat-banner.style-scope.yt-live-chat-item-list-renderer {
  1000. max-width: 100%;
  1001. box-sizing: border-box;
  1002. }
  1003. `;
  1004.  
  1005.  
  1006. const cssText18_REACTION_ANIMATION_PANEL_CSS_FIX = REACTION_ANIMATION_PANEL_CSS_FIX ? `
  1007. #reaction-control-panel-overlay[class] {
  1008. contain: strict;
  1009. margin: 0;
  1010. padding: 0;
  1011. border: 0;
  1012. box-sizing: border-box;
  1013. will-change: initial;
  1014. }
  1015. #reaction-control-panel-overlay[class] *[class] {
  1016. will-change: initial;
  1017. }
  1018. `: '';
  1019.  
  1020. const cssText19_FOR_ADVANCED_TICKING = USE_ADVANCED_TICKING ? `
  1021.  
  1022. ticker-bg-overlay {
  1023. display: block;
  1024. position: absolute;
  1025. z-index: -1;
  1026. box-sizing: border-box;
  1027. border: 0;
  1028. padding: 0;
  1029. margin: 0;
  1030. width: 200%;
  1031. top: 0;
  1032. bottom: 0;
  1033. left: clamp(-100%, calc( -100% * ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) ), 0%);
  1034. contain: strict;
  1035. pointer-events: none;
  1036. }
  1037. ticker-bg-overlay-end2 {
  1038.  
  1039. all:unset;
  1040. position: fixed;
  1041. display: block;
  1042. margin-left: -0.5px;
  1043. top: 8px;
  1044. left: clamp(-250px, calc( 250px * ( ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) - 1 ) ), 2px);
  1045.  
  1046. width: 1px;
  1047. height: 1px;
  1048. opacity: 0;
  1049. pointer-events: none;
  1050. box-sizing: border-box;
  1051. border: 0;
  1052. padding: 0;
  1053. margin: 0;
  1054. contain: strict;
  1055. z-index: -1;
  1056. visibility: collapse;
  1057.  
  1058.  
  1059. }
  1060.  
  1061.  
  1062. /* .r6-closing-ticker is provided in ADVANCED_TICKING */
  1063. /* so .r6-width-adjustable is only available for ADVANCED_TICKING too */
  1064.  
  1065. /* DO NOT use .r6-width-adjustable ~ .r6-width-adjustable => very laggy */
  1066.  
  1067. /*
  1068. yt-live-chat-ticker-renderer {
  1069. --r6-transition-duration: 0.2s;
  1070. }
  1071.  
  1072. .r6-width-adjustable, .yt-live-chat-ticker-stampdom {
  1073. --r6-transition-duration-v: var(--r6-transition-duration);
  1074. transition: var(--r6-transition-duration-v);
  1075. }
  1076.  
  1077. .r6-width-adjustable-f {
  1078. --r6-transition-duration-v: 0s;
  1079. }
  1080.  
  1081. .r6-closing-ticker[class] {
  1082. --r6-transition-duration-v: var(--r6-transition-duration);
  1083. }
  1084. */
  1085.  
  1086.  
  1087.  
  1088. .r6-width-adjustable {
  1089. --r6-min-width: 0;
  1090. min-width: var(--r6-min-width);
  1091. }
  1092.  
  1093. .r6-width-adjustable-f {
  1094. --r6-min-width: max-content;
  1095. }
  1096.  
  1097. .r6-closing-ticker[class] {
  1098. --r6-min-width: 0;
  1099. }
  1100.  
  1101. ` : '';
  1102.  
  1103. const cssText20_TICKER_SIZING = ENABLE_TICKERS_BOOSTED_STAMPING && DISABLE_DYNAMIC_TICKER_WIDTH ? `
  1104.  
  1105. :root {
  1106. --ticker-items-gap: 8px;
  1107. }
  1108. #ticker-items.yt-live-chat-ticker-renderer {
  1109. position: relative;
  1110. transform: translateZ(1px);
  1111. box-sizing: border-box;
  1112. contain: style;
  1113. display: flex;
  1114. flex-direction: row;
  1115. gap: var(--ticker-items-gap);
  1116. }
  1117. #container.yt-live-chat-ticker-renderer {
  1118. contain: layout paint style;
  1119. }
  1120.  
  1121. .yt-live-chat-ticker-stampdom {
  1122. position: static;
  1123. width: max-content;
  1124. content-visibility:auto;
  1125. }
  1126. .yt-live-chat-ticker-stampdom[class] {
  1127. transition: none;
  1128. }
  1129. .yt-live-chat-ticker-stampdom-container {
  1130. position: static;
  1131. width: max-content;
  1132. content-visibility:auto;
  1133. }
  1134.  
  1135. .yt-live-chat-ticker-stampdom {
  1136. margin-right:0 !important; /* flex gap 8px */
  1137. }
  1138.  
  1139. /* default animation */
  1140. .yt-live-chat-ticker-stampdom {
  1141. animation: ticker-shown-animation 220ms ease-in 0s 1 normal forwards;
  1142. }
  1143. /* default animation */
  1144. @keyframes ticker-shown-animation {
  1145. 0%, 70%, 100% { opacity: 1; }
  1146. 30% { opacity: 0.2; }
  1147. }
  1148.  
  1149.  
  1150. ` : "";
  1151. // const cssText19_FOR_ADVANCED_TICKING = `
  1152.  
  1153. // ticker-bg-overlay {
  1154. // display: block;
  1155. // position: absolute;
  1156. // z-index: -1;
  1157. // box-sizing: border-box;
  1158. // border: 0;
  1159. // padding: 0;
  1160. // margin: 0;
  1161. // width: 200%;
  1162. // top: 0;
  1163. // bottom: 0;
  1164. // left: clamp(-100%, calc( -100% * ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) ), 0%);
  1165. // contain: strict;
  1166. // }
  1167. // /*
  1168. // ticker-bg-overlay-end {
  1169. // position: absolute;
  1170. // right: 0px;
  1171. // top: 50%;
  1172. // display: block;
  1173. // width: 1px;
  1174. // height: 1px;
  1175. // opacity: 0;
  1176. // pointer-events: none;
  1177. // box-sizing: border-box;
  1178. // border: 0;
  1179. // padding: 0;
  1180. // margin: 0;
  1181. // contain: strict;
  1182. // }
  1183. // */
  1184.  
  1185. // ticker-bg-overlay-end2 {
  1186.  
  1187. // all:unset;
  1188. // position: fixed;
  1189. // display: block;
  1190. // margin-left: -0.5px;
  1191. // top: 8px;
  1192. // left: clamp(-250px, calc( 250px * ( ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) - 1 ) ), 2px);
  1193.  
  1194. // width: 1px;
  1195. // height: 1px;
  1196. // opacity: 0;
  1197. // pointer-events: none;
  1198. // box-sizing: border-box;
  1199. // border: 0;
  1200. // padding: 0;
  1201. // margin: 0;
  1202. // contain: strict;
  1203. // z-index: -1;
  1204. // visibility: collapse;
  1205.  
  1206.  
  1207. // }
  1208.  
  1209. // /* USE_ADVANCED_TICKING */
  1210.  
  1211. // /*
  1212.  
  1213. // .ticker-no-transition-time, .ticker-no-transition-time [id] {
  1214. // transition-duration: 0s !important;
  1215. // }
  1216.  
  1217. // [r6-advanced-ticking] .style-scope.yt-live-chat-ticker-renderer ~ .style-scope.yt-live-chat-ticker-renderer:not(.r6-closing-ticker) {
  1218. // transition-duration: 0s !important;
  1219. // }
  1220.  
  1221. // */
  1222.  
  1223. // .r6-width-adjustable ~ .r6-width-adjustable {
  1224. // --r6-min-width: max-content;
  1225. // }
  1226.  
  1227. // .r6-closing-ticker[class] {
  1228. // --r6-min-width: 0px;
  1229. // }
  1230.  
  1231. // .r6-width-adjustable {
  1232. // min-width: var(--r6-min-width, 0px);
  1233. // }
  1234.  
  1235.  
  1236. // /*
  1237.  
  1238.  
  1239. // .r6-width-adjustable {
  1240. // transition-duration: var(--r6-transition-duration, 0s) !important;
  1241. // }
  1242.  
  1243. // .r6-width-adjustable-first {
  1244. // --r6-transition-duration: 0.2s;
  1245. // }
  1246.  
  1247. // .r6-width-adjustable ~ .r6-width-adjustable-first {
  1248. // --r6-transition-duration: 0s;
  1249. // }
  1250.  
  1251. // .r6-closing-ticker {
  1252. // --r6-transition-duration: 0.2s;
  1253. // }
  1254. // */
  1255.  
  1256. // /*
  1257.  
  1258.  
  1259. // ey.style.position = 'absolute';
  1260. // ey.style.right = '0px';
  1261. // ey.style.top = '50%';
  1262. // ey.style.display='block';
  1263. // ey.style.width='1px';
  1264. // ey.style.height='1px';
  1265. // ey.style.opacity = '0';
  1266.  
  1267. // em.style.display = 'block';
  1268. // em.style.position = 'absolute';
  1269. // em.style.boxSizing = 'border-box';
  1270. // em.style.width = '200%';
  1271. // em.style.top = '0';
  1272. // em.style.bottom = '0';
  1273. // // em.style.height = '100%';
  1274.  
  1275.  
  1276. // // em.style.left = '-50%';
  1277. // // em.style.left = "clamp(-100%, calc( -100% * ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) ), 0%)";
  1278.  
  1279. // */
  1280.  
  1281. // `;
  1282.  
  1283. const addCss = () => `
  1284.  
  1285. yt-live-chat-renderer {
  1286. max-height: 100vh;
  1287. }
  1288.  
  1289. @property --ticker-rtime {
  1290. syntax: "<percentage>";
  1291. inherits: false;
  1292. initial-value: 0%;
  1293. }
  1294.  
  1295. .run-ticker {
  1296. --ticker-bg:linear-gradient(90deg, var(--ticker-c1),var(--ticker-c1) var(--ticker-rtime),var(--ticker-c2) var(--ticker-rtime),var(--ticker-c2));
  1297. }
  1298.  
  1299. .run-ticker,
  1300. yt-live-chat-ticker-renderer #items > * > #container.run-ticker,
  1301. yt-live-chat-ticker-renderer[class] #items[class] > *[class] > #container.run-ticker[class]
  1302. {
  1303. background: var(--ticker-bg) !important;
  1304. }
  1305.  
  1306. yt-live-chat-ticker-dummy777-item-renderer {
  1307. background: #00000001;
  1308. }
  1309.  
  1310. yt-live-chat-ticker-dummy777-item-renderer[dummy777] {
  1311. position: fixed !important;
  1312. top: -1000px !important;
  1313. left: -1000px !important;
  1314. font-size: 1px !important;
  1315. color: transparent !important;
  1316. pointer-events: none !important;
  1317. z-index: -1 !important;
  1318. contain: strict !important;
  1319. box-sizing: border-box !important;
  1320. pointer-events: none !important;
  1321. user-select: none !important;
  1322. max-width: 1px !important;
  1323. max-height: 1px !important;
  1324. overflow: hidden !important;
  1325. visibility: collapse !important;
  1326. display: none !important;
  1327. }
  1328.  
  1329. yt-live-chat-ticker-dummy777-item-renderer #container {
  1330. background: inherit;
  1331. }
  1332.  
  1333.  
  1334. ${cssText8_fonts_pre_render}
  1335.  
  1336. ${cssText9_no_backdrop_filter_when_menu_shown}
  1337.  
  1338. @supports (contain: layout paint style) {
  1339.  
  1340. ${cssText5}
  1341.  
  1342. }
  1343.  
  1344. @supports (color: var(--general)) {
  1345.  
  1346. html {
  1347. --yt-live-chat-item-list-renderer-padding: 0px 0px;
  1348. }
  1349.  
  1350. ${cssText3_smooth_transform_position}
  1351.  
  1352. ${cssText7c_will_change_unset}
  1353.  
  1354. ${cssText7b_content_visibility_unset}
  1355.  
  1356. yt-live-chat-item-list-renderer:not([allow-scroll]) #item-scroller.yt-live-chat-item-list-renderer {
  1357. overflow-y: scroll;
  1358. padding-right: 0;
  1359. }
  1360.  
  1361. ${cssText4_smooth_transform_forced_props}
  1362.  
  1363. yt-icon[icon="down_arrow"] > *, yt-icon-button#show-more > * {
  1364. pointer-events: none !important;
  1365. }
  1366.  
  1367. #continuations, #continuations * {
  1368. contain: strict;
  1369. position: fixed;
  1370. top: 2px;
  1371. height: 1px;
  1372. width: 2px;
  1373. height: 1px;
  1374. visibility: collapse;
  1375. }
  1376.  
  1377. ${cssText6b_show_more_button}
  1378.  
  1379. ${cssText6d_input_panel_border}
  1380.  
  1381. ${cssText6c_input_panel_overflow}
  1382.  
  1383. }
  1384.  
  1385.  
  1386. @supports (overflow-anchor: auto) {
  1387.  
  1388. .no-anchor * {
  1389. overflow-anchor: none;
  1390. }
  1391. .no-anchor > item-anchor {
  1392. overflow-anchor: auto;
  1393. }
  1394. #item-scroller.style-scope.yt-live-chat-item-list-renderer[class] {
  1395. overflow-anchor: initial !important; /* whenever ENABLE_OVERFLOW_ANCHOR or not */
  1396. }
  1397. }
  1398.  
  1399. item-anchor {
  1400.  
  1401. height: 1px;
  1402. width: 100%;
  1403. transform: scaleY(0.00001);
  1404. transform-origin:0 0;
  1405. contain: strict;
  1406. opacity:0;
  1407. display:flex;
  1408. position:relative;
  1409. flex-shrink:0;
  1410. flex-grow:0;
  1411. margin-bottom:0;
  1412. overflow:hidden;
  1413. box-sizing:border-box;
  1414. visibility: visible;
  1415. content-visibility: visible;
  1416. contain-intrinsic-size: auto 1px;
  1417. pointer-events:none !important;
  1418.  
  1419. }
  1420.  
  1421. html item-anchor {
  1422.  
  1423. height: 1px;
  1424. width: 1px;
  1425. top: auto;
  1426. left: auto;
  1427. right: auto;
  1428. bottom: auto;
  1429. transform: translateY(-1px);
  1430. position: absolute;
  1431. z-index: -1;
  1432.  
  1433. }
  1434.  
  1435. @supports (color: var(--pre-rendering)) {
  1436.  
  1437. @keyframes dontRenderAnimation {
  1438. 0% {
  1439. background-position-x: 3px;
  1440. }
  1441. 100% {
  1442. background-position-x: 4px;
  1443. }
  1444. }
  1445.  
  1446. .dont-render[class] {
  1447. /* visibility: collapse !important; */
  1448. /* visibility: collapse will make innerText become "" which conflicts with BetterStreamChat; see https://greasyfork.org/scripts/469878/discussions/197267 */
  1449.  
  1450. transform: scale(0.01) !important;
  1451. transform: scale(0.00001) !important;
  1452. transform: scale(0.0000001) !important;
  1453. transform-origin: 0 0 !important;
  1454. z-index: -1 !important;
  1455. contain: strict !important;
  1456. box-sizing: border-box !important;
  1457.  
  1458. height: 1px !important;
  1459. height: 0.1px !important;
  1460. height: 0.01px !important;
  1461. height: 0.0001px !important;
  1462. height: 0.000001px !important;
  1463.  
  1464. animation: dontRenderAnimation 1ms linear 80ms 1 normal forwards !important;
  1465.  
  1466. pointer-events: none !important;
  1467. user-select: none !important;
  1468.  
  1469. }
  1470.  
  1471. #sk35z {
  1472. display: block !important;
  1473.  
  1474. visibility: collapse !important;
  1475.  
  1476. transform: scale(0.01) !important;
  1477. transform: scale(0.00001) !important;
  1478. transform: scale(0.0000001) !important;
  1479. transform-origin: 0 0 !important;
  1480. z-index: -1 !important;
  1481. contain: strict !important;
  1482. box-sizing: border-box !important;
  1483.  
  1484. height: 1px !important;
  1485. height: 0.1px !important;
  1486. height: 0.01px !important;
  1487. height: 0.0001px !important;
  1488. height: 0.000001px !important;
  1489.  
  1490. position: absolute !important;
  1491. top: -1000px !important;
  1492. left: -1000px !important;
  1493.  
  1494. }
  1495.  
  1496. }
  1497.  
  1498. [rNgzQ] {
  1499. opacity: 0 !important;
  1500. pointer-events: none !important;
  1501. }
  1502.  
  1503.  
  1504. ${cssText10_show_more_blinker}
  1505.  
  1506. ${cssText11_entire_message_clickable}
  1507.  
  1508. ${cssText12_nowrap_tooltip}
  1509.  
  1510. ${cssText13_no_text_select_when_menu_visible}
  1511.  
  1512. ${cssText14_NO_FILTER_DROPDOWN_BORDER}
  1513.  
  1514. ${cssText15_FIX_ANIMATION_TICKER_TEXT_POSITION}
  1515.  
  1516. ${cssText16_FIX_AUTHOR_CHIP_BADGE_POSITION}
  1517.  
  1518. ${cssText17_FIX_overwidth_banner_message}
  1519.  
  1520. ${cssText18_REACTION_ANIMATION_PANEL_CSS_FIX}
  1521.  
  1522. ${cssText19_FOR_ADVANCED_TICKING}
  1523.  
  1524. ${cssText20_TICKER_SIZING}
  1525.  
  1526. `;
  1527.  
  1528. const win = typeof unsafeWindow !== 'undefined' ? unsafeWindow : (this instanceof Window ? this : window);
  1529.  
  1530. // Create a unique key for the script and check if it is already running
  1531. const hkey_script = 'mchbwnoasqph';
  1532. if (win[hkey_script]) throw new Error('Duplicated Userscript Calling'); // avoid duplicated scripting
  1533. win[hkey_script] = true;
  1534.  
  1535. const setTimeoutX0 = setTimeout;
  1536. const clearTimeoutX0 = clearTimeout;
  1537. const setIntervalX0 = setInterval;
  1538. const clearIntervalX0 = clearInterval;
  1539.  
  1540. const __shady_native_appendChild = HTMLElement_.prototype.__shady_native_appendChild || HTMLElement_.prototype.appendChild;
  1541. const __shady_native_removeChild = HTMLElement_.prototype.__shady_native_removeChild || HTMLElement_.prototype.removeChild;
  1542.  
  1543. const isEmptyObject = (obj) => {
  1544. for (const key in obj) {
  1545. if (obj.hasOwnProperty(key)) return false;
  1546. }
  1547. return true;
  1548. }
  1549.  
  1550. const firstObjectKey = (obj) => {
  1551. for (const key in obj) {
  1552. if (obj.hasOwnProperty(key) && typeof obj[key] === 'object') return key;
  1553. }
  1554. return null;
  1555. }
  1556.  
  1557.  
  1558. class LimitedSizeSet extends Set {
  1559. constructor(n) {
  1560. super();
  1561. this.limit = n;
  1562. }
  1563.  
  1564. add(key) {
  1565. if (!super.has(key)) {
  1566. super.add(key);
  1567. let n = super.size - this.limit;
  1568. if (n > 0) {
  1569. const iterator = super.values();
  1570. do {
  1571. const firstKey = iterator.next().value; // Get the first (oldest) key
  1572. super.delete(firstKey); // Delete the oldest key
  1573. } while (--n > 0)
  1574. }
  1575. }
  1576. }
  1577.  
  1578. removeAdd(key) {
  1579. super.delete(key);
  1580. this.add(key);
  1581. }
  1582.  
  1583. }
  1584.  
  1585.  
  1586. function deepCopy(obj, skipKeys) {
  1587. skipKeys = skipKeys || [];
  1588. if (!obj || typeof obj !== 'object') return obj;
  1589. if (Array.isArray(obj)) {
  1590. return obj.map(item => deepCopy(item, skipKeys));
  1591. }
  1592. const copy = {};
  1593. for (let key in obj) {
  1594. if (!skipKeys.includes(key)) {
  1595. copy[key] = deepCopy(obj[key], skipKeys);
  1596. }
  1597. }
  1598. return copy;
  1599. }
  1600.  
  1601. class Mutex {
  1602.  
  1603. constructor() {
  1604. this.p = Promise.resolve()
  1605. }
  1606.  
  1607. /**
  1608. * @param {(lockResolve: () => void)} f
  1609. */
  1610. lockWith(f) {
  1611. this.p = this.p.then(() => new Promise(f).catch(console.warn))
  1612. }
  1613.  
  1614. }
  1615.  
  1616. const PromiseExternal = ((resolve_, reject_) => {
  1617. const h = (resolve, reject) => { resolve_ = resolve; reject_ = reject };
  1618. return class PromiseExternal extends Promise {
  1619. constructor(cb = h) {
  1620. super(cb);
  1621. if (cb === h) {
  1622. /** @type {(value: any) => void} */
  1623. this.resolve = resolve_;
  1624. /** @type {(reason?: any) => void} */
  1625. this.reject = reject_;
  1626. }
  1627. }
  1628. };
  1629. })();
  1630.  
  1631. let ttpHTML = (s) => {
  1632. ttpHTML = s => s;
  1633. if (typeof trustedTypes !== 'undefined' && trustedTypes.defaultPolicy === null) {
  1634. let s = s => s;
  1635. trustedTypes.createPolicy('default', { createHTML: s, createScriptURL: s, createScript: s });
  1636. }
  1637. return s;
  1638. }
  1639.  
  1640. // const nextBrowserTick_ = nextBrowserTick;
  1641. // const nextBrowserTick_ = (f) => {
  1642. // typeof nextBrowserTick === 'function' ? nextBrowserTick(f) : setTimeout(f, Number.MIN_VALUE);
  1643. // };
  1644.  
  1645.  
  1646. // const { accurateTiming, isAccurateTimingUsable } = (() => {
  1647. // let audioCtx_ = null;
  1648. // let sampleRate = 0;
  1649. // const isAccurateTimingUsable = () => sampleRate > 0;
  1650. // const kill = () => {
  1651. // sampleRate = audioCtx_.currentTime;
  1652. // document.removeEventListener('pointerdown', listener, { capture: true, passive: true });
  1653. // document.removeEventListener('keydown', listener, { capture: true, passive: true });
  1654. // };
  1655. // const listener = (e) => {
  1656. // if (e.isTrusted === true) {
  1657. // if (!audioCtx_) {
  1658. // audioCtx_ = new (window.AudioContext || window.webkitAudioContext)();
  1659. // }
  1660. // if (audioCtx_.state === 'suspended') {
  1661. // const p = audioCtx_.resume();
  1662. // if (p && typeof p.then === 'function') p.then(kill);
  1663. // } else if (audioCtx_.state === 'running') {
  1664. // kill();
  1665. // }
  1666. // }
  1667. // };
  1668. // document.addEventListener('pointerdown', listener, { capture: true, passive: true });
  1669. // document.addEventListener('keydown', listener, { capture: true, passive: true });
  1670. // const fnSym = Symbol()
  1671. // const commonOscClean = (osc) => {
  1672. // osc[fnSym] = osc.onended = null;
  1673. // }
  1674. // const commonOscOnEnded = function () {
  1675. // this[fnSym]()
  1676. // Promise.resolve(this).then(commonOscClean)
  1677. // }
  1678. // let buffer_;
  1679. // const accurateTiming = (fn, delay) => {
  1680. // if (!sampleRate) return false;
  1681. // const audioCtx = audioCtx_;
  1682. // const ct = audioCtx.currentTime;
  1683.  
  1684. // if (!(delay >= 0)) delay = 0;
  1685. // const stopTime = ct + delay;
  1686. // let startTime = ct + delay - (1 / sampleRate);
  1687. // if (startTime === stopTime) startTime -= 1;
  1688. // if (startTime < 0) startTime = 0;
  1689.  
  1690. // if (!buffer_) {
  1691. // buffer_ = audioCtx.createBuffer(1, 1, sampleRate);
  1692. // // const data = buffer.getChannelData(0)
  1693. // // data[0] = 1e-20 // tiny pulse – not silent!
  1694. // }
  1695.  
  1696. // const buffer = buffer_;
  1697. // const source = audioCtx.createBufferSource()
  1698. // source.buffer = buffer
  1699. // source.connect(audioCtx.destination) // or silent gain node
  1700.  
  1701. // source[fnSym] = fn
  1702. // source.onended = commonOscOnEnded
  1703. // source.start(startTime) // schedule start
  1704.  
  1705. // return true;
  1706. // }
  1707. // return { accurateTiming, isAccurateTimingUsable }
  1708. // })();
  1709.  
  1710. const toUniqueArr = (arr) => {
  1711. const s = new Set(arr);
  1712. const r = [...s];
  1713. s.clear();
  1714. return r;
  1715. }
  1716.  
  1717. let qWidthAdjustable = null;
  1718.  
  1719. /** @type {typeof PromiseExternal.prototype | null} */
  1720. let relayPromise = null;
  1721.  
  1722.  
  1723. /** @type {typeof PromiseExternal.prototype | null} */
  1724. let onPlayStateChangePromise = null;
  1725.  
  1726.  
  1727. const reuseId = `${Math.floor(Math.random() * 314159265359 + 314159265359).toString(36)}`;
  1728.  
  1729. const reuseStore = new Map();
  1730. reuseStore.set = reuseStore.setOriginal || reuseStore.set;
  1731.  
  1732. let onPageContainer = null;
  1733.  
  1734. const customCreateComponent = (component, data, bool)=>{
  1735.  
  1736. const componentTag = typeof component === 'string' ? component : typeof (component||0).component === 'string' ? (component||0).component : '';
  1737. if(componentTag){
  1738.  
  1739. if(REUSE_TICKER && data.id && data.fullDurationSec){
  1740. // bool (param c) is true by default; just force it to reuse no matter true or false
  1741.  
  1742. if (!bool) {
  1743. // show a warning if it is false.
  1744. console.warn('[yt-chat] REUSE_TICKER: reuse bool is false');
  1745. }
  1746.  
  1747. const record = reuseStore.get(`<${componentTag}>${data.id}:${data.fullDurationSec}`);
  1748.  
  1749. const cnt = kRef(record);
  1750.  
  1751.  
  1752. if(cnt && cnt.isAttached === false){
  1753.  
  1754. const hostElement = cnt.hostElement;
  1755.  
  1756. if(hostElement instanceof HTMLElement_ && hostElement.isConnected === false && hostElement.parentNode === null && hostElement.getAttribute('__reuseid__')===reuseId ){
  1757.  
  1758. // console.log(952, cnt.hostElement.parentNode)
  1759. // debugger;
  1760. if (hostElement.hasAttribute('__nogc__')) {
  1761.  
  1762. Promise.resolve(hostElement).then((hostElement) => {
  1763. // microtask to provide some time for DOM attachment.
  1764. hostElement.isConnected && hostElement.removeAttribute('__nogc__');
  1765. });
  1766.  
  1767. }
  1768.  
  1769. // ------- follow rm3 -------
  1770.  
  1771. // a.prototype._initializeProtoProperties = function(c) {
  1772. // this.__data = Object.create(c);
  1773. // this.__dataPending = Object.create(c);
  1774. // this.__dataOld = {}
  1775. // }
  1776. // a.prototype._initializeProperties = function() {
  1777. // this.__dataProto && (this._initializeProtoProperties(this.__dataProto),
  1778. // this.__dataProto = null);
  1779. // b.prototype._initializeProperties.call(this)
  1780. // }
  1781. // ;
  1782.  
  1783. if(!cnt.__dataInvalid && cnt.__dataEnabled && cnt.__dataReady ){
  1784.  
  1785. // console.log(12883);
  1786.  
  1787.  
  1788. if (!onPageContainer) {
  1789. let p = document.createElement('noscript');
  1790. p.style.all = 'unset';
  1791. document.body.prepend(p);
  1792. onPageContainer = p;
  1793. }
  1794.  
  1795. onPageContainer.appendChild(hostElement); // to fix some issues for the rendered elements
  1796.  
  1797. cnt.__dataInvalid = false;
  1798. cnt.__dataEnabled = true;
  1799. cnt.__dataReady = true;
  1800. // cnt._initializeProtoProperties(cnt.data)
  1801.  
  1802. // window.meaa = cnt.$.container;
  1803. if (cnt.__data) cnt.__data = Object.assign({}, cnt.__data);
  1804. cnt.__dataPending = {};
  1805. cnt.__dataOld = {}
  1806.  
  1807. try{
  1808. cnt.markDirty();
  1809. }catch(e){}
  1810. try{
  1811. cnt.markDirtyVisibilityObserver();
  1812. }catch(e){}
  1813. try{
  1814. cnt.wasPrescan = cnt.wasVisible = !1
  1815. }catch(e){}
  1816. // try{
  1817. // cnt._setPendingProperty('data', Object.assign({}, cntData), !0);
  1818. // }catch(e){}
  1819. // // cnt.__dataInvalid = false;
  1820. // // cnt._enableProperties();
  1821.  
  1822. // try {
  1823. // cnt._flushProperties();
  1824. // } catch (e) { }
  1825. // cnt.ready();
  1826.  
  1827. return hostElement;
  1828.  
  1829. }
  1830.  
  1831.  
  1832. // console.log(12323)
  1833.  
  1834. // setTimeoutX0(()=>{
  1835. // console.log(window.meaa.parentNode)
  1836. // }, 1000)
  1837.  
  1838.  
  1839. // ------------ commented ------------
  1840. // cnt.__dataInvalid = false;
  1841. // cnt.__dataEnabled = false;
  1842. // if (cnt.__dataPending && typeof cnt.__dataPending === 'object') cnt.__dataPending = null;
  1843. // if (cnt.__dataOld && typeof cnt.__dataOld === 'object') cnt.__dataOld = null;
  1844. // if (cnt.__dataCounter && typeof cnt.__dataCounter === 'number') cnt.__dataCounter = 0;
  1845. // if ('__dataClientsInitialized' in cnt || '__dataClientsReady' in cnt) {
  1846. // cnt.__dataClientsReady = !1;
  1847. // cnt.__dataLinkedPaths = cnt.__dataToNotify = cnt.__dataPendingClients = null;
  1848. // cnt.__dataHasPaths = !1;
  1849. // cnt.__dataCompoundStorage = null; // cnt.__dataCompoundStorage = cnt.__dataCompoundStorage || null;
  1850. // cnt.__dataHost = null; // cnt.__dataHost = cnt.__dataHost || null;
  1851. // if (!cnt.__dataTemp) cnt.__dataTemp = {}; // cnt.__dataTemp = {};
  1852. // cnt.__dataClientsInitialized = !1;
  1853. // }
  1854. // try{
  1855. // cnt._flushProperties();
  1856. // }catch(e){
  1857. // console.warn(e)
  1858. // }
  1859. // for (const elm of cnt.hostElement.getElementsByTagName('*')) {
  1860. // if (elm.is) {
  1861. // const cnt = insp(elm);
  1862. // cnt.__dataInvalid = false;
  1863. // cnt.__dataEnabled = false;
  1864. // if (cnt.__dataPending && typeof cnt.__dataPending === 'object') cnt.__dataPending = null;
  1865. // if (cnt.__dataOld && typeof cnt.__dataOld === 'object') cnt.__dataOld = null;
  1866. // if (cnt.__dataCounter && typeof cnt.__dataCounter === 'number') cnt.__dataCounter = 0;
  1867. // if ('__dataClientsInitialized' in cnt || '__dataClientsReady' in cnt) {
  1868. // cnt.__dataClientsReady = !1;
  1869. // cnt.__dataLinkedPaths = cnt.__dataToNotify = cnt.__dataPendingClients = null;
  1870. // cnt.__dataHasPaths = !1;
  1871. // cnt.__dataCompoundStorage = null; // cnt.__dataCompoundStorage = cnt.__dataCompoundStorage || null;
  1872. // cnt.__dataHost = null; // cnt.__dataHost = cnt.__dataHost || null;
  1873. // if (!cnt.__dataTemp) cnt.__dataTemp = {}; // cnt.__dataTemp = {};
  1874. // cnt.__dataClientsInitialized = !1;
  1875. // }
  1876. // try {
  1877. // cnt._flushProperties();
  1878. // } catch (e) {
  1879. // console.warn(e)
  1880. // }
  1881. // if (elm.nodeName === 'YT-ICON') {
  1882. // // console.log(2133, JSON.stringify( cnt.__data))
  1883. // const qq = Object.assign({}, cnt.__data)
  1884. // console.log(1232466)
  1885. // const _qww = cnt;
  1886. // cnt.__data = new Proxy(Object.assign({}, qq), {
  1887. // get(target, p) {
  1888. // console.log(12838, p)
  1889. // if (p === 'icon') {
  1890. // window.wmk = _qww.hostElement;
  1891. // // debugger;
  1892. // }
  1893. // return target[p]
  1894. // },
  1895. // set(target, p, v) {
  1896. // console.log(12839, p)
  1897. // target[p] = v;
  1898. // if (p === 'icon') debugger;
  1899. // return true;
  1900. // }
  1901. // });
  1902. // Promise.resolve(cnt).then((cnt) => {
  1903. // cnt.__data = Object.assign({}, qq);
  1904. // });
  1905. // }
  1906. // // let q = elm.nextSibling;
  1907. // // let h = elm.parentNode;
  1908. // // elm.remove();
  1909. // // h.insertBefore(elm, q);
  1910. // // console.log(2233, elm)
  1911. // }
  1912. // }
  1913. // ------------ commented ------------
  1914.  
  1915. // ------- follow rm3 -------
  1916.  
  1917. // console.log('[yt-chat] reuse')
  1918.  
  1919.  
  1920.  
  1921. }
  1922.  
  1923. }
  1924.  
  1925. }
  1926.  
  1927. }
  1928. DEBUG_customCreateComponent && console.log(component, data, bool);
  1929. /*
  1930.  
  1931. const cntData = this.data;
  1932. reuseStore.set(`${cntData.id}:${cntData.fullDurationSec}`, mWeakRef(this));
  1933. */
  1934.  
  1935. }
  1936.  
  1937. const valAssign = (elm, attr, val) => {
  1938. if (typeof val === 'number') val = val.toFixed(3);
  1939. const currentVal = elm.style.getPropertyValue(attr);
  1940. if (currentVal === '' || !(Math.abs(currentVal - val) < 1e-5)) {
  1941. elm.style.setProperty(attr, val);
  1942. return true;
  1943. }
  1944. return false;
  1945. };
  1946.  
  1947. const insp = o => o ? (o.polymerController || o.inst || o || 0) : (o || 0);
  1948. const indr = o => insp(o).$ || o.$ || 0;
  1949.  
  1950.  
  1951. const getAttributes = (node) => {
  1952. const attrs = node.attributes;
  1953. const res = {};
  1954. for (const { name, value } of attrs) {
  1955. res[name] = value;
  1956. }
  1957. res['"'] = attrs.length;
  1958. // const res = new Array(attrs.length);
  1959. // for (let i = 0; i < res.length; i++) {
  1960. // const { name, value } = attrs[i];
  1961. // res[i] = { name, value };
  1962. // }
  1963. return res;
  1964. };
  1965.  
  1966. // const __refreshData938o__ = {};
  1967. // const __refreshData938__ = function (prop, opt) {
  1968. // const d = this[prop];
  1969. // if (d) {
  1970. // this._setPendingProperty(prop, __refreshData938o__, opt);
  1971. // this._setPendingProperty(prop, d, opt);
  1972. // this._invalidateProperties();
  1973. // }
  1974. // };
  1975.  
  1976. // const __refreshData933__ = function (prop, opt) {
  1977. // const d = this[prop];
  1978. // if (d) {
  1979. // this.signalProxy.setWithPath([prop], d);
  1980. // }
  1981. // }
  1982.  
  1983. // const setupRefreshData930 = (cnt) => {
  1984. // if (cnt.__refreshData930__ !== undefined) return;
  1985. // const cProto = Reflect.getPrototypeOf(cnt);
  1986. // let r = null;
  1987. // let flag = 0;
  1988. // if (typeof cnt._setPendingProperty === 'function' && typeof cnt._invalidateProperties === 'function' && cnt._setPendingProperty.length === 3 && cnt._invalidateProperties.length === 0) {
  1989. // flag |= 1;
  1990. // }
  1991. // if (typeof cnt.signalProxy !== "undefined") {
  1992. // flag |= 2;
  1993. // }
  1994. // if (typeof (cnt.signalProxy || 0).setWithPath === 'function' && cnt.signalProxy.setWithPath.length === 2) {
  1995. // flag |= 4;
  1996. // }
  1997. // if (r === 1) r = __refreshData938__;
  1998. // // else if (r === 6) r = __refreshData933__;
  1999. // cProto.__refreshData930__ = r;
  2000. // // ytd-comments-header-renderer : no _invalidateProperties (cnt.signalProxy.setWithPath)
  2001. // }
  2002.  
  2003. // const __refreshProps938__ = function () {
  2004. // const __data = this.__data;
  2005. // if (__data) {
  2006. // for (const key in __data) {
  2007. // const v = __data[key];
  2008. // if (typeof v === 'boolean') {
  2009. // this._setPendingProperty(key, !v) && this._setPendingProperty(key, v);
  2010. // } else if (typeof v === 'string') {
  2011. // this._setPendingProperty(key, `!${v}`) && this._setPendingProperty(key, `${v}`);
  2012. // } else if (typeof v === 'number') {
  2013. // this._setPendingProperty(key, v + 1) && this._setPendingProperty(key, v);
  2014. // }
  2015. // }
  2016. // }
  2017. // }
  2018.  
  2019. // const setupRefreshProps930 = (cnt) => {
  2020. // if (cnt.__refreshProps930__ !== undefined) return;
  2021. // const cProto = Reflect.getPrototypeOf(cnt);
  2022. // let r = null;
  2023. // let flag = 0;
  2024. // if (typeof cnt._setPendingProperty === 'function' && typeof cnt._invalidateProperties === 'function' && cnt._setPendingProperty.length === 3 && cnt._invalidateProperties.length === 0) {
  2025. // flag |= 1;
  2026. // }
  2027. // if (typeof cnt.signalProxy !== "undefined") {
  2028. // flag |= 2;
  2029. // }
  2030. // if (typeof (cnt.signalProxy || 0).setWithPath === 'function' && cnt.signalProxy.setWithPath.length === 2) {
  2031. // flag |= 4;
  2032. // }
  2033. // if (r === 1) r = __refreshProps938__;
  2034. // cProto.__refreshProps930__ = r;
  2035. // // ytd-comments-header-renderer : no _invalidateProperties (cnt.signalProxy.setWithPath)
  2036. // }
  2037.  
  2038. // const refreshChildrenYtIcons = (node) => {
  2039. // let goNext = false;
  2040. // for (const iconElm of node.getElementsByTagName('yt-icon')) {
  2041. // try {
  2042. // const cnt = insp(iconElm);
  2043. // setupRefreshProps930(cnt);
  2044. // if (cnt.__refreshProps930__) {
  2045. // cnt.__refreshProps930__();
  2046. // goNext = true;
  2047. // }
  2048. // // cnt.removeIconShape(); // detach iconShapeDataSignal?
  2049. // // cnt._setPendingProperty('isAttached', false);
  2050. // } catch (e) { }
  2051. // if (!goNext) break;
  2052. // }
  2053. // }
  2054.  
  2055.  
  2056. // const imageFetchCache = new Set();
  2057. // const imageFetch = function (imageLink) {
  2058. // return new Promise(resolve => {
  2059. // let img = null;
  2060. // for (const cacheWR of imageFetchCache) {
  2061. // let p = kRef(cacheWR);
  2062. // if (!p) {
  2063. // imageFetchCache.delete(cacheWR);
  2064. // } else if (img.busy588 === false) {
  2065. // img = p;
  2066. // break;
  2067. // }
  2068. // }
  2069. // if (!img) {
  2070. // img = new Image_();
  2071. // imageFetchCache.add(mWeakRef(img));
  2072. // }
  2073. // img.busy588 = true;
  2074.  
  2075. // window.mkek = imageFetchCache.size;
  2076. // let f = () => {
  2077. // resolve && resolve();
  2078. // resolve = null;
  2079. // img.onload = null;
  2080. // img.onerror = null;
  2081. // img.busy588 = false;
  2082. // img = null;
  2083. // }
  2084. // img.onload = f;
  2085. // img.onerror = f;
  2086. // img.src = imageLink;
  2087. // f = null;
  2088. // imageLink = null;
  2089. // });
  2090. // };
  2091.  
  2092.  
  2093. const autoTimerFn = (() => {
  2094.  
  2095. let p1 = null;
  2096. let p2 = null;
  2097. let p3 = null;
  2098. setInterval(() => {
  2099. if (p1) p1.resolve();
  2100. p1 = p2;
  2101. p2 = p3;
  2102. p3 = null;
  2103. }, 345.00123);
  2104.  
  2105. return () => {
  2106. const p = (p3 || (p3 = new PromiseExternal()));
  2107. return p;
  2108. };
  2109.  
  2110. })();
  2111.  
  2112. const __mockChildren__ = { get length() { return 0 } };
  2113. const mockCommentElement = (x) => {
  2114. // for flow chat
  2115. if (x instanceof Node && x.nodeType !== 1 && !x.children) {
  2116. x.children = __mockChildren__;
  2117. }
  2118. return x;
  2119. }
  2120.  
  2121. const wme = mockCommentElement(document.createComment('1'));
  2122. let wmp = new PromiseExternal();
  2123. const wmo = new MutationObserver(() => {
  2124. wmp.resolve();
  2125. wmp = new PromiseExternal();
  2126. });
  2127. wmo.observe(wme, { characterData: true });
  2128.  
  2129.  
  2130. let playEventsStack = Promise.resolve();
  2131.  
  2132.  
  2133. let playerProgressChangedArg1 = null;
  2134. let playerProgressChangedArg2 = null;
  2135. let playerProgressChangedArg3 = null;
  2136.  
  2137. let dntElementWeak = null;
  2138.  
  2139.  
  2140. let timestampUnderLiveMode = false;
  2141.  
  2142. const updateTickerCurrentTime = () => {
  2143.  
  2144. if (resistanceUpdateDebugMode) {
  2145. console.log('updateTickerCurrentTime')
  2146.  
  2147. if (!dntElementWeak || !kRef(dntElementWeak)) dntElementWeak = mWeakRef(document.querySelector('yt-live-chat-ticker-renderer'));
  2148. timestampUnderLiveMode = true;
  2149. }
  2150.  
  2151. const dntElement = kRef(dntElementWeak);
  2152. const v = timestampUnderLiveMode ? (Date.now() / 1000 - timeOriginDT / 1000) : playerProgressChangedArg1;
  2153. if (dntElement instanceof HTMLElement_ && v >= 0) {
  2154. valAssign(dntElement, '--ticker-current-time', v);
  2155. }
  2156. }
  2157.  
  2158. // ================== FOR USE_ADVANCED_TICKING ================
  2159.  
  2160. const timeOriginDT = +new Date(Math.floor(performance.timeOrigin)) - 1000;
  2161. let startResistanceUpdaterStarted = false;
  2162.  
  2163. const RESISTANCE_UPDATE_OPT = 3;
  2164. let resistanceUpdateLast = 0;
  2165. let resistanceUpdateBusy = false;
  2166. const resistanceUpdateDebugMode = false;
  2167. const allBackgroundOverLays = document.getElementsByTagName('ticker-bg-overlay');
  2168. // const rgFlag = {};
  2169. const resistanceUpdateFn = (b) => {
  2170. if (!resistanceUpdateDebugMode && allBackgroundOverLays.length === 0) return;
  2171. resistanceUpdateBusy = false;
  2172. const t = Date.now();
  2173. const d = t - resistanceUpdateLast;
  2174. if (d > 375) {
  2175. resistanceUpdateLast = t;
  2176. updateTickerCurrentTime();
  2177. }
  2178. }
  2179. const resistanceUpdateFn_ = (forced = false) => {
  2180. if (forced === true || timestampUnderLiveMode) {
  2181. if (!resistanceUpdateBusy) {
  2182. resistanceUpdateBusy = true;
  2183. Promise.resolve().then(resistanceUpdateFn);
  2184. }
  2185. }
  2186. }
  2187. const startResistanceUpdater = () => {
  2188.  
  2189. if (startResistanceUpdaterStarted) return;
  2190. startResistanceUpdaterStarted = true;
  2191.  
  2192. if (RESISTANCE_UPDATE_OPT & 1)
  2193. document.addEventListener('yt-action', () => {
  2194. resistanceUpdateFn_(true);
  2195. }, true)
  2196.  
  2197. resistanceUpdateFn_(true);
  2198. setIntervalX0(resistanceUpdateFn_, 400);
  2199. }
  2200.  
  2201. if(resistanceUpdateDebugMode) startResistanceUpdater();
  2202.  
  2203.  
  2204. function dr(s) {
  2205. // reserved for future use
  2206. return s;
  2207. // return window.deWeakJS ? window.deWeakJS(s) : s;
  2208. }
  2209.  
  2210.  
  2211. const getProto = (element) => {
  2212. if (element) {
  2213. const cnt = insp(element);
  2214. return cnt.constructor.prototype || null;
  2215. }
  2216. return null;
  2217. }
  2218.  
  2219.  
  2220.  
  2221. const logFn = (key, f) => {
  2222. return Function.prototype.bind.call(console.log, console, `%c ${key}`, 'background: #222; color: #bada55', f);
  2223. }
  2224.  
  2225.  
  2226.  
  2227. const assertor = (f) => f() || (console.assert(false, `${f}`), false);
  2228.  
  2229. const fnIntegrity = (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. const px2cm = (px) => px * window.devicePixelRatio * 0.026458333;
  2281. const px2mm = (px) => px * window.devicePixelRatio * 0.26458333;
  2282.  
  2283. // let createElement_fountain_model_fn = null;
  2284. // let createElement_fountain_model_enabled = null;
  2285.  
  2286. // ; (USE_RM_ON_FOUNTAIN_MODEL) && (()=>{
  2287. // document.createElement4719 = document.createElement;
  2288. // document.createElement = function (a) {
  2289. // if (createElement_fountain_model_enabled) {
  2290. // const r = createElement_fountain_model_fn(a);
  2291. // if (r) return r;
  2292. // }
  2293. // return document.createElement4719(a);
  2294. // }
  2295. // })();
  2296.  
  2297. ; (ENABLE_FLAGS_MAINTAIN_STABLE_LIST || ENABLE_FLAGS_REUSE_COMPONENTS || DISABLE_FLAGS_SHADYDOM_FREE) && (() => {
  2298.  
  2299. const _config_ = () => {
  2300. try {
  2301. return ytcfg.data_;
  2302. } catch (e) { }
  2303. return null;
  2304. };
  2305.  
  2306. const flagsFn = (EXPERIMENT_FLAGS) => {
  2307.  
  2308. // console.log(700)
  2309.  
  2310. if (!EXPERIMENT_FLAGS) return;
  2311.  
  2312. if (ENABLE_FLAGS_MAINTAIN_STABLE_LIST) {
  2313. if (USE_MAINTAIN_STABLE_LIST_ONLY_WHEN_KS_FLAG_IS_SET ? EXPERIMENT_FLAGS.kevlar_should_maintain_stable_list === true : true) {
  2314. // EXPERIMENT_FLAGS.kevlar_tuner_should_test_maintain_stable_list = true; // timestamp toggle issue
  2315. EXPERIMENT_FLAGS.kevlar_should_maintain_stable_list = true;
  2316. // console.log(701)
  2317. }
  2318. }
  2319.  
  2320. if (ENABLE_FLAGS_REUSE_COMPONENTS) {
  2321. EXPERIMENT_FLAGS.kevlar_tuner_should_test_reuse_components = true;
  2322. EXPERIMENT_FLAGS.kevlar_tuner_should_reuse_components = true;
  2323. // console.log(702);
  2324. }
  2325.  
  2326. if (DISABLE_FLAGS_SHADYDOM_FREE) {
  2327. EXPERIMENT_FLAGS.enable_shadydom_free_scoped_node_methods = false;
  2328. EXPERIMENT_FLAGS.enable_shadydom_free_scoped_query_methods = false;
  2329. EXPERIMENT_FLAGS.enable_shadydom_free_scoped_readonly_properties_batch_one = false;
  2330. EXPERIMENT_FLAGS.enable_shadydom_free_parent_node = false;
  2331. EXPERIMENT_FLAGS.enable_shadydom_free_children = false;
  2332. EXPERIMENT_FLAGS.enable_shadydom_free_last_child = false;
  2333. }
  2334.  
  2335. // EXPERIMENT_FLAGS.enable_button_behavior_reuse = false;
  2336.  
  2337. };
  2338.  
  2339. const uf = (config_) => {
  2340. config_ = config_ || _config_();
  2341. if (config_) {
  2342. const { EXPERIMENT_FLAGS, EXPERIMENTS_FORCED_FLAGS } = config_;
  2343. if (EXPERIMENT_FLAGS) {
  2344. flagsFn(EXPERIMENT_FLAGS);
  2345. if (EXPERIMENTS_FORCED_FLAGS) flagsFn(EXPERIMENTS_FORCED_FLAGS);
  2346. }
  2347. }
  2348. }
  2349.  
  2350. window._ytConfigHacks.add((config_) => {
  2351. uf(config_);
  2352. });
  2353.  
  2354. uf();
  2355.  
  2356. })();
  2357.  
  2358. if (DISABLE_Translation_By_Google) {
  2359.  
  2360. let mo = new MutationObserver(() => {
  2361.  
  2362. if (!mo) return;
  2363. let h = document.head;
  2364. if (!h) return;
  2365. mo.disconnect();
  2366. mo.takeRecords();
  2367. mo = null;
  2368.  
  2369. let meta = document.createElement('meta');
  2370. meta.setAttribute('name', 'google');
  2371. meta.setAttribute('content', 'notranslate');
  2372. h.appendChild(meta);
  2373.  
  2374.  
  2375. });
  2376. mo.observe(document, { subtree: true, childList: true });
  2377. }
  2378.  
  2379. console.assert(MAX_ITEMS_FOR_TOTAL_DISPLAY > 0)
  2380. // console.assert(MAX_ITEMS_FOR_TOTAL_DISPLAY > 0 && MAX_ITEMS_FOR_FULL_FLUSH > 0 && MAX_ITEMS_FOR_TOTAL_DISPLAY > MAX_ITEMS_FOR_FULL_FLUSH)
  2381.  
  2382. const isContainSupport = CSS.supports('contain', 'layout paint style');
  2383. if (!isContainSupport) {
  2384. console.warn("Your browser does not support css property 'contain'.\nPlease upgrade to the latest version.".trim());
  2385. }
  2386.  
  2387. const isOverflowAnchorSupport = CSS.supports('overflow-anchor', 'auto');
  2388. if (!isOverflowAnchorSupport) {
  2389. console.warn("Your browser does not support css property 'overflow-anchor'.\nPlease upgrade to the latest version.".trim());
  2390. }
  2391.  
  2392. const ENABLE_OVERFLOW_ANCHOR = ENABLE_OVERFLOW_ANCHOR_PREFERRED && isOverflowAnchorSupport && ENABLE_NO_SMOOTH_TRANSFORM && typeof ResizeObserver === 'function';
  2393. let WITH_SCROLL_ANCHOR = false;
  2394.  
  2395. const fxOperator = (proto, propertyName) => {
  2396. let propertyDescriptorGetter = null;
  2397. try {
  2398. propertyDescriptorGetter = Object.getOwnPropertyDescriptor(proto, propertyName).get;
  2399. } catch (e) { }
  2400. return typeof propertyDescriptorGetter === 'function' ? (e) => {
  2401. try {
  2402.  
  2403. return propertyDescriptorGetter.call(dr(e));
  2404. } catch (e) { }
  2405. return e[propertyName];
  2406. } : (e) => e[propertyName];
  2407. };
  2408.  
  2409. const nodeParent = fxOperator(Node.prototype, 'parentNode');
  2410. const nPrevElem = fxOperator(HTMLElement_.prototype, 'previousElementSibling');
  2411. const nNextElem = fxOperator(HTMLElement_.prototype, 'nextElementSibling');
  2412. const nLastElem = fxOperator(HTMLElement_.prototype, 'lastElementChild');
  2413.  
  2414. let groupCI = [];
  2415. let groupDI = 0;
  2416.  
  2417. const [console_] = [console];
  2418. const console1 = {
  2419. log(...args) {
  2420. if (!SHOW_DEVTOOL_DEBUG) return;
  2421. if (groupDI === 1) return grouppedConsoleLog(...args);
  2422. return console_.log(...args);
  2423. },
  2424. warn(...args) {
  2425. if (!SHOW_DEVTOOL_DEBUG) return;
  2426. if (groupDI === 1) return grouppedConsoleWarn(...args);
  2427. return console_.warn(...args);
  2428. },
  2429. debug(...args) {
  2430. if (!SHOW_DEVTOOL_DEBUG) return;
  2431. if (groupDI === 1) return grouppedConsoleDebug(...args);
  2432. return console_.debug(...args);
  2433. }
  2434. }
  2435. const grouppedConsoleLog = (...args) => {
  2436. if (DEBUG_LOG_HIDE_OK) {
  2437. for (const arg of args) {
  2438. if (typeof arg !== 'string') break;
  2439. if (arg.endsWith('OK')) return;
  2440. }
  2441. }
  2442. groupCI.push(['log', ...args]);
  2443. }
  2444. const grouppedConsoleWarn = (...args) => {
  2445. groupCI.push(['warn', ...args]);
  2446. }
  2447. const grouppedConsoleDebug = (...args) => {
  2448. groupCI.push(['debug', ...args]);
  2449. }
  2450. const groupCollapsed = (text1, text2) => {
  2451. if (!SHOW_DEVTOOL_DEBUG) return;
  2452. if (groupDI !== 0) console_.warn('groupDI in groupCollapsed fails', groupDI);
  2453. groupDI++;
  2454. groupCI.length = 0;
  2455.  
  2456. let w = 'groupCollapsed';
  2457. if (DEBUG_LOG_GROUP_EXPAND) w = 'group';
  2458. groupCI.push([w, `%c${text1}%c${text2}`,
  2459. "background-color: #010502; color: #6acafe; font-weight: 700; padding: 2px;",
  2460. "background-color: #010502; color: #6ad9fe; font-weight: 300; padding: 2px;"
  2461. ]);
  2462. }
  2463. const groupEnd = () => {
  2464. if (!SHOW_DEVTOOL_DEBUG) return;
  2465. groupDI--;
  2466. if (groupDI !== 0) console_.warn('groupDI in groupEnd fails', groupDI);
  2467. if (groupCI.length >= 0) {
  2468. let withContent = false;
  2469. for (const entry of groupCI) {
  2470. if (entry[0] === 'group' || entry[0] === 'groupCollapsed') continue;
  2471. if (entry[1] === '[Begin]' || entry[1] === '[End]') continue;
  2472. withContent = true;
  2473. break;
  2474. }
  2475. if (withContent) {
  2476. for (const entry of groupCI) {
  2477. const args = entry.slice(1);
  2478. let colorHighLight = '';
  2479. for (const arg of args) {
  2480. if (typeof arg !== 'string') {
  2481. colorHighLight = '';
  2482. break;
  2483. }
  2484. if (arg === 'OK' || arg === 'NG') {
  2485. colorHighLight = arg;
  2486. } else {
  2487. if (arg.endsWith(' OK')) colorHighLight = 'OK';
  2488. else if (arg.endsWith(' NG')) colorHighLight = 'NG';
  2489. }
  2490. }
  2491. let print = args;
  2492. if (colorHighLight) {
  2493. print = [args.map(e => `%c${e}`).join(' '), ...args.map(e => {
  2494. if (colorHighLight === 'OK' && e.includes(colorHighLight)) return "background-color:rgb(29, 29, 29); color:rgb(57, 215, 83); font-weight: 600;";
  2495. if (colorHighLight === 'NG' && e.includes(colorHighLight)) return "background-color:rgb(29, 29, 29); color:rgb(215, 133, 57); font-weight: 600;";
  2496. return "background-color:rgb(29, 29, 29); color:rgb(231, 231, 231); font-weight: 400;";
  2497. })];
  2498. }
  2499. console[entry[0]](...print);
  2500. }
  2501. console.groupEnd();
  2502. groupCI.length = 0;
  2503. }
  2504. }
  2505. }
  2506.  
  2507. // const microNow = () => performance.now() + (performance.timeOrigin || performance.timing.navigationStart);
  2508.  
  2509.  
  2510. const EVENT_KEY_ON_REGISTRY_READY = "ytI-ce-registry-created";
  2511. const onRegistryReady = (callback) => {
  2512. if (typeof customElements === 'undefined') {
  2513. if (!('__CE_registry' in document)) {
  2514. // https://github.com/webcomponents/polyfills/
  2515. Object.defineProperty(document, '__CE_registry', {
  2516. get() {
  2517. // return undefined
  2518. },
  2519. set(nv) {
  2520. if (typeof nv == 'object') {
  2521. delete this.__CE_registry;
  2522. this.__CE_registry = nv;
  2523. this.dispatchEvent(new CustomEvent(EVENT_KEY_ON_REGISTRY_READY));
  2524. }
  2525. return true;
  2526. },
  2527. enumerable: false,
  2528. configurable: true
  2529. })
  2530. }
  2531. let eventHandler = (evt) => {
  2532. document.removeEventListener(EVENT_KEY_ON_REGISTRY_READY, eventHandler, false);
  2533. const f = callback;
  2534. callback = null;
  2535. eventHandler = null;
  2536. f();
  2537. };
  2538. document.addEventListener(EVENT_KEY_ON_REGISTRY_READY, eventHandler, false);
  2539. } else {
  2540. callback();
  2541. }
  2542. };
  2543.  
  2544. const promiseForCustomYtElementsReady = new Promise(onRegistryReady);
  2545.  
  2546. const renderReadyPn = typeof ResizeObserver !== 'undefined' ? (sizingTarget) => {
  2547.  
  2548. return new Promise(resolve => {
  2549.  
  2550. let ro = new ResizeObserver(entries => {
  2551. if (entries && entries.length >= 1) {
  2552. resolve();
  2553. ro.disconnect();
  2554. ro = null;
  2555. }
  2556. });
  2557. ro.observe(sizingTarget);
  2558.  
  2559.  
  2560.  
  2561. });
  2562.  
  2563. } : (sizingTarget) => {
  2564.  
  2565.  
  2566. return new Promise(resolve => {
  2567.  
  2568. let io = new IntersectionObserver(entries => {
  2569. if (entries && entries.length >= 1) {
  2570. resolve();
  2571. io.disconnect();
  2572. io = null;
  2573. }
  2574. });
  2575. io.observe(sizingTarget);
  2576.  
  2577.  
  2578.  
  2579. });
  2580.  
  2581. };
  2582.  
  2583. /* globals WeakRef:false */
  2584.  
  2585. /** @type {(o: Object | null) => WeakRef | null} */
  2586. const mWeakRef = typeof WeakRef === 'function' ? (o => o ? new WeakRef(o) : null) : (o => o || null);
  2587.  
  2588. /** @type {(wr: Object | null) => Object | null} */
  2589. const kRef = (wr => (wr && wr.deref) ? wr.deref() : wr);
  2590.  
  2591. const { insertBeforeNaFn, appendChildNaFn } = (() => {
  2592. // native methods
  2593.  
  2594. const insertBefore = HTMLElement_.prototype.insertBefore;
  2595. const appendChild = HTMLElement_.prototype.appendChild;
  2596.  
  2597. return {
  2598. insertBeforeNaFn: (parent, node, child) => {
  2599. insertBefore.call(parent, node, child);
  2600. },
  2601. appendChildNaFn: (parent, node) => {
  2602. appendChild.call(parent, node);
  2603. }
  2604. };
  2605.  
  2606. /*
  2607. const insertBeforeFn = (parent, node, child) => {
  2608. if ('__shady_native_insertBefore' in parent) parent.__shady_native_insertBefore(node, child);
  2609. else parent.insertBefore(node, child);
  2610. }
  2611.  
  2612. const appendChildFn = (parent, node) =>{
  2613. if('__shady_native_appendChild' in parent) parent.__shady_native_appendChild(node);
  2614. else parent.appendChild(node);
  2615. }
  2616. */
  2617.  
  2618. })();
  2619.  
  2620.  
  2621.  
  2622. let __LCRInjection__ = 0; // 0 for no injection
  2623. const LCRImmedidates = []; // array of sync. func
  2624.  
  2625. let getLCRDummyP_ = null;
  2626. // lcrPromiseFn
  2627. const getLCRDummy = () => {
  2628.  
  2629. /* remarks */
  2630.  
  2631. /*
  2632.  
  2633. // YouTube uses `<ps-dom-if class="style-scope ytd-live-chat-frame"><template></template></ps-dom-if>` to create yt-live-chat-renderer
  2634. // <ps-dom-if> is located inside ytd-live-chat-frame#chat in main frame
  2635. // <ps-dom-if>.hostElement is located as iframe's yt-live-chat-app > div#contents > yt-live-chat-renderer
  2636.  
  2637. */
  2638.  
  2639.  
  2640. // direct createElement or createComponent_ will make the emoji rendering crashed. reason TBC
  2641.  
  2642. return getLCRDummyP_ || (getLCRDummyP_ = Promise.all([customElements.whenDefined('yt-live-chat-app'), customElements.whenDefined('yt-live-chat-renderer')]).then(async () => {
  2643.  
  2644. const tag = "yt-live-chat-renderer"
  2645. let dummy = document.querySelector(tag);
  2646. if (!dummy) {
  2647.  
  2648. let mo = null;
  2649.  
  2650. const ytLiveChatApp = document.querySelector('yt-live-chat-app') || document.createElement('yt-live-chat-app');
  2651.  
  2652. const lcaProto = getProto(ytLiveChatApp);
  2653. let fz38;
  2654.  
  2655. let qt38=0;
  2656. let bypass = false;
  2657.  
  2658.  
  2659. dummy = await new Promise(resolve => {
  2660.  
  2661.  
  2662. if (typeof lcaProto.createComponent_ === 'function' && !lcaProto.createComponent99_ && lcaProto.createComponent_.length === 3) {
  2663. console.log('[yt-chat-lcr] lcaProto.createComponent_ is found');
  2664.  
  2665. lcaProto.createComponent99_ = lcaProto.createComponent_;
  2666. lcaProto.createComponent98_ = function (a, b, c) {
  2667. const z = customCreateComponent(a,b,c);
  2668. if(z !== undefined) return z;
  2669. // (3) ['yt-live-chat-renderer', {…}, true]
  2670. const r = this.createComponent99_(a, b,c);
  2671. const componentTag = (typeof a === 'string' ? a : (a||0).component) || `${(r||0).nodeName}`.toLowerCase();
  2672. if ( componentTag === 'yt-live-chat-renderer' && !bypass) {
  2673. qt38 = 1;
  2674.  
  2675. __LCRInjection__ = __LCRInjection__ | 1;
  2676.  
  2677. // r.polymerController.__proto__.handleLiveChatActions471_ = r.polymerController.__proto__.handleLiveChatActions_;
  2678. // r.polymerController.__proto__.handleLiveChatActions_ = function (arr) {
  2679.  
  2680.  
  2681. // preprocessChatLiveActions(arr);
  2682.  
  2683. // return this.handleLiveChatActions471_(arr);
  2684.  
  2685.  
  2686. // }
  2687.  
  2688. for (const f of LCRImmedidates) {
  2689. f(r);
  2690. }
  2691. LCRImmedidates.length = 0;
  2692.  
  2693. resolve(r); // note: this dom is not yet adopted, but promise resolve is later than ops.
  2694. console.log('[yt-chat-lcr] element found by method 1');
  2695. }
  2696. return r;
  2697. };
  2698. lcaProto.createComponent_ = lcaProto.createComponent98_;
  2699.  
  2700. if (!USE_OBTAIN_LCR_BY_BOTH_METHODS) return;
  2701.  
  2702. }
  2703.  
  2704. // console.log('[yt-chat] lcaProto traditional');
  2705.  
  2706. const pz38 = document.getElementsByTagName(tag);
  2707. fz38 = () => {
  2708. const t = pz38[0]
  2709. if (t) {
  2710. qt38 = 2;
  2711.  
  2712. __LCRInjection__ = __LCRInjection__ | 2;
  2713. resolve(t);
  2714. console.log('[yt-chat-lcr] element found by method 2');
  2715. }
  2716. };
  2717. mo = new MutationObserver(fz38);
  2718. mo.observe(document, { subtree: true, childList: true, attributes: true });
  2719. document.addEventListener('yt-action', fz38, true);
  2720. fz38();
  2721.  
  2722. });
  2723.  
  2724. bypass = true;
  2725.  
  2726. if (mo) {
  2727. mo.disconnect();
  2728. mo.takeRecords();
  2729. mo = null;
  2730. }
  2731. if (fz38) {
  2732. document.removeEventListener('yt-action', fz38, true);
  2733. fz38 = null;
  2734. }
  2735. console.log(`[yt-chat-lcr] lcr appears, dom = ${document.getElementsByTagName(tag).length}, method = ${qt38}`);
  2736.  
  2737.  
  2738. // if (lcaProto.createComponent99_ && lcaProto.createComponent_ && lcaProto.createComponent98_ === lcaProto.createComponent_) {
  2739. // lcaProto.createComponent_ = lcaProto.createComponent99_;
  2740. // lcaProto.createComponent99_ = null;
  2741. // lcaProto.createComponent98_ = null;
  2742. // }
  2743.  
  2744. } else {
  2745. console.log('[yt-chat-lcr] lcr exists');
  2746. }
  2747. return dummy;
  2748.  
  2749. }));
  2750. }
  2751.  
  2752. const { addCssManaged } = (() => {
  2753.  
  2754. const addFontPreRendering = () => {
  2755.  
  2756. groupCollapsed("YouTube Super Fast Chat", " | Fonts Pre-Rendering");
  2757.  
  2758. let efsContainer = document.createElement('elzm-fonts');
  2759. efsContainer.id = 'elzm-fonts-yk75g'
  2760.  
  2761. const arr = [];
  2762. let p = document.createElement('elzm-font');
  2763. arr.push(p);
  2764.  
  2765. if (ENABLE_FONT_PRE_RENDERING & 1) {
  2766. for (const size of [100, 200, 300, 400, 500, 600, 700, 800, 900]) {
  2767.  
  2768. p = document.createElement('elzm-font');
  2769. p.style.fontWeight = size;
  2770. arr.push(p);
  2771. }
  2772. }
  2773.  
  2774. if (ENABLE_FONT_PRE_RENDERING & 2) {
  2775. for (const size of [100, 200, 300, 400, 500, 600, 700, 800, 900]) {
  2776.  
  2777. p = document.createElement('elzm-font');
  2778. p.style.fontFamily = 'Roboto';
  2779. p.style.fontWeight = size;
  2780. arr.push(p);
  2781. }
  2782. }
  2783.  
  2784. if (ENABLE_FONT_PRE_RENDERING & 4) {
  2785. for (const size of [100, 200, 300, 400, 500, 600, 700, 800, 900]) {
  2786.  
  2787. p = document.createElement('elzm-font');
  2788. p.style.fontFamily = '"YouTube Noto",Roboto,Arial,Helvetica,sans-serif';
  2789. p.style.fontWeight = size;
  2790. arr.push(p);
  2791. }
  2792. }
  2793.  
  2794.  
  2795. if (ENABLE_FONT_PRE_RENDERING & 8) {
  2796. for (const size of [100, 200, 300, 400, 500, 600, 700, 800, 900]) {
  2797.  
  2798. p = document.createElement('elzm-font');
  2799. p.style.fontFamily = '"Noto",Roboto,Arial,Helvetica,sans-serif';
  2800. p.style.fontWeight = size;
  2801. arr.push(p);
  2802. }
  2803. }
  2804.  
  2805.  
  2806. if (ENABLE_FONT_PRE_RENDERING & 16) {
  2807. for (const size of [100, 200, 300, 400, 500, 600, 700, 800, 900]) {
  2808.  
  2809. p = document.createElement('elzm-font');
  2810. p.style.fontFamily = 'sans-serif';
  2811. p.style.fontWeight = size;
  2812. arr.push(p);
  2813. }
  2814. }
  2815.  
  2816. console1.log('number of elzm-font elements', arr.length);
  2817.  
  2818. HTMLElement_.prototype.append.apply(efsContainer, arr);
  2819.  
  2820. (document.body || document.documentElement).appendChild(efsContainer);
  2821.  
  2822.  
  2823. console1.log('elzm-font elements have been added to the page for rendering.');
  2824.  
  2825. groupEnd();
  2826.  
  2827. }
  2828.  
  2829. let isCssAdded = false;
  2830.  
  2831. function addCssElement() {
  2832. let s = document.createElement('style');
  2833. s.id = 'ewRvC';
  2834. return s;
  2835. }
  2836.  
  2837. const addCssManaged = () => {
  2838. if (!isCssAdded && document.documentElement && document.head) {
  2839. isCssAdded = true;
  2840. document.head.appendChild(dr(addCssElement())).textContent = addCss();
  2841. if (ENABLE_FONT_PRE_RENDERING) {
  2842. Promise.resolve().then(addFontPreRendering)
  2843. }
  2844. }
  2845. }
  2846.  
  2847. return { addCssManaged };
  2848. })();
  2849.  
  2850.  
  2851. const { setupStyle } = (() => {
  2852.  
  2853. const sp7 = Symbol();
  2854.  
  2855. const proxyHelperFn = (dummy) => ({
  2856.  
  2857. get(target, prop) {
  2858. return (prop in dummy) ? dummy[prop] : prop === sp7 ? target : target[prop];
  2859. },
  2860. set(target, prop, value) {
  2861. if (!(prop in dummy)) {
  2862. target[prop] = value;
  2863. }
  2864. return true;
  2865. },
  2866. has(target, prop) {
  2867. return (prop in target);
  2868. },
  2869. deleteProperty(target, prop) {
  2870. return true;
  2871. },
  2872. ownKeys(target) {
  2873. return Object.keys(target);
  2874. },
  2875. defineProperty(target, key, descriptor) {
  2876. return Object.defineProperty(target, key, descriptor);
  2877. },
  2878. getOwnPropertyDescriptor(target, key) {
  2879. return Object.getOwnPropertyDescriptor(target, key);
  2880. },
  2881.  
  2882. });
  2883.  
  2884. const setupStyle = (m1, m2) => {
  2885. if (!ENABLE_NO_SMOOTH_TRANSFORM) return;
  2886.  
  2887. const dummy1v = {
  2888. transform: '',
  2889. height: '',
  2890. minHeight: '',
  2891. paddingBottom: '',
  2892. paddingTop: ''
  2893. };
  2894.  
  2895. const dummyStyleFn = (k) => (function () { const style = this[sp7]; return style[k](...arguments); });
  2896. for (const k of ['toString', 'getPropertyPriority', 'getPropertyValue', 'item', 'removeProperty', 'setProperty']) {
  2897. dummy1v[k] = dummyStyleFn(k);
  2898. }
  2899.  
  2900. const dummy1p = proxyHelperFn(dummy1v);
  2901. const sp1v = new Proxy(m1.style, dummy1p);
  2902. const sp2v = new Proxy(m2.style, dummy1p);
  2903. Object.defineProperty(m1, 'style', { get() { return sp1v }, set() { }, enumerable: true, configurable: true });
  2904. Object.defineProperty(m2, 'style', { get() { return sp2v }, set() { }, enumerable: true, configurable: true });
  2905. m1.removeAttribute("style");
  2906. m2.removeAttribute("style");
  2907.  
  2908. }
  2909.  
  2910. return { setupStyle };
  2911.  
  2912. })();
  2913.  
  2914.  
  2915.  
  2916. function setThumbnails(config) {
  2917.  
  2918. const { baseObject, thumbnails, flag0, imageLinks } = config;
  2919.  
  2920. if (flag0 || (ENABLE_PRELOAD_THUMBNAIL && imageLinks)) {
  2921.  
  2922.  
  2923. if (thumbnails && thumbnails.length > 0) {
  2924. if (flag0 > 0 && thumbnails.length > 1) {
  2925. let pSize = 0;
  2926. let newThumbnails = [];
  2927. for (const thumbnail of thumbnails) {
  2928. if (!thumbnail || !thumbnail.url) continue;
  2929. const squarePhoto = thumbnail.width === thumbnail.height && typeof thumbnail.width === 'number';
  2930. const condSize = pSize <= 0 || (flag0 === 1 ? pSize > thumbnail.width : pSize < thumbnail.width);
  2931. const leastSizeFulfilled = squarePhoto ? thumbnail.width >= LEAST_IMAGE_SIZE : true;
  2932. if ((!squarePhoto || condSize) && leastSizeFulfilled) {
  2933. newThumbnails.push(thumbnail);
  2934. if (imageLinks) imageLinks.add(thumbnail.url);
  2935. }
  2936. if (squarePhoto && condSize && leastSizeFulfilled) {
  2937. pSize = thumbnail.width;
  2938. }
  2939. }
  2940. if (thumbnails.length !== newThumbnails.length && thumbnails === baseObject.thumbnails && newThumbnails.length > 0) {
  2941. baseObject.thumbnails = newThumbnails;
  2942. } else {
  2943. newThumbnails.length = 0;
  2944. }
  2945. newThumbnails = null;
  2946. } else {
  2947. for (const thumbnail of thumbnails) {
  2948. if (thumbnail && thumbnail.url) {
  2949. if (imageLinks) imageLinks.add(thumbnail.url);
  2950. }
  2951. }
  2952. }
  2953. }
  2954.  
  2955. }
  2956. }
  2957.  
  2958. function fixLiveChatItem(item, imageLinks) {
  2959. const liveChatTextMessageRenderer = (item || 0).liveChatTextMessageRenderer || 0;
  2960. if (liveChatTextMessageRenderer) {
  2961. const messageRuns = (liveChatTextMessageRenderer.message || 0).runs || 0;
  2962. if (messageRuns && messageRuns.length > 0) {
  2963. for (const run of messageRuns) {
  2964. const emojiImage = (((run || 0).emoji || 0).image || 0);
  2965. setThumbnails({
  2966. baseObject: emojiImage,
  2967. thumbnails: emojiImage.thumbnails,
  2968. flag0: EMOJI_IMAGE_SINGLE_THUMBNAIL,
  2969. imageLinks
  2970. });
  2971. }
  2972. }
  2973. const authorPhoto = liveChatTextMessageRenderer.authorPhoto || 0;
  2974. setThumbnails({
  2975. baseObject: authorPhoto,
  2976. thumbnails: authorPhoto.thumbnails,
  2977. flag0: AUTHOR_PHOTO_SINGLE_THUMBNAIL,
  2978. imageLinks
  2979. });
  2980. }
  2981. }
  2982.  
  2983.  
  2984.  
  2985. let kptPF = null;
  2986. const emojiPrefetched = new LimitedSizeSet(PREFETCH_LIMITED_SIZE_EMOJI);
  2987. const authorPhotoPrefetched = new LimitedSizeSet(PREFETCH_LIMITED_SIZE_AUTHOR_PHOTO);
  2988.  
  2989. const linkerOnload = function () {
  2990. this.resolveFn({
  2991. link: this,
  2992. success: true
  2993. });
  2994. this.remove();
  2995. };
  2996. const linkerOnError = function () {
  2997. this.resolveFn({
  2998. link: this,
  2999. success: false
  3000. });
  3001. this.remove();
  3002. };
  3003. function linker(link, rel, href, _as) {
  3004. return new Promise(resolve => {
  3005. if (!link) link = document.createElement('link');
  3006. link.rel = rel;
  3007. if (_as) link.setAttribute('as', _as);
  3008. link.resolveFn = resolve;
  3009. link.onload = linkerOnload;
  3010. link.onerror = linkerOnError;
  3011. link.href = href;
  3012. document.head.appendChild(link);
  3013. link = null;
  3014. });
  3015. }
  3016.  
  3017. // ------- side process [sideProcesses] -------
  3018. const reuseFixDataViewModel = (elm) => {
  3019. // detach data-view model signal
  3020. return Promise.resolve(elm).then((elm) => {
  3021. for (const node of elm.getElementsByTagName('*')) {
  3022. const cnt = insp(node);
  3023. if (typeof cnt.dispose === 'function' && cnt.dispose.length === 0) {
  3024. try {
  3025. cnt.dispose();
  3026. } catch (e) { }
  3027. } else if (typeof node.dispose === 'function' && node.dispose.length === 0) {
  3028. try {
  3029. node.dispose();
  3030. } catch (e) { }
  3031. }
  3032. }
  3033. }).catch(console.warn);;
  3034. };
  3035. const reuseFixYtIconRendering = (elm) => {
  3036. // make properties fresh for flushing
  3037. // return Promise.resolve(elm).then((elm) => {
  3038. // refreshChildrenYtIcons(elm);
  3039. // }).catch(console.warn);;
  3040. };
  3041. const tickerMessageRemovalMo = new MutationObserver(() => {
  3042. const elements = document.querySelectorAll('[ticker-message-removed]:nth-child(n + 40)');
  3043. for (const s of elements) {
  3044. insp(s).requestRemoval();
  3045. }
  3046. });
  3047. tickerMessageRemovalMo.observe(document, { subtree: true, attributes: true, attributeFilter: ['ticker-message-removed'] });
  3048. const onVisibleItemStampNodeRemoval = (elmId) => {
  3049. // set the corresponding ticker [ticker-message-removed]
  3050. return Promise.resolve(elmId).then((elmId) => {
  3051. const tickerElm = document.querySelector(`.style-scope.yt-live-chat-ticker-renderer[id="${elmId}"]`);
  3052. if (tickerElm) {
  3053. tickerElm.setAttribute('ticker-message-removed', '');
  3054. }
  3055. }).catch(console.warn);;
  3056. };
  3057. let onTickerItemStampNodeAddedwaiting = false;
  3058. const onTickerItemStampNodeAdded = () =>{
  3059. // remove the stale ticker(s)
  3060. if (onTickerItemStampNodeAddedwaiting) return;
  3061. onTickerItemStampNodeAddedwaiting = true;
  3062. return Promise.resolve().then(() => {
  3063. onTickerItemStampNodeAddedwaiting = false;
  3064. const selector = "[ticker-message-removed]:nth-child(n + 40)";
  3065. const tickerElm = document.querySelector(selector);
  3066. if (tickerElm) { // likely false
  3067. const tickerElms = document.querySelectorAll(selector);
  3068. for (const tickerElm of tickerElms) insp(tickerElm).requestRemoval();
  3069. }
  3070. }).catch(console.warn);;
  3071. };
  3072. // const mutationDelayedRefreshData = async (cnt) => {
  3073. // // ensure data is invalidated correctly after mutation
  3074. // return Promise.resolve(cnt).then(async cnt => {
  3075. // wme.data = `${(wme.data & 7) + 1}`;
  3076. // await wmp;
  3077. // cnt.__refreshData930__ && cnt.data && cnt.isAttached && cnt.parentComponent && cnt.__refreshData930__('data', !0);
  3078. // });
  3079. // }
  3080. // ------- side process [sideProcesses] -------
  3081.  
  3082. const cleanContext = async (win) => {
  3083. const waitFn = requestAnimationFrame; // shall have been binded to window
  3084. try {
  3085. let mx = 16; // MAX TRIAL
  3086. const frameId = 'vanillajs-iframe-v1';
  3087. /** @type {HTMLIFrameElement | null} */
  3088. let frame = document.getElementById(frameId);
  3089. let removeIframeFn = null;
  3090. if (!frame) {
  3091. frame = document.createElement('iframe');
  3092. frame.id = frameId;
  3093. const blobURL = typeof webkitCancelAnimationFrame === 'function' && typeof kagi === 'undefined' ? (frame.src = URL.createObjectURL(new Blob([], { type: 'text/html' }))) : null; // avoid Brave Crash
  3094. frame.sandbox = 'allow-same-origin'; // script cannot be run inside iframe but API can be obtained from iframe
  3095. let n = document.createElement('noscript'); // wrap into NOSCRPIT to avoid reflow (layouting)
  3096. n.appendChild(frame);
  3097. while (!document.documentElement && mx-- > 0) await new Promise(waitFn); // requestAnimationFrame here could get modified by YouTube engine
  3098. const root = document.documentElement;
  3099. root.appendChild(n); // throw error if root is null due to exceeding MAX TRIAL
  3100. if (blobURL) Promise.resolve().then(() => URL.revokeObjectURL(blobURL));
  3101.  
  3102. removeIframeFn = (setTimeout) => {
  3103. const removeIframeOnDocumentReady = (e) => {
  3104. e && win.removeEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false);
  3105. e = n;
  3106. n = win = removeIframeFn = 0;
  3107. setTimeout ? setTimeout(() => e.remove(), 200) : e.remove();
  3108. }
  3109. if (!setTimeout || document.readyState !== 'loading') {
  3110. removeIframeOnDocumentReady();
  3111. } else {
  3112. win.addEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false);
  3113. }
  3114. }
  3115. }
  3116. while (!frame.contentWindow && mx-- > 0) await new Promise(waitFn);
  3117. const fc = frame.contentWindow;
  3118. if (!fc) throw "window is not found."; // throw error if root is null due to exceeding MAX TRIAL
  3119. try {
  3120. const { requestAnimationFrame, setTimeout, cancelAnimationFrame, setInterval, clearInterval, getComputedStyle } = fc;
  3121. const res = { requestAnimationFrame, setTimeout, cancelAnimationFrame, setInterval, clearInterval, getComputedStyle };
  3122. for (let k in res) res[k] = res[k].bind(win); // necessary
  3123. if (removeIframeFn) Promise.resolve(res.setTimeout).then(removeIframeFn);
  3124.  
  3125. /** @type {HTMLElement} */
  3126. const HTMLElementProto = fc.HTMLElement.prototype;
  3127. /** @type {EventTarget} */
  3128. const EventTargetProto = fc.EventTarget.prototype;
  3129. // jsonParseFix = {
  3130. // _JSON: fc.JSON, _parse: fc.JSON.parse
  3131. // }
  3132. return {
  3133. ...res,
  3134. animate: HTMLElementProto.animate,
  3135. addEventListener: EventTargetProto.addEventListener,
  3136. removeEventListener: EventTargetProto.removeEventListener
  3137. };
  3138. } catch (e) {
  3139. if (removeIframeFn) removeIframeFn();
  3140. return null;
  3141. }
  3142. } catch (e) {
  3143. console.warn(e);
  3144. return null;
  3145. }
  3146. };
  3147.  
  3148. cleanContext(win).then(__CONTEXT__ => {
  3149. if (!__CONTEXT__) return null;
  3150.  
  3151. const { requestAnimationFrame, setTimeout, cancelAnimationFrame, setInterval, clearInterval, animate, getComputedStyle, addEventListener, removeEventListener } = __CONTEXT__;
  3152.  
  3153. const wmComputedStyle = new WeakMap();
  3154. const getComputedStyleCached = (elem) => {
  3155. let cs = wmComputedStyle.get(elem);
  3156. if (!cs) {
  3157. cs = getComputedStyle(elem);
  3158. wmComputedStyle.set(elem, cs);
  3159. }
  3160. return cs;
  3161. }
  3162.  
  3163.  
  3164. const isGPUAccelerationAvailable = (() => {
  3165. // https://gist.github.com/cvan/042b2448fcecefafbb6a91469484cdf8
  3166. try {
  3167. const canvas = document.createElement('canvas');
  3168. return !!(canvas.getContext('webgl') || canvas.getContext('experimental-webgl'));
  3169. } catch (e) {
  3170. return false;
  3171. }
  3172. })();
  3173.  
  3174. const foregroundPromiseFn_noGPU = (() => {
  3175.  
  3176. if (isGPUAccelerationAvailable) return null;
  3177.  
  3178. const pd = Object.getOwnPropertyDescriptor(Document.prototype, 'visibilityState');
  3179. if (!pd || typeof pd.get !== 'function') return null;
  3180. const pdGet = pd.get;
  3181.  
  3182. let pr = null;
  3183.  
  3184. let hState = pdGet.call(document) === 'hidden';
  3185. // let cid = 0;
  3186. pureAddEventListener.call(document, 'visibilitychange', (evt) => {
  3187. const newHState = pdGet.call(document) === 'hidden';
  3188. if (hState !== newHState) {
  3189. // if (cid > 0) cid = clearInterval(cid);
  3190. hState = newHState;
  3191. if (!hState && pr) pr = pr.resolve();
  3192. }
  3193. });
  3194.  
  3195. // cid = setInterval(() => {
  3196. // const newHState = document.visibilityState === 'hidden';
  3197. // if (hState !== newHState) {
  3198. // hState = newHState;
  3199. // if (!hState && pr) pr = pr.resolve();
  3200. // }
  3201. // }, 100);
  3202.  
  3203.  
  3204. return (() => {
  3205. if (pr) return pr;
  3206. const w = ((!hState && setTimeout(() => {
  3207. if (!hState && pr === w) pr = pr.resolve();
  3208. })), (pr = new PromiseExternal()));
  3209. return w;
  3210. });
  3211.  
  3212. })();
  3213.  
  3214. // window.foregroundPromiseFn_noGPU = foregroundPromiseFn_noGPU;
  3215.  
  3216. let rafPromise = null;
  3217. const getRafPromise = () => rafPromise || (rafPromise = new Promise(resolve => {
  3218. requestAnimationFrame(hRes => {
  3219. rafPromise = null;
  3220. resolve(hRes);
  3221. });
  3222. }));
  3223. const foregroundPromiseFn = foregroundPromiseFn_noGPU || getRafPromise;
  3224.  
  3225. // const iAFP = foregroundPromiseFn_noGPU ? foregroundPromiseFn_noGPU : typeof IntersectionObserver === 'undefined' ? getRafPromise : (() => {
  3226.  
  3227. // const ioWM = new WeakMap();
  3228. // const ek = Symbol();
  3229. // /** @type {IntersectionObserverCallback} */
  3230. // const ioCb = (entries, observer) => {
  3231. // /** @type {PromiseExternal} */
  3232. // const pr = observer[ek];
  3233. // const resolve = pr.resolve;
  3234. // let target;
  3235. // if (resolve && (target = ((entries ? entries[0] : 0) || 0).target) instanceof Element) {
  3236. // pr.resolve = null;
  3237. // observer.unobserve(target);
  3238. // resolve();
  3239. // }
  3240. // };
  3241. // /**
  3242. // *
  3243. // * @param {Element} elm
  3244. // * @returns {Promise<void>}
  3245. // */
  3246. // const iAFP = (elm) => {
  3247. // let io = ioWM.get(elm);
  3248. // if (!io) {
  3249. // io = new IntersectionObserver(ioCb);
  3250. // ioWM.set(elm, io); // strong reference
  3251. // }
  3252. // let pr = io[ek];
  3253. // if (!pr) {
  3254. // pr = io[ek] = new PromiseExternal();
  3255. // io.observe(elm);
  3256. // }
  3257. // return pr;
  3258. // }
  3259.  
  3260. // return iAFP;
  3261.  
  3262. // })();
  3263.  
  3264. let playerState = null;
  3265. let _playerState = null;
  3266. let lastPlayerProgress = null;
  3267. let relayCount = 0;
  3268. let playerEventsByIframeRelay = false;
  3269. let isPlayProgressTriggered = false;
  3270. let waitForInitialDataCompletion = 0;
  3271.  
  3272.  
  3273.  
  3274. // let aeConstructor = null;
  3275.  
  3276. // << __openedChanged82 >>
  3277. let currentMenuPivotWR = null;
  3278.  
  3279. // << if DO_PARTICIPANT_LIST_HACKS >>
  3280. const beforeParticipantsMap = new WeakMap();
  3281. // << end >>
  3282.  
  3283.  
  3284.  
  3285. // << if onRegistryReadyForDOMOperations >>
  3286.  
  3287. let dt0 = Date.now() - 2000;
  3288. const dateNow = () => Date.now() - dt0;
  3289. // let lastScroll = 0;
  3290. // let lastLShow = 0;
  3291. let lastWheel = 0;
  3292. let lastMouseUp = 0;
  3293. let currentMouseDown = false;
  3294. let lastTouchDown = 0;
  3295. let lastTouchUp = 0;
  3296. let currentTouchDown = false;
  3297. let lastUserInteraction = 0;
  3298.  
  3299. let scrollChatFn = null;
  3300.  
  3301. // let skipDontRender = true; // true first; false by flushActiveItems_
  3302. // let allowDontRender = null;
  3303.  
  3304. // ---- #items mutation ----
  3305. // let firstList = true;
  3306.  
  3307. // << end >>
  3308.  
  3309.  
  3310. const stackMarcoTask = (f) => {
  3311. return new Promise(resolve => {
  3312. nextBrowserTick_(async () => {
  3313. try {
  3314. await f();
  3315. } catch (e) {
  3316. console.warn(e);
  3317. } finally {
  3318. resolve();
  3319. }
  3320. });
  3321. })
  3322. };
  3323.  
  3324.  
  3325. const elementFirstElementChild = Object.getOwnPropertyDescriptor(Element.prototype, 'firstElementChild');
  3326. const sFirstElementChild = Symbol();
  3327. Object.defineProperty(Element.prototype, sFirstElementChild, elementFirstElementChild);
  3328.  
  3329. const elementLastElementChild = Object.getOwnPropertyDescriptor(Element.prototype, 'lastElementChild');
  3330. const sLastElementChild = Symbol();
  3331. Object.defineProperty(Element.prototype, sLastElementChild, elementLastElementChild);
  3332.  
  3333. const elementPrevElementSibling = Object.getOwnPropertyDescriptor(Element.prototype, 'previousElementSibling');
  3334. const sPrevElementSibling = Symbol();
  3335. Object.defineProperty(Element.prototype, sPrevElementSibling, elementPrevElementSibling);
  3336.  
  3337. const elementNextElementSibling = Object.getOwnPropertyDescriptor(Element.prototype, 'nextElementSibling');
  3338. const sNextElementSibling = Symbol();
  3339. Object.defineProperty(Element.prototype, sNextElementSibling, elementNextElementSibling);
  3340.  
  3341. const firstComponentChildFn = (elNode) => {
  3342. elNode = elNode[sFirstElementChild];
  3343. while ((elNode instanceof Element) && !elNode.is) elNode = elNode[sNextElementSibling];
  3344. return elNode;
  3345. }
  3346. const lastComponentChildFn = (elNode) => {
  3347. elNode = elNode[sLastElementChild];
  3348. while ((elNode instanceof Element) && !elNode.is) elNode = elNode[sPrevElementSibling];
  3349. return elNode;
  3350. }
  3351. const nextComponentSiblingFn = (elNode) => {
  3352. do {
  3353. elNode = elNode[sNextElementSibling];
  3354. } while ((elNode instanceof Element) && !elNode.is);
  3355. return elNode;
  3356. }
  3357.  
  3358. const nativeNow = performance.constructor.prototype.now.bind(performance);
  3359.  
  3360. const queueMicrotask_ = typeof queueMicrotask === 'function' ? queueMicrotask : (f) => (Promise.resolve().then(f), void 0);
  3361.  
  3362. const executeTaskBatch = function (taskArr, firstMarco = true) {
  3363. if (!(taskArr || 0).length) throw new TypeError(`Illegal invocation`);
  3364. return new Promise(resolveFinal => {
  3365. let resolveFn = null;
  3366. const len = taskArr.length;
  3367. const results = new Array(len);
  3368. const makePromise = () => new Promise(resolve => { resolveFn = resolve });
  3369. let firedCount = 0;
  3370. const executor = () => {
  3371. if (taskArr.length !== len) throw new TypeError(`Illegal invocation`);
  3372. const resolveFn_ = resolveFn;
  3373. let t0 = 0;
  3374. let next = 0;
  3375. taskArr.forEach((task, idx) => {
  3376. if (typeof (task || 0) !== 'object') throw new TypeError(`Illegal invocation`);
  3377. if (!task.fired) {
  3378. queueMicrotask_(() => {
  3379. if (next || task.fired) return;
  3380. task.fired = true;
  3381. if (++firedCount === len) next |= 2;
  3382. if (!t0) t0 = nativeNow() + 10;
  3383. const { fn } = task;
  3384. results[idx] = fn(task); // sync task only
  3385. if (nativeNow() > t0) next |= 1;
  3386. });
  3387. }
  3388. });
  3389. queueMicrotask_(() => resolveFn_(next))
  3390. }
  3391. const looper = (next) => {
  3392. if (!next) throw new TypeError(`Illegal invocation`);
  3393. if (next & 2) {
  3394. if (next & 1) {
  3395. nextBrowserTick_(() => resolveFinal(results))
  3396. } else {
  3397. resolveFinal(results);
  3398. }
  3399. } else {
  3400. const p = makePromise();
  3401. nextBrowserTick_(executor);
  3402. p.then(looper);
  3403. }
  3404. }
  3405. const p = makePromise();
  3406. firstMarco ? nextBrowserTick_(executor) : executor();
  3407. p.then(looper);
  3408.  
  3409. })
  3410.  
  3411. }
  3412. // window.executeTaskBatch = executeTaskBatch;
  3413.  
  3414.  
  3415. const renderMap = new WeakMap();
  3416.  
  3417.  
  3418. // reserved for future use
  3419. const countKeys = (H) => {
  3420.  
  3421. const countKeys_ = (H, u, q, l) => {
  3422. if (u.has(H)) return;
  3423. u.add(H);
  3424. const pds = Object.getOwnPropertyDescriptors(H);
  3425. for (const name in pds) {
  3426. const pd_ = pds[name];
  3427. const o = pd_.value;
  3428. if (o && pd_.configurable && pd_.writable && !(o instanceof EventTarget)) {
  3429. if (typeof o === 'object') {
  3430. q.push([l, name.length]);
  3431. countKeys_(o, u, q, l+1);
  3432. }
  3433. }
  3434. }
  3435. };
  3436. const m = [];
  3437. countKeys_(H, new WeakSet(), m, 0);
  3438. return `-${tupleHash(m, false).toString(36)}${tupleHash(m, true).toString(36)}`; // 12 chars
  3439. }
  3440.  
  3441. // reserved for future use
  3442. function tupleHash(pairs, reversed) {
  3443. let hash = 17; // Prime seed
  3444. const prime1 = 31;
  3445. for (let i = 0; i < pairs.length; i++) {
  3446. const [a_, b_] = pairs[i];
  3447. const a = reversed ? b_ : a_;
  3448. const b = reversed ? a_ : b_;
  3449. // Combine a and b into pairHash
  3450. let pairHash = ((a * prime1) ^ b) >>> 0;
  3451. // Mix pairHash into hash with bitwise operations
  3452. hash ^= pairHash;
  3453. hash = ((hash << 5) | (hash >>> 27)) >>> 0; // Rotate left 5 bits
  3454. hash = (hash * 37 + 11) >>> 0; // Small prime multiplier and offset
  3455. }
  3456. // Finalize to ensure fixed range (optional: constrain to 30 bits)
  3457. return 0x2FFFFFFF + (hash & 0x3FFFFFFF); // Mask to 30 bits (max: 1073741823)
  3458. }
  3459.  
  3460.  
  3461. const rendererStamperFactory = (cProto, options) => {
  3462.  
  3463.  
  3464. let pDivResourceEventCountLast = 0;
  3465. let pDivResourceEventCount = 0;
  3466.  
  3467. const pDivOnResource = function (evt) {
  3468. const target = evt.target;
  3469. if (target && target.nodeType === 1 && target.nodeName === "IMG") {
  3470. pDivResourceEventCount = (pDivResourceEventCount & 1073741823) + 1;
  3471. }
  3472. };
  3473.  
  3474. const { key, stamperDomClass, preloadFn } = options;
  3475.  
  3476. // const newDoc = document.implementation.createHTMLDocument("NewDoc");
  3477. const pSpace = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
  3478. document.documentElement.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3479. mockCommentElement(document.documentElement.lastChild);
  3480. document.documentElement.lastChild.replaceWith(pSpace);
  3481. const pNode = document.createElement('ns-538');
  3482. pSpace.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3483. mockCommentElement(pSpace.lastChild);
  3484. pSpace.lastChild.replaceWith(pNode);
  3485.  
  3486. const pDiv = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
  3487. if (typeof pNode.attachShadow === 'function') {
  3488. const pShadow = pNode.attachShadow({ mode: "open" });
  3489. pShadow.replaceChildren(pDiv);
  3490. } else {
  3491. pNode.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3492. mockCommentElement(pNode.lastChild);
  3493. pNode.lastChild.replaceWith(pDiv);
  3494. }
  3495.  
  3496. const pDivNew = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
  3497.  
  3498. pDiv.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3499. mockCommentElement(pDiv.lastChild);
  3500. pDiv.lastChild.replaceWith(pDivNew);
  3501.  
  3502. pDivNew.addEventListener('load', pDivOnResource, true);
  3503. pDivNew.addEventListener('error', pDivOnResource, true);
  3504.  
  3505. const wmRemoved = new Map();
  3506. wmRemoved.set = wmRemoved.setOriginal || wmRemoved.set;
  3507.  
  3508. // const wmMapToItem = new WeakMap();
  3509. // let wmPendingList = null;
  3510.  
  3511. const nullComponents = new Map();
  3512. nullComponents.set = nullComponents.setOriginal || nullComponents.set;
  3513.  
  3514. const componentDefaultAttributes = new WeakMap();
  3515.  
  3516. const fnKeyH = `${key}$$c472`;
  3517.  
  3518. cProto.__ensureContainerDomApi7577 = function (cId) {
  3519. const container = this.getStampContainer_(cId);
  3520. if (container && !container.__checkedDomApi33__) {
  3521. container.__checkedDomApi33__ = true;
  3522. if (!container.__domApi) {
  3523. if (typeof this.stampDomArray366_ === 'function' && this.stampDomArray366_.length === 6) {
  3524. let c = container;
  3525. try {
  3526. this.stampDomArray366_.call({
  3527. getStampContainer_(d) {
  3528. return c
  3529. },
  3530. get is() {
  3531. throw new Error('');
  3532. },
  3533. get hostElement() {
  3534. throw new Error('');
  3535. }
  3536. }, 0, cId, false, false, false, false);
  3537. } catch (e) { }
  3538. c = null;
  3539. }
  3540. }
  3541. }
  3542. }
  3543.  
  3544. cProto[fnKeyH] = async function (cTag, cId, pr00) {
  3545.  
  3546. this.__ensureContainerDomApi7577(cId);
  3547.  
  3548. // await the current executing task (if any)
  3549. // and avoid stacking in the same marco task
  3550. await Promise.all([pr00, nextBrowserTick_()]);
  3551. if (!this.ec389a && !this.ec389r) return;
  3552. const addedCount0 = this.ec389a;
  3553. const removedCount0 = this.ec389r;
  3554.  
  3555. this.ec389 = false;
  3556. this.ec389a = 0;
  3557. this.ec389r = 0;
  3558.  
  3559. const stampDomMap = this.stampDom[cTag].mapping;
  3560. const isTickerRendering = cTag === 'tickerItems';
  3561. const isMessageListRendering = cTag === 'visibleItems';
  3562.  
  3563. // coming process can be stacked as ec389a and ec389r are reset.
  3564.  
  3565. const deObjectComponent = (itemEntry) => {
  3566. const I = firstObjectKey(itemEntry);
  3567. const L = stampDomMap[I];
  3568. const H = itemEntry[I];
  3569. return [L, H];
  3570. }
  3571.  
  3572. const hostElement = this.hostElement;
  3573.  
  3574. let renderNodeCount = 0;
  3575. const renderList = this[cTag].map((item) => {
  3576. const [L, H] = deObjectComponent(item);
  3577. const node = kRef(renderMap.get(H));
  3578. return node && hostElement.contains(node) ? (renderNodeCount++, node) : item;
  3579. });
  3580.  
  3581. const isRenderListEmpty = renderList.length === 0;
  3582.  
  3583.  
  3584. // this.ec389 = null;
  3585. // this.ec389a = 0;
  3586. // this.ec389r = 0;
  3587.  
  3588. let addedCounter = 0;
  3589. let removedCounter = 0;
  3590.  
  3591. const createConnectedComponentElm = (insertionObj, L, H, componentName) => {
  3592. // const reusable = false;
  3593. // const componentName = this.getComponentName_(L, H);
  3594. let component;
  3595. if (!nullComponents.has(componentName)) {
  3596. nullComponents.set(componentName, (component = document.createElement(componentName)));
  3597. component.className = stamperDomClass;
  3598. // shadowElm.insertAdjacentElement('beforeend', component);
  3599. } else {
  3600. component = nullComponents.get(componentName);
  3601. }
  3602. component = component.cloneNode(false);
  3603.  
  3604. // const cnt = insp(component);
  3605.  
  3606. // cnt.__dataOld = cnt.__dataPending = null;
  3607. pDivNew.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3608. mockCommentElement(pDivNew.lastChild);
  3609. pDivNew.lastChild.replaceWith(component);
  3610. // cnt.__dataOld = cnt.__dataPending = null;
  3611.  
  3612. return component;
  3613. }
  3614.  
  3615. const listDom = this.getStampContainer_(cId);
  3616.  
  3617. const pnForNewItem = (item) => {
  3618.  
  3619. const [L, H] = deObjectComponent(item);
  3620.  
  3621. const componentName = this.getComponentName_(L, H);
  3622.  
  3623. const wmList = wmRemoved.get(componentName.toLowerCase());
  3624.  
  3625. let connectedComponent = null;
  3626. if (wmList && (connectedComponent = wmList.firstElementChild)) {
  3627. if (this.telemetry_) this.telemetry_.reuse++;
  3628. // if (!wmPendingList) {
  3629. // wmPendingList = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
  3630. // wmPendingList.setAttributeNS('http://www.w3.org/2000/svg', 'wm-pending', 'true');
  3631. // pDiv.insertAdjacentElement('afterend', wmPendingList);
  3632. // }
  3633. // wmPendingList.insertAdjacentElement('beforeend', connectedComponent);
  3634. pDivNew.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3635. mockCommentElement(pDivNew.lastChild);
  3636. pDivNew.lastChild.replaceWith(connectedComponent);
  3637. const attrMap = connectedComponent.attributes;
  3638. const defaultAttrs = componentDefaultAttributes.get(connectedComponent);
  3639. if (defaultAttrs) {
  3640. for (const attr of [...attrMap]) {
  3641. const name = attr.name;
  3642. if (name in defaultAttrs) attr.value = defaultAttrs[name];
  3643. else attrMap.removeNamedItem(name);
  3644. }
  3645. if (attrMap.length !== defaultAttrs['"']) {
  3646. for (const name in defaultAttrs) {
  3647. if (!attrMap[name] && name !== '"') connectedComponent.setAttribute(name, defaultAttrs[name]);
  3648. }
  3649. }
  3650. }
  3651.  
  3652. } else {
  3653. connectedComponent = createConnectedComponentElm(item, L, H, componentName);
  3654. if (this.telemetry_) this.telemetry_.create++;
  3655. }
  3656. if (isTickerRendering) {
  3657. const container = connectedComponent.firstElementChild;
  3658. if (container) container.classList.add('yt-live-chat-ticker-stampdom-container');
  3659. }
  3660.  
  3661. return [item, L, H, connectedComponent];
  3662.  
  3663. };
  3664.  
  3665. let imgPreloadPr = null;
  3666. if (isMessageListRendering) {
  3667. const addedItems = renderList.filter(item => item === 'object' && (item instanceof Node));
  3668. imgPreloadPr = preloadFn(addedItems)();
  3669. }
  3670.  
  3671. // const pt1 = performance.now();
  3672. // const newComponentsEntries = await Promise.all(renderList.map((item) => {
  3673. // return typeof item === 'object' && !(item instanceof Node) ? Promise.resolve(item).then(pnForNewItem) : item;
  3674. // }));
  3675. const newComponentsEntries = isRenderListEmpty ? [] : await executeTaskBatch(renderList.map(item => ({
  3676. item,
  3677. fn(task) {
  3678. const { item } = task;
  3679. return typeof item === 'object' && !(item instanceof Node) ? pnForNewItem(item) : item;
  3680. }
  3681. })));
  3682. // const pt2 = performance.now();
  3683.  
  3684. const imgPromises = [];
  3685.  
  3686. const imgPaths = new Set();
  3687.  
  3688. const pnForRenderNewItem = (entry) => {
  3689. const [item, L, H, connectedComponent] = entry;
  3690.  
  3691. const cnt = insp(connectedComponent);
  3692. // setupRefreshData930(cnt);
  3693. // if (typeof cnt.data === 'object' && cnt.__dataEnabled === true && cnt.__dataReady === true && cnt.__dataInvalid === false) {
  3694. // cnt.data = H;
  3695. // } else {
  3696. const q = this.deferRenderStamperBinding_
  3697. let q2;
  3698. if (typeof q === 'object') q2 = this.deferRenderStamperBinding_ = [];
  3699. this.deferRenderStamperBinding_(connectedComponent, L, Object.assign({}, H)); // pre-flush
  3700. this.flushRenderStamperComponentBindings_();
  3701. if (typeof q === 'object') {
  3702. this.deferRenderStamperBinding_ = q;
  3703. q2.length = 0;
  3704. }
  3705. // }
  3706. // if (cnt.__refreshData930__ && cnt.data) cnt.__refreshData930__('data', !0); // ensure data is invalidated
  3707.  
  3708. // fix yt-icon issue
  3709. // refreshChildrenYtIcons(connectedComponent);
  3710.  
  3711. // const imgs = connectedComponent.getElementsByTagName('IMG');
  3712. // if (imgs.length > 0) {
  3713. // for (let i = 0, l = imgs.length; i < l; i++) {
  3714. // const src = imgs[i].src;
  3715. // if (src.includes('://') && !imgPaths.has(src)) {
  3716. // imgPaths.add(src);
  3717. // imgPromises.push(imageFetch(src));
  3718. // }
  3719. // }
  3720. // }
  3721. componentDefaultAttributes.set(connectedComponent, getAttributes(connectedComponent));
  3722. return entry;
  3723. }
  3724.  
  3725. // const pt3 = performance.now();
  3726. // const newRenderedComponents = await Promise.all(newComponentsEntries.map((entry) => {
  3727. // return typeof entry === 'object' && !(entry instanceof Node) ? Promise.resolve(entry).then(pnForRenderNewItem) : entry;
  3728. // }));
  3729. const newRenderedComponents = isRenderListEmpty ? [] : await executeTaskBatch(newComponentsEntries.map(entry => ({
  3730. entry,
  3731. fn(task) {
  3732. const { entry } = task;
  3733. return typeof entry === 'object' && !(entry instanceof Node) ? pnForRenderNewItem(entry) : entry;
  3734. }
  3735. })));
  3736. // const pt4 = performance.now();
  3737.  
  3738.  
  3739. // console.log('xxss' , pt2-pt1, pt4-pt3)
  3740.  
  3741.  
  3742. // wait for network cached images loading
  3743. // let trialMax = 4;
  3744. // while (trialMax--) {
  3745. // wme.data = `${(wme.data & 7) + 1}`;
  3746. // await wmp;
  3747. // if (pDivResourceEventCountLast === pDivResourceEventCount) break;
  3748. // pDivResourceEventCountLast = pDivResourceEventCount;
  3749. // }
  3750.  
  3751. this.flushRenderStamperComponentBindings_(); // ensure all deferred flush render tasks clear.
  3752.  
  3753. // imgPromises.push(imageFetch('data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'));
  3754. if (imgPromises.length > 0) {
  3755. const pr1 = Promise.all(imgPromises).catch(e => { });
  3756. const pr2 = autoTimerFn();
  3757. await Promise.race([pr1, pr2]).catch(e => { });
  3758. imgPaths.clear();
  3759. imgPromises.length = 0;
  3760. }
  3761. if (imgPreloadPr) await imgPreloadPr;
  3762.  
  3763. // const batching = [];
  3764. // let j = 0;
  3765. // let elNode;
  3766.  
  3767. const sideProcesses = [];
  3768.  
  3769. const removeStampNode_ = (elNode) => {
  3770.  
  3771. const elm = elNode;
  3772. const cnt = insp(elm);
  3773. let elemCount1 = elm.querySelectorAll('yt-img-shadow').length;
  3774.  
  3775. const elParent = elm.parentNode;
  3776. if (elm.__requestRemovalAt003__) {
  3777. elm.__requestRemovalAt003__ = 0;
  3778. } else {
  3779. if (cnt.requestRemoval) cnt.requestRemoval();
  3780. }
  3781. try {
  3782. (elParent.__domApi || elParent).removeChild(elm);
  3783. } catch (e) { }
  3784. const frag = document.createDocumentFragment();
  3785. frag.appendChild(elm);
  3786.  
  3787. const componentName = elm.nodeName.toLowerCase();
  3788. let wmList = wmRemoved.get(componentName);
  3789. if (!wmList) {
  3790. wmList = document.createDocumentFragment();
  3791. wmRemoved.set(componentName, wmList);
  3792. }
  3793. const data = cnt.data;
  3794. if (data) renderMap.delete(cnt.data);
  3795.  
  3796. let elemCount2 = elm.querySelectorAll('yt-img-shadow').length;
  3797.  
  3798. const [p1, p2] = [reuseFixDataViewModel(elm), reuseFixYtIconRendering(elm)];
  3799.  
  3800. sideProcesses.push(p1);
  3801. sideProcesses.push(p2);
  3802.  
  3803. if (!window.__fixTemplateReuse1058__ && elemCount1 !== elemCount2) return; // cannot reuse
  3804.  
  3805. Promise.all([elm, wmList, p1, p2]).then((r) => {
  3806. const [elm, wmList] = r;
  3807. wmList.appendChild(elm);
  3808. });
  3809. }
  3810.  
  3811. // const removeStampNode = async () => {
  3812.  
  3813. // removedCounter++;
  3814.  
  3815. // const nextElm = nextComponentSiblingFn(elNode);
  3816. // const elmId = elNode.id;
  3817. // removeStampNode_(elNode);
  3818. // // const dzid = this.getAttribute('dz-component-id');
  3819. // // ---- no-cache ----
  3820. // // try{
  3821. // // elm.remove();
  3822. // // }catch(e){}
  3823. // // ---- no-cache ----
  3824.  
  3825. // if (cTag === 'visibleItems') {
  3826. // sideProcesses.push(onVisibleItemStampNodeRemoval(elmId));
  3827. // }
  3828.  
  3829. // j++;
  3830. // elNode = nextElm;
  3831.  
  3832. // }
  3833.  
  3834. // if (typeof Polymer !== "undefined" && typeof Polymer.flush === "function") {
  3835. // // clear all pending rendering first
  3836. // await stackMarcoTask(async () => {
  3837. // Polymer.flush();
  3838. // });
  3839. // }
  3840.  
  3841. // main UI thread - DOM modification
  3842. await new Promise((resolveDM) => {
  3843. nextBrowserTick_(() => {
  3844.  
  3845. const isAtBottom = this.atBottom === true;
  3846. // if (ENABLE_OVERFLOW_ANCHOR && isAtBottom) {
  3847. // shouldScrollAfterFlush = true;
  3848. // }
  3849.  
  3850.  
  3851. const tasks = [];
  3852. let fragAppend = document.createDocumentFragment();
  3853. let shouldManualScroll = null;
  3854. let scrollTop1 = null, scrollTop2 = null;
  3855.  
  3856. const taskFn = {
  3857. remove: (task) => {
  3858.  
  3859. const { elNode } = task;
  3860.  
  3861. removedCounter++;
  3862.  
  3863. const elmId = elNode.id;
  3864. removeStampNode_(elNode);
  3865. // const dzid = this.getAttribute('dz-component-id');
  3866. // ---- no-cache ----
  3867. // try{
  3868. // elm.remove();
  3869. // }catch(e){}
  3870. // ---- no-cache ----
  3871.  
  3872. if (isMessageListRendering) {
  3873. sideProcesses.push(onVisibleItemStampNodeRemoval(elmId));
  3874. }
  3875.  
  3876. return 2
  3877.  
  3878. },
  3879. append: (task) => {
  3880.  
  3881. if (!fragAppend) return;
  3882.  
  3883. const { newNode, nodeAfter, parentNode, L, H } = task;
  3884.  
  3885. fragAppend.appendChild(newNode);
  3886.  
  3887.  
  3888. const itemScrollerX = (isMessageListRendering && isAtBottom) ? this.itemScroller : null;
  3889.  
  3890.  
  3891. if (itemScrollerX) {
  3892. if (scrollTop1 === null) scrollTop1 = itemScrollerX.scrollTop;
  3893. }
  3894.  
  3895. if (nodeAfter) {
  3896. (parentNode.__domApi || parentNode).insertBefore(fragAppend, nodeAfter);
  3897. } else {
  3898. (parentNode.__domApi || parentNode).appendChild(fragAppend);
  3899. }
  3900.  
  3901. this.deferRenderStamperBinding_(newNode, L, H);
  3902. this.flushRenderStamperComponentBindings_();
  3903.  
  3904.  
  3905. // nodeAfter ? nodeAfter.insertAdjacentElement('beforebegin', newNode) : parentNode.insertAdjacentElement('beforeend', newNode);
  3906. const connectedComponent = newNode;
  3907. const cnt = insp(connectedComponent);
  3908. renderMap.set(cnt.data, mWeakRef(connectedComponent));
  3909. // mutationDelayedRefreshData(cnt); // not included to sideProcesses
  3910. addedCounter++;
  3911.  
  3912. if (isTickerRendering) {
  3913. sideProcesses.push(onTickerItemStampNodeAdded());
  3914. }
  3915.  
  3916. if (itemScrollerX) {
  3917. if (scrollTop2 === null) scrollTop2 = itemScrollerX.scrollTop;
  3918. if (shouldManualScroll === null) shouldManualScroll = (scrollTop1 >= 0 && scrollTop2 >= 0 && Math.abs(scrollTop2 - scrollTop1) < 6);
  3919. if (shouldManualScroll) {
  3920. itemScrollerX.scrollTop = scrollTop2 + 16777216;
  3921. }
  3922. }
  3923.  
  3924. return 1
  3925. }
  3926. }
  3927.  
  3928. {
  3929. const indexMap = new WeakMap();
  3930. // let index = 0;
  3931.  
  3932. if (!isRenderListEmpty) {
  3933. for (let elNode_ = firstComponentChildFn(listDom), index = 0; elNode_ instanceof Node; elNode_ = nextComponentSiblingFn(elNode_)) {
  3934. indexMap.set(elNode_, index++);
  3935. }
  3936. }
  3937.  
  3938.  
  3939.  
  3940. const keepIndices = new Array(renderNodeCount);
  3941. let keepIndicesLen = 0, lastKeepIndex = -1, requireSort = false;
  3942. for (let i = 0, l = newRenderedComponents.length; i < l; i++) {
  3943. const entry = newRenderedComponents[i];
  3944. if (entry instanceof Node) {
  3945. const index = indexMap.get(entry);
  3946. keepIndices[keepIndicesLen++] = [index, entry];
  3947. if (index > lastKeepIndex) lastKeepIndex = index;
  3948. else requireSort = true;
  3949. }
  3950. }
  3951. keepIndices.length = keepIndicesLen;
  3952. if (requireSort) keepIndices.sort((a, b) => a[0] - b[0]);
  3953. let dk = 0;
  3954.  
  3955. let j = 0;
  3956. let elNode;
  3957.  
  3958. elNode = firstComponentChildFn(listDom);
  3959.  
  3960. if (!isRenderListEmpty) {
  3961. for (const rcEntry of newRenderedComponents) {
  3962. const index = indexMap.get(rcEntry);
  3963. if (typeof index === 'number') {
  3964. const indexEntry = keepIndices[dk++];
  3965. const [dIdx, dNode] = indexEntry;
  3966. indexMap.delete(rcEntry);
  3967. const idx = dIdx;
  3968. while (j < idx && elNode) {
  3969. tasks.push({
  3970. type: 'remove',
  3971. elNode,
  3972. fn: taskFn.remove
  3973. });
  3974. elNode = nextComponentSiblingFn(elNode);
  3975. j++;
  3976. }
  3977. if (j === idx) {
  3978. if (elNode) {
  3979. // if (dNode !== elNode) tasks.push({
  3980. // type: 'swap',
  3981. // earlyNode: indexEntry[1],
  3982. // laterNode: elNode
  3983. // });
  3984. elNode = nextComponentSiblingFn(elNode);
  3985. j++;
  3986. } else {
  3987. console.warn('elNode is not available?', renderList, addedCount0, removedCount0, j, idx);
  3988. }
  3989. }
  3990. } else if (rcEntry instanceof Node) {
  3991. // interruped by the external like clearList
  3992.  
  3993. tasks.push({
  3994. type: 'remove',
  3995. elNode: rcEntry,
  3996. fn: taskFn.remove
  3997. });
  3998.  
  3999. } else {
  4000. const [item, L, H, connectedComponent] = rcEntry;
  4001.  
  4002. tasks.push({
  4003. type: 'append',
  4004. newNode: connectedComponent,
  4005. nodeAfter: elNode,
  4006. parentNode: listDom,
  4007. item, L, H,
  4008. fn: taskFn.append
  4009. });
  4010.  
  4011. }
  4012.  
  4013. }
  4014. }
  4015.  
  4016. while (elNode) {
  4017.  
  4018. tasks.push({
  4019. type: 'remove',
  4020. elNode,
  4021. fn: taskFn.remove
  4022. });
  4023. elNode = nextComponentSiblingFn(elNode);
  4024.  
  4025. }
  4026.  
  4027. }
  4028.  
  4029. if (tasks.length >= 1) {
  4030. executeTaskBatch(tasks).then(() => {
  4031. fragAppend = null;
  4032. resolveDM();
  4033. }).catch(console.warn);
  4034. }
  4035.  
  4036. });
  4037. }).catch(console.warn);
  4038.  
  4039. {
  4040. const arr = this[cTag];
  4041. let b = 0;
  4042. b = b | this._setPendingPropertyOrPath(`${cTag}.splices`, {}, true, true);
  4043. b = b | this._setPendingPropertyOrPath(`${cTag}.length`, arr.length, true, true);
  4044. b && this._invalidateProperties();
  4045. }
  4046.  
  4047. // this.flushRenderStamperComponentBindings_(); // just in case...
  4048.  
  4049. await Promise.all(sideProcesses);
  4050.  
  4051. const detail = {
  4052. container: listDom
  4053. };
  4054. this.stampDom[cTag].events && this.hostElement.dispatchEvent(new CustomEvent("yt-rendererstamper-finished", {
  4055. bubbles: !0,
  4056. cancelable: !1,
  4057. composed: !0,
  4058. detail
  4059. }));
  4060. detail.container = null;
  4061.  
  4062. // if (typeof Polymer !== "undefined" && typeof Polymer.flush === "function") {
  4063. // // clear all remaining rendering before promise resolve
  4064. // await stackMarcoTask(async () => {
  4065. // Polymer.flush();
  4066. // });
  4067. // }
  4068.  
  4069. }
  4070.  
  4071. // proceedStampDomArraySplices371_ // proceedStampDomArraySplices381_
  4072. cProto[key] = function (cTag, cId, indexSplice) {
  4073. // console.log('proceedStampDomArraySplices_')
  4074. // assume no error -> no try catch (performance consideration)
  4075. const { index, addedCount, removed } = indexSplice;
  4076. const removedCount = removed ? removed.length : indexSplice.removedCount;
  4077. indexSplice = null;
  4078. if (!addedCount && !removedCount) {
  4079. console.warn('proceedStampDomArraySplices_', 'Error 001');
  4080. return false;
  4081. }
  4082. // const streamArr = this[cTag];
  4083. if (!this.ec389) {
  4084. if (this.ec389a || this.ec389r) {
  4085. console.warn('proceedStampDomArraySplices_', 'Error 002');
  4086. return false;
  4087. }
  4088. this.ec389 = true;
  4089. this.ec389a = 0;
  4090. this.ec389r = 0;
  4091. }
  4092. const shouldExecute = !this.ec389a && !this.ec389r;
  4093.  
  4094. this.ec389a += addedCount;
  4095. this.ec389r += removedCount;
  4096.  
  4097. if (shouldExecute) {
  4098.  
  4099. // let shouldScrollAfterFlush = false;
  4100. const pr00 = this.ec389pr;
  4101. const ec389pr = this.ec389pr = this[fnKeyH](cTag, cId, pr00).catch(console.warn);
  4102.  
  4103. if (cTag === 'visibleItems') {
  4104. this.prDelay288 = ec389pr;
  4105. // this.hasUserJustInteracted12_ = (this.hasUserJustInteracted11_ || (() => false));
  4106.  
  4107. // the first microtask after promise resolved
  4108. // YYYYYYY
  4109. // ec389pr.then(async () => {
  4110. // if (shouldScrollAfterFlush) {
  4111. // if (this.atBottom === false && this.allowScroll === true && !this.hasUserJustInteracted12_()) this.scrollToBottom_();
  4112. // wme.data = `${(wme.data & 7) + 1}`;
  4113. // await wmp;
  4114. // if (this.atBottom === false && this.allowScroll === true && !this.hasUserJustInteracted12_()) this.scrollToBottom_();
  4115. // }
  4116. // });
  4117.  
  4118. }
  4119.  
  4120. }
  4121.  
  4122. return true;
  4123. }
  4124.  
  4125.  
  4126.  
  4127.  
  4128.  
  4129. }
  4130.  
  4131.  
  4132. class RAFHub {
  4133. constructor() {
  4134. /** @type {number} */
  4135. this.startAt = 8170;
  4136. /** @type {number} */
  4137. this.counter = 0;
  4138. /** @type {number} */
  4139. this.rid = 0;
  4140. /** @type {Map<number, FrameRequestCallback>} */
  4141. this.funcs = new Map();
  4142. const funcs = this.funcs;
  4143. /** @type {FrameRequestCallback} */
  4144. this.bCallback = this.mCallback.bind(this);
  4145. this.pClear = () => funcs.clear();
  4146. this.keepRAF = false;
  4147. }
  4148. /** @param {DOMHighResTimeStamp} highResTime */
  4149. mCallback(highResTime) {
  4150. this.rid = 0;
  4151. Promise.resolve().then(this.pClear);
  4152. this.funcs.forEach(func => Promise.resolve(highResTime).then(func).catch(console.warn));
  4153. }
  4154. /** @param {FrameRequestCallback} f */
  4155. request(f) {
  4156. const cid = this.startAt + (this.counter = (this.counter & 1073741823) + 1);
  4157. this.funcs.set(cid, f);
  4158. if (this.rid === 0) this.rid = requestAnimationFrame(this.bCallback);
  4159. return cid;
  4160. }
  4161. /** @param {number} cid */
  4162. cancel(cid) {
  4163. cid = +cid;
  4164. if (cid > 0) {
  4165. if (cid <= this.startAt) {
  4166. return cancelAnimationFrame(cid);
  4167. }
  4168. if (this.rid > 0) {
  4169. this.funcs.delete(cid);
  4170. if (this.funcs.size === 0 && !this.keepRAF) {
  4171. cancelAnimationFrame(this.rid);
  4172. this.rid = 0;
  4173. }
  4174. }
  4175. }
  4176. }
  4177. }
  4178.  
  4179. function basePrefetching() {
  4180.  
  4181. new Promise(resolve => {
  4182.  
  4183. if (document.readyState !== 'loading') {
  4184. resolve();
  4185. } else {
  4186. win.addEventListener("DOMContentLoaded", resolve, false);
  4187. }
  4188.  
  4189. }).then(() => {
  4190. const hostL1 = [
  4191. 'https://www.youtube.com', 'https://googlevideo.com',
  4192. 'https://googleapis.com', 'https://accounts.youtube.com',
  4193. 'https://www.gstatic.com', 'https://ggpht.com',
  4194. 'https://yt3.ggpht.com', 'https://yt4.ggpht.com'
  4195. ];
  4196.  
  4197. const hostL2 = [
  4198. 'https://youtube.com',
  4199. 'https://fonts.googleapis.com', 'https://fonts.gstatic.com'
  4200. ];
  4201.  
  4202. let link = null;
  4203.  
  4204. function kn() {
  4205.  
  4206. link = document.createElement('link');
  4207. if (link.relList && link.relList.supports) {
  4208. 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)
  4209. } else {
  4210. kptPF = 0;
  4211. }
  4212.  
  4213. groupCollapsed("YouTube Super Fast Chat", " | PREFETCH SUPPORTS");
  4214. if (ENABLE_BASE_PREFETCHING) console1.log('dns-prefetch', (kptPF & 1) ? 'OK' : 'NG');
  4215. if (ENABLE_BASE_PREFETCHING) console1.log('preconnect', (kptPF & 2) ? 'OK' : 'NG');
  4216. if (ENABLE_PRELOAD_THUMBNAIL) console1.log('prefetch', (kptPF & 4) ? 'OK' : 'NG');
  4217. if (ENABLE_PRELOAD_THUMBNAIL) console1.log('preload', (kptPF & 16) ? 'OK' : 'NG');
  4218. groupEnd();
  4219.  
  4220. }
  4221.  
  4222. for (const h of hostL1) {
  4223.  
  4224. if (kptPF === null) kn();
  4225. if (ENABLE_BASE_PREFETCHING) {
  4226. // if (kptPF & 1) {
  4227. // linker(link, 'dns-prefetch', h);
  4228. // link = null;
  4229. // }
  4230. if (kptPF & 2) {
  4231. linker(link, 'preconnect', h);
  4232. link = null;
  4233. }
  4234. }
  4235. }
  4236.  
  4237. for (const h of hostL2) {
  4238. if (kptPF === null) kn();
  4239. if (ENABLE_BASE_PREFETCHING) {
  4240. if (kptPF & 1) {
  4241. linker(link, 'dns-prefetch', h);
  4242. link = null;
  4243. }
  4244. }
  4245. }
  4246.  
  4247. })
  4248.  
  4249.  
  4250. }
  4251.  
  4252. if (DO_LINK_PREFETCH) basePrefetching();
  4253.  
  4254. const { notifyPath7081 } = (() => {
  4255. // DO_PARTICIPANT_LIST_HACKS
  4256.  
  4257. const mutexParticipants = new Mutex();
  4258.  
  4259. let uvid = 0;
  4260. let r95dm = 0;
  4261. let c95dm = -1;
  4262.  
  4263. const foundMap = (base, content) => {
  4264. /*
  4265. let lastSearch = 0;
  4266. let founds = base.map(baseEntry => {
  4267. let search = content.indexOf(baseEntry, lastSearch);
  4268. if (search < 0) return false;
  4269. lastSearch = search + 1;
  4270. return true;
  4271. });
  4272. return founds;
  4273. */
  4274. const contentSet = new Set(content);
  4275. const r = base.map(baseEntry => contentSet.has(baseEntry));
  4276. contentSet.clear();
  4277. return r
  4278.  
  4279. }
  4280.  
  4281.  
  4282.  
  4283. let participantsForSpliceWR = null;
  4284.  
  4285. class IndexSpliceEntry {
  4286. /**
  4287. *
  4288. * @param {number} _index
  4289. * @param {number} _addedCount
  4290. * @param {any[]} _removed
  4291. */
  4292. constructor(_index, _addedCount, _removed) {
  4293. this.index = _index;
  4294. this.addedCount = _addedCount;
  4295. this.removed = _removed;
  4296. }
  4297. get __proxy312__() {
  4298. return 1
  4299. }
  4300. get type() {
  4301. return 'splice'
  4302. }
  4303. get object() {
  4304. return kRef(participantsForSpliceWR); // avoid memory leakage
  4305. }
  4306. }
  4307.  
  4308. const spliceIndicesFunc = (beforeParticipants, participants, idsBefore, idsAfter) => {
  4309.  
  4310. let foundsForAfter = foundMap(idsAfter, idsBefore);
  4311. let foundsForBefore = foundMap(idsBefore, idsAfter);
  4312.  
  4313. const nAfter = foundsForAfter.length;
  4314. const nBefore = foundsForBefore.length;
  4315.  
  4316. const indexSplices = [];
  4317. const contentUpdates = [];
  4318. participantsForSpliceWR = null;
  4319. for (let i = 0, j = 0; i < nBefore || j < nAfter;) {
  4320. if (beforeParticipants[i] === participants[j]) {
  4321. i++; j++;
  4322. } else if (idsBefore[i] === idsAfter[j]) {
  4323. // content changed
  4324. contentUpdates.push({ indexI: i, indexJ: j })
  4325. i++; j++;
  4326. } else {
  4327. let addedCount = 0;
  4328. for (let q = j; q < nAfter; q++) {
  4329. if (foundsForAfter[q] === false) addedCount++;
  4330. else break;
  4331. }
  4332. let removedCount = 0;
  4333. for (let q = i; q < nBefore; q++) {
  4334. if (foundsForBefore[q] === false) removedCount++;
  4335. else break;
  4336. }
  4337. if (!addedCount && !removedCount) {
  4338. throw 'ERROR(0xFF32): spliceIndicesFunc';
  4339. }
  4340. const entry = new IndexSpliceEntry(
  4341. j,
  4342. addedCount,
  4343. removedCount >= 1 ? beforeParticipants.slice(i, i + removedCount) : []
  4344. );
  4345. indexSplices.push(entry);
  4346. i += removedCount;
  4347. j += addedCount;
  4348. }
  4349. }
  4350. foundsForBefore = null;
  4351. foundsForAfter = null;
  4352. idsBefore = null;
  4353. idsAfter = null;
  4354. beforeParticipants = null;
  4355. participantsForSpliceWR = indexSplices.length > 0 ? mWeakRef(participants) : null;
  4356. participants = null;
  4357. return { indexSplices, contentUpdates };
  4358.  
  4359. }
  4360.  
  4361. /*
  4362.  
  4363. customElements.get("yt-live-chat-participant-renderer").prototype.notifyPath=function(){ console.log(123); console.log(new Error().stack)}
  4364.  
  4365. VM63631:1 Error
  4366. at customElements.get.notifyPath (<anonymous>:1:122)
  4367. at e.forwardRendererStamperChanges_ (live_chat_polymer.js:4453:35)
  4368. at e.rendererStamperApplyChangeRecord_ (live_chat_polymer.js:4451:12)
  4369. at e.rendererStamperObserver_ (live_chat_polymer.js:4448:149)
  4370. at Object.pu [as fn] (live_chat_polymer.js:1692:118)
  4371. at ju (live_chat_polymer.js:1674:217)
  4372. at a._propertiesChanged (live_chat_polymer.js:1726:122)
  4373. at b._flushProperties (live_chat_polymer.js:1597:200)
  4374. at a._invalidateProperties (live_chat_polymer.js:1718:69)
  4375. at a.notifyPath (live_chat_polymer.js:1741:182)
  4376.  
  4377. */
  4378.  
  4379. function convertToIds(participants) {
  4380. return participants.map(participant => {
  4381. if (!participant || typeof participant !== 'object') {
  4382. console.warn('Error(0xFA41): convertToIds', participant);
  4383. return participant; // just in case
  4384. }
  4385. let keys = Object.keys(participant);
  4386. // liveChatTextMessageRenderer
  4387. // liveChatParticipantRenderer - livestream channel owner [no authorExternalChannelId]
  4388. // liveChatPaidMessageRenderer
  4389. /*
  4390.  
  4391. 'yt-live-chat-participant-renderer' utilizes the following:
  4392. authorName.simpleText: string
  4393. authorPhoto.thumbnails: Object{url:string, width:int, height:int} []
  4394. authorBadges[].liveChatAuthorBadgeRenderer.icon.iconType: string
  4395. authorBadges[].liveChatAuthorBadgeRenderer.tooltip: string
  4396. authorBadges[].liveChatAuthorBadgeRenderer.accessibility.accessibilityData: Object{label:string}
  4397.  
  4398. */
  4399. if (keys.length !== 1) {
  4400. console.warn('Error(0xFA42): convertToIds', participant);
  4401. return participant; // just in case
  4402. }
  4403. let key = keys[0];
  4404. let renderer = (participant[key] || 0);
  4405. let authorName = (renderer.authorName || 0);
  4406. let text = `${authorName.simpleText || authorName.text}`
  4407. let res = participant; // fallback if it is not a vaild entry
  4408. if (typeof text !== 'string') {
  4409. console.warn('Error(0xFA53): convertToIds', participant);
  4410. } else {
  4411. text = `${renderer.authorExternalChannelId || 'null'}|${text || ''}`;
  4412. if (text.length > 1) res = text;
  4413. }
  4414. return res;
  4415. // return renderer?`${renderer.id}|${renderer.authorExternalChannelId}`: '';
  4416. // note: renderer.id will be changed if the user typed something to trigger the update of the participants' record.
  4417. });
  4418. }
  4419.  
  4420. const checkChangeToParticipantRendererContent = CHECK_CHANGE_TO_PARTICIPANT_RENDERER_CONTENT ? (p1, p2) => {
  4421. // just update when content is changed.
  4422. if (p1.authorName !== p2.authorName) return true;
  4423. if (p1.authorPhoto !== p2.authorPhoto) return true;
  4424. if (p1.authorBadges !== p2.authorBadges) return true;
  4425. return false;
  4426. } : (p1, p2) => {
  4427. // keep integrity all the time.
  4428. return p1 !== p2; // always true
  4429. }
  4430.  
  4431. function notifyPath7081(path) { // cnt "yt-live-chat-participant-list-renderer"
  4432.  
  4433. if (PARTICIPANT_UPDATE_ONLY_ONLY_IF_MODIFICATION_DETECTED) {
  4434. if (path !== "participantsManager.participants") {
  4435. return this.__notifyPath5036__.apply(this, arguments);
  4436. }
  4437. if (c95dm === r95dm) return;
  4438. } else {
  4439. const stack = new Error().stack;
  4440. if (path !== "participantsManager.participants" || stack.indexOf('.onParticipantsChanged') < 0) {
  4441. return this.__notifyPath5036__.apply(this, arguments);
  4442. }
  4443. }
  4444.  
  4445. if (uvid > 1e8) uvid = uvid % 100;
  4446. let tid = ++uvid;
  4447.  
  4448.  
  4449. // const cnt = this; // "yt-live-chat-participant-list-renderer"
  4450.  
  4451. const wNode = mWeakRef(this);
  4452.  
  4453. mutexParticipants.lockWith(lockResolve => {
  4454.  
  4455. const cnt = kRef(wNode);
  4456.  
  4457. const participants00 = (((cnt || 0).participantsManager || 0).participants || 0);
  4458.  
  4459. if (tid !== uvid || !cnt || typeof (participants00 || 0).splice !== 'function') {
  4460. lockResolve();
  4461. return;
  4462. }
  4463.  
  4464. let doUpdate = false;
  4465.  
  4466. if (PARTICIPANT_UPDATE_ONLY_ONLY_IF_MODIFICATION_DETECTED) {
  4467.  
  4468. if (!participants00.r94dm) {
  4469. participants00.r94dm = 1;
  4470. r95dm = (r95dm & 1073741823) + 1;
  4471. participants00.push = function () {
  4472. r95dm = (r95dm & 1073741823) + 1;
  4473. return Array.prototype.push.apply(this, arguments);
  4474. }
  4475. participants00.pop = function () {
  4476. r95dm = (r95dm & 1073741823) + 1;
  4477. return Array.prototype.pop.apply(this, arguments);
  4478. }
  4479. participants00.shift = function () {
  4480. r95dm = (r95dm & 1073741823) + 1;
  4481. return Array.prototype.shift.apply(this, arguments);
  4482. }
  4483. participants00.unshift = function () {
  4484. r95dm = (r95dm & 1073741823) + 1;
  4485. return Array.prototype.unshift.apply(this, arguments);
  4486. }
  4487. participants00.splice = function () {
  4488. r95dm = (r95dm & 1073741823) + 1;
  4489. return Array.prototype.splice.apply(this, arguments);
  4490. }
  4491. participants00.sort = function () {
  4492. r95dm = (r95dm & 1073741823) + 1;
  4493. return Array.prototype.sort.apply(this, arguments);
  4494. }
  4495. participants00.reverse = function () {
  4496. r95dm = (r95dm & 1073741823) + 1;
  4497. return Array.prototype.reverse.apply(this, arguments);
  4498. }
  4499. }
  4500.  
  4501. if (c95dm !== r95dm) {
  4502. c95dm = r95dm;
  4503. doUpdate = true;
  4504. }
  4505.  
  4506. } else {
  4507. doUpdate = true;
  4508. }
  4509.  
  4510. if (!doUpdate) {
  4511. lockResolve();
  4512. return;
  4513. }
  4514.  
  4515. const participants = participants00.slice(0);
  4516. const beforeParticipants = beforeParticipantsMap.get(cnt) || [];
  4517. beforeParticipantsMap.set(cnt, participants);
  4518.  
  4519. const resPromise = (async () => {
  4520.  
  4521. if (beforeParticipants.length === 0) {
  4522. // not error
  4523. return 0;
  4524. }
  4525.  
  4526. let countOfElements = cnt.__getAllParticipantsDOMRenderedLength__()
  4527.  
  4528. // console.log(participants.length, doms.length) // different if no requestAnimationFrame
  4529. if (beforeParticipants.length !== countOfElements) {
  4530. // there is somewrong for the cache. - sometimes happen
  4531. return 0;
  4532. }
  4533.  
  4534. const idsBefore = convertToIds(beforeParticipants);
  4535. const idsAfter = convertToIds(participants);
  4536.  
  4537. let { indexSplices, contentUpdates } = spliceIndicesFunc(beforeParticipants, participants, idsBefore, idsAfter);
  4538.  
  4539. let res = 1; // default 1 for no update
  4540.  
  4541. if (indexSplices.length >= 1) {
  4542.  
  4543.  
  4544. // let p2 = participants.slice(indexSplices[0].index, indexSplices[0].index+indexSplices[0].addedCount);
  4545. // let p1 = indexSplices[0].removed;
  4546. // console.log(indexSplices.length, indexSplices ,p1,p2, convertToIds(p1),convertToIds(p2))
  4547.  
  4548. /* folllow
  4549. a.notifyPath(c + ".splices", d);
  4550. a.notifyPath(c + ".length", b.length);
  4551. */
  4552. // stampDomArraySplices_
  4553.  
  4554.  
  4555. await new Promise(resolve => {
  4556. cnt.resolveForDOMRendering781 = resolve;
  4557.  
  4558. cnt.__notifyPath5036__("participantsManager.participants.splices", {
  4559. indexSplices
  4560. });
  4561. indexSplices = null;
  4562. participantsForSpliceWR = null;
  4563. cnt.__notifyPath5036__("participantsManager.participants.length",
  4564. participants.length
  4565. );
  4566.  
  4567. });
  4568.  
  4569. // play safe for the change of 'length'
  4570. await nextBrowserTick_();
  4571.  
  4572. countOfElements = cnt.__getAllParticipantsDOMRenderedLength__();
  4573.  
  4574. const wrongSize = participants.length !== countOfElements
  4575. if (wrongSize) {
  4576. console.warn("ERROR(0xE2C3): notifyPath7081", beforeParticipants.length, participants.length, doms.length)
  4577. return 0;
  4578. }
  4579.  
  4580. res = 2 | 4;
  4581.  
  4582. } else {
  4583.  
  4584. indexSplices = null;
  4585. participantsForSpliceWR = null;
  4586.  
  4587. if (participants.length !== countOfElements) {
  4588. // other unhandled cases
  4589. return 0;
  4590. }
  4591.  
  4592. }
  4593.  
  4594. // participants.length === countOfElements before contentUpdates
  4595. if (contentUpdates.length >= 1) {
  4596. for (const contentUpdate of contentUpdates) {
  4597. let isChanged = checkChangeToParticipantRendererContent(beforeParticipants[contentUpdate.indexI], participants[contentUpdate.indexJ]);
  4598. if (isChanged) {
  4599. cnt.__notifyPath5036__(`participantsManager.participants[${contentUpdate.indexJ}]`);
  4600. res |= 4 | 8;
  4601. }
  4602. }
  4603. }
  4604. contentUpdates = null;
  4605.  
  4606. return res;
  4607.  
  4608.  
  4609. })();
  4610.  
  4611.  
  4612. resPromise.then(async (resValue) => {
  4613. const condition = resValue === 0 ? 1 : (resValue & 4) === 4 ? 2 : 0;
  4614. const isLogRequired = SHOW_PARTICIPANT_CHANGES_IN_CONSOLE && condition > 0;
  4615. isLogRequired && groupCollapsed("Participant List Change", `tid = ${tid}; res = ${resValue}`);
  4616. if (condition === 1) {
  4617. isLogRequired && console1.log("Full Refresh begins");
  4618. await new Promise(resolve => {
  4619. cnt.resolveForDOMRendering781 = resolve;
  4620. cnt.__notifyPath5036__("participantsManager.participants"); // full refresh
  4621. });
  4622. isLogRequired && console1.log("Full Refresh ends");
  4623. } else if (condition === 2) {
  4624. isLogRequired && console1.log(`Number of participants (before): ${beforeParticipants.length}`);
  4625. isLogRequired && console1.log(`Number of participants (after): ${participants.length}`);
  4626. isLogRequired && console1.log(`Total number of rendered participants: ${cnt.__getAllParticipantsDOMRenderedLength__()}`);
  4627. isLogRequired && console1.log(`Participant Renderer Content Updated: ${(resValue & 8) === 8}`);
  4628. // requestAnimationFrame is required to avoid particiant update during DOM changing (stampDomArraySplices_)
  4629. // mutex lock with requestAnimationFrame can also disable participants update in background
  4630. }
  4631. isLogRequired && groupEnd();
  4632. (condition === 2) && (await new Promise(requestAnimationFrame));
  4633. lockResolve();
  4634. });
  4635.  
  4636. });
  4637.  
  4638. }
  4639.  
  4640. return { notifyPath7081 };
  4641.  
  4642. })();
  4643.  
  4644. const whenDefinedMultiple = async (tags) => {
  4645.  
  4646. const sTags = [...new Set(tags)];
  4647. const len = sTags.length;
  4648.  
  4649. const pTags = new Array(len);
  4650. for (let i = 0; i < len; i++) {
  4651. pTags[i] = customElements.whenDefined(sTags[i]);
  4652. }
  4653.  
  4654. await Promise.all(pTags);
  4655. pTags.length = 0;
  4656.  
  4657. return sTags;
  4658.  
  4659. }
  4660.  
  4661. const onRegistryReadyForDataManipulation = () => {
  4662.  
  4663. function dummy5035(a, b, c) { }
  4664. function dummy411(a, b, c) { }
  4665.  
  4666.  
  4667.  
  4668. customElements.whenDefined("yt-live-chat-participant-list-renderer").then(() => {
  4669.  
  4670. if (!DO_PARTICIPANT_LIST_HACKS) return;
  4671.  
  4672. const tag = "yt-live-chat-participant-list-renderer";
  4673. const cProto = getProto(document.createElement(tag));
  4674. if (!cProto || typeof cProto.attached !== 'function') {
  4675. // for _registered, proto.attached shall exist when the element is defined.
  4676. // for controller extraction, attached shall exist when instance creates.
  4677. console.warn(`proto.attached for ${tag} is unavailable.`);
  4678. return;
  4679. }
  4680.  
  4681.  
  4682. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-participant-list-renderer hacks");
  4683.  
  4684. 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'];
  4685. const fgs = {};
  4686. for (const key of fgsArr) fgs[key] = undefined;
  4687.  
  4688. try {
  4689. const EXPERIMENT_FLAGS = ytcfg.data_.EXPERIMENT_FLAGS;
  4690. for (const key of fgsArr) fgs[key] = EXPERIMENT_FLAGS[key];
  4691. } catch (e) { }
  4692. console1.log(`EXPERIMENT_FLAGS: ${JSON.stringify(fgs, null, 2)}`);
  4693.  
  4694. const canDoReplacement = (() => {
  4695. if (typeof cProto.__notifyPath5035__ === 'function' && cProto.__notifyPath5035__.name !== 'dummy5035') {
  4696. console.warn('YouTube Live Chat Tamer is running.');
  4697. return;
  4698. }
  4699.  
  4700. if (typeof cProto.__attached411__ === 'function' && cProto.__attached411__.name !== 'dummy411') {
  4701. console.warn('YouTube Live Chat Tamer is running.');
  4702. return;
  4703. }
  4704.  
  4705. cProto.__notifyPath5035__ = dummy5035 // just to against Live Chat Tamer
  4706. cProto.__attached411__ = dummy411 // just to against Live Chat Tamer
  4707.  
  4708. if (typeof cProto.flushRenderStamperComponentBindings_ !== 'function' || cProto.flushRenderStamperComponentBindings_.length !== 0) {
  4709. console.warn("ERROR(0xE355): cProto.flushRenderStamperComponentBindings_ not found");
  4710. return;
  4711. }
  4712.  
  4713. if (typeof cProto.flushRenderStamperComponentBindings66_ === 'function') {
  4714. console.warn("ERROR(0xE356): cProto.flushRenderStamperComponentBindings66_");
  4715. return;
  4716. }
  4717.  
  4718. if (typeof cProto.__getAllParticipantsDOMRenderedLength__ === 'function') {
  4719. console.warn("ERROR(0xE357): cProto.__getAllParticipantsDOMRenderedLength__");
  4720. return;
  4721. }
  4722. return true;
  4723. })();
  4724.  
  4725. console1.log(`Data Manipulation Boost = ${canDoReplacement}`);
  4726.  
  4727. assertor(() => fnIntegrity(cProto.attached, '0.32.22')) // just warning
  4728. if (typeof cProto.flushRenderStamperComponentBindings_ === 'function') {
  4729. const fiRSCB = fnIntegrity(cProto.flushRenderStamperComponentBindings_);
  4730. console1.log(`flushRenderStamperComponentBindings_ ### ${fiRSCB} ###`);
  4731. } else {
  4732. console1.log("flushRenderStamperComponentBindings_ - not found");
  4733. }
  4734. // assertor(() => fnIntegrity(cProto.flushRenderStamperComponentBindings_, '0.386.233')) // just warning
  4735.  
  4736. if (typeof cProto.flushRenderStamperComponentBindings_ === 'function') {
  4737. cProto.flushRenderStamperComponentBindings66_ = cProto.flushRenderStamperComponentBindings_;
  4738. cProto.flushRenderStamperComponentBindings_ = function () {
  4739. // console.log('flushRenderStamperComponentBindings_')
  4740. this.flushRenderStamperComponentBindings66_();
  4741. if (this.resolveForDOMRendering781) {
  4742. this.resolveForDOMRendering781();
  4743. this.resolveForDOMRendering781 = null;
  4744. }
  4745. };
  4746. }
  4747.  
  4748. cProto.__getAllParticipantsDOMRenderedLength__ = function () {
  4749. const container = ((this || 0).$ || 0).participants;
  4750. if (!container) return 0;
  4751. return HTMLElement_.prototype.querySelectorAll.call(container, 'yt-live-chat-participant-renderer').length;
  4752. }
  4753.  
  4754. const onPageElements = [...document.querySelectorAll('yt-live-chat-participant-list-renderer:not(.n9fJ3)')];
  4755.  
  4756. cProto.__attached412__ = cProto.attached;
  4757. const fpPList = function (hostElement) {
  4758. const cnt = insp(hostElement);
  4759. if (beforeParticipantsMap.has(cnt)) return;
  4760. hostElement.classList.add('n9fJ3');
  4761.  
  4762. assertor(() => (cnt.__dataEnabled === true && cnt.__dataReady === true));
  4763. if (typeof cnt.notifyPath !== 'function' || typeof cnt.__notifyPath5036__ !== 'undefined') {
  4764. console.warn("ERROR(0xE318): yt-live-chat-participant-list-renderer")
  4765. return;
  4766. }
  4767.  
  4768. groupCollapsed("Participant List attached", "");
  4769. cnt.__notifyPath5036__ = cnt.notifyPath
  4770. const participants = ((cnt.participantsManager || 0).participants || 0);
  4771. assertor(() => (participants.length > -1 && typeof participants.slice === 'function'));
  4772. console1.log(`initial number of participants: ${participants.length}`);
  4773. const newParticipants = (participants.length >= 1 && typeof participants.slice === 'function') ? participants.slice(0) : [];
  4774. beforeParticipantsMap.set(cnt, newParticipants);
  4775. cnt.notifyPath = notifyPath7081;
  4776. console1.log(`CHECK_CHANGE_TO_PARTICIPANT_RENDERER_CONTENT = ${CHECK_CHANGE_TO_PARTICIPANT_RENDERER_CONTENT}`);
  4777. groupEnd();
  4778. }
  4779. cProto.attached = function () {
  4780. fpPList(this.hostElement || this);
  4781. this.__attached412__.apply(this, arguments);
  4782. };
  4783.  
  4784.  
  4785. if (ENABLE_FLAGS_MAINTAIN_STABLE_LIST_FOR_PARTICIPANTS_LIST) {
  4786.  
  4787. /** @type {boolean | (()=>boolean)} */
  4788. let toUseMaintainStableList = USE_MAINTAIN_STABLE_LIST_ONLY_WHEN_KS_FLAG_IS_SET ? (() => ytcfg.data_.EXPERIMENT_FLAGS.kevlar_should_maintain_stable_list === true) : true;
  4789. if (typeof cProto.stampDomArray_ === 'function' && cProto.stampDomArray_.length === 6 && !cProto.stampDomArray_.nIegT && !cProto.stampDomArray66_) {
  4790.  
  4791. let lastMessageDate = 0;
  4792. cProto.stampDomArray66_ = cProto.stampDomArray_;
  4793.  
  4794. cProto.stampDomArray_ = function (...args) {
  4795. if (args[0] && args[0].length > 0 && args[1] === "participants" && args[2] && args[3] === true && !args[5]) {
  4796. if (typeof toUseMaintainStableList === 'function') {
  4797. toUseMaintainStableList = toUseMaintainStableList();
  4798. }
  4799. args[5] = toUseMaintainStableList;
  4800. let currentDate = Date.now();
  4801. if (currentDate - lastMessageDate > 440) {
  4802. lastMessageDate = currentDate;
  4803. console.log('maintain_stable_list for participants list', toUseMaintainStableList);
  4804. }
  4805. }
  4806. return this.stampDomArray66_.apply(this, args);
  4807. }
  4808.  
  4809. cProto.stampDomArray_.nIegT = 1;
  4810.  
  4811. }
  4812. console1.log(`ENABLE_FLAGS_MAINTAIN_STABLE_LIST_FOR_PARTICIPANTS_LIST - OK`);
  4813. } else {
  4814. console1.log(`ENABLE_FLAGS_MAINTAIN_STABLE_LIST_FOR_PARTICIPANTS_LIST - NG`);
  4815. }
  4816.  
  4817. groupEnd();
  4818.  
  4819. if (onPageElements.length >= 1) {
  4820. for (const s of onPageElements) {
  4821. if (insp(s).isAttached === true) {
  4822. fpPList(s);
  4823. }
  4824. }
  4825. }
  4826.  
  4827. }).catch(console.warn);
  4828.  
  4829. };
  4830.  
  4831. if (DO_PARTICIPANT_LIST_HACKS) {
  4832. promiseForCustomYtElementsReady.then(onRegistryReadyForDataManipulation);
  4833. }
  4834.  
  4835.  
  4836.  
  4837. const rafHub = (ENABLE_RAF_HACK_TICKERS || ENABLE_RAF_HACK_DOCKED_MESSAGE || ENABLE_RAF_HACK_INPUT_RENDERER || ENABLE_RAF_HACK_EMOJI_PICKER) ? new RAFHub() : null;
  4838.  
  4839. const transitionEndHooks = new WeakSet();
  4840. const transitionEndAfterFnSimple = new WeakMap();
  4841. let transitionEndAfterFnSimpleEnable = 0;
  4842. // let prevTransitionClosing = null;
  4843.  
  4844. const passiveCapture = typeof IntersectionObserver === 'function' ? { capture: true, passive: true } : true;
  4845.  
  4846.  
  4847. const transitionEndAfterFn = (evt) => {
  4848. if (transitionEndAfterFnSimpleEnable > 0 && evt.propertyName && !evt.pseudoElement) {
  4849. const elm = evt.target;
  4850. const f = transitionEndAfterFnSimple.get(elm);
  4851. if (f) {
  4852. transitionEndAfterFnSimple.delete(elm);
  4853. f.resolve(evt.propertyName);
  4854. }
  4855. }
  4856. };
  4857.  
  4858. const fixChildrenIssue = !!fixChildrenIssue801;
  4859. if (fixChildrenIssue && typeof Object.getOwnPropertyDescriptor === 'function' && typeof Proxy !== 'undefined') {
  4860. let fixChildrenIssue_status = false;
  4861. const divProto = HTMLDivElement.prototype;
  4862. const polymerControllerSetData3 = function (c, d, e) {
  4863. return insp(this).set(c, d, e);
  4864. }
  4865. const polymerControllerSetData2 = function (c, d) {
  4866. return insp(this).set(c, d);
  4867. }
  4868. const dummyFn = function () {
  4869. console.log('dummyFn', ...arguments);
  4870. };
  4871.  
  4872. const wm44 = new Map();
  4873. function unPolymerSet(elem) {
  4874. const is = elem.is;
  4875. if (is && !elem.set) {
  4876. let rt = wm44.get(is);
  4877. if (!rt) {
  4878. rt = 1;
  4879. const cnt = insp(elem);
  4880. if (cnt !== elem && cnt && typeof cnt.set === 'function') {
  4881. const pcSet = cnt.constructor.prototype.set;
  4882. if (pcSet && typeof pcSet === 'function' && pcSet.length === 3) {
  4883. rt = polymerControllerSetData3;
  4884. } else if (pcSet && typeof pcSet === 'function' && pcSet.length === 2) {
  4885. rt = polymerControllerSetData2;
  4886. }
  4887. }
  4888. wm44.set(is, rt);
  4889. }
  4890. if (typeof rt === 'function') {
  4891. elem.set = rt;
  4892. } else {
  4893. elem.set = dummyFn;
  4894. }
  4895. }
  4896. }
  4897. if (!divProto.__children577__ && !divProto.__children578__) {
  4898.  
  4899. const dp = Object.getOwnPropertyDescriptor(Element.prototype, 'children');
  4900. const dp2 = Object.getOwnPropertyDescriptor(HTMLElement_.prototype, 'children');
  4901. const dp3 = Object.getOwnPropertyDescriptor(divProto, 'children');
  4902.  
  4903. if (dp && dp.configurable === true && dp.enumerable === true && typeof dp.get === 'function' && !dp2 && !dp3) {
  4904.  
  4905. if (divProto instanceof HTMLElement_ && divProto instanceof Element) {
  4906.  
  4907. let m = Object.assign({}, dp);
  4908. divProto.__children577__ = dp.get;
  4909. divProto.__children578__ = function () {
  4910. if (this.__children803__) return this.__children803__;
  4911. if (this.__children801__) {
  4912. let arr = [];
  4913. for (let elem = this.firstElementChild; elem !== null; elem = elem.nextElementSibling) {
  4914. if (elem.is) {
  4915. unPolymerSet(elem);
  4916. arr.push(elem);
  4917. }
  4918. }
  4919. if (this.__children801__ === 2) this.__children803__ = arr;
  4920. return arr;
  4921. }
  4922. return 577;
  4923. };
  4924. m.get = function () {
  4925. const r = this.__children578__();
  4926. if (r !== 577) return r;
  4927. return this.__children577__();
  4928. };
  4929. Object.defineProperty(divProto, 'children', m);
  4930.  
  4931. fixChildrenIssue_status = true;
  4932.  
  4933. }
  4934. }
  4935.  
  4936. }
  4937.  
  4938. if (!fixChildrenIssue_status) {
  4939. console.log('fixChildrenIssue - set NG')
  4940. }
  4941.  
  4942.  
  4943. }
  4944.  
  4945.  
  4946. const watchUserCSS = () => {
  4947.  
  4948. // if (!CSS.supports('contain-intrinsic-size', 'auto var(--wsr94)')) return;
  4949.  
  4950. const getElemFromWR = (nr) => {
  4951. const n = kRef(nr);
  4952. if (n && n.isConnected) return n;
  4953. return null;
  4954. }
  4955.  
  4956. const clearContentVisibilitySizing = () => {
  4957. Promise.resolve().then(() => {
  4958.  
  4959. const e = document.querySelector('#show-more[disabled]');
  4960. let btnShowMoreWR = e ? mWeakRef(e) : null;
  4961.  
  4962. let lastVisibleItemWR = null;
  4963. for (const elm of document.querySelectorAll('[wsr93]')) {
  4964. if (elm.getAttribute('wsr93') === 'visible') lastVisibleItemWR = mWeakRef(elm);
  4965. elm.setAttribute('wsr93', '');
  4966. // custom CSS property --wsr94 not working when attribute wsr93 removed
  4967. }
  4968. foregroundPromiseFn().then(() => {
  4969. const btnShowMore = getElemFromWR(btnShowMoreWR); btnShowMoreWR = null;
  4970. if (btnShowMore) btnShowMore.click();
  4971. else {
  4972. // would not work if switch it frequently
  4973. const lastVisibleItem = getElemFromWR(lastVisibleItemWR); lastVisibleItemWR = null;
  4974. if (lastVisibleItem) {
  4975.  
  4976. Promise.resolve()
  4977. .then(() => lastVisibleItem.scrollIntoView())
  4978. .then(() => lastVisibleItem.scrollIntoView(false))
  4979. .then(() => lastVisibleItem.scrollIntoView({ behavior: "instant", block: "end", inline: "nearest" }))
  4980. .catch(e => { }) // break the chain when method not callable
  4981.  
  4982. }
  4983. }
  4984. });
  4985.  
  4986. }).catch(console.warn);
  4987.  
  4988. }
  4989.  
  4990. const mutObserver = new MutationObserver((mutations) => {
  4991. for (const mutation of mutations) {
  4992. if ((mutation.addedNodes || 0).length >= 1) {
  4993. for (const addedNode of mutation.addedNodes) {
  4994. if (addedNode.nodeName === 'STYLE') {
  4995. clearContentVisibilitySizing();
  4996. return;
  4997. }
  4998. }
  4999. }
  5000. if ((mutation.removedNodes || 0).length >= 1) {
  5001. for (const removedNode of mutation.removedNodes) {
  5002. if (removedNode.nodeName === 'STYLE') {
  5003. clearContentVisibilitySizing();
  5004. return;
  5005. }
  5006. }
  5007. }
  5008. }
  5009. });
  5010.  
  5011. mutObserver.observe(document.documentElement, {
  5012. childList: true,
  5013. subtree: false
  5014. });
  5015. mutObserver.observe(document.head, {
  5016. childList: true,
  5017. subtree: false
  5018. });
  5019. mutObserver.observe(document.body, {
  5020. childList: true,
  5021. subtree: false
  5022. });
  5023.  
  5024. }
  5025.  
  5026.  
  5027. const { lcRendererElm, visObserver } = (() => {
  5028.  
  5029. let lcRendererWR = null;
  5030.  
  5031. const lcRendererElm = () => {
  5032. let lcRenderer = kRef(lcRendererWR);
  5033. if (!lcRenderer || !lcRenderer.isConnected) {
  5034. lcRenderer = document.querySelector('yt-live-chat-item-list-renderer.yt-live-chat-renderer');
  5035. lcRendererWR = lcRenderer ? mWeakRef(lcRenderer) : null;
  5036. }
  5037. return lcRenderer;
  5038. };
  5039.  
  5040.  
  5041. let hasFirstShowMore = false;
  5042. // let lastVisible = null;
  5043.  
  5044. const visObserverFn = (entry) => {
  5045.  
  5046. const target = entry.target;
  5047. if (!target || !target.hasAttribute('wsr93')) return;
  5048. // if(target.classList.contains('dont-render')) return;
  5049. let isVisible = entry.isIntersecting === true && entry.intersectionRatio > 0.5;
  5050. // const h = entry.boundingClientRect.height;
  5051. /*
  5052. if (h < 16) { // wrong: 8 (padding/margin); standard: 32; test: 16 or 20
  5053. // e.g. under fullscreen. the element created but not rendered.
  5054. target.setAttribute('wsr93', '');
  5055. return;
  5056. }
  5057. */
  5058. if (isVisible) {
  5059. // target.style.setProperty('--wsr94', h + 'px');
  5060. target.setAttribute('wsr93', 'visible');
  5061. // lastVisible = mWeakRef(target);
  5062. if (nNextElem(target) === null) {
  5063.  
  5064. // firstVisibleItemDetected = true;
  5065. /*
  5066. if (dateNow() - lastScroll < 80) {
  5067. lastLShow = 0;
  5068. lastScroll = 0;
  5069. Promise.resolve().then(clickShowMore);
  5070. } else {
  5071. lastLShow = dateNow();
  5072. }
  5073. */
  5074. // lastLShow = dateNow();
  5075. } else if (!hasFirstShowMore) { // should more than one item being visible
  5076. // implement inside visObserver to ensure there is sufficient delay
  5077. hasFirstShowMore = true;
  5078. // foregroundPromiseFn().then(() => {
  5079. // // foreground page
  5080. // // page visibly ready -> load the latest comments at initial loading
  5081. // const lcRenderer = lcRendererElm();
  5082. // if (lcRenderer) {
  5083. // nextBrowserTick_(() => {
  5084. // const cnt = insp(lcRenderer);
  5085. // if (cnt.isAttached === false || (cnt.hostElement || cnt).isConnected === false) return;
  5086. // cnt.scrollToBottom_();
  5087. // });
  5088. // }
  5089. // });
  5090. }
  5091. }
  5092. else if (target.getAttribute('wsr93') === 'visible') { // ignore target.getAttribute('wsr93') === '' to avoid wrong sizing
  5093.  
  5094. // target.style.setProperty('--wsr94', h + 'px');
  5095. target.setAttribute('wsr93', 'hidden');
  5096. } // note: might consider 0 < entry.intersectionRatio < 0.5 and target.getAttribute('wsr93') === '' <new last item>
  5097.  
  5098. }
  5099.  
  5100.  
  5101.  
  5102. const visObserver = new IntersectionObserver((entries) => {
  5103.  
  5104. for (const entry of entries) {
  5105.  
  5106. Promise.resolve(entry).then(visObserverFn);
  5107.  
  5108. }
  5109.  
  5110. }, {
  5111. rootMargin: "0px",
  5112. threshold: [0.05, 0.95],
  5113. });
  5114.  
  5115.  
  5116. return { lcRendererElm, visObserver }
  5117.  
  5118.  
  5119. })();
  5120.  
  5121. // let itemsResizeObserverAttached = false;
  5122. // const resizeObserverFallback = new IntersectionObserver((mutation, observer) => {
  5123. // const itemScroller = mutation[0].target;
  5124. // observer.unobserve(itemScroller);
  5125. // if (itemScroller.scrollTop === 0) itemScroller.scrollTop = window.screen.height; // scrollTop changing
  5126. // });
  5127.  
  5128. const itemScrollerResizeObserver = typeof ResizeObserver === 'function' && ENABLE_OVERFLOW_ANCHOR ? new ResizeObserver((mutations) => {
  5129. const mutation = mutations[mutations.length - 1];
  5130. // console.log('resizeObserver', mutation)
  5131. const itemScroller = (mutation || 0).target;
  5132. if (!itemScroller) return;
  5133. const listDom = itemScroller.closest('yt-live-chat-item-list-renderer');
  5134. if (!listDom) return;
  5135. const listCnt = insp(listDom);
  5136. if(listCnt.visibleItems.length === 0) return;
  5137. if (listCnt.atBottom !== true) return;
  5138. // if (itemScroller.scrollTop === 0) {
  5139. itemScroller.scrollTop = 16777216; // scrollTop changing
  5140. // }
  5141. }) : null;
  5142.  
  5143. const { setupMutObserver } = (() => {
  5144.  
  5145.  
  5146. const mutFn = (items) => {
  5147. let seqIndex = -1;
  5148. const elementSet = new Set();
  5149. elementSet.add = elementSet.addOriginal || elementSet.add;
  5150. for (let node = nLastElem(items); node !== null; node = nPrevElem(node)) { // from bottom
  5151. let found = node.hasAttribute('wsr93') ? (node.hasAttribute('yt-chat-item-seq') ? 2 : 1) : 0;
  5152. if (found === 1) node.removeAttribute('wsr93'); // reuse -> wsr93: hidden after re-attach
  5153. if (found === 2) {
  5154. seqIndex = parseInt(node.getAttribute('yt-chat-item-seq'), 10);
  5155. break;
  5156. }
  5157. visObserver.unobserve(node); // reuse case
  5158. node.setAttribute('wsr93', '');
  5159. visObserver.observe(node);
  5160. elementSet.add(node);
  5161. }
  5162. let iter = elementSet.values();
  5163. let i = seqIndex + elementSet.size;
  5164. for (let curr; curr = iter.next().value;) { // from bottom
  5165. curr.setAttribute('yt-chat-item-seq', i % 60);
  5166. curr.classList.add('yt-chat-item-' + ((i % 2) ? 'odd' : 'even'));
  5167. i--;
  5168. }
  5169. iter = null;
  5170. elementSet.clear();
  5171. }
  5172.  
  5173. // const itemsResizeObserver = typeof ResizeObserver === 'function' && 0 ? new ResizeObserver((mutations) => {
  5174. // const mutation = mutations[mutations.length - 1];
  5175. // // console.log('resizeObserver', mutation)
  5176. // const items = (mutation || 0).target;
  5177. // if (!items) return;
  5178. // const listDom = items.closest('yt-live-chat-item-list-renderer');
  5179. // if (!listDom) return;
  5180. // const listCnt = insp(listDom);
  5181. // if (listCnt.atBottom !== true) return;
  5182. // const itemScroller = listCnt.itemScroller || listCnt.$['item-scroller'] || listCnt.querySelector('#item-scroller') || 0;
  5183. // // if (itemScroller.scrollTop === 0) {
  5184. // itemScroller.scrollTop = mutation.contentRect.height; // scrollTop changing
  5185. // // }
  5186. // }) : null;
  5187. // itemsResizeObserverAttached = itemsResizeObserver !== null;
  5188.  
  5189. const mutObserver = new MutationObserver((mutations) => {
  5190. const items = (mutations[0] || 0).target;
  5191. if (!items) return;
  5192. mutFn(items);
  5193. });
  5194.  
  5195. const setupMutObserver = (items) => {
  5196. scrollChatFn = null;
  5197. mutObserver.disconnect();
  5198. mutObserver.takeRecords();
  5199. if (items) {
  5200. if (typeof items.__appendChild932__ === 'function') {
  5201. if (typeof items.appendChild === 'function') items.appendChild = items.__appendChild932__;
  5202. if (typeof items.__shady_native_appendChild === 'function') items.__shady_native_appendChild = items.__appendChild932__;
  5203. }
  5204. mutObserver.observe(items, {
  5205. childList: true,
  5206. subtree: false
  5207. });
  5208. mutFn(items);
  5209.  
  5210.  
  5211. // if (itemsResizeObserver) itemsResizeObserver.observe(items);
  5212.  
  5213. // const isFirstList = firstList;
  5214. // firstList = false;
  5215.  
  5216.  
  5217. if (items && items.nextElementSibling === null) {
  5218. items.parentNode.appendChild(dr(document.createElement('item-anchor')));
  5219. WITH_SCROLL_ANCHOR = true;
  5220. if (ENABLE_OVERFLOW_ANCHOR) {
  5221. items.classList.add('no-anchor');
  5222. nodeParent(items).classList.add('no-anchor'); // required
  5223. }
  5224. }
  5225.  
  5226.  
  5227.  
  5228.  
  5229. if (ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX) {
  5230.  
  5231. (() => {
  5232.  
  5233. const tag = 'yt-iframed-player-events-relay'
  5234. const dummy = document.createElement(tag);
  5235.  
  5236. const cProto = getProto(dummy);
  5237. if (!cProto || !cProto.handlePostMessage_) {
  5238. console.warn(`proto.handlePostMessage_ for ${tag} is unavailable.`);
  5239. return;
  5240. }
  5241.  
  5242. if (typeof cProto.handlePostMessage_ === 'function' && !cProto.handlePostMessage66_ && !cProto.handlePostMessage67_ ) {
  5243.  
  5244. cProto.handlePostMessage66_ = cProto.handlePostMessage_;
  5245.  
  5246. const handlePostMessageAfterPromiseA = (da) => {
  5247.  
  5248. if (!da || typeof da !== 'object') return;
  5249.  
  5250. if ('yt-player-state-change' in da) {
  5251.  
  5252. const qc = da['yt-player-state-change'];
  5253.  
  5254.  
  5255. let isQcChanged = false;
  5256.  
  5257. if (qc === 2) { isQcChanged = qc !== _playerState; _playerState = 2; relayCount = 0; } // paused
  5258. else if (qc === 3) { isQcChanged = qc !== _playerState; _playerState = 3; } // playing
  5259. else if (qc === 1) { isQcChanged = qc !== _playerState; _playerState = 1; } // playing
  5260.  
  5261.  
  5262. if ((isQcChanged) && playerState !== _playerState) {
  5263. playerEventsByIframeRelay = true;
  5264. onPlayStateChangePromise = new Promise((resolve) => {
  5265. const k = _playerState;
  5266. foregroundPromiseFn().then(() => {
  5267. if (k === _playerState && playerState !== _playerState) playerState = _playerState;
  5268. onPlayStateChangePromise = null;
  5269. resolve();
  5270. })
  5271. }).catch(console.warn);
  5272.  
  5273. }
  5274.  
  5275. } else if ('yt-player-video-progress' in da) {
  5276. const vp = da['yt-player-video-progress'];
  5277.  
  5278.  
  5279. relayCount++;
  5280. lastPlayerProgress = vp > 0 ? vp : 0; // no use ?
  5281.  
  5282.  
  5283. if (relayPromise && vp > 0 && relayCount >= 2) {
  5284. if (onPlayStateChangePromise) {
  5285. onPlayStateChangePromise.then(() => {
  5286. relayPromise && relayPromise.resolve();
  5287. relayPromise = null;
  5288. })
  5289. } else {
  5290. relayPromise.resolve();
  5291. relayPromise = null;
  5292. }
  5293. }
  5294.  
  5295. }
  5296.  
  5297. };
  5298.  
  5299. cProto.handlePostMessage67_ = function (a) {
  5300.  
  5301. let da = a.data;
  5302. const wNode = mWeakRef(this);
  5303. // const wData = mWeakRef(da);
  5304.  
  5305. playEventsStack = playEventsStack.then(() => {
  5306.  
  5307. const cnt = kRef(wNode);
  5308. // const da = kRef(wData);
  5309.  
  5310. if (!cnt || !a || !da) return;
  5311. handlePostMessageAfterPromiseA(da);
  5312. da = null;
  5313.  
  5314. const r = cnt.handlePostMessage66_(a);
  5315. a = null;
  5316.  
  5317. }).catch(console.warn);
  5318.  
  5319. }
  5320.  
  5321. const handlePostMessageAfterPromiseB = (da) => {
  5322.  
  5323. const lcr = document.querySelector('yt-live-chat-renderer');
  5324. const psc = document.querySelector("yt-player-seek-continuation");
  5325. if (lcr && psc && lcr.replayBuffer_) {
  5326.  
  5327. const rbProgress = lcr.replayBuffer_.lastVideoOffsetTimeMsec;
  5328. const daProgress = da['yt-player-video-progress'] * 1000
  5329. // document.querySelector('yt-live-chat-renderer').playerProgressChanged_(1e-5);
  5330.  
  5331. const front_ = (lcr.replayBuffer_.replayQueue || 0).front_;
  5332. const back_ = (lcr.replayBuffer_.replayQueue || 0).back_;
  5333.  
  5334. // console.log(deepCopy( front_))
  5335. // console.log(deepCopy( back_))
  5336. // console.log(rbProgress, daProgress, )
  5337. if (front_ && back_ && rbProgress > daProgress && back_.length > 2 && back_.some(e => e && +e.videoOffsetTimeMsec > daProgress) && back_.some(e => e && +e.videoOffsetTimeMsec < daProgress)) {
  5338. // no action
  5339. // console.log('ss1')
  5340. } else if (rbProgress < daProgress + 3400 && rbProgress > daProgress - 1200) {
  5341. // daProgress - 1200 < rbProgress < daProgress + 3400
  5342. // console.log('ss2')
  5343. } else {
  5344.  
  5345. lcr.previousProgressSec = 1E-5;
  5346. // lcr._setIsSeeking(!0),
  5347. lcr.replayBuffer_.clear()
  5348. psc.fireSeekContinuation_(da['yt-player-video-progress']);
  5349. }
  5350.  
  5351. }
  5352.  
  5353.  
  5354. };
  5355.  
  5356. cProto.handlePostMessage_ = function (a) {
  5357.  
  5358. let da = (a || 0).data || 0;
  5359. const wNode = mWeakRef(this);
  5360.  
  5361. if (typeof da !== 'object') return;
  5362.  
  5363. if (waitForInitialDataCompletion === 1) return;
  5364.  
  5365. if (!isPlayProgressTriggered) {
  5366. isPlayProgressTriggered = true; // set once
  5367.  
  5368. if ('yt-player-video-progress' in da) {
  5369. waitForInitialDataCompletion = 1;
  5370.  
  5371. const wrapWith = (data) => {
  5372. const { origin } = a;
  5373. return {
  5374. origin,
  5375. data
  5376. };
  5377. }
  5378.  
  5379. this.handlePostMessage67_(wrapWith({
  5380. "yt-iframed-parent-ready": true
  5381. }));
  5382.  
  5383.  
  5384. playEventsStack = playEventsStack.then(() => {
  5385.  
  5386. const cnt = kRef(wNode);
  5387.  
  5388. if (!cnt || !a || !da) return;
  5389.  
  5390. handlePostMessageAfterPromiseB(da);
  5391. da = null;
  5392.  
  5393. waitForInitialDataCompletion = 2;
  5394.  
  5395. const r = cnt.handlePostMessage_(a); // isPlayProgressTriggered is set
  5396. a = null;
  5397.  
  5398. }).catch(console.warn);
  5399.  
  5400. return;
  5401.  
  5402. }
  5403.  
  5404. }
  5405.  
  5406. this.handlePostMessage67_(a);
  5407.  
  5408. }
  5409.  
  5410. }
  5411.  
  5412.  
  5413. })();
  5414.  
  5415. }
  5416.  
  5417.  
  5418. }
  5419. }
  5420.  
  5421. return { setupMutObserver };
  5422.  
  5423.  
  5424.  
  5425. })();
  5426.  
  5427. const setupEvents = () => {
  5428. // not called when boost chat is enabled
  5429.  
  5430. // global - currentMouseDown, lastUserInteraction
  5431.  
  5432. let scrollCount = 0;
  5433. let lastScrollCount = -1;
  5434. let lastMouseDown = 0;
  5435.  
  5436. const passiveCapture = typeof IntersectionObserver === 'function' ? { capture: true, passive: true } : true;
  5437.  
  5438. // const delayFlushActiveItemsAfterUserActionK_ = () => {
  5439.  
  5440. // const lcRenderer = lcRendererElm();
  5441. // if (lcRenderer) {
  5442. // const cnt = insp(lcRenderer);
  5443. // if (!cnt.hasUserJustInteracted11_) return;
  5444. // if (cnt.atBottom && cnt.allowScroll && cnt.activeItems_.length >= 1 && cnt.hasUserJustInteracted11_()) {
  5445. // cnt.delayFlushActiveItemsAfterUserAction11_ && cnt.delayFlushActiveItemsAfterUserAction11_();
  5446. // }
  5447. // }
  5448.  
  5449. // }
  5450.  
  5451. const delayFlushActiveItemsAfterUserActionK_ = null;
  5452.  
  5453. document.addEventListener('scroll', (evt) => {
  5454. if (!evt || !evt.isTrusted) return;
  5455. // lastScroll = dateNow();
  5456. scrollCount = (scrollCount & 1073741823) + 1;
  5457. }, passiveCapture); // support contain => support passive
  5458.  
  5459. document.addEventListener('wheel', (evt) => {
  5460. if (!evt || !evt.isTrusted) return;
  5461. if (lastScrollCount === scrollCount) return;
  5462. lastScrollCount = scrollCount;
  5463. lastWheel = dateNow();
  5464. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5465. }, passiveCapture); // support contain => support passive
  5466.  
  5467. document.addEventListener('mousedown', (evt) => {
  5468. if (!evt || !evt.isTrusted) return;
  5469. if (((evt || 0).target || 0).id !== 'item-scroller') return;
  5470. lastMouseDown = dateNow();
  5471. currentMouseDown = true;
  5472. lastUserInteraction = lastMouseDown;
  5473. }, passiveCapture);
  5474.  
  5475. document.addEventListener('pointerdown', (evt) => {
  5476. if (!evt || !evt.isTrusted) return;
  5477. if (((evt || 0).target || 0).id !== 'item-scroller') return;
  5478. lastMouseDown = dateNow();
  5479. currentMouseDown = true;
  5480. lastUserInteraction = lastMouseDown;
  5481. }, passiveCapture);
  5482.  
  5483. document.addEventListener('click', (evt) => {
  5484. if (!evt || !evt.isTrusted) return;
  5485. if (((evt || 0).target || 0).id !== 'item-scroller') return;
  5486. lastMouseDown = lastMouseUp = dateNow();
  5487. currentMouseDown = false;
  5488. lastUserInteraction = lastMouseDown;
  5489. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5490. }, passiveCapture);
  5491.  
  5492. document.addEventListener('tap', (evt) => {
  5493. if (!evt || !evt.isTrusted) return;
  5494. if (((evt || 0).target || 0).id !== 'item-scroller') return;
  5495. lastMouseDown = lastMouseUp = dateNow();
  5496. currentMouseDown = false;
  5497. lastUserInteraction = lastMouseDown;
  5498. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5499. }, passiveCapture);
  5500.  
  5501.  
  5502. document.addEventListener('mouseup', (evt) => {
  5503. if (!evt || !evt.isTrusted) return;
  5504. if (currentMouseDown) {
  5505. lastMouseUp = dateNow();
  5506. currentMouseDown = false;
  5507. lastUserInteraction = lastMouseUp;
  5508. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5509. }
  5510. }, passiveCapture);
  5511.  
  5512.  
  5513. document.addEventListener('pointerup', (evt) => {
  5514. if (!evt || !evt.isTrusted) return;
  5515. if (currentMouseDown) {
  5516. lastMouseUp = dateNow();
  5517. currentMouseDown = false;
  5518. lastUserInteraction = lastMouseUp;
  5519. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5520. }
  5521. }, passiveCapture);
  5522.  
  5523. document.addEventListener('touchstart', (evt) => {
  5524. if (!evt || !evt.isTrusted) return;
  5525. lastTouchDown = dateNow();
  5526. currentTouchDown = true;
  5527. lastUserInteraction = lastTouchDown;
  5528. }, passiveCapture);
  5529.  
  5530. document.addEventListener('touchmove', (evt) => {
  5531. if (!evt || !evt.isTrusted) return;
  5532. lastTouchDown = dateNow();
  5533. currentTouchDown = true;
  5534. lastUserInteraction = lastTouchDown;
  5535. }, passiveCapture);
  5536.  
  5537. document.addEventListener('touchend', (evt) => {
  5538. if (!evt || !evt.isTrusted) return;
  5539. if (currentTouchDown) {
  5540. lastTouchUp = dateNow();
  5541. currentTouchDown = false;
  5542. lastUserInteraction = lastTouchUp;
  5543. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5544. }
  5545. }, passiveCapture);
  5546.  
  5547. document.addEventListener('touchcancel', (evt) => {
  5548. if (!evt || !evt.isTrusted) return;
  5549. if (currentTouchDown) {
  5550. lastTouchUp = dateNow();
  5551. currentTouchDown = false;
  5552. lastUserInteraction = lastTouchUp;
  5553. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5554. }
  5555. }, passiveCapture);
  5556.  
  5557.  
  5558. }
  5559.  
  5560. // const getTimestampUsec = (itemRenderer) => {
  5561. // if (itemRenderer && 'timestampUsec' in itemRenderer) {
  5562. // return itemRenderer.timestampUsec
  5563. // } else if (itemRenderer && itemRenderer.showItemEndpoint) {
  5564. // const messageRenderer = ((itemRenderer.showItemEndpoint.showLiveChatItemEndpoint || 0).renderer || 0);
  5565. // if (messageRenderer) {
  5566.  
  5567. // const messageRendererKey = firstObjectKey(messageRenderer);
  5568. // if (messageRendererKey && messageRenderer[messageRendererKey]) {
  5569. // const messageRendererData = messageRenderer[messageRendererKey];
  5570. // if (messageRendererData && 'timestampUsec' in messageRendererData) {
  5571. // return messageRendererData.timestampUsec
  5572. // }
  5573. // }
  5574. // }
  5575. // }
  5576. // return null;
  5577. // }
  5578.  
  5579. const onRegistryReadyForDOMOperations = () => {
  5580.  
  5581. let firstCheckedOnYtInit = false;
  5582.  
  5583. const assertorURL = () => assertor(() => location.pathname.startsWith('/live_chat') && (location.search.indexOf('continuation=') > 0 || location.search.indexOf('v=') > 0));
  5584.  
  5585. const mightFirstCheckOnYtInit = () => {
  5586. if (firstCheckedOnYtInit) return;
  5587. firstCheckedOnYtInit = true;
  5588.  
  5589. if (!document.body || !document.head) return;
  5590. if (!assertorURL()) return;
  5591.  
  5592. addCssManaged();
  5593.  
  5594. let efsContainer = document.getElementById('elzm-fonts-yk75g');
  5595. if (efsContainer && efsContainer.parentNode !== document.body) {
  5596. document.body.appendChild(efsContainer);
  5597. }
  5598.  
  5599. };
  5600.  
  5601. if (!assertorURL()) return;
  5602. // if (!assertor(() => document.getElementById('yt-masthead') === null)) return;
  5603.  
  5604.  
  5605. const { weakWrap } = (() => {
  5606.  
  5607.  
  5608. // const tickerFuncProps = new Set([
  5609. // 'animateShowStats', 'animateHideStats', // updateStatsBarAndMaybeShowAnimationRevised
  5610. // 'collapse', // slideDownNoSelfLeakage
  5611. // 'requestRemoval', // collapseNoSelfLeakage
  5612. // 'setContainerWidth', 'get', 'set', // deletedChangedNoSelfLeakage
  5613. // 'computeAriaLabel', //dataChanged
  5614. // 'startCountdown', // dataChanged [in case]
  5615. // ]);
  5616.  
  5617. // const tickerTags = new Set([
  5618. // "yt-live-chat-ticker-renderer",
  5619. // "yt-live-chat-ticker-paid-message-item-renderer",
  5620. // "yt-live-chat-ticker-paid-sticker-item-renderer",
  5621. // "yt-live-chat-ticker-sponsor-item-renderer"
  5622. // ]);
  5623.  
  5624. // const emptySet = new Set();
  5625.  
  5626.  
  5627.  
  5628. // const tickerFuncPropsFn = (cnt) => {
  5629.  
  5630. // const is = `${cnt.is}`;
  5631.  
  5632. // if (tickerTags.has(is)) {
  5633. // let flg = 0;
  5634. // if (cnt.get && cnt.set) flg |= 1;
  5635. // if (cnt.setContainerWidth && cnt.collapse && cnt.requestRemoval) flg |= 2;
  5636. // if (cnt.animateShowStats && cnt.animateHideStats) flg |= 4;
  5637. // if (cnt.startCountdown) flg |= 8;
  5638. // console.log(`DEBUG flag_6877 = ${flg}`, is);
  5639. // // DEBUG flag_6877 = 15 yt-live-chat-ticker-paid-message-item-renderer
  5640. // // DEBUG flag_6877 = 11 yt-live-chat-ticker-sponsor-item-renderer
  5641. // return tickerFuncProps;
  5642. // }
  5643.  
  5644. // return emptySet;
  5645.  
  5646.  
  5647. // }
  5648.  
  5649.  
  5650. // const smb = Symbol();
  5651. const vmb = 'dtz02' // Symbol(); // return kThis for thisArg
  5652. const vmc = 'dtz04' // Symbol(); // whether it is proxied fn
  5653. const vmd = 'dtz08' // Symbol(); // self fn proxy (fn--fn)
  5654.  
  5655.  
  5656.  
  5657.  
  5658. const thisConversionFn = (thisArg) => {
  5659. if (!thisArg) return null;
  5660. const kThis = thisArg[vmb];
  5661. if (kThis) {
  5662. const ref = kThis.ref;
  5663. return (ref ? kRef(ref) : null) || null;
  5664. }
  5665. return thisArg;
  5666. }
  5667.  
  5668. const pFnHandler2 = {
  5669. get(target, prop) {
  5670. if (prop === vmc) return target;
  5671. return Reflect.get(target, prop);
  5672. },
  5673. apply(target, thisArg, argumentsList) {
  5674. thisArg = thisConversionFn(thisArg);
  5675. if (thisArg) return Reflect.apply(target, thisArg, argumentsList);
  5676. }
  5677. }
  5678.  
  5679.  
  5680. const proxySelfHandler = {
  5681. get(target, prop) {
  5682. if(prop === vmb) return target;
  5683. const ref = target.ref;
  5684. const cnt = kRef(ref);
  5685. if (!cnt) return;
  5686. if (typeof cnt[prop] === 'function' && !cnt[prop][vmc] && !cnt[prop][vmb]) {
  5687. if (!cnt[prop][vmd]) cnt[prop][vmd] = new Proxy(cnt[prop], pFnHandler2);
  5688. return cnt[prop][vmd];
  5689. }
  5690. return cnt[prop];
  5691. },
  5692. set(target, prop, value) {
  5693. const cnt = kRef(target.ref);
  5694. if (!cnt) return true;
  5695. if(value && (value[vmc] || value[vmb])){
  5696. cnt[prop] = value[vmc] || thisConversionFn(value);
  5697. return true;
  5698. }
  5699. cnt[prop] = value;
  5700. return true;
  5701. }
  5702. };
  5703.  
  5704. const weakWrap = (thisArg) => {
  5705. thisArg = thisConversionFn(thisArg);
  5706. if (!thisArg) {
  5707. console.error('thisArg is not found');
  5708. return null;
  5709. }
  5710. return new Proxy({ ref: mWeakRef(thisArg) }, proxySelfHandler);
  5711. }
  5712.  
  5713.  
  5714.  
  5715.  
  5716.  
  5717.  
  5718. if (!window.getComputedStyle533 && typeof window.getComputedStyle === 'function') {
  5719. window.getComputedStyle533 = window.getComputedStyle;
  5720. window.getComputedStyle = function (a, ...args) {
  5721. a = thisConversionFn(a);
  5722. if (a) {
  5723. return getComputedStyle533(a, ...args);
  5724. }
  5725. return null;
  5726. }
  5727. }
  5728.  
  5729.  
  5730.  
  5731.  
  5732.  
  5733.  
  5734.  
  5735. // const fnProxySelf = function (...args) {
  5736. // const cnt = kRef(this.ref);
  5737. // if (cnt) {
  5738. // return cnt[this.prop](...args); // might throw error
  5739. // }
  5740. // }
  5741. // const proxySelfHandler = {
  5742. // get(target, prop) {
  5743. // const ref = target.ref;
  5744. // const cnt = kRef(ref);
  5745. // if (!cnt) return;
  5746. // if (prop === 'dtz06') return 1;
  5747. // if (typeof cnt[prop] === 'function') {
  5748. // if (!target.funcs.has(prop)) {
  5749. // console.warn(`proxy get to function | prop: ${prop} | is: ${cnt.is}`);
  5750. // }
  5751. // if (!target[`$$${prop}$$`]) target[`$$${prop}$$`] = fnProxySelf.bind({ prop, ref });
  5752. // return target[`$$${prop}$$`];
  5753. // }
  5754. // return cnt[prop];
  5755. // },
  5756. // set(target, prop, value) {
  5757. // const cnt = kRef(target.ref);
  5758. // if (!cnt) return true;
  5759. // if (typeof value === 'function') {
  5760. // console.warn(`proxy set to function | prop: ${prop} | is: ${cnt.is}`);
  5761. // cnt[prop] = value;
  5762. // return true;
  5763. // }
  5764. // cnt[prop] = value;
  5765. // return true;
  5766. // }
  5767. // };
  5768.  
  5769. // return { tickerFuncPropsFn, proxySelfHandler }
  5770.  
  5771. return {weakWrap}
  5772. })();
  5773.  
  5774.  
  5775.  
  5776. if (document.documentElement && document.head) {
  5777. addCssManaged();
  5778. }
  5779. // console.log(document.body===null)
  5780.  
  5781. const preprocessChatLiveActionsMap = new WeakSet();
  5782.  
  5783. const toLAObj=(aItem)=>{
  5784.  
  5785. if (!aItem || typeof aItem !== 'object') return false;
  5786. const key = firstObjectKey(aItem); // addLiveChatTickerItemAction
  5787. if (!key) return false;
  5788. let obj = aItem[key];
  5789. if (!obj || typeof obj !== 'object') return false;
  5790.  
  5791. if (typeof (obj.item || 0) == 'object' && firstObjectKey(obj) === 'item') {
  5792. obj = obj.item;
  5793. const key = firstObjectKey(obj);
  5794. if (key) {
  5795. obj = obj[key];
  5796. }
  5797. }
  5798.  
  5799. return obj;
  5800.  
  5801. };
  5802.  
  5803. const groupsK38=[];
  5804.  
  5805.  
  5806. function intervalsOverlap(a1, a2, b1, b2) {
  5807. // Order the intervals without using Math functions
  5808. var startA = a1 <= a2 ? a1 : a2;
  5809. var endA = a1 <= a2 ? a2 : a1;
  5810.  
  5811. var startB = b1 <= b2 ? b1 : b2;
  5812. var endB = b1 <= b2 ? b2 : b1;
  5813.  
  5814. // Check for overlap
  5815. return endA >= startB && endB >= startA;
  5816. }
  5817.  
  5818.  
  5819.  
  5820. const insertIntoSortedArrayA28 = (arr, val) => {
  5821. let left = 0;
  5822. const n = arr.length;
  5823. let right = n;
  5824.  
  5825. // Binary search to find the correct insertion index:
  5826. // We want the first index where arr[index][2] >= val[2].
  5827. while (left < right) {
  5828. const mid = (left + right) >>> 1;
  5829. if (arr[mid][0] < val[0]) {
  5830. left = mid + 1;
  5831. } else {
  5832. right = mid;
  5833. }
  5834. }
  5835.  
  5836. // 'left' is now the insertion index
  5837. left === n ? arr.push(val): arr.splice(left, 0, val);
  5838. };
  5839.  
  5840. function removeNullsInPlace(arr, startI = 0) {
  5841. let insertPos = startI;
  5842. for (let i = startI; i < arr.length; i++) {
  5843. if (arr[i] !== null) {
  5844. insertPos !== i && (arr[insertPos] = arr[i]);
  5845. insertPos++;
  5846. }
  5847. }
  5848. arr.length = insertPos; // Remove the trailing nulls.
  5849. }
  5850.  
  5851. let fir = 0;
  5852.  
  5853. const limitAddition = (a, b) => {
  5854. // Number.MAX_SAFE_INTEGER = 9007199254740991
  5855. // formula = Math.round((a + b) / (1 + a * b / k / k))
  5856. // avoid a*b > 9007199254740991
  5857. // say a, b <= 94800000
  5858. // Consider (x+x) - (x+x) / (1 + x^2 / k^2) < 0.49
  5859. // x < 130095
  5860.  
  5861. const w = 130095;
  5862. if (a < w && b < w) return a + b;
  5863. const k2 = 94800000 * 94800000;
  5864. return Math.round((a + b) / (1 + (a * b) / k2));
  5865. }
  5866.  
  5867. const preprocessChatLiveActions = (arr, ct_) =>{
  5868.  
  5869. if (!ct_) ct_ = Date.now();
  5870.  
  5871. if (!fir) {
  5872.  
  5873. if (!__LCRInjection__) {
  5874. console.error('[yt-chat] preprocessChatLiveActions might fail because of no __LCRInjection__');
  5875. }
  5876.  
  5877. DEBUG_preprocessChatLiveActions && console.log('[yt-chat-debug] 5990', 'preprocessChatLiveActions', arr)
  5878.  
  5879. DEBUG_preprocessChatLiveActions && console.log('[yt-chat-debug] 5991', document.querySelectorAll('yt-live-chat-ticker-renderer #ticker-items [class]').length)
  5880.  
  5881. fir = 1;
  5882. // debugger;
  5883. }
  5884.  
  5885. if (!arr || !arr.length) return arr;
  5886.  
  5887. if (preprocessChatLiveActionsMap.has(arr)) return arr;
  5888. preprocessChatLiveActionsMap.add(arr);
  5889.  
  5890.  
  5891.  
  5892. const ct = ct_;
  5893.  
  5894. let groups_ = null;
  5895.  
  5896. // console.log(1237005);
  5897. // const conversionMap = new WeakMap();
  5898.  
  5899. const additionalInfo = new WeakMap();
  5900.  
  5901. // const adjustmentMap = new Map();
  5902.  
  5903. if (FIX_TIMESTAMP_FOR_REPLAY) {
  5904.  
  5905. // console.log('group02331')
  5906. // console.time('FIX_TIMESTAMP_FOR_REPLAY')
  5907.  
  5908. // const stack = new Array(arr.length);
  5909. // let stackL = 0;
  5910.  
  5911. // const arrHash = new Array(arr.length);
  5912.  
  5913.  
  5914. const groups = groupsK38;
  5915. // const delta = 2.0; // head-to-tail + 0.5 + 0.5 = 1.0 -> symmetric -> 1.0 * 2 = 2.0
  5916. // (2)
  5917. // (1.5, 2.5)
  5918. // (1.51, 2.49)
  5919. // -> (1.01, 2.01) , (1.99, 2.99)
  5920. // 2.99 - 1.01 = 1.98 -> 2
  5921.  
  5922.  
  5923.  
  5924. const pushToGroup = (t0mu)=>{
  5925.  
  5926. const t0auDv = t0mu - 1e6; // t0buDv - t0auDv = 2e6
  5927. const t0buDv = t0mu + 1e6;
  5928. // const t0auEv = t0mu - 2e6;
  5929. // const t0buEv = t0mu + 2e6;
  5930.  
  5931. let groupK = false;
  5932. // let m = -1;
  5933. // let q= 0;
  5934. //const qq =true;
  5935. //qq && console.log('-------')
  5936.  
  5937. let lastRight = null;
  5938. let lastK = null;
  5939. let deletedStartIndex = -1;
  5940.  
  5941. for (let k = 0, kl = groups.length; k < kl; k++) {
  5942.  
  5943. const group = groups[k];
  5944. const [groupStart, groupEnd, gCount] = group;
  5945. //qq && console.log(`-- ${k} ----- ${groupMid} : [${groupStart},${groupEnd}] || C1 = ${t0buEv < groupMid} || C2 = ${t0auEv > groupMid}`);
  5946.  
  5947. // if (t0bsEv < groupMid) continue; // if(t0m + 1.0 < groupMid - 1.0) continue;
  5948. // if (m < 0) m = k;
  5949. // if (t0asEv > groupMid){
  5950. // continue; // if(t0m - 1.0 > groupMid + 1.0) break;
  5951. // }
  5952.  
  5953.  
  5954. // if (m < 0) m = k;
  5955.  
  5956. if (lastRight > groupStart) {
  5957. if (!groupK) {
  5958. // just in case sth wrong
  5959. console.warn('logic ERROR');
  5960. groups[k] = null;
  5961. if(deletedStartIndex < 0) deletedStartIndex = k;
  5962. break;
  5963. } else {
  5964.  
  5965.  
  5966. // GroupA: N_a' = N_a + n_e{1} ; Note n_e is the only way to shift right to cause " (lastRight > groupStart) "
  5967. // GroupB: N_b
  5968. // Merge Group (A) = N_a' + N_b
  5969.  
  5970. // without entry moditification, no overlap
  5971. // this must be due to entry moditifcation
  5972. // entry is already count. so can be skipped after merging
  5973.  
  5974. // for merging, groupA will move to right side but left than groupB, so no overlap to groupC
  5975.  
  5976. const group = groups[lastK];
  5977. const newN = limitAddition(group[2], gCount);
  5978.  
  5979. const factor = gCount / (group[2] + gCount);
  5980.  
  5981. // group[0] = (group[0] * group[2] + groupStart * gCount) / (group[2] + gCount)
  5982. group[0] += (groupStart - group[0]) * factor;
  5983.  
  5984. // group[1] = lastRight = (group[1] * group[2] + groupEnd * gCount) / (group[2] + gCount)
  5985. group[1] += (groupEnd - group[1]) * factor;
  5986.  
  5987. group[2] = newN;
  5988. // no change of lastK
  5989. groups[k] = null;
  5990. if(deletedStartIndex < 0) deletedStartIndex = k;
  5991. continue;
  5992. }
  5993. }
  5994.  
  5995. const minGroupStart = lastRight; // all groupStart, groupEnd >= minGroupStart for k, k+1, ...
  5996. if (t0buDv < minGroupStart) {
  5997. // no overlapping could be possible
  5998. break;
  5999. }
  6000.  
  6001. if (intervalsOverlap(t0auDv, t0buDv, groupStart, groupEnd)) {
  6002.  
  6003. groupK = true;
  6004.  
  6005. // if (t0auDv > groupStart) group[0] = t0auDv;
  6006. // else if (t0buDv < groupEnd) group[1] = t0buDv;
  6007.  
  6008. // const newStart = (groupStart * gCount + t0auDv) / (gCount + 1);
  6009. const newStart = groupStart + (t0auDv - groupStart) * 1 / (gCount + 1);
  6010.  
  6011. if (newStart < lastRight) {
  6012. // n_e{1} will make N_b shift left
  6013.  
  6014. // GroupA: N_a
  6015. // GroupB: N_b
  6016. // Merge Group (A) = N_a + N_b + n_e{1}
  6017.  
  6018. const group = groups[lastK];
  6019. const newN = limitAddition(limitAddition(group[2], gCount), 1);
  6020. const f1 = gCount / (group[2] + gCount + 1);
  6021. const f2 = 1 / (group[2] + gCount + 1);
  6022.  
  6023. // group[0] = (group[0] * group[2] + groupStart * gCount + t0auDv) / (group[2] + gCount + 1);
  6024. group[0] += (groupStart - group[0]) * f1 + (t0auDv - group[0]) * f2;
  6025.  
  6026. // group[1] = lastRight = (group[1] * group[2] + groupEnd * gCount + t0buDv) / (group[2] + gCount + 1)
  6027. lastRight = (group[1] += (groupEnd - group[1]) * f1 + (t0buDv - group[1]) * f2);
  6028.  
  6029. group[2] = newN;
  6030. // no change of lastK
  6031. groups[k] = null;
  6032. if(deletedStartIndex < 0) deletedStartIndex = k;
  6033. continue;
  6034.  
  6035. } else {
  6036. // n_e{1} will make N_b shift either left or right
  6037.  
  6038. // GroupT: N_t
  6039. // Group (T) = N_t + n_e{1}
  6040.  
  6041. const newN = limitAddition(gCount, 1);
  6042.  
  6043. group[0] = newStart;
  6044. // group[1] = lastRight = (groupEnd * gCount + t0buDv) / (gCount + 1);
  6045. group[1] = lastRight = groupEnd + (t0buDv - groupEnd) * 1 / (gCount + 1);
  6046. group[2] = newN;
  6047.  
  6048. lastK = k;
  6049.  
  6050. // (t0asDv > groupStart) && (t0bsDv < groupEnd) means full containement
  6051. // however, group size is smaller than or equal to t0width
  6052. }
  6053.  
  6054.  
  6055. } else {
  6056. // just update record for next iteration
  6057.  
  6058. lastRight = groupEnd;
  6059. lastK = k;
  6060. }
  6061.  
  6062.  
  6063.  
  6064. }
  6065.  
  6066. if (deletedStartIndex >= 0) {
  6067. // rarely used
  6068.  
  6069. removeNullsInPlace(groups, deletedStartIndex);
  6070.  
  6071. }
  6072. if (!groupK) {
  6073. // groups.push([t0auDv, t0buDv, 1]);
  6074. insertIntoSortedArrayA28(groups, [t0auDv, t0buDv, 1]);
  6075. // insertIntoSortedArrayA27(groups, [t0auDv, t0buDv, t0mu]);
  6076. }
  6077.  
  6078.  
  6079. }
  6080.  
  6081. let autoTimeStampFrameChoose = 0;
  6082.  
  6083. // console.log('group02332')
  6084. for (let j = 0, l = arr.length; j < l; j++) {
  6085. const aItem = arr[j];
  6086.  
  6087. const obj = toLAObj(aItem);
  6088. if (obj === false) continue;
  6089.  
  6090. let p = obj.timestampText;
  6091. let p2, p3=null, p4a=null, p4b=null;
  6092. if(p&&p.simpleText ) p2 = p.simpleText;
  6093.  
  6094. let q = obj.timestampUsec ;
  6095. let q2;
  6096.  
  6097. if(q && +q > 1110553200000000) q2 = +q;
  6098. if (q2 > 0 && !autoTimeStampFrameChoose) {
  6099. const q2cc = Math.round(q2 / 1e6);
  6100. autoTimeStampFrameChoose = q2cc - (q2cc % 10000000);
  6101. if (q2cc - autoTimeStampFrameChoose < 2000000) autoTimeStampFrameChoose -= 10000000;
  6102. // around 10day range
  6103. // exceeded ~10day -> above 10000000
  6104. }
  6105.  
  6106. // console.log('group02333', p2, q2)
  6107. // console.log(3775, q2/1e6, autoTimeStampFrameChoose)
  6108.  
  6109. if(p2 && q2){
  6110.  
  6111. let m;
  6112.  
  6113. if (m = /^\s*(-?)(\d+):(\d+)\s*$/.exec(p2)) {
  6114. let c0z = m[1] ? -1 : 1;
  6115. let c1 = (+m[2]);
  6116. let c2 = (+m[3]);
  6117. if (c0z > 0 && c1 >= 0 && c2 >= 0) {
  6118.  
  6119. p3 = c1 * 60 + c2;
  6120. } else if (c0z < 0 && c1 >= 0 && c2 >= 0) {
  6121. // -4:43 -> -4:42 -> -4:41 ... -> -4:01 -> -4:00 -> -3:59 -> -3:58
  6122. // -> ... -1:01 -> -1:00 -> -0:59 -> ... -> -0:02 -> -0:01 -> -0:00 -> 0:00 -> ...
  6123.  
  6124. p3 = (-c1 * 60) + (-c2);
  6125.  
  6126. }
  6127. if (p3 !== null) {
  6128. // 0:14 -> 13.5s ~ 14.4999s -> [13.5, 14.5)
  6129. p4a = p3 - 0.5;
  6130. p4b = p3 + 0.5;
  6131. }
  6132. } else if (m = /^\s*(-?)(\d+):(\d+):(\d+)\s*$/.exec(p2)) {
  6133.  
  6134. let c0z = m[1] ? -1 : 1;
  6135. let c1 = (+m[2]);
  6136. let c2 = (+m[3]);
  6137. let c3 = (+m[4]);
  6138.  
  6139.  
  6140.  
  6141. if (c0z > 0 && c1 >= 0 && c2 >= 0 && c3 >= 0) {
  6142.  
  6143. p3 = c1 * 60 * 60 + c2 * 60 + c3;
  6144. } else if (c0z < 0 && c1 >= 0 && c2 >= 0 && c3>=0) {
  6145. // -4:43 -> -4:42 -> -4:41 ... -> -4:01 -> -4:00 -> -3:59 -> -3:58
  6146. // -> ... -1:01 -> -1:00 -> -0:59 -> ... -> -0:02 -> -0:01 -> -0:00 -> 0:00 -> ...
  6147.  
  6148. p3 = (-c1 * 60 * 60) + (-c2 * 60) + (-c3);
  6149.  
  6150. }
  6151. if (p3 !== null) {
  6152. // 0:14 -> 13.5s ~ 14.4999s -> [13.5, 14.5)
  6153. p4a = p3 - 0.5;
  6154. p4b = p3 + 0.5;
  6155. }
  6156.  
  6157.  
  6158. }
  6159.  
  6160. }
  6161.  
  6162. if(p4a !== null && p4b !== null && q2 > 0){
  6163.  
  6164. // q2_us = t0_us + dt_us
  6165. // p4a_us <= dt_us < p4b_us
  6166. let p4au = p4a * 1e6;
  6167. let p4bu = p4b * 1e6;
  6168.  
  6169. // p4a_us <= q2_us - t0_us < p4b_us
  6170.  
  6171.  
  6172. // p4a_us - q2_us <= - t0_us < p4b_us - q2_us
  6173.  
  6174. // -p4a_us + q2_us >= t0_us > -p4b_us + q2_us
  6175.  
  6176.  
  6177. let t0au = q2 - p4bu; // q2_us - p4b_us
  6178. let t0bu = q2 - p4au; // q2_us - p4a_us
  6179.  
  6180. // t0 (t0au, t0bu]
  6181.  
  6182. const t0mu = (t0au+t0bu)/2;
  6183.  
  6184. // stack[stackL++]=({
  6185. // id: obj.id,
  6186. // idx: j,
  6187. // p2,
  6188. // // q2s : (q2/ 1e6 - autoTimeStampFrameChoose).toFixed(2),
  6189. // p3,
  6190. // /*
  6191. // timestampText: obj.timestampText,
  6192. // timestampUsec: obj.timestampUsec, // us = 1/1000 ms
  6193. // q2,
  6194. // p4a,
  6195. // p4b,
  6196. // */
  6197. // q2s: +(q2 / 1e6 - autoTimeStampFrameChoose).toFixed(2),
  6198. // t0as: +(t0au / 1e6 - autoTimeStampFrameChoose).toFixed(2),
  6199. // t0bs: +(t0bu /1e6 - autoTimeStampFrameChoose).toFixed(2),
  6200.  
  6201. // t0au,
  6202. // t0bu,
  6203. // t0mu
  6204. // });
  6205.  
  6206. // console.log('group02334')
  6207. let wobj = additionalInfo.get(obj);
  6208. if(!wobj) additionalInfo.set(obj, wobj = {});
  6209.  
  6210. wobj.timestampUsecOriginal = q2;
  6211. // wobj.timestampUsecAdjusted = q2;
  6212. wobj.t0au = t0au;
  6213. wobj.t0bu = t0bu;
  6214. wobj.t0mu = t0mu;
  6215.  
  6216. // arrHash[j] = {
  6217. // index: j,
  6218. // id: obj.id,
  6219. // timestampUsec: q2,
  6220. // t0au,
  6221. // t0bu,
  6222. // t0mu
  6223. // };
  6224.  
  6225. pushToGroup(t0mu);
  6226.  
  6227. // console.log('group02335')
  6228. // console.log('grouping', `${obj.id}.${obj.timestampUsec}`);
  6229.  
  6230. // timestamp (q2) can be incorrect.
  6231.  
  6232. // https://www.youtube.com/watch?v=IKKar5SS29E
  6233. // ChwKGkNQZUxfXzZxLS04Q0ZXNGxyUVlkODZrQzNR
  6234.  
  6235. /*
  6236.  
  6237.  
  6238. [
  6239. {
  6240. "id": "ChwKGkNNWHZqXy1xLS04Q0ZXNGxyUVlkODZrQzNR",
  6241. "p2": "2:04",
  6242. "p3": 124,
  6243. "t0as": 8320733.78,
  6244. "t0bs": 8320734.78
  6245. },
  6246. {
  6247. "id": "ChwKGkNQZUxfXzZxLS04Q0ZXNGxyUVlkODZrQzNR",
  6248. "p2": "2:04",
  6249. "p3": 124,
  6250. "t0as": 8320898.89, // incorrect
  6251. "t0bs": 8320899.89
  6252. }
  6253. ]
  6254.  
  6255.  
  6256. */
  6257.  
  6258. }
  6259.  
  6260.  
  6261.  
  6262.  
  6263. }
  6264.  
  6265. // stack.length = stackL;
  6266.  
  6267.  
  6268. groups_ = groups;
  6269. // console.log('groups', groups)
  6270.  
  6271. }
  6272.  
  6273. // console.log(1237006);
  6274.  
  6275. // console.log(5592,1)
  6276. const groupMids = FIX_TIMESTAMP_FOR_REPLAY ? groups_.map(group=>{
  6277.  
  6278. const [groupStart, groupEnd ] = group;
  6279. const groupMid = (groupStart+groupEnd)/2;
  6280. return groupMid;
  6281. }): null;
  6282. // console.log('groupMids', groupMids)
  6283.  
  6284.  
  6285. // console.log(1237007);
  6286.  
  6287. const adjustTimestampFn = (obj) => {
  6288.  
  6289. const groupCount = groupMids.length;
  6290.  
  6291. if (groupCount < 1) return null;
  6292.  
  6293. // const obj = toLAObj(aItem);
  6294. if (obj === false) return null;
  6295.  
  6296. const wobj = additionalInfo.get(obj);
  6297. if (!wobj) return null;
  6298.  
  6299. const { t0mu } = wobj;
  6300.  
  6301.  
  6302. let i0 = 0;
  6303.  
  6304. if (groupCount >= 3) {
  6305. // For larger arrays, use binary search.
  6306. let low = 0;
  6307. let high = groupCount - 1;
  6308.  
  6309. while (high - low > 1) {
  6310. const mid = (low + high) >>> 1;
  6311. if (groupMids[mid] >= t0mu) {
  6312. high = mid;
  6313. } else {
  6314. low = mid;
  6315. }
  6316. }
  6317. i0 = low;
  6318.  
  6319. }
  6320.  
  6321. let upperDiff = -1;
  6322. let lowerDiff = -1;
  6323. for (let i = i0; i < groupCount; i++) {
  6324. const y = groupMids[i] - t0mu;
  6325. if (y >= 0) {
  6326. upperDiff = y; // >=0, entry > value is found
  6327. break;
  6328. }
  6329. lowerDiff = -y; // >0, cache
  6330. }
  6331.  
  6332.  
  6333. const d1 = upperDiff;
  6334. const d2 = lowerDiff;
  6335.  
  6336.  
  6337. // console.log(5381, index1 ,d1, index2 , d2);
  6338.  
  6339. if (d1 >= 0 && ((d2 < 0) || (d1 <= d2))) {
  6340. wobj.chosenT0 = t0mu + d1; // groupMids[index1];
  6341. } else if (d2 >= 0 && ((d1 < 0) || (d2 <= d1))) {
  6342. wobj.chosenT0 = t0mu - d2; // groupMids[index2];
  6343. } else {
  6344. console.warn('logic error');
  6345. return null;
  6346. }
  6347.  
  6348. const adjusted = wobj.timestampUsecOriginal - wobj.chosenT0;
  6349.  
  6350. wobj.timestampUsecAdjusted = adjusted + 1110553200000000;
  6351.  
  6352. // console.log('adjusted', `${obj.id}.${obj.timestampUsec}`, wobj.timestampUsecOriginal - wobj.chosenT0);
  6353.  
  6354. // adjustmentMap.set(`${obj.id}.${obj.timestampUsec}`, wobj.timestampUsecOriginal - wobj.chosenT0);
  6355.  
  6356. return adjusted;
  6357.  
  6358.  
  6359.  
  6360. };
  6361.  
  6362.  
  6363. // console.log(5592,2)
  6364. // console.log(1237008);
  6365. // if (FIX_TIMESTAMP_FOR_REPLAY) {
  6366.  
  6367.  
  6368. // try{
  6369.  
  6370. // // console.log('groupmid',groupMids, groups);
  6371.  
  6372. // for(let j = 0; j< arr.length;j++){
  6373. // if(groupMids.length<1) break;
  6374.  
  6375. // const aItem = arr[j];
  6376. // const obj = toLAObj(aItem);
  6377. // if (obj === false) continue;
  6378.  
  6379. // const wobj = additionalInfo.get(obj);
  6380. // if(!wobj) continue;
  6381.  
  6382. // // wobj.timestampUsecOriginal = q2;
  6383. // // wobj.timestampUsecAdjusted = q2;
  6384. // // wobj.t0au = t0au;
  6385. // // wobj.t0bu = t0bu;
  6386. // // wobj.t0mu = t0mu;
  6387.  
  6388. // const {t0au, t0bu, t0mu} = wobj;
  6389.  
  6390. // let upper = -1;
  6391.  
  6392. // for(let i = 0; i <groupMids.length;i++){
  6393. // const groupMid = groupMids[i];
  6394. // if(groupMid>= t0mu){
  6395. // upper = i;
  6396. // break;
  6397. // }
  6398. // }
  6399. // let index1, index2;
  6400. // if(upper>-1){
  6401. // index1 = upper-1;
  6402. // index2 = upper;
  6403. // }else{
  6404. // index1 = groups.length-1;
  6405. // index2 = -1;
  6406. // }
  6407. // let d1 = null;
  6408. // if(index1 >=0){
  6409. // d1 = Math.abs(groupMids[index1] - t0mu);
  6410. // }
  6411.  
  6412. // let d2 = null;
  6413. // if(index2 >=0){
  6414. // d2 = Math.abs(groupMids[index2] - t0mu);
  6415. // }
  6416. // // console.log(5381, index1 ,d1, index2 , d2);
  6417. // if(d1 >= 0 && ((d1 <= d2) || (d2 === null)) ){
  6418.  
  6419. // wobj.chosenT0 = groupMids[index1];
  6420. // } else if(d2 >= 0 && ((d2 <= d1) || (d1 === null))){
  6421. // wobj.chosenT0 = groupMids[index2];
  6422. // } else {
  6423. // console.warn('logic error');
  6424. // continue;
  6425. // }
  6426.  
  6427. // wobj.timestampUsecAdjusted = wobj.timestampUsecOriginal - wobj.chosenT0 + 1110553200000000;
  6428.  
  6429. // console.log('adjusted', `${obj.id}.${obj.timestampUsec}`, wobj.timestampUsecOriginal - wobj.chosenT0);
  6430.  
  6431. // adjustmentMap.set(`${obj.id}.${obj.timestampUsec}`, wobj.timestampUsecOriginal - wobj.chosenT0);
  6432. // // conversionMap.set(obj, arrHash[j].adjustedTime);
  6433.  
  6434. // // console.log(5382, index, id, t0mu, arrHash[j].adjustedT0, arrHash[j].timestampUsec, arrHash[j].adjustedTime);
  6435.  
  6436. // }
  6437.  
  6438.  
  6439. // }catch(e){
  6440. // console.warn(e);
  6441. // }
  6442.  
  6443.  
  6444.  
  6445.  
  6446.  
  6447. // // if(stack.length > 1){
  6448. // // stack.sort((a,b)=>{
  6449. // // return a.t0mu - b.t0mu
  6450. // // });
  6451. // // // small to large
  6452. // // // console.log(34588, stack.map(e=>e.t0as))
  6453. // // }
  6454.  
  6455. // // grouping
  6456.  
  6457.  
  6458.  
  6459.  
  6460. // // if (stack.length > 0) {
  6461.  
  6462. // // try {
  6463.  
  6464. // // for (let j = 0, l = stack.length; j < l; j++) {
  6465. // // pushToGroup(stack[j].t0mu);
  6466.  
  6467. // // }
  6468.  
  6469. // // }catch(e){
  6470.  
  6471. // // console.warn(e)
  6472. // // }
  6473.  
  6474. // // // console.log(4882, groups.map(e=>e.slice()), stack.slice())
  6475.  
  6476. // // }
  6477.  
  6478.  
  6479.  
  6480.  
  6481. // // console.log(376, 'group', groups);
  6482.  
  6483.  
  6484. // // consolidated group
  6485. // // const consolidatedGroups = doConsolidation(groups);
  6486.  
  6487.  
  6488.  
  6489.  
  6490.  
  6491.  
  6492. // // if(stack.length > 1){
  6493.  
  6494.  
  6495. // // // // console.log(341, 'consolidatedGroups', consolidatedGroups ,groups.map(e=>{
  6496. // // // // return e.map(noTransform);
  6497. // // // // // return e.map(prettyNum);
  6498. // // // // }))
  6499.  
  6500.  
  6501. // // // console.log(344, 'groups', groups.map(e=>{
  6502. // // // return e.map(noTransform);
  6503. // // // // return e.map(prettyNum);
  6504. // // // }))
  6505.  
  6506. // // // // for(const s of stack){
  6507. // // // // for(const g of consolidatedGroups){
  6508. // // // // if(s.t0as<=g.cen && s.t0bs >=g.cen ){
  6509. // // // // s.cen = g.cen;
  6510. // // // // break;
  6511. // // // // }
  6512. // // // // }
  6513.  
  6514. // // // // }
  6515.  
  6516. // // // console.log(377, stack) // Ms
  6517.  
  6518. // // }
  6519.  
  6520.  
  6521. // // console.timeEnd('FIX_TIMESTAMP_FOR_REPLAY')
  6522.  
  6523. // }
  6524.  
  6525.  
  6526.  
  6527.  
  6528.  
  6529.  
  6530.  
  6531.  
  6532.  
  6533. // console.log(5592,5)
  6534.  
  6535.  
  6536. // console.log('preprocessChatLiveActions', arr)
  6537.  
  6538.  
  6539. const mapper = new Map();
  6540. mapper.set = mapper.setOriginal || mapper.set;
  6541.  
  6542. // without delaying. get the time of request
  6543. // (both streaming and replay, but replay relys on progress update so background operation is suppressed)
  6544.  
  6545. for (let j = 0, l = arr.length; j < l; j++) {
  6546. const aItem = arr[j];
  6547.  
  6548. const obj = toLAObj(aItem);
  6549. if(obj === false) continue;
  6550.  
  6551. if (obj.id && !obj.__timestampActionRequest__) {
  6552. // for all item entries
  6553. obj.__timestampActionRequest__ = ct;
  6554. }
  6555.  
  6556. if (obj.id && obj.__timestampActionRequest__ > 0 && obj.durationSec > 0 && obj.fullDurationSec) {
  6557.  
  6558. // console.log(948700, obj , obj.id, (obj.fullDurationSec - obj.durationSec) * 1000)
  6559. const m = obj.__timestampActionRequest__ - (obj.fullDurationSec - obj.durationSec) * 1000;
  6560.  
  6561. // obj.__t374__ = (obj.fullDurationSec - obj.durationSec) * 1000;
  6562. // obj.__t375__ = obj.__timestampActionRequest__ - (obj.fullDurationSec - obj.durationSec) * 1000;
  6563. // console.log(5993, obj)
  6564. // obj.__orderTime__ = m;
  6565. mapper.set(aItem, m);
  6566.  
  6567.  
  6568. }
  6569.  
  6570. }
  6571.  
  6572. if (mapper.size > 1) {
  6573.  
  6574. const idxices = [];
  6575.  
  6576. // sort ticker
  6577. let mArr1 = arr.filter((aItem,idx) => {
  6578.  
  6579. if (mapper.has(aItem)) {
  6580. idxices.push(idx);
  6581. return true;
  6582. }
  6583. return false;
  6584.  
  6585. });
  6586.  
  6587.  
  6588. let mArr2 = mArr1/*.slice(0)*/.sort((a, b) => {
  6589. return mapper.get(a) - mapper.get(b);
  6590. // low index = oldest = smallest timestamp
  6591. });
  6592.  
  6593.  
  6594.  
  6595. // console.log(948701, arr.slice(0));
  6596. for(let j = 0, l=mArr1.length;j <l;j++){
  6597.  
  6598. const idx = idxices[j];
  6599. // arr[idx] = mArr1[j]
  6600. arr[idx] = mArr2[j];
  6601.  
  6602. // const obj1 = toObj(mArr1[j]);
  6603. // const obj2 = toObj(mArr2[j]);
  6604.  
  6605. // console.log(948705, idx, obj1 , obj1.id, (obj1.fullDurationSec - obj1.durationSec) * 1000, obj1.__orderTime__)
  6606.  
  6607. // console.log(948706, idx, obj2 , obj2.id, (obj2.fullDurationSec - obj2.durationSec) * 1000, obj2.__orderTime__)
  6608.  
  6609. }
  6610.  
  6611. // console.log(5994,arr)
  6612.  
  6613. // console.log(948702, arr.slice(0));
  6614. // console.log(948701, arr);
  6615. // arr = arr.map(aItem => {
  6616. // const idx = mArr1.indexOf(aItem);
  6617. // if (idx < 0) return aItem;
  6618. // return mArr2[idx];
  6619. // });
  6620. // console.log(948702, arr);
  6621.  
  6622. // mostly in order, but some not in order
  6623.  
  6624.  
  6625. // eg
  6626.  
  6627. /*
  6628.  
  6629.  
  6630. 948711 68 '1734488590715474'
  6631. 948711 69 '1734488590909853'
  6632. 948711 70 '1734488594763719'
  6633. 948711 71 '1734488602334615' <
  6634. 948711 72 '1734488602267214' <
  6635. 948711 73 '1734488602751771'
  6636. */
  6637.  
  6638. // arr.filter(aItem=>{
  6639.  
  6640. // const p = toObj(aItem);
  6641. // if(p.timestampUsec) return true;
  6642.  
  6643. // }).forEach((aItem,idx)=>{
  6644.  
  6645. // const p = toObj(aItem);
  6646. // console.log(948711, idx, p.timestampUsec);
  6647. // })
  6648.  
  6649. // return arr;
  6650.  
  6651. }
  6652.  
  6653. // console.log(1237001);
  6654.  
  6655. {
  6656.  
  6657. const mapper = new Map();
  6658. mapper.set = mapper.setOriginal || mapper.set;
  6659.  
  6660. const idxices = [];
  6661.  
  6662. let mArr1 = arr.filter((aItem,idx) => {
  6663.  
  6664. const obj = toLAObj(aItem);
  6665. if (!obj) return false;
  6666.  
  6667. const baseText = obj.timestampText;
  6668. const baseTime = +obj.timestampUsec;
  6669. if (!baseTime || !baseText) return false;
  6670. // const timestampUsec = +toLAObj(aItem).timestampUsec; // +false.x = NaN
  6671. // const timestampUsec = +toLAObj(aItem).adjustedTime;
  6672.  
  6673. let timestampUsec;
  6674.  
  6675. // console.log(1237002)
  6676. if (FIX_TIMESTAMP_FOR_REPLAY) {
  6677.  
  6678. // const adjustmentTime = adjustmentMap.get(`${obj.id}.${obj.timestampUsec}`);
  6679.  
  6680. // // const wobj = additionalInfo.get(obj);
  6681.  
  6682. // // if(!wobj){
  6683. // // console.warn('FIX_TIMESTAMP_FOR_REPLAY - no wobj', obj)
  6684. // // return false;
  6685. // // }
  6686.  
  6687. // // timestampUsec = +wobj.timestampUsecAdjusted;
  6688. // if (!Number.isFinite(adjustmentTime)) {
  6689. // console.warn(`FIX_TIMESTAMP_FOR_REPLAY - no adjustmentTime for ${obj.id}.${obj.timestampUsec}`, obj, [...adjustmentMap])
  6690. // return false;
  6691. // }
  6692. // timestampUsec = adjustmentTime;
  6693.  
  6694.  
  6695. const adjustmentTime = adjustTimestampFn(obj);
  6696.  
  6697. if (!Number.isFinite(adjustmentTime)) {
  6698.  
  6699. console.warn(`FIX_TIMESTAMP_FOR_REPLAY - no adjustmentTime for ${obj.id}.${obj.timestampUsec}`, obj);
  6700. return false;
  6701. }
  6702. timestampUsec = adjustmentTime;
  6703.  
  6704.  
  6705. } else {
  6706.  
  6707. if (!Number.isFinite(baseTime)) {
  6708. console.warn(`no baseTime for ${obj.id}.${obj.timestampUsec}`, obj);
  6709.  
  6710. return false;
  6711. }
  6712. timestampUsec = baseTime;
  6713.  
  6714. }
  6715.  
  6716. // if(timestampUsec > 0){
  6717. idxices.push(idx);
  6718. mapper.set(aItem, timestampUsec)
  6719. return true;
  6720. // }
  6721. // return false;
  6722.  
  6723. });
  6724.  
  6725. if(mapper.size > 1){
  6726.  
  6727.  
  6728. // console.log(1237004)
  6729. let mArr2 = mArr1/*.slice(0)*/.sort((a, b) => {
  6730. return mapper.get(a) - mapper.get(b);
  6731. // low index = oldest = smallest timestamp
  6732. });
  6733.  
  6734.  
  6735.  
  6736. // console.log(948701, arr.slice(0));
  6737. for(let j = 0, l=mArr1.length;j <l;j++){
  6738.  
  6739. const idx = idxices[j];
  6740. arr[idx] = mArr2[j];
  6741.  
  6742. // const obj1 = toObj(mArr1[j]);
  6743. // const obj2 = toObj(mArr2[j]);
  6744.  
  6745.  
  6746. // console.log(948711, idx, obj1 === obj2, obj1, obj1.timestampUsec);
  6747. // console.log(948712, idx, obj1 === obj2, obj2, obj2.timestampUsec);
  6748. }
  6749.  
  6750. }
  6751.  
  6752.  
  6753. }
  6754.  
  6755. // console.log(1237005)
  6756.  
  6757. // console.log(378, arr);
  6758.  
  6759. return arr;
  6760.  
  6761.  
  6762. }
  6763.  
  6764. if (ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION) {
  6765.  
  6766. console.log('[yt-chat-control] ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION is used.')
  6767.  
  6768. // console.log('ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION 0001')
  6769.  
  6770. const pop078 = function () {
  6771. const r = this.pop78();
  6772.  
  6773. if (r && (r.actions || 0).length >= 1 && r.videoOffsetTimeMsec) {
  6774. for (const action of r.actions) {
  6775.  
  6776. const itemActionKey = !action ? null : 'addChatItemAction' in action ? 'addChatItemAction' : 'addLiveChatTickerItemAction' in action ? 'addLiveChatTickerItemAction' : null;
  6777. if (itemActionKey) {
  6778.  
  6779. const itemAction = action[itemActionKey];
  6780. const item = (itemAction || 0).item;
  6781. if (typeof item === 'object') {
  6782.  
  6783. const rendererKey = firstObjectKey(item);
  6784. if (rendererKey) {
  6785. const renderer = item[rendererKey];
  6786. if (renderer && typeof renderer === 'object') {
  6787. renderer.__videoOffsetTimeMsec__ = r.videoOffsetTimeMsec;
  6788. renderer.__progressAt__ = playerProgressChangedArg1;
  6789.  
  6790. // console.log(48117006)
  6791. }
  6792.  
  6793. }
  6794.  
  6795. }
  6796. }
  6797. }
  6798. }
  6799. return r;
  6800. }
  6801.  
  6802.  
  6803.  
  6804. const replayQueueProxyHandler = {
  6805. get(target, prop, receiver) {
  6806. if (prop === 'qe3') return 1;
  6807. const v = target[prop];
  6808. if (prop === 'front_') {
  6809. if (v && typeof v.length === 'number') {
  6810. if (!v.pop78) {
  6811. v.pop78 = v.pop;
  6812. v.pop = pop078;
  6813. }
  6814. }
  6815. }
  6816. return v;
  6817. }
  6818. };
  6819.  
  6820. // lcrFn2 will run twice to ensure the method is successfully injected.
  6821. const lcrFn2 = (lcrDummy)=>{
  6822. // make minimal function overhead by pre-defining all possible outside.
  6823.  
  6824. const tag = "yt-live-chat-renderer"
  6825. const dummy = lcrDummy;
  6826.  
  6827. const cProto = getProto(dummy);
  6828. if (!cProto || !cProto.attached) {
  6829. console.warn(`proto.attached for ${tag} is unavailable.`);
  6830. return;
  6831. }
  6832.  
  6833. // mightFirstCheckOnYtInit();
  6834. // groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-renderer hacks");
  6835. // console.log("[Begin]");
  6836.  
  6837.  
  6838. if (typeof cProto.playerProgressChanged_ === 'function' && !cProto.playerProgressChanged32_) {
  6839.  
  6840. cProto.playerProgressChanged32_ = cProto.playerProgressChanged_;
  6841.  
  6842.  
  6843. cProto.playerProgressChanged_ = function (a, b, c) {
  6844. // console.log(48117005)
  6845. if (a === 0) a = arguments[0] = Number.MIN_VALUE; // avoid issue dealing with zero value
  6846. playerProgressChangedArg1 = a;
  6847. playerProgressChangedArg2 = b;
  6848. playerProgressChangedArg3 = c;
  6849. const replayBuffer_ = this.replayBuffer_;
  6850. if (replayBuffer_) {
  6851. const replayQueue = replayBuffer_.replayQueue
  6852. if (replayQueue && typeof replayQueue === 'object' && !replayQueue.qe3) {
  6853. replayBuffer_.replayQueue = new Proxy(replayBuffer_.replayQueue, replayQueueProxyHandler);
  6854. }
  6855. }
  6856. Promise.resolve().then(updateTickerCurrentTime);
  6857. return this.playerProgressChanged32_.apply(this, arguments);
  6858. };
  6859.  
  6860. }
  6861.  
  6862. // console.log("[End]");
  6863. // groupEnd();
  6864.  
  6865.  
  6866. };
  6867. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  6868.  
  6869.  
  6870. // console.log('ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION 0002')
  6871.  
  6872. // getLCRDummy() must be called for injection
  6873. getLCRDummy().then(lcrFn2);
  6874.  
  6875. }
  6876.  
  6877. const stackDM = (()=>{
  6878.  
  6879. let cm, stack, mo;
  6880.  
  6881. let firstRun = ()=>{
  6882. cm = mockCommentElement(document.createComment('1'));
  6883. stack = new Set();
  6884. mo = new MutationObserver(()=>{
  6885. const stack_ = stack;
  6886. stack = new Set();
  6887. // for(const value of stack_){
  6888. // Promise.resolve(value).then(f=>f());
  6889. // }
  6890. for(const value of stack_){
  6891. value();
  6892. }
  6893. stack_.clear();
  6894. });
  6895. mo.observe(cm, {characterData: true});
  6896.  
  6897. }
  6898.  
  6899.  
  6900. const stackDM = (f) => {
  6901.  
  6902. if (firstRun) firstRun = firstRun();
  6903. stack.add(f);
  6904. cm.data = `${(cm.data & 1) + 1}`;
  6905. }
  6906. return stackDM;
  6907. })();
  6908. window.stackDM = stackDM;
  6909.  
  6910.  
  6911. const widthReq = (()=>{
  6912.  
  6913. let widthIORes;
  6914. let widthIO;
  6915.  
  6916. let firstRun = () => {
  6917. widthIORes = new WeakMap();
  6918. widthIO = new IntersectionObserver((mutations) => {
  6919. const r = new Map();
  6920. for (const mutation of mutations) {
  6921. r.set(mutation.target, mutation.boundingClientRect);
  6922. }
  6923.  
  6924. for (const [elm, rect] of r) {
  6925. widthIO.unobserve(elm);
  6926. const o = widthIORes.get(elm);
  6927. o && widthIORes.delete(elm);
  6928. const { promise, values } = o || {};
  6929. if (promise && values) {
  6930. values.width = rect.width;
  6931. promise.resolve(values);
  6932. }
  6933. }
  6934. });
  6935. };
  6936.  
  6937. const widthReq = (elm) => {
  6938.  
  6939. if (firstRun) firstRun = firstRun();
  6940.  
  6941. {
  6942. const { promise, values } = widthIORes.get(elm) || {};
  6943. if (promise) return promise;
  6944. }
  6945.  
  6946. const promise = new PromiseExternal();
  6947. widthIORes.set(elm, { promise, values: {} });
  6948. widthIO.unobserve(elm);
  6949. widthIO.observe(elm);
  6950.  
  6951. return promise;
  6952.  
  6953. }
  6954. return widthReq;
  6955. })();
  6956.  
  6957.  
  6958.  
  6959.  
  6960. customElements.whenDefined('yt-live-chat-item-list-renderer').then(() => {
  6961.  
  6962.  
  6963. const tag = "yt-live-chat-item-list-renderer"
  6964. const dummy = document.createElement(tag);
  6965.  
  6966. const cProto = getProto(dummy);
  6967. if (!cProto || !cProto.attached) {
  6968. console.warn(`proto.attached for ${tag} is unavailable.`);
  6969. return;
  6970. }
  6971.  
  6972. mightFirstCheckOnYtInit();
  6973. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-item-list-renderer hacks");
  6974. console1.log("[Begin]");
  6975.  
  6976. const mclp = cProto;
  6977. const _flag0281_ = window._flag0281_;
  6978.  
  6979. try {
  6980. assertor(() => typeof mclp.scrollToBottom_ === 'function');
  6981. assertor(() => typeof mclp.flushActiveItems_ === 'function');
  6982. assertor(() => typeof mclp.canScrollToBottom_ === 'function');
  6983. assertor(() => typeof mclp.setAtBottom === 'function');
  6984. assertor(() => typeof mclp.scrollToBottom66_ === 'undefined');
  6985. assertor(() => typeof mclp.flushActiveItems66_ === 'undefined');
  6986. } catch (e) { }
  6987.  
  6988.  
  6989. try {
  6990. assertor(() => typeof mclp.attached === 'function');
  6991. assertor(() => typeof mclp.detached === 'function');
  6992. assertor(() => typeof mclp.canScrollToBottom_ === 'function');
  6993. assertor(() => typeof mclp.isSmoothScrollEnabled_ === 'function');
  6994. assertor(() => typeof mclp.maybeResizeScrollContainer_ === 'function');
  6995. assertor(() => typeof mclp.refreshOffsetContainerHeight_ === 'function');
  6996. assertor(() => typeof mclp.smoothScroll_ === 'function');
  6997. assertor(() => typeof mclp.resetSmoothScroll_ === 'function');
  6998. } catch (e) { }
  6999.  
  7000. mclp.prDelay171 = null;
  7001.  
  7002. let myk = 0; // showNewItems77_
  7003. let mlf = 0; // flushActiveItems77_
  7004. let myw = 0; // onScrollItems77_
  7005. let mzt = 0; // handleLiveChatActions77_
  7006. let mlg = 0; // delayFlushActiveItemsAfterUserAction11_
  7007. let zarr = null;
  7008.  
  7009. if ((_flag0281_ & 0x2000) == 0) {
  7010.  
  7011. if ((mclp.clearList || 0).length === 0) {
  7012. (_flag0281_ & 0x2) == 0 && assertor(() => fnIntegrity(mclp.clearList, '0.106.50'));
  7013. mclp.clearList66 = mclp.clearList;
  7014. mclp.clearList = function () {
  7015. myk = (myk & 1073741823) + 1;
  7016. mlf = (mlf & 1073741823) + 1;
  7017. myw = (myw & 1073741823) + 1;
  7018. mzt = (mzt & 1073741823) + 1;
  7019. mlg = (mlg & 1073741823) + 1;
  7020. zarr = null;
  7021. this.prDelay171 = null;
  7022. this.clearList66();
  7023. };
  7024. console1.log("clearList", "OK");
  7025. } else {
  7026. console1.log("clearList", "NG");
  7027. }
  7028.  
  7029. }
  7030.  
  7031.  
  7032.  
  7033. let onListRendererAttachedDone = false;
  7034.  
  7035. function setList(itemOffset, items) {
  7036.  
  7037. const isFirstTime = onListRendererAttachedDone === false;
  7038.  
  7039. if (isFirstTime) {
  7040. onListRendererAttachedDone = true;
  7041. Promise.resolve().then(watchUserCSS);
  7042. addCssManaged();
  7043.  
  7044. const isBoostChatEnabled = (window._flag0281_ & 0x40000) === 0x40000;
  7045. if (!isBoostChatEnabled) setupEvents();
  7046. }
  7047.  
  7048. setupStyle(itemOffset, items);
  7049.  
  7050. setupMutObserver(items);
  7051.  
  7052. console.log('[yt-chat] setupMutObserver DONE')
  7053. }
  7054.  
  7055.  
  7056. const deferSeqFns = []; // ensure correct sequence
  7057. let deferSeqFnI = 0;
  7058. const deferCallbackLooper = entry => {
  7059. nextBrowserTick_(() => {
  7060. const { a, b } = entry;
  7061. const cnt = kRef(a);
  7062. if (cnt && b) b.call(cnt);
  7063. entry.a = entry.b = null;
  7064. });
  7065. }
  7066. const deferCallback = async (cnt, callback) => {
  7067. const a = cnt.__weakRef9441__ || (cnt.__weakRef9441__ = mWeakRef(cnt));
  7068. deferSeqFns[deferSeqFnI++] = { a, b: callback };
  7069. if (deferSeqFnI > 1) return;
  7070. const pr288 = cnt.prDelay288;
  7071. await pr288;
  7072. wme.data = `${(wme.data & 7) + 1}`;
  7073. await wmp;
  7074. const l = deferSeqFnI;
  7075. deferSeqFnI = 0;
  7076. for (let i = 0; i < l; i++) {
  7077. Promise.resolve(deferSeqFns[i]).then(deferCallbackLooper);
  7078. }
  7079. };
  7080.  
  7081. let showMoreBtnTransitionTrigg = null;
  7082.  
  7083. mclp.__showMoreBtn_transitionstart011__ = function (evt) {
  7084. showMoreBtnTransitionTrigg = true;
  7085. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7086. if (newVisibility === "visible") {
  7087. const btn = evt.target;
  7088. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7089. }
  7090. };
  7091.  
  7092.  
  7093. mclp.__showMoreBtn_transitionend011__ = function (evt) {
  7094. showMoreBtnTransitionTrigg = true;
  7095. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7096. if (newVisibility === "hidden") {
  7097. const btn = evt.target;
  7098. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7099. }
  7100. };
  7101. mclp.attached419 = async function () {
  7102.  
  7103. if (!this.isAttached) return;
  7104.  
  7105. let maxTrial = 16;
  7106. while (!this.$ || !this.$['item-scroller'] || !this.$['item-offset'] || !this.$['items']) {
  7107. if (--maxTrial < 0 || !this.isAttached) return;
  7108. await nextBrowserTick_();
  7109. // await new Promise(requestAnimationFrame);
  7110. }
  7111.  
  7112. if (this.isAttached !== true) return;
  7113.  
  7114. if (!this.$) {
  7115. console.warn("!this.$");
  7116. return;
  7117. }
  7118. if (!this.$) return;
  7119. /** @type {HTMLElement | null} */
  7120. const itemScroller = this.$['item-scroller'];
  7121. /** @type {HTMLElement | null} */
  7122. const itemOffset = this.$['item-offset'];
  7123. /** @type {HTMLElement | null} */
  7124. const items = this.$['items'];
  7125.  
  7126. if (!itemScroller || !itemOffset || !items) {
  7127. console.warn("items.parentNode !== itemOffset");
  7128. return;
  7129. }
  7130.  
  7131. if (nodeParent(items) !== itemOffset) {
  7132.  
  7133. console.warn("items.parentNode !== itemOffset");
  7134. return;
  7135. }
  7136.  
  7137.  
  7138. if (items.id !== 'items' || itemOffset.id !== "item-offset") {
  7139.  
  7140. console.warn("id incorrect");
  7141. return;
  7142. }
  7143.  
  7144. 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')
  7145.  
  7146. if (!isTargetItems) {
  7147. console.warn("!isTargetItems");
  7148. return;
  7149. }
  7150.  
  7151. setList(itemOffset, items);
  7152.  
  7153. if (WITH_SCROLL_ANCHOR) this.__itemAnchorColl011__ = itemOffset.getElementsByTagName('item-anchor');
  7154. else this.__itemAnchorColl011__ = null;
  7155.  
  7156.  
  7157.  
  7158. // btn-show-more-transition
  7159. const btn = this.$['show-more'];
  7160. if (btn) {
  7161. if (!this.__showMoreBtn_transitionstart012__) this.__showMoreBtn_transitionstart012__ = this.__showMoreBtn_transitionstart011__.bind(this);
  7162. if (!this.__showMoreBtn_transitionend012__) this.__showMoreBtn_transitionend012__ = this.__showMoreBtn_transitionend011__.bind(this);
  7163. btn.addEventListener('transitionrun', this.__showMoreBtn_transitionstart012__, false);
  7164. btn.addEventListener('transitionstart', this.__showMoreBtn_transitionstart012__, false);
  7165. btn.addEventListener('transitionend', this.__showMoreBtn_transitionend012__, false);
  7166. btn.addEventListener('transitioncancel', this.__showMoreBtn_transitionend012__, false);
  7167. }
  7168.  
  7169. // fix panel height changing issue (ENABLE_OVERFLOW_ANCHOR only)
  7170. if (itemScrollerResizeObserver) itemScrollerResizeObserver.observe(this.itemScroller || this.$['item-scroller']);
  7171.  
  7172. }
  7173.  
  7174. mclp.attached331 = mclp.attached;
  7175. mclp.attached = function () {
  7176. this.attached419 && this.attached419();
  7177. return this.attached331();
  7178. }
  7179.  
  7180. mclp.detached331 = mclp.detached;
  7181.  
  7182. mclp.detached = function () {
  7183. setupMutObserver();
  7184. return this.detached331();
  7185. }
  7186.  
  7187. const t29s = document.querySelectorAll("yt-live-chat-item-list-renderer");
  7188. for (const t29 of t29s) {
  7189. const cnt = insp(t29);
  7190. if (cnt.isAttached === true) {
  7191. cnt.attached419();
  7192. }
  7193. }
  7194.  
  7195. if ((mclp.async || 0).length === 2 && (mclp.cancelAsync || 0).length === 1) {
  7196.  
  7197. assertor(() => fnIntegrity(mclp.async, '2.24.15'));
  7198. assertor(() => fnIntegrity(mclp.cancelAsync, '1.15.8'));
  7199.  
  7200. /** @type {Map<number, any>} */
  7201. const aMap = new Map();
  7202. const mcid = setTimeout(() => 0, 0.625);
  7203. const maid = requestAnimationFrame(() => 0);
  7204. clearTimeout(mcid);
  7205. cancelAnimationFrame(maid);
  7206. const count0 = mcid + maid + 1740;
  7207. let count = count0;
  7208. mclp.async66 = mclp.async;
  7209. mclp.async = function (e, f) {
  7210. // ensure the previous operation is done
  7211. // .async is usually after the time consuming functions like flushActiveItems_ and scrollToBottom_
  7212. const hasF = arguments.length === 2;
  7213. if (count > 1e9) count = count0 + 9;
  7214. const resId = ++count;
  7215. aMap.set(resId, e);
  7216. const pr1 = Promise.all([this.prDelay288, wmp, this.prDelay171, Promise.resolve()]);
  7217. const pr2 = autoTimerFn();
  7218. Promise.race([pr1, pr2]).then(() => {
  7219. const rp = aMap.get(resId);
  7220. if (typeof rp !== 'function') {
  7221. return;
  7222. }
  7223. const asyncEn = function () {
  7224. return aMap.delete(resId) && rp.apply(this, arguments);
  7225. };
  7226. aMap.set(resId, hasF ? this.async66(asyncEn, f) : this.async66(asyncEn));
  7227. });
  7228.  
  7229. return resId;
  7230. }
  7231.  
  7232. mclp.cancelAsync66 = mclp.cancelAsync;
  7233. mclp.cancelAsync = function (resId) {
  7234. if (resId <= count0) {
  7235. this.cancelAsync66(resId);
  7236. } else if (aMap.has(resId)) {
  7237. const rp = aMap.get(resId);
  7238. aMap.delete(resId);
  7239. if (typeof rp !== 'function') {
  7240. this.cancelAsync66(rp);
  7241. }
  7242. }
  7243. }
  7244.  
  7245. console1.log("async", "OK");
  7246. } else {
  7247. console1.log("async", "NG");
  7248. }
  7249.  
  7250.  
  7251. if ((_flag0281_ & 0x2) == 0) {
  7252. if ((mclp.showNewItems_ || 0).length === 0 && ENABLE_NO_SMOOTH_TRANSFORM) {
  7253.  
  7254. assertor(() => fnIntegrity(mclp.showNewItems_, '0.170.79'));
  7255. mclp.showNewItems66_ = mclp.showNewItems_;
  7256. mclp.showNewItems_ = function () {
  7257. //
  7258. }
  7259.  
  7260. console1.log("showNewItems_", "OK");
  7261. } else {
  7262. console1.log("showNewItems_", "NG");
  7263. }
  7264.  
  7265. }
  7266.  
  7267.  
  7268.  
  7269. if ((_flag0281_ & 0x2) == 0) {
  7270. if ((mclp.onScrollItems_ || 0).length === 1) {
  7271.  
  7272. if (mclp.onScrollItems3641_) {
  7273.  
  7274. } else {
  7275. assertor(() => fnIntegrity(mclp.onScrollItems_, '1.17.9'));
  7276.  
  7277. }
  7278.  
  7279. if (typeof mclp.setAtBottom === 'function' && mclp.setAtBottom.length === 0) {
  7280.  
  7281. mclp.setAtBottom217 = mclp.setAtBottom;
  7282. mclp.setAtBottom = function () {
  7283. const v = this.ec217;
  7284. if (typeof v !== 'boolean') return this.setAtBottom217();
  7285. const u = this.atBottom;
  7286. if (u !== v && typeof u === 'boolean') this.atBottom = v;
  7287. // this.atBottom = a.scrollTop >= a.scrollHeight - a.clientHeight - 15
  7288. }
  7289.  
  7290. let lastScrollTarget = null;
  7291. mclp.onScrollItems66_ = mclp.onScrollItems_;
  7292. let callback = () => { };
  7293.  
  7294. // let itemScrollerWR = null;
  7295. let lastEvent = null;
  7296.  
  7297. let io2 = null, io1 = null;
  7298. const io2f = (entries, observer) => {
  7299. const entry = entries[entries.length - 1];
  7300. if (entry.target !== lastScrollTarget) return;
  7301. callback(entry);
  7302. };
  7303. const io1f = (entries, observer) => {
  7304. const entry = entries[entries.length - 1];
  7305. observer.unobserve(entry.target);
  7306. if (entry.target !== lastScrollTarget) return;
  7307. lastScrollTarget = null;
  7308. callback(entry);
  7309. };
  7310. mclp.onScrollItems3885cb2_ = function (entry) {
  7311. const v = (entry.isIntersecting === true);
  7312. this.ec217 = v;
  7313. this.onScrollItems66_(lastEvent);
  7314. this.ec217 = null;
  7315. }
  7316. mclp.onScrollItems3885cb1_ = function (entry) {
  7317. const v = (entry.intersectionRatio > 0.98);
  7318. this.ec217 = v;
  7319. this.onScrollItems66_(lastEvent);
  7320. this.ec217 = null;
  7321. };
  7322.  
  7323. mclp.onScrollItems_ = function (evt) {
  7324.  
  7325. if (evt === lastEvent) return;
  7326. if (evt && lastEvent && evt.timeStamp === lastEvent.timeStamp) return;
  7327. lastEvent = evt;
  7328. const ytRendererBehavior = this.ytRendererBehavior || 0;
  7329. if (typeof ytRendererBehavior.onScroll === 'function') ytRendererBehavior.onScroll(evt);
  7330. const coll = this.__itemAnchorColl011__;
  7331. if (coll) {
  7332. const anchorElement = coll.length === 1 ? coll[0] : null;
  7333. if (lastScrollTarget !== anchorElement) {
  7334. if (io2) io2.disconnect();
  7335. lastScrollTarget = anchorElement;
  7336. if (anchorElement) {
  7337. if (!this.onScrollItems3886cb2_) this.onScrollItems3886cb2_ = this.onScrollItems3885cb2_.bind(this);
  7338. callback = this.onScrollItems3886cb2_;
  7339. if (!io2) io2 = new IntersectionObserver(io2f);
  7340. io2.observe(anchorElement);
  7341. }
  7342. }
  7343. } else {
  7344. const items = this.$.items;
  7345. if (!items) return this.onScrollItems66_();
  7346. const lastComponent = lastComponentChildFn(items);
  7347. if (!lastComponent) return this.onScrollItems66_();
  7348. if (lastScrollTarget === lastComponent) return;
  7349. lastScrollTarget = lastComponent;
  7350.  
  7351. if (io1) io1.disconnect();
  7352. if (!this.onScrollItems3886cb1_) this.onScrollItems3886cb1_ = this.onScrollItems3885cb1_.bind(this);
  7353. callback = this.onScrollItems3886cb1_;
  7354. if (!io1) io1 = new IntersectionObserver(io1f);
  7355. io1.observe(lastComponent);
  7356. }
  7357. };
  7358.  
  7359. }
  7360.  
  7361. console1.log("onScrollItems_", "OK");
  7362. } else {
  7363. console1.log("onScrollItems_", "NG");
  7364. }
  7365. }
  7366.  
  7367.  
  7368. if ((_flag0281_ & 0x40) == 0) {
  7369.  
  7370. if (ENABLE_NO_SMOOTH_TRANSFORM && SUPPRESS_refreshOffsetContainerHeight_ && typeof mclp.refreshOffsetContainerHeight_ === 'function' && !mclp.refreshOffsetContainerHeight26_ && mclp.refreshOffsetContainerHeight_.length === 0) {
  7371. assertor(() => fnIntegrity(mclp.refreshOffsetContainerHeight_, '0.31.21'));
  7372. mclp.refreshOffsetContainerHeight26_ = mclp.refreshOffsetContainerHeight_;
  7373. mclp.refreshOffsetContainerHeight_ = function () {
  7374. // var a = this.itemScroller.clientHeight;
  7375. // this.itemOffset.style.height = this.items.clientHeight + "px";
  7376. // this.bottomAlignMessages && (this.itemOffset.style.minHeight = a + "px")
  7377. }
  7378. console1.log("refreshOffsetContainerHeight_", "OK");
  7379. } else {
  7380. console1.log("refreshOffsetContainerHeight_", "NG");
  7381. }
  7382.  
  7383. }
  7384.  
  7385. if ((_flag0281_ & 0x2000) == 0) {
  7386. if ((mclp.flushActiveItems_ || 0).length === 0) {
  7387.  
  7388. if ((_flag0281_ & 0x2) == 0) {
  7389.  
  7390. const sfi = fnIntegrity(mclp.flushActiveItems_);
  7391. if(sfi === '0.158.86'){
  7392.  
  7393. // https://www.youtube.com/s/desktop/c01ea7e3/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  7394.  
  7395.  
  7396. // f.flushActiveItems_ = function() {
  7397. // var a = this;
  7398. // if (this.activeItems_.length > 0)
  7399. // if (this.canScrollToBottom_()) {
  7400. // var b = Math.max(this.visibleItems.length + this.activeItems_.length - this.data.maxItemsToDisplay, 0);
  7401. // b && this.splice("visibleItems", 0, b);
  7402. // if (this.isSmoothScrollEnabled_() || this.dockableMessages.length)
  7403. // this.preinsertHeight_ = this.items.clientHeight;
  7404. // this.activeItems_.unshift("visibleItems");
  7405. // try {
  7406. // this.push.apply(this, this.activeItems_)
  7407. // } catch (c) {
  7408. // Tm(c)
  7409. // }
  7410. // this.activeItems_ = [];
  7411. // this.isSmoothScrollEnabled_() ? this.canScrollToBottom_() && $u(function() {
  7412. // a.showNewItems_()
  7413. // }) : $u(function() {
  7414. // a.refreshOffsetContainerHeight_();
  7415. // a.maybeScrollToBottom_()
  7416. // })
  7417. // } else
  7418. // this.activeItems_.length > this.data.maxItemsToDisplay && this.activeItems_.splice(0, this.activeItems_.length - this.data.maxItemsToDisplay)
  7419. // }
  7420.  
  7421. } else if (sfi === '0.156.86') {
  7422. // https://www.youtube.com/s/desktop/f61c8d85/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  7423.  
  7424. // added "refreshOffsetContainerHeight_"
  7425.  
  7426. // f.flushActiveItems_ = function() {
  7427. // var a = this;
  7428. // if (0 < this.activeItems_.length)
  7429. // if (this.canScrollToBottom_()) {
  7430. // var b = Math.max(this.visibleItems.length + this.activeItems_.length - this.data.maxItemsToDisplay, 0);
  7431. // b && this.splice("visibleItems", 0, b);
  7432. // if (this.isSmoothScrollEnabled_() || this.dockableMessages.length)
  7433. // this.preinsertHeight_ = this.items.clientHeight;
  7434. // this.activeItems_.unshift("visibleItems");
  7435. // try {
  7436. // this.push.apply(this, this.activeItems_)
  7437. // } catch (c) {
  7438. // fm(c)
  7439. // }
  7440. // this.activeItems_ = [];
  7441. // this.isSmoothScrollEnabled_() ? this.canScrollToBottom_() && Mw(function() {
  7442. // a.showNewItems_()
  7443. // }) : Mw(function() {
  7444. // a.refreshOffsetContainerHeight_();
  7445. // a.maybeScrollToBottom_()
  7446. // })
  7447. // } else
  7448. // this.activeItems_.length > this.data.maxItemsToDisplay && this.activeItems_.splice(0, this.activeItems_.length - this.data.maxItemsToDisplay)
  7449. // }
  7450. // ;
  7451.  
  7452. } else if (sfi === '0.150.84') {
  7453. // https://www.youtube.com/s/desktop/e4d15d2c/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  7454. // var b = Math.max(this.visibleItems.length + this.activeItems_.length - this.data.maxItemsToDisplay, 0);
  7455. // b && this.splice("visibleItems", 0, b);
  7456. // if (this.isSmoothScrollEnabled_() || this.dockableMessages.length)
  7457. // this.preinsertHeight_ = this.items.clientHeight;
  7458. // this.activeItems_.unshift("visibleItems");
  7459. // try {
  7460. // this.push.apply(this, this.activeItems_)
  7461. // } catch (c) {
  7462. // nm(c)
  7463. // }
  7464. // this.activeItems_ = [];
  7465. // this.isSmoothScrollEnabled_() ? this.canScrollToBottom_() && zQ(function() {
  7466. // a.showNewItems_()
  7467. // }) : zQ(function() {
  7468. // a.maybeScrollToBottom_()
  7469. // })
  7470. } else if (sfi === '0.137.81' || sfi === '0.138.81') {
  7471. // e.g. https://www.youtube.com/yts/jsbin/live_chat_polymer-vflCyWEBP/live_chat_polymer.js
  7472. } else {
  7473. assertor(() => fnIntegrity(mclp.flushActiveItems_, '0.158.86'))
  7474. || logFn('mclp.flushActiveItems_', mclp.flushActiveItems_)();
  7475. }
  7476. }
  7477.  
  7478. let hasMoreMessageState = !ENABLE_SHOW_MORE_BLINKER ? -1 : 0;
  7479.  
  7480. mclp.flushActiveItems66a_ = mclp.flushActiveItems_;
  7481. // let lastLastRow = null;
  7482.  
  7483.  
  7484. const preloadFn = (acItems) => {
  7485. let waitFor = [];
  7486. /** @type {Set<string>} */
  7487. const imageLinks = new Set();
  7488. imageLinks.add = imageLinks.addOriginal || imageLinks.add;
  7489.  
  7490. if (ENABLE_PRELOAD_THUMBNAIL || EMOJI_IMAGE_SINGLE_THUMBNAIL || AUTHOR_PHOTO_SINGLE_THUMBNAIL) {
  7491. for (const item of acItems) {
  7492. fixLiveChatItem(item, imageLinks);
  7493. }
  7494. }
  7495. if (ENABLE_PRELOAD_THUMBNAIL && kptPF !== null && (kptPF & (8 | 4)) && imageLinks.size > 0) {
  7496.  
  7497. // reference: https://github.com/Yuanfang-fe/Blog-X/issues/34
  7498. const rel = kptPF & 8 ? 'subresource' : kptPF & 16 ? 'preload' : kptPF & 4 ? 'prefetch' : '';
  7499. // preload performs the high priority fetching.
  7500. // prefetch delays the chat display if the video resoruce is demanding.
  7501.  
  7502. if (rel) {
  7503.  
  7504. imageLinks.forEach(imageLink => {
  7505. let d = false;
  7506. if (SKIP_PRELOAD_EMOJI && imageLink.includes('.ggpht.com/')) return;
  7507. const isEmoji = imageLink.includes('/emoji/');
  7508. const pretechedSet = isEmoji ? emojiPrefetched : authorPhotoPrefetched;
  7509. if (!pretechedSet.has(imageLink)) {
  7510. pretechedSet.add(imageLink);
  7511. d = true;
  7512. }
  7513. if (d) {
  7514. waitFor.push(linker(null, rel, imageLink, 'image'));
  7515.  
  7516. }
  7517. })
  7518.  
  7519. }
  7520.  
  7521. }
  7522. imageLinks.clear();
  7523.  
  7524. return async () => {
  7525. if (waitFor.length > 0) {
  7526. await Promise.race([new Promise(r => setTimeout(r, 250)), Promise.all(waitFor)]);
  7527. }
  7528. waitFor.length = 0;
  7529. waitFor = null;
  7530. };
  7531.  
  7532. };
  7533.  
  7534.  
  7535.  
  7536. if(ENABLE_CHAT_MESSAGES_BOOSTED_STAMPING && `${mclp.flushActiveItems_}`.includes("this.push.apply(this,this.activeItems_)") && `${mclp.flushActiveItems_}`.includes(`this.splice("visibleItems",0,`) && !cProto.notifyPath371){
  7537.  
  7538.  
  7539.  
  7540. {
  7541.  
  7542.  
  7543. rendererStamperFactory(cProto, {
  7544. key: 'proceedStampDomArraySplices381_',
  7545. stamperDomClass: 'style-scope yt-live-chat-item-list-renderer yt-live-chat-item-list-stampdom',
  7546. preloadFn
  7547. });
  7548. cProto.notifyPath371 = cProto.notifyPath;
  7549.  
  7550.  
  7551. cProto.stampDomArraySplices381_ = cProto.stampDomArraySplices_;
  7552.  
  7553. cProto.stampDomArraySplices_ = function (a, b, c) {
  7554. if (a === 'visibleItems' && b === 'items' && (c || 0).indexSplices) {
  7555. // if (this.ec388) {
  7556. const indexSplices = c.indexSplices;
  7557. if (indexSplices.length === 1 || typeof indexSplices.length === "undefined") {
  7558. const indexSplice = indexSplices[0] || indexSplices;
  7559. if (indexSplice.type === 'splice' && (indexSplice.addedCount >= 1 || (indexSplice.removed || []).length >= 1)) {
  7560. // console.log(1059, a, b, indexSplice);
  7561. if (this.proceedStampDomArraySplices381_(a, b, indexSplice)) return;
  7562. }
  7563. }
  7564. // } else {
  7565. // console.warn('stampDomArraySplices_ warning', ...arguments);
  7566. // }
  7567. }
  7568. return this.stampDomArraySplices381_(...arguments);
  7569. }
  7570.  
  7571. cProto.stampDomArray366_ = cProto.stampDomArray_;
  7572. cProto.stampDomArray_ = function (items, containerId, componentConfig, rxConfig, shouldCallback, isStableList) {
  7573. const isTickerRendering = items === this.tickerItems && containerId === 'ticker-items';
  7574. const isMessageListRendering = items === this.visibleItems && containerId === 'items';
  7575. if(!isTickerRendering && !isMessageListRendering){
  7576. console.log('stampDomArray_ warning 0xF501', ...arguments)
  7577. return this.stampDomArray366_(...arguments);
  7578. }
  7579.  
  7580. const container = (this.$ || 0)[containerId];
  7581. if (!container) {
  7582. console.log('stampDomArray_ warning 0xF502', ...arguments)
  7583. return this.stampDomArray366_(...arguments);
  7584. }
  7585.  
  7586. if (container[sFirstElementChild] === null && items.length === 0) {
  7587.  
  7588. } else {
  7589. const cTag = isTickerRendering ? 'tickerItems' : 'visibleItems';
  7590. this.proceedStampDomArraySplices381_(cTag, containerId, {
  7591. addedCount: items.length,
  7592. removedCount: container.childElementCount
  7593. });
  7594. }
  7595.  
  7596. const f = () => {
  7597. this.markDirty && this.markDirty();
  7598. const detail = {
  7599. container
  7600. };
  7601. shouldCallback && this.hostElement.dispatchEvent(new CustomEvent("yt-rendererstamper-finished", {
  7602. bubbles: !0,
  7603. cancelable: !1,
  7604. composed: !0,
  7605. detail
  7606. }));
  7607. detail.container = null;
  7608. };
  7609.  
  7610. if (this.ec389pr) {
  7611. this.ec389pr.then(f)
  7612. } else {
  7613. f();
  7614. }
  7615.  
  7616. };
  7617.  
  7618. mclp.push377 = mclp.push;
  7619. mclp.splice377 = mclp.splice;
  7620.  
  7621.  
  7622.  
  7623. const emptyArr = [];
  7624. emptyArr.push = () => 0;
  7625. emptyArr.unshift = () => 0;
  7626. emptyArr.pop = () => void 0;
  7627. emptyArr.shift = () => void 0;
  7628. emptyArr.splice = () => void 0;
  7629. emptyArr.slice = function () { return this };
  7630.  
  7631.  
  7632. mclp.push = function (cTag, ...fnArgs) {
  7633. if (cTag !== 'visibleItems' || !fnArgs.length || !fnArgs[0]) return this.push377(...arguments);
  7634. const arr = this.visibleItems;
  7635. const len = arr.length;
  7636. const newTotalLen = arr.push(...fnArgs);
  7637. const addedCount = fnArgs.length;
  7638. // console.log('push')
  7639. this.proceedStampDomArraySplices381_('visibleItems', 'items', {
  7640. index: len, addedCount: addedCount, removedCount: 0
  7641. })
  7642. return newTotalLen;
  7643. }
  7644.  
  7645. mclp.splice = function (cTag, ...fnArgs) {
  7646. if (cTag !== 'visibleItems' || !fnArgs.length || (fnArgs.length === 2 && !fnArgs[1]) || (fnArgs.length > 2 && !fnArgs[2])) return this.splice377(...arguments);
  7647. const arr = this.visibleItems;
  7648. const removed = arr.splice(...fnArgs);
  7649. const removedCount = removed.length;
  7650. const addedCount = (fnArgs.length > 2 ? fnArgs.length - 2 : 0);
  7651. if (fnArgs.length >= 2 && removedCount !== fnArgs[1]) {
  7652. console.warn(`incorrect splice count. expected = ${fnArgs[1]}; actual = ${removedCount}`);
  7653. }
  7654. // console.log('splice')
  7655. this.proceedStampDomArraySplices381_('visibleItems', 'items', {
  7656. index: fnArgs[0], addedCount: addedCount, removedCount
  7657. })
  7658. return removed;
  7659. }
  7660.  
  7661.  
  7662.  
  7663. }
  7664.  
  7665. /*
  7666. mclp.flushActiveItems66b_ = function () {
  7667.  
  7668. let prWait = null;
  7669. let shouldProceedNextFlushActiveItems = false;
  7670.  
  7671. try {
  7672.  
  7673.  
  7674. const activeItems_ = this.activeItems_;
  7675. const activeItemsCount = activeItems_.length;
  7676. const maxItemsToDisplay = this.data.maxItemsToDisplay;
  7677. if (activeItemsCount > maxItemsToDisplay) {
  7678. activeItems_.splice(0, activeItemsCount - maxItemsToDisplay);
  7679. }
  7680. const qLen = this.visibleItems.length;
  7681. const pr0 = this.prDelay288;
  7682. const pr = this.prDelay288 = new PromiseExternal();
  7683. this.ec377 = true;
  7684. const ec378 = this.ec378 = new Array(qLen).fill(0).map((e, idx) => idx);
  7685. this.flushActiveItems66a_();
  7686. this.ec377 = false;
  7687. this.ec378 = null;
  7688. this.prDelay288 = pr0;
  7689. this.activeItems_ = typeof activeItems_[0] === 'string' ? activeItems_.slice(1) : activeItems_;
  7690. wme.data = `${(wme.data & 7) + 1}`;
  7691. const isSuccess = this.renderSplicedList323(ec378, qLen, pr);
  7692. if (isSuccess) {
  7693. // console.log('19949 - ok')
  7694. this.prDelay288 = pr;
  7695. shouldProceedNextFlushActiveItems = true;
  7696.  
  7697. wme.data = `${(wme.data & 7) + 1}`;
  7698. prWait = wmp;
  7699.  
  7700. } else if (activeItemsCount === 0 || !this.canScrollToBottom_()) {
  7701. // skip
  7702. } else {
  7703. const ppr = ((slist, qLen, pr) => {
  7704. const deleteCount = (typeof slist[0] === 'number') ? slist[0] : qLen;
  7705. let newAt = qLen - deleteCount;
  7706. if (newAt > 0 && slist[newAt - 1] !== qLen - 1) return 3;
  7707. if (newAt > slist.length) return 4;
  7708. if (newAt < slist.length && typeof slist[newAt] === 'number') return 5;
  7709. const addedCount = slist.length - newAt;
  7710. // if (deleteCount > addedCount) return 6;
  7711.  
  7712. if (deleteCount === 0 && addedCount === 0) return 7;
  7713.  
  7714. })(ec378, qLen, pr);
  7715.  
  7716. console.log('19949 - ng', ppr)
  7717.  
  7718. const pr2 = this.prDelay288 = new PromiseExternal();
  7719. this.flushActiveItems66a_();
  7720. pr2.resolve();
  7721. shouldProceedNextFlushActiveItems = true;
  7722.  
  7723. wme.data = `${(wme.data & 7) + 1}`;
  7724. prWait = wmp;
  7725.  
  7726. }
  7727.  
  7728. } catch (e) {
  7729.  
  7730. console.warn(e);
  7731. }
  7732.  
  7733.  
  7734. const pr5 = this.prDelay288;
  7735.  
  7736. (async ()=>{
  7737. await pr5;
  7738. await prWait;
  7739. flushActiveItemExecuted = false;
  7740. if (shouldProceedNextFlushActiveItems && this.activeItems_.length > 0) setTimeout(() => this.flushActiveItems_(), 0);
  7741. })();
  7742.  
  7743. }
  7744. */
  7745.  
  7746.  
  7747. mclp.flushActiveItemsFix001_ = function () {
  7748.  
  7749. // fix YouTube wrong code
  7750. // var b = Math.max(this.visibleItems.length + this.activeItems_.length - this.data.maxItemsToDisplay, 0);
  7751. // b && this.splice("visibleItems", 0, b);
  7752. // e.g. 0 + 99 - 90 = 9
  7753.  
  7754. const data = this.data;
  7755. if (!data) return;
  7756. const visibleItems = this.visibleItems;
  7757. const activeItems_ = this.activeItems_;
  7758. if (!visibleItems || !activeItems_) return;
  7759. const viLen = visibleItems.length;
  7760. const aiLen = activeItems_.length;
  7761. const maxDisplayLen = data.maxItemsToDisplay;
  7762. if (!maxDisplayLen) return;
  7763. if (viLen + aiLen > maxDisplayLen) {
  7764. if (aiLen > maxDisplayLen) activeItems_.splice(0, aiLen - maxDisplayLen);
  7765. // visibleItems splice done by original flushActiveItems_
  7766. }
  7767. }
  7768.  
  7769. mclp.flushActiveItems3641_ = mclp.flushActiveItems_;
  7770.  
  7771. mclp.__moreItemButtonBlinkingCheck183__ = function () {
  7772. const hasPendingItems = (this.activeItems_ && this.activeItems_.length > 0) ? 1 : 0;
  7773. const shouldChange = (hasMoreMessageState === (1 - hasPendingItems));
  7774. if (shouldChange) {
  7775. hasMoreMessageState = hasPendingItems;
  7776. const showMore = (this.$ || 0)['show-more'];
  7777. if (showMore) {
  7778. showMore.classList.toggle('has-new-messages-miuzp', hasPendingItems ? true : false);
  7779. }
  7780. }
  7781. }
  7782.  
  7783. let ps00 = false;
  7784. mclp.flushActiveItems_ = function () {
  7785. if (ps00) return;
  7786. // console.log('flushActiveItems_')
  7787. ps00 = true;
  7788. deferCallback(this, () => {
  7789. ps00 = false;
  7790. // console.log('flushActiveItems3641_')
  7791. if (this.activeItems_.length > 0) {
  7792. const data = this.data;
  7793. if (data) {
  7794. if (data.maxItemsToDisplay > MAX_ITEMS_FOR_TOTAL_DISPLAY) data.maxItemsToDisplay = MAX_ITEMS_FOR_TOTAL_DISPLAY;
  7795. this.flushActiveItemsFix001_(); // bug fix
  7796. this.flushActiveItems3641_();
  7797. if (ENABLE_SHOW_MORE_BLINKER) {
  7798. this.__moreItemButtonBlinkingCheck183__(); // blink the button if there are activeItems remaining.
  7799. }
  7800. }
  7801. }
  7802. }).catch(console.warn);
  7803. };
  7804.  
  7805. mclp.showNewItems3641_ = mclp.showNewItems_;
  7806. mclp.refreshOffsetContainerHeight3641_ = mclp.refreshOffsetContainerHeight_;
  7807. mclp.maybeScrollToBottom3641_ = mclp.maybeScrollToBottom_;
  7808.  
  7809. let ps01 = false;
  7810. mclp.showNewItems_ = function () {
  7811. if (ps01) return;
  7812. // console.log('showNewItems_')
  7813. ps01 = true;
  7814. deferCallback(this, () => {
  7815. ps01 = false;
  7816. this.showNewItems3641_();
  7817. }).catch(console.warn);
  7818. };
  7819.  
  7820. if (!ENABLE_NO_SMOOTH_TRANSFORM && !mclp.refreshOffsetContainerHeight26_) {
  7821. let ps02 = false;
  7822. mclp.refreshOffsetContainerHeight_ = function () {
  7823. if (ps02) return;
  7824. // console.log('refreshOffsetContainerHeight_')
  7825. ps02 = true;
  7826. deferCallback(this, () => {
  7827. ps02 = false;
  7828. this.refreshOffsetContainerHeight3641_();
  7829. }).catch(console.warn);
  7830. };
  7831. }
  7832.  
  7833.  
  7834. let ps03 = false;
  7835. mclp.maybeScrollToBottom_ = function () {
  7836. if (ps03) return;
  7837. // console.log('maybeScrollToBottom_')
  7838. ps03 = true;
  7839. deferCallback(this, () => {
  7840. ps03 = false;
  7841. if (this.atBottom === true) {
  7842.  
  7843. // if (itemsResizeObserverAttached !== true && this.atBottom === true) {
  7844. // // fallback for old browser
  7845. // const itemScroller = this.itemScroller || this.$['item-scroller'] || this.querySelector('#item-scroller') || 0;
  7846. // if (itemScroller.scrollTop === 0) {
  7847. // resizeObserverFallback.observe(itemScroller);
  7848. // }
  7849. // }
  7850. } else {
  7851.  
  7852. this.maybeScrollToBottom3641_();
  7853. }
  7854. }).catch(console.warn);
  7855. };
  7856.  
  7857. mclp.onScrollItems3641_ = mclp.onScrollItems_;
  7858. mclp.maybeResizeScrollContainer3641_ = mclp.maybeResizeScrollContainer_;
  7859. mclp.handleLiveChatActions3641_ = mclp.handleLiveChatActions_;
  7860.  
  7861. let ps11 = false;
  7862. mclp.onScrollItems_ = function (a) {
  7863. if (ps11) return;
  7864. // console.log('onScrollItems_')
  7865. ps11 = true;
  7866. deferCallback(this, () => {
  7867. ps11 = false;
  7868. this.onScrollItems3641_(a);
  7869. }).catch(console.warn);
  7870. };
  7871.  
  7872. if (!ENABLE_NO_SMOOTH_TRANSFORM) { // no function for ENABLE_NO_SMOOTH_TRANSFORM
  7873. let ps12 = false;
  7874. mclp.maybeResizeScrollContainer_ = function (a) {
  7875. if (ps12) return;
  7876. // console.log('maybeResizeScrollContainer_')
  7877. ps12 = true;
  7878. deferCallback(this, () => {
  7879. ps12 = false;
  7880. this.maybeResizeScrollContainer3641_(a);
  7881. }).catch(console.warn);
  7882. };
  7883. }
  7884.  
  7885. }
  7886.  
  7887. console1.log("flushActiveItems_", "OK");
  7888. } else {
  7889. console1.log("flushActiveItems_", "NG");
  7890. }
  7891. }
  7892.  
  7893.  
  7894. if ((_flag0281_ & 0x40) == 0 ) {
  7895.  
  7896.  
  7897. let showBtnLastState = null;
  7898. let lastAtBottomState = null;
  7899. // let showMoreBtnTransitionTrigg = false;
  7900. mclp.atBottomChanged314_ = mclp.atBottomChanged_;
  7901. mclp.atBottomChanged_ = function () {
  7902.  
  7903. const currentAtBottomState = this.atBottom;
  7904. if(lastAtBottomState === currentAtBottomState) return;
  7905. lastAtBottomState = currentAtBottomState;
  7906.  
  7907. // console.log(1289, showMoreBtnTransitionTrigg)
  7908.  
  7909. /*
  7910. if (!this.___btn3848___) {
  7911. this.___btn3848___ = true;
  7912. const btn = ((this || 0).$ || 0)["show-more"] || 0;
  7913. if (btn) {
  7914. btn.addEventListener('transitionstart', (evt) => {
  7915. showMoreBtnTransitionTrigg = true;
  7916. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7917. if (newVisibility === "visible") {
  7918. const btn = evt.target;
  7919. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7920. }
  7921. });
  7922. btn.addEventListener('transitionend', (evt) => {
  7923. showMoreBtnTransitionTrigg = true;
  7924. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7925. if (newVisibility === "hidden") {
  7926. const btn = evt.target;
  7927. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7928. }
  7929. });
  7930. btn.addEventListener('transitioncancel', (evt) => {
  7931. showMoreBtnTransitionTrigg = true;
  7932. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7933. if (newVisibility === "hidden") {
  7934. const btn = evt.target;
  7935. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7936. }
  7937. });
  7938. }
  7939. }
  7940. */
  7941.  
  7942. // btn-show-more-transition
  7943. if (showMoreBtnTransitionTrigg) return;
  7944.  
  7945. const btn = ((this || 0).$ || 0)["show-more"] || 0;
  7946. if (!btn) return this.atBottomChanged314_();
  7947.  
  7948. const showBtnCurrentState = btn.hasAttribute('disabled');
  7949. if (showBtnLastState === showBtnCurrentState) return;
  7950. showBtnLastState = showBtnCurrentState;
  7951.  
  7952. if (this.visibleItems.length === 0) {
  7953. if (this.atBottom === true) {
  7954. btn.setAttribute('disabled', '');
  7955. showBtnLastState = true;
  7956. }
  7957. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7958. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7959. return;
  7960. }
  7961.  
  7962. nextBrowserTick_(() => {
  7963.  
  7964. if (showMoreBtnTransitionTrigg) return;
  7965.  
  7966. // fallback
  7967.  
  7968. // const isAtBottom = this.atBottom === true;
  7969. // if (isAtBottom) {
  7970. // if (!this.hideShowMoreAsync_) {
  7971. // this.hideShowMoreAsync_ = setTimeoutX0(function () {
  7972. // const btn = ((this || 0).$ || 0)["#show-more"] || 0;
  7973. // if (btn) btn.style.visibility = "hidden";
  7974. // }, 200 - 0.125);
  7975. // }
  7976. // } else {
  7977. // if (this.hideShowMoreAsync_) {
  7978. // clearTimeoutX0(this.hideShowMoreAsync_);
  7979. // this.hideShowMoreAsync_ = null;
  7980. // }
  7981. // const btn = ((this || 0).$ || 0)["#show-more"] || 0;
  7982. // if (btn) btn.style.visibility = "visible";
  7983. // }
  7984.  
  7985. const btn = ((this || 0).$ || 0)["show-more"] || 0;
  7986. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7987.  
  7988. if (newVisibility === "hidden") {
  7989. console.warn('show-more-btn no transition')
  7990. }
  7991.  
  7992. if (btn && btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7993.  
  7994. });
  7995.  
  7996. };
  7997.  
  7998. }
  7999.  
  8000.  
  8001.  
  8002. if ((_flag0281_ & 0x2) == 0) {
  8003. if ((mclp.handleLiveChatActions_ || 0).length === 1) {
  8004.  
  8005. const sfi = fnIntegrity(mclp.handleLiveChatActions_);
  8006. // handleLiveChatActions66_
  8007. if (sfi === '1.40.20') {
  8008. // https://www.youtube.com/s/desktop/c01ea7e3/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  8009.  
  8010.  
  8011. // f.handleLiveChatActions_ = function(a) {
  8012. // var b = this;
  8013. // a.length && (a.forEach(this.handleLiveChatAction_, this),
  8014. // this.maybeResizeScrollContainer_(a),
  8015. // this.flushActiveItems_(),
  8016. // $u(function() {
  8017. // b.maybeScrollToBottom_()
  8018. // }))
  8019. // }
  8020.  
  8021. } else if (sfi === '1.39.20') {
  8022. // TBC
  8023. } else if (sfi === '1.31.17') {
  8024. // original
  8025. } else if (mclp.handleLiveChatActions3641_){
  8026. } else {
  8027. assertor(() => fnIntegrity(mclp.handleLiveChatActions_, '1.40.20'))
  8028. || logFn('mclp.handleLiveChatActions_', mclp.handleLiveChatActions_)();
  8029. }
  8030.  
  8031. mclp.handleLiveChatActions66_ = mclp.handleLiveChatActions_;
  8032.  
  8033. mclp.handleLiveChatActions_ = function (arr) {
  8034.  
  8035. try {
  8036. preprocessChatLiveActions(arr);
  8037. } catch (e) {
  8038. console.warn(e);
  8039. }
  8040.  
  8041. this.handleLiveChatActions66_(arr);
  8042.  
  8043. resistanceUpdateFn_(true);
  8044. }
  8045. console1.log("handleLiveChatActions_", "OK");
  8046. } else {
  8047. console1.log("handleLiveChatActions_", "NG");
  8048. }
  8049. }
  8050.  
  8051. // we do not need to do user interaction check for Boost Chat (0x40000)
  8052. const noScrollToBottomCheckForBoostChat = (_flag0281_ & 0x40000) === 0x40000;
  8053.  
  8054. if (noScrollToBottomCheckForBoostChat === false) {
  8055.  
  8056. mclp.hasUserJustInteracted11_ = () => {
  8057. const t = dateNow();
  8058. return (t - lastWheel < 80) || currentMouseDown || currentTouchDown || (t - lastUserInteraction < 80);
  8059. }
  8060.  
  8061. if ((mclp.canScrollToBottom_ || 0).length === 0 && !mclp.canScrollToBottom157_) {
  8062.  
  8063. assertor(() => fnIntegrity(mclp.canScrollToBottom_, '0.9.5'));
  8064.  
  8065. mclp.canScrollToBottom157_ = mclp.canScrollToBottom_;
  8066. mclp.canScrollToBottom_ = function () {
  8067. return this.canScrollToBottom157_() && !this.hasUserJustInteracted11_();
  8068. }
  8069.  
  8070. console1.log("canScrollToBottom_", "OK");
  8071.  
  8072.  
  8073. } else {
  8074. console1.log("canScrollToBottom_", "NG");
  8075. }
  8076.  
  8077. }
  8078.  
  8079. if (ENABLE_NO_SMOOTH_TRANSFORM) {
  8080.  
  8081. mclp.isSmoothScrollEnabled_ = function () {
  8082. return false;
  8083. }
  8084.  
  8085. mclp.maybeResizeScrollContainer_ = function () {
  8086. //
  8087. }
  8088.  
  8089. mclp.refreshOffsetContainerHeight_ = function () {
  8090. //
  8091. }
  8092.  
  8093. mclp.smoothScroll_ = function () {
  8094. //
  8095. }
  8096.  
  8097. mclp.resetSmoothScroll_ = function () {
  8098. //
  8099. }
  8100. console1.log("ENABLE_NO_SMOOTH_TRANSFORM", "OK");
  8101. } else {
  8102. console1.log("ENABLE_NO_SMOOTH_TRANSFORM", "NG");
  8103. }
  8104.  
  8105. if ((_flag0281_ & 0x8) == 0) {
  8106.  
  8107.  
  8108. if (typeof mclp.forEachItem_ === 'function' && !mclp.forEachItem66_ && skipErrorForhandleAddChatItemAction_ && mclp.forEachItem_.length === 1) {
  8109.  
  8110. mclp.forEachItem66_ = mclp.forEachItem_;
  8111. mclp.forEachItem_ = function (a) {
  8112.  
  8113. if ((this._flag0281_ & 0x8) == 0x8) return this.forEachItem66_(a);
  8114.  
  8115. // ƒ (a){this.visibleItems.forEach(a.bind(this,"visibleItems"));this.activeItems_.forEach(a.bind(this,"activeItems_"))}
  8116.  
  8117. try {
  8118.  
  8119. let items801 = false;
  8120. if (typeof a === 'function') {
  8121. const items = this.items;
  8122. if (items instanceof HTMLDivElement) {
  8123. const ev = this.visibleItems;
  8124. const ea = this.activeItems_;
  8125. if (ev && ea && ev.length >= 0 && ea.length >= 0) {
  8126. items801 = items;
  8127. }
  8128. }
  8129. }
  8130.  
  8131. if (items801) {
  8132. items801.__children801__ = 1;
  8133. const res = this.forEachItem66_(a);
  8134. items801.__children801__ = 0;
  8135. return res;
  8136. }
  8137.  
  8138. } catch (e) { }
  8139. return this.forEachItem66_(a);
  8140.  
  8141.  
  8142. // this.visibleItems.forEach((val, idx, arr)=>{
  8143. // a.call(this, 'visibleItems', val, idx, arr);
  8144. // });
  8145.  
  8146. // this.activeItems_.forEach((val, idx, arr)=>{
  8147. // a.call(this, 'activeItems_', val, idx, arr);
  8148. // });
  8149.  
  8150.  
  8151.  
  8152. }
  8153.  
  8154.  
  8155. }
  8156.  
  8157. }
  8158.  
  8159. if (typeof mclp.handleAddChatItemAction_ === 'function' && !mclp.handleAddChatItemAction66_ && FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION && (EMOJI_IMAGE_SINGLE_THUMBNAIL || AUTHOR_PHOTO_SINGLE_THUMBNAIL)) {
  8160.  
  8161. mclp.handleAddChatItemAction66_ = mclp.handleAddChatItemAction_;
  8162. mclp.handleAddChatItemAction_ = function (a) {
  8163. try {
  8164. if (a && typeof a === 'object' && !('length' in a)) {
  8165. fixLiveChatItem(a.item, null);
  8166. console.assert(arguments[0] === a);
  8167. }
  8168. } catch (e) { console.warn(e) }
  8169. let res;
  8170. if (skipErrorForhandleAddChatItemAction_) { // YouTube Native Engine Issue
  8171. try {
  8172. res = this.handleAddChatItemAction66_.apply(this, arguments);
  8173. } catch (e) {
  8174. if (e && (e.message || '').includes('.querySelector(')) {
  8175. console.log("skipErrorForhandleAddChatItemAction_", e.message);
  8176. } else {
  8177. throw e;
  8178. }
  8179. }
  8180. } else {
  8181. res = this.handleAddChatItemAction66_.apply(this, arguments);
  8182. }
  8183. return res;
  8184. }
  8185.  
  8186. if (FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION) console1.log("handleAddChatItemAction_ [ FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION ]", "OK");
  8187. } else {
  8188.  
  8189. if (FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION) console1.log("handleAddChatItemAction_ [ FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION ]", "OK");
  8190. }
  8191.  
  8192.  
  8193. if (typeof mclp.handleReplaceChatItemAction_ === 'function' && !mclp.handleReplaceChatItemAction66_ && FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT && (EMOJI_IMAGE_SINGLE_THUMBNAIL || AUTHOR_PHOTO_SINGLE_THUMBNAIL)) {
  8194.  
  8195. mclp.handleReplaceChatItemAction66_ = mclp.handleReplaceChatItemAction_;
  8196. mclp.handleReplaceChatItemAction_ = function (a) {
  8197. try {
  8198. if (a && typeof a === 'object' && !('length' in a)) {
  8199. fixLiveChatItem(a.replacementItem, null);
  8200. console.assert(arguments[0] === a);
  8201. }
  8202. } catch (e) { console.warn(e) }
  8203. return this.handleReplaceChatItemAction66_.apply(this, arguments);
  8204. }
  8205.  
  8206. if (FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT) console1.log("handleReplaceChatItemAction_ [ FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT ]", "OK");
  8207. } else {
  8208.  
  8209. if (FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT) console1.log("handleReplaceChatItemAction_ [ FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT ]", "OK");
  8210. }
  8211.  
  8212. console1.log("[End]");
  8213. groupEnd();
  8214.  
  8215. }).catch(console.warn);
  8216.  
  8217.  
  8218. const tickerContainerSetAttribute = function (attrName, attrValue) { // ensure '14.30000001%'.toFixed(1)
  8219.  
  8220. let yd = (this.__dataHost || insp(this).__dataHost || 0).__data;
  8221.  
  8222. if (arguments.length === 2 && attrName === 'style' && yd && attrValue) {
  8223.  
  8224. // let v = yd.containerStyle.privateDoNotAccessOrElseSafeStyleWrappedValue_;
  8225. let v = `${attrValue}`;
  8226. // conside a ticker is 101px width
  8227. // 1% = 1.01px
  8228. // 0.2% = 0.202px
  8229.  
  8230.  
  8231. const ratio1 = (yd.ratio * 100);
  8232. if (ratio1 > -1) { // avoid NaN
  8233.  
  8234. // countdownDurationMs
  8235. // 600000 - 0.2% <1% = 6s> <0.2% = 1.2s>
  8236. // 300000 - 0.5% <1% = 3s> <0.5% = 1.5s>
  8237. // 150000 - 1% <1% = 1.5s>
  8238. // 75000 - 2% <1% =0.75s > <2% = 1.5s>
  8239. // 30000 - 5% <1% =0.3s > <5% = 1.5s>
  8240.  
  8241. // 99px * 5% = 4.95px
  8242.  
  8243. // 15000 - 10% <1% =0.15s > <10% = 1.5s>
  8244.  
  8245.  
  8246. // 1% Duration
  8247.  
  8248. let ratio2 = ratio1;
  8249.  
  8250. const ydd = yd.data;
  8251. if (ydd) {
  8252.  
  8253. const d1 = ydd.durationSec;
  8254. const d2 = ydd.fullDurationSec;
  8255.  
  8256. // @ step timing [min. 0.2%]
  8257. let numOfSteps = 500;
  8258. if ((d1 === d2 || (d1 + 1 === d2)) && d1 > 1) {
  8259. if (d2 > 400) numOfSteps = 500; // 0.2%
  8260. else if (d2 > 200) numOfSteps = 200; // 0.5%
  8261. else if (d2 > 100) numOfSteps = 100; // 1%
  8262. else if (d2 > 50) numOfSteps = 50; // 2%
  8263. else if (d2 > 25) numOfSteps = 20; // 5% (max => 99px * 5% = 4.95px)
  8264. else numOfSteps = 20;
  8265. }
  8266. if (numOfSteps > TICKER_MAX_STEPS_LIMIT) numOfSteps = TICKER_MAX_STEPS_LIMIT;
  8267. if (numOfSteps < 5) numOfSteps = 5;
  8268.  
  8269. const rd = numOfSteps / 100.0;
  8270.  
  8271. ratio2 = Math.round(ratio2 * rd) / rd;
  8272.  
  8273. // ratio2 = Math.round(ratio2 * 5) / 5;
  8274. ratio2 = ratio2.toFixed(1);
  8275. v = v.replace(`${ratio1}%`, `${ratio2}%`).replace(`${ratio1}%`, `${ratio2}%`);
  8276.  
  8277. if (yd.__style_last__ === v) return;
  8278. yd.__style_last__ = v;
  8279. // do not consider any delay here.
  8280. // it shall be inside the looping for all properties changes. all the css background ops are in the same microtask.
  8281.  
  8282. }
  8283. }
  8284.  
  8285. HTMLElement_.prototype.setAttribute.call(dr(this), attrName, v);
  8286.  
  8287.  
  8288. } else {
  8289. HTMLElement_.prototype.setAttribute.apply(dr(this), arguments);
  8290. }
  8291.  
  8292. };
  8293.  
  8294.  
  8295. const fpTicker = (renderer) => {
  8296. const cnt = insp(renderer);
  8297. assertor(() => typeof (cnt || 0).is === 'string');
  8298. assertor(() => ((cnt || 0).hostElement || 0).nodeType === 1);
  8299. const container = (cnt.$ || 0).container;
  8300. if (container) {
  8301. assertor(() => (container || 0).nodeType === 1);
  8302. assertor(() => typeof container.setAttribute === 'function');
  8303. container.setAttribute = tickerContainerSetAttribute;
  8304. } else {
  8305. console.warn(`"container" does not exist in ${cnt.is}`);
  8306. }
  8307. };
  8308.  
  8309.  
  8310. const tags = [
  8311. "yt-live-chat-ticker-renderer",
  8312. "yt-live-chat-ticker-paid-message-item-renderer",
  8313. "yt-live-chat-ticker-paid-sticker-item-renderer",
  8314. "yt-live-chat-ticker-sponsor-item-renderer"
  8315. ];
  8316.  
  8317. const tagsItemRenderer = [
  8318. "yt-live-chat-ticker-renderer",
  8319. "yt-live-chat-ticker-paid-message-item-renderer",
  8320. "yt-live-chat-ticker-paid-sticker-item-renderer",
  8321. "yt-live-chat-ticker-sponsor-item-renderer"
  8322. ];
  8323.  
  8324. // const wmList = new Set;
  8325.  
  8326. true && (new MutationObserver((mutations) => {
  8327.  
  8328. const s = new Set();
  8329. for (const mutation of mutations) {
  8330. if (mutation.type === 'attributes') {
  8331. s.add(mutation.target);
  8332. }
  8333. }
  8334. for (const target of s) {
  8335. const p = target && target.isConnected === true ? target.getAttribute('q92wb') : '';
  8336. if (p === '1') {
  8337. target.setAttribute('q92wb', '2');
  8338. const cnt = insp(target);
  8339. const dataId = ((cnt || 0).data || 0).id;
  8340. if (cnt && typeof cnt.requestRemoval49 === 'function' && dataId) {
  8341. target.id = dataId;
  8342. cnt.requestRemoval49();
  8343. target.setAttribute('q92wb', '3');
  8344. }
  8345. } else if (p === '3') {
  8346. target.setAttribute('q92wb', '4');
  8347. const cnt = insp(target);
  8348. const dataId = ((cnt || 0).data || 0).id;
  8349. if (cnt && typeof cnt.requestRemoval49 === 'function' && dataId) {
  8350. target.id = dataId;
  8351. const parentComponent = target.closest('yt-live-chat-ticker-renderer') || cnt.parentComponent;
  8352. const parentCnt = insp(parentComponent);
  8353. if(parentComponent && parentCnt && parentCnt.removeTickerItemById){
  8354. parentCnt.removeTickerItemById(dataId);
  8355. target.setAttribute('q92wb', '5');
  8356. }
  8357. }
  8358. }
  8359. }
  8360. s.clear();
  8361.  
  8362. })).observe(document, { attributes: true, attributeFilter: ['q92wb'], subtree: true });
  8363.  
  8364. Promise.all(tags.map(tag => customElements.whenDefined(tag))).then(() => {
  8365.  
  8366. mightFirstCheckOnYtInit();
  8367. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-ticker-... hacks");
  8368. console1.log("[Begin]");
  8369.  
  8370.  
  8371. let tickerAttachmentId = 0;
  8372.  
  8373.  
  8374. const __requestRemoval__ = function (cnt) {
  8375. if (cnt.hostElement && typeof cnt.requestRemoval === 'function') {
  8376. try {
  8377. const id = (cnt.data || 0).id;
  8378. if (!id) cnt.data = { id: 1 };
  8379. } catch (e) { }
  8380. try {
  8381. cnt.requestRemoval();
  8382. return true;
  8383. } catch (e) { }
  8384. }
  8385. return false;
  8386. }
  8387.  
  8388.  
  8389. const overlayBgMap = new WeakMap();
  8390.  
  8391. const dProto = {
  8392.  
  8393.  
  8394. /**
  8395. *
  8396.  
  8397. f.updateStatsBarAndMaybeShowAnimation = function(a, b, c) {
  8398. var d = this;
  8399. a || c();
  8400. a && this.statsBar && this.username && this.textContent && (this.isMouseOver ? (b(),
  8401. c()) : (a = this.animateShowStats(),
  8402. this.data.animationOrigin && this.data.trackingParams && aB().stateChanged(this.data.trackingParams, {
  8403. animationEventData: {
  8404. origin: this.data.animationOrigin
  8405. }
  8406. }),
  8407. a.finished.then(function() {
  8408. var e;
  8409. setTimeout(function() {
  8410. b();
  8411. c();
  8412. if (!d.isMouseOver) {
  8413. var g, k;
  8414. d.animateHideStats(((g = d.data) == null ? void 0 : g.dynamicStateData.stateSlideDurationMs) || 0, ((k = d.data) == null ? void 0 : k.dynamicStateData.stateUpdateDelayAfterMs) || 0)
  8415. }
  8416. }, ((e = d.data) == null ? void 0 : e.dynamicStateData.stateUpdateDelayBeforeMs) || 0)
  8417. })))
  8418. }
  8419.  
  8420. *
  8421. */
  8422.  
  8423.  
  8424.  
  8425. /**
  8426. *
  8427. *
  8428.  
  8429. f.animateShowStats = function() {
  8430. var a = this.textContent.animate({
  8431. transform: "translateY(-30px)"
  8432. }, {
  8433. duration: this.data.dynamicStateData.stateSlideDurationMs,
  8434. fill: "forwards"
  8435. });
  8436. this.username.animate({
  8437. opacity: 0
  8438. }, {
  8439. duration: 500,
  8440. fill: "forwards"
  8441. });
  8442. this.statsBar.animate({
  8443. opacity: 1
  8444. }, {
  8445. duration: 500,
  8446. fill: "forwards"
  8447. });
  8448. return a
  8449. }
  8450. ;
  8451. f.animateHideStats = function(a, b) {
  8452. this.textContent.animate({
  8453. transform: "translateY(0)"
  8454. }, {
  8455. duration: a,
  8456. fill: "forwards",
  8457. delay: b
  8458. });
  8459. this.username.animate({
  8460. opacity: 1
  8461. }, {
  8462. duration: 300,
  8463. fill: "forwards",
  8464. delay: b
  8465. });
  8466. this.statsBar.animate({
  8467. opacity: 0
  8468. }, {
  8469. duration: 300,
  8470. fill: "forwards",
  8471. delay: b
  8472. })
  8473. }
  8474. *
  8475. */
  8476.  
  8477. updateStatsBarAndMaybeShowAnimationRevised: function (a, b, c) {
  8478. // prevent memory leakage due to d.data was asked in a.finished.then
  8479. try{
  8480. // console.log('updateStatsBarAndMaybeShowAnimation called', this.is)
  8481. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8482. return this.updateStatsBarAndMaybeShowAnimation38.call(this.__proxySelf0__, a, b, c);
  8483. }catch(e){
  8484. console.log('updateStatsBarAndMaybeShowAnimationRevised ERROR');
  8485. console.error(e);
  8486. }
  8487. },
  8488.  
  8489. detachedForMemoryLeakage: function () {
  8490.  
  8491. try{
  8492.  
  8493. this.actionHandlerBehavior.unregisterActionMap(this.behaviorActionMap)
  8494.  
  8495. // this.behaviorActionMap = 0;
  8496. // this.isVisibilityRoot = 0;
  8497.  
  8498.  
  8499. }catch(e){}
  8500.  
  8501. return this.detached582MemoryLeak();
  8502. },
  8503.  
  8504. detachedForTickerInit: function () {
  8505.  
  8506. Promise.resolve(this).then((cnt) => {
  8507. if (cnt.isAttached) return;
  8508. cnt.isAttached === false && ((cnt.$ || 0).container || 0).isConnected === false && __requestRemoval__(cnt);
  8509. cnt.rafId > 1 && rafHub.cancel(cnt.rafId);
  8510. }).catch(console.warn);
  8511.  
  8512.  
  8513. const hostElement = (this || 0).hostElement;
  8514. if (USE_ADVANCED_TICKING && (this || 0).__isTickerItem58__ && hostElement instanceof HTMLElement_) {
  8515. // otherwise the startCountDown not working
  8516. hostElement.style.removeProperty('--ticker-start-time');
  8517. hostElement.style.removeProperty('--ticker-duration-time');
  8518.  
  8519. if (kRef(qWidthAdjustable) === hostElement) {
  8520.  
  8521. // need to update the first ticker
  8522. const q = document.querySelector('.r6-width-adjustable');
  8523. if (q instanceof HTMLElement_ && q.classList.contains('r6-width-adjustable-f')) {
  8524. q.classList.remove('r6-width-adjustable-f');
  8525. }
  8526. qWidthAdjustable = mWeakRef(q);
  8527.  
  8528. }
  8529. }
  8530.  
  8531. let r;
  8532. try {
  8533. r = this.detached77();
  8534. } catch (e) {
  8535. console.warn(e);
  8536. }
  8537. this.__ticker_attachmentId__ = 0;
  8538. return r;
  8539. },
  8540.  
  8541. attachedForTickerInit: function () {
  8542. this.__ticker_attachmentId__ = tickerAttachmentId = (tickerAttachmentId & 1073741823) + 1;
  8543.  
  8544. const hostElement = (this || 0).hostElement;
  8545. if (USE_ADVANCED_TICKING && (this || 0).__isTickerItem58__ && hostElement instanceof HTMLElement_) {
  8546. const prevElement = kRef(qWidthAdjustable);
  8547. if (prevElement instanceof HTMLElement_) {
  8548. prevElement.classList.add('r6-width-adjustable-f');
  8549. }
  8550. if (hostElement.__fgvm573__) {
  8551. hostElement.classList.remove('r6-closing-ticker');
  8552. hostElement.classList.remove('r6-width-adjustable-f');
  8553. } else {
  8554. hostElement.__fgvm573__ = 1;
  8555. hostElement.classList.add('r6-width-adjustable');
  8556. }
  8557. qWidthAdjustable = mWeakRef(hostElement);
  8558. }
  8559.  
  8560.  
  8561. fpTicker(hostElement || this);
  8562. return this.attached77();
  8563.  
  8564. },
  8565.  
  8566.  
  8567.  
  8568. setContainerWidthNoSelfLeakage: function(){
  8569. // prevent memory leakage due ot delay function
  8570. try{
  8571. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8572. return this.setContainerWidth55.call(this.__proxySelf0__);
  8573. }catch(e){
  8574. console.log('setContainerWidthNoSelfLeakage ERROR');
  8575. console.error(e);
  8576. }
  8577.  
  8578. },
  8579.  
  8580. slideDownNoSelfLeakage: function(){
  8581. // prevent memory leakage due ot delay function
  8582. try{
  8583. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8584. return this.slideDown55.call(this.__proxySelf0__);
  8585. }catch(e){
  8586. console.log('slideDownNoSelfLeakage ERROR');
  8587. console.error(e);
  8588. }
  8589.  
  8590. },
  8591.  
  8592. collapseNoSelfLeakage: function(){
  8593. // prevent memory leakage due ot delay function
  8594. try{
  8595. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8596. return this.collapse55.call(this.__proxySelf0__);
  8597. }catch(e){
  8598. console.log('collapseNoSelfLeakage ERROR');
  8599. console.error(e);
  8600. }
  8601. },
  8602.  
  8603. deletedChangedNoSelfLeakage: function(){
  8604. // prevent memory leakage due ot delay function
  8605. try{
  8606. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8607. return this.deletedChanged55.call(this.__proxySelf0__);
  8608. }catch(e){
  8609. console.log('deletedChangedNoSelfLeakage ERROR');
  8610. console.error(e);
  8611. }
  8612.  
  8613. },
  8614.  
  8615.  
  8616.  
  8617.  
  8618. /** @type {()} */
  8619. handlePauseReplayForPlaybackProgressState: function () {
  8620. if (!playerEventsByIframeRelay) return this.handlePauseReplay66.apply(this, arguments);
  8621.  
  8622. const attachementId = this.__ticker_attachmentId__;
  8623. if(!attachementId) return;
  8624.  
  8625. const jr = mWeakRef(this);
  8626.  
  8627. if (onPlayStateChangePromise) {
  8628.  
  8629. const tid = this._Y7rtu = (this._Y7rtu & 1073741823) + 1;
  8630.  
  8631. onPlayStateChangePromise.then(() => {
  8632. const cnt = kRef(jr) || 0;
  8633. if (attachementId !== cnt.__ticker_attachmentId__) return;
  8634. if (cnt.isAttached) {
  8635. if (tid === cnt._Y7rtu && !onPlayStateChangePromise && typeof cnt.handlePauseReplay === 'function' && cnt.hostElement) cnt.handlePauseReplay.apply(cnt, arguments);
  8636. // this.handlePauseReplay can be undefined if it is memory cleaned
  8637. }
  8638. });
  8639.  
  8640. return;
  8641. }
  8642.  
  8643. if (playerState !== 2) return;
  8644. if (this.isAttached) {
  8645. const tid = this._Y7rtk = (this._Y7rtk & 1073741823) + 1;
  8646. const tc = relayCount;
  8647. foregroundPromiseFn().then(() => {
  8648. const cnt = kRef(jr);
  8649. if (attachementId !== (cnt || 0).__ticker_attachmentId__) return;
  8650. if (cnt.isAttached) {
  8651. if (tid === cnt._Y7rtk && tc === relayCount && playerState === 2 && _playerState === playerState && cnt.hostElement) {
  8652. cnt.handlePauseReplay66();
  8653. }
  8654. }
  8655. })
  8656. }
  8657. },
  8658.  
  8659. /** @type {()} */
  8660. handleResumeReplayForPlaybackProgressState: function () {
  8661. if (!playerEventsByIframeRelay) return this.handleResumeReplay66.apply(this, arguments);
  8662.  
  8663. const attachementId = this.__ticker_attachmentId__;
  8664. if(!attachementId) return;
  8665.  
  8666. const jr = mWeakRef(this);
  8667. if (onPlayStateChangePromise) {
  8668.  
  8669. const tid = this._Y7rtv = (this._Y7rtv & 1073741823) + 1;
  8670.  
  8671. onPlayStateChangePromise.then(() => {
  8672. const cnt = kRef(jr);
  8673. if(attachementId !== (cnt || 0).__ticker_attachmentId__) return;
  8674. if (tid === cnt._Y7rtv && !onPlayStateChangePromise && typeof cnt.handleResumeReplay === 'function' && cnt.hostElement) cnt.handleResumeReplay.apply(cnt, arguments);
  8675. // this.handleResumeReplay can be undefined if it is memory cleaned
  8676. });
  8677.  
  8678. return;
  8679. }
  8680.  
  8681.  
  8682. if (playerState !== 1) return;
  8683. if (this.isAttached) {
  8684. const tc = relayCount;
  8685.  
  8686. relayPromise = relayPromise || new PromiseExternal();
  8687. relayPromise.then(() => {
  8688. const cnt = kRef(jr);
  8689. if(attachementId !== (cnt || 0).__ticker_attachmentId__) return;
  8690. if (relayCount > tc && playerState === 1 && _playerState === playerState && cnt.hostElement) {
  8691. cnt.handleResumeReplay66();
  8692. }
  8693. });
  8694. }
  8695. },
  8696.  
  8697. /** @type {(a,)} */
  8698. handleReplayProgressForPlaybackProgressState: function (a) {
  8699. if (this.isAttached) {
  8700. const attachementId = this.__ticker_attachmentId__;
  8701. if(!attachementId) return;
  8702. const tid = this._Y7rtk = (this._Y7rtk & 1073741823) + 1;
  8703. const jr = mWeakRef(kRef(this));
  8704. foregroundPromiseFn().then(() => {
  8705. const cnt = kRef(jr);
  8706. if(attachementId !== (cnt || 0).__ticker_attachmentId__) return;
  8707. if (cnt.isAttached) {
  8708. if (tid === cnt._Y7rtk && cnt.hostElement) {
  8709. cnt.handleReplayProgress66(a);
  8710. }
  8711. }
  8712. })
  8713. }
  8714. }
  8715.  
  8716.  
  8717. }
  8718.  
  8719.  
  8720.  
  8721. const isTickerItemsScrolling = function () {
  8722. const elm = document.querySelector('#ticker-bar.yt-live-chat-ticker-renderer');
  8723. if (!elm) return false;
  8724. return (elm.scrollLeft > 0);
  8725. }
  8726.  
  8727.  
  8728.  
  8729.  
  8730. const u37fn = function (cnt) {
  8731.  
  8732. if (cnt.__dataEnabled === false || cnt.__dataInvalid === true) return;
  8733.  
  8734. if (!__LCRInjection__) {
  8735. console.error('[yt-chat] USE_ADVANCED_TICKING fails because of no __LCRInjection__');
  8736. }
  8737.  
  8738. const cntData = ((cnt || 0).__data || 0).data || (cnt || 0).data || 0;
  8739. if (!cntData) return;
  8740. const cntElement = cnt.hostElement;
  8741. if (!(cntElement instanceof HTMLElement_)) return;
  8742.  
  8743. const duration = (cntData.fullDurationSec || cntData.durationSec || 0);
  8744.  
  8745. let ct;
  8746.  
  8747. if (__LCRInjection__ && cntData && duration > 0 && !('__progressAt__' in cntData)) {
  8748. ct = Date.now();
  8749.  
  8750. if (!cntData.__timestampActionRequest__) {
  8751. console.log(' 5688001 ');
  8752. // console.log(`(5688001) ${new Error().stack}`);
  8753. }
  8754. cntData.__liveTimestamp__ = (((cntData.__timestampActionRequest__ || ct) - timeOriginDT) / 1000) || Number.MIN_VALUE;
  8755. timestampUnderLiveMode = true;
  8756. } else if (__LCRInjection__ && cntData && duration > 0 && cntData.__progressAt__ > 0) {
  8757. timestampUnderLiveMode = false;
  8758. }
  8759. // console.log(48117007, cntData)
  8760.  
  8761. let tk = cntData.__progressAt__ || cntData.__liveTimestamp__;
  8762.  
  8763. if (!tk) {
  8764. console.log('time property is not found', !!__LCRInjection__, !!cntData, !!(duration > 0), !('__progressAt__' in cntData), cntData.__progressAt__, cntData.__liveTimestamp__);
  8765. return;
  8766. }
  8767.  
  8768.  
  8769.  
  8770. const liveOffsetMs = ct > 0 && cntData.__timestampActionRequest__ > 0 ? ct - cntData.__timestampActionRequest__ : 0;
  8771.  
  8772. // console.log(1237, liveOffsetMs, cntData.durationSec)
  8773.  
  8774. if (liveOffsetMs > 0) {
  8775. cntData.durationSec -= Math.floor(liveOffsetMs / 1000);
  8776. if (cntData.durationSec < 0) cntData.durationSec = 0;
  8777. // console.log(1238, liveOffsetMs, cntData.durationSec)
  8778. if (!cntData.durationSec) {
  8779. try {
  8780. cnt.requestRemoval();
  8781. } catch (e) { }
  8782. return;
  8783. }
  8784. }
  8785.  
  8786.  
  8787. let offset = cntData.fullDurationSec - cntData.durationSec; // consider this is live replay video, offset can be > 0
  8788. if (offset > 0) tk -= offset;
  8789. // in livestreaming. tk can be negative as we use performance.timeOrigin for t=0s time frame
  8790.  
  8791.  
  8792.  
  8793. const existingOverlaySelector = `ticker-bg-overlay[ticker-id="${cnt.__ticker_attachmentId__}"]`;
  8794.  
  8795. const q = kRef(overlayBgMap.get(cnt));
  8796.  
  8797. let r = valAssign(cntElement, '--ticker-start-time', tk);
  8798.  
  8799. if ((r || !q || q.isConnected === false) && duration > 0) {
  8800.  
  8801. // t0 ...... 1 ... fullDurationSec
  8802. // tk ...... k ... fullDurationSec-durationSec
  8803. // t0-fullDurationSec ...... 0 ... 0
  8804.  
  8805. // now - (fullDurationSec-durationSec)
  8806.  
  8807.  
  8808. // update dntElementWeak
  8809. const dnt = cnt.parentComponent;
  8810. const dntElement = dnt ? dnt.hostElement || dnt : 0;
  8811. if (dntElement) {
  8812. dntElementWeak = mWeakRef(dntElement);
  8813. resistanceUpdateBusy = false;
  8814. if (!startResistanceUpdaterStarted) startResistanceUpdater();
  8815. else updateTickerCurrentTime();
  8816. }
  8817.  
  8818.  
  8819. // create overlay if needed
  8820. if (!cntElement.querySelector(existingOverlaySelector)) {
  8821.  
  8822. // remove if any
  8823. const oldElement = cntElement.querySelector('ticker-bg-overlay');
  8824. if (oldElement) oldElement.remove();
  8825.  
  8826. // use advancedTicking, ticker enabled
  8827. cnt.__advancedTicking038__ = 1;
  8828.  
  8829. const em = q || document.createElement('ticker-bg-overlay');
  8830.  
  8831. overlayBgMap.set(cnt, mWeakRef(em));
  8832. // const ey = document.createElement('ticker-bg-overlay-end');
  8833. const wy = document.createElement('ticker-bg-overlay-end2');
  8834.  
  8835. const cr1 = cnt.colorFromDecimal(cntData.startBackgroundColor);
  8836. const cr2 = cnt.colorFromDecimal(cntData.endBackgroundColor);
  8837.  
  8838. const container = cnt.$.container;
  8839.  
  8840. em.setAttribute('ticker-id', `${cnt.__ticker_attachmentId__}`);
  8841.  
  8842. const tid = `ticker-${cnt.__ticker_attachmentId__}-${Math.floor(Math.random() * 314159265359 + 314159265359).toString(36)}`;
  8843.  
  8844. em.id = `${tid}-b`;
  8845. em.style.background = `linear-gradient(90deg, ${cr1},${cr1} 50%,${cr2} 50%,${cr2})`;
  8846.  
  8847. if (!(container instanceof HTMLElement_)) {
  8848. // em.insertBefore(ey, em.firstChild);
  8849. insertBeforeNaFn(cntElement, em, cntElement.firstChild); // cntElement.insertBefore(em, cntElement.firstChild);
  8850. cntElement.style.borderRadius = '16px';
  8851. container.style.borderRadius = 'initial';
  8852. } else {
  8853. // em.insertBefore(ey, em.firstChild);
  8854. insertBeforeNaFn(container, em, container.firstChild); // container.insertBefore(em, container.firstChild);
  8855. }
  8856.  
  8857. // em.style.left = '-50%';
  8858. // em.style.left = "clamp(-100%, calc( -100% * ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) ), 0%)";
  8859.  
  8860. if (container instanceof HTMLElement_) {
  8861.  
  8862. container.style.background = 'transparent';
  8863. container.style.backgroundColor = 'transparent';
  8864. // container.style.zIndex = '1';
  8865. }
  8866. // em.style.zIndex = '-1';
  8867. valAssign(cntElement, '--ticker-duration-time', duration)
  8868.  
  8869. valAssign(wy, '--ticker-start-time', tk);
  8870. valAssign(wy, '--ticker-duration-time', duration);
  8871. wy.id = `${tid}-e`;
  8872.  
  8873. appendChildNaFn(dntElement, wy);
  8874.  
  8875. // if (wio instanceof IntersectionObserver) {
  8876. // wio.observe(ey);
  8877. // }
  8878.  
  8879. const wio2 = dProto.wio2;
  8880. if (wio2 instanceof IntersectionObserver) {
  8881. wio2.observe(wy);
  8882. }
  8883.  
  8884. }
  8885. }
  8886. };
  8887.  
  8888.  
  8889.  
  8890. const timeFn749 = (cnt) => {
  8891. cnt = kRef(cnt);
  8892. if (!cnt) return;
  8893. cnt.__startCountdownAdv477__ = Date.now();
  8894.  
  8895. if (
  8896. cnt
  8897. && (cnt.hostElement && cnt.isAttached && cnt.hostElement.isConnected)
  8898. && cnt.parentComponent // startCountdown is triggered by dataChanged; // not yet attached to the actual dom tree
  8899. && cnt.__ticker_attachmentId__
  8900. ) {
  8901.  
  8902. const data = cnt.data;
  8903. const dataId = data ? ((cnt || 0).data || 0).id : null;
  8904. const elemId = ((cnt || 0).hostElement || 0).id;
  8905.  
  8906. if (dataId && dataId === elemId) {
  8907.  
  8908. const attachId = cnt.__ticker_attachmentId__;
  8909. const uid = `${attachId}!${dataId}`;
  8910.  
  8911. if (data.__wsi6c__ !== uid) {
  8912. data.__wsi6c__ = uid;
  8913. Promise.resolve(cnt).then(u37fn);
  8914. return true;
  8915. }
  8916.  
  8917. }
  8918.  
  8919. }
  8920.  
  8921. return false;
  8922. }
  8923.  
  8924. let tagI = 0;
  8925. for (const tag of tagsItemRenderer) { // ##tag##
  8926.  
  8927. tagI++;
  8928.  
  8929. const dummy = document.createElement(tag);
  8930.  
  8931. const cProto = getProto(dummy);
  8932. if (!cProto || !cProto.attached) {
  8933. console1.warn(`proto.attached for ${tag} is unavailable.`);
  8934. continue;
  8935. }
  8936.  
  8937. if (FIX_MEMORY_LEAKAGE_TICKER_ACTIONMAP && typeof cProto.detached582MemoryLeak !== 'function' && typeof cProto.detached === 'function') {
  8938. cProto.detached582MemoryLeak = cProto.detached;
  8939. cProto.detached = dProto.detachedForMemoryLeakage;
  8940. }
  8941.  
  8942. cProto.detached77 = cProto.detached;
  8943. cProto.detached = dProto.detachedForTickerInit;
  8944.  
  8945. cProto.attached77 = cProto.attached;
  8946.  
  8947. cProto.attached = dProto.attachedForTickerInit;
  8948.  
  8949. let flgLeakageFixApplied = 0;
  8950.  
  8951. if (FIX_MEMORY_LEAKAGE_TICKER_STATSBAR && typeof cProto.updateStatsBarAndMaybeShowAnimation === 'function' && !cProto.updateStatsBarAndMaybeShowAnimation38 && cProto.updateStatsBarAndMaybeShowAnimation.length === 3) {
  8952.  
  8953. cProto.updateStatsBarAndMaybeShowAnimation38 = cProto.updateStatsBarAndMaybeShowAnimation;
  8954. cProto.updateStatsBarAndMaybeShowAnimation = dProto.updateStatsBarAndMaybeShowAnimationRevised;
  8955.  
  8956. flgLeakageFixApplied |= 2;
  8957. } else {
  8958. // the function is only in yt-live-chat-ticker-paid-message-item-renderer
  8959. }
  8960.  
  8961.  
  8962. // ------------- withTimerFn_ -------------
  8963.  
  8964. let withTimerFn_ = 0;
  8965. if (typeof cProto.startCountdown === 'function' && typeof cProto.updateTimeout === 'function' && typeof cProto.isAnimationPausedChanged === 'function') {
  8966.  
  8967. // console.log('startCountdown', typeof cProto.startCountdown)
  8968. // console.log('updateTimeout', typeof cProto.updateTimeout)
  8969. // console.log('isAnimationPausedChanged', typeof cProto.isAnimationPausedChanged)
  8970.  
  8971. // <<< to be reviewed cProto.updateTimeout --- isTimingFunctionHackable -- doHack >>>
  8972. const isTimingFunctionHackable = fnIntegrity(cProto.startCountdown, '2.66.37') && fnIntegrity(cProto.updateTimeout, '1.76.45') && fnIntegrity(cProto.isAnimationPausedChanged, '2.56.30')
  8973. if (!isTimingFunctionHackable) console1.log('isTimingFunctionHackable = false');
  8974. withTimerFn_ = isTimingFunctionHackable ? 2 : 1;
  8975. } else {
  8976. let flag = 0;
  8977. if (typeof cProto.startCountdown === 'function') flag |= 1;
  8978. if (typeof cProto.updateTimeout === 'function') flag |= 2;
  8979. if (typeof cProto.isAnimationPausedChanged === 'function') flag |= 4;
  8980.  
  8981. console1.log(`Skip Timing Function Modification[#${tagI}]: ${flag} / ${1 + 2 + 4}`, ` ${tag}`);
  8982. // console.log(Object.getOwnPropertyNames(cProto))
  8983. // continue;
  8984. }
  8985.  
  8986. // ------------- withTimerFn_ -------------
  8987.  
  8988. // ------------- ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX -------------
  8989.  
  8990. let urt = 0;
  8991.  
  8992. if (ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX) {
  8993.  
  8994.  
  8995. /**
  8996. *
  8997. f.handlePauseReplay = function() {
  8998. this.isAnimationPaused = !0;
  8999. this.detlaSincePausedSecs = 0
  9000. }
  9001. */
  9002.  
  9003. /**
  9004. *
  9005.  
  9006. f.handlePauseReplay = function() {
  9007. this.isReplayPaused = !0
  9008. }
  9009. *
  9010. */
  9011.  
  9012. if (typeof cProto.handlePauseReplay === 'function' && !cProto.handlePauseReplay66 && cProto.handlePauseReplay.length === 0) {
  9013. const fi = fnIntegrity(cProto.handlePauseReplay);
  9014. urt++;
  9015. if (fi === '0.8.2' || fi === '0.12.4') {
  9016. } else {
  9017. assertor(() => fnIntegrity(cProto.handlePauseReplay, '0.12.4'));
  9018. }
  9019. } else {
  9020. if (withTimerFn_ > 0) console1.log('Error for setting cProto.handlePauseReplay', tag)
  9021. }
  9022.  
  9023. if (typeof cProto.handleResumeReplay === 'function' && !cProto.handleResumeReplay66 && cProto.handleResumeReplay.length === 0) {
  9024. urt++;
  9025. assertor(() => fnIntegrity(cProto.handleResumeReplay, '0.8.2'));
  9026. } else {
  9027. if (withTimerFn_ > 0) console1.log('Error for setting cProto.handleResumeReplay', tag)
  9028. }
  9029.  
  9030. if (typeof cProto.handleReplayProgress === 'function' && !cProto.handleReplayProgress66 && cProto.handleReplayProgress.length === 1) {
  9031. urt++;
  9032. assertor(() => fnIntegrity(cProto.handleReplayProgress, '1.16.13'));
  9033. } else {
  9034. if (withTimerFn_ > 0) console1.log('Error for setting cProto.handleReplayProgress', tag)
  9035. }
  9036.  
  9037.  
  9038.  
  9039. }
  9040.  
  9041. 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);
  9042. cProto.__ENABLE_VIDEO_PROGRESS_STATE_FIX_AND_URT_PASSED__ = ENABLE_VIDEO_PROGRESS_STATE_FIX_AND_URT_PASSED;
  9043.  
  9044. if (ENABLE_VIDEO_PROGRESS_STATE_FIX_AND_URT_PASSED) {
  9045.  
  9046. cProto._Y7rtk = 0;
  9047. cProto._Y7rtu = 0;
  9048. cProto._Y7rtv = 0;
  9049.  
  9050. cProto.handlePauseReplay66 = cProto.handlePauseReplay;
  9051. cProto.handlePauseReplay = dProto.handlePauseReplayForPlaybackProgressState;
  9052.  
  9053. cProto.handleResumeReplay66 = cProto.handleResumeReplay;
  9054. cProto.handleResumeReplay = dProto.handleResumeReplayForPlaybackProgressState;
  9055.  
  9056. cProto.handleReplayProgress66 = cProto.handleReplayProgress;
  9057. cProto.handleReplayProgress = dProto.handleReplayProgressForPlaybackProgressState;
  9058.  
  9059. }
  9060.  
  9061. // ------------- ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX -------------
  9062.  
  9063. // ------------- FIX_MEMORY_LEAKAGE_TICKER_TIMER -------------
  9064.  
  9065. if (FIX_MEMORY_LEAKAGE_TICKER_TIMER) {
  9066. if (!USE_ADVANCED_TICKING && typeof cProto.setContainerWidth === 'function' && !cProto.setContainerWidth55 && cProto.setContainerWidth.length === 0) {
  9067. cProto.setContainerWidth55 = cProto.setContainerWidth;
  9068. cProto.setContainerWidth = dProto.setContainerWidthNoSelfLeakage;
  9069. flgLeakageFixApplied |= 4;
  9070. }
  9071. if (!USE_ADVANCED_TICKING && typeof cProto.slideDown === 'function' && !cProto.slideDown55 && cProto.slideDown.length === 0) {
  9072. cProto.slideDown55 = cProto.slideDown;
  9073. cProto.slideDown = dProto.slideDownNoSelfLeakage;
  9074. flgLeakageFixApplied |= 8;
  9075. }
  9076. if (!USE_ADVANCED_TICKING && typeof cProto.collapse === 'function' && !cProto.collapse55 && cProto.collapse.length === 0) {
  9077. cProto.collapse55 = cProto.collapse;
  9078. cProto.collapse = dProto.collapseNoSelfLeakage;
  9079. flgLeakageFixApplied |= 16;
  9080. }
  9081. if (typeof cProto.deletedChanged === 'function' && !cProto.deletedChanged55 && cProto.deletedChanged.length === 0) {
  9082.  
  9083. cProto.deletedChanged55 = cProto.deletedChanged;
  9084. cProto.deletedChanged = dProto.deletedChangedNoSelfLeakage;
  9085. flgLeakageFixApplied |= 32;
  9086. }
  9087.  
  9088. }
  9089.  
  9090. const flgTotal = USE_ADVANCED_TICKING ? 1 + 2 + 32 : 1 + 2 + 4 + 8 + 16 + 32;
  9091.  
  9092. console1.log(`FIX_MEMORY_LEAKAGE_TICKER_[#${tagI}]: ${flgLeakageFixApplied} / ${flgTotal}`, cProto.is);
  9093.  
  9094. // ------------- FIX_MEMORY_LEAKAGE_TICKER_TIMER -------------
  9095.  
  9096.  
  9097.  
  9098. const canDoAdvancedTicking = 1 &&
  9099. ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION &&
  9100. typeof cProto.startCountdown === 'function' && !cProto.startCountdown49 && cProto.startCountdown.length === 2 &&
  9101. typeof cProto.updateTimeout === 'function' && !cProto.updateTimeout49 && cProto.updateTimeout.length === 1 &&
  9102. typeof cProto.isAnimationPausedChanged === 'function' && !cProto.isAnimationPausedChanged49 && cProto.isAnimationPausedChanged.length === 2 &&
  9103. typeof cProto.setContainerWidth === 'function' && cProto.setContainerWidth.length === 0 &&
  9104. typeof cProto.requestRemoval === 'function' && !cProto.requestRemoval49 && cProto.requestRemoval.length === 0
  9105. CSS.supports("left","clamp(-100%, calc( -100% * ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) ), 0%)");
  9106.  
  9107.  
  9108.  
  9109. if (USE_ADVANCED_TICKING && canDoAdvancedTicking && ENABLE_TICKERS_BOOSTED_STAMPING) {
  9110. // startResistanceUpdater();
  9111. // live replay video -> 48117005 -> 48117006 keep fire. ->48117007 0 -> 48117007 {...}
  9112. // live stream video -> 48117007 0 -> 48117007 YES
  9113.  
  9114. document.documentElement.setAttribute('r6-advanced-ticking', '');
  9115. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::START`)
  9116.  
  9117. const wio2 = dProto.wio2 || (dProto.wio2 = new IntersectionObserver((mutations) => {
  9118.  
  9119. for (const mutation of mutations) {
  9120. if (mutation.isIntersecting) {
  9121.  
  9122. const marker = mutation.target;
  9123. let endId = marker.id
  9124. if (!endId) continue;
  9125. let tid = endId.substring(0, endId.length - 2);
  9126. if (!tid) continue;
  9127. // let bId = `${tid}-b`;
  9128. const bgElm = document.querySelector(`#${tid}-b`);
  9129. if (!bgElm) continue;
  9130. const overlay = bgElm;
  9131.  
  9132. wio2.unobserve(marker);
  9133. marker.remove();
  9134. let p = overlay || 0;
  9135. let cn = 4;
  9136. while ((p = p.parentElement) instanceof HTMLElement_) {
  9137. if (p instanceof HTMLElement_) {
  9138. const cnt = insp(p);
  9139. if (cnt && typeof cnt.slideDown === 'function' && typeof cnt.setContainerWidth === 'function' && cnt.__advancedTicking038__ === 1) {
  9140.  
  9141. cnt.__advancedTicking038__ = 2;
  9142.  
  9143. let deletionMode = false;
  9144. const cntData = ((cnt || 0).__data || 0).data || (cnt || 0).data || 0;
  9145. if (timestampUnderLiveMode && cntData && cntData.durationSec > 0 && cntData.__timestampActionRequest__ > 0) {
  9146.  
  9147. // time choose - 0.2s for transition (slideDown sliding-down)
  9148. // 60hz = 17ms
  9149. // choose 0.28s
  9150. const targetFutureTime = cntData.__timestampActionRequest__ + cntData.durationSec * 1000;
  9151. // check whether the targetFutureTime is already the past
  9152. if (targetFutureTime + 280 < Date.now()) {
  9153. // just dispose
  9154. deletionMode = true;
  9155. }
  9156. } else if (__LCRInjection__ && !timestampUnderLiveMode && cntData && cntData.durationSec > 0 && cntData.__progressAt__ > 0) {
  9157.  
  9158. const targetFutureTime = (cntData.__progressAt__ + cntData.durationSec);
  9159. // check whether the targetFutureTime is already the past
  9160. if (targetFutureTime + 0.28 < playerProgressChangedArg1) {
  9161. // just dispose
  9162. deletionMode = true;
  9163. }
  9164.  
  9165.  
  9166. }
  9167.  
  9168.  
  9169. if (deletionMode) {
  9170. __requestRemoval__(cnt);
  9171. } else {
  9172.  
  9173. const w = cnt.hostElement.style.width;
  9174. if (w === "auto" || w === "") cnt.setContainerWidth();
  9175. cnt.slideDown();
  9176. }
  9177.  
  9178. break;
  9179. }
  9180. }
  9181. cn--;
  9182. if (!cn) {
  9183. console.log('cnt not found for ticker-bg-overlay');
  9184. break;
  9185. }
  9186. }
  9187.  
  9188.  
  9189. }
  9190. }
  9191.  
  9192. // console.log(mutations);
  9193. }, {
  9194.  
  9195. rootMargin: '0px',
  9196. threshold: [1]
  9197.  
  9198. }));
  9199.  
  9200.  
  9201.  
  9202. cProto.__isTickerItem58__ = 1;
  9203. cProto.attached747 = cProto.attached;
  9204. cProto.attached = function () {
  9205. const hostElement = (this || 0).hostElement;
  9206. if (hostElement && hostElement.hasAttribute('q92wb')) hostElement.removeAttribute('q92wb');
  9207. if (hostElement && hostElement.__requestRemovalAt003__) hostElement.__requestRemovalAt003__ = 0;
  9208. Promise.resolve().then(() => {
  9209. if (this.hostElement && this.isAttached && this.hostElement.isConnected && this.parentComponent) {
  9210. if (this.__startCountdownAdv477__) Promise.resolve(this).then(timeFn749);
  9211. }
  9212. }).catch(console.warn);
  9213. return this.attached747();
  9214. };
  9215. cProto.startCountdown = dProto.startCountdownAdv || (dProto.startCountdownAdv = function (a, b) {
  9216.  
  9217.  
  9218. timeFn749(this);
  9219.  
  9220.  
  9221. });
  9222.  
  9223. cProto.updateTimeout = dProto.updateTimeoutAdv || (dProto.updateTimeoutAdv = function (a) {
  9224.  
  9225.  
  9226.  
  9227. });
  9228.  
  9229. cProto.isAnimationPausedChanged = dProto.isAnimationPausedChangedAdv || (dProto.isAnimationPausedChangedAdv = function (a, b) {
  9230.  
  9231.  
  9232.  
  9233. });
  9234.  
  9235.  
  9236. if (typeof cProto.slideDown === 'function' && !cProto.slideDown43 && cProto.slideDown.length === 0) {
  9237.  
  9238. cProto.slideDown43 = cProto.slideDown;
  9239. cProto.slideDown = dProto.slideDownAdv || (dProto.slideDownAdv = async function () {
  9240.  
  9241. // console.log('calling slideDown', Date.now())
  9242. if (this.__advancedTicking038__) {
  9243.  
  9244. if (this.__advancedTicking038__ === 1) this.__advancedTicking038__ = 2; // ignore intersectionobserver detection
  9245.  
  9246.  
  9247. const hostElement = this.hostElement;
  9248. const container = this.$.container;
  9249.  
  9250. const parentComponentCnt = insp(this.parentComponent);
  9251. const parentComponentElm = parentComponentCnt? parentComponentCnt.hostElement : null;
  9252.  
  9253. if (hostElement instanceof HTMLElement_ && container instanceof HTMLElement_ && parentComponentElm instanceof HTMLElement_) {
  9254. // const prevTransitionClosingElm = kRef(prevTransitionClosing);
  9255. // if (prevTransitionClosingElm !== hostElement) {
  9256. // prevTransitionClosingElm && prevTransitionClosingElm.classList.add('ticker-no-transition-time');
  9257. // prevTransitionClosing = mWeakRef(hostElement);
  9258. // }
  9259. // if (hostElement.classList.contains('ticker-no-transition-time')) hostElement.classList.remove('ticker-no-transition-time');
  9260. hostElement.classList.add('r6-closing-ticker');
  9261.  
  9262. if (!transitionEndHooks.has(parentComponentElm)) {
  9263. transitionEndHooks.add(parentComponentElm);
  9264. document.addEventListener('transitionend', transitionEndAfterFn, passiveCapture);
  9265. }
  9266.  
  9267. const pr = new PromiseExternal();
  9268. transitionEndAfterFnSimple.set(hostElement, pr);
  9269. transitionEndAfterFnSimple.set(container, pr);
  9270. transitionEndAfterFnSimpleEnable++;
  9271. hostElement.classList.add("sliding-down");
  9272. await pr.then();
  9273. transitionEndAfterFnSimpleEnable--;
  9274. transitionEndAfterFnSimple.delete(hostElement);
  9275. transitionEndAfterFnSimple.delete(container);
  9276. if (this && this.hostElement instanceof HTMLElement_) {
  9277.  
  9278. this.collapse();
  9279. }
  9280. return;
  9281. }
  9282. }
  9283. this.slideDown43();
  9284.  
  9285. });
  9286.  
  9287.  
  9288. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::slideDown - OK`)
  9289. } else {
  9290.  
  9291. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::slideDown - NG`)
  9292. }
  9293.  
  9294.  
  9295. if (typeof cProto.collapse === 'function' && !cProto.collapse43 && cProto.collapse.length === 0) {
  9296. cProto.collapse43 = cProto.collapse;
  9297. cProto.collapse = dProto.collapseAdv || (dProto.collapseAdv = async function () {
  9298.  
  9299.  
  9300. if (this.__advancedTicking038__) {
  9301.  
  9302.  
  9303. if (this.__advancedTicking038__ === 1) this.__advancedTicking038__ = 2; // ignore intersectionobserver detection
  9304.  
  9305.  
  9306. const hostElement = this.hostElement;
  9307. const container = this.$.container;
  9308.  
  9309. const parentComponentCnt = insp(this.parentComponent);
  9310. const parentComponentElm = parentComponentCnt ? parentComponentCnt.hostElement : null;
  9311.  
  9312. if (hostElement instanceof HTMLElement_ && container instanceof HTMLElement_ && parentComponentElm instanceof HTMLElement_) {
  9313. // const prevTransitionClosingElm = kRef(prevTransitionClosing);
  9314. // if (prevTransitionClosingElm !== hostElement) {
  9315. // prevTransitionClosingElm && prevTransitionClosingElm.classList.add('ticker-no-transition-time');
  9316. // prevTransitionClosing = mWeakRef(hostElement);
  9317. // }
  9318. // if (hostElement.classList.contains('ticker-no-transition-time')) hostElement.classList.remove('ticker-no-transition-time');
  9319. hostElement.classList.add('r6-closing-ticker');
  9320.  
  9321. if (!transitionEndHooks.has(parentComponentElm)) {
  9322. transitionEndHooks.add(parentComponentElm);
  9323. document.addEventListener('transitionend', transitionEndAfterFn, passiveCapture);
  9324. }
  9325.  
  9326. const pr = new PromiseExternal();
  9327. transitionEndAfterFnSimple.set(hostElement, pr);
  9328. transitionEndAfterFnSimple.set(container, pr);
  9329. transitionEndAfterFnSimpleEnable++;
  9330. hostElement.classList.add("collapsing");
  9331. hostElement.style.width = "0";
  9332. await pr.then();
  9333. transitionEndAfterFnSimpleEnable--;
  9334. transitionEndAfterFnSimple.delete(hostElement);
  9335. transitionEndAfterFnSimple.delete(container);
  9336. if (this && this.hostElement instanceof HTMLElement_) {
  9337.  
  9338. this.requestRemoval();
  9339. }
  9340.  
  9341. return;
  9342. }
  9343.  
  9344.  
  9345. }
  9346. this.collapse43();
  9347.  
  9348.  
  9349. });
  9350.  
  9351. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::collapse - OK`)
  9352. } else {
  9353.  
  9354. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::collapse - NG`)
  9355. }
  9356.  
  9357.  
  9358.  
  9359. if (typeof cProto.requestRemoval === 'function' && !cProto.requestRemoval49 && cProto.requestRemoval.length === 0) {
  9360.  
  9361. cProto.requestRemoval49 = cProto.requestRemoval;
  9362. cProto.requestRemoval = dProto.requestRemovalAdv || (dProto.requestRemovalAdv = function () {
  9363.  
  9364. const hostElement = this.hostElement;
  9365. hostElement.__requestRemovalAt003__ = Date.now();
  9366. if (this.__advancedTicking038__) {
  9367. try {
  9368. const overlayBg = hostElement.querySelector('ticker-bg-overlay[id]');
  9369. if (overlayBg) {
  9370. const overlayBgId = overlayBg.id;
  9371. const tid = overlayBgId ? overlayBgId.substring(0, overlayBgId.length - 2) : '';
  9372. const endElm = tid ? document.querySelector(`#${tid}-e`) : null;
  9373. if (endElm) {
  9374. wio2.unobserve(endElm);
  9375. endElm.remove();
  9376. }
  9377. }
  9378. } catch (e) { }
  9379. this.__advancedTicking038__ = 2;
  9380. // console.log('requestRemoval!!')
  9381. if (hostElement instanceof HTMLElement_) {
  9382. // otherwise the startCountDown not working
  9383. hostElement.style.removeProperty('--ticker-start-time');
  9384. hostElement.style.removeProperty('--ticker-duration-time');
  9385. }
  9386. if (REUSE_TICKER) {
  9387. const cntData = this.data;
  9388. if (hostElement instanceof HTMLElement_ && cntData.id && cntData.fullDurationSec && !hostElement.hasAttribute('__reuseid__')) {
  9389. hostElement.setAttribute('__reuseid__', reuseId);
  9390. hostElement.setAttribute('__nogc__', ''); // provided to leakage detection script
  9391. // this.__markReuse13__ = true;
  9392. reuseStore.set(`<${this.is}>${cntData.id}:${cntData.fullDurationSec}`, mWeakRef(this));
  9393. }
  9394. }
  9395. }
  9396. if (hostElement instanceof HTMLElement_) {
  9397. // try {
  9398. // // hostElement.remove();
  9399.  
  9400. // if (!hostElement.classList.contains('ticker-no-transition-time')) hostElement.classList.add('ticker-no-transition-time');
  9401. // } catch (e) { }
  9402.  
  9403. try {
  9404.  
  9405. hostElement.classList.remove('r6-closing-ticker');
  9406. hostElement.classList.remove('r6-width-adjustable-f');
  9407. } catch (e) { }
  9408.  
  9409. // if(ADVANCED_TICKING_MEMORY_CLEAN_FOR_REMOVAL){
  9410. // const wr = mWeakRef(hostElement);
  9411. // const wf = ()=>{
  9412. // const element = kRef(wr);
  9413. // if(!element) {
  9414. // console.log('[yt-chat-removalrequest] element was memory cleaned.');
  9415. // return;
  9416. // }
  9417.  
  9418. // setTimeout(wf, 8000);
  9419. // if(element.isConnected){
  9420. // console.log('[yt-chat-removalrequest] element is still connected to DOM Tree.');
  9421. // return;
  9422. // }
  9423.  
  9424. // const cnt = insp(element)
  9425. // if(typeof cnt.requestRemoval !== 'function'){
  9426.  
  9427. // console.log('[yt-chat-removalrequest] element is not connected to cnt.');
  9428. // return;
  9429. // }
  9430. // console.log('[yt-chat-removalrequest] element is not GC.');
  9431. // try{
  9432. // cnt.data = null;
  9433. // }catch(e){}
  9434.  
  9435. // Object.setPrototypeOf(cnt, Object.prototype);
  9436. // for(const k of Object.getOwnPropertyNames(cnt)){
  9437. // try{
  9438. // cnt[k] = null;
  9439. // }catch(e){}
  9440.  
  9441. // try{
  9442. // delete cnt[k];
  9443. // }catch(e){}
  9444. // }
  9445.  
  9446.  
  9447. // for(const k of Object.getOwnPropertySymbols(cnt)){
  9448. // try{
  9449. // cnt[k] = null;
  9450. // }catch(e){}
  9451.  
  9452. // try{
  9453. // delete cnt[k];
  9454. // }catch(e){}
  9455. // }
  9456.  
  9457. // }
  9458. // setTimeout(wf, 8000);
  9459. // }
  9460.  
  9461. hostElement.setAttribute('q92wb', '1');
  9462. }
  9463. });
  9464.  
  9465.  
  9466. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::requestRemoval - OK`)
  9467. } else {
  9468.  
  9469. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::requestRemoval - NG`)
  9470. }
  9471.  
  9472.  
  9473. if (typeof cProto.computeContainerStyle === 'function' && !cProto.computeContainerStyle49 && cProto.computeContainerStyle.length === 2) {
  9474. cProto.computeContainerStyle49 = cProto.computeContainerStyle;
  9475. cProto.computeContainerStyle = dProto.computeContainerStyleAdv || (dProto.computeContainerStyleAdv = function (a, b) {
  9476. if (this.__advancedTicking038__) {
  9477. return "";
  9478. }
  9479. return this.computeContainerStyle49(a, b);
  9480. });
  9481.  
  9482.  
  9483. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::computeContainerStyle - OK`)
  9484. } else {
  9485.  
  9486. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::computeContainerStyle - NG`)
  9487. }
  9488.  
  9489.  
  9490.  
  9491. if(ENABLE_TICKERS_BOOSTED_STAMPING && DISABLE_DYNAMIC_TICKER_WIDTH && typeof cProto.updateWidthOnDataChanged === 'function' && cProto.updateWidthOnDataChanged.length === 0 && !cProto.updateWidthOnDataChanged41){
  9492.  
  9493. cProto.updateWidthOnDataChanged41 = cProto.updateWidthOnDataChanged;
  9494. cProto.updateWidthOnDataChanged = dProto.updateWidthOnDataChangedAdv || (dProto.updateWidthOnDataChangedAdv = function(){
  9495. const style = this.hostElement.style;
  9496. style.width = "";
  9497. style.overflow = "";
  9498. });
  9499.  
  9500. }
  9501.  
  9502.  
  9503. if (!cProto.setStandardContainerWidth8447) {
  9504. cProto.setStandardContainerWidth8447 = dProto.setStandardContainerWidthAdv || (dProto.setStandardContainerWidthAdv = async function (kName) {
  9505.  
  9506. if (this.__startCountdownAdv477__) Promise.resolve(this).then(timeFn749);
  9507.  
  9508. const hostElement = (this || 0).hostElement;
  9509. const container = this.$.container;
  9510.  
  9511. let qw = null;
  9512. let qt = '';
  9513.  
  9514. {
  9515.  
  9516. let maxC = 4;
  9517.  
  9518. for (let p = qt = hostElement.getAttribute('r6-ticker-width') || ''; maxC--;) {
  9519.  
  9520. const ed = `${hostElement.id}`
  9521. if (!p || !p.startsWith(`${ed}::`)) {
  9522.  
  9523. const w = hostElement.style.width;
  9524. if (w !== '' && w !== 'auto') hostElement.style.width = 'auto';
  9525.  
  9526. const res = await widthReq(container);
  9527.  
  9528. if (res.width < 1 || !Number.isFinite(res.width)) {
  9529. // just skip due to iron-page hidden
  9530. return;
  9531. }
  9532.  
  9533. hostElement.setAttribute('r6-ticker-width', p = qt = `${ed}::${(res.width).toFixed(2)}`);
  9534.  
  9535. } else {
  9536. qw = p.split('::');
  9537. break;
  9538. }
  9539.  
  9540. }
  9541.  
  9542. }
  9543.  
  9544. if (!qw) {
  9545.  
  9546. console.log('container width failure');
  9547. if(kName === 'setContainerWidth') this.setContainerWidth41(); else this.setRevampContainerWidth41();
  9548. return; // failure
  9549. }
  9550.  
  9551.  
  9552. const shouldAnimateIn = ((this || 0).ytLiveChatTickerItemBehavior || 0).shouldAnimateIn || (this || 0).shouldAnimateIn || false;
  9553. if (shouldAnimateIn) {
  9554.  
  9555. stackDM(async () => {
  9556.  
  9557. if (hostElement.getAttribute('r6-ticker-width') !== qt || hostElement.isConnected !== true) return;
  9558. if (hostElement.previousElementSibling || isTickerItemsScrolling()) {
  9559.  
  9560. hostElement.style.width = `${qw[1]}px`;
  9561.  
  9562. } else {
  9563.  
  9564. const w = hostElement.style.width;
  9565. if (w !== '0px' && w !== '0') hostElement.style.width = '0';
  9566.  
  9567. await widthReq(container);
  9568.  
  9569. hostElement.style.width = `${qw[1]}px`;
  9570. }
  9571.  
  9572.  
  9573. });
  9574.  
  9575.  
  9576. } else {
  9577.  
  9578.  
  9579. stackDM(async () => {
  9580.  
  9581.  
  9582.  
  9583. if (hostElement.getAttribute('r6-ticker-width') !== qt || hostElement.isConnected !== true) return;
  9584.  
  9585. hostElement.style.width = `${qw[1]}px`;
  9586.  
  9587. });
  9588. }
  9589.  
  9590.  
  9591.  
  9592. });
  9593. }
  9594.  
  9595. if (typeof cProto.setRevampContainerWidth === 'function' && !cProto.setRevampContainerWidth41 && cProto.setRevampContainerWidth.length === 0 && typeof cProto.setStandardContainerWidth8447 === 'function' && cProto.setStandardContainerWidth8447.length === 1) {
  9596. cProto.setRevampContainerWidth41 = cProto.setRevampContainerWidth;
  9597. if (ENABLE_TICKERS_BOOSTED_STAMPING && DISABLE_DYNAMIC_TICKER_WIDTH) {
  9598.  
  9599. cProto.setRevampContainerWidth = dProto.setRevampContainerWidthAdv || (dProto.setRevampContainerWidthAdv = async function () {
  9600. const hostElement = this.hostElement;
  9601. if (((hostElement || 0).style || 0).width) hostElement.style.width = '';
  9602. return;
  9603. });
  9604.  
  9605. } else {
  9606.  
  9607.  
  9608.  
  9609. cProto.setRevampContainerWidth = dProto.setRevampContainerWidthAdv || (dProto.setRevampContainerWidthAdv = async function () {
  9610.  
  9611. // not sure the reason for auto instead of pixel.
  9612. // this is a new function in Dec 2024, but not mainly adopted in the coding yet
  9613.  
  9614. /*
  9615. var a = this;
  9616. (R(this.hostElement).querySelector("#container").clientWidth || 0) === 0 ? (this.hostElement.style.overflow = "visible",
  9617. this.hostElement.style.width = "auto") : (this.hostElement.style.overflow = "hidden",
  9618. this.ytLiveChatTickerItemBehavior.shouldAnimateIn ? (this.hostElement.style.width = "0",
  9619. Zu(function() {
  9620. a.hostElement.style.width = "auto"
  9621. }, 1)) : this.hostElement.style.width = "auto")
  9622. */
  9623.  
  9624.  
  9625. return this.setStandardContainerWidth8447('setRevampContainerWidth');
  9626.  
  9627. });
  9628. }
  9629.  
  9630.  
  9631. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::setRevampContainerWidth - OK`)
  9632. } else {
  9633.  
  9634. DEBUG_skipLog001 || console1.log(`USE_ADVANCED_TICKING[#${tagI}]::setRevampContainerWidth - NG (acceptable)`)
  9635. }
  9636.  
  9637.  
  9638. if (typeof cProto.setContainerWidth === 'function' && !cProto.setContainerWidth41 && cProto.setContainerWidth.length === 0 && typeof cProto.setStandardContainerWidth8447 === 'function' && cProto.setStandardContainerWidth8447.length === 1) {
  9639. cProto.setContainerWidth41 = cProto.setContainerWidth;
  9640.  
  9641. if (ENABLE_TICKERS_BOOSTED_STAMPING && DISABLE_DYNAMIC_TICKER_WIDTH) {
  9642.  
  9643. cProto.setContainerWidth = dProto.setContainerWidthAdv || (dProto.setContainerWidthAdv = async function () {
  9644. const hostElement = this.hostElement;
  9645. if (((hostElement || 0).style || 0).width) hostElement.style.width = '';
  9646. return;
  9647. });
  9648.  
  9649. } else {
  9650.  
  9651. cProto.setContainerWidth = dProto.setContainerWidthAdv || (dProto.setContainerWidthAdv = async function () {
  9652.  
  9653.  
  9654.  
  9655. /*
  9656. var a = this
  9657. , b = R(this.hostElement).querySelector("#container").clientWidth || 0;
  9658. b === 0 ? (this.hostElement.style.overflow = "visible",
  9659. this.hostElement.style.width = "auto") : (this.hostElement.style.overflow = "hidden",
  9660. this.shouldAnimateIn ? (this.hostElement.style.width = "0",
  9661. Zu(function() {
  9662. a.hostElement.style.width = b + "px"
  9663. }, 1)) : this.hostElement.style.width = b + "px")
  9664. */
  9665. return this.setStandardContainerWidth8447('setContainerWidth');
  9666.  
  9667. });
  9668.  
  9669. }
  9670.  
  9671.  
  9672.  
  9673. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::setContainerWidth - OK`)
  9674. } else {
  9675.  
  9676.  
  9677. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::setContainerWidth - NG`)
  9678. }
  9679.  
  9680.  
  9681.  
  9682.  
  9683. } else if (USE_ADVANCED_TICKING) {
  9684. console1.log(`USE_ADVANCED_TICKING[#${tagI}] is not injected.`);
  9685. }
  9686.  
  9687.  
  9688.  
  9689. }
  9690.  
  9691. const selector = tags.join(', ');
  9692. const elements = document.querySelectorAll(selector);
  9693. if (elements.length >= 1) {
  9694. for (const elm of elements) {
  9695. if (insp(elm).isAttached === true) {
  9696. fpTicker(elm);
  9697. }
  9698. }
  9699. }
  9700.  
  9701. console1.log("[End]");
  9702. groupEnd();
  9703.  
  9704.  
  9705. }).catch(console.warn);
  9706.  
  9707. if(FIX_MEMORY_LEAKAGE_TICKER_DATACHANGED_setContainerWidth){
  9708.  
  9709. /**
  9710. *
  9711. *
  9712. *
  9713. *
  9714. cT.prototype.dataChanged = function() {
  9715. var a = this;
  9716. this.data && (Q(this.hostElement).querySelector("#content").style.color = this.ytLiveChatTickerItemBehavior.colorFromDecimal(this.data.detailTextColor),
  9717. this.hostElement.ariaLabel = this.computeAriaLabel(this.data),
  9718. this.ytLiveChatTickerItemBehavior.startCountdown(this.data.durationSec, this.data.fullDurationSec),
  9719. qw(function() {
  9720. a.ytLiveChatTickerItemBehavior.setContainerWidth()
  9721. }))
  9722. }
  9723.  
  9724.  
  9725. znb.prototype.dataChanged = function(a) {
  9726. var b = this;
  9727. a && (a.tickerThumbnails.length > 1 && Q(this.hostElement).querySelector("#content").classList.add("multiple-thumbnails"),
  9728. this.ytLiveChatTickerItemBehavior.startCountdown(a.durationSec, a.fullDurationSec),
  9729. qw(function() {
  9730. b.ytLiveChatTickerItemBehavior.setContainerWidth()
  9731. }))
  9732. }
  9733.  
  9734. *
  9735. */
  9736.  
  9737. const dProto = {
  9738. dataChanged54500: function () {
  9739. // prevent memory leakage due to _.ytLiveChatTickerItemBehavior.setContainerWidth() in _.dataChanged
  9740. if (typeof (this.ytLiveChatTickerItemBehavior || 0).setContainerWidth === 'function') {
  9741. try {
  9742. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  9743. return this.dataChanged544.call(this.__proxySelf0__);
  9744. } catch (e) {
  9745. console.log('dataChanged54500 ERROR');
  9746. console.error(e);
  9747. }
  9748. } else {
  9749. return this.dataChanged544();
  9750. }
  9751. },
  9752. dataChanged54501: function (a) {
  9753. // prevent memory leakage due to _.ytLiveChatTickerItemBehavior.setContainerWidth() in _.dataChanged
  9754. if (typeof (this.ytLiveChatTickerItemBehavior || 0).setContainerWidth === 'function') {
  9755. try {
  9756. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  9757. return this.dataChanged544.call(this.__proxySelf0__, a);
  9758. } catch (e) {
  9759. console.log('dataChanged54501 ERROR');
  9760. console.error(e);
  9761. }
  9762. } else {
  9763. return this.dataChanged544(a);
  9764. }
  9765. },
  9766. }
  9767.  
  9768. for (const sto of [
  9769. 'yt-live-chat-ticker-sponsor-item-renderer',
  9770. 'yt-live-chat-ticker-paid-sticker-item-renderer'
  9771. ].map(tag => [tag, customElements.whenDefined(tag)])) {
  9772.  
  9773. const [tag, promise] = sto;
  9774.  
  9775. promise.then(()=>{
  9776.  
  9777. const dummy = document.createElement(tag);
  9778.  
  9779. const cProto = getProto(dummy);
  9780. if (!cProto || !cProto.attached) {
  9781. console.warn(`proto.attached for ${tag} is unavailable.`);
  9782. return;
  9783. }
  9784.  
  9785. if (!cProto.dataChanged || cProto.dataChanged544 || typeof cProto.dataChanged !== 'function' || !(cProto.dataChanged.length >= 0 && cProto.dataChanged.length <= 1)) return;
  9786.  
  9787. cProto.dataChanged544 = cProto.dataChanged;
  9788.  
  9789. if (cProto.dataChanged.length === 0) cProto.dataChanged = dProto.dataChanged54500;
  9790. else if (cProto.dataChanged.length === 1) cProto.dataChanged = dProto.dataChanged54501;
  9791.  
  9792.  
  9793.  
  9794. })
  9795.  
  9796.  
  9797. }
  9798.  
  9799. }
  9800.  
  9801. customElements.whenDefined('yt-live-chat-ticker-renderer').then(() => {
  9802.  
  9803. mightFirstCheckOnYtInit();
  9804. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-ticker-renderer hacks");
  9805. console1.log("[Begin]");
  9806. (() => {
  9807.  
  9808. /* pending!!
  9809.  
  9810. handleLiveChatAction
  9811.  
  9812. removeTickerItemById
  9813.  
  9814. _itemsChanged
  9815. itemsChanged
  9816.  
  9817. handleMarkChatItemAsDeletedAction
  9818. handleMarkChatItemsByAuthorAsDeletedAction
  9819. handleRemoveChatItemByAuthorAction
  9820.  
  9821.  
  9822. */
  9823.  
  9824. const tag = "yt-live-chat-ticker-renderer"
  9825. const dummy = document.createElement(tag);
  9826.  
  9827. const cProto = getProto(dummy);
  9828. if (!cProto || !cProto.attached) {
  9829. console1.warn(`proto.attached for ${tag} is unavailable.`);
  9830. return;
  9831. }
  9832.  
  9833. if (FIX_REMOVE_TICKER_ITEM_BY_ID && typeof cProto.splice === 'function' && typeof cProto.markDirty === 'function' && typeof cProto.removeTickerItemById === 'function' && !cProto.removeTickerItemById737) {
  9834. cProto.removeTickerItemById737 = cProto.removeTickerItemById;
  9835. cProto.removeTickerItemById = function (a) {
  9836. // console.log('removeTickerItemById#01', a);
  9837. if (this.tickerItemsQuery !== '#ticker-items' || typeof (a || 0) !== 'string') return this.removeTickerItemById737(a);
  9838. // console.log('removeTickerItemById#02', a);
  9839. const hostElement = this.hostElement;
  9840. if (!hostElement || !a) return this.removeTickerItemById737(a);
  9841. // console.log('removeTickerItemById#03', a);
  9842. const arr = hostElement.querySelectorAll(`[id="${a}"]`);
  9843. const s = new Set();
  9844. if (typeof (a || 0) === 'string') s.add(a);
  9845. for (const elem of arr) {
  9846. if (!elem) continue;
  9847. const elemId = elem.id;
  9848. if (!elemId) continue;
  9849. s.add(elemId);
  9850. const data = (insp(elem).data || 0);
  9851. if (data) {
  9852. const u = data.id;
  9853. if (u) s.add(u);
  9854. else data.id = elemId;
  9855. }
  9856. }
  9857. const tickerItems = this.tickerItems;
  9858. let deleteCount = 0;
  9859. for (let i = tickerItems.length - 1; i >= 0; i--) {
  9860. const obj = tickerItems[i];
  9861. if (!obj || typeof obj !== 'object') continue;
  9862. const key = firstObjectKey(obj);
  9863. if (!key) continue;
  9864. const dataObj = obj[key];
  9865. const dataId = (dataObj || 0).id;
  9866. if (s.has(dataId)) {
  9867. this.splice("tickerItems", i, 1);
  9868. this.markDirty();
  9869. deleteCount++;
  9870. }
  9871. }
  9872. // console.log('removeTickerItemById#06', a, deleteCount);
  9873. s.has(this.highlightId) && (this.highlightId = void 0);
  9874. // console.log('removeTickerItemById#07', a, deleteCount);
  9875. }
  9876. }
  9877.  
  9878. // const imgCollection = document.getElementsByTagName('IMG');
  9879.  
  9880. if (ENABLE_TICKERS_BOOSTED_STAMPING && typeof cProto.notifyPath === 'function' && cProto.notifyPath.length === 2 && typeof cProto.stampDomArraySplices_ === 'function' && cProto.stampDomArraySplices_.length === 3 && !cProto.notifyPath371) {
  9881.  
  9882. rendererStamperFactory(cProto, {
  9883. key: 'proceedStampDomArraySplices371_',
  9884. stamperDomClass: 'style-scope yt-live-chat-ticker-renderer yt-live-chat-ticker-stampdom'
  9885. });
  9886.  
  9887. cProto.notifyPath371 = cProto.notifyPath;
  9888.  
  9889. // cProto.notifyPath = function (a, b) {
  9890. // // console.log(a, b);
  9891. // if (a === 'tickerItems.splices' && (b||0).indexSplices && !this.ec388) {
  9892. // const indexSplices = b.indexSplices;
  9893. // if (indexSplices.length === 1 || typeof indexSplices.length === "undefined") {
  9894. // const indexSplice = indexSplices[0] || indexSplices;
  9895. // if (indexSplice.type === 'splice' && (indexSplice.addedCount >= 1 || (indexSplice.removed || []).length >= 1)) {
  9896. // // console.log(1039, a, indexSplice);
  9897. // this.ec388 = true;
  9898. // const r = this.notifyPath371(a, b);
  9899. // this.ec388 = false;
  9900. // return r;
  9901. // }
  9902. // }
  9903. // }
  9904.  
  9905. // return this.notifyPath371(a, b);
  9906. // }
  9907.  
  9908. cProto.stampDomArraySplices371_ = cProto.stampDomArraySplices_;
  9909.  
  9910. cProto.stampDomArraySplices_ = function (a, b, c) {
  9911. if (a === 'tickerItems' && b === 'ticker-items' && (c || 0).indexSplices) {
  9912. // if (this.ec388) {
  9913. const indexSplices = c.indexSplices;
  9914. if (indexSplices.length === 1 || typeof indexSplices.length === "undefined") {
  9915. const indexSplice = indexSplices[0] || indexSplices;
  9916. if (indexSplice.type === 'splice' && (indexSplice.addedCount >= 1 || (indexSplice.removed || 0).length >= 1)) {
  9917. // console.log(1059, a, b, indexSplice);
  9918. if (this.proceedStampDomArraySplices371_(a, b, indexSplice)) return;
  9919. }
  9920. }
  9921. // } else {
  9922. // console.warn('stampDomArraySplices_ warning', ...arguments);
  9923. // }
  9924. }
  9925. return this.stampDomArraySplices371_(...arguments);
  9926. };
  9927.  
  9928. cProto.stampDomArray366_ = cProto.stampDomArray_;
  9929. cProto.stampDomArray_ = function (items, containerId, componentConfig, rxConfig, shouldCallback, isStableList) {
  9930. const isTickerRendering = items === this.tickerItems && containerId === 'ticker-items';
  9931. const isMessageListRendering = items === this.visibleItems && containerId === 'items';
  9932.  
  9933. if(!isTickerRendering && !isMessageListRendering){
  9934. console.log('stampDomArray_ warning 0xF501', ...arguments)
  9935. return this.stampDomArray366_(...arguments);
  9936. }
  9937.  
  9938. const container = (this.$ || 0)[containerId];
  9939. if (!container) {
  9940. console.log('stampDomArray_ warning 0xF502', ...arguments)
  9941. return this.stampDomArray366_(...arguments);
  9942. }
  9943.  
  9944. if (container[sFirstElementChild] === null && items.length === 0){
  9945.  
  9946. }else{
  9947. const cTag = isTickerRendering ? 'tickerItems' : 'visibleItems';
  9948. this.proceedStampDomArraySplices371_(cTag, containerId, {
  9949. addedCount: items.length,
  9950. removedCount: container.childElementCount
  9951. });
  9952. }
  9953.  
  9954. const f = () => {
  9955. this.markDirty && this.markDirty();
  9956. const detail = {
  9957. container
  9958. };
  9959. shouldCallback && this.hostElement.dispatchEvent(new CustomEvent("yt-rendererstamper-finished", {
  9960. bubbles: !0,
  9961. cancelable: !1,
  9962. composed: !0,
  9963. detail
  9964. }));
  9965. detail.container = null;
  9966. };
  9967. if (this.ec389pr) {
  9968. this.ec389pr.then(f)
  9969. } else {
  9970. f();
  9971. }
  9972.  
  9973. };
  9974.  
  9975. }
  9976.  
  9977.  
  9978.  
  9979. if(typeof cProto.createComponent_ === 'function' && cProto.createComponent_.length === 3 && !cProto.createComponent58_ ){
  9980.  
  9981. cProto.createComponent58_ = cProto.createComponent_;
  9982. cProto.createComponent_ = function (a, b, c) {
  9983.  
  9984. const z = customCreateComponent(a, b, c);
  9985. if (z !== undefined) return z;
  9986. const r = this.createComponent58_(a, b, c);
  9987. return r;
  9988.  
  9989. }
  9990.  
  9991. }
  9992.  
  9993.  
  9994.  
  9995.  
  9996.  
  9997.  
  9998.  
  9999.  
  10000. /* Dec 2024 */
  10001.  
  10002. /*
  10003.  
  10004.  
  10005. f.handleLiveChatActions = function(a) {
  10006. a.length && (a.forEach(this.handleLiveChatAction, this),
  10007. this.updateHighlightedItem(),
  10008. this.shouldAnimateIn = !0)
  10009. }
  10010. ;
  10011. f.handleLiveChatAction = function(a) {
  10012. var b = z(a, fL)
  10013. , c = z(a, gL)
  10014. , d = z(a, eL)
  10015. , e = z(a, gdb)
  10016. , g = z(a, rdb)
  10017. , k = z(a, Deb);
  10018. a = z(a, Ceb);
  10019. 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)
  10020. }
  10021. */
  10022.  
  10023.  
  10024. if(USE_ADVANCED_TICKING && !cProto.handleLiveChatActions47 && typeof cProto.handleLiveChatActions === 'function' && cProto.handleLiveChatActions.length ===1){
  10025.  
  10026. cProto.handleLiveChatActions47 = cProto.handleLiveChatActions;
  10027.  
  10028. cProto.handleLiveChatActions = function (a) {
  10029.  
  10030. // first loading in livestream. so this is required for sorting.
  10031.  
  10032. try{
  10033. preprocessChatLiveActions(a);
  10034. }catch(e){
  10035. console.warn(e);
  10036. }
  10037. return this.handleLiveChatActions47(a);
  10038.  
  10039. }
  10040.  
  10041. console1.log("USE_ADVANCED_TICKING::handleLiveChatActions - OK");
  10042.  
  10043. }else if(USE_ADVANCED_TICKING){
  10044.  
  10045.  
  10046. console1.log("USE_ADVANCED_TICKING::handleLiveChatActions - NG");
  10047.  
  10048. }
  10049.  
  10050. // yt-live-chat-ticker-renderer hacks
  10051.  
  10052.  
  10053. if (RAF_FIX_keepScrollClamped) {
  10054.  
  10055. // to be improved
  10056.  
  10057. if (typeof cProto.keepScrollClamped === 'function' && !cProto.keepScrollClamped72 && fnIntegrity(cProto.keepScrollClamped) === '0.17.10') {
  10058.  
  10059. cProto.keepScrollClamped72 = cProto.keepScrollClamped;
  10060. cProto.keepScrollClamped = function () {
  10061.  
  10062. const cnt = kRef(this);
  10063. if (!cnt) return;
  10064. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10065.  
  10066. cnt._bound_keepScrollClamped = cnt._bound_keepScrollClamped || cnt.keepScrollClamped.bind(mWeakRef(cnt));
  10067. cnt.scrollClampRaf = requestAnimationFrame(cnt._bound_keepScrollClamped);
  10068. cnt.maybeClampScroll()
  10069. }
  10070.  
  10071. console1.log('RAF_FIX: keepScrollClamped', tag, "OK")
  10072. } else {
  10073.  
  10074. assertor(() => fnIntegrity(cProto.keepScrollClamped, '0.17.10'));
  10075. console1.log('RAF_FIX: keepScrollClamped', tag, "NG")
  10076. }
  10077.  
  10078. }
  10079.  
  10080.  
  10081. if (RAF_FIX_scrollIncrementally && typeof cProto.startScrolling === 'function' && typeof cProto.scrollIncrementally === 'function'
  10082. && '|1.43.31|1.44.31|'.indexOf('|' + fnIntegrity(cProto.startScrolling) + '|') >= 0
  10083. && '|1.78.45|1.82.43|1.43.31|'.indexOf('|' + fnIntegrity(cProto.scrollIncrementally) + '|') >= 0) {
  10084. // to be replaced by animator
  10085.  
  10086. cProto.startScrolling = function (a) {
  10087.  
  10088. const cnt = kRef(this);
  10089. if (!cnt) return;
  10090. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10091.  
  10092. cnt.scrollStopHandle && cnt.cancelAsync(cnt.scrollStopHandle);
  10093. cnt.asyncHandle && cancelAnimationFrame(cnt.asyncHandle);
  10094. cnt.lastFrameTimestamp = cnt.scrollStartTime = performance.now();
  10095. cnt.scrollRatePixelsPerSecond = a;
  10096. cnt._bound_scrollIncrementally = cnt._bound_scrollIncrementally || cnt.scrollIncrementally.bind(mWeakRef(cnt));
  10097. cnt.asyncHandle = requestAnimationFrame(cnt._bound_scrollIncrementally)
  10098. };
  10099.  
  10100. // related functions: startScrollBack, startScrollingLeft, startScrollingRight, etc.
  10101.  
  10102. /**
  10103. *
  10104. * // 2024.12.17
  10105. * // https://www.youtube.com/s/desktop/f7495da0/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  10106.  
  10107. f.startScrolling = function(a) {
  10108. this.scrollStopHandle && $u(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. f.scrollIncrementally = function(a) {
  10117. var b = a - (this.lastFrameTimestamp || 0);
  10118. R(this.hostElement).querySelector(this.tickerBarQuery).scrollLeft += b / 1E3 * (this.scrollRatePixelsPerSecond || 0);
  10119. this.maybeClampScroll();
  10120. this.updateArrows();
  10121. this.lastFrameTimestamp = a;
  10122. R(this.hostElement).querySelector(this.tickerBarQuery).scrollLeft > 0 || this.scrollRatePixelsPerSecond && this.scrollRatePixelsPerSecond > 0 ? this.asyncHandle = window.requestAnimationFrame(this.scrollIncrementally.bind(this)) : this.stopScrolling()
  10123. }
  10124. ;
  10125. *
  10126. */
  10127.  
  10128. /**
  10129. *
  10130. // 2024.12.20
  10131.  
  10132.  
  10133.  
  10134. f.startScrolling = function(a) {
  10135. this.scrollStopHandle && av(this.scrollStopHandle);
  10136. this.asyncHandle && window.cancelAnimationFrame(this.asyncHandle);
  10137. this.scrollStartTime = performance.now();
  10138. this.lastFrameTimestamp = performance.now();
  10139. this.scrollRatePixelsPerSecond = a;
  10140. this.asyncHandle = window.requestAnimationFrame(this.scrollIncrementally.bind(this))
  10141. }
  10142.  
  10143. *
  10144. *
  10145. */
  10146.  
  10147. cProto.__getTickerBarQuery__ = function () {
  10148. const tickerBarQuery = this.tickerBarQuery === '#items' ? this.$.items : this.hostElement.querySelector(this.tickerBarQuery);
  10149. return tickerBarQuery;
  10150. }
  10151.  
  10152. cProto.scrollIncrementally = (RAF_FIX_scrollIncrementally === 2) ? function (a) {
  10153.  
  10154. const cnt = kRef(this);
  10155. if (!cnt) return;
  10156. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10157.  
  10158. const b = a - (cnt.lastFrameTimestamp || 0);
  10159. const rate = cnt.scrollRatePixelsPerSecond
  10160. const q = b / 1E3 * (rate || 0);
  10161.  
  10162. const tickerBarQuery = cnt.__getTickerBarQuery__();
  10163. if (!tickerBarQuery) return; // memory leakage. to be reviewed
  10164. const sl = tickerBarQuery.scrollLeft;
  10165. // console.log(rate, sl, q)
  10166. if (cnt.lastFrameTimestamp == cnt.scrollStartTime) {
  10167.  
  10168. } else if (q > -1e-5 && q < 1e-5) {
  10169.  
  10170. } else {
  10171. let cond1 = sl > 0 && rate > 0 && q > 0;
  10172. let cond2 = sl > 0 && rate < 0 && q < 0;
  10173. let cond3 = sl < 1e-5 && sl > -1e-5 && rate > 0 && q > 0;
  10174. if (cond1 || cond2 || cond3) {
  10175. tickerBarQuery.scrollLeft += q;
  10176. cnt.maybeClampScroll();
  10177. cnt.updateArrows();
  10178. }
  10179. }
  10180.  
  10181. cnt.lastFrameTimestamp = a;
  10182. cnt._bound_scrollIncrementally = cnt._bound_scrollIncrementally || cnt.scrollIncrementally.bind(mWeakRef(cnt));
  10183. 0 < tickerBarQuery.scrollLeft || rate && 0 < rate ? cnt.asyncHandle = requestAnimationFrame(cnt._bound_scrollIncrementally) : cnt.stopScrolling()
  10184. } : function (a) {
  10185.  
  10186. const cnt = kRef(this);
  10187. if (!cnt) return;
  10188. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10189.  
  10190. const b = a - (cnt.lastFrameTimestamp || 0);
  10191. const tickerBarQuery = cnt.__getTickerBarQuery__();
  10192. if (!tickerBarQuery) return; // memory leakage. to be reviewed
  10193. tickerBarQuery.scrollLeft += b / 1E3 * (cnt.scrollRatePixelsPerSecond || 0);
  10194. cnt.maybeClampScroll();
  10195. cnt.updateArrows();
  10196. cnt.lastFrameTimestamp = a;
  10197. cnt._bound_scrollIncrementally = cnt._bound_scrollIncrementally || cnt.scrollIncrementally.bind(mWeakRef(cnt));
  10198. 0 < tickerBarQuery.scrollLeft || cnt.scrollRatePixelsPerSecond && 0 < cnt.scrollRatePixelsPerSecond ? cnt.asyncHandle = requestAnimationFrame(cnt._bound_scrollIncrementally) : cnt.stopScrolling()
  10199. };
  10200.  
  10201. console1.log(`RAF_FIX: scrollIncrementally${RAF_FIX_scrollIncrementally}`, tag, "OK")
  10202. } else {
  10203. assertor(() => fnIntegrity(cProto.startScrolling, '1.43.31'))
  10204. || logFn('cProto.startScrolling', cProto.startScrolling)();
  10205. assertor(() => fnIntegrity(cProto.scrollIncrementally, '1.78.45'))
  10206. || logFn('cProto.scrollIncrementally', cProto.scrollIncrementally)();
  10207. console1.log('RAF_FIX: scrollIncrementally', tag, "NG")
  10208. }
  10209.  
  10210.  
  10211. if (CLOSE_TICKER_PINNED_MESSAGE_WHEN_HEADER_CLICKED && typeof cProto.attached === 'function' && !cProto.attached37 && typeof cProto.detached === 'function' && !cProto.detached37) {
  10212.  
  10213. cProto.attached37 = cProto.attached;
  10214. cProto.detached37 = cProto.detached;
  10215.  
  10216. let naohzId = 0;
  10217. cProto.__naohzId__ = 0;
  10218. cProto.attached = function () {
  10219. Promise.resolve(this).then((cnt) => {
  10220.  
  10221. const hostElement = cnt.hostElement || cnt;
  10222. if (!(hostElement instanceof HTMLElement_)) return;
  10223. if (!HTMLElement_.prototype.matches.call(hostElement, '.yt-live-chat-renderer')) return;
  10224. const ironPage = HTMLElement_.prototype.closest.call(hostElement, 'iron-pages.yt-live-chat-renderer');
  10225. // or #chat-messages
  10226. if (!ironPage) return;
  10227.  
  10228. if (cnt.__naohzId__) removeEventListener.call(ironPage, 'click', cnt.messageBoxClickHandlerForFade, { capture: false, passive: true });
  10229. cnt.__naohzId__ = naohzId = (naohzId & 1073741823) + 1;
  10230. ironPage.setAttribute('naohz', `${+cnt.__naohzId__}`);
  10231.  
  10232. addEventListener.call(ironPage, 'click', cnt.messageBoxClickHandlerForFade, { capture: false, passive: true });
  10233.  
  10234. cnt = null;
  10235.  
  10236. });
  10237. return this.attached37.apply(this, arguments);
  10238. };
  10239. cProto.detached = function () {
  10240. Promise.resolve(this).then((cnt) => {
  10241.  
  10242. const ironPage = document.querySelector(`iron-pages[naohz="${+cnt.__naohzId__}"]`);
  10243. if (!ironPage) return;
  10244.  
  10245. removeEventListener.call(ironPage, 'click', cnt.messageBoxClickHandlerForFade, { capture: false, passive: true });
  10246.  
  10247. cnt = null;
  10248.  
  10249. });
  10250. return this.detached37.apply(this, arguments);
  10251. };
  10252.  
  10253. const clickFade = (u) => {
  10254. u.click();
  10255. };
  10256. cProto.messageBoxClickHandlerForFade = async (evt) => {
  10257.  
  10258. const target = (evt || 0).target || 0;
  10259. if (!target) return;
  10260.  
  10261. for (let p = target; p instanceof HTMLElement_; p = nodeParent(p)) {
  10262. const is = p.is;
  10263. if (typeof is === 'string' && is) {
  10264.  
  10265. if (is === 'yt-live-chat-pinned-message-renderer') {
  10266. return;
  10267. }
  10268. if (is === 'iron-pages' || is === 'yt-live-chat-renderer' || is === 'yt-live-chat-app') {
  10269. const fade = HTMLElement_.prototype.querySelector.call(p, 'yt-live-chat-pinned-message-renderer:not([hidden]) #fade');
  10270. if (fade) {
  10271. Promise.resolve(fade).then(clickFade);
  10272. evt && evt.stopPropagation();
  10273. }
  10274. return;
  10275. }
  10276. if (is !== 'yt-live-chat-ticker-renderer') {
  10277. if (is.startsWith('yt-live-chat-ticker-')) return;
  10278. if (!is.endsWith('-renderer')) return;
  10279. }
  10280.  
  10281. } else {
  10282. if ((p.nodeName || '').includes('BUTTON')) return;
  10283. }
  10284.  
  10285. }
  10286. };
  10287.  
  10288. console1.log("CLOSE_TICKER_PINNED_MESSAGE_WHEN_HEADER_CLICKED - OK")
  10289.  
  10290. } else {
  10291. console1.log("CLOSE_TICKER_PINNED_MESSAGE_WHEN_HEADER_CLICKED - NG")
  10292. }
  10293.  
  10294.  
  10295. })();
  10296.  
  10297. console1.log("[End]");
  10298.  
  10299. groupEnd();
  10300.  
  10301. }).catch(console.warn);
  10302.  
  10303.  
  10304.  
  10305. if (ENABLE_RAF_HACK_INPUT_RENDERER || DELAY_FOCUSEDCHANGED) {
  10306.  
  10307. customElements.whenDefined("yt-live-chat-message-input-renderer").then(() => {
  10308.  
  10309. mightFirstCheckOnYtInit();
  10310. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-message-input-renderer hacks");
  10311. console1.log("[Begin]");
  10312. (() => {
  10313.  
  10314.  
  10315.  
  10316. const tag = "yt-live-chat-message-input-renderer"
  10317. const dummy = document.createElement(tag);
  10318.  
  10319. const cProto = getProto(dummy);
  10320. if (!cProto || !cProto.attached) {
  10321. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10322. return;
  10323. }
  10324.  
  10325.  
  10326. if (ENABLE_RAF_HACK_INPUT_RENDERER && rafHub !== null) {
  10327.  
  10328. let doHack = false;
  10329. if (typeof cProto.handleTimeout === 'function' && typeof cProto.updateTimeout === 'function') {
  10330.  
  10331. // not cancellable
  10332.  
  10333. // <<< to be reviewed cProto.updateTimeout --- isTimingFunctionHackable -- doHack >>>
  10334.  
  10335. doHack = fnIntegrity(cProto.handleTimeout, '1.27.16') && fnIntegrity(cProto.updateTimeout, '1.50.33');
  10336.  
  10337. if (!doHack) console1.log('doHack = false')
  10338.  
  10339. }
  10340. // doHack = false; // M55
  10341.  
  10342. if (doHack) {
  10343.  
  10344. cProto.handleTimeout = function (a) {
  10345.  
  10346. const cnt = kRef(this);
  10347. if (!cnt) return;
  10348. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10349.  
  10350. console.log('cProto.handleTimeout', tag)
  10351. if (!cnt.boundUpdateTimeout38_) cnt.boundUpdateTimeout38_ = cnt.updateTimeout.bind(mWeakRef(cnt));
  10352. cnt.timeoutDurationMs = cnt.timeoutMs = a;
  10353. cnt.countdownRatio = 1;
  10354. 0 === cnt.lastTimeoutTimeMs && rafHub.request(cnt.boundUpdateTimeout38_)
  10355. };
  10356. cProto.updateTimeout = function (a) {
  10357.  
  10358. const cnt = kRef(this);
  10359. if (!cnt) return;
  10360. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10361.  
  10362. console.log('cProto.updateTimeout', tag)
  10363. if (!cnt.boundUpdateTimeout38_) cnt.boundUpdateTimeout38_ = cnt.updateTimeout.bind(mWeakRef(cnt));
  10364. cnt.lastTimeoutTimeMs && (cnt.timeoutMs = Math.max(0, cnt.timeoutMs - (a - cnt.lastTimeoutTimeMs)),
  10365. cnt.countdownRatio = cnt.timeoutMs / cnt.timeoutDurationMs);
  10366. cnt.isAttached && cnt.timeoutMs ? (cnt.lastTimeoutTimeMs = a,
  10367. rafHub.request(cnt.boundUpdateTimeout38_)) : cnt.lastTimeoutTimeMs = 0
  10368. };
  10369.  
  10370. console1.log('RAF_HACK_INPUT_RENDERER', tag, "OK")
  10371. } else {
  10372.  
  10373. console1.log('typeof handleTimeout', typeof cProto.handleTimeout)
  10374. console1.log('typeof updateTimeout', typeof cProto.updateTimeout)
  10375.  
  10376. console1.log('RAF_HACK_INPUT_RENDERER', tag, "NG")
  10377. }
  10378.  
  10379.  
  10380. }
  10381.  
  10382. if (DELAY_FOCUSEDCHANGED && typeof cProto.onFocusedChanged === 'function' && cProto.onFocusedChanged.length === 1 && !cProto.onFocusedChanged372) {
  10383. cProto.onFocusedChanged372 = cProto.onFocusedChanged;
  10384. cProto.onFocusedChanged = function (a) {
  10385. Promise.resolve(this).then((cnt) => {
  10386. if (cnt.isAttached === true) cnt.onFocusedChanged372(a);
  10387. cnt = null;
  10388. }).catch(console.warn);
  10389. }
  10390. }
  10391.  
  10392. })();
  10393.  
  10394. console1.log("[End]");
  10395.  
  10396. groupEnd();
  10397.  
  10398.  
  10399. })
  10400.  
  10401. }
  10402.  
  10403.  
  10404. if (ENABLE_RAF_HACK_EMOJI_PICKER && rafHub !== null) {
  10405.  
  10406. customElements.whenDefined("yt-emoji-picker-renderer").then(() => {
  10407.  
  10408. mightFirstCheckOnYtInit();
  10409. groupCollapsed("YouTube Super Fast Chat", " | yt-emoji-picker-renderer hacks");
  10410. console1.log("[Begin]");
  10411. (() => {
  10412.  
  10413. const tag = "yt-emoji-picker-renderer"
  10414. const dummy = document.createElement(tag);
  10415.  
  10416. const cProto = getProto(dummy);
  10417. if (!cProto || !cProto.attached) {
  10418. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10419. return;
  10420. }
  10421.  
  10422. let doHack = false;
  10423. if (typeof cProto.animateScroll_ === 'function') {
  10424.  
  10425. // not cancellable
  10426. console1.log('animateScroll_: function - OK')
  10427.  
  10428. doHack = fnIntegrity(cProto.animateScroll_, '1.102.49')
  10429.  
  10430. } else {
  10431.  
  10432. console1.log('animateScroll_', typeof cProto.animateScroll_)
  10433. }
  10434.  
  10435. if (doHack) {
  10436.  
  10437. const querySelector = HTMLElement_.prototype.querySelector;
  10438. const U = (element) => ({
  10439. querySelector: (selector) => querySelector.call(element, selector)
  10440. });
  10441.  
  10442. cProto.animateScroll_ = function (a) {
  10443.  
  10444. const cnt = kRef(this);
  10445. if (!cnt) return;
  10446. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10447.  
  10448. // console.log('cProto.animateScroll_', tag) // yt-emoji-picker-renderer
  10449. if (!cnt.boundAnimateScroll39_) cnt.boundAnimateScroll39_ = cnt.animateScroll_.bind(mWeakRef(cnt));
  10450. cnt.lastAnimationTime_ || (cnt.lastAnimationTime_ = a);
  10451. a -= cnt.lastAnimationTime_;
  10452. 200 > a ? (U(cnt.hostElement).querySelector("#categories").scrollTop = cnt.animationStart_ + (cnt.animationEnd_ - cnt.animationStart_) * a / 200,
  10453. rafHub.request(cnt.boundAnimateScroll39_)) : (null != cnt.animationEnd_ && (U(cnt.hostElement).querySelector("#categories").scrollTop = cnt.animationEnd_),
  10454. cnt.animationEnd_ = cnt.animationStart_ = null,
  10455. cnt.lastAnimationTime_ = 0);
  10456. cnt.updateButtons_()
  10457. }
  10458.  
  10459. console1.log('ENABLE_RAF_HACK_EMOJI_PICKER', tag, "OK")
  10460. } else {
  10461.  
  10462. console1.log('ENABLE_RAF_HACK_EMOJI_PICKER', tag, "NG")
  10463. }
  10464.  
  10465. })();
  10466.  
  10467. console1.log("[End]");
  10468.  
  10469. groupEnd();
  10470. });
  10471. }
  10472.  
  10473. if (ENABLE_RAF_HACK_DOCKED_MESSAGE && rafHub !== null) {
  10474.  
  10475. customElements.whenDefined("yt-live-chat-docked-message").then(() => {
  10476.  
  10477. mightFirstCheckOnYtInit();
  10478. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-docked-message hacks");
  10479. console1.log("[Begin]");
  10480. (() => {
  10481.  
  10482. const tag = "yt-live-chat-docked-message"
  10483. const dummy = document.createElement(tag);
  10484.  
  10485. const cProto = getProto(dummy);
  10486. if (!cProto || !cProto.attached) {
  10487. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10488. return;
  10489. }
  10490.  
  10491. let doHack = false;
  10492. if (typeof cProto.detached === 'function' && typeof cProto.checkIntersections === 'function' && typeof cProto.onDockableMessagesChanged === 'function' && typeof cProto.boundCheckIntersections === 'undefined') {
  10493.  
  10494. // cancelable - this.intersectRAF <detached>
  10495. // yt-live-chat-docked-message
  10496. // boundCheckIntersections <-> checkIntersections
  10497. // onDockableMessagesChanged
  10498. // this.intersectRAF = window.requestAnimationFrame(this.boundCheckIntersections);
  10499.  
  10500. console1.log(`detached: function - OK`)
  10501. console1.log('checkIntersections: function - OK')
  10502. console1.log('onDockableMessagesChanged: function - OK')
  10503.  
  10504. doHack = fnIntegrity(cProto.detached, '0.32.22') && fnIntegrity(cProto.checkIntersections, '0.128.85') && fnIntegrity(cProto.onDockableMessagesChanged, '0.20.11')
  10505.  
  10506. } else {
  10507.  
  10508. console1.log('detached', typeof cProto.detached, 'NG')
  10509. console1.log('checkIntersections', typeof cProto.checkIntersections, 'NG')
  10510. console1.log('onDockableMessagesChanged', typeof cProto.onDockableMessagesChanged, 'NG')
  10511. }
  10512.  
  10513. if (doHack) {
  10514.  
  10515. cProto.__boundCheckIntersectionsSubstitutionFn__ = function () {
  10516. const cnt = this;
  10517. if (!cnt.i5zmk && typeof cnt.boundCheckIntersections === 'function' && typeof cnt.checkIntersections === 'function') {
  10518. cnt.i5zmk = 1
  10519. cnt.boundCheckIntersections = cnt.checkIntersections.bind(mWeakRef(cnt));
  10520. }
  10521. }
  10522.  
  10523. cProto.checkIntersections = function () {
  10524.  
  10525. const cnt = kRef(this);
  10526. if (!cnt) return;
  10527. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10528.  
  10529. if(typeof cnt.__boundCheckIntersectionsSubstitutionFn__ === 'function') cnt.__boundCheckIntersectionsSubstitutionFn__();
  10530.  
  10531. // console.log('cProto.checkIntersections', tag)
  10532. if (cnt.dockableMessages.length) {
  10533. cnt.intersectRAF = rafHub.request(cnt.boundCheckIntersections);
  10534. let a = cnt.dockableMessages[0]
  10535. , b = cnt.hostElement.getBoundingClientRect();
  10536. a = a.getBoundingClientRect();
  10537. let c = a.top - b.top
  10538. , d = 8 >= c;
  10539. c = 8 >= c - cnt.hostElement.clientHeight;
  10540. if (d) {
  10541. let e;
  10542. for (; d;) {
  10543. e = cnt.dockableMessages.shift();
  10544. d = cnt.dockableMessages[0];
  10545. if (!d)
  10546. break;
  10547. d = d.getBoundingClientRect();
  10548. c = d.top - b.top;
  10549. let f = 8 >= c;
  10550. if (8 >= c - a.height)
  10551. if (f)
  10552. a = d;
  10553. else
  10554. return;
  10555. d = f
  10556. }
  10557. cnt.dock(e)
  10558. } else
  10559. c && cnt.dockedItem && cnt.clear()
  10560. } else
  10561. cnt.intersectRAF = 0
  10562. }
  10563.  
  10564. cProto.onDockableMessagesChanged = function () {
  10565. const cnt = this;
  10566. if(typeof cnt.__boundCheckIntersectionsSubstitutionFn__ === 'function') cnt.__boundCheckIntersectionsSubstitutionFn__();
  10567. // console.log('cProto.onDockableMessagesChanged', tag) // yt-live-chat-docked-message
  10568. cnt.dockableMessages.length && !cnt.intersectRAF && (cnt.intersectRAF = rafHub.request(cnt.boundCheckIntersections))
  10569. }
  10570.  
  10571. cProto.detached = function () {
  10572. this.intersectRAF && rafHub.cancel(this.intersectRAF)
  10573. }
  10574.  
  10575. console1.log('ENABLE_RAF_HACK_DOCKED_MESSAGE', tag, "OK")
  10576. } else {
  10577.  
  10578. console1.log('ENABLE_RAF_HACK_DOCKED_MESSAGE', tag, "NG")
  10579. }
  10580.  
  10581. })();
  10582.  
  10583. console1.log("[End]");
  10584.  
  10585. groupEnd();
  10586.  
  10587. }).catch(console.warn);
  10588.  
  10589. }
  10590.  
  10591. if (FIX_SETSRC_AND_THUMBNAILCHANGE_) {
  10592.  
  10593. customElements.whenDefined("yt-img-shadow").then(() => {
  10594.  
  10595. mightFirstCheckOnYtInit();
  10596. groupCollapsed("YouTube Super Fast Chat", " | yt-img-shadow hacks");
  10597. console1.log("[Begin]");
  10598. (() => {
  10599.  
  10600. const tag = "yt-img-shadow"
  10601. const dummy = document.createElement(tag);
  10602.  
  10603. const cProto = getProto(dummy);
  10604. if (!cProto || !cProto.attached) {
  10605. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10606. return;
  10607. }
  10608.  
  10609. if (typeof cProto.thumbnailChanged_ === 'function' && !cProto.thumbnailChanged66_) {
  10610.  
  10611. cProto.thumbnailChanged66_ = cProto.thumbnailChanged_;
  10612. cProto.thumbnailChanged_ = function (a) {
  10613.  
  10614. if (this.oldThumbnail_ && this.thumbnail && this.oldThumbnail_.thumbnails === this.thumbnail.thumbnails) return;
  10615. if (!this.oldThumbnail_ && !this.thumbnail) return;
  10616.  
  10617. return this.thumbnailChanged66_.apply(this, arguments)
  10618.  
  10619. }
  10620. console1.log("cProto.thumbnailChanged_ - OK");
  10621.  
  10622. } else {
  10623. console1.log("cProto.thumbnailChanged_ - NG");
  10624.  
  10625. }
  10626. if (typeof cProto.setSrc_ === 'function' && !cProto.setSrc66_) {
  10627.  
  10628. cProto.setSrc66_ = cProto.setSrc_;
  10629. cProto.setSrc_ = function (a) {
  10630. if ((((this || 0).$ || 0).img || 0).src === a) return;
  10631. return this.setSrc66_.apply(this, arguments)
  10632. }
  10633.  
  10634. console1.log("cProto.setSrc_ - OK");
  10635. } else {
  10636.  
  10637. console1.log("cProto.setSrc_ - NG");
  10638. }
  10639.  
  10640. })();
  10641.  
  10642. console1.log("[End]");
  10643.  
  10644. groupEnd();
  10645.  
  10646. }).catch(console.warn);
  10647.  
  10648. }
  10649.  
  10650. if (FIX_THUMBNAIL_DATACHANGED) {
  10651.  
  10652. customElements.whenDefined("yt-live-chat-author-badge-renderer").then(() => {
  10653.  
  10654. mightFirstCheckOnYtInit();
  10655. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-author-badge-renderer hacks");
  10656. console1.log("[Begin]");
  10657. (() => {
  10658.  
  10659. const tag = "yt-live-chat-author-badge-renderer"
  10660. const dummy = document.createElement(tag);
  10661.  
  10662. const cProto = getProto(dummy);
  10663. if (!cProto || !cProto.attached) {
  10664. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10665. return;
  10666. }
  10667.  
  10668. if (typeof cProto.dataChanged === 'function' && !cProto.dataChanged86 && '|0.169.106|'.includes(`|${fnIntegrity(cProto.dataChanged)}|`)) {
  10669.  
  10670. cProto.dataChanged86 = cProto.dataChanged;
  10671. cProto.dataChanged = function () {
  10672.  
  10673. /* 2024.12.15 */
  10674. /*
  10675. zO.prototype.dataChanged = function() {
  10676. for (var a = Ov(R(this.hostElement).querySelector("#image")); a.firstChild; )
  10677. a.removeChild(a.firstChild);
  10678. if (this.data)
  10679. if (this.data.icon) {
  10680. var b = document.createElement("yt-icon");
  10681. this.data.icon.iconType === "MODERATOR" && this.enableNewModeratorBadge ? (b.polymerController.icon = "yt-sys-icons:shield-filled",
  10682. b.polymerController.defaultToFilled = !0) : b.polymerController.icon = "live-chat-badges:" + this.data.icon.iconType.toLowerCase();
  10683. a.appendChild(b)
  10684. } else if (this.data.customThumbnail) {
  10685. b = document.createElement("img");
  10686. var c;
  10687. (c = (c = UA(this.data.customThumbnail.thumbnails, 16)) ? Yb(kc(c)) : null) ? (b.src = c,
  10688. a.appendChild(b),
  10689. b.setAttribute("alt", this.hostElement.ariaLabel || "")) : Fq(new Zn("Could not compute URL for thumbnail",this.data.customThumbnail))
  10690. }
  10691. }
  10692. */
  10693.  
  10694. const a = (this || 0).data;
  10695. const image = ((this || 0).$ || 0).image;
  10696. if (image && a && image.firstElementChild) {
  10697. const exisiting = image.firstElementChild;
  10698. if (exisiting === image.lastElementChild) {
  10699.  
  10700. if (a.icon && exisiting.nodeName.toUpperCase() === 'YT-ICON') {
  10701.  
  10702. const c = exisiting;
  10703. const t = insp(c);
  10704. const w = ('icon' in t || 'defaultToFilled' in t) ? t : c;
  10705. if ("MODERATOR" === a.icon.iconType && this.enableNewModeratorBadge) {
  10706. if (w.icon !== "yt-sys-icons:shield-filled") w.icon = "yt-sys-icons:shield-filled";
  10707. if (w.defaultToFilled !== true) w.defaultToFilled = true;
  10708. } else {
  10709. const p = "live-chat-badges:" + a.icon.iconType.toLowerCase();;
  10710. if (w.icon !== p) w.icon = p;
  10711. if (w.defaultToFilled !== false) w.defaultToFilled = false;
  10712. }
  10713. return;
  10714.  
  10715.  
  10716. } else if (a.customThumbnail && exisiting.nodeName.toUpperCase() == 'IMG') {
  10717.  
  10718. const c = exisiting;
  10719. if (a.customThumbnail.thumbnails.map(e => e.url).includes(c.src)) {
  10720.  
  10721. c.setAttribute("alt", this.hostElement.ariaLabel || "");
  10722. return;
  10723. }
  10724. /*
  10725.  
  10726. var d;
  10727. (d = (d = KC(a.customThumbnail.thumbnails, 16)) ? lc(oc(d)) : null) ? (c.src = d,
  10728.  
  10729. c.setAttribute("alt", this.hostElement.ariaLabel || "")) : lq(new tm("Could not compute URL for thumbnail", a.customThumbnail))
  10730. */
  10731. }
  10732.  
  10733. }
  10734. }
  10735. return this.dataChanged86.apply(this, arguments)
  10736.  
  10737. }
  10738. console1.log("cProto.dataChanged - OK");
  10739.  
  10740. } else if (typeof cProto.dataChanged === 'function' && !cProto.dataChanged86 && '|1.163.100|1.162.100|1.160.97|1.159.97|'.includes(`|${fnIntegrity(cProto.dataChanged)}|`)) {
  10741.  
  10742. cProto.dataChanged86 = cProto.dataChanged;
  10743. cProto.dataChanged = function (a) {
  10744.  
  10745. /*
  10746.  
  10747. for (var b = xC(Z(this.hostElement).querySelector("#image")); b.firstChild; )
  10748. b.removeChild(b.firstChild);
  10749. if (a)
  10750. if (a.icon) {
  10751. var c = document.createElement("yt-icon");
  10752. "MODERATOR" === a.icon.iconType && this.enableNewModeratorBadge ? (c.icon = "yt-sys-icons:shield-filled",
  10753. c.defaultToFilled = !0) : c.icon = "live-chat-badges:" + a.icon.iconType.toLowerCase();
  10754. b.appendChild(c)
  10755. } else if (a.customThumbnail) {
  10756. c = document.createElement("img");
  10757. var d;
  10758. (d = (d = KC(a.customThumbnail.thumbnails, 16)) ? lc(oc(d)) : null) ? (c.src = d,
  10759. b.appendChild(c),
  10760. c.setAttribute("alt", this.hostElement.ariaLabel || "")) : lq(new tm("Could not compute URL for thumbnail",a.customThumbnail))
  10761. }
  10762.  
  10763. */
  10764.  
  10765.  
  10766. /* 2024.04.20 */
  10767. /*
  10768. for (var b = Tx(N(this.hostElement).querySelector("#image")); b.firstChild; )
  10769. b.removeChild(b.firstChild);
  10770. if (a)
  10771. if (a.icon) {
  10772. var c = document.createElement("yt-icon");
  10773. "MODERATOR" === a.icon.iconType && this.enableNewModeratorBadge ? (c.polymerController.icon = "yt-sys-icons:shield-filled",
  10774. c.polymerController.defaultToFilled = !0) : c.polymerController.icon = "live-chat-badges:" + a.icon.iconType.toLowerCase();
  10775. b.appendChild(c)
  10776. } else if (a.customThumbnail) {
  10777. c = document.createElement("img");
  10778. var d;
  10779. (d = (d = WD(a.customThumbnail.thumbnails, 16)) ? Sb(ec(d)) : null) ? (c.src = d,
  10780. b.appendChild(c),
  10781. c.setAttribute("alt", this.hostElement.ariaLabel || "")) : nr(new mn("Could not compute URL for thumbnail",a.customThumbnail))
  10782. }
  10783. */
  10784.  
  10785. const image = ((this || 0).$ || 0).image
  10786. if (image && a && image.firstElementChild) {
  10787. const exisiting = image.firstElementChild;
  10788. if (exisiting === image.lastElementChild) {
  10789.  
  10790. if (a.icon && exisiting.nodeName.toUpperCase() === 'YT-ICON') {
  10791.  
  10792. const c = exisiting;
  10793. const t = insp(c);
  10794. const w = ('icon' in t || 'defaultToFilled' in t) ? t : c;
  10795. if ("MODERATOR" === a.icon.iconType && this.enableNewModeratorBadge) {
  10796. if (w.icon !== "yt-sys-icons:shield-filled") w.icon = "yt-sys-icons:shield-filled";
  10797. if (w.defaultToFilled !== true) w.defaultToFilled = true;
  10798. } else {
  10799. const p = "live-chat-badges:" + a.icon.iconType.toLowerCase();;
  10800. if (w.icon !== p) w.icon = p;
  10801. if (w.defaultToFilled !== false) w.defaultToFilled = false;
  10802. }
  10803. return;
  10804.  
  10805.  
  10806. } else if (a.customThumbnail && exisiting.nodeName.toUpperCase() == 'IMG') {
  10807.  
  10808. const c = exisiting;
  10809. if (a.customThumbnail.thumbnails.map(e => e.url).includes(c.src)) {
  10810.  
  10811. c.setAttribute("alt", this.hostElement.ariaLabel || "");
  10812. return;
  10813. }
  10814. /*
  10815.  
  10816. var d;
  10817. (d = (d = KC(a.customThumbnail.thumbnails, 16)) ? lc(oc(d)) : null) ? (c.src = d,
  10818.  
  10819. c.setAttribute("alt", this.hostElement.ariaLabel || "")) : lq(new tm("Could not compute URL for thumbnail", a.customThumbnail))
  10820. */
  10821. }
  10822.  
  10823. }
  10824. }
  10825. return this.dataChanged86.apply(this, arguments)
  10826.  
  10827. }
  10828. console1.log("cProto.dataChanged - OK");
  10829.  
  10830. } else {
  10831. assertor(() => fnIntegrity(cProto.dataChanged, '0.169.106'));
  10832. console1.log("cProto.dataChanged - NG");
  10833.  
  10834. }
  10835.  
  10836. })();
  10837.  
  10838. console1.log("[End]");
  10839.  
  10840. groupEnd();
  10841.  
  10842. }).catch(console.warn);
  10843.  
  10844.  
  10845. }
  10846.  
  10847. if (USE_ADVANCED_TICKING) {
  10848. // leading the emoji cannot be rendered.
  10849.  
  10850. // const qz38 = lcrPromiseFn();
  10851.  
  10852. // qz38.then((lcrGet) => {
  10853.  
  10854. // const tag = "yt-live-chat-renderer"
  10855. // const dummy = lcrGet();
  10856.  
  10857. const lcrFn2 = (lcrDummy) => {
  10858.  
  10859. const tag = "yt-live-chat-renderer"
  10860. const dummy = lcrDummy;
  10861.  
  10862.  
  10863. const cProto = getProto(dummy);
  10864.  
  10865. // dummy.usePatchedLifecycles = false;
  10866. // dummy.data = null;
  10867. // dummy.__data = null;
  10868. // Object.setPrototypeOf(dummy, Object.prototype);
  10869. if (!cProto || !cProto.attached) {
  10870. console.warn(`proto.attached for ${tag} is unavailable.`);
  10871. return;
  10872. }
  10873.  
  10874. /*
  10875. <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;
  10876. */
  10877.  
  10878. if (cProto && typeof cProto.immediatelyApplyLiveChatActions === 'function' && cProto.immediatelyApplyLiveChatActions.length === 1 && !cProto.immediatelyApplyLiveChatActions82) {
  10879. cProto.immediatelyApplyLiveChatActions82 = cProto.immediatelyApplyLiveChatActions;
  10880. cProto.immediatelyApplyLiveChatActions = function (arr) {
  10881.  
  10882.  
  10883. // console.log(1237)
  10884. try {
  10885. preprocessChatLiveActions(arr);
  10886. } catch (e) {
  10887. console.warn(e);
  10888. }
  10889. return this.immediatelyApplyLiveChatActions82(arr);
  10890. };
  10891. }
  10892.  
  10893.  
  10894. if (cProto && typeof cProto.preprocessActions_ === 'function' && cProto.preprocessActions_.length === 1 && !cProto.preprocessActions82_) {
  10895. cProto.preprocessActions82_ = cProto.preprocessActions_;
  10896. cProto.preprocessActions_ = function (arr) {
  10897.  
  10898. const ct_ = Date.now();
  10899.  
  10900. arr = this.preprocessActions82_(arr);
  10901.  
  10902. try {
  10903. preprocessChatLiveActions(arr, ct_);
  10904. } catch (e) {
  10905. console.warn(e);
  10906. }
  10907. return arr;
  10908. };
  10909. }
  10910.  
  10911.  
  10912.  
  10913. };
  10914. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  10915. getLCRDummy().then(lcrFn2);
  10916. }
  10917.  
  10918. if (MODIFY_EMIT_MESSAGES_FOR_BOOST_CHAT) {
  10919.  
  10920. const lcrFn2 = (lcrDummy) => {
  10921.  
  10922. const tag = "yt-live-chat-renderer"
  10923. const dummy = lcrDummy;
  10924.  
  10925.  
  10926. const cProto = getProto(dummy);
  10927.  
  10928. // dummy.usePatchedLifecycles = false;
  10929. // dummy.data = null;
  10930. // dummy.__data = null;
  10931. // Object.setPrototypeOf(dummy, Object.prototype);
  10932. if (!cProto || !cProto.attached) {
  10933. console.warn(`proto.attached for ${tag} is unavailable.`);
  10934. return;
  10935. }
  10936.  
  10937. /*
  10938.  
  10939. // https://www.youtube.com/s/desktop/c01ea7e3/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  10940.  
  10941.  
  10942. YP.prototype.emitSmoothedMessages = function() {
  10943. this.JSC$10797_nextUpdateId = null;
  10944. if (this.JSC$10797_messageQueue.length) {
  10945. var a = 1E4;
  10946. this.JSC$10797_estimatedUpdateInterval !== null && this.JSC$10797_lastUpdateTime !== null && (a = this.JSC$10797_estimatedUpdateInterval - Date.now() + this.JSC$10797_lastUpdateTime);
  10947. var b = this.JSC$10797_messageQueue.length < a / 80 ? 1 : Math.ceil(this.JSC$10797_messageQueue.length / (a / 80));
  10948. var c = aba(this.JSC$10797_messageQueue.splice(0, b));
  10949. this.callback && this.callback(c);
  10950. this.JSC$10797_messageQueue.length && (b === 1 ? (b = a / this.JSC$10797_messageQueue.length,
  10951. b *= Math.random() + .5,
  10952. b = Math.min(1E3, b),
  10953. b = Math.max(80, b)) : b = 80,
  10954. this.JSC$10797_nextUpdateId = window.setTimeout(this.emitSmoothedMessages.bind(this), b))
  10955. }
  10956. }
  10957. // emitSmoothedMessages: say b = 1000, 858.24, 529.49, 357.15, 194.96, 82.12, 80, 80, 80 ....
  10958.  
  10959. */
  10960.  
  10961.  
  10962. const _flag0281_ = window._flag0281_;
  10963.  
  10964.  
  10965. if ((_flag0281_ & 0x40000) === 0x40000 && cProto && typeof cProto.preprocessActions_ === 'function' && cProto.preprocessActions_.length === 1 && !cProto.preprocessActions92_) {
  10966. // we can disable smooth message emitting if boost chat is enabled (0x40000)
  10967. let byPass = false;
  10968. let q33 = false;
  10969. let key_estimatedUpdateInterval = '';
  10970. let key_lastUpdateTime = '';
  10971. let key_messageQueue = '';
  10972. const emitSmoothedMessagesInstantFn = function () {
  10973. if (byPass) return this.emitSmoothedMessages018();
  10974. byPass = true;
  10975. try {
  10976. if (!q33) {
  10977. const keys = Object.getOwnPropertyNames(this);
  10978. for (const key of keys) {
  10979. if (`${key}`.endsWith('_estimatedUpdateInterval')) key_estimatedUpdateInterval = key;
  10980. else if (`${key}`.endsWith('_lastUpdateTime')) key_lastUpdateTime = key;
  10981. else if (`${key}`.endsWith('_messageQueue')) key_messageQueue = key;
  10982. else continue;
  10983. if (key_estimatedUpdateInterval && key_lastUpdateTime && key_messageQueue) break;
  10984. }
  10985. if (key_estimatedUpdateInterval && key_lastUpdateTime && key_messageQueue) {
  10986. q33 = true;
  10987. }
  10988. }
  10989. if (key_estimatedUpdateInterval && key_lastUpdateTime) {
  10990. this[key_estimatedUpdateInterval] = 78; // 80 - 2
  10991. this[key_lastUpdateTime] = Date.now() - 1;
  10992. }
  10993. } catch (e) { }
  10994. // console.log(19893,key_estimatedUpdateInterval, key_lastUpdateTime)
  10995. // make a = this.JSC$10797_estimatedUpdateInterval - Date.now() + this.JSC$10797_lastUpdateTime small
  10996.  
  10997. // this.JSC$10797_estimatedUpdateInterval = Date.now() + 1
  10998. // this.JSC$10797_lastUpdateTime = Date.now()
  10999.  
  11000. // if (!window.setTimeout837) {
  11001. // window.setTimeout837 = window.setTimeout;
  11002. // window.setTimeout838 = function (f, d) {
  11003. // if (arguments.length !== 2) return window.setTimeout837(...arguments);
  11004. // console.log(12883, d)
  11005. // return window.setTimeout837(f, d > 80 ? 80 : d)
  11006. // }
  11007. // }
  11008. // else if (window.setTimeout837 !== window.setTimeout) {
  11009. // window.setTimeout837 = window.setTimeout;
  11010. // }
  11011. // let r;
  11012. // if (window.setTimeout837 && window.setTimeout838) {
  11013. // window.setTimeout = window.setTimeout838;
  11014. // r = this.emitSmoothedMessages018();
  11015. // window.setTimeout = window.setTimeout837;
  11016. // } else {
  11017. // r = this.emitSmoothedMessages018();
  11018. // }
  11019. let doInNextCall = false;
  11020. try {
  11021. const messageQueue = key_messageQueue ? this[key_messageQueue] : null;
  11022. if (!messageQueue || !messageQueue.length) {
  11023.  
  11024. } else if (messageQueue.length > 255) {
  11025.  
  11026. } else if (!document.hidden) {
  11027.  
  11028. } else {
  11029. doInNextCall = true;
  11030. }
  11031. } catch (e) { }
  11032.  
  11033. let r;
  11034. if (doInNextCall) {
  11035. setTimeout_(() => this.emitSmoothedMessages019(), 250);
  11036. } else {
  11037. r = this.emitSmoothedMessages018();
  11038. }
  11039. byPass = false;
  11040. return r;
  11041. };
  11042. cProto.preprocessActions92_ = cProto.preprocessActions_;
  11043. cProto.preprocessActions_ = function (arr) {
  11044.  
  11045. arr = this.preprocessActions92_(arr);
  11046.  
  11047. try {
  11048.  
  11049. const smoothedQueue_ = this.smoothedQueue_;
  11050. if (smoothedQueue_ && !smoothedQueue_.__fix018__) {
  11051. smoothedQueue_.__fix018__ = true;
  11052. if (!smoothedQueue_.emitSmoothedMessages018 && typeof smoothedQueue_.emitSmoothedMessages === 'function' && smoothedQueue_.emitSmoothedMessages.length === 0) {
  11053. smoothedQueue_.emitSmoothedMessages018 = smoothedQueue_.emitSmoothedMessages;
  11054. smoothedQueue_.emitSmoothedMessages019 = emitSmoothedMessagesInstantFn;
  11055. smoothedQueue_.emitSmoothedMessages = emitSmoothedMessagesInstantFn;
  11056. }
  11057. }
  11058. } catch (e) {
  11059. console.warn(e);
  11060. }
  11061. return arr;
  11062. };
  11063. }
  11064.  
  11065.  
  11066.  
  11067.  
  11068. };
  11069. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  11070. getLCRDummy().then(lcrFn2);
  11071. }
  11072.  
  11073.  
  11074. if (FIX_TOOLTIP_DISPLAY) {
  11075.  
  11076. // ----------------------------------------------------------------------------------------------------
  11077.  
  11078. const checkPDGet = (pd) => {
  11079. return pd && pd.get && !pd.set && pd.enumerable && pd.configurable;
  11080. }
  11081.  
  11082. const tooltipUIWM = new WeakMap();
  11083. const tooltipInitProps = {};
  11084. const createTooltipIfRequired_ = function () {
  11085. let r;
  11086. if (tooltipUIWM.get(this) === void 0) {
  11087. const w = document.createElement;
  11088. let EU = null;
  11089. tooltipUIWM.set(this, null);
  11090. document.createElement = function () {
  11091. let r = w.apply(this, arguments);
  11092. EU = r;
  11093. return r;
  11094. };
  11095. r = this.createTooltipIfRequired14_();
  11096. document.createElement = w;
  11097. if (EU instanceof HTMLElement_ && EU.is) {
  11098. tooltipUIWM.set(this, EU);
  11099. EU.setAttribute('__nogc__', ''); // avoid gc process script
  11100.  
  11101. if (typeof EU.offset === 'number') tooltipInitProps['offset'] = EU.offset;
  11102. if (typeof EU.fitToVisibleBounds === 'boolean') tooltipInitProps['fitToVisibleBounds'] = EU.fitToVisibleBounds;
  11103. if (typeof EU.position === 'string') tooltipInitProps['position'] = EU.position;
  11104. if (typeof EU.for === 'string') tooltipInitProps['for'] = EU.for;
  11105.  
  11106. // this.__mcT__ = EU.outerHTML;
  11107. // EU.__dataX = JSON.stringify(EU.__data);
  11108. // EU.__dataY = Object.entries(EU);
  11109.  
  11110. // <<< FOR DEBUG >>>
  11111. // let kx;
  11112. // Object.defineProperty(EU, '_target', {
  11113. // get(){
  11114. // return kx;
  11115. // },
  11116. // set(nv){
  11117. // kx= nv;
  11118. // debugger;
  11119. // return true;
  11120. // }
  11121. // });
  11122. // <<< FOR DEBUG >>>
  11123.  
  11124. if (typeof Polymer !== 'undefined' && Polymer.__fixedGetOwnerRoot__ && Polymer.__fixedQuerySelector__) {
  11125.  
  11126. } else {
  11127. let eProto = null;
  11128. const euCnt = insp(EU);
  11129. if (checkPDGet(Object.getOwnPropertyDescriptor(euCnt.constructor.prototype || {}, 'target'))) {
  11130.  
  11131. eProto = euCnt.constructor.prototype;
  11132. } else if (checkPDGet(Object.getOwnPropertyDescriptor(EU.constructor.prototype || {}, 'target'))) {
  11133.  
  11134. eProto = EU.constructor.prototype;
  11135. }
  11136. if (eProto) {
  11137. delete eProto.target;
  11138. /*
  11139.  
  11140. get target() {
  11141. var a = Pv(this).parentNode, b = Pv(this).getOwnerRoot(), c;
  11142. this.for ? c = Pv(b).querySelector("#" + this.for) : c = a.nodeType == Node.DOCUMENT_FRAGMENT_NODE ? b.host : a;
  11143. return c
  11144. },
  11145. */
  11146. Object.defineProperty(eProto, 'target', {
  11147. get() {
  11148. const cnt = insp(this);
  11149. const hostElement = cnt.hostElement || cnt;
  11150. let a = hostElement.parentNode, b = hostElement.getRootNode();
  11151. const fr = cnt.for || hostElement.for;
  11152. return (fr ? b.querySelector("#" + fr) : a)
  11153. }
  11154. })
  11155. }
  11156. }
  11157. // setInterval(()=>EU.updatePosition(), 100)
  11158.  
  11159. } else {
  11160. tooltipUIWM.set(this, null);
  11161. }
  11162. } else {
  11163. r = this.createTooltipIfRequired14_();
  11164. }
  11165.  
  11166. const EU = tooltipUIWM.get(this);
  11167. if (EU) {
  11168. EU.remove();
  11169. if (typeof tooltipInitProps.offset === 'number') EU['offset'] = tooltipInitProps.offset;
  11170. if (typeof tooltipInitProps.fitToVisibleBounds === 'boolean') EU['fitToVisibleBounds'] = tooltipInitProps.fitToVisibleBounds;
  11171. try {
  11172. if (typeof tooltipInitProps.position === 'string') EU['position'] = tooltipInitProps.position;
  11173. if (typeof tooltipInitProps.for === 'string') EU['for'] = tooltipInitProps.for; else delete EU.for;
  11174. } catch (e) { }
  11175. }
  11176.  
  11177. // 2025.01.10 fix
  11178. const CS = EU;
  11179. if (!CS._showing && CS.__shady_parentNode && CS.__shady_parentNode !== CS.parentNode) {
  11180. if (CS.__shady_parentNode) {
  11181. try {
  11182. CS.__shady_parentNode.__shady_removeChild(CS);
  11183. } catch (e) { }
  11184. }
  11185. if (CS.__shady_parentNode) {
  11186. try {
  11187. CS.__shady_parentNode.removeChild(CS);
  11188. } catch (e) { }
  11189. }
  11190. if (CS.__shady_parentNode) {
  11191. try {
  11192. CS.__shady_parentNode.__shady_native_removeChild(CS);
  11193. } catch (e) { }
  11194. }
  11195. if (CS.__shady_parentNode) {
  11196. try {
  11197. __shady_native_removeChild.call(CS.__shady_parentNode, CS);
  11198. } catch (e) { }
  11199. }
  11200. if (CS.parentNode && !CS.__shady_parentNode) {
  11201. try {
  11202. __shady_native_removeChild.call(CS.parentNode, CS);
  11203. } catch (e) { }
  11204. }
  11205. }
  11206.  
  11207. return r;
  11208. };
  11209.  
  11210.  
  11211. // added in 2024.05.02
  11212. const lcrFn2 = (lcrDummy) => {
  11213.  
  11214. // console.log(8171, 99);
  11215. const tag = "yt-live-chat-renderer"
  11216. const dummy = lcrDummy;
  11217.  
  11218. const cProto = getProto(dummy);
  11219. if (!cProto || !cProto.attached) {
  11220. console.warn(`proto.attached for ${tag} is unavailable.`);
  11221. return;
  11222. }
  11223.  
  11224. /*
  11225. <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;
  11226. */
  11227.  
  11228. if (cProto && typeof cProto.createTooltipIfRequired_ === 'function' && cProto.createTooltipIfRequired_.length === 0 && !cProto.createTooltipIfRequired14_) {
  11229. cProto.createTooltipIfRequired14_ = cProto.createTooltipIfRequired_;
  11230. cProto.createTooltipIfRequired_ = createTooltipIfRequired_;
  11231. }
  11232.  
  11233. };
  11234. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  11235. getLCRDummy().then(lcrFn2);
  11236.  
  11237. // ----------------------------------------------------------------------------------------------------
  11238.  
  11239. customElements.whenDefined("tp-yt-paper-tooltip").then(() => {
  11240.  
  11241. mightFirstCheckOnYtInit();
  11242. groupCollapsed("YouTube Super Fast Chat", " | tp-yt-paper-tooltip hacks");
  11243. console1.log("[Begin]");
  11244. (() => {
  11245.  
  11246. const tag = "tp-yt-paper-tooltip"
  11247. const dummy = document.createElement(tag);
  11248.  
  11249. const cProto = getProto(dummy);
  11250. if (!cProto || !cProto.attached) {
  11251. console1.warn(`proto.attached for ${tag} is unavailable.`);
  11252. return;
  11253. }
  11254.  
  11255. if (typeof cProto.attached === 'function' && typeof cProto.detached === 'function' && cProto._readyClients && cProto._attachDom && cProto.ready && !cProto._readyClients43) {
  11256.  
  11257. cProto._readyClients43 = cProto._readyClients;
  11258. cProto._readyClients = function () {
  11259. // console.log(1238)
  11260.  
  11261. let r = cProto._readyClients43.apply(this, arguments);
  11262. if (this.$ && this.$$ && this.$.tooltip) this.root = null; // fix this.root = null != (b = a.root) ? b : this.host
  11263. return r;
  11264. }
  11265.  
  11266. console1.log("_readyClients - OK");
  11267.  
  11268. } else {
  11269. console1.log("_readyClients - NG");
  11270.  
  11271. }
  11272.  
  11273. if (typeof cProto.show === 'function' && !cProto.show17) {
  11274. cProto.show17 = cProto.show;
  11275. cProto.show = function () {
  11276.  
  11277. let r = this.show17.apply(this, arguments);
  11278. this._showing === true && Promise.resolve(this).then((cnt) => {
  11279. const tooltip = (cnt.$ || 0).tooltip;
  11280.  
  11281. if (tooltip && tooltip.firstElementChild === null) {
  11282. let text = tooltip.textContent;
  11283. if (typeof text === 'string' && text.length >= 2) {
  11284. tooltip.textContent = text.trim();
  11285. }
  11286. }
  11287. cnt = null;
  11288. }).catch(console.warn)
  11289. return r;
  11290. }
  11291.  
  11292. console1.log("trim tooltip content - OK");
  11293.  
  11294. } else {
  11295. console1.log("trim tooltip content - NG");
  11296.  
  11297. }
  11298.  
  11299.  
  11300. })();
  11301.  
  11302. console1.log("[End]");
  11303.  
  11304. groupEnd();
  11305.  
  11306. }).catch(console.warn);
  11307.  
  11308. }
  11309.  
  11310.  
  11311. if (FIX_CLICKING_MESSAGE_MENU_DISPLAY_ON_MOUSE_CLICK) {
  11312.  
  11313. const hookDocumentMouseDownSetupFn = () => {
  11314.  
  11315. let muzTimestamp = 0;
  11316. let nszDropdown = null;
  11317.  
  11318. const handlerObject = {
  11319.  
  11320. muHandler282: function (evt) {
  11321. // console.log(evt, 7, document.querySelector('tp-yt-iron-dropdown[focused].style-scope.yt-live-chat-app'))
  11322. if (!evt || !evt.isTrusted || !muzTimestamp) return;
  11323. const dropdown = nszDropdown;
  11324. muzTimestamp = 0;
  11325. nszDropdown = null;
  11326.  
  11327. const kurMPCe = kRef(currentMenuPivotWR) || 0;
  11328. const hostElement = kurMPCe.hostElement || kurMPCe; // should be always hostElement === kurMPCe ?
  11329. if (!hostElement.hasAttribute('menu-visible')) return;
  11330.  
  11331. const chatBanner = HTMLElement_.prototype.closest.call(hostElement, 'yt-live-chat-banner-renderer') || 0;
  11332. if (chatBanner) return;
  11333.  
  11334. if (dropdown && dropdown.positionTarget && hostElement.contains(dropdown.positionTarget)) {
  11335. muzTimestamp = Date.now();
  11336. evt.stopImmediatePropagation();
  11337. evt.stopPropagation();
  11338. Promise.resolve(dropdown).then((dropdown) => {
  11339. dropdown.cancel();
  11340. dropdown = null;
  11341. });
  11342. }
  11343.  
  11344. },
  11345.  
  11346. mlHandler282: function (evt) {
  11347. muzTimestamp = 0;
  11348. nszDropdown = null;
  11349. },
  11350.  
  11351. ckHandler282: function (evt) {
  11352. if (!evt || !evt.isTrusted || !muzTimestamp) return;
  11353. if (Date.now() - muzTimestamp < 40) {
  11354. muzTimestamp = Date.now();
  11355. evt.stopImmediatePropagation();
  11356. evt.stopPropagation();
  11357. }
  11358. },
  11359.  
  11360. tapHandler282: function (evt) {
  11361. if (!evt || !evt.isTrusted || !muzTimestamp) return;
  11362. if (Date.now() - muzTimestamp < 40) {
  11363. muzTimestamp = Date.now();
  11364. evt.stopImmediatePropagation();
  11365. evt.stopPropagation();
  11366. }
  11367. },
  11368.  
  11369. handleEvent(evt) {
  11370. if (evt) {
  11371. const kurMPCe = kRef(currentMenuPivotWR) || 0;
  11372. const kurMPCc = insp(kurMPCe);
  11373. const hostElement = kurMPCc.hostElement || kurMPCc;
  11374. if (!kurMPCc || kurMPCc.isAttached !== true || hostElement.isConnected !== true) return;
  11375. switch (evt.type) {
  11376. case 'mouseup':
  11377. return this.muHandler282(evt);
  11378. case 'mouseleave':
  11379. return this.mlHandler282(evt);
  11380. case 'tap':
  11381. return this.tapHandler282(evt);
  11382. case 'click':
  11383. return this.ckHandler282(evt);
  11384. }
  11385. }
  11386. }
  11387.  
  11388. }
  11389.  
  11390. document.addEventListener('mousedown', function (evt) {
  11391.  
  11392. if (!evt || !evt.isTrusted || !evt.target) return;
  11393.  
  11394. muzTimestamp = 0;
  11395. nszDropdown = null;
  11396.  
  11397. /** @type {HTMLElement | null} */
  11398. const kurMP = kRef(currentMenuPivotWR);
  11399. if (!kurMP) return;
  11400. const kurMPCe = HTMLElement_.prototype.closest.call(kurMP, '[menu-visible]') || 0; // element
  11401.  
  11402. if (!kurMPCe || !kurMPCe.hasAttribute('whole-message-clickable')) return;
  11403.  
  11404. const kurMPCc = insp(kurMPCe); // controller
  11405.  
  11406. if (!kurMPCc.isClickableChatRow111 || !kurMPCc.isClickableChatRow111() || !HTMLElement_.prototype.contains.call(kurMPCe, evt.target)) return;
  11407.  
  11408. const chatBanner = HTMLElement_.prototype.closest.call(kurMPCe, 'yt-live-chat-banner-renderer') || 0;
  11409. if (chatBanner) return;
  11410.  
  11411. let targetDropDown = null;
  11412. for (const dropdown of document.querySelectorAll('tp-yt-iron-dropdown.style-scope.yt-live-chat-app')) {
  11413. if (dropdown && dropdown.positionTarget === kurMP) {
  11414. targetDropDown = dropdown;
  11415. }
  11416. }
  11417.  
  11418. if (!targetDropDown) return;
  11419.  
  11420. if (evt.target.closest('ytd-menu-popup-renderer')) return;
  11421.  
  11422. if ((nszDropdown = targetDropDown)) {
  11423. muzTimestamp = Date.now();
  11424. evt.stopImmediatePropagation();
  11425. evt.stopPropagation();
  11426. currentMenuPivotWR = mWeakRef(kurMPCe);
  11427.  
  11428. const listenOpts = { capture: true, passive: false, once: true };
  11429.  
  11430. // remove unexcecuted eventHandler
  11431. document.removeEventListener('mouseup', handlerObject, listenOpts);
  11432. document.removeEventListener('mouseleave', handlerObject, listenOpts);
  11433. document.removeEventListener('tap', handlerObject, listenOpts);
  11434. document.removeEventListener('click', handlerObject, listenOpts);
  11435.  
  11436. // inject one time eventHandler to by pass events
  11437. document.addEventListener('mouseup', handlerObject, listenOpts);
  11438. document.addEventListener('mouseleave', handlerObject, listenOpts);
  11439. document.addEventListener('tap', handlerObject, listenOpts);
  11440. document.addEventListener('click', handlerObject, listenOpts);
  11441.  
  11442. }
  11443.  
  11444. }, true);
  11445.  
  11446. }
  11447.  
  11448.  
  11449. // yt-live-chat-paid-message-renderer ??
  11450.  
  11451. /*
  11452.  
  11453. [...(new Set([...document.querySelectorAll('*')].filter(e=>e.is&&('shouldSupportWholeItemClick' in e)).map(e=>e.is))).keys()]
  11454.  
  11455.  
  11456. "yt-live-chat-ticker-paid-message-item-renderer"
  11457. "yt-live-chat-ticker-paid-sticker-item-renderer"
  11458. "yt-live-chat-paid-message-renderer"
  11459. "yt-live-chat-text-message-renderer"
  11460. "yt-live-chat-paid-sticker-renderer"
  11461.  
  11462. */
  11463.  
  11464.  
  11465. whenDefinedMultiple([
  11466.  
  11467. "yt-live-chat-paid-message-renderer",
  11468. "yt-live-chat-membership-item-renderer",
  11469. "yt-live-chat-paid-sticker-renderer",
  11470. "yt-live-chat-text-message-renderer",
  11471. "yt-live-chat-auto-mod-message-renderer",
  11472.  
  11473. /*
  11474. "yt-live-chat-ticker-paid-message-item-renderer",
  11475. "yt-live-chat-ticker-paid-sticker-item-renderer",
  11476. "yt-live-chat-paid-message-renderer",
  11477. "yt-live-chat-text-message-renderer",
  11478. "yt-live-chat-paid-sticker-renderer",
  11479.  
  11480. "yt-live-chat-ticker-sponsor-item-renderer",
  11481. "yt-live-chat-banner-header-renderer",
  11482. "ytd-sponsorships-live-chat-gift-purchase-announcement-renderer",
  11483. "ytd-sponsorships-live-chat-header-renderer",
  11484. "ytd-sponsorships-live-chat-gift-redemption-announcement-renderer",
  11485.  
  11486.  
  11487.  
  11488.  
  11489. "yt-live-chat-auto-mod-message-renderer",
  11490. "yt-live-chat-text-message-renderer",
  11491. "yt-live-chat-paid-message-renderer",
  11492.  
  11493. "yt-live-chat-legacy-paid-message-renderer",
  11494. "yt-live-chat-membership-item-renderer",
  11495. "yt-live-chat-paid-sticker-renderer",
  11496. "yt-live-chat-donation-announcement-renderer",
  11497. "yt-live-chat-moderation-message-renderer",
  11498. "ytd-sponsorships-live-chat-gift-purchase-announcement-renderer",
  11499. "ytd-sponsorships-live-chat-gift-redemption-announcement-renderer",
  11500. "yt-live-chat-viewer-engagement-message-renderer",
  11501.  
  11502. */
  11503.  
  11504.  
  11505. ]).then(sTags => {
  11506. // return; // M33
  11507.  
  11508. mightFirstCheckOnYtInit();
  11509. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-message-renderer(s)... hacks");
  11510. console1.log("[Begin]");
  11511. let doMouseHook = false;
  11512.  
  11513. const dProto = {
  11514. isClickableChatRow111: function () {
  11515. return (
  11516. this.data && typeof this.shouldSupportWholeItemClick === 'function' && typeof this.hasModerationOverlayVisible === 'function' &&
  11517. this.data.contextMenuEndpoint && this.wholeMessageClickable && this.shouldSupportWholeItemClick() && !this.hasModerationOverlayVisible()
  11518. ); // follow .onItemTap(a)
  11519. }
  11520. };
  11521.  
  11522. for (const sTag of sTags) { // ##tag##
  11523.  
  11524.  
  11525. (() => {
  11526.  
  11527. const tag = sTag;
  11528. const dummy = document.createElement(tag);
  11529.  
  11530. const cProto = getProto(dummy);
  11531. if (!cProto || !cProto.attached) {
  11532. console1.warn(`proto.attached for ${tag} is unavailable.`);
  11533. return;
  11534. }
  11535.  
  11536. const dCnt = insp(dummy);
  11537. if ('wholeMessageClickable' in dCnt && typeof dCnt.hasModerationOverlayVisible === 'function' && typeof dCnt.shouldSupportWholeItemClick === 'function') {
  11538.  
  11539. cProto.isClickableChatRow111 = dProto.isClickableChatRow111;
  11540.  
  11541. const toHookDocumentMouseDown = typeof cProto.shouldSupportWholeItemClick === 'function' && typeof cProto.hasModerationOverlayVisible === 'function';
  11542.  
  11543. if (toHookDocumentMouseDown) {
  11544. doMouseHook = true;
  11545. }
  11546.  
  11547. console1.log("shouldSupportWholeItemClick - OK", tag);
  11548.  
  11549. } else {
  11550.  
  11551. console1.log("shouldSupportWholeItemClick - NG", tag);
  11552. }
  11553.  
  11554.  
  11555. })();
  11556.  
  11557. }
  11558.  
  11559.  
  11560. if (doMouseHook) {
  11561.  
  11562. hookDocumentMouseDownSetupFn();
  11563.  
  11564. console1.log("FIX_CLICKING_MESSAGE_MENU_DISPLAY_ON_MOUSE_CLICK - Doc MouseEvent OK");
  11565. }
  11566.  
  11567. console1.log("[End]");
  11568.  
  11569. groupEnd();
  11570.  
  11571.  
  11572. }).catch(console.warn);
  11573.  
  11574.  
  11575. // https://www.youtube.com/watch?v=oQzFi1NO7io
  11576.  
  11577.  
  11578. }
  11579.  
  11580. if (NO_ITEM_TAP_FOR_NON_STATIONARY_TAP) {
  11581. let targetElementCntWR = null;
  11582. let _e0 = null;
  11583. document.addEventListener('mousedown', (e) => {
  11584. if (!e || !e.isTrusted) return;
  11585. let element = e.target;
  11586. for (; element instanceof HTMLElement_; element = element.parentNode) {
  11587. if (element.is) break;
  11588. }
  11589. if (!element || !element.is) return;
  11590. if (element.closest('ytd-menu-popup-renderer')) return;
  11591. const cnt = insp(element);
  11592. if (typeof cnt.onItemTap === 'function') {
  11593. cnt._onItemTap_isNonStationary = 0;
  11594. const cProto = getProto(element);
  11595. if (!cProto.onItemTap366 && typeof cProto.onItemTap === 'function' && cProto.onItemTap.length === 1) {
  11596. cProto.onItemTap366 = cProto.onItemTap; // note: [onItemTap] .some(function(){...})
  11597. cProto.onItemTap = function (a) {
  11598. const t = this._onItemTap_isNonStationary;
  11599. this._onItemTap_isNonStationary = 0;
  11600. if (t > Date.now()) return;
  11601. return this.onItemTap366.apply(this, arguments)
  11602. }
  11603. }
  11604. _e0 = e;
  11605. targetElementCntWR = mWeakRef(cnt);
  11606. } else {
  11607. _e0 = null;
  11608. targetElementCntWR = null;
  11609. }
  11610. }, { capture: true, passive: true });
  11611.  
  11612. document.addEventListener('mouseup', (e) => {
  11613. if (!e || !e.isTrusted) return;
  11614. const e0 = _e0;
  11615. _e0 = null;
  11616. if (!e0) return;
  11617. const cnt = kRef(targetElementCntWR);
  11618. targetElementCntWR = null;
  11619. if (!cnt) return;
  11620. if (e.timeStamp - e0.timeStamp > TAP_ACTION_DURATION) {
  11621. cnt._onItemTap_isNonStationary = Date.now() + 40;
  11622. } else if (`${window.getSelection()}`.trim().replace(/[\u2000-\u200a\u202f\u2800\u200B\u200C\u200D\uFEFF]+/g, '').length >= 1) {
  11623. cnt._onItemTap_isNonStationary = Date.now() + 40;
  11624. } else {
  11625. const dx = e.clientX - e0.clientX;
  11626. const dy = e.clientY - e0.clientY;
  11627. const dd = Math.sqrt(dx * dx + dy * dy);
  11628. const ddmm = px2mm(dd);
  11629. if (ddmm > 1.0) {
  11630. cnt._onItemTap_isNonStationary = Date.now() + 40;
  11631. } else {
  11632. cnt._onItemTap_isNonStationary = 0;
  11633. }
  11634. }
  11635. }, { capture: true, passive: true });
  11636.  
  11637. }
  11638.  
  11639.  
  11640. const __showContextMenu_assign_lock_with_external_unlock_ = function (targetCnt) {
  11641.  
  11642. let rr = null;
  11643. const p1 = new Promise(resolve => {
  11644. rr = resolve;
  11645. });
  11646.  
  11647. const p1unlock = () => {
  11648. const f = rr;
  11649. if (f) {
  11650. rr = null;
  11651. f();
  11652. }
  11653. }
  11654.  
  11655. return {
  11656. p1,
  11657. p1unlock,
  11658. assignLock: (targetCnt, timeout) => {
  11659. targetCnt.__showContextMenu_assign_lock__(p1);
  11660. if (timeout) setTimeout(p1unlock, timeout);
  11661. }
  11662. }
  11663.  
  11664. }
  11665.  
  11666. if (PREREQUEST_CONTEXT_MENU_ON_MOUSE_DOWN) {
  11667.  
  11668. document.addEventListener('mousedown', function (evt) {
  11669.  
  11670. const maxloopDOMTreeElements = 4;
  11671. const maxloopYtCompontents = 4;
  11672. let j1 = 0;
  11673. let j2 = 0;
  11674. let target = (evt || 0).target || 0;
  11675. if (!target) return;
  11676. if (target.closest('ytd-menu-popup-renderer')) return;
  11677.  
  11678. while (target instanceof HTMLElement_) {
  11679. if (++j1 > maxloopDOMTreeElements) break;
  11680. if (typeof (target.is || insp(target).is || null) === 'string') break;
  11681. target = nodeParent(target);
  11682. }
  11683. const components = [];
  11684. while (target instanceof HTMLElement_) {
  11685. if (++j2 > maxloopYtCompontents) break;
  11686. const cnt = insp(target);
  11687. if (typeof (target.is || cnt.is || null) === 'string') {
  11688. components.push(target);
  11689. }
  11690. if (typeof cnt.showContextMenu === 'function') break;
  11691. target = target.parentComponent || cnt.parentComponent || null;
  11692. }
  11693. if (!(target instanceof HTMLElement_)) return;
  11694. const targetCnt = insp(target);
  11695. if (typeof targetCnt.handleGetContextMenuResponse_ !== 'function' || typeof targetCnt.handleGetContextMenuError !== 'function') {
  11696. console.log('Error Found: handleGetContextMenuResponse_ OR handleGetContextMenuError is not defined on a component with showContextMenu')
  11697. return;
  11698. }
  11699.  
  11700. const endpoint = (targetCnt.data || 0).contextMenuEndpoint
  11701. if (!endpoint) return;
  11702. if (targetCnt.opened || !targetCnt.isAttached) return;
  11703.  
  11704. if (typeof targetCnt.__cacheResolvedEndpointData__ !== 'function') {
  11705. console.log(`preRequest for showContextMenu in ${targetCnt.is} is not yet supported.`)
  11706. }
  11707.  
  11708. const targetDollar = indr(target);
  11709.  
  11710. let doPreRequest = false;
  11711. if (components.length >= 2 && components[0].id === 'menu-button' && (targetDollar || 0)['menu-button'] === components[0]) {
  11712. doPreRequest = true;
  11713. } else if (components.length === 1 && components[0] === target) {
  11714. doPreRequest = true;
  11715. } else if (components.length >= 2 && components[0].id === 'author-photo' && (targetDollar || 0)['author-photo'] === components[0]) {
  11716. doPreRequest = true;
  11717. }
  11718. if (doPreRequest === false) {
  11719. console.log('doPreRequest = fasle on showContextMenu', components);
  11720. return;
  11721. }
  11722.  
  11723. if (typeof targetCnt.__getCachedEndpointData__ !== 'function' || targetCnt.__getCachedEndpointData__(endpoint)) return;
  11724.  
  11725. if ((typeof targetCnt.__showContextMenu_mutex_unlock_isEmpty__ === 'function') && !targetCnt.__showContextMenu_mutex_unlock_isEmpty__()) {
  11726. console.log('preRequest on showContextMenu aborted due to stacked network request');
  11727. return;
  11728. }
  11729.  
  11730.  
  11731. const onSuccess = (a) => {
  11732. /*
  11733.  
  11734. dQ() && (a = a.response);
  11735. a.liveChatItemContextMenuSupportedRenderers && a.liveChatItemContextMenuSupportedRenderers.menuRenderer && this.showContextMenu_(a.liveChatItemContextMenuSupportedRenderers.menuRenderer);
  11736. a.actions && Eu(this.hostElement, "yt-live-chat-actions", [a.actions])
  11737.  
  11738. */
  11739.  
  11740. a = a.response || a;
  11741.  
  11742. if (!a) {
  11743. console.log('unexpected error in prerequest for showContextMenu.onSuccess');
  11744. return;
  11745. }
  11746.  
  11747. let z = null;
  11748. a.liveChatItemContextMenuSupportedRenderers && a.liveChatItemContextMenuSupportedRenderers.menuRenderer && (z = a.liveChatItemContextMenuSupportedRenderers.menuRenderer);
  11749.  
  11750. if (z) {
  11751. a = z;
  11752. targetCnt.__cacheResolvedEndpointData__(endpoint, a, true);
  11753. }
  11754.  
  11755. };
  11756. const onFailure = (a) => {
  11757.  
  11758. /*
  11759.  
  11760. if (a instanceof Error || a instanceof Object || a instanceof String)
  11761. var b = a;
  11762. hq(new xm("Error encountered calling GetLiveChatItemContextMenu",b))
  11763.  
  11764. */
  11765.  
  11766. targetCnt.__cacheResolvedEndpointData__(endpoint, null);
  11767. // console.log('onFailure', a)
  11768.  
  11769. };
  11770.  
  11771. if (doPreRequest) {
  11772.  
  11773. let propertyCounter = 0;
  11774. const pm1 = __showContextMenu_assign_lock_with_external_unlock_(targetCnt);
  11775. const p1Timeout = 800;
  11776. const proxyKey = '__$$__proxy_to_this__$$__' + Date.now();
  11777.  
  11778. try {
  11779.  
  11780. const onSuccessHelperFn = function () {
  11781. pm1.p1unlock();
  11782. if (propertyCounter !== 5) {
  11783. console.log('Error in prerequest for showContextMenu.onSuccessHelperFn')
  11784. return;
  11785. }
  11786. if (this[proxyKey] !== targetCnt) {
  11787. console.log('Error in prerequest for showContextMenu.this');
  11788. return;
  11789. }
  11790. onSuccess(...arguments);
  11791. };
  11792. const onFailureHelperFn = function () {
  11793. pm1.p1unlock();
  11794. if (propertyCounter !== 5) {
  11795. console.log('Error in prerequest for showContextMenu.onFailureHelperFn')
  11796. return;
  11797. }
  11798. if (this[proxyKey] !== targetCnt) {
  11799. console.log('Error in prerequest for showContextMenu.this');
  11800. return;
  11801. }
  11802. onFailure(...arguments);
  11803.  
  11804. }
  11805. const fakeTargetCnt = new Proxy({
  11806. __showContextMenu_forceNativeRequest__: 1,
  11807. get handleGetContextMenuResponse_() {
  11808. propertyCounter += 2;
  11809. return onSuccessHelperFn;
  11810. },
  11811. get handleGetContextMenuError() {
  11812. propertyCounter += 3;
  11813. return onFailureHelperFn;
  11814. }
  11815. }, {
  11816. get(_, key, receiver) {
  11817. if (key in _) return _[key];
  11818. if (key === proxyKey) return targetCnt;
  11819.  
  11820. let giveNative = false;
  11821. if (key in targetCnt) {
  11822. if (key === 'data') giveNative = true;
  11823. else if (typeof targetCnt[key] === 'function') giveNative = true;
  11824. }
  11825. if (giveNative) return targetCnt[key];
  11826. }
  11827. });
  11828.  
  11829. const fakeEvent = (() => {
  11830. const { target, bubbles, cancelable, cancelBubble, srcElement, timeStamp, defaultPrevented, currentTarget, composed } = evt;
  11831. const nf = function () { }
  11832. const [stopPropagation, stopImmediatePropagation, preventDefault] = [nf, nf, nf];
  11833.  
  11834. return {
  11835. type: 'tap',
  11836. eventPhase: 0,
  11837. isTrusted: false,
  11838. __composed: true,
  11839. bubbles, cancelable, cancelBubble, timeStamp,
  11840. target, srcElement, defaultPrevented, currentTarget, composed,
  11841. stopPropagation, stopImmediatePropagation, preventDefault
  11842. };
  11843. })(evt);
  11844. targetCnt.showContextMenu.call(fakeTargetCnt, fakeEvent);
  11845.  
  11846.  
  11847. } catch (e) {
  11848. console.warn(e);
  11849. propertyCounter = 7;
  11850.  
  11851. }
  11852. if (propertyCounter !== 5) {
  11853. console.log('Error in prerequest for showContextMenu', propertyCounter);
  11854. return;
  11855. }
  11856.  
  11857. pm1.assignLock(targetCnt, p1Timeout);
  11858.  
  11859. }
  11860.  
  11861.  
  11862.  
  11863.  
  11864.  
  11865.  
  11866. }, true);
  11867.  
  11868.  
  11869. }
  11870.  
  11871.  
  11872.  
  11873. /*
  11874.  
  11875. const w=new Set(); for(const a of document.getElementsByTagName('*')) if(a.showContextMenu && a.showContextMenu_) w.add(a.is||''); console.log([...w.keys()])
  11876.  
  11877. */
  11878.  
  11879. whenDefinedMultiple([
  11880. "yt-live-chat-ticker-sponsor-item-renderer",
  11881. "yt-live-chat-ticker-paid-message-item-renderer",
  11882.  
  11883. "yt-live-chat-banner-header-renderer",
  11884. "yt-live-chat-text-message-renderer",
  11885. "ytd-sponsorships-live-chat-gift-purchase-announcement-renderer",
  11886. "ytd-sponsorships-live-chat-header-renderer",
  11887. "ytd-sponsorships-live-chat-gift-redemption-announcement-renderer",
  11888.  
  11889. "yt-live-chat-paid-sticker-renderer",
  11890. "yt-live-chat-viewer-engagement-message-renderer",
  11891. "yt-live-chat-paid-message-renderer"
  11892.  
  11893.  
  11894.  
  11895.  
  11896. ]).then(sTags => {
  11897.  
  11898. mightFirstCheckOnYtInit();
  11899. groupCollapsed("YouTube Super Fast Chat", " | fixShowContextMenu");
  11900. console1.log("[Begin]");
  11901.  
  11902.  
  11903. const __showContextMenu_mutex__ = new Mutex();
  11904. let __showContextMenu_mutex_unlock__ = null;
  11905. let lastShowMenuTarget = null;
  11906.  
  11907.  
  11908.  
  11909.  
  11910. const wm37 = new WeakMap();
  11911.  
  11912. const dProto = {
  11913.  
  11914.  
  11915. // CACHE_SHOW_CONTEXT_MENU_FOR_REOPEN
  11916.  
  11917. __cacheResolvedEndpointData__: (endpoint, a, doDeepCopy) => {
  11918. if (a) {
  11919. if (doDeepCopy) a = deepCopy(a);
  11920. wm37.set(endpoint, a);
  11921. } else {
  11922. wm37.remove(endpoint);
  11923. }
  11924. },
  11925. __getCachedEndpointData__: function (endpoint) {
  11926. endpoint = endpoint || (this.data || 0).contextMenuEndpoint || 0;
  11927. if (endpoint) return wm37.get(endpoint);
  11928. return null;
  11929. },
  11930. /** @type {(resolvedEndpoint: any) => void 0} */
  11931. __showCachedContextMenu__: function (resolvedEndpoint) { // non-null
  11932.  
  11933. resolvedEndpoint = deepCopy(resolvedEndpoint);
  11934. // let b = deepCopy(resolvedEndpoint, ['trackingParams', 'clickTrackingParams'])
  11935. Promise.resolve(resolvedEndpoint).then((resolvedEndpoint) => {
  11936. this.__showContextMenu_skip_cacheResolvedEndpointData__ = 1;
  11937. this.showContextMenu_(resolvedEndpoint);
  11938. this.__showContextMenu_skip_cacheResolvedEndpointData__ = 0;
  11939. resolvedEndpoint = null;
  11940. });
  11941.  
  11942.  
  11943. },
  11944.  
  11945.  
  11946.  
  11947. showContextMenuForCacheReopen: function (a) {
  11948. if (this && this.__showContextMenu_forceNativeRequest__) return this.showContextMenu37(a);
  11949. if (!this || !this.isAttached) return; // in case; avoid Error: No provider for: InjectionToken(NETWORK_TOKEN) in _.showContextMenu
  11950. if (!this.__showContextMenu_forceNativeRequest__) {
  11951. const endpoint = (this.data || 0).contextMenuEndpoint || 0;
  11952. if (endpoint) {
  11953. const resolvedEndpoint = this.__getCachedEndpointData__(endpoint);
  11954. if (resolvedEndpoint) {
  11955. this.__showCachedContextMenu__(resolvedEndpoint);
  11956. a && a.stopPropagation()
  11957. return;
  11958. }
  11959. }
  11960. }
  11961. return this.showContextMenu37(a);
  11962. },
  11963.  
  11964. showContextMenuForCacheReopen_: function (a) {
  11965. if (this && this.__showContextMenu_forceNativeRequest__) return this.showContextMenu37_(a);
  11966. if (!this || !this.isAttached) return; // in case; avoid Error: No provider for: InjectionToken(NETWORK_TOKEN) in _.showContextMenu
  11967. if (!this.__showContextMenu_skip_cacheResolvedEndpointData__) {
  11968. const endpoint = (this.data || 0).contextMenuEndpoint || 0;
  11969. if (endpoint) {
  11970. const f = this.__cacheResolvedEndpointData__;
  11971. if (typeof f === 'function') f(endpoint, a, true);
  11972. }
  11973. }
  11974. return this.showContextMenu37_(a);
  11975. },
  11976.  
  11977. // ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU
  11978.  
  11979. showContextMenuWithDisableScroll: function (a) {
  11980.  
  11981. const endpoint = (this.data || 0).contextMenuEndpoint || 0;
  11982. if (endpoint && typeof this.is === 'string' && this.menuVisible === false && this.menuOpen === false) {
  11983.  
  11984. const parentComponent = this.parentComponent;
  11985. if (parentComponent && parentComponent.is === 'yt-live-chat-item-list-renderer' && parentComponent.contextMenuOpen === false && parentComponent.allowScroll === true) {
  11986. parentComponent.contextMenuOpen = true; // computeAllowScroll_(contextMenuOpen, moderationModeEnabled): allowScroll = !(contextMenuOpen || moderationModeEnabled)
  11987. }
  11988. }
  11989.  
  11990. return this.showContextMenu48.apply(this, arguments);
  11991.  
  11992. },
  11993.  
  11994. // ENABLE_MUTEX_FOR_SHOW_CONTEXT_MENU
  11995.  
  11996. __showContextMenu_mutex_unlock_isEmpty__: () => {
  11997. return __showContextMenu_mutex_unlock__ === null;
  11998. },
  11999.  
  12000. __showContextMenu_assign_lock__: function (p) {
  12001.  
  12002. const mutex = __showContextMenu_mutex__;
  12003.  
  12004. mutex.lockWith(unlock => {
  12005. p.then(unlock);
  12006. p = null;
  12007. unlock = null;
  12008. });
  12009.  
  12010. },
  12011.  
  12012. showContextMenuWithMutex: function (a) {
  12013. if (this.__showContextMenu_forceNativeRequest__) return this.showContextMenu47(a);
  12014. if (!this || !this.isAttached) return; // in case; avoid Error: No provider for: InjectionToken(NETWORK_TOKEN) in _.showContextMenu
  12015. lastShowMenuTarget = this;
  12016. const wNode = mWeakRef(this);
  12017.  
  12018.  
  12019. const mutex = __showContextMenu_mutex__;
  12020.  
  12021. mutex.lockWith(unlock => {
  12022. const cnt = kRef(wNode);
  12023. if (lastShowMenuTarget !== cnt || !cnt) {
  12024. unlock();
  12025. return;
  12026. }
  12027.  
  12028. setTimeout(unlock, 800); // in case network failure
  12029. __showContextMenu_mutex_unlock__ = unlock;
  12030. try {
  12031. cnt.showContextMenu47(a);
  12032. } catch (e) {
  12033. console.warn(e);
  12034. unlock(); // in case function script error
  12035. }
  12036.  
  12037. });
  12038.  
  12039.  
  12040. },
  12041.  
  12042. showContextMenuWithMutex_: function (a) {
  12043.  
  12044. if (__showContextMenu_mutex_unlock__ && this === lastShowMenuTarget) {
  12045. __showContextMenu_mutex_unlock__();
  12046. __showContextMenu_mutex_unlock__ = null;
  12047. }
  12048. return this.showContextMenu47_(a);
  12049.  
  12050. }
  12051.  
  12052. }
  12053.  
  12054. for (const tag of sTags) { // ##tag##
  12055.  
  12056. (() => {
  12057.  
  12058. const dummy = document.createElement(tag);
  12059.  
  12060. const cProto = getProto(dummy);
  12061. if (!cProto || !cProto.attached) {
  12062. console1.warn(`proto.attached for ${tag} is unavailable.`);
  12063. return;
  12064. }
  12065.  
  12066.  
  12067. 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) {
  12068. cProto.showContextMenu37_ = cProto.showContextMenu_;
  12069. cProto.showContextMenu37 = cProto.showContextMenu;
  12070. cProto.__showContextMenu_forceNativeRequest__ = 0;
  12071. cProto.__cacheResolvedEndpointData__ = dProto.__cacheResolvedEndpointData__
  12072. cProto.__getCachedEndpointData__ = dProto.__getCachedEndpointData__
  12073. cProto.__showCachedContextMenu__ = dProto.__showCachedContextMenu__
  12074. cProto.showContextMenu = dProto.showContextMenuForCacheReopen;
  12075. cProto.showContextMenu_ = dProto.showContextMenuForCacheReopen_;
  12076. console1.log("CACHE_SHOW_CONTEXT_MENU_FOR_REOPEN - OK", tag);
  12077. } else {
  12078. console1.log("CACHE_SHOW_CONTEXT_MENU_FOR_REOPEN - NG", tag);
  12079. }
  12080.  
  12081. 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) {
  12082. cProto.showContextMenu48 = cProto.showContextMenu;
  12083. cProto.showContextMenu = dProto.showContextMenuWithDisableScroll;
  12084. console1.log("ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU - OK", tag);
  12085. } else if (!ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU) {
  12086. DEBUG_skipLog001 || console1.log("ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU - N/A", tag);
  12087. } else {
  12088. console1.log("ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU - NG", tag);
  12089. }
  12090.  
  12091.  
  12092. 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) {
  12093. cProto.showContextMenu47_ = cProto.showContextMenu_;
  12094. cProto.showContextMenu47 = cProto.showContextMenu;
  12095. cProto.__showContextMenu_mutex_unlock_isEmpty__ = dProto.__showContextMenu_mutex_unlock_isEmpty__;
  12096. cProto.__showContextMenu_assign_lock__ = dProto.__showContextMenu_assign_lock__;
  12097. cProto.showContextMenu = dProto.showContextMenuWithMutex;
  12098. cProto.showContextMenu_ = dProto.showContextMenuWithMutex_;
  12099. console1.log("ENABLE_MUTEX_FOR_SHOW_CONTEXT_MENU - OK", tag);
  12100. } else {
  12101. console1.log("ENABLE_MUTEX_FOR_SHOW_CONTEXT_MENU - NG", tag);
  12102. }
  12103.  
  12104. })();
  12105.  
  12106. }
  12107.  
  12108. console1.log("[End]");
  12109.  
  12110. groupEnd();
  12111.  
  12112. }).catch(console.warn);
  12113.  
  12114.  
  12115.  
  12116. if (FIX_UNKNOWN_BUG_FOR_OVERLAY) {
  12117. // this is to fix " TypeError: this.backdropElement.prepare is not a function "
  12118.  
  12119. customElements.whenDefined('tp-yt-paper-dialog').then(() => {
  12120.  
  12121.  
  12122. mightFirstCheckOnYtInit();
  12123. groupCollapsed("YouTube Super Fast Chat", " | tp-yt-paper-dialog hacks");
  12124. console1.log("[Begin]");
  12125. (() => {
  12126.  
  12127. const tag = "tp-yt-paper-dialog";
  12128. const dummy = document.createElement(tag);
  12129.  
  12130. const cProto = getProto(dummy);
  12131. if (!cProto || !cProto.attached) {
  12132. console1.warn(`proto.attached for ${tag} is unavailable.`);
  12133. return;
  12134. }
  12135.  
  12136. if (typeof cProto.__openedChanged === 'function' && !cProto.__openedChanged49 && cProto.__openedChanged.length === 0) {
  12137.  
  12138.  
  12139. cProto.__openedChanged49 = cProto.__openedChanged;
  12140.  
  12141. cProto.__openedChanged = function () {
  12142. const manager = (this || 0)._manager || 0;
  12143. if (manager && !manager.trackBackdrop49 && manager.trackBackdrop) {
  12144. manager.trackBackdrop49 = manager.trackBackdrop;
  12145. if (manager.trackBackdrop.length === 0) {
  12146. manager.trackBackdrop = function () {
  12147. try {
  12148. return this.trackBackdrop49();
  12149. } catch (e) {
  12150. let showMessage = true;
  12151. if (e instanceof TypeError && e.message === 'this.backdropElement.prepare is not a function') {
  12152. // this is well known issue.
  12153. showMessage = false;
  12154. }
  12155. showMessage && console.log('manager.trackBackdrop', e);
  12156. }
  12157. }
  12158. }
  12159. }
  12160. return this.__openedChanged49();
  12161. };
  12162.  
  12163.  
  12164. }
  12165.  
  12166.  
  12167. })();
  12168.  
  12169.  
  12170. console1.log("[End]");
  12171.  
  12172. groupEnd();
  12173.  
  12174.  
  12175. }).catch(console.warn);
  12176.  
  12177. }
  12178.  
  12179.  
  12180. customElements.whenDefined('tp-yt-iron-dropdown').then(() => {
  12181.  
  12182. mightFirstCheckOnYtInit();
  12183. groupCollapsed("YouTube Super Fast Chat", " | tp-yt-iron-dropdown hacks");
  12184. console1.log("[Begin]");
  12185. (() => {
  12186.  
  12187. const tag = "tp-yt-iron-dropdown";
  12188. const dummy = document.createElement(tag);
  12189.  
  12190. const cProto = getProto(dummy);
  12191. if (!cProto || !cProto.attached) {
  12192. console1.warn(`proto.attached for ${tag} is unavailable.`);
  12193. return;
  12194. }
  12195.  
  12196. if (USE_VANILLA_DEREF && typeof cProto.__deraf === 'function' && cProto.__deraf.length === 2 && !cProto.__deraf34 && fnIntegrity(cProto.__deraf) === '2.42.24') {
  12197. cProto.__deraf_hn__ = function (sId, fn) {
  12198. const rhKey = `_rafHandler_${sId}`;
  12199. const m = this[rhKey] || (this[rhKey] = new WeakMap());
  12200. if (m.has(fn)) return m.get(fn);
  12201. const resFn = () => {
  12202. this.__rafs[sId] = null;
  12203. fn.call(this)
  12204. };
  12205. m.set(fn, resFn);
  12206. m.set(resFn, resFn);
  12207. return resFn;
  12208. };
  12209. cProto.__deraf34 = cProto.__deraf;
  12210. cProto.__deraf = function (a, b) { // sId, fn
  12211. let c = this.__rafs;
  12212. null !== c[a] && cancelAnimationFrame(c[a]);
  12213. c[a] = requestAnimationFrame(this.__deraf_hn__(a, b));
  12214. };
  12215. console1.log("USE_VANILLA_DEREF - OK");
  12216. } else {
  12217. console1.log("USE_VANILLA_DEREF - NG");
  12218. }
  12219.  
  12220. if (FIX_DROPDOWN_DERAF && typeof cProto.__deraf === 'function' && cProto.__deraf.length === 2 && !cProto.__deraf66) {
  12221. cProto.__deraf66 = cProto.__deraf;
  12222. cProto.__deraf = function (sId, fn) {
  12223. if (this.__byPassRAF__) {
  12224. Promise.resolve(this).then((cnt) => {
  12225. fn.call(cnt);
  12226. cnt = null;
  12227. });
  12228. }
  12229. let r = this.__deraf66.apply(this, arguments);
  12230. return r;
  12231. }
  12232. console1.log("FIX_DROPDOWN_DERAF - OK");
  12233. } else {
  12234. console1.log("FIX_DROPDOWN_DERAF - NG");
  12235. }
  12236.  
  12237.  
  12238. if (BOOST_MENU_OPENCHANGED_RENDERING && typeof cProto.__openedChanged === 'function' && !cProto.__mtChanged__ && fnIntegrity(cProto.__openedChanged) === '0.46.20') {
  12239.  
  12240. let lastClose = null;
  12241. let lastOpen = null;
  12242. let cid = 0;
  12243.  
  12244. cProto.__mtChanged__ = function (b) {
  12245.  
  12246. Promise.resolve(this).then((cnt) => {
  12247. cnt._applyFocus();
  12248. return cnt;
  12249. }).then((cnt) => {
  12250. b ? cnt._renderOpened() : cnt._renderClosed();
  12251. cnt = null;
  12252. }).catch(console.warn);
  12253.  
  12254. };
  12255.  
  12256. const __moChanged__ = () => {
  12257. if (!cid) return;
  12258. // console.log(553, !!lastOpen, !!lastClose);
  12259. cid = 0;
  12260. if (lastOpen && !lastClose && lastOpen.isAttached) {
  12261. lastOpen.__mtChanged__(1)
  12262. } else if (lastClose && !lastOpen && lastClose.isAttached) {
  12263. lastClose.__mtChanged__(0);
  12264. }
  12265. lastOpen = null;
  12266. lastClose = null;
  12267. };
  12268.  
  12269.  
  12270. if (typeof cProto._openedChanged === 'function' && !cProto._openedChanged66) {
  12271. cProto._openedChanged66 = cProto._openedChanged;
  12272. cProto._openedChanged = function () {
  12273. // this.__byPassRAF__ = !lastOpen ? true : false; // or just true?
  12274. this.__byPassRAF__ = true;
  12275. let r = this._openedChanged66.apply(this, arguments);
  12276. this.__byPassRAF__ = false;
  12277. return r;
  12278. }
  12279. }
  12280.  
  12281. const pSetGet = (key, pdThis, pdBase) => {
  12282. // note: this is not really a standard way for the getOwnPropertyDescriptors; but it is sufficient to make the job done
  12283. return {
  12284. get: (pdThis[key] || 0).get || (pdBase[key] || 0).get,
  12285. set: (pdThis[key] || 0).set || (pdBase[key] || 0).set
  12286. };
  12287. };
  12288.  
  12289. cProto.__modifiedMenuPropsFn__ = function () {
  12290. const pdThis = Object.getOwnPropertyDescriptors(this.constructor.prototype)
  12291. const pdBase = Object.getOwnPropertyDescriptors(this)
  12292.  
  12293. const pdAutoFitOnAttach = pSetGet('autoFitOnAttach', pdThis, pdBase);
  12294. const pdExpandSizingTargetForScrollbars = pSetGet('expandSizingTargetForScrollbars', pdThis, pdBase);
  12295. const pdAllowOutsideScroll = pSetGet('allowOutsideScroll', pdThis, pdBase);
  12296.  
  12297. if (pdAutoFitOnAttach.get || pdAutoFitOnAttach.set) {
  12298. console.warn('there is setter/getter for autoFitOnAttach');
  12299. return;
  12300. }
  12301. if (pdExpandSizingTargetForScrollbars.get || pdExpandSizingTargetForScrollbars.set) {
  12302. console.warn('there is setter/getter for expandSizingTargetForScrollbars');
  12303. return;
  12304. }
  12305. if (!pdAllowOutsideScroll.get || !pdAllowOutsideScroll.set) {
  12306. console.warn('there is NO setter-getter for allowOutsideScroll');
  12307. return;
  12308. }
  12309.  
  12310. let { autoFitOnAttach, expandSizingTargetForScrollbars, allowOutsideScroll } = this;
  12311.  
  12312. this.__AllowOutsideScrollPD__ = pdAllowOutsideScroll;
  12313.  
  12314. const fitEnable = CHAT_MENU_REFIT_ALONG_SCROLLING === 2;
  12315.  
  12316. Object.defineProperties(this, {
  12317. autoFitOnAttach: {
  12318. get() {
  12319. if (fitEnable && this._modifiedMenuPropOn062__) return true;
  12320. return autoFitOnAttach;
  12321. },
  12322. set(nv) {
  12323. autoFitOnAttach = nv;
  12324. return true;
  12325. },
  12326. enumerable: true,
  12327. configurable: true
  12328. }, expandSizingTargetForScrollbars: {
  12329. get() {
  12330. if (fitEnable && this._modifiedMenuPropOn062__) return true;
  12331. return expandSizingTargetForScrollbars;
  12332. },
  12333. set(nv) {
  12334. expandSizingTargetForScrollbars = nv;
  12335. return true;
  12336. },
  12337. enumerable: true,
  12338. configurable: true
  12339. }, allowOutsideScroll: {
  12340. get() {
  12341. if (this._modifiedMenuPropOn062__) return true;
  12342. return allowOutsideScroll;
  12343. },
  12344. set(nv) {
  12345. allowOutsideScroll = nv;
  12346. this.__AllowOutsideScrollPD__.set.call(this, nv);
  12347. return true;
  12348. },
  12349. enumerable: true,
  12350. configurable: true
  12351. }
  12352. })
  12353. };
  12354.  
  12355. /*
  12356. // ***** position() to be changed. *****
  12357. tp-yt-iron-dropdown[class], tp-yt-iron-dropdown[class] #contentWrapper, tp-yt-iron-dropdown[class] ytd-menu-popup-renderer[class] {
  12358.  
  12359. overflow: visible !important;
  12360. min-width: max-content !important;
  12361. max-width: max-content !important;
  12362. max-height: max-content !important;
  12363. min-height: max-content !important;
  12364. white-space: nowrap;
  12365. }
  12366.  
  12367. */
  12368. if (FIX_MENU_POSITION_N_SIZING_ON_SHOWN && typeof cProto.position === 'function' && !cProto.position34 && typeof cProto.refit === 'function') {
  12369.  
  12370. let m34 = 0;
  12371. cProto.__refitByPosition__ = function () {
  12372. m34++;
  12373. if (m34 <= 0) m34 = 0;
  12374. if (m34 !== 1) return;
  12375. const hostElement = this.hostElement || this;
  12376. if (document.visibilityState === 'visible') {
  12377. const sizingTarget = this.sizingTarget;
  12378. if (!sizingTarget) {
  12379. m34 = 0;
  12380. return;
  12381. }
  12382. hostElement.setAttribute('rNgzQ', '');
  12383. sizingTarget.setAttribute('rNgzQ', '');
  12384.  
  12385. const gn = () => {
  12386. hostElement.removeAttribute('rNgzQ');
  12387. sizingTarget.removeAttribute('rNgzQ');
  12388. }
  12389.  
  12390. const an = async () => {
  12391. while (m34 >= 1) {
  12392. await renderReadyPn(sizingTarget);
  12393. if (this.opened && this.isAttached && sizingTarget.isConnected === true && sizingTarget === this.sizingTarget) {
  12394. if (sizingTarget.matches('ytd-menu-popup-renderer[slot="dropdown-content"].yt-live-chat-app')) this.refit();
  12395. }
  12396. m34--;
  12397. }
  12398. m34 = 0;
  12399. Promise.resolve().then(gn);
  12400. }
  12401. setTimeout(an, 4); // wait those resizing function calls
  12402.  
  12403.  
  12404. } else {
  12405. m34 = 0;
  12406. }
  12407. }
  12408. cProto.position34 = cProto.position
  12409. cProto.position = function () {
  12410. if (this._positionInitialize_) {
  12411. this._positionInitialize_ = 0;
  12412. this.__refitByPosition__();
  12413. }
  12414. let r = cProto.position34.apply(this, arguments);
  12415. return r;
  12416. }
  12417. console1.log("FIX_MENU_POSITION_ON_SHOWN - OK");
  12418.  
  12419. } else {
  12420.  
  12421. console1.log("FIX_MENU_POSITION_ON_SHOWN - NG");
  12422.  
  12423. }
  12424.  
  12425.  
  12426.  
  12427. cProto.__openedChanged = function () {
  12428. // console.log(123445)
  12429. this._positionInitialize_ = 1;
  12430. // this.removeAttribute('horizontal-align')
  12431. // this.removeAttribute('vertical-align')
  12432. if (typeof this.__menuTypeCheck__ !== 'boolean') {
  12433. this.__menuTypeCheck__ = true;
  12434. if (CHAT_MENU_SCROLL_UNLOCKING) {
  12435. this._modifiedMenuPropOn062__ = false;
  12436. // console.log(513, this.positionTarget && this.positionTarget.classList.contains('yt-live-chat-text-message-renderer'))
  12437. // this.autoFitOnAttach = true;
  12438. // this.expandSizingTargetForScrollbars = true;
  12439. // this.allowOutsideScroll = true;
  12440. // console.log(519,Object.getOwnPropertyDescriptors(this.constructor.prototype))
  12441. this.__modifiedMenuPropsFn__();
  12442. // this.constrain= function(){}
  12443. // this.position= function(){}
  12444.  
  12445. // this.autoFitOnAttach = true;
  12446. // this.expandSizingTargetForScrollbars = true;
  12447. // this.allowOutsideScroll = true;
  12448. }
  12449. }
  12450. if (CHAT_MENU_SCROLL_UNLOCKING && this.opened) {
  12451. let newValue = null;
  12452. const positionTarget = this.positionTarget;
  12453. if (positionTarget && positionTarget.classList.contains('yt-live-chat-text-message-renderer')) {
  12454. if (this._modifiedMenuPropOn062__ === false) {
  12455. newValue = true;
  12456. }
  12457. } else if (this._modifiedMenuPropOn062__ === true) {
  12458. newValue = false;
  12459. }
  12460. if (newValue !== null) {
  12461. const beforeAllowOutsideScroll = this.allowOutsideScroll;
  12462. this._modifiedMenuPropOn062__ = newValue;
  12463. const afterAllowOutsideScroll = this.allowOutsideScroll;
  12464. if (beforeAllowOutsideScroll !== afterAllowOutsideScroll) this.__AllowOutsideScrollPD__.set.call(this, afterAllowOutsideScroll);
  12465. }
  12466. }
  12467.  
  12468. if (this.opened) {
  12469.  
  12470. Promise.resolve().then(() => {
  12471.  
  12472. this._prepareRenderOpened();
  12473. }).then(() => {
  12474. // console.log('[yt-chat-dialog]', this._manager)
  12475. try{
  12476. this._manager.addOverlay(this);
  12477. }catch(e){
  12478. console.log('this._manager.addOverlay(this) fails.')
  12479. }
  12480. if (this._manager._overlays.length === 1) {
  12481. lastOpen = this;
  12482. lastClose = null;
  12483. } else {
  12484. return 1;
  12485. }
  12486. // if (cid) {
  12487. // clearTimeout(cid);
  12488. // cid = -1;
  12489. // this.__moChanged__();
  12490. // cid = 0;
  12491. // } else {
  12492. // cid = -1;
  12493. // this.__moChanged__();
  12494. // cid = 0;
  12495. // }
  12496. // cid = cid > 0 ? clearTimeout(cid) : 0;
  12497. // console.log(580, this.positionTarget && this.positionTarget.classList.contains('yt-live-chat-text-message-renderer'))
  12498. // cid = cid || setTimeout(__moChanged__, delay1);
  12499. cid = cid || requestAnimationFrame(__moChanged__);
  12500. }).then((r) => {
  12501.  
  12502. if (r) this.__mtChanged__(1);
  12503. }).catch(console.warn);
  12504.  
  12505. } else {
  12506. Promise.resolve().then(() => {
  12507. // console.log('[yt-chat-dialog]', this._manager)
  12508. try{
  12509. this._manager.removeOverlay(this);
  12510. }catch(e){
  12511. console.log('this._manager.removeOverlay(this) fails.')
  12512. }
  12513. if (this._manager._overlays.length === 0) {
  12514. lastClose = this;
  12515. lastOpen = null;
  12516. } else {
  12517. return 1;
  12518. }
  12519. // cid = cid > 0 ? clearTimeout(cid) : 0;
  12520. // console.log(581, this.positionTarget && this.positionTarget.classList.contains('yt-live-chat-text-message-renderer'))
  12521. // cid = cid || setTimeout(__moChanged__, delay1);
  12522. cid = cid || requestAnimationFrame(__moChanged__);
  12523. }).then((r) => {
  12524. if (r) this.__mtChanged__(0);
  12525. }).catch(console.warn);
  12526.  
  12527. }
  12528.  
  12529. }
  12530. console1.log("BOOST_MENU_OPENCHANGED_RENDERING - OK");
  12531.  
  12532. } else {
  12533.  
  12534. assertor(() => fnIntegrity(cProto.__openedChanged, '0.46.20'));
  12535. console1.log("FIX_MENU_REOPEN_RENDER_PERFORMANC_1 - NG");
  12536.  
  12537. }
  12538.  
  12539.  
  12540. if (FIX_CLICKING_MESSAGE_MENU_DISPLAY_ON_MOUSE_CLICK && typeof cProto.__openedChanged === 'function' && !cProto.__openedChanged82) {
  12541.  
  12542. cProto.__openedChanged82 = cProto.__openedChanged;
  12543.  
  12544.  
  12545. cProto.__openedChanged = function () {
  12546. const positionTarget = this.positionTarget;
  12547. currentMenuPivotWR = positionTarget ? mWeakRef(positionTarget) : null;
  12548. return this.__openedChanged82.apply(this, arguments);
  12549. }
  12550. }
  12551.  
  12552.  
  12553. })();
  12554.  
  12555. console1.log("[End]");
  12556.  
  12557. groupEnd();
  12558.  
  12559. }).catch(console.warn);
  12560.  
  12561.  
  12562.  
  12563. FIX_ToggleRenderPolymerControllerExtractionBug && customElements.whenDefined('yt-live-chat-toggle-renderer').then(() => {
  12564.  
  12565. mightFirstCheckOnYtInit();
  12566. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-toggle-renderer hacks");
  12567. console1.log("[Begin]");
  12568. (() => {
  12569.  
  12570. const tag = "yt-live-chat-toggle-renderer";
  12571. const dummy = document.createElement(tag);
  12572.  
  12573. const cProto = getProto(dummy);
  12574. if (!cProto || !cProto.attached) {
  12575. console1.warn(`proto.attached for ${tag} is unavailable.`);
  12576. return;
  12577. }
  12578.  
  12579. })();
  12580.  
  12581. console1.log("[End]");
  12582. groupEnd();
  12583.  
  12584. });
  12585.  
  12586. FIX_MOUSEOVER_FN && (() => {
  12587.  
  12588. // this is to show tooltip for emoji
  12589.  
  12590.  
  12591. let lastShow = 0;
  12592.  
  12593. const wm = new WeakSet();
  12594. const mo1 = new MutationObserver((mutations) => {
  12595.  
  12596. for (const p of document.querySelectorAll('[shared-tooltip-text]:not([__a6cwm__])')) {
  12597. p.setAttribute('__a6cwm__', '');
  12598. }
  12599.  
  12600. });
  12601. mo1.observe(document, { subtree: true, attributes: true, attributeFilter: ['shared-tooltip-text'], childList: true });
  12602.  
  12603. const mo2 = new MutationObserver((mutations) => {
  12604.  
  12605. for (const mutation of mutations) {
  12606. const p = mutation.target;
  12607. if (mutation.attributeName) {
  12608. if (p.getAttribute('shared-tooltip-text')) { // allow hack
  12609. wm.add(p);
  12610. for (const e of p.getElementsByTagName('*')) {
  12611. wm.add(e);
  12612. }
  12613. } else {
  12614. if (wm.has(p)) {
  12615. wm.remove(p);
  12616. for (const e of p.getElementsByTagName('*')) {
  12617. wm.remove(e);
  12618. }
  12619. }
  12620. }
  12621. }
  12622. }
  12623. });
  12624. mo2.observe(document, { subtree: true, attributes: true, attributeFilter: ['__a6cwm__', 'shared-tooltip-text'], childList: false });
  12625.  
  12626.  
  12627. let done = 0;
  12628. // lcrFn2 will run twice to ensure the method is successfully injected.
  12629. const lcrFn2 = (lcrDummy) => {
  12630. // make minimal function overhead by pre-defining all possible outside.
  12631.  
  12632. const tag = "yt-live-chat-renderer"
  12633. const dummy = lcrDummy;
  12634.  
  12635. const cProto = getProto(dummy);
  12636. if (!cProto || !cProto.attached) {
  12637. console.warn(`proto.attached for ${tag} is unavailable.`);
  12638. return;
  12639. }
  12640.  
  12641. // mightFirstCheckOnYtInit();
  12642. // groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-renderer hacks");
  12643. // console.log("[Begin]");
  12644.  
  12645.  
  12646.  
  12647. if (done !== 1 && typeof cProto.onMouseOver_ === 'function' && !cProto.onMouseOver37_ && typeof cProto.createTooltipIfRequired_ === 'function' && cProto.createTooltipIfRequired_.length === 0) {
  12648.  
  12649. done = 1;
  12650. const onMouseOver37_ = cProto.onMouseOver37_ = cProto.onMouseOver_;
  12651.  
  12652. const checkMatch = (() => {
  12653.  
  12654.  
  12655. let accessList = [];
  12656. let withError = false;
  12657. try {
  12658.  
  12659. onMouseOver37_.call(lcrDummy, {
  12660. type: 'mouseover',
  12661. target: new Proxy({
  12662. nodeName: 'DIV',
  12663. tagName: 'DIV',
  12664. getAttribute: function () { },
  12665. parentNode: null
  12666. }, {
  12667. get(target, p) {
  12668. accessList.push(`getter:${p}`);
  12669. if (!(p in target)) throw Error(`getter ${p} is not found`);
  12670. },
  12671. set(target, p, v) {
  12672. accessList.push(`setter:${p}`);
  12673. throw Error(`setter ${p} is not found`);
  12674. }
  12675. })
  12676. });
  12677. } catch (e) {
  12678. withError = true;
  12679. // console.warn(e);
  12680. }
  12681.  
  12682. if (withError) return false;
  12683.  
  12684. if (accessList.join(',') !== 'getter:getAttribute,getter:parentNode') return false;
  12685.  
  12686. accessList.length = 0;
  12687.  
  12688. let parent;
  12689. try {
  12690.  
  12691. parent = new Proxy({
  12692. nodeName: 'DIV',
  12693. tagName: 'DIV',
  12694. getAttribute: function (e) {
  12695.  
  12696. accessList.push(`getter:getAttribute(${e})`);
  12697. return e === 'shared-tooltip-text' ? ':cherry_blossom:' : null;
  12698.  
  12699. },
  12700. parentNode: null
  12701. }, {
  12702. get(target, p) {
  12703. accessList.push(`getter:${p}`);
  12704. if (!(p in target)) throw Error(`getter ${p} is not found`);
  12705. return target[p]
  12706. },
  12707. set(target, p, v) {
  12708. accessList.push(`setter:${p}`);
  12709. throw Error(`setter ${p} is not found`);
  12710. }
  12711. });
  12712.  
  12713. onMouseOver37_.call(lcrDummy, {
  12714. type: 'mouseover',
  12715. target: new Proxy({
  12716. nodeName: 'IMG',
  12717. tagName: 'IMG',
  12718. id: 'img',
  12719. getAttribute: function (e) {
  12720.  
  12721. accessList.push(`getter:getAttribute(${e})`);
  12722. return e === 'shared-tooltip-text' ? ':cherry_blossom:' : null;
  12723.  
  12724. },
  12725. get parentNode() {
  12726. return parent
  12727. },
  12728. get parentElement() {
  12729. return parent
  12730. }
  12731. }, {
  12732. get(target, p) {
  12733. accessList.push(`getter:${p}`);
  12734. if (!(p in target)) throw Error(`getter ${p} is not found`);
  12735. return target[p]
  12736. },
  12737. set(target, p, v) {
  12738. accessList.push(`setter:${p}`);
  12739. throw Error(`setter ${p} is not found`);
  12740. }
  12741. })
  12742. });
  12743. } catch (e) {
  12744. withError = true;
  12745. // console.warn(e);
  12746. }
  12747. parent = null;
  12748.  
  12749. 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:$$') {
  12750. return true;
  12751. }
  12752.  
  12753.  
  12754.  
  12755. })();
  12756. if (checkMatch) {
  12757.  
  12758. cProto.onMouseOver_ = function (evt) {
  12759. const p = (evt || 0).target || 0;
  12760. if (p.nodeType === 1 && wm.has(p)) {
  12761. const ct = Date.now();
  12762. if (lastShow + 18 > ct) return;
  12763. const cnt = insp(this);
  12764. lastShow = ct;
  12765. try {
  12766. cnt.onMouseOver37_.call(this, evt);
  12767. } catch (e) {
  12768. console.warn(e);
  12769. }
  12770. }
  12771. };
  12772.  
  12773. const lcrs = toUniqueArr([lcrDummy, ...document.querySelectorAll('yt-live-chat-renderer')]);
  12774. for (const lcr of lcrs) {
  12775. const cnt = insp(lcr);
  12776. const hostElement = cnt.hostElement;
  12777. if (hostElement && cnt.isAttached === true && cnt.onMouseOver37_ === cProto.onMouseOver37_ && typeof cProto.onMouseOver_ === 'function' && cProto.onMouseOver_ !== cProto.onMouseOver37_ && cnt.onMouseOver_ === cProto.onMouseOver_) {
  12778. hostElement.removeEventListener("mouseover", cProto.onMouseOver37_, !0)
  12779. hostElement.addEventListener("mouseover", cProto.onMouseOver_, !0)
  12780. }
  12781. }
  12782.  
  12783. console.log('[yt-chat-lcr] FIX_MOUSEOVER_FN - OK')
  12784.  
  12785. } else {
  12786.  
  12787. console.log('[yt-chat-lcr] FIX_MOUSEOVER_FN - NG')
  12788.  
  12789. }
  12790.  
  12791. } else if (done !== 1) {
  12792. done = 2;
  12793. console.log('[yt-chat-lcr] FIX_MOUSEOVER_FN - NG')
  12794. }
  12795.  
  12796. // console.log("[End]");
  12797. // groupEnd();
  12798.  
  12799.  
  12800. };
  12801. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  12802. // getLCRDummy() must be called for injection
  12803. getLCRDummy().then(lcrFn2);
  12804.  
  12805. })();
  12806.  
  12807.  
  12808. /*
  12809.  
  12810.  
  12811.  
  12812.  
  12813.  
  12814. var FU = function() {
  12815. var a = this;
  12816. this.nextHandle_ = 1;
  12817. this.clients_ = {};
  12818. this.JSC$10323_callbacks_ = {};
  12819. this.unsubscribeAsyncHandles_ = {};
  12820. this.subscribe = vl(function(b, c, d) {
  12821. var e = Geb(b);
  12822. if (e in a.clients_)
  12823. e in a.unsubscribeAsyncHandles_ && Jq.cancel(a.unsubscribeAsyncHandles_[e]);
  12824. else {
  12825. a: {
  12826. var h = Geb(b), l;
  12827. for (l in a.unsubscribeAsyncHandles_) {
  12828. var m = a.clients_[l];
  12829. if (m instanceof KO) {
  12830. delete a.clients_[l];
  12831. delete a.JSC$10323_callbacks_[l];
  12832. Jq.cancel(a.unsubscribeAsyncHandles_[l]);
  12833. delete a.unsubscribeAsyncHandles_[l];
  12834. i6a(m);
  12835. m.objectId_ = new FQa(h);
  12836. m.register();
  12837. d = m;
  12838. break a
  12839. }
  12840. }
  12841. d.objectSource = b.invalidationId.objectSource;
  12842. d.objectId = h;
  12843. if (b = b.webAuthConfigurationData)
  12844. b.multiUserSessionIndex && (d.sessionIndex = parseInt(b.multiUserSessionIndex, 10)),
  12845. b.pageId && (d.pageId = b.pageId);
  12846. d = new KO(d,a.handleInvalidationData_.bind(a));
  12847. d.register()
  12848. }
  12849. a.clients_[e] = d;
  12850. a.JSC$10323_callbacks_[e] = {}
  12851. }
  12852. d = a.nextHandle_++;
  12853. a.JSC$10323_callbacks_[e][d] = c;
  12854. return d
  12855. })
  12856. };
  12857. FU.prototype.unsubscribe = function(a, b) {
  12858. var c = Geb(a);
  12859. if (c in this.JSC$10323_callbacks_ && (delete this.JSC$10323_callbacks_[c][b],
  12860. !this.JSC$10323_callbacks_[c].length)) {
  12861. var d = this.clients_[c];
  12862. b = Jq.run(function() {
  12863. ei(d);
  12864. delete this.clients_[c];
  12865. delete this.unsubscribeAsyncHandles_[c]
  12866. }
  12867. .bind(this));
  12868. this.unsubscribeAsyncHandles_[c] = b
  12869. }
  12870. }
  12871. ;
  12872.  
  12873.  
  12874. */
  12875.  
  12876.  
  12877. const onManagerFound = (dummyManager) => {
  12878. if (!dummyManager || typeof dummyManager !== 'object') return;
  12879.  
  12880. const mgrProto = dummyManager.constructor.prototype;
  12881.  
  12882. let keyCallbackStore = '';
  12883. for (const [key, v] of Object.entries(dummyManager)) {
  12884. if (key.includes('_callbacks_')) keyCallbackStore = key;
  12885. }
  12886.  
  12887. if (!keyCallbackStore || typeof mgrProto.unsubscribe !== 'function' || mgrProto.unsubscribe.length !== 2) return;
  12888.  
  12889. if (mgrProto.unsubscribe16) return;
  12890.  
  12891. mgrProto.unsubscribe16 = mgrProto.unsubscribe;
  12892.  
  12893. groupCollapsed("YouTube Super Fast Chat", " | *live-chat-manager* hacks");
  12894. console1.log("[Begin]");
  12895.  
  12896. const idMapper = new Map();
  12897.  
  12898. const convertId = function (objectId) {
  12899. if (!objectId || typeof objectId !== 'string') return null;
  12900.  
  12901. let result = idMapper.get(objectId)
  12902. if (result) return result;
  12903. result = atob(objectId.replace(/-/g, "+").replace(/_/g, "/"));
  12904. idMapper.set(objectId, result)
  12905. return result;
  12906. }
  12907.  
  12908.  
  12909. const rafHandleHolder = [];
  12910.  
  12911. let pzw = 0;
  12912. let lza = 0;
  12913. const rafHandlerFn = () => {
  12914. pzw = 0;
  12915. if (rafHandleHolder.length === 1) {
  12916. const f = rafHandleHolder[0];
  12917. rafHandleHolder.length = 0;
  12918. f();
  12919. } else if (rafHandleHolder.length > 1) {
  12920. const arr = rafHandleHolder.slice(0);
  12921. rafHandleHolder.length = 0;
  12922. for (const fn of arr) fn();
  12923. }
  12924. };
  12925.  
  12926.  
  12927. if (CHANGE_MANAGER_UNSUBSCRIBE) {
  12928.  
  12929. const checkIntegrityForSubscribe = (mgr) => {
  12930. if (mgr
  12931. && typeof mgr.unsubscribe16 === 'function' && mgr.unsubscribe16.length === 2
  12932. && typeof mgr.subscribe18 === 'function' && (mgr.subscribe18.length === 0 || mgr.subscribe18.length === 3)) {
  12933.  
  12934. const ns = new Set(Object.keys(mgr));
  12935. const ms = new Set(Object.keys(mgr.constructor.prototype));
  12936.  
  12937. if (ns.size >= 6 && ms.size >= 4) {
  12938. // including 'subscribe18'
  12939. // 'unsubscribe16', 'subscribe19'
  12940.  
  12941. let r = 0;
  12942. for (const k of ['nextHandle_', 'clients_', keyCallbackStore, 'unsubscribeAsyncHandles_', 'subscribe', 'subscribe18']) {
  12943. r += ns.has(k) ? 1 : 0;
  12944. }
  12945. for (const k of ['unsubscribe', 'handleInvalidationData_', 'unsubscribe16', 'subscribe19']) {
  12946. r += ms.has(k) ? 1 : 0;
  12947. }
  12948. if (r === 10) {
  12949. const isObject = (c) => (c || 0).constructor === Object;
  12950.  
  12951. if (isObject(mgr['clients_']) && isObject(mgr[keyCallbackStore]) && isObject(mgr['unsubscribeAsyncHandles_'])) {
  12952.  
  12953. return true;
  12954. }
  12955.  
  12956.  
  12957. }
  12958.  
  12959. }
  12960.  
  12961.  
  12962. }
  12963. return false;
  12964. }
  12965.  
  12966. mgrProto.subscribe19 = function (o, f, opts) {
  12967.  
  12968. const ct_clients_ = this.clients_ || 0;
  12969. const ct_handles_ = this.unsubscribeAsyncHandles_ || 0;
  12970.  
  12971. if (this.__doCustomSubscribe__ !== true || !ct_clients_ || !ct_handles_) return this.subscribe18.apply(this, arguments);
  12972.  
  12973. let objectId = ((o || 0).invalidationId || 0).objectId;
  12974. if (!objectId) return this.subscribe18.apply(this, arguments);
  12975. objectId = convertId(objectId);
  12976.  
  12977. // console.log('subscribe', objectId, ct_clients_[objectId], arguments);
  12978.  
  12979. if (ct_clients_[objectId]) {
  12980. if (ct_handles_[objectId] < 0) delete ct_handles_[objectId];
  12981. }
  12982.  
  12983. return this.subscribe18.apply(this, arguments);
  12984. }
  12985.  
  12986. mgrProto.unsubscribe = function (o, d) {
  12987. if (!this.subscribe18 && typeof this.subscribe === 'function') {
  12988. this.subscribe18 = this.subscribe;
  12989. this.subscribe = this.subscribe19;
  12990. this.__doCustomSubscribe__ = checkIntegrityForSubscribe(this);
  12991. }
  12992. const ct_clients_ = this.clients_;
  12993. const ct_handles_ = this.unsubscribeAsyncHandles_;
  12994. if (this.__doCustomSubscribe__ !== true || !ct_clients_ || !ct_handles_) return this.unsubscribe16.apply(this, arguments);
  12995.  
  12996. let objectId = ((o || 0).invalidationId || 0).objectId;
  12997. if (!objectId) return this.unsubscribe16.apply(this, arguments);
  12998.  
  12999. objectId = convertId(objectId);
  13000.  
  13001.  
  13002. // console.log('unsubscribe', objectId, ct_clients_[objectId], arguments);
  13003.  
  13004. const callbacks = this[keyCallbackStore] || 0;
  13005. const callbackObj = callbacks[objectId] || 0;
  13006.  
  13007.  
  13008. if (callbackObj && (delete callbackObj[d], isEmptyObject(callbackObj))) {
  13009. const w = ct_clients_[objectId];
  13010. lza = (lza & 1073741823) + 1;
  13011. const qta = -lza;
  13012. rafHandleHolder.push(() => {
  13013. if (qta === ct_handles_[objectId]) {
  13014. const o = {
  13015. callbacks, callbackObj,
  13016. client: ct_clients_[objectId],
  13017. handle: ct_handles_[objectId]
  13018. };
  13019. let p = 0;
  13020. try {
  13021. if (ct_clients_[objectId] === w) {
  13022. w && "function" === typeof w.dispose && w.dispose();
  13023. delete ct_clients_[objectId];
  13024. delete ct_handles_[objectId];
  13025. p = 1;
  13026. } else {
  13027. // w && "function" === typeof w.dispose && w.dispose();
  13028. // delete ct_clients_[objectId];
  13029. // delete ct_handles_[objectId];
  13030. p = 2;
  13031. }
  13032. } catch (e) {
  13033. console.warn(e);
  13034. }
  13035. console.log(`unsubscribed: ${p}`, this, o);
  13036. }
  13037. });
  13038. ct_handles_[objectId] = qta;
  13039. if (pzw === 0) {
  13040. pzw = requestAnimationFrame(rafHandlerFn);
  13041. }
  13042. }
  13043. }
  13044.  
  13045.  
  13046. console1.log("CHANGE_MANAGER_UNSUBSCRIBE - OK")
  13047.  
  13048. } else {
  13049.  
  13050. console1.log("CHANGE_MANAGER_UNSUBSCRIBE - NG")
  13051. }
  13052.  
  13053. console1.log("[End]");
  13054.  
  13055. groupEnd();
  13056.  
  13057. }
  13058.  
  13059.  
  13060.  
  13061. /*
  13062.  
  13063.  
  13064. a.prototype.async = function(e, h) {
  13065. return 0 < h ? Iq.run(e.bind(this), h) : ~Kq.run(e.bind(this))
  13066. }
  13067. ;
  13068. a.prototype.cancelAsync = function(e) {
  13069. 0 > e ? Kq.cancel(~e) : Iq.cancel(e)
  13070. }
  13071.  
  13072. */
  13073.  
  13074.  
  13075. (FASTER_ICON_RENDERING && Promise.all(
  13076. [
  13077. customElements.whenDefined("yt-icon-shape"),
  13078. customElements.whenDefined("yt-icon")
  13079. // document.createElement('icon-shape'),
  13080. ]
  13081. )).then(() => {
  13082. let cq = 0;
  13083. let dummys = [document.createElement('yt-icon-shape'), document.createElement('yt-icon')]
  13084. for (const dummy of dummys) {
  13085. let cProto = getProto(dummy);
  13086. if (cProto && typeof cProto.shouldRenderIconShape === 'function' && !cProto.shouldRenderIconShape571 && cProto.shouldRenderIconShape.length === 1) {
  13087. assertor(() => fnIntegrity(cProto.shouldRenderIconShape, '1.70.38'));
  13088. cq++;
  13089. cProto.shouldRenderIconShape571 = cProto.shouldRenderIconShape;
  13090. cProto.shouldRenderIconShape = function (a) {
  13091. if (this.isAnimatedIcon) return this.shouldRenderIconShape571(a);
  13092. if (!this.iconType || !this.iconShapeData) return this.shouldRenderIconShape571(a);
  13093. if (!this.iconName) return this.shouldRenderIconShape571(a);
  13094. return false;
  13095. // console.log(1051, this.iconType)
  13096. // console.log(1052, this.iconShapeData)
  13097. // console.log(1053, this.isAnimatedIcon)
  13098. }
  13099. }
  13100. // if(cProto && cProto.switchTemplateAtRegistration){
  13101. // cProto.switchTemplateAtRegistration = false;
  13102. // }
  13103. }
  13104. if (cq === 1) {
  13105. console.log("modified shouldRenderIconShape - Y")
  13106. } else {
  13107. console.log("modified shouldRenderIconShape - N", cq)
  13108. }
  13109. });
  13110.  
  13111. customElements.whenDefined("yt-invalidation-continuation").then(() => {
  13112.  
  13113. let __dummyManager__ = null;
  13114.  
  13115. mightFirstCheckOnYtInit();
  13116. groupCollapsed("YouTube Super Fast Chat", " | yt-invalidation-continuation hacks");
  13117. console1.log("[Begin]");
  13118. (() => {
  13119.  
  13120. const tag = "yt-invalidation-continuation"
  13121. const dummy = document.createElement(tag);
  13122.  
  13123. const cProto = getProto(dummy);
  13124. if (!cProto || !cProto.attached) {
  13125. console1.warn(`proto.attached for ${tag} is unavailable.`);
  13126. return;
  13127. }
  13128.  
  13129. const dummyManager = insp(dummy).manager_ || 0;
  13130. __dummyManager__ = dummyManager;
  13131.  
  13132.  
  13133. })();
  13134.  
  13135. console1.log("[End]");
  13136.  
  13137. groupEnd();
  13138.  
  13139.  
  13140.  
  13141. onManagerFound(__dummyManager__);
  13142.  
  13143. }).catch(console.warn);
  13144.  
  13145.  
  13146. if (INTERACTIVITY_BACKGROUND_ANIMATION >= 1) {
  13147.  
  13148. customElements.whenDefined("yt-live-interactivity-component-background").then(() => {
  13149.  
  13150. mightFirstCheckOnYtInit();
  13151. groupCollapsed("YouTube Super Fast Chat", " | yt-live-interactivity-component-background hacks");
  13152. console1.log("[Begin]");
  13153. (() => {
  13154.  
  13155. const tag = "yt-live-interactivity-component-background"
  13156. const dummy = document.createElement(tag);
  13157.  
  13158. const cProto = getProto(dummy);
  13159. if (!cProto || !cProto.attached) {
  13160. console1.warn(`proto.attached for ${tag} is unavailable.`);
  13161. return;
  13162. }
  13163.  
  13164. cProto.__toStopAfterRun__ = function (hostElement) {
  13165. let mo = new MutationObserver(() => {
  13166. mo.disconnect();
  13167. mo.takeRecords();
  13168. mo = null;
  13169. this.lottieAnimation && this.lottieAnimation.stop(); // primary
  13170. foregroundPromiseFn().then(() => { // if the lottieAnimation is started with rAf triggering
  13171. this.lottieAnimation && this.lottieAnimation.stop(); // fallback
  13172. });
  13173. });
  13174. mo.observe(hostElement, { subtree: true, childList: true });
  13175. }
  13176.  
  13177. if (INTERACTIVITY_BACKGROUND_ANIMATION >= 1 && typeof cProto.maybeLoadAnimationBackground === 'function' && !cProto.maybeLoadAnimationBackground77 && cProto.maybeLoadAnimationBackground.length === 0) {
  13178.  
  13179. cProto.maybeLoadAnimationBackground77 = cProto.maybeLoadAnimationBackground;
  13180. cProto.maybeLoadAnimationBackground = function () {
  13181. let toRun = true;
  13182. let stopAfterRun = false;
  13183. if (!this.__bypassDisableAnimationBackground__) {
  13184. let doFix = false;
  13185. if (INTERACTIVITY_BACKGROUND_ANIMATION === 1) {
  13186. if (!this.lottieAnimation) {
  13187. doFix = true;
  13188. }
  13189. } else if (INTERACTIVITY_BACKGROUND_ANIMATION === 2) {
  13190. doFix = true;
  13191. }
  13192. if (doFix) {
  13193. if (this.useAnimationBackground === true) {
  13194. console.log('DISABLE_INTERACTIVITY_BACKGROUND_ANIMATION', this.lottieAnimation);
  13195. }
  13196. toRun = true;
  13197. stopAfterRun = true;
  13198. }
  13199. }
  13200. if (toRun) {
  13201. if (stopAfterRun && (this.hostElement instanceof HTMLElement_)) {
  13202. this.__toStopAfterRun__(this.hostElement); // primary
  13203. }
  13204. const r = this.maybeLoadAnimationBackground77.apply(this, arguments);
  13205. if (stopAfterRun && this.lottieAnimation) {
  13206. this.lottieAnimation.stop(); // fallback if no mutation
  13207. }
  13208. return r;
  13209. }
  13210. }
  13211.  
  13212. console1.log(`INTERACTIVITY_BACKGROUND_ANIMATION(${INTERACTIVITY_BACKGROUND_ANIMATION}) - OK`);
  13213.  
  13214. } else {
  13215. console1.log(`INTERACTIVITY_BACKGROUND_ANIMATION(${INTERACTIVITY_BACKGROUND_ANIMATION}) - NG`);
  13216.  
  13217. }
  13218.  
  13219. })();
  13220.  
  13221. console1.log("[End]");
  13222.  
  13223. groupEnd();
  13224.  
  13225.  
  13226. }).catch(console.warn);
  13227.  
  13228. }
  13229.  
  13230.  
  13231. if (DELAY_FOCUSEDCHANGED) {
  13232.  
  13233. customElements.whenDefined("yt-live-chat-text-input-field-renderer").then(() => {
  13234.  
  13235.  
  13236. mightFirstCheckOnYtInit();
  13237. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-text-input-field-renderer hacks");
  13238. console1.log("[Begin]");
  13239. (() => {
  13240.  
  13241. const tag = "yt-live-chat-text-input-field-renderer"
  13242. const dummy = document.createElement(tag);
  13243.  
  13244. const cProto = getProto(dummy);
  13245. if (!cProto || !cProto.attached) {
  13246. console1.warn(`proto.attached for ${tag} is unavailable.`);
  13247. return;
  13248. }
  13249.  
  13250. if (DELAY_FOCUSEDCHANGED && typeof cProto.focusedChanged === 'function' && cProto.focusedChanged.length === 0 && !cProto.focusedChanged372) {
  13251. cProto.focusedChanged372 = cProto.focusedChanged;
  13252. cProto.focusedChanged = function () {
  13253. Promise.resolve(this).then((cnt) => {
  13254. if (cnt.isAttached === true) cnt.focusedChanged372();
  13255. });
  13256. }
  13257. }
  13258.  
  13259. })();
  13260.  
  13261. console1.log("[End]");
  13262.  
  13263. groupEnd();
  13264.  
  13265. });
  13266.  
  13267. }
  13268.  
  13269. }
  13270.  
  13271.  
  13272.  
  13273.  
  13274. promiseForCustomYtElementsReady.then(onRegistryReadyForDOMOperations);
  13275.  
  13276. const fixJsonParse = () => {
  13277.  
  13278. let p1 = window.onerror;
  13279.  
  13280. try {
  13281. JSON.parse("{}");
  13282. } catch (e) {
  13283. console.warn(e);
  13284. }
  13285.  
  13286. let p2 = window.onerror;
  13287.  
  13288. if (p1 !== p2) {
  13289.  
  13290.  
  13291. console.groupCollapsed(`%c${"YouTube Super Fast Chat"}%c${" | JS Engine Issue Found"}`,
  13292. "background-color: #010502; color: #fe806a; font-weight: 700; padding: 2px;",
  13293. "background-color: #010502; color: #fe806a; font-weight: 300; padding: 2px;"
  13294. );
  13295.  
  13296. console.warn("\nJSON.parse is hacked (e.g. Brave's script injection) which causes window.onerror changes on every JSON.parse call.\nPlease install https://greasyfork.org/scripts/473972-youtube-js-engine-tamer to fix the issue.\n");
  13297.  
  13298. console.groupEnd();
  13299.  
  13300. }
  13301.  
  13302. }
  13303.  
  13304. if (CHECK_JSONPRUNE) {
  13305. promiseForCustomYtElementsReady.then(fixJsonParse);
  13306. }
  13307.  
  13308. });
  13309.  
  13310.  
  13311.  
  13312. })({ IntersectionObserver });