Greasy Fork is available in English.

YouTube Super Fast Chat

Ultimate Performance Boost for YouTube Live Chats

Install this script?
Author's suggested script

You may also like YouTube JS Engine Tamer.

Install this script
  1. // ==UserScript==
  2. // @name YouTube Super Fast Chat
  3. // @version 0.100.14
  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.greatest.deepsurf.us/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.  
  71. /// -------------------------------------------------------------------------
  72.  
  73. // ENABLE_REDUCED_MAXITEMS_FOR_FLUSH and MAX_ITEMS_FOR_FULL_FLUSH are removed due to ENABLE_CHAT_MESSAGES_BOOSTED_STAMPING is introduced
  74.  
  75. // 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
  76. 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)
  77. // 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)
  78.  
  79. const ENABLE_NO_SMOOTH_TRANSFORM = true; // Depends on whether you want the animation effect for new chat messages <<< DON'T CHANGE >>>
  80. // const USE_OPTIMIZED_ON_SCROLL_ITEMS = true; // TRUE for the majority
  81. 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)
  82.  
  83. const FIX_SHOW_MORE_BUTTON_LOCATION = true; // When there are voting options (bottom panel), move the "show more" button to the top.
  84. const FIX_INPUT_PANEL_OVERFLOW_ISSUE = true; // When the super chat button is flicking with color, the scrollbar might come out.
  85. const FIX_INPUT_PANEL_BORDER_ISSUE = true; // No border should be allowed if there is an empty input panel.
  86. const SET_CONTAIN_FOR_CHATROOM = true; // Rendering hacks (`contain`) for chatroom elements. [ General ]
  87.  
  88. const FORCE_CONTENT_VISIBILITY_UNSET = true; // Content-visibility should be always VISIBLE for high performance and great rendering.
  89. const FORCE_WILL_CHANGE_UNSET = true; // Will-change should be always UNSET (auto) for high performance and low energy impact.
  90.  
  91. // Replace requestAnimationFrame timers with custom implementation
  92. const ENABLE_RAF_HACK_TICKERS = true; // When there is a ticker
  93. const ENABLE_RAF_HACK_DOCKED_MESSAGE = true; // To be confirmed
  94. const ENABLE_RAF_HACK_INPUT_RENDERER = true; // To be confirmed
  95. const ENABLE_RAF_HACK_EMOJI_PICKER = true; // When changing the page of the emoji picker
  96.  
  97. // Force rendering all the character subsets of the designated font(s) before messages come (Pre-Rendering of Text)
  98. const ENABLE_FONT_PRE_RENDERING_PREFERRED = 1 | 2 | 4 | 8 | 16;
  99.  
  100. // Backdrop `filter: blur(4px)` inside the iframe can extend to the whole page, causing a negative visual impact on the video you are watching.
  101. const NO_BACKDROP_FILTER_WHEN_MENU_SHOWN = true;
  102.  
  103. // Data Manipulation for Participants (Participant List)
  104. // << if DO_PARTICIPANT_LIST_HACKS >>
  105. const DO_PARTICIPANT_LIST_HACKS = true; // TRUE for the majority
  106. const SHOW_PARTICIPANT_CHANGES_IN_CONSOLE = false; // Just too annoying to show them all in popular chat
  107. const CHECK_CHANGE_TO_PARTICIPANT_RENDERER_CONTENT = true; // Only consider changes in renderable content (not concerned with the last chat message of the participants)
  108. const PARTICIPANT_UPDATE_ONLY_ONLY_IF_MODIFICATION_DETECTED = true;
  109. // << end >>
  110.  
  111. // show more button
  112. const ENABLE_SHOW_MORE_BLINKER = true; // BLINK WHEN NEW MESSAGES COME
  113.  
  114. // faster stampDomArray_ for participants list creation
  115. const ENABLE_FLAGS_MAINTAIN_STABLE_LIST_VAL = 1; // 0 - OFF; 1 - ON; 2 - ON(PARTICIPANTS_LIST ONLY)
  116. const USE_MAINTAIN_STABLE_LIST_ONLY_WHEN_KS_FLAG_IS_SET = false;
  117.  
  118. // reuse yt components
  119. const ENABLE_FLAGS_REUSE_COMPONENTS = true;
  120.  
  121. // ShadyDom Free is buggy
  122. const DISABLE_FLAGS_SHADYDOM_FREE = true;
  123.  
  124. // images <Group#I01>
  125. const AUTHOR_PHOTO_SINGLE_THUMBNAIL = 1; // 0 - disable; 1- smallest; 2- largest
  126. const EMOJI_IMAGE_SINGLE_THUMBNAIL = 1; // 0 - disable; 1- smallest; 2- largest
  127. const LEAST_IMAGE_SIZE = 48; // minium size = 48px
  128.  
  129. const DO_LINK_PREFETCH = true; // DO NOT CHANGE
  130. // << if DO_LINK_PREFETCH >>
  131. const ENABLE_BASE_PREFETCHING = true; // (SUB-)DOMAIN | dns-prefetch & preconnect
  132. const ENABLE_PRELOAD_THUMBNAIL = true; // subresource (prefetch) [LINK for Images]
  133. const SKIP_PRELOAD_EMOJI = true;
  134. const PREFETCH_LIMITED_SIZE_EMOJI = 512; // DO NOT CHANGE THIS
  135. const PREFETCH_LIMITED_SIZE_AUTHOR_PHOTO = 68; // DO NOT CHANGE THIS
  136. // << end >>
  137.  
  138. const FIX_SETSRC_AND_THUMBNAILCHANGE_ = true; // Function Replacement for yt-img-shadow....
  139. const FIX_THUMBNAIL_DATACHANGED = true; // Function Replacement for yt-live-chat-author-badge-renderer..dataChanged
  140. // const REMOVE_PRELOADAVATARFORADDACTION = false; // Function Replacement for yt-live-chat-renderer..preloadAvatarForAddAction
  141.  
  142. const FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION = true; // important [depends on <Group#I01>]
  143. const FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT = true; // [depends on <Group#I01>]
  144.  
  145. // BROWSER SUPPORT: Chrome 75+, Edge 79+, Safari 13.1+, Firefox 63+, Opera 62+
  146. const TICKER_MAX_STEPS_LIMIT = 500; // NOT LESS THAN 5 STEPS!!
  147. // (( KEEP AS ALTERNATIVE IF USE_ADVANCED_TICKING NOT WORKING ))
  148. // [limiting 500 max steps] is recommended for "confortable visual change"
  149. // min. step increment 0.2% => max steps: 500 => 800ms per each update
  150. // min. step increment 0.5% => max steps: 200 => 1000ms per each update
  151. // min. step increment 1.0% => max steps: 100 => 1000ms per each update
  152. // min. step increment 2.5% => max steps: 40 => 1000ms per each update
  153. // min. step increment 5.0% => max steps: 20 => 1250ms per each update
  154. const ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX = true; // for video playback's ticker issue. [ Playback Replay - Pause at Middle - Backwards Seeking ]
  155. 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
  156. // << end >>
  157.  
  158. const FIX_TOOLTIP_DISPLAY = true; // changed in 2024.05.02; updated in 2025.01.10
  159. const USE_VANILLA_DEREF = true;
  160. const FIX_DROPDOWN_DERAF = true; // DONT CHANGE
  161.  
  162.  
  163. const CACHE_SHOW_CONTEXT_MENU_FOR_REOPEN = true; // cache the menu data and used for the next reopen
  164. const ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU = false; // pause auto scroll faster when the context menu is about to show
  165. const ENABLE_MUTEX_FOR_SHOW_CONTEXT_MENU = true; // avoid multiple requests on the same time
  166.  
  167. const BOOST_MENU_OPENCHANGED_RENDERING = true;
  168. const FIX_CLICKING_MESSAGE_MENU_DISPLAY_ON_MOUSE_CLICK = true; // click again = close
  169. const NO_ITEM_TAP_FOR_NON_STATIONARY_TAP = true; // dont open the menu (e.g. text message) if cursor is moved or long press
  170. const TAP_ACTION_DURATION = 280; // exceeding 280ms would not consider as a tap action
  171. const PREREQUEST_CONTEXT_MENU_ON_MOUSE_DOWN = true; // require CACHE_SHOW_CONTEXT_MENU_FOR_REOPEN = true
  172. // const FIX_MENU_CAPTURE_SCROLL = true;
  173. const CHAT_MENU_REFIT_ALONG_SCROLLING = 0; // 0 for locking / default; 1 for unlocking only; 2 for unlocking and refit
  174.  
  175. const RAF_FIX_keepScrollClamped = true;
  176. const RAF_FIX_scrollIncrementally = 2; // 0: no action; 1: basic fix; 2: also fix scroll position
  177.  
  178. // << if BOOST_MENU_OPENCHANGED_RENDERING >>
  179. const FIX_MENU_POSITION_N_SIZING_ON_SHOWN = 1; // correct size and position when the menu dropdown opens
  180.  
  181. const CHECK_JSONPRUNE = true; // This is a bug in Brave
  182. // << end >>
  183.  
  184. // const LIVE_CHAT_FLUSH_ON_FOREGROUND_ONLY = false;
  185.  
  186. const CHANGE_MANAGER_UNSUBSCRIBE = true;
  187.  
  188. const INTERACTIVITY_BACKGROUND_ANIMATION = 1; // mostly for pinned message
  189. // 0 = default Yt animation background [= no fix];
  190. // 1 = disable default animation background [= keep special animation];
  191. // 2 = disable all animation backgrounds [= no animation backbround]
  192.  
  193. const CLOSE_TICKER_PINNED_MESSAGE_WHEN_HEADER_CLICKED = true;
  194.  
  195. const MAX_TOOLTIP_NO_WRAP_WIDTH = '72vw'; // '' for disable; accept values like '60px', '25vw'
  196.  
  197. const DISABLE_Translation_By_Google = true;
  198.  
  199. const FASTER_ICON_RENDERING = true;
  200.  
  201. const DELAY_FOCUSEDCHANGED = true;
  202.  
  203. const skipErrorForhandleAddChatItemAction_ = true; // currently depends on ENABLE_NO_SMOOTH_TRANSFORM
  204. const fixChildrenIssue801 = true; // if __children801__ is set [fix polymer controller method extration for `.set()`]
  205.  
  206. const SUPPRESS_refreshOffsetContainerHeight_ = true; // added in FEB 2024; true for default layout options; no effect if ENABLE_NO_SMOOTH_TRANSFORM is false
  207.  
  208. const NO_FILTER_DROPDOWN_BORDER = true; // added in 2024.03.02
  209.  
  210. const FIX_ANIMATION_TICKER_TEXT_POSITION = true; // CSS fix; experimental; added in 2024.04.07
  211. const FIX_AUTHOR_CHIP_BADGE_POSITION = true;
  212.  
  213. const FIX_ToggleRenderPolymerControllerExtractionBug = false; // to be reviewed
  214.  
  215. const REACTION_ANIMATION_PANEL_CSS_FIX = true;
  216.  
  217. const FIX_UNKNOWN_BUG_FOR_OVERLAY = true; // no .prepare() in backdrop element. reason is unknown.
  218.  
  219. const FIX_MOUSEOVER_FN = true; // avoid onMouseOver_ being triggerd quite a lot
  220.  
  221. // -------------------------------
  222.  
  223. const USE_OBTAIN_LCR_BY_BOTH_METHODS = false; // true for play safe
  224.  
  225. const FIX_MEMORY_LEAKAGE_TICKER_ACTIONMAP = true; // To fix Memory Leakage in yt-live-chat-ticker-...-item-renderer
  226. const FIX_MEMORY_LEAKAGE_TICKER_STATSBAR = true; // To fix Memory Leakage in updateStatsBarAndMaybeShowAnimation
  227. const FIX_MEMORY_LEAKAGE_TICKER_TIMER = true; // To fix Memory Leakage in setContainerWidth, slideDown, collapse // Dec 2024 fix in advance tickering
  228. const FIX_MEMORY_LEAKAGE_TICKER_DATACHANGED_setContainerWidth = true; // To fix Memory Leakage due to _.ytLiveChatTickerItemBehavior.setContainerWidth()
  229.  
  230.  
  231. // const USE_RM_ON_FOUNTAIN_MODEL = false; // No longer working since 2025.04.15
  232. // const DEBUG_RM_ON_FOUNTAIN_MODEL = false;
  233. // const FOUNTAIN_MODEL_TIME_CONFIRM = 1600; // 800 not sufficient; re-adding?
  234. const MODIFY_EMIT_MESSAGES_FOR_BOOST_CHAT = true; // enabled for boost chat only; instant emit & no background flush
  235.  
  236. /**
  237. *
  238. *
  239. *
  240. *
  241. *
  242. rendererStamperObserver_: function(a, b, c) {
  243. if (c.path == a) {
  244. if (c.value === void 0 && !this.hasDataPath_[a])
  245. return;
  246. this.hasDataPath_[a] = c.value !== void 0
  247. }
  248. this.rendererStamperApplyChangeRecord_(a, b, c)
  249. },
  250.  
  251.  
  252. addStampDomObserverFns_: function() {
  253. for (var a in this.stampDom) {
  254. var b = this.stampDom[a];
  255. b.id ? (this[SQa(b.id)] = this.rendererStamperObserver_.bind(this, a, b.id),
  256. this.hasDataPath_[a] = !1) : Er(new Dn("Bad rendererstamper config",this.is + ":" + a))
  257. }
  258. },
  259. *
  260. *
  261. *
  262. *
  263. *
  264. */
  265.  
  266.  
  267.  
  268.  
  269.  
  270.  
  271. // <<<<< FOR MEMORY LEAKAGE >>>>
  272.  
  273. // ========= EXPLANTION FOR 0.2% @ step timing [min. 0.2%] ===========
  274. /*
  275.  
  276. ### Time Approach
  277.  
  278. // all below values can make the time interval > 250ms
  279. // 250ms (practical value) refers to the minimum frequency for timeupdate in most browsers (typically, shorter timeupdate interval in modern browsers)
  280. if (totalDuration > 400000) stepInterval = 0.2; // 400000ms with 0.2% increment => 800ms
  281. else if (totalDuration > 200000) stepInterval = 0.5; // 200000ms with 0.5% increment => 1000ms
  282. else if (totalDuration > 100000) stepInterval = 1; // 100000ms with 1% increment => 1000ms
  283. else if (totalDuration > 50000) stepInterval = 2; // 50000ms with 2% increment => 1000ms
  284. else if (totalDuration > 25000) stepInterval = 5; // 25000ms with 5% increment => 1250ms
  285.  
  286. ### Pixel Check
  287. // Target Max Pixel Increment < 5px for Short Period Ticker (Rapid Background Change)
  288. // Assume total width <= 99px for short period ticker, like small donation & member welcome
  289. 99px * 5% = 4.95px < 5px [Condition Fulfilled]
  290.  
  291. ### Example - totalDuration = 280000
  292. totalDuration 280000
  293. stepInterval 0.5
  294. numOfSteps = Math.round(100 / stepInterval) = 200
  295. time interval = 280000 / 200 = 1400ms <acceptable>
  296.  
  297. ### Example - totalDuration = 18000
  298. totalDuration 18000
  299. stepInterval 5
  300. numOfSteps = Math.round(100 / stepInterval) = 20
  301. time interval = 18000 / 20 = 900ms <acceptable>
  302.  
  303. ### Example - totalDuration = 5000
  304. totalDuration 5000
  305. stepInterval 5
  306. numOfSteps = Math.round(100 / stepInterval) = 20
  307. time interval = 5000 / 20 = 250ms <threshold value>
  308.  
  309. ### Example - totalDuration = 3600
  310. totalDuration 3600
  311. stepInterval 5
  312. numOfSteps = Math.round(100 / stepInterval) = 20
  313. time interval = 3600 / 20 = 180ms <reasonable for 3600ms ticker>
  314.  
  315. */
  316.  
  317. // =======================================================================================================
  318.  
  319. // AUTOMAICALLY DETERMINED
  320. const ENABLE_FLAGS_MAINTAIN_STABLE_LIST = ENABLE_FLAGS_MAINTAIN_STABLE_LIST_VAL === 1;
  321. const ENABLE_FLAGS_MAINTAIN_STABLE_LIST_FOR_PARTICIPANTS_LIST = ENABLE_FLAGS_MAINTAIN_STABLE_LIST_VAL >= 1;
  322. const CHAT_MENU_SCROLL_UNLOCKING = CHAT_MENU_REFIT_ALONG_SCROLLING >= 1;
  323.  
  324.  
  325. // image sizing code
  326. // (d = (d = KC(a.customThumbnail.thumbnails, 16)) ? lc(oc(d)) : null)
  327.  
  328.  
  329. // function KC(a, b, c, d) {
  330. // d = void 0 === d ? "width" : d;
  331. // if (!a || !a.length)
  332. // return null;
  333. // if (z("kevlar_tuner_should_always_use_device_pixel_ratio")) {
  334. // var e = window.devicePixelRatio;
  335. // 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"));
  336. // HC = e
  337. // } else
  338. // HC || (HC = window.devicePixelRatio);
  339. // e = HC;
  340. // z("kevlar_tuner_should_always_use_device_pixel_ratio") ? b *= e : 1 < e && (b *= e);
  341. // if (z("kevlar_tuner_min_thumbnail_quality"))
  342. // return a[0].url || null;
  343. // e = a.length;
  344. // if (z("kevlar_tuner_max_thumbnail_quality"))
  345. // return a[e - 1].url || null;
  346. // if (c)
  347. // for (var h = 0; h < e; h++)
  348. // if (0 <= a[h].url.indexOf(c))
  349. // return a[h].url || null;
  350. // for (c = 0; c < e; c++)
  351. // if (a[c][d] >= b)
  352. // return a[c].url || null;
  353. // for (b = e - 1; 0 < b; b--)
  354. // if (a[b][d])
  355. // return a[b].url || null;
  356. // return a[0].url || null
  357. // }
  358.  
  359.  
  360. /// ------
  361.  
  362. // https://www.youtube.com/watch?v=byyvH5t0hKc
  363. // yt-live-chat-ticker-creator-goal-view-model
  364. // no ticker effect on timing
  365.  
  366. /*
  367.  
  368.  
  369. {
  370. "id": "ChwKGkNQS0pyNV9NdG9vREZVYlB6Z2FkRHWFUv2E",
  371. "initialTickerText": {
  372. "content": "Goal",
  373. "styleRuns": [
  374. {
  375. "startIndex": 0,
  376. "length": 4
  377. }
  378. ]
  379. },
  380. "tickerIcon": {
  381. "sources": [
  382. {
  383. "clientResource": {
  384. "imageName": "TARGET_ADD"
  385. }
  386. }
  387. ]
  388. },
  389. "showGoalStatusCommand": {
  390. "innertubeCommand": {
  391. "clickTrackingParams": "CCQQ7NANIhMI58DT_ef5rhMVxMW1Cx4qBzTz",
  392. "showEngagementPanelEndpoint": {
  393. "engagementPanel": {
  394. "engagementPanelSectionListRenderer": {
  395. "header": {
  396. "engagementPanelTitleHeaderRenderer": {
  397. "actionButton": {
  398. "buttonRenderer": {
  399. "icon": {
  400. "iconType": "QUESTION_CIRCLE"
  401. },
  402. "trackingParams": "CCgQ8FsiEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  403. "command": {
  404. "clickTrackingParams": "CCgQ8FsiEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  405. "commandExecutorCommand": {
  406. "commands": [
  407. {
  408. "clickTrackingParams": "CCgQ8FsiEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  409. "liveChatDialogEndpoint": {
  410. "content": {
  411. "liveChatDialogRenderer": {
  412. "trackingParams": "CCkQzS8iEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  413. "title": {
  414. "runs": [
  415. {
  416. "text": "Super Chat Goal"
  417. }
  418. ]
  419. },
  420. "dialogMessages": [
  421. {
  422. "runs": [
  423. {
  424. "text": "Join the fun by participating in the goal! "
  425. },
  426. {
  427. "text": "Learn more.\n",
  428. "navigationEndpoint": {
  429. "clickTrackingParams": "CCkQzS8iEwjm0Iz72rbKBxXT1EQBJekHNQM="
  430. }
  431. }
  432. ]
  433. },
  434. {
  435. "runs": [
  436. {
  437. "text": "How to participate",
  438. "bold": true,
  439. "textColor": 4294967295
  440. },
  441. {
  442. "text": "\n"
  443. },
  444. {
  445. "text": "1. Press \"Continue\"\n2. Purchase a Super Chat \n3. Watch the progress towards the goal\n4. Celebrate achieving it with the community!",
  446. "textColor": 4294967295
  447. }
  448. ]
  449. }
  450. ],
  451. "confirmButton": {
  452. "buttonRenderer": {
  453. "style": "STYLE_MONO_FILLED",
  454. "size": "SIZE_DEFAULT",
  455. "isDisabled": false,
  456. "text": {
  457. "simpleText": "Got it"
  458. },
  459. "trackingParams": "CCoQ8FsiEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  460. "accessibilityData": {
  461. "accessibilityData": {
  462. "label": "Got it"
  463. }
  464. }
  465. }
  466. }
  467. }
  468. }
  469. }
  470. },
  471. {
  472. "clickTrackingParams": "CCgQ8FsiEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  473. "hideEngagementPanelEndpoint": {
  474. "identifier": {
  475. "surface": "ENGAGEMENT_PANEL_SURFACE_LIVE_CHAT",
  476. "tag": "creator_goal_progress_engagement_panel"
  477. }
  478. }
  479. }
  480. ]
  481. }
  482. }
  483. }
  484. },
  485. "trackingParams": "CCUQ040EIhMI58DT_ef5rhMVxMW1Cx4qBzTz"
  486. }
  487. },
  488. "content": {
  489. "sectionListRenderer": {
  490. "contents": [
  491. {
  492. "creatorGoalProgressFlowViewModel": {
  493. "creatorGoalEntityKey": "EgtieXl2SDV0MGhLYyG7BzhF",
  494. "progressFlowButton": {
  495. "buttonViewModel": {
  496. "onTap": {
  497. "innertubeCommand": {
  498. "clickTrackingParams": "CCcQ8FsiEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  499. "commandMetadata": {
  500. "webCommandMetadata": {
  501. "ignoreNavigation": true
  502. }
  503. },
  504. "liveChatPurchaseMessageEndpoint": {
  505. "params": "Q2lrcUp3b1lWVU14ZFdObmIwTmZjMGQzZDE5RmRYVTFhVTF4Y0ZGM0VndGllWGwyU0RWME1HaExZeEFCSUFFNEFFSUNDQUUlM0Q="
  506. }
  507. }
  508. },
  509. "style": "BUTTON_VIEW_MODEL_STYLE_MONO",
  510. "trackingParams": "CCcQ8FsiEwjm0Iz72rbKBxXT1EQBJekHNQM=",
  511. "type": "BUTTON_VIEW_MODEL_TYPE_FILLED",
  512. "titleFormatted": {
  513. "content": "Continue",
  514. "styleRuns": [
  515. {
  516. "startIndex": 0,
  517. "length": 8
  518. }
  519. ]
  520. }
  521. }
  522. },
  523. "progressCountA11yLabel": "Super Chat goal progress: $0 out of $1"
  524. }
  525. }
  526. ],
  527. "trackingParams": "CCYQui8iEwjm0Iz72rbKBxXT1EQBJekHNQM="
  528. }
  529. },
  530. "identifier": {
  531. "surface": "ENGAGEMENT_PANEL_SURFACE_LIVE_CHAT",
  532. "tag": "creator_goal_progress_engagement_panel"
  533. }
  534. }
  535. },
  536. "identifier": {
  537. "surface": "ENGAGEMENT_PANEL_SURFACE_LIVE_CHAT",
  538. "tag": "creator_goal_progress_engagement_panel"
  539. },
  540. "engagementPanelPresentationConfigs": {
  541. "engagementPanelPopupPresentationConfig": {
  542. "popupType": "PANEL_POPUP_TYPE_DIALOG"
  543. }
  544. }
  545. }
  546. }
  547. },
  548. "creatorGoalEntityKey": "EgtieXl2SDV0MGhLYyG7BzhF",
  549. "shouldShowSetUpFlowOnMobile": true,
  550. "a11yLabel": "See Super Chat goal",
  551. "loggingDirectives": {
  552. "trackingParams": "CCQQ7NANIhMI58DT_ef5rhMVxMW1Cx4qBzTz",
  553. "visibility": {
  554. "types": "12"
  555. }
  556. }
  557. }
  558.  
  559.  
  560. */
  561.  
  562.  
  563. // ------
  564.  
  565. const { IntersectionObserver } = __CONTEXT__;
  566. let _x69;
  567. try {
  568. _x69 = document.createAttributeNS("http://www.w3.org/2000/svg", "nil").addEventListener;
  569. } catch (e) { }
  570. const pureAddEventListener = _x69;
  571. if (!pureAddEventListener) return console.warn("pureAddEventListener cannot be obtained.");
  572.  
  573. /** @type {globalThis.PromiseConstructor} */
  574. const Promise = (async () => { })().constructor; // YouTube hacks Promise in WaterFox Classic and "Promise.resolve(0)" nevers resolve.
  575. const [setTimeout_] = [setTimeout];
  576. // let jsonParseFix = null;
  577. const Image_ = Image;
  578. /** @type {typeof HTMLElement} */
  579. const HTMLElement_ = Reflect.getPrototypeOf(HTMLTitleElement);
  580.  
  581. const nextBrowserTick_ = nextBrowserTick;
  582. if (typeof nextBrowserTick_ !== "function" || (nextBrowserTick_.version || 0) < 2) {
  583. console.log('nextBrowserTick is not found.');
  584. return;
  585. }
  586.  
  587. if (!IntersectionObserver) return console.warn("Your browser does not support IntersectionObserver.\nPlease upgrade to the latest version.");
  588. if (typeof WebAssembly !== 'object') return console.warn("Your browser is too old.\nPlease upgrade to the latest version."); // for passive and once
  589.  
  590. if (typeof CSS === 'undefined' || typeof (CSS || 0).supports !== 'function' || !CSS.supports('left', 'clamp(-100%, calc( -100% * 0.5 ), 0%)')) {
  591. return console.warn("Your browser is too old.\nPlease upgrade to the latest version."); // for advanced tickering
  592. }
  593.  
  594.  
  595. // necessity of cssText3_smooth_transform_position to be checked.
  596. const cssText3_smooth_transform_position = ENABLE_NO_SMOOTH_TRANSFORM ? `
  597.  
  598. #item-offset.style-scope.yt-live-chat-item-list-renderer > #items.style-scope.yt-live-chat-item-list-renderer {
  599. position: static !important;
  600. }
  601.  
  602. `: '';
  603.  
  604. // fallback if dummy style fn fails
  605. const cssText4_smooth_transform_forced_props = ENABLE_NO_SMOOTH_TRANSFORM ? `
  606.  
  607. /* optional */
  608. #item-offset.style-scope.yt-live-chat-item-list-renderer {
  609. height: auto !important;
  610. min-height: unset !important;
  611. }
  612.  
  613. #items.style-scope.yt-live-chat-item-list-renderer {
  614. transform: translateY(0px) !important;
  615. }
  616.  
  617. /* optional */
  618.  
  619. `: '';
  620.  
  621. const cssText5 = SET_CONTAIN_FOR_CHATROOM ? `
  622.  
  623. /* ------------------------------------------------------------------------------------------------------------- */
  624.  
  625. 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 {
  626. contain: layout style;
  627. }
  628.  
  629. #items.style-scope.yt-live-chat-item-list-renderer {
  630. contain: layout paint style;
  631. }
  632.  
  633. #item-offset.style-scope.yt-live-chat-item-list-renderer {
  634. contain: style;
  635. }
  636.  
  637. #item-scroller.style-scope.yt-live-chat-item-list-renderer {
  638. contain: size style;
  639. }
  640.  
  641. #contents.style-scope.yt-live-chat-item-list-renderer, #chat.style-scope.yt-live-chat-renderer, img.style-scope.yt-img-shadow[width][height] {
  642. contain: size layout paint style;
  643. }
  644.  
  645. .style-scope.yt-live-chat-ticker-renderer[role="button"][aria-label], .style-scope.yt-live-chat-ticker-renderer[role="button"][aria-label] > #container {
  646. contain: layout paint style;
  647. }
  648.  
  649. 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 {
  650. contain: layout style;
  651. }
  652.  
  653. tp-yt-paper-tooltip[style*="inset"][role="tooltip"] {
  654. contain: layout paint style;
  655. }
  656.  
  657. /* ------------------------------------------------------------------------------------------------------------- */
  658.  
  659. ` : '';
  660.  
  661. const cssText6b_show_more_button = FIX_SHOW_MORE_BUTTON_LOCATION ? `
  662.  
  663. yt-live-chat-renderer[has-action-panel-renderer] #show-more.yt-live-chat-item-list-renderer{
  664. top: 4px;
  665. transition-property: top;
  666. bottom: unset;
  667. }
  668.  
  669. yt-live-chat-renderer[has-action-panel-renderer] #show-more.yt-live-chat-item-list-renderer[disabled]{
  670. top: -42px;
  671. }
  672.  
  673. `: '';
  674.  
  675. const cssText6c_input_panel_overflow = FIX_INPUT_PANEL_OVERFLOW_ISSUE ? `
  676.  
  677. #input-panel #picker-buttons yt-live-chat-icon-toggle-button-renderer#product-picker {
  678. contain: layout style;
  679. }
  680.  
  681. #chat.yt-live-chat-renderer ~ #panel-pages.yt-live-chat-renderer {
  682. overflow: visible;
  683. }
  684.  
  685. `: '';
  686.  
  687. const cssText6d_input_panel_border = FIX_INPUT_PANEL_BORDER_ISSUE ? `
  688.  
  689. html #panel-pages.yt-live-chat-renderer > #input-panel.yt-live-chat-renderer:not(:empty) {
  690. --yt-live-chat-action-panel-top-border: none;
  691. }
  692.  
  693. html #panel-pages.yt-live-chat-renderer > #input-panel.yt-live-chat-renderer.iron-selected > *:first-child {
  694. border-top: 1px solid var(--yt-live-chat-panel-pages-border-color);
  695. }
  696.  
  697. html #panel-pages.yt-live-chat-renderer {
  698. border-top: 0;
  699. border-bottom: 0;
  700. }
  701.  
  702. `: '';
  703.  
  704. const cssText7b_content_visibility_unset = FORCE_CONTENT_VISIBILITY_UNSET ? `
  705.  
  706. img,
  707. yt-img-shadow[height][width],
  708. yt-img-shadow {
  709. content-visibility: visible !important;
  710. }
  711.  
  712. ` : '';
  713.  
  714. const cssText7c_will_change_unset = FORCE_WILL_CHANGE_UNSET ? `
  715.  
  716. /* remove YouTube constant will-change */
  717. /* constant value will slow down the performance; default auto */
  718.  
  719. /* www-player.css */
  720. html .ytp-contextmenu,
  721. html .ytp-settings-menu {
  722. will-change: unset;
  723. }
  724.  
  725. /* frequently matched elements */
  726. html .fill.yt-interaction,
  727. html .stroke.yt-interaction,
  728. html .yt-spec-touch-feedback-shape__fill,
  729. html .yt-spec-touch-feedback-shape__stroke {
  730. will-change: unset;
  731. }
  732.  
  733. /* live_chat_polymer.js */
  734. /*
  735. html .toggle-button.tp-yt-paper-toggle-button,
  736. html #primaryProgress.tp-yt-paper-progress,
  737. html #secondaryProgress.tp-yt-paper-progress,
  738. html #onRadio.tp-yt-paper-radio-button,
  739. html .fill.yt-interaction,
  740. html .stroke.yt-interaction,
  741. html .yt-spec-touch-feedback-shape__fill,
  742. html .yt-spec-touch-feedback-shape__stroke {
  743. will-change: unset;
  744. }
  745. */
  746.  
  747. /* desktop_polymer_enable_wil_icons.js */
  748. /* html .fill.yt-interaction,
  749. html .stroke.yt-interaction, */
  750. html tp-yt-app-header::before,
  751. html tp-yt-iron-list,
  752. html #items.tp-yt-iron-list > *,
  753. html #onRadio.tp-yt-paper-radio-button,
  754. html .toggle-button.tp-yt-paper-toggle-button,
  755. html ytd-thumbnail-overlay-toggle-button-renderer[use-expandable-tooltip] #label.ytd-thumbnail-overlay-toggle-button-renderer,
  756. html #items.ytd-post-multi-image-renderer,
  757. html #items.ytd-horizontal-card-list-renderer,
  758. html #items.yt-horizontal-list-renderer,
  759. html #left-arrow.yt-horizontal-list-renderer,
  760. html #right-arrow.yt-horizontal-list-renderer,
  761. html #items.ytd-video-description-infocards-section-renderer,
  762. html #items.ytd-video-description-music-section-renderer,
  763. html #chips.ytd-feed-filter-chip-bar-renderer,
  764. html #chips.yt-chip-cloud-renderer,
  765. html #items.ytd-merch-shelf-renderer,
  766. html #items.ytd-product-details-image-carousel-renderer,
  767. html ytd-video-preview,
  768. html #player-container.ytd-video-preview,
  769. html #primaryProgress.tp-yt-paper-progress,
  770. html #secondaryProgress.tp-yt-paper-progress,
  771. html ytd-miniplayer[enabled] /* ,
  772. html .yt-spec-touch-feedback-shape__fill,
  773. html .yt-spec-touch-feedback-shape__stroke */ {
  774. will-change: unset;
  775. }
  776.  
  777. /* other */
  778. .ytp-videowall-still-info-content[class],
  779. .ytp-suggestion-image[class] {
  780. will-change: unset !important;
  781. }
  782.  
  783. ` : '';
  784.  
  785. const ENABLE_FONT_PRE_RENDERING = typeof HTMLElement_.prototype.append === 'function' ? (ENABLE_FONT_PRE_RENDERING_PREFERRED || 0) : 0;
  786. const cssText8_fonts_pre_render = ENABLE_FONT_PRE_RENDERING ? `
  787.  
  788. elzm-fonts {
  789. visibility: collapse;
  790. position: fixed;
  791. top: -10px;
  792. left: -10px;
  793. font-size: 10pt;
  794. line-height: 100%;
  795. width: 100px;
  796. height: 100px;
  797. transform: scale(0.1);
  798. transform: scale(0.01);
  799. transform: scale(0.001);
  800. transform-origin: 0 0;
  801. contain: strict;
  802. display: block;
  803.  
  804. pointer-events: none !important;
  805. user-select: none !important;
  806. }
  807.  
  808. elzm-fonts[id]#elzm-fonts-yk75g {
  809. user-select: none !important;
  810. pointer-events: none !important;
  811. }
  812.  
  813. elzm-font {
  814. visibility: collapse;
  815. position: absolute;
  816. line-height: 100%;
  817. width: 100px;
  818. height: 100px;
  819. contain: strict;
  820. display: block;
  821.  
  822. user-select: none !important;
  823. pointer-events: none !important;
  824. }
  825.  
  826. elzm-font::before {
  827. visibility: collapse;
  828. position: absolute;
  829. line-height: 100%;
  830. width: 100px;
  831. height: 100px;
  832. contain: strict;
  833. display: block;
  834.  
  835. 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';
  836.  
  837. user-select: none !important;
  838. pointer-events: none !important;
  839. }
  840.  
  841. `: '';
  842.  
  843. const cssText9_no_backdrop_filter_when_menu_shown = NO_BACKDROP_FILTER_WHEN_MENU_SHOWN ? `
  844. tp-yt-iron-dropdown.yt-live-chat-app ytd-menu-popup-renderer {
  845. -webkit-backdrop-filter: none;
  846. backdrop-filter: none;
  847. }
  848. `: '';
  849.  
  850. const cssText10_show_more_blinker = ENABLE_SHOW_MORE_BLINKER ? `
  851.  
  852. @keyframes blinker-miuzp {
  853. 0%, 60%, 100% {
  854. opacity: 1;
  855. }
  856. 30% {
  857. opacity: 0.6;
  858. }
  859. }
  860.  
  861. yt-icon-button#show-more.has-new-messages-miuzp {
  862. animation: blinker-miuzp 1.74s linear infinite;
  863. }
  864.  
  865. `: '';
  866.  
  867. const cssText11_entire_message_clickable = FIX_CLICKING_MESSAGE_MENU_DISPLAY_ON_MOUSE_CLICK ? `
  868.  
  869. yt-live-chat-paid-message-renderer.yt-live-chat-item-list-renderer[whole-message-clickable] #menu.style-scope[class] {
  870. pointer-events: none !important;
  871. }
  872.  
  873. yt-live-chat-membership-item-renderer.yt-live-chat-item-list-renderer[whole-message-clickable] #menu.style-scope[class] {
  874. pointer-events: none !important;
  875. }
  876.  
  877. yt-live-chat-paid-sticker-renderer.yt-live-chat-item-list-renderer[whole-message-clickable] #menu.style-scope[class] {
  878. pointer-events: none !important;
  879. }
  880.  
  881. yt-live-chat-text-message-renderer.yt-live-chat-item-list-renderer[whole-message-clickable] #menu.style-scope[class] {
  882. pointer-events: none !important; /* TO_BE_REVIEWED */
  883. }
  884.  
  885. yt-live-chat-auto-mod-message-renderer.yt-live-chat-item-list-renderer[whole-message-clickable] #menu.style-scope[class] {
  886. pointer-events: none !important;
  887. }
  888.  
  889. `: '';
  890.  
  891. const cssText12_nowrap_tooltip = MAX_TOOLTIP_NO_WRAP_WIDTH && typeof MAX_TOOLTIP_NO_WRAP_WIDTH === 'string' ? `
  892.  
  893.  
  894. tp-yt-paper-tooltip[role="tooltip"] {
  895. box-sizing: content-box !important;
  896. margin: 0px !important;
  897. padding: 0px !important;
  898. contain: none !important;
  899. }
  900.  
  901. tp-yt-paper-tooltip[role="tooltip"] #tooltip[style-target="tooltip"] {
  902. box-sizing: content-box !important;
  903. display: inline-block;
  904. contain: none !important;
  905. }
  906.  
  907.  
  908. tp-yt-paper-tooltip[role="tooltip"] #tooltip[style-target="tooltip"]{
  909. max-width: ${MAX_TOOLTIP_NO_WRAP_WIDTH};
  910. width: max-content;
  911. text-overflow: ellipsis;
  912. overflow: hidden;
  913. white-space: nowrap;
  914. }
  915.  
  916.  
  917. `: '';
  918.  
  919.  
  920. const cssText13_no_text_select_when_menu_visible = `
  921. [menu-visible] {
  922. --sfc47-text-select: none;
  923. }
  924. [menu-visible] #header[id][class],
  925. [menu-visible] #content[id][class],
  926. [menu-visible] #header[id][class] *,
  927. [menu-visible] #content[id][class] * {
  928. user-select: var(--sfc47-text-select) !important;
  929. }
  930. [menu-visible] #menu {
  931. --sfc47-text-select: inherit;
  932. }
  933. `;
  934.  
  935. const cssText14_NO_FILTER_DROPDOWN_BORDER = NO_FILTER_DROPDOWN_BORDER ? `
  936. yt-live-chat-header-renderer.yt-live-chat-renderer #label.yt-dropdown-menu::before {
  937. border:0;
  938. }
  939. ` : '';
  940.  
  941. const cssText15_FIX_ANIMATION_TICKER_TEXT_POSITION = FIX_ANIMATION_TICKER_TEXT_POSITION ? `
  942. .style-scope.yt-live-chat-ticker-renderer #animation-container[id][class] {
  943. position: relative;
  944. display: grid;
  945. grid-auto-columns: 1fr;
  946. grid-auto-rows: 1fr;
  947. grid-template-columns: repeat(1, 1fr);
  948. gap: 7px;
  949. padding-bottom: 0;
  950. margin-bottom: 0;
  951. padding-top: 0;
  952. align-self: flex-start;
  953. flex-wrap: nowrap;
  954. margin-top: 1px;
  955. }
  956.  
  957. .style-scope.yt-live-chat-ticker-renderer #animation-container > [id][class] {
  958. margin-top: 0px;
  959. margin-bottom: 0px;
  960. flex-direction: row;
  961. flex-wrap: nowrap;
  962. align-items: center;
  963. justify-content: flex-start;
  964. }
  965.  
  966. .style-scope.yt-live-chat-ticker-renderer #animation-container > [id][class]:first-child::after {
  967. content: '補';
  968. visibility: collapse;
  969. display: inline-block;
  970. position: relative;
  971. width: 0;
  972. line-height: 22px;
  973. }
  974.  
  975. ` : '';
  976.  
  977. const cssText16_FIX_AUTHOR_CHIP_BADGE_POSITION = FIX_AUTHOR_CHIP_BADGE_POSITION ? `
  978. #card #author-name-chip > yt-live-chat-author-chip[single-line] {
  979. flex-wrap: nowrap;
  980. white-space: nowrap;
  981. display: inline-flex;
  982. flex-direction: row;
  983. text-wrap: nowrap;
  984. flex-shrink: 0;
  985. align-items: center;
  986. }
  987.  
  988. #card #author-name-chip {
  989. display: inline-flex;
  990. flex-direction: row;
  991. align-items: flex-start;
  992. }
  993. `: '';
  994.  
  995.  
  996. // Example: https://www.youtube.com/watch?v=Xfytz-igsuc
  997. const cssText17_FIX_overwidth_banner_message = `
  998. yt-live-chat-banner-manager#live-chat-banner.style-scope.yt-live-chat-item-list-renderer {
  999. max-width: 100%;
  1000. box-sizing: border-box;
  1001. }
  1002. `;
  1003.  
  1004.  
  1005. const cssText18_REACTION_ANIMATION_PANEL_CSS_FIX = REACTION_ANIMATION_PANEL_CSS_FIX ? `
  1006. #reaction-control-panel-overlay[class] {
  1007. contain: strict;
  1008. margin: 0;
  1009. padding: 0;
  1010. border: 0;
  1011. box-sizing: border-box;
  1012. will-change: initial;
  1013. }
  1014. #reaction-control-panel-overlay[class] *[class] {
  1015. will-change: initial;
  1016. }
  1017. `: '';
  1018.  
  1019. const cssText19_FOR_ADVANCED_TICKING = USE_ADVANCED_TICKING ? `
  1020.  
  1021. ticker-bg-overlay {
  1022. display: block;
  1023. position: absolute;
  1024. z-index: -1;
  1025. box-sizing: border-box;
  1026. border: 0;
  1027. padding: 0;
  1028. margin: 0;
  1029. width: 200%;
  1030. top: 0;
  1031. bottom: 0;
  1032. left: clamp(-100%, calc( -100% * ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) ), 0%);
  1033. contain: strict;
  1034. pointer-events: none;
  1035. }
  1036. ticker-bg-overlay-end2 {
  1037.  
  1038. all:unset;
  1039. position: fixed;
  1040. display: block;
  1041. margin-left: -0.5px;
  1042. top: 8px;
  1043. left: clamp(-250px, calc( 250px * ( ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) - 1 ) ), 2px);
  1044.  
  1045. width: 1px;
  1046. height: 1px;
  1047. opacity: 0;
  1048. pointer-events: none;
  1049. box-sizing: border-box;
  1050. border: 0;
  1051. padding: 0;
  1052. margin: 0;
  1053. contain: strict;
  1054. z-index: -1;
  1055. visibility: collapse;
  1056.  
  1057.  
  1058. }
  1059.  
  1060.  
  1061. /* .r6-closing-ticker is provided in ADVANCED_TICKING */
  1062. /* so .r6-width-adjustable is only available for ADVANCED_TICKING too */
  1063.  
  1064. /* DO NOT use .r6-width-adjustable ~ .r6-width-adjustable => very laggy */
  1065.  
  1066. /*
  1067. yt-live-chat-ticker-renderer {
  1068. --r6-transition-duration: 0.2s;
  1069. }
  1070.  
  1071. .r6-width-adjustable, .yt-live-chat-ticker-stampdom {
  1072. --r6-transition-duration-v: var(--r6-transition-duration);
  1073. transition: var(--r6-transition-duration-v);
  1074. }
  1075.  
  1076. .r6-width-adjustable-f {
  1077. --r6-transition-duration-v: 0s;
  1078. }
  1079.  
  1080. .r6-closing-ticker[class] {
  1081. --r6-transition-duration-v: var(--r6-transition-duration);
  1082. }
  1083. */
  1084.  
  1085.  
  1086.  
  1087. .r6-width-adjustable {
  1088. --r6-min-width: 0;
  1089. min-width: var(--r6-min-width);
  1090. }
  1091.  
  1092. .r6-width-adjustable-f {
  1093. --r6-min-width: max-content;
  1094. }
  1095.  
  1096. .r6-closing-ticker[class] {
  1097. --r6-min-width: 0;
  1098. }
  1099.  
  1100. ` : '';
  1101.  
  1102. const cssText20_TICKER_SIZING = ENABLE_TICKERS_BOOSTED_STAMPING && DISABLE_DYNAMIC_TICKER_WIDTH ? `
  1103.  
  1104. :root {
  1105. --ticker-items-gap: 8px;
  1106. }
  1107. #ticker-items.yt-live-chat-ticker-renderer {
  1108. position: relative;
  1109. transform: translateZ(1px);
  1110. box-sizing: border-box;
  1111. contain: style;
  1112. display: flex;
  1113. flex-direction: row;
  1114. gap: var(--ticker-items-gap);
  1115. }
  1116. #container.yt-live-chat-ticker-renderer {
  1117. contain: layout paint style;
  1118. }
  1119.  
  1120. .yt-live-chat-ticker-stampdom {
  1121. position: static;
  1122. width: max-content;
  1123. content-visibility:auto;
  1124. }
  1125. .yt-live-chat-ticker-stampdom[class] {
  1126. transition: none;
  1127. }
  1128. .yt-live-chat-ticker-stampdom-container {
  1129. position: static;
  1130. width: max-content;
  1131. content-visibility:auto;
  1132. }
  1133.  
  1134. .yt-live-chat-ticker-stampdom {
  1135. margin-right:0 !important; /* flex gap 8px */
  1136. }
  1137.  
  1138. /* default animation */
  1139. .yt-live-chat-ticker-stampdom {
  1140. animation: ticker-shown-animation 220ms ease-in 0s 1 normal forwards;
  1141. }
  1142. /* default animation */
  1143. @keyframes ticker-shown-animation {
  1144. 0%, 70%, 100% { opacity: 1; }
  1145. 30% { opacity: 0.2; }
  1146. }
  1147.  
  1148.  
  1149. ` : "";
  1150. // const cssText19_FOR_ADVANCED_TICKING = `
  1151.  
  1152. // ticker-bg-overlay {
  1153. // display: block;
  1154. // position: absolute;
  1155. // z-index: -1;
  1156. // box-sizing: border-box;
  1157. // border: 0;
  1158. // padding: 0;
  1159. // margin: 0;
  1160. // width: 200%;
  1161. // top: 0;
  1162. // bottom: 0;
  1163. // left: clamp(-100%, calc( -100% * ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) ), 0%);
  1164. // contain: strict;
  1165. // }
  1166. // /*
  1167. // ticker-bg-overlay-end {
  1168. // position: absolute;
  1169. // right: 0px;
  1170. // top: 50%;
  1171. // display: block;
  1172. // width: 1px;
  1173. // height: 1px;
  1174. // opacity: 0;
  1175. // pointer-events: none;
  1176. // box-sizing: border-box;
  1177. // border: 0;
  1178. // padding: 0;
  1179. // margin: 0;
  1180. // contain: strict;
  1181. // }
  1182. // */
  1183.  
  1184. // ticker-bg-overlay-end2 {
  1185.  
  1186. // all:unset;
  1187. // position: fixed;
  1188. // display: block;
  1189. // margin-left: -0.5px;
  1190. // top: 8px;
  1191. // left: clamp(-250px, calc( 250px * ( ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) - 1 ) ), 2px);
  1192.  
  1193. // width: 1px;
  1194. // height: 1px;
  1195. // opacity: 0;
  1196. // pointer-events: none;
  1197. // box-sizing: border-box;
  1198. // border: 0;
  1199. // padding: 0;
  1200. // margin: 0;
  1201. // contain: strict;
  1202. // z-index: -1;
  1203. // visibility: collapse;
  1204.  
  1205.  
  1206. // }
  1207.  
  1208. // /* USE_ADVANCED_TICKING */
  1209.  
  1210. // /*
  1211.  
  1212. // .ticker-no-transition-time, .ticker-no-transition-time [id] {
  1213. // transition-duration: 0s !important;
  1214. // }
  1215.  
  1216. // [r6-advanced-ticking] .style-scope.yt-live-chat-ticker-renderer ~ .style-scope.yt-live-chat-ticker-renderer:not(.r6-closing-ticker) {
  1217. // transition-duration: 0s !important;
  1218. // }
  1219.  
  1220. // */
  1221.  
  1222. // .r6-width-adjustable ~ .r6-width-adjustable {
  1223. // --r6-min-width: max-content;
  1224. // }
  1225.  
  1226. // .r6-closing-ticker[class] {
  1227. // --r6-min-width: 0px;
  1228. // }
  1229.  
  1230. // .r6-width-adjustable {
  1231. // min-width: var(--r6-min-width, 0px);
  1232. // }
  1233.  
  1234.  
  1235. // /*
  1236.  
  1237.  
  1238. // .r6-width-adjustable {
  1239. // transition-duration: var(--r6-transition-duration, 0s) !important;
  1240. // }
  1241.  
  1242. // .r6-width-adjustable-first {
  1243. // --r6-transition-duration: 0.2s;
  1244. // }
  1245.  
  1246. // .r6-width-adjustable ~ .r6-width-adjustable-first {
  1247. // --r6-transition-duration: 0s;
  1248. // }
  1249.  
  1250. // .r6-closing-ticker {
  1251. // --r6-transition-duration: 0.2s;
  1252. // }
  1253. // */
  1254.  
  1255. // /*
  1256.  
  1257.  
  1258. // ey.style.position = 'absolute';
  1259. // ey.style.right = '0px';
  1260. // ey.style.top = '50%';
  1261. // ey.style.display='block';
  1262. // ey.style.width='1px';
  1263. // ey.style.height='1px';
  1264. // ey.style.opacity = '0';
  1265.  
  1266. // em.style.display = 'block';
  1267. // em.style.position = 'absolute';
  1268. // em.style.boxSizing = 'border-box';
  1269. // em.style.width = '200%';
  1270. // em.style.top = '0';
  1271. // em.style.bottom = '0';
  1272. // // em.style.height = '100%';
  1273.  
  1274.  
  1275. // // em.style.left = '-50%';
  1276. // // em.style.left = "clamp(-100%, calc( -100% * ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) ), 0%)";
  1277.  
  1278. // */
  1279.  
  1280. // `;
  1281.  
  1282. const addCss = () => `
  1283.  
  1284. yt-live-chat-renderer {
  1285. max-height: 100vh;
  1286. }
  1287.  
  1288. @property --ticker-rtime {
  1289. syntax: "<percentage>";
  1290. inherits: false;
  1291. initial-value: 0%;
  1292. }
  1293.  
  1294. .run-ticker {
  1295. --ticker-bg:linear-gradient(90deg, var(--ticker-c1),var(--ticker-c1) var(--ticker-rtime),var(--ticker-c2) var(--ticker-rtime),var(--ticker-c2));
  1296. }
  1297.  
  1298. .run-ticker,
  1299. yt-live-chat-ticker-renderer #items > * > #container.run-ticker,
  1300. yt-live-chat-ticker-renderer[class] #items[class] > *[class] > #container.run-ticker[class]
  1301. {
  1302. background: var(--ticker-bg) !important;
  1303. }
  1304.  
  1305. yt-live-chat-ticker-dummy777-item-renderer {
  1306. background: #00000001;
  1307. }
  1308.  
  1309. yt-live-chat-ticker-dummy777-item-renderer[dummy777] {
  1310. position: fixed !important;
  1311. top: -1000px !important;
  1312. left: -1000px !important;
  1313. font-size: 1px !important;
  1314. color: transparent !important;
  1315. pointer-events: none !important;
  1316. z-index: -1 !important;
  1317. contain: strict !important;
  1318. box-sizing: border-box !important;
  1319. pointer-events: none !important;
  1320. user-select: none !important;
  1321. max-width: 1px !important;
  1322. max-height: 1px !important;
  1323. overflow: hidden !important;
  1324. visibility: collapse !important;
  1325. display: none !important;
  1326. }
  1327.  
  1328. yt-live-chat-ticker-dummy777-item-renderer #container {
  1329. background: inherit;
  1330. }
  1331.  
  1332.  
  1333. ${cssText8_fonts_pre_render}
  1334.  
  1335. ${cssText9_no_backdrop_filter_when_menu_shown}
  1336.  
  1337. @supports (contain: layout paint style) {
  1338.  
  1339. ${cssText5}
  1340.  
  1341. }
  1342.  
  1343. @supports (color: var(--general)) {
  1344.  
  1345. html {
  1346. --yt-live-chat-item-list-renderer-padding: 0px 0px;
  1347. }
  1348.  
  1349. ${cssText3_smooth_transform_position}
  1350.  
  1351. ${cssText7c_will_change_unset}
  1352.  
  1353. ${cssText7b_content_visibility_unset}
  1354.  
  1355. yt-live-chat-item-list-renderer:not([allow-scroll]) #item-scroller.yt-live-chat-item-list-renderer {
  1356. overflow-y: scroll;
  1357. padding-right: 0;
  1358. }
  1359.  
  1360. ${cssText4_smooth_transform_forced_props}
  1361.  
  1362. yt-icon[icon="down_arrow"] > *, yt-icon-button#show-more > * {
  1363. pointer-events: none !important;
  1364. }
  1365.  
  1366. #continuations, #continuations * {
  1367. contain: strict;
  1368. position: fixed;
  1369. top: 2px;
  1370. height: 1px;
  1371. width: 2px;
  1372. height: 1px;
  1373. visibility: collapse;
  1374. }
  1375.  
  1376. ${cssText6b_show_more_button}
  1377.  
  1378. ${cssText6d_input_panel_border}
  1379.  
  1380. ${cssText6c_input_panel_overflow}
  1381.  
  1382. }
  1383.  
  1384.  
  1385. @supports (overflow-anchor: auto) {
  1386.  
  1387. .no-anchor * {
  1388. overflow-anchor: none;
  1389. }
  1390. .no-anchor > item-anchor {
  1391. overflow-anchor: auto;
  1392. }
  1393. #item-scroller.style-scope.yt-live-chat-item-list-renderer[class] {
  1394. overflow-anchor: initial !important; /* whenever ENABLE_OVERFLOW_ANCHOR or not */
  1395. }
  1396. }
  1397.  
  1398. item-anchor {
  1399.  
  1400. height: 1px;
  1401. width: 100%;
  1402. transform: scaleY(0.00001);
  1403. transform-origin:0 0;
  1404. contain: strict;
  1405. opacity:0;
  1406. display:flex;
  1407. position:relative;
  1408. flex-shrink:0;
  1409. flex-grow:0;
  1410. margin-bottom:0;
  1411. overflow:hidden;
  1412. box-sizing:border-box;
  1413. visibility: visible;
  1414. content-visibility: visible;
  1415. contain-intrinsic-size: auto 1px;
  1416. pointer-events:none !important;
  1417.  
  1418. }
  1419.  
  1420. html item-anchor {
  1421.  
  1422. height: 1px;
  1423. width: 1px;
  1424. top: auto;
  1425. left: auto;
  1426. right: auto;
  1427. bottom: auto;
  1428. transform: translateY(-1px);
  1429. position: absolute;
  1430. z-index: -1;
  1431.  
  1432. }
  1433.  
  1434. @supports (color: var(--pre-rendering)) {
  1435.  
  1436. @keyframes dontRenderAnimation {
  1437. 0% {
  1438. background-position-x: 3px;
  1439. }
  1440. 100% {
  1441. background-position-x: 4px;
  1442. }
  1443. }
  1444.  
  1445. .dont-render[class] {
  1446. /* visibility: collapse !important; */
  1447. /* visibility: collapse will make innerText become "" which conflicts with BetterStreamChat; see https://greatest.deepsurf.us/scripts/469878/discussions/197267 */
  1448.  
  1449. transform: scale(0.01) !important;
  1450. transform: scale(0.00001) !important;
  1451. transform: scale(0.0000001) !important;
  1452. transform-origin: 0 0 !important;
  1453. z-index: -1 !important;
  1454. contain: strict !important;
  1455. box-sizing: border-box !important;
  1456.  
  1457. height: 1px !important;
  1458. height: 0.1px !important;
  1459. height: 0.01px !important;
  1460. height: 0.0001px !important;
  1461. height: 0.000001px !important;
  1462.  
  1463. animation: dontRenderAnimation 1ms linear 80ms 1 normal forwards !important;
  1464.  
  1465. pointer-events: none !important;
  1466. user-select: none !important;
  1467.  
  1468. }
  1469.  
  1470. #sk35z {
  1471. display: block !important;
  1472.  
  1473. visibility: collapse !important;
  1474.  
  1475. transform: scale(0.01) !important;
  1476. transform: scale(0.00001) !important;
  1477. transform: scale(0.0000001) !important;
  1478. transform-origin: 0 0 !important;
  1479. z-index: -1 !important;
  1480. contain: strict !important;
  1481. box-sizing: border-box !important;
  1482.  
  1483. height: 1px !important;
  1484. height: 0.1px !important;
  1485. height: 0.01px !important;
  1486. height: 0.0001px !important;
  1487. height: 0.000001px !important;
  1488.  
  1489. position: absolute !important;
  1490. top: -1000px !important;
  1491. left: -1000px !important;
  1492.  
  1493. }
  1494.  
  1495. }
  1496.  
  1497. [rNgzQ] {
  1498. opacity: 0 !important;
  1499. pointer-events: none !important;
  1500. }
  1501.  
  1502.  
  1503. ${cssText10_show_more_blinker}
  1504.  
  1505. ${cssText11_entire_message_clickable}
  1506.  
  1507. ${cssText12_nowrap_tooltip}
  1508.  
  1509. ${cssText13_no_text_select_when_menu_visible}
  1510.  
  1511. ${cssText14_NO_FILTER_DROPDOWN_BORDER}
  1512.  
  1513. ${cssText15_FIX_ANIMATION_TICKER_TEXT_POSITION}
  1514.  
  1515. ${cssText16_FIX_AUTHOR_CHIP_BADGE_POSITION}
  1516.  
  1517. ${cssText17_FIX_overwidth_banner_message}
  1518.  
  1519. ${cssText18_REACTION_ANIMATION_PANEL_CSS_FIX}
  1520.  
  1521. ${cssText19_FOR_ADVANCED_TICKING}
  1522.  
  1523. ${cssText20_TICKER_SIZING}
  1524.  
  1525. `;
  1526.  
  1527. const win = typeof unsafeWindow !== 'undefined' ? unsafeWindow : (this instanceof Window ? this : window);
  1528.  
  1529. // Create a unique key for the script and check if it is already running
  1530. const hkey_script = 'mchbwnoasqph';
  1531. if (win[hkey_script]) throw new Error('Duplicated Userscript Calling'); // avoid duplicated scripting
  1532. win[hkey_script] = true;
  1533.  
  1534. const setTimeoutX0 = setTimeout;
  1535. const clearTimeoutX0 = clearTimeout;
  1536. const setIntervalX0 = setInterval;
  1537. const clearIntervalX0 = clearInterval;
  1538.  
  1539. const __shady_native_appendChild = HTMLElement_.prototype.__shady_native_appendChild || HTMLElement_.prototype.appendChild;
  1540. const __shady_native_removeChild = HTMLElement_.prototype.__shady_native_removeChild || HTMLElement_.prototype.removeChild;
  1541.  
  1542. const isEmptyObject = (obj) => {
  1543. for (const key in obj) {
  1544. if (obj.hasOwnProperty(key)) return false;
  1545. }
  1546. return true;
  1547. }
  1548.  
  1549. const firstObjectKey = (obj) => {
  1550. for (const key in obj) {
  1551. if (obj.hasOwnProperty(key) && typeof obj[key] === 'object') return key;
  1552. }
  1553. return null;
  1554. }
  1555.  
  1556.  
  1557. class LimitedSizeSet extends Set {
  1558. constructor(n) {
  1559. super();
  1560. this.limit = n;
  1561. }
  1562.  
  1563. add(key) {
  1564. if (!super.has(key)) {
  1565. super.add(key);
  1566. let n = super.size - this.limit;
  1567. if (n > 0) {
  1568. const iterator = super.values();
  1569. do {
  1570. const firstKey = iterator.next().value; // Get the first (oldest) key
  1571. super.delete(firstKey); // Delete the oldest key
  1572. } while (--n > 0)
  1573. }
  1574. }
  1575. }
  1576.  
  1577. removeAdd(key) {
  1578. super.delete(key);
  1579. this.add(key);
  1580. }
  1581.  
  1582. }
  1583.  
  1584.  
  1585. function deepCopy(obj, skipKeys) {
  1586. skipKeys = skipKeys || [];
  1587. if (!obj || typeof obj !== 'object') return obj;
  1588. if (Array.isArray(obj)) {
  1589. return obj.map(item => deepCopy(item, skipKeys));
  1590. }
  1591. const copy = {};
  1592. for (let key in obj) {
  1593. if (!skipKeys.includes(key)) {
  1594. copy[key] = deepCopy(obj[key], skipKeys);
  1595. }
  1596. }
  1597. return copy;
  1598. }
  1599.  
  1600. class Mutex {
  1601.  
  1602. constructor() {
  1603. this.p = Promise.resolve()
  1604. }
  1605.  
  1606. /**
  1607. * @param {(lockResolve: () => void)} f
  1608. */
  1609. lockWith(f) {
  1610. this.p = this.p.then(() => new Promise(f).catch(console.warn))
  1611. }
  1612.  
  1613. }
  1614.  
  1615. const PromiseExternal = ((resolve_, reject_) => {
  1616. const h = (resolve, reject) => { resolve_ = resolve; reject_ = reject };
  1617. return class PromiseExternal extends Promise {
  1618. constructor(cb = h) {
  1619. super(cb);
  1620. if (cb === h) {
  1621. /** @type {(value: any) => void} */
  1622. this.resolve = resolve_;
  1623. /** @type {(reason?: any) => void} */
  1624. this.reject = reject_;
  1625. }
  1626. }
  1627. };
  1628. })();
  1629.  
  1630. let ttpHTML = (s) => {
  1631. ttpHTML = s => s;
  1632. if (typeof trustedTypes !== 'undefined' && trustedTypes.defaultPolicy === null) {
  1633. let s = s => s;
  1634. trustedTypes.createPolicy('default', { createHTML: s, createScriptURL: s, createScript: s });
  1635. }
  1636. return s;
  1637. }
  1638.  
  1639. // const nextBrowserTick_ = nextBrowserTick;
  1640. // const nextBrowserTick_ = (f) => {
  1641. // typeof nextBrowserTick === 'function' ? nextBrowserTick(f) : setTimeout(f, Number.MIN_VALUE);
  1642. // };
  1643.  
  1644.  
  1645. // const { accurateTiming, isAccurateTimingUsable } = (() => {
  1646. // let audioCtx_ = null;
  1647. // let sampleRate = 0;
  1648. // const isAccurateTimingUsable = () => sampleRate > 0;
  1649. // const kill = () => {
  1650. // sampleRate = audioCtx_.currentTime;
  1651. // document.removeEventListener('pointerdown', listener, { capture: true, passive: true });
  1652. // document.removeEventListener('keydown', listener, { capture: true, passive: true });
  1653. // };
  1654. // const listener = (e) => {
  1655. // if (e.isTrusted === true) {
  1656. // if (!audioCtx_) {
  1657. // audioCtx_ = new (window.AudioContext || window.webkitAudioContext)();
  1658. // }
  1659. // if (audioCtx_.state === 'suspended') {
  1660. // const p = audioCtx_.resume();
  1661. // if (p && typeof p.then === 'function') p.then(kill);
  1662. // } else if (audioCtx_.state === 'running') {
  1663. // kill();
  1664. // }
  1665. // }
  1666. // };
  1667. // document.addEventListener('pointerdown', listener, { capture: true, passive: true });
  1668. // document.addEventListener('keydown', listener, { capture: true, passive: true });
  1669. // const fnSym = Symbol()
  1670. // const commonOscClean = (osc) => {
  1671. // osc[fnSym] = osc.onended = null;
  1672. // }
  1673. // const commonOscOnEnded = function () {
  1674. // this[fnSym]()
  1675. // Promise.resolve(this).then(commonOscClean)
  1676. // }
  1677. // let buffer_;
  1678. // const accurateTiming = (fn, delay) => {
  1679. // if (!sampleRate) return false;
  1680. // const audioCtx = audioCtx_;
  1681. // const ct = audioCtx.currentTime;
  1682.  
  1683. // if (!(delay >= 0)) delay = 0;
  1684. // const stopTime = ct + delay;
  1685. // let startTime = ct + delay - (1 / sampleRate);
  1686. // if (startTime === stopTime) startTime -= 1;
  1687. // if (startTime < 0) startTime = 0;
  1688.  
  1689. // if (!buffer_) {
  1690. // buffer_ = audioCtx.createBuffer(1, 1, sampleRate);
  1691. // // const data = buffer.getChannelData(0)
  1692. // // data[0] = 1e-20 // tiny pulse – not silent!
  1693. // }
  1694.  
  1695. // const buffer = buffer_;
  1696. // const source = audioCtx.createBufferSource()
  1697. // source.buffer = buffer
  1698. // source.connect(audioCtx.destination) // or silent gain node
  1699.  
  1700. // source[fnSym] = fn
  1701. // source.onended = commonOscOnEnded
  1702. // source.start(startTime) // schedule start
  1703.  
  1704. // return true;
  1705. // }
  1706. // return { accurateTiming, isAccurateTimingUsable }
  1707. // })();
  1708.  
  1709.  
  1710.  
  1711. let qWidthAdjustable = null;
  1712.  
  1713. /** @type {typeof PromiseExternal.prototype | null} */
  1714. let relayPromise = null;
  1715.  
  1716.  
  1717. /** @type {typeof PromiseExternal.prototype | null} */
  1718. let onPlayStateChangePromise = null;
  1719.  
  1720.  
  1721. const reuseId = `${Math.floor(Math.random() * 314159265359 + 314159265359).toString(36)}`;
  1722.  
  1723. const reuseStore = new Map();
  1724.  
  1725. let onPageContainer = null;
  1726.  
  1727. const customCreateComponent = (component, data, bool)=>{
  1728.  
  1729. const componentTag = typeof component === 'string' ? component : typeof (component||0).component === 'string' ? (component||0).component : '';
  1730. if(componentTag){
  1731.  
  1732. if(REUSE_TICKER && data.id && data.fullDurationSec){
  1733. // bool (param c) is true by default; just force it to reuse no matter true or false
  1734.  
  1735. if (!bool) {
  1736. // show a warning if it is false.
  1737. console.warn('[yt-chat] REUSE_TICKER: reuse bool is false');
  1738. }
  1739.  
  1740. const record = reuseStore.get(`<${componentTag}>${data.id}:${data.fullDurationSec}`);
  1741.  
  1742. const cnt = kRef(record);
  1743.  
  1744.  
  1745. if(cnt && cnt.isAttached === false){
  1746.  
  1747. const hostElement = cnt.hostElement;
  1748.  
  1749. if(hostElement instanceof HTMLElement_ && hostElement.isConnected === false && hostElement.parentNode === null && hostElement.getAttribute('__reuseid__')===reuseId ){
  1750.  
  1751. // console.log(952, cnt.hostElement.parentNode)
  1752. // debugger;
  1753. if (hostElement.hasAttribute('__nogc__')) {
  1754.  
  1755. Promise.resolve(hostElement).then((hostElement) => {
  1756. // microtask to provide some time for DOM attachment.
  1757. hostElement.isConnected && hostElement.removeAttribute('__nogc__');
  1758. });
  1759.  
  1760. }
  1761.  
  1762. // ------- follow rm3 -------
  1763.  
  1764. // a.prototype._initializeProtoProperties = function(c) {
  1765. // this.__data = Object.create(c);
  1766. // this.__dataPending = Object.create(c);
  1767. // this.__dataOld = {}
  1768. // }
  1769. // a.prototype._initializeProperties = function() {
  1770. // this.__dataProto && (this._initializeProtoProperties(this.__dataProto),
  1771. // this.__dataProto = null);
  1772. // b.prototype._initializeProperties.call(this)
  1773. // }
  1774. // ;
  1775.  
  1776. if(!cnt.__dataInvalid && cnt.__dataEnabled && cnt.__dataReady ){
  1777.  
  1778. // console.log(12883);
  1779.  
  1780.  
  1781. if (!onPageContainer) {
  1782. let p = document.createElement('noscript');
  1783. p.style.all = 'unset';
  1784. document.body.prepend(p);
  1785. onPageContainer = p;
  1786. }
  1787.  
  1788. onPageContainer.appendChild(hostElement); // to fix some issues for the rendered elements
  1789.  
  1790. cnt.__dataInvalid = false;
  1791. cnt.__dataEnabled = true;
  1792. cnt.__dataReady = true;
  1793. // cnt._initializeProtoProperties(cnt.data)
  1794.  
  1795. // window.meaa = cnt.$.container;
  1796. if (cnt.__data) cnt.__data = Object.assign({}, cnt.__data);
  1797. cnt.__dataPending = {};
  1798. cnt.__dataOld = {}
  1799.  
  1800. try{
  1801. cnt.markDirty();
  1802. }catch(e){}
  1803. try{
  1804. cnt.markDirtyVisibilityObserver();
  1805. }catch(e){}
  1806. try{
  1807. cnt.wasPrescan = cnt.wasVisible = !1
  1808. }catch(e){}
  1809. // try{
  1810. // cnt._setPendingProperty('data', Object.assign({}, cntData), !0);
  1811. // }catch(e){}
  1812. // // cnt.__dataInvalid = false;
  1813. // // cnt._enableProperties();
  1814.  
  1815. // try {
  1816. // cnt._flushProperties();
  1817. // } catch (e) { }
  1818. // cnt.ready();
  1819.  
  1820. return hostElement;
  1821.  
  1822. }
  1823.  
  1824.  
  1825. // console.log(12323)
  1826.  
  1827. // setTimeoutX0(()=>{
  1828. // console.log(window.meaa.parentNode)
  1829. // }, 1000)
  1830.  
  1831.  
  1832. // ------------ commented ------------
  1833. // cnt.__dataInvalid = false;
  1834. // cnt.__dataEnabled = false;
  1835. // if (cnt.__dataPending && typeof cnt.__dataPending === 'object') cnt.__dataPending = null;
  1836. // if (cnt.__dataOld && typeof cnt.__dataOld === 'object') cnt.__dataOld = null;
  1837. // if (cnt.__dataCounter && typeof cnt.__dataCounter === 'number') cnt.__dataCounter = 0;
  1838. // if ('__dataClientsInitialized' in cnt || '__dataClientsReady' in cnt) {
  1839. // cnt.__dataClientsReady = !1;
  1840. // cnt.__dataLinkedPaths = cnt.__dataToNotify = cnt.__dataPendingClients = null;
  1841. // cnt.__dataHasPaths = !1;
  1842. // cnt.__dataCompoundStorage = null; // cnt.__dataCompoundStorage = cnt.__dataCompoundStorage || null;
  1843. // cnt.__dataHost = null; // cnt.__dataHost = cnt.__dataHost || null;
  1844. // if (!cnt.__dataTemp) cnt.__dataTemp = {}; // cnt.__dataTemp = {};
  1845. // cnt.__dataClientsInitialized = !1;
  1846. // }
  1847. // try{
  1848. // cnt._flushProperties();
  1849. // }catch(e){
  1850. // console.warn(e)
  1851. // }
  1852. // for (const elm of cnt.hostElement.getElementsByTagName('*')) {
  1853. // if (elm.is) {
  1854. // const cnt = insp(elm);
  1855. // cnt.__dataInvalid = false;
  1856. // cnt.__dataEnabled = false;
  1857. // if (cnt.__dataPending && typeof cnt.__dataPending === 'object') cnt.__dataPending = null;
  1858. // if (cnt.__dataOld && typeof cnt.__dataOld === 'object') cnt.__dataOld = null;
  1859. // if (cnt.__dataCounter && typeof cnt.__dataCounter === 'number') cnt.__dataCounter = 0;
  1860. // if ('__dataClientsInitialized' in cnt || '__dataClientsReady' in cnt) {
  1861. // cnt.__dataClientsReady = !1;
  1862. // cnt.__dataLinkedPaths = cnt.__dataToNotify = cnt.__dataPendingClients = null;
  1863. // cnt.__dataHasPaths = !1;
  1864. // cnt.__dataCompoundStorage = null; // cnt.__dataCompoundStorage = cnt.__dataCompoundStorage || null;
  1865. // cnt.__dataHost = null; // cnt.__dataHost = cnt.__dataHost || null;
  1866. // if (!cnt.__dataTemp) cnt.__dataTemp = {}; // cnt.__dataTemp = {};
  1867. // cnt.__dataClientsInitialized = !1;
  1868. // }
  1869. // try {
  1870. // cnt._flushProperties();
  1871. // } catch (e) {
  1872. // console.warn(e)
  1873. // }
  1874. // if (elm.nodeName === 'YT-ICON') {
  1875. // // console.log(2133, JSON.stringify( cnt.__data))
  1876. // const qq = Object.assign({}, cnt.__data)
  1877. // console.log(1232466)
  1878. // const _qww = cnt;
  1879. // cnt.__data = new Proxy(Object.assign({}, qq), {
  1880. // get(target, p) {
  1881. // console.log(12838, p)
  1882. // if (p === 'icon') {
  1883. // window.wmk = _qww.hostElement;
  1884. // // debugger;
  1885. // }
  1886. // return target[p]
  1887. // },
  1888. // set(target, p, v) {
  1889. // console.log(12839, p)
  1890. // target[p] = v;
  1891. // if (p === 'icon') debugger;
  1892. // return true;
  1893. // }
  1894. // });
  1895. // Promise.resolve(cnt).then((cnt) => {
  1896. // cnt.__data = Object.assign({}, qq);
  1897. // });
  1898. // }
  1899. // // let q = elm.nextSibling;
  1900. // // let h = elm.parentNode;
  1901. // // elm.remove();
  1902. // // h.insertBefore(elm, q);
  1903. // // console.log(2233, elm)
  1904. // }
  1905. // }
  1906. // ------------ commented ------------
  1907.  
  1908. // ------- follow rm3 -------
  1909.  
  1910. // console.log('[yt-chat] reuse')
  1911.  
  1912.  
  1913.  
  1914. }
  1915.  
  1916. }
  1917.  
  1918. }
  1919.  
  1920. }
  1921. DEBUG_customCreateComponent && console.log(component, data, bool);
  1922. /*
  1923.  
  1924. const cntData = this.data;
  1925. reuseStore.set(`${cntData.id}:${cntData.fullDurationSec}`, mWeakRef(this));
  1926. */
  1927.  
  1928. }
  1929.  
  1930. const valAssign = (elm, attr, val) => {
  1931. if (typeof val === 'number') val = val.toFixed(3);
  1932. if (!(Math.abs(elm.style.getPropertyValue(attr) - val) < 1e-5)) {
  1933. elm.style.setProperty(attr, val);
  1934. return true;
  1935. }
  1936. return false;
  1937. };
  1938.  
  1939. const insp = o => o ? (o.polymerController || o.inst || o || 0) : (o || 0);
  1940. const indr = o => insp(o).$ || o.$ || 0;
  1941.  
  1942.  
  1943. const getAttributes = (node) => {
  1944. const attrs = node.attributes;
  1945. const res = {};
  1946. for (const { name, value } of attrs) {
  1947. res[name] = value;
  1948. }
  1949. res['"'] = attrs.length;
  1950. // const res = new Array(attrs.length);
  1951. // for (let i = 0; i < res.length; i++) {
  1952. // const { name, value } = attrs[i];
  1953. // res[i] = { name, value };
  1954. // }
  1955. return res;
  1956. };
  1957.  
  1958. const __refreshData938o__ = {};
  1959. const __refreshData938__ = function (prop, opt) {
  1960. const d = this[prop];
  1961. if (d) {
  1962. this._setPendingProperty(prop, __refreshData938o__, opt);
  1963. this._setPendingProperty(prop, d, opt);
  1964. this._invalidateProperties();
  1965. }
  1966. };
  1967.  
  1968. const __refreshData933__ = function (prop, opt) {
  1969. const d = this[prop];
  1970. if (d) {
  1971. this.signalProxy.setWithPath([prop], d);
  1972. }
  1973. }
  1974.  
  1975. const setupRefreshData930 = (cnt) => {
  1976. if (cnt.__refreshData930__ !== undefined) return;
  1977. const cProto = Reflect.getPrototypeOf(cnt);
  1978. let r = null;
  1979. let flag = 0;
  1980. if (typeof cnt._setPendingProperty === 'function' && typeof cnt._invalidateProperties === 'function' && cnt._setPendingProperty.length === 3 && cnt._invalidateProperties.length === 0) {
  1981. flag |= 1;
  1982. }
  1983. if (typeof cnt.signalProxy !== "undefined") {
  1984. flag |= 2;
  1985. }
  1986. if (typeof (cnt.signalProxy || 0).setWithPath === 'function' && cnt.signalProxy.setWithPath.length === 2) {
  1987. flag |= 4;
  1988. }
  1989. if (r === 1) r = __refreshData938__;
  1990. // else if (r === 6) r = __refreshData933__;
  1991. cProto.__refreshData930__ = r;
  1992. // ytd-comments-header-renderer : no _invalidateProperties (cnt.signalProxy.setWithPath)
  1993. }
  1994.  
  1995. const __refreshProps938__ = function () {
  1996. const __data = this.__data;
  1997. if (__data) {
  1998. for (const key in __data) {
  1999. const v = __data[key];
  2000. if (typeof v === 'boolean') {
  2001. this._setPendingProperty(key, !v) && this._setPendingProperty(key, v);
  2002. } else if (typeof v === 'string') {
  2003. this._setPendingProperty(key, `!${v}`) && this._setPendingProperty(key, `${v}`);
  2004. } else if (typeof v === 'number') {
  2005. this._setPendingProperty(key, v + 1) && this._setPendingProperty(key, v);
  2006. }
  2007. }
  2008. }
  2009. }
  2010.  
  2011. const setupRefreshProps930 = (cnt) => {
  2012. if (cnt.__refreshProps930__ !== undefined) return;
  2013. const cProto = Reflect.getPrototypeOf(cnt);
  2014. let r = null;
  2015. let flag = 0;
  2016. if (typeof cnt._setPendingProperty === 'function' && typeof cnt._invalidateProperties === 'function' && cnt._setPendingProperty.length === 3 && cnt._invalidateProperties.length === 0) {
  2017. flag |= 1;
  2018. }
  2019. if (typeof cnt.signalProxy !== "undefined") {
  2020. flag |= 2;
  2021. }
  2022. if (typeof (cnt.signalProxy || 0).setWithPath === 'function' && cnt.signalProxy.setWithPath.length === 2) {
  2023. flag |= 4;
  2024. }
  2025. if (r === 1) r = __refreshProps938__;
  2026. cProto.__refreshProps930__ = r;
  2027. // ytd-comments-header-renderer : no _invalidateProperties (cnt.signalProxy.setWithPath)
  2028. }
  2029.  
  2030. const refreshChildrenYtIcons = (node) => {
  2031. let goNext = false;
  2032. for (const iconElm of node.getElementsByTagName('yt-icon')) {
  2033. try {
  2034. const cnt = insp(iconElm);
  2035. setupRefreshProps930(cnt);
  2036. if (cnt.__refreshProps930__) {
  2037. cnt.__refreshProps930__();
  2038. goNext = true;
  2039. }
  2040. // cnt.removeIconShape(); // detach iconShapeDataSignal?
  2041. // cnt._setPendingProperty('isAttached', false);
  2042. } catch (e) { }
  2043. if (!goNext) break;
  2044. }
  2045. }
  2046.  
  2047.  
  2048. const imageFetchCache = new Set();
  2049. const imageFetch = function (imageLink) {
  2050. return new Promise(resolve => {
  2051. let img = null;
  2052. for (const cacheWR of imageFetchCache) {
  2053. let p = kRef(cacheWR);
  2054. if (!p) {
  2055. imageFetchCache.delete(cacheWR);
  2056. } else if (img.busy588 === false) {
  2057. img = p;
  2058. break;
  2059. }
  2060. }
  2061. if (!img) {
  2062. img = new Image_();
  2063. imageFetchCache.add(mWeakRef(img));
  2064. }
  2065. img.busy588 = true;
  2066.  
  2067. window.mkek = imageFetchCache.size;
  2068. let f = () => {
  2069. resolve && resolve();
  2070. resolve = null;
  2071. img.onload = null;
  2072. img.onerror = null;
  2073. img.busy588 = false;
  2074. img = null;
  2075. }
  2076. img.onload = f;
  2077. img.onerror = f;
  2078. img.src = imageLink;
  2079. f = null;
  2080. imageLink = null;
  2081. });
  2082. };
  2083.  
  2084.  
  2085. const autoTimerFn = (() => {
  2086.  
  2087. let p1 = null;
  2088. let p2 = null;
  2089. let p3 = null;
  2090. setInterval(() => {
  2091. if (p1) p1.resolve();
  2092. p1 = p2;
  2093. p2 = p3;
  2094. p3 = null;
  2095. }, 345.00123);
  2096.  
  2097. return () => {
  2098. const p = (p3 || (p3 = new PromiseExternal()));
  2099. return p;
  2100. };
  2101.  
  2102. })();
  2103.  
  2104. const wme = document.createComment('1');
  2105. let wmp = new PromiseExternal();
  2106. const wmo = new MutationObserver(() => {
  2107. wmp.resolve();
  2108. wmp = new PromiseExternal();
  2109. });
  2110. wmo.observe(wme, { characterData: true });
  2111.  
  2112.  
  2113. let playEventsStack = Promise.resolve();
  2114.  
  2115.  
  2116. let playerProgressChangedArg1 = null;
  2117. let playerProgressChangedArg2 = null;
  2118. let playerProgressChangedArg3 = null;
  2119.  
  2120. let dntElementWeak = null;
  2121.  
  2122.  
  2123. let timestampUnderLiveMode = false;
  2124.  
  2125. const updateTickerCurrentTime = () => {
  2126.  
  2127. if (resistanceUpdateDebugMode) {
  2128. console.log('updateTickerCurrentTime')
  2129.  
  2130. if (!dntElementWeak || !kRef(dntElementWeak)) dntElementWeak = mWeakRef(document.querySelector('yt-live-chat-ticker-renderer'));
  2131. timestampUnderLiveMode = true;
  2132. }
  2133.  
  2134. const dntElement = kRef(dntElementWeak);
  2135. const v = timestampUnderLiveMode ? (Date.now() / 1000 - timeOriginDT / 1000) : playerProgressChangedArg1;
  2136. if (dntElement instanceof HTMLElement_ && v >= 0) {
  2137. valAssign(dntElement, '--ticker-current-time', v);
  2138. }
  2139. }
  2140.  
  2141. // ================== FOR USE_ADVANCED_TICKING ================
  2142.  
  2143. const timeOriginDT = +new Date(performance.timeOrigin);
  2144. let startResistanceUpdaterStarted = false;
  2145.  
  2146. const RESISTANCE_UPDATE_OPT = 3;
  2147. let resistanceUpdateLast = 0;
  2148. let resistanceUpdateBusy = false;
  2149. const resistanceUpdateDebugMode = false;
  2150. const allBackgroundOverLays = document.getElementsByTagName('ticker-bg-overlay');
  2151. // const rgFlag = {};
  2152. const resistanceUpdateFn = (b) => {
  2153. if (!resistanceUpdateDebugMode && allBackgroundOverLays.length === 0) return;
  2154. resistanceUpdateBusy = false;
  2155. const t = Date.now();
  2156. const d = t - resistanceUpdateLast;
  2157. if (d > 375) {
  2158. resistanceUpdateLast = t;
  2159. updateTickerCurrentTime();
  2160. }
  2161. }
  2162. const resistanceUpdateFn_ = (forced = false) => {
  2163. if (forced === true || timestampUnderLiveMode) {
  2164. if (!resistanceUpdateBusy) {
  2165. resistanceUpdateBusy = true;
  2166. Promise.resolve().then(resistanceUpdateFn);
  2167. }
  2168. }
  2169. }
  2170. const startResistanceUpdater = () => {
  2171.  
  2172. if (startResistanceUpdaterStarted) return;
  2173. startResistanceUpdaterStarted = true;
  2174.  
  2175. if (RESISTANCE_UPDATE_OPT & 1)
  2176. document.addEventListener('yt-action', () => {
  2177. resistanceUpdateFn_(true);
  2178. }, true)
  2179.  
  2180. resistanceUpdateFn_(true);
  2181. setIntervalX0(resistanceUpdateFn_, 400);
  2182. }
  2183.  
  2184. if(resistanceUpdateDebugMode) startResistanceUpdater();
  2185.  
  2186.  
  2187. function dr(s) {
  2188. // reserved for future use
  2189. return s;
  2190. // return window.deWeakJS ? window.deWeakJS(s) : s;
  2191. }
  2192.  
  2193.  
  2194. const getProto = (element) => {
  2195. if (element) {
  2196. const cnt = insp(element);
  2197. return cnt.constructor.prototype || null;
  2198. }
  2199. return null;
  2200. }
  2201.  
  2202.  
  2203.  
  2204. const logFn = (key, f) => {
  2205. return Function.prototype.bind.call(console.log, console, `%c ${key}`, 'background: #222; color: #bada55', f);
  2206. }
  2207.  
  2208.  
  2209.  
  2210. const assertor = (f) => f() || (console.assert(false, `${f}`), false);
  2211.  
  2212. const fnIntegrity = (f, d) => {
  2213.  
  2214.  
  2215. if (!f || typeof f !== 'function') {
  2216. console.warn('f is not a function', f);
  2217. return;
  2218. }
  2219. // return; // M44
  2220. let p = `${f}`, s = 0, j = -1, w = 0;
  2221. // return; // M44
  2222. for (let i = 0, l = p.length; i < l; i++) {
  2223. const t = p[i];
  2224. if (((t >= 'a' && t <= 'z') || (t >= 'A' && t <= 'Z'))) {
  2225. if (j < i - 1) w++;
  2226. j = i;
  2227. } else {
  2228. s++;
  2229. }
  2230. }
  2231. // if(p.length > 44 && p.length < 50){
  2232.  
  2233. // (window.skam|| (window.skam=[])).push(p);
  2234. // return false;
  2235. // }
  2236.  
  2237. // if(p.length > 405 && p.length < 415 ){ //350 450
  2238.  
  2239.  
  2240. // //  [353, 411, 411, 411]
  2241.  
  2242. // // if(p.length >= 350 && p.length<=450){
  2243.  
  2244. // // (window.skam|| (window.skam=[])).push(p.length);
  2245. // // }
  2246. // (window.skam|| (window.skam=[])).push(p);
  2247. // return false;
  2248. // }
  2249.  
  2250. // if(p.length < 50) return true; else return false;
  2251. // return; // M44
  2252. let itz = `${f.length}.${s}.${w}`;
  2253. if (!d) {
  2254. return itz;
  2255. } else if (itz !== d) {
  2256. console.warn('fnIntegrity=false', itz);
  2257. return false;
  2258. } else {
  2259. return true;
  2260. }
  2261. }
  2262.  
  2263. const px2cm = (px) => px * window.devicePixelRatio * 0.026458333;
  2264. const px2mm = (px) => px * window.devicePixelRatio * 0.26458333;
  2265.  
  2266. // let createElement_fountain_model_fn = null;
  2267. // let createElement_fountain_model_enabled = null;
  2268.  
  2269. // ; (USE_RM_ON_FOUNTAIN_MODEL) && (()=>{
  2270. // document.createElement4719 = document.createElement;
  2271. // document.createElement = function (a) {
  2272. // if (createElement_fountain_model_enabled) {
  2273. // const r = createElement_fountain_model_fn(a);
  2274. // if (r) return r;
  2275. // }
  2276. // return document.createElement4719(a);
  2277. // }
  2278. // })();
  2279.  
  2280. ; (ENABLE_FLAGS_MAINTAIN_STABLE_LIST || ENABLE_FLAGS_REUSE_COMPONENTS || DISABLE_FLAGS_SHADYDOM_FREE) && (() => {
  2281.  
  2282. const _config_ = () => {
  2283. try {
  2284. return ytcfg.data_;
  2285. } catch (e) { }
  2286. return null;
  2287. };
  2288.  
  2289. const flagsFn = (EXPERIMENT_FLAGS) => {
  2290.  
  2291. // console.log(700)
  2292.  
  2293. if (!EXPERIMENT_FLAGS) return;
  2294.  
  2295. if (ENABLE_FLAGS_MAINTAIN_STABLE_LIST) {
  2296. if (USE_MAINTAIN_STABLE_LIST_ONLY_WHEN_KS_FLAG_IS_SET ? EXPERIMENT_FLAGS.kevlar_should_maintain_stable_list === true : true) {
  2297. // EXPERIMENT_FLAGS.kevlar_tuner_should_test_maintain_stable_list = true; // timestamp toggle issue
  2298. EXPERIMENT_FLAGS.kevlar_should_maintain_stable_list = true;
  2299. // console.log(701)
  2300. }
  2301. }
  2302.  
  2303. if (ENABLE_FLAGS_REUSE_COMPONENTS) {
  2304. EXPERIMENT_FLAGS.kevlar_tuner_should_test_reuse_components = true;
  2305. EXPERIMENT_FLAGS.kevlar_tuner_should_reuse_components = true;
  2306. // console.log(702);
  2307. }
  2308.  
  2309. if (DISABLE_FLAGS_SHADYDOM_FREE) {
  2310. EXPERIMENT_FLAGS.enable_shadydom_free_scoped_node_methods = false;
  2311. EXPERIMENT_FLAGS.enable_shadydom_free_scoped_query_methods = false;
  2312. EXPERIMENT_FLAGS.enable_shadydom_free_scoped_readonly_properties_batch_one = false;
  2313. EXPERIMENT_FLAGS.enable_shadydom_free_parent_node = false;
  2314. EXPERIMENT_FLAGS.enable_shadydom_free_children = false;
  2315. EXPERIMENT_FLAGS.enable_shadydom_free_last_child = false;
  2316. }
  2317.  
  2318. // EXPERIMENT_FLAGS.enable_button_behavior_reuse = false;
  2319.  
  2320. };
  2321.  
  2322. const uf = (config_) => {
  2323. config_ = config_ || _config_();
  2324. if (config_) {
  2325. const { EXPERIMENT_FLAGS, EXPERIMENTS_FORCED_FLAGS } = config_;
  2326. if (EXPERIMENT_FLAGS) {
  2327. flagsFn(EXPERIMENT_FLAGS);
  2328. if (EXPERIMENTS_FORCED_FLAGS) flagsFn(EXPERIMENTS_FORCED_FLAGS);
  2329. }
  2330. }
  2331. }
  2332.  
  2333. window._ytConfigHacks.add((config_) => {
  2334. uf(config_);
  2335. });
  2336.  
  2337. uf();
  2338.  
  2339. })();
  2340.  
  2341. if (DISABLE_Translation_By_Google) {
  2342.  
  2343. let mo = new MutationObserver(() => {
  2344.  
  2345. if (!mo) return;
  2346. let h = document.head;
  2347. if (!h) return;
  2348. mo.disconnect();
  2349. mo.takeRecords();
  2350. mo = null;
  2351.  
  2352. let meta = document.createElement('meta');
  2353. meta.setAttribute('name', 'google');
  2354. meta.setAttribute('content', 'notranslate');
  2355. h.appendChild(meta);
  2356.  
  2357.  
  2358. });
  2359. mo.observe(document, { subtree: true, childList: true });
  2360. }
  2361.  
  2362. console.assert(MAX_ITEMS_FOR_TOTAL_DISPLAY > 0)
  2363. // console.assert(MAX_ITEMS_FOR_TOTAL_DISPLAY > 0 && MAX_ITEMS_FOR_FULL_FLUSH > 0 && MAX_ITEMS_FOR_TOTAL_DISPLAY > MAX_ITEMS_FOR_FULL_FLUSH)
  2364.  
  2365. const isContainSupport = CSS.supports('contain', 'layout paint style');
  2366. if (!isContainSupport) {
  2367. console.warn("Your browser does not support css property 'contain'.\nPlease upgrade to the latest version.".trim());
  2368. }
  2369.  
  2370. const isOverflowAnchorSupport = CSS.supports('overflow-anchor', 'auto');
  2371. if (!isOverflowAnchorSupport) {
  2372. console.warn("Your browser does not support css property 'overflow-anchor'.\nPlease upgrade to the latest version.".trim());
  2373. }
  2374.  
  2375. const ENABLE_OVERFLOW_ANCHOR = ENABLE_OVERFLOW_ANCHOR_PREFERRED && isOverflowAnchorSupport && ENABLE_NO_SMOOTH_TRANSFORM && typeof ResizeObserver === 'function';
  2376. let WITH_SCROLL_ANCHOR = false;
  2377.  
  2378. const fxOperator = (proto, propertyName) => {
  2379. let propertyDescriptorGetter = null;
  2380. try {
  2381. propertyDescriptorGetter = Object.getOwnPropertyDescriptor(proto, propertyName).get;
  2382. } catch (e) { }
  2383. return typeof propertyDescriptorGetter === 'function' ? (e) => {
  2384. try {
  2385.  
  2386. return propertyDescriptorGetter.call(dr(e));
  2387. } catch (e) { }
  2388. return e[propertyName];
  2389. } : (e) => e[propertyName];
  2390. };
  2391.  
  2392. const nodeParent = fxOperator(Node.prototype, 'parentNode');
  2393. const nPrevElem = fxOperator(HTMLElement_.prototype, 'previousElementSibling');
  2394. const nNextElem = fxOperator(HTMLElement_.prototype, 'nextElementSibling');
  2395. const nLastElem = fxOperator(HTMLElement_.prototype, 'lastElementChild');
  2396.  
  2397. let groupCI = [];
  2398. let groupDI = 0;
  2399.  
  2400. const [console_] = [console];
  2401. const console1 = {
  2402. log(...args) {
  2403. if (!SHOW_DEVTOOL_DEBUG) return;
  2404. if (groupDI === 1) return grouppedConsoleLog(...args);
  2405. return console_.log(...args);
  2406. },
  2407. warn(...args) {
  2408. if (!SHOW_DEVTOOL_DEBUG) return;
  2409. if (groupDI === 1) return grouppedConsoleWarn(...args);
  2410. return console_.warn(...args);
  2411. },
  2412. debug(...args) {
  2413. if (!SHOW_DEVTOOL_DEBUG) return;
  2414. if (groupDI === 1) return grouppedConsoleDebug(...args);
  2415. return console_.debug(...args);
  2416. }
  2417. }
  2418. const grouppedConsoleLog = (...args) => {
  2419. if (DEBUG_LOG_HIDE_OK) {
  2420. for (const arg of args) {
  2421. if (typeof arg !== 'string') break;
  2422. if (arg.endsWith('OK')) return;
  2423. }
  2424. }
  2425. groupCI.push(['log', ...args]);
  2426. }
  2427. const grouppedConsoleWarn = (...args) => {
  2428. groupCI.push(['warn', ...args]);
  2429. }
  2430. const grouppedConsoleDebug = (...args) => {
  2431. groupCI.push(['debug', ...args]);
  2432. }
  2433. const groupCollapsed = (text1, text2) => {
  2434. if (!SHOW_DEVTOOL_DEBUG) return;
  2435. if (groupDI !== 0) console_.warn('groupDI in groupCollapsed fails', groupDI);
  2436. groupDI++;
  2437. groupCI.length = 0;
  2438.  
  2439. let w = 'groupCollapsed';
  2440. if (DEBUG_LOG_GROUP_EXPAND) w = 'group';
  2441. groupCI.push([w, `%c${text1}%c${text2}`,
  2442. "background-color: #010502; color: #6acafe; font-weight: 700; padding: 2px;",
  2443. "background-color: #010502; color: #6ad9fe; font-weight: 300; padding: 2px;"
  2444. ]);
  2445. }
  2446. const groupEnd = () => {
  2447. if (!SHOW_DEVTOOL_DEBUG) return;
  2448. groupDI--;
  2449. if (groupDI !== 0) console_.warn('groupDI in groupEnd fails', groupDI);
  2450. if (groupCI.length >= 0) {
  2451. let withContent = false;
  2452. for (const entry of groupCI) {
  2453. if (entry[0] === 'group' || entry[0] === 'groupCollapsed') continue;
  2454. if (entry[1] === '[Begin]' || entry[1] === '[End]') continue;
  2455. withContent = true;
  2456. break;
  2457. }
  2458. if (withContent) {
  2459. for (const entry of groupCI) {
  2460. const args = entry.slice(1);
  2461. let colorHighLight = '';
  2462. for (const arg of args) {
  2463. if (typeof arg !== 'string') {
  2464. colorHighLight = '';
  2465. break;
  2466. }
  2467. if (arg === 'OK' || arg === 'NG') {
  2468. colorHighLight = arg;
  2469. } else {
  2470. if (arg.endsWith(' OK')) colorHighLight = 'OK';
  2471. else if (arg.endsWith(' NG')) colorHighLight = 'NG';
  2472. }
  2473. }
  2474. let print = args;
  2475. if (colorHighLight) {
  2476. print = [args.map(e => `%c${e}`).join(' '), ...args.map(e => {
  2477. if (colorHighLight === 'OK' && e.includes(colorHighLight)) return "background-color:rgb(29, 29, 29); color:rgb(57, 215, 83); font-weight: 600;";
  2478. if (colorHighLight === 'NG' && e.includes(colorHighLight)) return "background-color:rgb(29, 29, 29); color:rgb(215, 133, 57); font-weight: 600;";
  2479. return "background-color:rgb(29, 29, 29); color:rgb(231, 231, 231); font-weight: 400;";
  2480. })];
  2481. }
  2482. console[entry[0]](...print);
  2483. }
  2484. console.groupEnd();
  2485. groupCI.length = 0;
  2486. }
  2487. }
  2488. }
  2489.  
  2490. // const microNow = () => performance.now() + (performance.timeOrigin || performance.timing.navigationStart);
  2491.  
  2492.  
  2493. const EVENT_KEY_ON_REGISTRY_READY = "ytI-ce-registry-created";
  2494. const onRegistryReady = (callback) => {
  2495. if (typeof customElements === 'undefined') {
  2496. if (!('__CE_registry' in document)) {
  2497. // https://github.com/webcomponents/polyfills/
  2498. Object.defineProperty(document, '__CE_registry', {
  2499. get() {
  2500. // return undefined
  2501. },
  2502. set(nv) {
  2503. if (typeof nv == 'object') {
  2504. delete this.__CE_registry;
  2505. this.__CE_registry = nv;
  2506. this.dispatchEvent(new CustomEvent(EVENT_KEY_ON_REGISTRY_READY));
  2507. }
  2508. return true;
  2509. },
  2510. enumerable: false,
  2511. configurable: true
  2512. })
  2513. }
  2514. let eventHandler = (evt) => {
  2515. document.removeEventListener(EVENT_KEY_ON_REGISTRY_READY, eventHandler, false);
  2516. const f = callback;
  2517. callback = null;
  2518. eventHandler = null;
  2519. f();
  2520. };
  2521. document.addEventListener(EVENT_KEY_ON_REGISTRY_READY, eventHandler, false);
  2522. } else {
  2523. callback();
  2524. }
  2525. };
  2526.  
  2527. const promiseForCustomYtElementsReady = new Promise(onRegistryReady);
  2528.  
  2529. const renderReadyPn = typeof ResizeObserver !== 'undefined' ? (sizingTarget) => {
  2530.  
  2531. return new Promise(resolve => {
  2532.  
  2533. let ro = new ResizeObserver(entries => {
  2534. if (entries && entries.length >= 1) {
  2535. resolve();
  2536. ro.disconnect();
  2537. ro = null;
  2538. }
  2539. });
  2540. ro.observe(sizingTarget);
  2541.  
  2542.  
  2543.  
  2544. });
  2545.  
  2546. } : (sizingTarget) => {
  2547.  
  2548.  
  2549. return new Promise(resolve => {
  2550.  
  2551. let io = new IntersectionObserver(entries => {
  2552. if (entries && entries.length >= 1) {
  2553. resolve();
  2554. io.disconnect();
  2555. io = null;
  2556. }
  2557. });
  2558. io.observe(sizingTarget);
  2559.  
  2560.  
  2561.  
  2562. });
  2563.  
  2564. };
  2565.  
  2566. /* globals WeakRef:false */
  2567.  
  2568. /** @type {(o: Object | null) => WeakRef | null} */
  2569. const mWeakRef = typeof WeakRef === 'function' ? (o => o ? new WeakRef(o) : null) : (o => o || null);
  2570.  
  2571. /** @type {(wr: Object | null) => Object | null} */
  2572. const kRef = (wr => (wr && wr.deref) ? wr.deref() : wr);
  2573.  
  2574. const { insertBeforeNaFn, appendChildNaFn } = (() => {
  2575. // native methods
  2576.  
  2577. const insertBefore = HTMLElement_.prototype.insertBefore;
  2578. const appendChild = HTMLElement_.prototype.appendChild;
  2579.  
  2580. return {
  2581. insertBeforeNaFn: (parent, node, child) => {
  2582. insertBefore.call(parent, node, child);
  2583. },
  2584. appendChildNaFn: (parent, node) => {
  2585. appendChild.call(parent, node);
  2586. }
  2587. };
  2588.  
  2589. /*
  2590. const insertBeforeFn = (parent, node, child) => {
  2591. if ('__shady_native_insertBefore' in parent) parent.__shady_native_insertBefore(node, child);
  2592. else parent.insertBefore(node, child);
  2593. }
  2594.  
  2595. const appendChildFn = (parent, node) =>{
  2596. if('__shady_native_appendChild' in parent) parent.__shady_native_appendChild(node);
  2597. else parent.appendChild(node);
  2598. }
  2599. */
  2600.  
  2601. })();
  2602.  
  2603.  
  2604.  
  2605. let __LCRInjection__ = 0; // 0 for no injection
  2606. const LCRImmedidates = []; // array of sync. func
  2607.  
  2608. let getLCRDummyP_ = null;
  2609. // lcrPromiseFn
  2610. const getLCRDummy = () => {
  2611.  
  2612. /* remarks */
  2613.  
  2614. /*
  2615.  
  2616. // YouTube uses `<ps-dom-if class="style-scope ytd-live-chat-frame"><template></template></ps-dom-if>` to create yt-live-chat-renderer
  2617. // <ps-dom-if> is located inside ytd-live-chat-frame#chat in main frame
  2618. // <ps-dom-if>.hostElement is located as iframe's yt-live-chat-app > div#contents > yt-live-chat-renderer
  2619.  
  2620. */
  2621.  
  2622.  
  2623. // direct createElement or createComponent_ will make the emoji rendering crashed. reason TBC
  2624.  
  2625. return getLCRDummyP_ || (getLCRDummyP_ = Promise.all([customElements.whenDefined('yt-live-chat-app'), customElements.whenDefined('yt-live-chat-renderer')]).then(async () => {
  2626.  
  2627. const tag = "yt-live-chat-renderer"
  2628. let dummy = document.querySelector(tag);
  2629. if (!dummy) {
  2630.  
  2631. let mo = null;
  2632.  
  2633. const ytLiveChatApp = document.querySelector('yt-live-chat-app') || document.createElement('yt-live-chat-app');
  2634.  
  2635. const lcaProto = getProto(ytLiveChatApp);
  2636. let fz38;
  2637.  
  2638. let qt38=0;
  2639. let bypass = false;
  2640.  
  2641.  
  2642. dummy = await new Promise(resolve => {
  2643.  
  2644.  
  2645. if (typeof lcaProto.createComponent_ === 'function' && !lcaProto.createComponent99_ && lcaProto.createComponent_.length === 3) {
  2646. console.log('[yt-chat-lcr] lcaProto.createComponent_ is found');
  2647.  
  2648. lcaProto.createComponent99_ = lcaProto.createComponent_;
  2649. lcaProto.createComponent98_ = function (a, b, c) {
  2650. const z = customCreateComponent(a,b,c);
  2651. if(z !== undefined) return z;
  2652. // (3) ['yt-live-chat-renderer', {…}, true]
  2653. const r = this.createComponent99_(a, b,c);
  2654. const componentTag = (typeof a === 'string' ? a : (a||0).component) || `${(r||0).nodeName}`.toLowerCase();
  2655. if ( componentTag === 'yt-live-chat-renderer' && !bypass) {
  2656. qt38 = 1;
  2657.  
  2658. __LCRInjection__ = __LCRInjection__ | 1;
  2659.  
  2660. // r.polymerController.__proto__.handleLiveChatActions471_ = r.polymerController.__proto__.handleLiveChatActions_;
  2661. // r.polymerController.__proto__.handleLiveChatActions_ = function (arr) {
  2662.  
  2663.  
  2664. // preprocessChatLiveActions(arr);
  2665.  
  2666. // return this.handleLiveChatActions471_(arr);
  2667.  
  2668.  
  2669. // }
  2670.  
  2671. for (const f of LCRImmedidates) {
  2672. f(r);
  2673. }
  2674. LCRImmedidates.length = 0;
  2675.  
  2676. resolve(r); // note: this dom is not yet adopted, but promise resolve is later than ops.
  2677. console.log('[yt-chat-lcr] element found by method 1');
  2678. }
  2679. return r;
  2680. };
  2681. lcaProto.createComponent_ = lcaProto.createComponent98_;
  2682.  
  2683. if (!USE_OBTAIN_LCR_BY_BOTH_METHODS) return;
  2684.  
  2685. }
  2686.  
  2687. // console.log('[yt-chat] lcaProto traditional');
  2688.  
  2689. const pz38 = document.getElementsByTagName(tag);
  2690. fz38 = () => {
  2691. const t = pz38[0]
  2692. if (t) {
  2693. qt38 = 2;
  2694.  
  2695. __LCRInjection__ = __LCRInjection__ | 2;
  2696. resolve(t);
  2697. console.log('[yt-chat-lcr] element found by method 2');
  2698. }
  2699. };
  2700. mo = new MutationObserver(fz38);
  2701. mo.observe(document, { subtree: true, childList: true, attributes: true });
  2702. document.addEventListener('yt-action', fz38, true);
  2703. fz38();
  2704.  
  2705. });
  2706.  
  2707. bypass = true;
  2708.  
  2709. if (mo) {
  2710. mo.disconnect();
  2711. mo.takeRecords();
  2712. mo = null;
  2713. }
  2714. if (fz38) {
  2715. document.removeEventListener('yt-action', fz38, true);
  2716. fz38 = null;
  2717. }
  2718. console.log(`[yt-chat-lcr] lcr appears, dom = ${document.getElementsByTagName(tag).length}, method = ${qt38}`);
  2719.  
  2720.  
  2721. // if (lcaProto.createComponent99_ && lcaProto.createComponent_ && lcaProto.createComponent98_ === lcaProto.createComponent_) {
  2722. // lcaProto.createComponent_ = lcaProto.createComponent99_;
  2723. // lcaProto.createComponent99_ = null;
  2724. // lcaProto.createComponent98_ = null;
  2725. // }
  2726.  
  2727. } else {
  2728. console.log('[yt-chat-lcr] lcr exists');
  2729. }
  2730. return dummy;
  2731.  
  2732. }));
  2733. }
  2734.  
  2735. const { addCssManaged } = (() => {
  2736.  
  2737. const addFontPreRendering = () => {
  2738.  
  2739. groupCollapsed("YouTube Super Fast Chat", " | Fonts Pre-Rendering");
  2740.  
  2741. let efsContainer = document.createElement('elzm-fonts');
  2742. efsContainer.id = 'elzm-fonts-yk75g'
  2743.  
  2744. const arr = [];
  2745. let p = document.createElement('elzm-font');
  2746. arr.push(p);
  2747.  
  2748. if (ENABLE_FONT_PRE_RENDERING & 1) {
  2749. for (const size of [100, 200, 300, 400, 500, 600, 700, 800, 900]) {
  2750.  
  2751. p = document.createElement('elzm-font');
  2752. p.style.fontWeight = size;
  2753. arr.push(p);
  2754. }
  2755. }
  2756.  
  2757. if (ENABLE_FONT_PRE_RENDERING & 2) {
  2758. for (const size of [100, 200, 300, 400, 500, 600, 700, 800, 900]) {
  2759.  
  2760. p = document.createElement('elzm-font');
  2761. p.style.fontFamily = 'Roboto';
  2762. p.style.fontWeight = size;
  2763. arr.push(p);
  2764. }
  2765. }
  2766.  
  2767. if (ENABLE_FONT_PRE_RENDERING & 4) {
  2768. for (const size of [100, 200, 300, 400, 500, 600, 700, 800, 900]) {
  2769.  
  2770. p = document.createElement('elzm-font');
  2771. p.style.fontFamily = '"YouTube Noto",Roboto,Arial,Helvetica,sans-serif';
  2772. p.style.fontWeight = size;
  2773. arr.push(p);
  2774. }
  2775. }
  2776.  
  2777.  
  2778. if (ENABLE_FONT_PRE_RENDERING & 8) {
  2779. for (const size of [100, 200, 300, 400, 500, 600, 700, 800, 900]) {
  2780.  
  2781. p = document.createElement('elzm-font');
  2782. p.style.fontFamily = '"Noto",Roboto,Arial,Helvetica,sans-serif';
  2783. p.style.fontWeight = size;
  2784. arr.push(p);
  2785. }
  2786. }
  2787.  
  2788.  
  2789. if (ENABLE_FONT_PRE_RENDERING & 16) {
  2790. for (const size of [100, 200, 300, 400, 500, 600, 700, 800, 900]) {
  2791.  
  2792. p = document.createElement('elzm-font');
  2793. p.style.fontFamily = 'sans-serif';
  2794. p.style.fontWeight = size;
  2795. arr.push(p);
  2796. }
  2797. }
  2798.  
  2799. console1.log('number of elzm-font elements', arr.length);
  2800.  
  2801. HTMLElement_.prototype.append.apply(efsContainer, arr);
  2802.  
  2803. (document.body || document.documentElement).appendChild(efsContainer);
  2804.  
  2805.  
  2806. console1.log('elzm-font elements have been added to the page for rendering.');
  2807.  
  2808. groupEnd();
  2809.  
  2810. }
  2811.  
  2812. let isCssAdded = false;
  2813.  
  2814. function addCssElement() {
  2815. let s = document.createElement('style');
  2816. s.id = 'ewRvC';
  2817. return s;
  2818. }
  2819.  
  2820. const addCssManaged = () => {
  2821. if (!isCssAdded && document.documentElement && document.head) {
  2822. isCssAdded = true;
  2823. document.head.appendChild(dr(addCssElement())).textContent = addCss();
  2824. if (ENABLE_FONT_PRE_RENDERING) {
  2825. Promise.resolve().then(addFontPreRendering)
  2826. }
  2827. }
  2828. }
  2829.  
  2830. return { addCssManaged };
  2831. })();
  2832.  
  2833.  
  2834. const { setupStyle } = (() => {
  2835.  
  2836. const sp7 = Symbol();
  2837.  
  2838. const proxyHelperFn = (dummy) => ({
  2839.  
  2840. get(target, prop) {
  2841. return (prop in dummy) ? dummy[prop] : prop === sp7 ? target : target[prop];
  2842. },
  2843. set(target, prop, value) {
  2844. if (!(prop in dummy)) {
  2845. target[prop] = value;
  2846. }
  2847. return true;
  2848. },
  2849. has(target, prop) {
  2850. return (prop in target);
  2851. },
  2852. deleteProperty(target, prop) {
  2853. return true;
  2854. },
  2855. ownKeys(target) {
  2856. return Object.keys(target);
  2857. },
  2858. defineProperty(target, key, descriptor) {
  2859. return Object.defineProperty(target, key, descriptor);
  2860. },
  2861. getOwnPropertyDescriptor(target, key) {
  2862. return Object.getOwnPropertyDescriptor(target, key);
  2863. },
  2864.  
  2865. });
  2866.  
  2867. const setupStyle = (m1, m2) => {
  2868. if (!ENABLE_NO_SMOOTH_TRANSFORM) return;
  2869.  
  2870. const dummy1v = {
  2871. transform: '',
  2872. height: '',
  2873. minHeight: '',
  2874. paddingBottom: '',
  2875. paddingTop: ''
  2876. };
  2877.  
  2878. const dummyStyleFn = (k) => (function () { const style = this[sp7]; return style[k](...arguments); });
  2879. for (const k of ['toString', 'getPropertyPriority', 'getPropertyValue', 'item', 'removeProperty', 'setProperty']) {
  2880. dummy1v[k] = dummyStyleFn(k);
  2881. }
  2882.  
  2883. const dummy1p = proxyHelperFn(dummy1v);
  2884. const sp1v = new Proxy(m1.style, dummy1p);
  2885. const sp2v = new Proxy(m2.style, dummy1p);
  2886. Object.defineProperty(m1, 'style', { get() { return sp1v }, set() { }, enumerable: true, configurable: true });
  2887. Object.defineProperty(m2, 'style', { get() { return sp2v }, set() { }, enumerable: true, configurable: true });
  2888. m1.removeAttribute("style");
  2889. m2.removeAttribute("style");
  2890.  
  2891. }
  2892.  
  2893. return { setupStyle };
  2894.  
  2895. })();
  2896.  
  2897.  
  2898.  
  2899. function setThumbnails(config) {
  2900.  
  2901. const { baseObject, thumbnails, flag0, imageLinks } = config;
  2902.  
  2903. if (flag0 || (ENABLE_PRELOAD_THUMBNAIL && imageLinks)) {
  2904.  
  2905.  
  2906. if (thumbnails && thumbnails.length > 0) {
  2907. if (flag0 > 0 && thumbnails.length > 1) {
  2908. let pSize = 0;
  2909. let newThumbnails = [];
  2910. for (const thumbnail of thumbnails) {
  2911. if (!thumbnail || !thumbnail.url) continue;
  2912. const squarePhoto = thumbnail.width === thumbnail.height && typeof thumbnail.width === 'number';
  2913. const condSize = pSize <= 0 || (flag0 === 1 ? pSize > thumbnail.width : pSize < thumbnail.width);
  2914. const leastSizeFulfilled = squarePhoto ? thumbnail.width >= LEAST_IMAGE_SIZE : true;
  2915. if ((!squarePhoto || condSize) && leastSizeFulfilled) {
  2916. newThumbnails.push(thumbnail);
  2917. if (imageLinks) imageLinks.add(thumbnail.url);
  2918. }
  2919. if (squarePhoto && condSize && leastSizeFulfilled) {
  2920. pSize = thumbnail.width;
  2921. }
  2922. }
  2923. if (thumbnails.length !== newThumbnails.length && thumbnails === baseObject.thumbnails && newThumbnails.length > 0) {
  2924. baseObject.thumbnails = newThumbnails;
  2925. } else {
  2926. newThumbnails.length = 0;
  2927. }
  2928. newThumbnails = null;
  2929. } else {
  2930. for (const thumbnail of thumbnails) {
  2931. if (thumbnail && thumbnail.url) {
  2932. if (imageLinks) imageLinks.add(thumbnail.url);
  2933. }
  2934. }
  2935. }
  2936. }
  2937.  
  2938. }
  2939. }
  2940.  
  2941. function fixLiveChatItem(item, imageLinks) {
  2942. const liveChatTextMessageRenderer = (item || 0).liveChatTextMessageRenderer || 0;
  2943. if (liveChatTextMessageRenderer) {
  2944. const messageRuns = (liveChatTextMessageRenderer.message || 0).runs || 0;
  2945. if (messageRuns && messageRuns.length > 0) {
  2946. for (const run of messageRuns) {
  2947. const emojiImage = (((run || 0).emoji || 0).image || 0);
  2948. setThumbnails({
  2949. baseObject: emojiImage,
  2950. thumbnails: emojiImage.thumbnails,
  2951. flag0: EMOJI_IMAGE_SINGLE_THUMBNAIL,
  2952. imageLinks
  2953. });
  2954. }
  2955. }
  2956. const authorPhoto = liveChatTextMessageRenderer.authorPhoto || 0;
  2957. setThumbnails({
  2958. baseObject: authorPhoto,
  2959. thumbnails: authorPhoto.thumbnails,
  2960. flag0: AUTHOR_PHOTO_SINGLE_THUMBNAIL,
  2961. imageLinks
  2962. });
  2963. }
  2964. }
  2965.  
  2966.  
  2967.  
  2968. let kptPF = null;
  2969. const emojiPrefetched = new LimitedSizeSet(PREFETCH_LIMITED_SIZE_EMOJI);
  2970. const authorPhotoPrefetched = new LimitedSizeSet(PREFETCH_LIMITED_SIZE_AUTHOR_PHOTO);
  2971.  
  2972. const linkerOnload = function () {
  2973. this.resolveFn({
  2974. link: this,
  2975. success: true
  2976. });
  2977. this.remove();
  2978. };
  2979. const linkerOnError = function () {
  2980. this.resolveFn({
  2981. link: this,
  2982. success: false
  2983. });
  2984. this.remove();
  2985. };
  2986. function linker(link, rel, href, _as) {
  2987. return new Promise(resolve => {
  2988. if (!link) link = document.createElement('link');
  2989. link.rel = rel;
  2990. if (_as) link.setAttribute('as', _as);
  2991. link.resolveFn = resolve;
  2992. link.onload = linkerOnload;
  2993. link.onerror = linkerOnError;
  2994. link.href = href;
  2995. document.head.appendChild(link);
  2996. link = null;
  2997. });
  2998. }
  2999.  
  3000. // ------- side process [sideProcesses] -------
  3001. const reuseFixDataViewModel = (elm) => {
  3002. // detach data-view model signal
  3003. return Promise.resolve(elm).then((elm) => {
  3004. for (const node of elm.getElementsByTagName('*')) {
  3005. const cnt = insp(node);
  3006. if (typeof cnt.dispose === 'function' && cnt.dispose.length === 0) {
  3007. try {
  3008. cnt.dispose();
  3009. } catch (e) { }
  3010. } else if (typeof node.dispose === 'function' && node.dispose.length === 0) {
  3011. try {
  3012. node.dispose();
  3013. } catch (e) { }
  3014. }
  3015. }
  3016. }).catch(console.warn);;
  3017. };
  3018. const reuseFixYtIconRendering = (elm) => {
  3019. // make properties fresh for flushing
  3020. return Promise.resolve(elm).then((elm) => {
  3021. refreshChildrenYtIcons(elm);
  3022. }).catch(console.warn);;
  3023. };
  3024. const onVisibleItemStampNodeRemoval = (elmId) =>{
  3025. // set the corresponding ticker [ticker-message-removed]
  3026. return Promise.resolve(elmId).then((elmId) => {
  3027. const tickerElm = document.querySelector(`.style-scope.yt-live-chat-ticker-renderer[id="${elmId}"]`);
  3028. if (tickerElm) {
  3029. tickerElm.setAttribute('ticker-message-removed', '')
  3030. if (tickerElm.matches('[ticker-message-removed]:nth-child(n + 40)')) {
  3031. insp(tickerElm).requestRemoval();
  3032. }
  3033. }
  3034. }).catch(console.warn);;
  3035. };
  3036. let onTickerItemStampNodeAddedwaiting = false;
  3037. const onTickerItemStampNodeAdded = () =>{
  3038. // remove the stale ticker(s)
  3039. if (onTickerItemStampNodeAddedwaiting) return;
  3040. onTickerItemStampNodeAddedwaiting = true;
  3041. return Promise.resolve().then(() => {
  3042. onTickerItemStampNodeAddedwaiting = false;
  3043. const selector = "[ticker-message-removed]:nth-child(n + 40)";
  3044. const tickerElm = document.querySelector(selector);
  3045. if (tickerElm) { // likely false
  3046. const tickerElms = document.querySelectorAll(selector);
  3047. for (const tickerElm of tickerElms) insp(tickerElm).requestRemoval();
  3048. }
  3049. }).catch(console.warn);;
  3050. };
  3051. const mutationDelayedRefreshData = async (cnt) => {
  3052. // ensure data is invalidated correctly after mutation
  3053. return Promise.resolve(cnt).then(async cnt => {
  3054. wme.data = `${(wme.data & 7) + 1}`;
  3055. await wmp;
  3056. cnt.__refreshData930__ && cnt.data && cnt.isAttached && cnt.parentComponent && cnt.__refreshData930__('data', !0);
  3057. });
  3058. }
  3059. // ------- side process [sideProcesses] -------
  3060.  
  3061. const cleanContext = async (win) => {
  3062. const waitFn = requestAnimationFrame; // shall have been binded to window
  3063. try {
  3064. let mx = 16; // MAX TRIAL
  3065. const frameId = 'vanillajs-iframe-v1';
  3066. /** @type {HTMLIFrameElement | null} */
  3067. let frame = document.getElementById(frameId);
  3068. let removeIframeFn = null;
  3069. if (!frame) {
  3070. frame = document.createElement('iframe');
  3071. frame.id = frameId;
  3072. const blobURL = typeof webkitCancelAnimationFrame === 'function' && typeof kagi === 'undefined' ? (frame.src = URL.createObjectURL(new Blob([], { type: 'text/html' }))) : null; // avoid Brave Crash
  3073. frame.sandbox = 'allow-same-origin'; // script cannot be run inside iframe but API can be obtained from iframe
  3074. let n = document.createElement('noscript'); // wrap into NOSCRPIT to avoid reflow (layouting)
  3075. n.appendChild(frame);
  3076. while (!document.documentElement && mx-- > 0) await new Promise(waitFn); // requestAnimationFrame here could get modified by YouTube engine
  3077. const root = document.documentElement;
  3078. root.appendChild(n); // throw error if root is null due to exceeding MAX TRIAL
  3079. if (blobURL) Promise.resolve().then(() => URL.revokeObjectURL(blobURL));
  3080.  
  3081. removeIframeFn = (setTimeout) => {
  3082. const removeIframeOnDocumentReady = (e) => {
  3083. e && win.removeEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false);
  3084. e = n;
  3085. n = win = removeIframeFn = 0;
  3086. setTimeout ? setTimeout(() => e.remove(), 200) : e.remove();
  3087. }
  3088. if (!setTimeout || document.readyState !== 'loading') {
  3089. removeIframeOnDocumentReady();
  3090. } else {
  3091. win.addEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false);
  3092. }
  3093. }
  3094. }
  3095. while (!frame.contentWindow && mx-- > 0) await new Promise(waitFn);
  3096. const fc = frame.contentWindow;
  3097. if (!fc) throw "window is not found."; // throw error if root is null due to exceeding MAX TRIAL
  3098. try {
  3099. const { requestAnimationFrame, setTimeout, cancelAnimationFrame, setInterval, clearInterval, getComputedStyle } = fc;
  3100. const res = { requestAnimationFrame, setTimeout, cancelAnimationFrame, setInterval, clearInterval, getComputedStyle };
  3101. for (let k in res) res[k] = res[k].bind(win); // necessary
  3102. if (removeIframeFn) Promise.resolve(res.setTimeout).then(removeIframeFn);
  3103.  
  3104. /** @type {HTMLElement} */
  3105. const HTMLElementProto = fc.HTMLElement.prototype;
  3106. /** @type {EventTarget} */
  3107. const EventTargetProto = fc.EventTarget.prototype;
  3108. // jsonParseFix = {
  3109. // _JSON: fc.JSON, _parse: fc.JSON.parse
  3110. // }
  3111. return {
  3112. ...res,
  3113. animate: HTMLElementProto.animate,
  3114. addEventListener: EventTargetProto.addEventListener,
  3115. removeEventListener: EventTargetProto.removeEventListener
  3116. };
  3117. } catch (e) {
  3118. if (removeIframeFn) removeIframeFn();
  3119. return null;
  3120. }
  3121. } catch (e) {
  3122. console.warn(e);
  3123. return null;
  3124. }
  3125. };
  3126.  
  3127. let xoIcjPr = null;
  3128. const xoIcjId = `xoIcj${Math.floor(Math.random() * 314159265359 + 314159265359).toString(36)}`;
  3129. const xoIcjPost = window.postMessage.bind(window, xoIcjId);
  3130. window.addEventListener('message', (evt) => {
  3131. if ((evt || 0).data === xoIcjId) {
  3132. const t = xoIcjPr;
  3133. if (t !== null) {
  3134. xoIcjPr = null;
  3135. t.resolve();
  3136. }
  3137. }
  3138. });
  3139. const timelineResolve = async () => {
  3140. let t = xoIcjPr;
  3141. if (t === null) {
  3142. t = xoIcjPr = new PromiseExternal();
  3143. xoIcjPost();
  3144. }
  3145. await t.then();
  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.  
  3419.  
  3420. const rendererStamperFactory = (cProto, options) => {
  3421.  
  3422.  
  3423. let pDivResourceEventCountLast = 0;
  3424. let pDivResourceEventCount = 0;
  3425.  
  3426. const pDivOnResource = function (evt) {
  3427. const target = evt.target;
  3428. if (target && target.nodeType === 1 && target.nodeName === "IMG") {
  3429. pDivResourceEventCount = (pDivResourceEventCount & 1073741823) + 1;
  3430. }
  3431. };
  3432.  
  3433. const { key, stamperDomClass, preloadFn } = options;
  3434.  
  3435. // const newDoc = document.implementation.createHTMLDocument("NewDoc");
  3436. const pSpace = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
  3437. document.documentElement.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3438. document.documentElement.lastChild.replaceWith(pSpace);
  3439. const pNode = document.createElement('ns-538');
  3440. pSpace.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3441. pSpace.lastChild.replaceWith(pNode);
  3442.  
  3443. const pDiv = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
  3444. if (typeof pNode.attachShadow === 'function') {
  3445. const pShadow = pNode.attachShadow({ mode: "open" });
  3446. pShadow.replaceChildren(pDiv);
  3447. } else {
  3448. pNode.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3449. pNode.lastChild.replaceWith(pDiv);
  3450. }
  3451.  
  3452. const pDivNew = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
  3453.  
  3454. pDiv.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3455. pDiv.lastChild.replaceWith(pDivNew);
  3456.  
  3457. pDivNew.addEventListener('load', pDivOnResource, true);
  3458. pDivNew.addEventListener('error', pDivOnResource, true);
  3459.  
  3460. const wmRemoved = new Map();
  3461.  
  3462. // const wmMapToItem = new WeakMap();
  3463. // let wmPendingList = null;
  3464.  
  3465. const nullComponents = new Map();
  3466.  
  3467. const componentDefaultAttributes = new WeakMap();
  3468.  
  3469. const fnKeyH = `${key}$$c472`;
  3470.  
  3471. cProto[fnKeyH] = async function (cTag, cId, pr00) {
  3472. // await the current executing task (if any)
  3473. // and avoid stacking in the same marco task
  3474. await Promise.all([pr00, nextBrowserTick_()]);
  3475. if (!this.ec389a && !this.ec389r) return;
  3476. const addedCount0 = this.ec389a;
  3477. const removedCount0 = this.ec389r;
  3478.  
  3479. this.ec389 = false;
  3480. this.ec389a = 0;
  3481. this.ec389r = 0;
  3482.  
  3483. const stampDomMap = this.stampDom[cTag].mapping;
  3484. const isTickerRendering = cTag === 'tickerItems';
  3485. const isMessageListRendering = cTag === 'visibleItems';
  3486.  
  3487. // coming process can be stacked as ec389a and ec389r are reset.
  3488.  
  3489. const deObjectComponent = (itemEntry) => {
  3490. const I = firstObjectKey(itemEntry);
  3491. const L = stampDomMap[I];
  3492. const H = itemEntry[I];
  3493. return [L, H];
  3494. }
  3495.  
  3496. const hostElement = this.hostElement;
  3497.  
  3498. let renderNodeCount = 0;
  3499. const renderList = this[cTag].map((item) => {
  3500. const [L, H] = deObjectComponent(item);
  3501. const node = kRef(renderMap.get(H));
  3502. return node && hostElement.contains(node) ? (renderNodeCount++, node) : item;
  3503. });
  3504.  
  3505. const isRenderListEmpty = renderList.length === 0;
  3506.  
  3507.  
  3508. // this.ec389 = null;
  3509. // this.ec389a = 0;
  3510. // this.ec389r = 0;
  3511.  
  3512. let addedCounter = 0;
  3513. let removedCounter = 0;
  3514.  
  3515. const createConnectedComponentElm = (insertionObj, L, H, componentName) => {
  3516. // const reusable = false;
  3517. // const componentName = this.getComponentName_(L, H);
  3518. let component;
  3519. if (!nullComponents.has(componentName)) {
  3520. nullComponents.set(componentName, (component = document.createElement(componentName)));
  3521. component.className = stamperDomClass;
  3522. // shadowElm.insertAdjacentElement('beforeend', component);
  3523. } else {
  3524. component = nullComponents.get(componentName);
  3525. }
  3526. component = component.cloneNode(false);
  3527.  
  3528. // const cnt = insp(component);
  3529.  
  3530. // cnt.__dataOld = cnt.__dataPending = null;
  3531. pDivNew.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3532. pDivNew.lastChild.replaceWith(component);
  3533. // cnt.__dataOld = cnt.__dataPending = null;
  3534.  
  3535. return component;
  3536. }
  3537.  
  3538. const listDom = this.getStampContainer_(cId);
  3539.  
  3540. const pnForNewItem = (item) => {
  3541.  
  3542. const [L, H] = deObjectComponent(item);
  3543.  
  3544. const componentName = this.getComponentName_(L, H);
  3545.  
  3546. const wmList = wmRemoved.get(componentName.toLowerCase());
  3547.  
  3548. let connectedComponent = null;
  3549. if (wmList && (connectedComponent = wmList.firstElementChild)) {
  3550. if (this.telemetry_) this.telemetry_.reuse++;
  3551. // if (!wmPendingList) {
  3552. // wmPendingList = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
  3553. // wmPendingList.setAttributeNS('http://www.w3.org/2000/svg', 'wm-pending', 'true');
  3554. // pDiv.insertAdjacentElement('afterend', wmPendingList);
  3555. // }
  3556. // wmPendingList.insertAdjacentElement('beforeend', connectedComponent);
  3557. pDivNew.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3558. pDivNew.lastChild.replaceWith(connectedComponent);
  3559. const attrMap = connectedComponent.attributes;
  3560. const defaultAttrs = componentDefaultAttributes.get(connectedComponent);
  3561. if (defaultAttrs) {
  3562. for (const attr of attrMap) {
  3563. const name = attr.name;
  3564. if (name in defaultAttrs) attr.value = defaultAttrs[name];
  3565. else attrMap.removeNamedItem(name);
  3566. }
  3567. if (attrMap.length !== defaultAttrs['"']) {
  3568. for (const name in defaultAttrs) {
  3569. if (!attrMap[name] && name !== '"') connectedComponent.setAttribute(name, defaultAttrs[name]);
  3570. }
  3571. }
  3572. }
  3573.  
  3574. } else {
  3575. connectedComponent = createConnectedComponentElm(item, L, H, componentName);
  3576. if (this.telemetry_) this.telemetry_.create++;
  3577. }
  3578. if (isTickerRendering) {
  3579. const container = connectedComponent.firstElementChild;
  3580. if (container) container.classList.add('yt-live-chat-ticker-stampdom-container');
  3581. }
  3582.  
  3583. return [item, L, H, connectedComponent];
  3584.  
  3585. };
  3586.  
  3587. let imgPreloadPr = null;
  3588. if (isMessageListRendering) {
  3589. const addedItems = renderList.filter(item => item === 'object' && (item instanceof Node));
  3590. imgPreloadPr = preloadFn(addedItems)();
  3591. }
  3592.  
  3593. // const pt1 = performance.now();
  3594. // const newComponentsEntries = await Promise.all(renderList.map((item) => {
  3595. // return typeof item === 'object' && !(item instanceof Node) ? Promise.resolve(item).then(pnForNewItem) : item;
  3596. // }));
  3597. const newComponentsEntries = isRenderListEmpty ? [] : await executeTaskBatch(renderList.map(item => ({
  3598. item,
  3599. fn(task) {
  3600. const { item } = task;
  3601. return typeof item === 'object' && !(item instanceof Node) ? pnForNewItem(item) : item;
  3602. }
  3603. })));
  3604. // const pt2 = performance.now();
  3605.  
  3606. const imgPromises = [];
  3607.  
  3608. const imgPaths = new Set();
  3609.  
  3610. const pnForRenderNewItem = (entry) => {
  3611. const [item, L, H, connectedComponent] = entry;
  3612.  
  3613. const cnt = insp(connectedComponent);
  3614. setupRefreshData930(cnt);
  3615. if (typeof cnt.data === 'object' && cnt.__dataEnabled === true && cnt.__dataReady === true && cnt.__dataInvalid === false) {
  3616. cnt.data = H;
  3617. } else {
  3618. const q = this.deferRenderStamperBinding_
  3619. let q2;
  3620. if (typeof q === 'object') q2 = this.deferRenderStamperBinding_ = [];
  3621. this.deferRenderStamperBinding_(connectedComponent, L, H);
  3622. this.flushRenderStamperComponentBindings_();
  3623. if (typeof q === 'object') {
  3624. this.deferRenderStamperBinding_ = q;
  3625. q2.length = 0;
  3626. }
  3627. }
  3628. if (cnt.__refreshData930__ && cnt.data) cnt.__refreshData930__('data', !0); // ensure data is invalidated
  3629.  
  3630. // fix yt-icon issue
  3631. refreshChildrenYtIcons(connectedComponent);
  3632.  
  3633. // const imgs = connectedComponent.getElementsByTagName('IMG');
  3634. // if (imgs.length > 0) {
  3635. // for (let i = 0, l = imgs.length; i < l; i++) {
  3636. // const src = imgs[i].src;
  3637. // if (src.includes('://') && !imgPaths.has(src)) {
  3638. // imgPaths.add(src);
  3639. // imgPromises.push(imageFetch(src));
  3640. // }
  3641. // }
  3642. // }
  3643. componentDefaultAttributes.set(connectedComponent, getAttributes(connectedComponent));
  3644. return entry;
  3645. }
  3646.  
  3647. // const pt3 = performance.now();
  3648. // const newRenderedComponents = await Promise.all(newComponentsEntries.map((entry) => {
  3649. // return typeof entry === 'object' && !(entry instanceof Node) ? Promise.resolve(entry).then(pnForRenderNewItem) : entry;
  3650. // }));
  3651. const newRenderedComponents = isRenderListEmpty ? [] : await executeTaskBatch(newComponentsEntries.map(entry => ({
  3652. entry,
  3653. fn(task) {
  3654. const { entry } = task;
  3655. return typeof entry === 'object' && !(entry instanceof Node) ? pnForRenderNewItem(entry) : entry;
  3656. }
  3657. })));
  3658. // const pt4 = performance.now();
  3659.  
  3660.  
  3661. // console.log('xxss' , pt2-pt1, pt4-pt3)
  3662.  
  3663.  
  3664. // wait for network cached images loading
  3665. // let trialMax = 4;
  3666. // while (trialMax--) {
  3667. // wme.data = `${(wme.data & 7) + 1}`;
  3668. // await wmp;
  3669. // if (pDivResourceEventCountLast === pDivResourceEventCount) break;
  3670. // pDivResourceEventCountLast = pDivResourceEventCount;
  3671. // }
  3672.  
  3673. this.flushRenderStamperComponentBindings_(); // ensure all deferred flush render tasks clear.
  3674.  
  3675. // imgPromises.push(imageFetch('data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'));
  3676. if (imgPromises.length > 0) {
  3677. const pr1 = Promise.all(imgPromises).catch(e => { });
  3678. const pr2 = autoTimerFn();
  3679. await Promise.race([pr1, pr2]).catch(e => { });
  3680. imgPaths.clear();
  3681. imgPromises.length = 0;
  3682. }
  3683. if (imgPreloadPr) await imgPreloadPr;
  3684.  
  3685. // const batching = [];
  3686. // let j = 0;
  3687. // let elNode;
  3688.  
  3689. const sideProcesses = [];
  3690.  
  3691. const removeStampNode_ = (elNode) => {
  3692. const elm = elNode;
  3693. const cnt = insp(elm);
  3694. const componentName = elm.nodeName.toLowerCase();
  3695. let wmList = wmRemoved.get(componentName);
  3696. if (!wmList) {
  3697. wmList = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
  3698. wmList.setAttributeNS('http://www.w3.org/2000/svg', 'wm-component', componentName);
  3699. pDiv.insertAdjacentHTML('afterend', ttpHTML('<!---->'));
  3700. pDiv.nextSibling.replaceWith(wmList);
  3701. wmRemoved.set(componentName, wmList);
  3702. }
  3703. wmList.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3704. wmList.lastChild.replaceWith(elm);
  3705. const data = cnt.data;
  3706. if (data) renderMap.delete(cnt.data);
  3707.  
  3708. sideProcesses.push(reuseFixDataViewModel(elm));
  3709. sideProcesses.push(reuseFixYtIconRendering(elm));
  3710. }
  3711.  
  3712. // const removeStampNode = async () => {
  3713.  
  3714. // removedCounter++;
  3715.  
  3716. // const nextElm = nextComponentSiblingFn(elNode);
  3717. // const elmId = elNode.id;
  3718. // removeStampNode_(elNode);
  3719. // // const dzid = this.getAttribute('dz-component-id');
  3720. // // ---- no-cache ----
  3721. // // try{
  3722. // // elm.remove();
  3723. // // }catch(e){}
  3724. // // ---- no-cache ----
  3725.  
  3726. // if (cTag === 'visibleItems') {
  3727. // sideProcesses.push(onVisibleItemStampNodeRemoval(elmId));
  3728. // }
  3729.  
  3730. // j++;
  3731. // elNode = nextElm;
  3732.  
  3733. // }
  3734.  
  3735. // if (typeof Polymer !== "undefined" && typeof Polymer.flush === "function") {
  3736. // // clear all pending rendering first
  3737. // await stackMarcoTask(async () => {
  3738. // Polymer.flush();
  3739. // });
  3740. // }
  3741.  
  3742. // main UI thread - DOM modification
  3743. await new Promise((resolveDM) => {
  3744. nextBrowserTick_(() => {
  3745.  
  3746. const isAtBottom = this.atBottom === true;
  3747. // if (ENABLE_OVERFLOW_ANCHOR && isAtBottom) {
  3748. // shouldScrollAfterFlush = true;
  3749. // }
  3750.  
  3751.  
  3752. const tasks = [];
  3753.  
  3754. const taskFn = {
  3755. remove: (task) => {
  3756.  
  3757. const { elNode } = task;
  3758.  
  3759. removedCounter++;
  3760.  
  3761. const elmId = elNode.id;
  3762. removeStampNode_(elNode);
  3763. // const dzid = this.getAttribute('dz-component-id');
  3764. // ---- no-cache ----
  3765. // try{
  3766. // elm.remove();
  3767. // }catch(e){}
  3768. // ---- no-cache ----
  3769.  
  3770. if (isMessageListRendering) {
  3771. sideProcesses.push(onVisibleItemStampNodeRemoval(elmId));
  3772. }
  3773.  
  3774. return 2
  3775.  
  3776. },
  3777. append: (task) => {
  3778.  
  3779. const { newNode, nodeAfter, parentNode } = task;
  3780.  
  3781. if (nodeAfter) {
  3782. nodeAfter.insertAdjacentHTML('beforebegin', ttpHTML('<!---->'));
  3783. nodeAfter.previousSibling.replaceWith(newNode);
  3784. } else {
  3785. parentNode.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3786. parentNode.lastChild.replaceWith(newNode);
  3787. }
  3788.  
  3789. // nodeAfter ? nodeAfter.insertAdjacentElement('beforebegin', newNode) : parentNode.insertAdjacentElement('beforeend', newNode);
  3790. const connectedComponent = newNode;
  3791. const cnt = insp(connectedComponent);
  3792. renderMap.set(cnt.data, mWeakRef(connectedComponent));
  3793. mutationDelayedRefreshData(cnt); // not included to sideProcesses
  3794. addedCounter++;
  3795.  
  3796. if (isTickerRendering) {
  3797. sideProcesses.push(onTickerItemStampNodeAdded());
  3798. }
  3799.  
  3800. if (isMessageListRendering && isAtBottom) {
  3801.  
  3802. const itemScroller = this.itemScroller;
  3803. if (itemScroller && (!ENABLE_OVERFLOW_ANCHOR || typeof webkitCancelAnimationFrame !== "function" || itemScroller.scrollTop === 0)) itemScroller.scrollTop = 16777216;
  3804.  
  3805. }
  3806.  
  3807. return 1
  3808. }
  3809. }
  3810.  
  3811. {
  3812. const indexMap = new WeakMap();
  3813. // let index = 0;
  3814.  
  3815. if (!isRenderListEmpty) {
  3816. for (let elNode_ = firstComponentChildFn(listDom), index = 0; elNode_ instanceof Node; elNode_ = nextComponentSiblingFn(elNode_)) {
  3817. indexMap.set(elNode_, index++);
  3818. }
  3819. }
  3820.  
  3821.  
  3822.  
  3823. const keepIndices = new Array(renderNodeCount);
  3824. let keepIndicesLen = 0, lastKeepIndex = -1, requireSort = false;
  3825. for (let i = 0, l = newRenderedComponents.length; i < l; i++) {
  3826. const entry = newRenderedComponents[i];
  3827. if (entry instanceof Node) {
  3828. const index = indexMap.get(entry);
  3829. keepIndices[keepIndicesLen++] = [index, entry];
  3830. if (index > lastKeepIndex) lastKeepIndex = index;
  3831. else requireSort = true;
  3832. }
  3833. }
  3834. keepIndices.length = keepIndicesLen;
  3835. if (requireSort) keepIndices.sort((a, b) => a[0] - b[0]);
  3836. let dk = 0;
  3837.  
  3838. let j = 0;
  3839. let elNode;
  3840.  
  3841. elNode = firstComponentChildFn(listDom);
  3842.  
  3843. if (!isRenderListEmpty) {
  3844. for (const rcEntry of newRenderedComponents) {
  3845. const index = indexMap.get(rcEntry);
  3846. if (typeof index === 'number') {
  3847. const indexEntry = keepIndices[dk++];
  3848. const [dIdx, dNode] = indexEntry;
  3849. indexMap.delete(rcEntry);
  3850. const idx = dIdx;
  3851. while (j < idx && elNode) {
  3852. tasks.push({
  3853. type: 'remove',
  3854. elNode,
  3855. fn: taskFn.remove
  3856. });
  3857. elNode = nextComponentSiblingFn(elNode);
  3858. j++;
  3859. }
  3860. if (j === idx) {
  3861. if (elNode) {
  3862. // if (dNode !== elNode) tasks.push({
  3863. // type: 'swap',
  3864. // earlyNode: indexEntry[1],
  3865. // laterNode: elNode
  3866. // });
  3867. elNode = nextComponentSiblingFn(elNode);
  3868. j++;
  3869. } else {
  3870. console.warn('elNode is not available?', renderList, addedCount0, removedCount0, j, idx);
  3871. }
  3872. }
  3873. } else if (rcEntry instanceof Node) {
  3874. // interruped by the external like clearList
  3875.  
  3876. tasks.push({
  3877. type: 'remove',
  3878. elNode: rcEntry,
  3879. fn: taskFn.remove
  3880. });
  3881.  
  3882. } else {
  3883. const [item, L, H, connectedComponent] = rcEntry;
  3884.  
  3885. tasks.push({
  3886. type: 'append',
  3887. newNode: connectedComponent,
  3888. nodeAfter: elNode,
  3889. parentNode: listDom,
  3890. fn: taskFn.append
  3891. });
  3892.  
  3893. }
  3894.  
  3895. }
  3896. }
  3897.  
  3898. while (elNode) {
  3899.  
  3900. tasks.push({
  3901. type: 'remove',
  3902. elNode,
  3903. fn: taskFn.remove
  3904. });
  3905. elNode = nextComponentSiblingFn(elNode);
  3906.  
  3907. }
  3908.  
  3909. }
  3910.  
  3911.  
  3912. executeTaskBatch(tasks).then(resolveDM).catch(console.warn);
  3913.  
  3914. });
  3915. }).catch(console.warn);
  3916.  
  3917. {
  3918. const arr = this[cTag];
  3919. let b = 0;
  3920. b = b | this._setPendingPropertyOrPath(`${cTag}.splices`, {}, true, true);
  3921. b = b | this._setPendingPropertyOrPath(`${cTag}.length`, arr.length, true, true);
  3922. b && this._invalidateProperties();
  3923. }
  3924.  
  3925. // this.flushRenderStamperComponentBindings_(); // just in case...
  3926.  
  3927. await Promise.all(sideProcesses);
  3928.  
  3929. const detail = {
  3930. container: listDom
  3931. };
  3932. this.stampDom[cTag].events && this.hostElement.dispatchEvent(new CustomEvent("yt-rendererstamper-finished", {
  3933. bubbles: !0,
  3934. cancelable: !1,
  3935. composed: !0,
  3936. detail
  3937. }));
  3938. detail.container = null;
  3939.  
  3940. // if (typeof Polymer !== "undefined" && typeof Polymer.flush === "function") {
  3941. // // clear all remaining rendering before promise resolve
  3942. // await stackMarcoTask(async () => {
  3943. // Polymer.flush();
  3944. // });
  3945. // }
  3946.  
  3947. }
  3948.  
  3949. // proceedStampDomArraySplices371_ // proceedStampDomArraySplices381_
  3950. cProto[key] = function (cTag, cId, indexSplice) {
  3951. // console.log('proceedStampDomArraySplices_')
  3952. // assume no error -> no try catch (performance consideration)
  3953. const { index, addedCount, removed } = indexSplice;
  3954. const removedCount = removed ? removed.length : indexSplice.removedCount;
  3955. indexSplice = null;
  3956. if (!addedCount && !removedCount) {
  3957. console.warn('proceedStampDomArraySplices_', 'Error 001');
  3958. return false;
  3959. }
  3960. // const streamArr = this[cTag];
  3961. if (!this.ec389) {
  3962. if (this.ec389a || this.ec389r) {
  3963. console.warn('proceedStampDomArraySplices_', 'Error 002');
  3964. return false;
  3965. }
  3966. this.ec389 = true;
  3967. this.ec389a = 0;
  3968. this.ec389r = 0;
  3969. }
  3970. const shouldExecute = !this.ec389a && !this.ec389r;
  3971.  
  3972. this.ec389a += addedCount;
  3973. this.ec389r += removedCount;
  3974.  
  3975. if (shouldExecute) {
  3976.  
  3977. // let shouldScrollAfterFlush = false;
  3978. const pr00 = this.ec389pr;
  3979. const ec389pr = this.ec389pr = this[fnKeyH](cTag, cId, pr00).catch(console.warn);
  3980.  
  3981. if (cTag === 'visibleItems') {
  3982. this.prDelay288 = ec389pr;
  3983. // this.hasUserJustInteracted12_ = (this.hasUserJustInteracted11_ || (() => false));
  3984.  
  3985. // the first microtask after promise resolved
  3986. // YYYYYYY
  3987. // ec389pr.then(async () => {
  3988. // if (shouldScrollAfterFlush) {
  3989. // if (this.atBottom === false && this.allowScroll === true && !this.hasUserJustInteracted12_()) this.scrollToBottom_();
  3990. // wme.data = `${(wme.data & 7) + 1}`;
  3991. // await wmp;
  3992. // if (this.atBottom === false && this.allowScroll === true && !this.hasUserJustInteracted12_()) this.scrollToBottom_();
  3993. // }
  3994. // });
  3995.  
  3996. }
  3997.  
  3998. }
  3999.  
  4000. return true;
  4001. }
  4002.  
  4003.  
  4004.  
  4005.  
  4006.  
  4007. }
  4008.  
  4009.  
  4010. class RAFHub {
  4011. constructor() {
  4012. /** @type {number} */
  4013. this.startAt = 8170;
  4014. /** @type {number} */
  4015. this.counter = 0;
  4016. /** @type {number} */
  4017. this.rid = 0;
  4018. /** @type {Map<number, FrameRequestCallback>} */
  4019. this.funcs = new Map();
  4020. const funcs = this.funcs;
  4021. /** @type {FrameRequestCallback} */
  4022. this.bCallback = this.mCallback.bind(this);
  4023. this.pClear = () => funcs.clear();
  4024. this.keepRAF = false;
  4025. }
  4026. /** @param {DOMHighResTimeStamp} highResTime */
  4027. mCallback(highResTime) {
  4028. this.rid = 0;
  4029. Promise.resolve().then(this.pClear);
  4030. this.funcs.forEach(func => Promise.resolve(highResTime).then(func).catch(console.warn));
  4031. }
  4032. /** @param {FrameRequestCallback} f */
  4033. request(f) {
  4034. const cid = this.startAt + (this.counter = (this.counter & 1073741823) + 1);
  4035. this.funcs.set(cid, f);
  4036. if (this.rid === 0) this.rid = requestAnimationFrame(this.bCallback);
  4037. return cid;
  4038. }
  4039. /** @param {number} cid */
  4040. cancel(cid) {
  4041. cid = +cid;
  4042. if (cid > 0) {
  4043. if (cid <= this.startAt) {
  4044. return cancelAnimationFrame(cid);
  4045. }
  4046. if (this.rid > 0) {
  4047. this.funcs.delete(cid);
  4048. if (this.funcs.size === 0 && !this.keepRAF) {
  4049. cancelAnimationFrame(this.rid);
  4050. this.rid = 0;
  4051. }
  4052. }
  4053. }
  4054. }
  4055. }
  4056.  
  4057. function basePrefetching() {
  4058.  
  4059. new Promise(resolve => {
  4060.  
  4061. if (document.readyState !== 'loading') {
  4062. resolve();
  4063. } else {
  4064. win.addEventListener("DOMContentLoaded", resolve, false);
  4065. }
  4066.  
  4067. }).then(() => {
  4068. const hostL1 = [
  4069. 'https://www.youtube.com', 'https://googlevideo.com',
  4070. 'https://googleapis.com', 'https://accounts.youtube.com',
  4071. 'https://www.gstatic.com', 'https://ggpht.com',
  4072. 'https://yt3.ggpht.com', 'https://yt4.ggpht.com'
  4073. ];
  4074.  
  4075. const hostL2 = [
  4076. 'https://youtube.com',
  4077. 'https://fonts.googleapis.com', 'https://fonts.gstatic.com'
  4078. ];
  4079.  
  4080. let link = null;
  4081.  
  4082. function kn() {
  4083.  
  4084. link = document.createElement('link');
  4085. if (link.relList && link.relList.supports) {
  4086. 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)
  4087. } else {
  4088. kptPF = 0;
  4089. }
  4090.  
  4091. groupCollapsed("YouTube Super Fast Chat", " | PREFETCH SUPPORTS");
  4092. if (ENABLE_BASE_PREFETCHING) console1.log('dns-prefetch', (kptPF & 1) ? 'OK' : 'NG');
  4093. if (ENABLE_BASE_PREFETCHING) console1.log('preconnect', (kptPF & 2) ? 'OK' : 'NG');
  4094. if (ENABLE_PRELOAD_THUMBNAIL) console1.log('prefetch', (kptPF & 4) ? 'OK' : 'NG');
  4095. if (ENABLE_PRELOAD_THUMBNAIL) console1.log('preload', (kptPF & 16) ? 'OK' : 'NG');
  4096. groupEnd();
  4097.  
  4098. }
  4099.  
  4100. for (const h of hostL1) {
  4101.  
  4102. if (kptPF === null) kn();
  4103. if (ENABLE_BASE_PREFETCHING) {
  4104. // if (kptPF & 1) {
  4105. // linker(link, 'dns-prefetch', h);
  4106. // link = null;
  4107. // }
  4108. if (kptPF & 2) {
  4109. linker(link, 'preconnect', h);
  4110. link = null;
  4111. }
  4112. }
  4113. }
  4114.  
  4115. for (const h of hostL2) {
  4116. if (kptPF === null) kn();
  4117. if (ENABLE_BASE_PREFETCHING) {
  4118. if (kptPF & 1) {
  4119. linker(link, 'dns-prefetch', h);
  4120. link = null;
  4121. }
  4122. }
  4123. }
  4124.  
  4125. })
  4126.  
  4127.  
  4128. }
  4129.  
  4130. if (DO_LINK_PREFETCH) basePrefetching();
  4131.  
  4132. const { notifyPath7081 } = (() => {
  4133. // DO_PARTICIPANT_LIST_HACKS
  4134.  
  4135. const mutexParticipants = new Mutex();
  4136.  
  4137. let uvid = 0;
  4138. let r95dm = 0;
  4139. let c95dm = -1;
  4140.  
  4141. const foundMap = (base, content) => {
  4142. /*
  4143. let lastSearch = 0;
  4144. let founds = base.map(baseEntry => {
  4145. let search = content.indexOf(baseEntry, lastSearch);
  4146. if (search < 0) return false;
  4147. lastSearch = search + 1;
  4148. return true;
  4149. });
  4150. return founds;
  4151. */
  4152. const contentSet = new Set(content);
  4153. return base.map(baseEntry => contentSet.has(baseEntry));
  4154.  
  4155. }
  4156.  
  4157.  
  4158.  
  4159. let participantsForSpliceWR = null;
  4160.  
  4161. class IndexSpliceEntry {
  4162. /**
  4163. *
  4164. * @param {number} _index
  4165. * @param {number} _addedCount
  4166. * @param {any[]} _removed
  4167. */
  4168. constructor(_index, _addedCount, _removed) {
  4169. this.index = _index;
  4170. this.addedCount = _addedCount;
  4171. this.removed = _removed;
  4172. }
  4173. get __proxy312__() {
  4174. return 1
  4175. }
  4176. get type() {
  4177. return 'splice'
  4178. }
  4179. get object() {
  4180. return kRef(participantsForSpliceWR); // avoid memory leakage
  4181. }
  4182. }
  4183.  
  4184. const spliceIndicesFunc = (beforeParticipants, participants, idsBefore, idsAfter) => {
  4185.  
  4186. let foundsForAfter = foundMap(idsAfter, idsBefore);
  4187. let foundsForBefore = foundMap(idsBefore, idsAfter);
  4188.  
  4189. const nAfter = foundsForAfter.length;
  4190. const nBefore = foundsForBefore.length;
  4191.  
  4192. const indexSplices = [];
  4193. const contentUpdates = [];
  4194. participantsForSpliceWR = null;
  4195. for (let i = 0, j = 0; i < nBefore || j < nAfter;) {
  4196. if (beforeParticipants[i] === participants[j]) {
  4197. i++; j++;
  4198. } else if (idsBefore[i] === idsAfter[j]) {
  4199. // content changed
  4200. contentUpdates.push({ indexI: i, indexJ: j })
  4201. i++; j++;
  4202. } else {
  4203. let addedCount = 0;
  4204. for (let q = j; q < nAfter; q++) {
  4205. if (foundsForAfter[q] === false) addedCount++;
  4206. else break;
  4207. }
  4208. let removedCount = 0;
  4209. for (let q = i; q < nBefore; q++) {
  4210. if (foundsForBefore[q] === false) removedCount++;
  4211. else break;
  4212. }
  4213. if (!addedCount && !removedCount) {
  4214. throw 'ERROR(0xFF32): spliceIndicesFunc';
  4215. }
  4216. const entry = new IndexSpliceEntry(
  4217. j,
  4218. addedCount,
  4219. removedCount >= 1 ? beforeParticipants.slice(i, i + removedCount) : []
  4220. );
  4221. indexSplices.push(entry);
  4222. i += removedCount;
  4223. j += addedCount;
  4224. }
  4225. }
  4226. foundsForBefore = null;
  4227. foundsForAfter = null;
  4228. idsBefore = null;
  4229. idsAfter = null;
  4230. beforeParticipants = null;
  4231. participantsForSpliceWR = indexSplices.length > 0 ? mWeakRef(participants) : null;
  4232. participants = null;
  4233. return { indexSplices, contentUpdates };
  4234.  
  4235. }
  4236.  
  4237. /*
  4238.  
  4239. customElements.get("yt-live-chat-participant-renderer").prototype.notifyPath=function(){ console.log(123); console.log(new Error().stack)}
  4240.  
  4241. VM63631:1 Error
  4242. at customElements.get.notifyPath (<anonymous>:1:122)
  4243. at e.forwardRendererStamperChanges_ (live_chat_polymer.js:4453:35)
  4244. at e.rendererStamperApplyChangeRecord_ (live_chat_polymer.js:4451:12)
  4245. at e.rendererStamperObserver_ (live_chat_polymer.js:4448:149)
  4246. at Object.pu [as fn] (live_chat_polymer.js:1692:118)
  4247. at ju (live_chat_polymer.js:1674:217)
  4248. at a._propertiesChanged (live_chat_polymer.js:1726:122)
  4249. at b._flushProperties (live_chat_polymer.js:1597:200)
  4250. at a._invalidateProperties (live_chat_polymer.js:1718:69)
  4251. at a.notifyPath (live_chat_polymer.js:1741:182)
  4252.  
  4253. */
  4254.  
  4255. function convertToIds(participants) {
  4256. return participants.map(participant => {
  4257. if (!participant || typeof participant !== 'object') {
  4258. console.warn('Error(0xFA41): convertToIds', participant);
  4259. return participant; // just in case
  4260. }
  4261. let keys = Object.keys(participant);
  4262. // liveChatTextMessageRenderer
  4263. // liveChatParticipantRenderer - livestream channel owner [no authorExternalChannelId]
  4264. // liveChatPaidMessageRenderer
  4265. /*
  4266.  
  4267. 'yt-live-chat-participant-renderer' utilizes the following:
  4268. authorName.simpleText: string
  4269. authorPhoto.thumbnails: Object{url:string, width:int, height:int} []
  4270. authorBadges[].liveChatAuthorBadgeRenderer.icon.iconType: string
  4271. authorBadges[].liveChatAuthorBadgeRenderer.tooltip: string
  4272. authorBadges[].liveChatAuthorBadgeRenderer.accessibility.accessibilityData: Object{label:string}
  4273.  
  4274. */
  4275. if (keys.length !== 1) {
  4276. console.warn('Error(0xFA42): convertToIds', participant);
  4277. return participant; // just in case
  4278. }
  4279. let key = keys[0];
  4280. let renderer = (participant[key] || 0);
  4281. let authorName = (renderer.authorName || 0);
  4282. let text = `${authorName.simpleText || authorName.text}`
  4283. let res = participant; // fallback if it is not a vaild entry
  4284. if (typeof text !== 'string') {
  4285. console.warn('Error(0xFA53): convertToIds', participant);
  4286. } else {
  4287. text = `${renderer.authorExternalChannelId || 'null'}|${text || ''}`;
  4288. if (text.length > 1) res = text;
  4289. }
  4290. return res;
  4291. // return renderer?`${renderer.id}|${renderer.authorExternalChannelId}`: '';
  4292. // note: renderer.id will be changed if the user typed something to trigger the update of the participants' record.
  4293. });
  4294. }
  4295.  
  4296. const checkChangeToParticipantRendererContent = CHECK_CHANGE_TO_PARTICIPANT_RENDERER_CONTENT ? (p1, p2) => {
  4297. // just update when content is changed.
  4298. if (p1.authorName !== p2.authorName) return true;
  4299. if (p1.authorPhoto !== p2.authorPhoto) return true;
  4300. if (p1.authorBadges !== p2.authorBadges) return true;
  4301. return false;
  4302. } : (p1, p2) => {
  4303. // keep integrity all the time.
  4304. return p1 !== p2; // always true
  4305. }
  4306.  
  4307. function notifyPath7081(path) { // cnt "yt-live-chat-participant-list-renderer"
  4308.  
  4309. if (PARTICIPANT_UPDATE_ONLY_ONLY_IF_MODIFICATION_DETECTED) {
  4310. if (path !== "participantsManager.participants") {
  4311. return this.__notifyPath5036__.apply(this, arguments);
  4312. }
  4313. if (c95dm === r95dm) return;
  4314. } else {
  4315. const stack = new Error().stack;
  4316. if (path !== "participantsManager.participants" || stack.indexOf('.onParticipantsChanged') < 0) {
  4317. return this.__notifyPath5036__.apply(this, arguments);
  4318. }
  4319. }
  4320.  
  4321. if (uvid > 1e8) uvid = uvid % 100;
  4322. let tid = ++uvid;
  4323.  
  4324.  
  4325. // const cnt = this; // "yt-live-chat-participant-list-renderer"
  4326.  
  4327. const wNode = mWeakRef(this);
  4328.  
  4329. mutexParticipants.lockWith(lockResolve => {
  4330.  
  4331. const cnt = kRef(wNode);
  4332.  
  4333. const participants00 = (((cnt || 0).participantsManager || 0).participants || 0);
  4334.  
  4335. if (tid !== uvid || !cnt || typeof (participants00 || 0).splice !== 'function') {
  4336. lockResolve();
  4337. return;
  4338. }
  4339.  
  4340. let doUpdate = false;
  4341.  
  4342. if (PARTICIPANT_UPDATE_ONLY_ONLY_IF_MODIFICATION_DETECTED) {
  4343.  
  4344. if (!participants00.r94dm) {
  4345. participants00.r94dm = 1;
  4346. r95dm = (r95dm & 1073741823) + 1;
  4347. participants00.push = function () {
  4348. r95dm = (r95dm & 1073741823) + 1;
  4349. return Array.prototype.push.apply(this, arguments);
  4350. }
  4351. participants00.pop = function () {
  4352. r95dm = (r95dm & 1073741823) + 1;
  4353. return Array.prototype.pop.apply(this, arguments);
  4354. }
  4355. participants00.shift = function () {
  4356. r95dm = (r95dm & 1073741823) + 1;
  4357. return Array.prototype.shift.apply(this, arguments);
  4358. }
  4359. participants00.unshift = function () {
  4360. r95dm = (r95dm & 1073741823) + 1;
  4361. return Array.prototype.unshift.apply(this, arguments);
  4362. }
  4363. participants00.splice = function () {
  4364. r95dm = (r95dm & 1073741823) + 1;
  4365. return Array.prototype.splice.apply(this, arguments);
  4366. }
  4367. participants00.sort = function () {
  4368. r95dm = (r95dm & 1073741823) + 1;
  4369. return Array.prototype.sort.apply(this, arguments);
  4370. }
  4371. participants00.reverse = function () {
  4372. r95dm = (r95dm & 1073741823) + 1;
  4373. return Array.prototype.reverse.apply(this, arguments);
  4374. }
  4375. }
  4376.  
  4377. if (c95dm !== r95dm) {
  4378. c95dm = r95dm;
  4379. doUpdate = true;
  4380. }
  4381.  
  4382. } else {
  4383. doUpdate = true;
  4384. }
  4385.  
  4386. if (!doUpdate) {
  4387. lockResolve();
  4388. return;
  4389. }
  4390.  
  4391. const participants = participants00.slice(0);
  4392. const beforeParticipants = beforeParticipantsMap.get(cnt) || [];
  4393. beforeParticipantsMap.set(cnt, participants);
  4394.  
  4395. const resPromise = (async () => {
  4396.  
  4397. if (beforeParticipants.length === 0) {
  4398. // not error
  4399. return 0;
  4400. }
  4401.  
  4402. let countOfElements = cnt.__getAllParticipantsDOMRenderedLength__()
  4403.  
  4404. // console.log(participants.length, doms.length) // different if no requestAnimationFrame
  4405. if (beforeParticipants.length !== countOfElements) {
  4406. // there is somewrong for the cache. - sometimes happen
  4407. return 0;
  4408. }
  4409.  
  4410. const idsBefore = convertToIds(beforeParticipants);
  4411. const idsAfter = convertToIds(participants);
  4412.  
  4413. let { indexSplices, contentUpdates } = spliceIndicesFunc(beforeParticipants, participants, idsBefore, idsAfter);
  4414.  
  4415. let res = 1; // default 1 for no update
  4416.  
  4417. if (indexSplices.length >= 1) {
  4418.  
  4419.  
  4420. // let p2 = participants.slice(indexSplices[0].index, indexSplices[0].index+indexSplices[0].addedCount);
  4421. // let p1 = indexSplices[0].removed;
  4422. // console.log(indexSplices.length, indexSplices ,p1,p2, convertToIds(p1),convertToIds(p2))
  4423.  
  4424. /* folllow
  4425. a.notifyPath(c + ".splices", d);
  4426. a.notifyPath(c + ".length", b.length);
  4427. */
  4428. // stampDomArraySplices_
  4429.  
  4430.  
  4431. await new Promise(resolve => {
  4432. cnt.resolveForDOMRendering781 = resolve;
  4433.  
  4434. cnt.__notifyPath5036__("participantsManager.participants.splices", {
  4435. indexSplices
  4436. });
  4437. indexSplices = null;
  4438. participantsForSpliceWR = null;
  4439. cnt.__notifyPath5036__("participantsManager.participants.length",
  4440. participants.length
  4441. );
  4442.  
  4443. });
  4444.  
  4445. // play safe for the change of 'length'
  4446. await nextBrowserTick_();
  4447.  
  4448. countOfElements = cnt.__getAllParticipantsDOMRenderedLength__();
  4449.  
  4450. const wrongSize = participants.length !== countOfElements
  4451. if (wrongSize) {
  4452. console.warn("ERROR(0xE2C3): notifyPath7081", beforeParticipants.length, participants.length, doms.length)
  4453. return 0;
  4454. }
  4455.  
  4456. res = 2 | 4;
  4457.  
  4458. } else {
  4459.  
  4460. indexSplices = null;
  4461. participantsForSpliceWR = null;
  4462.  
  4463. if (participants.length !== countOfElements) {
  4464. // other unhandled cases
  4465. return 0;
  4466. }
  4467.  
  4468. }
  4469.  
  4470. // participants.length === countOfElements before contentUpdates
  4471. if (contentUpdates.length >= 1) {
  4472. for (const contentUpdate of contentUpdates) {
  4473. let isChanged = checkChangeToParticipantRendererContent(beforeParticipants[contentUpdate.indexI], participants[contentUpdate.indexJ]);
  4474. if (isChanged) {
  4475. cnt.__notifyPath5036__(`participantsManager.participants[${contentUpdate.indexJ}]`);
  4476. res |= 4 | 8;
  4477. }
  4478. }
  4479. }
  4480. contentUpdates = null;
  4481.  
  4482. return res;
  4483.  
  4484.  
  4485. })();
  4486.  
  4487.  
  4488. resPromise.then(async (resValue) => {
  4489. const condition = resValue === 0 ? 1 : (resValue & 4) === 4 ? 2 : 0;
  4490. const isLogRequired = SHOW_PARTICIPANT_CHANGES_IN_CONSOLE && condition > 0;
  4491. isLogRequired && groupCollapsed("Participant List Change", `tid = ${tid}; res = ${resValue}`);
  4492. if (condition === 1) {
  4493. isLogRequired && console1.log("Full Refresh begins");
  4494. await new Promise(resolve => {
  4495. cnt.resolveForDOMRendering781 = resolve;
  4496. cnt.__notifyPath5036__("participantsManager.participants"); // full refresh
  4497. });
  4498. isLogRequired && console1.log("Full Refresh ends");
  4499. } else if (condition === 2) {
  4500. isLogRequired && console1.log(`Number of participants (before): ${beforeParticipants.length}`);
  4501. isLogRequired && console1.log(`Number of participants (after): ${participants.length}`);
  4502. isLogRequired && console1.log(`Total number of rendered participants: ${cnt.__getAllParticipantsDOMRenderedLength__()}`);
  4503. isLogRequired && console1.log(`Participant Renderer Content Updated: ${(resValue & 8) === 8}`);
  4504. // requestAnimationFrame is required to avoid particiant update during DOM changing (stampDomArraySplices_)
  4505. // mutex lock with requestAnimationFrame can also disable participants update in background
  4506. }
  4507. isLogRequired && groupEnd();
  4508. (condition === 2) && (await new Promise(requestAnimationFrame));
  4509. lockResolve();
  4510. });
  4511.  
  4512. });
  4513.  
  4514. }
  4515.  
  4516. return { notifyPath7081 };
  4517.  
  4518. })();
  4519.  
  4520. const whenDefinedMultiple = async (tags) => {
  4521.  
  4522. const sTags = [...new Set(tags)];
  4523. const len = sTags.length;
  4524.  
  4525. const pTags = new Array(len);
  4526. for (let i = 0; i < len; i++) {
  4527. pTags[i] = customElements.whenDefined(sTags[i]);
  4528. }
  4529.  
  4530. await Promise.all(pTags);
  4531. pTags.length = 0;
  4532.  
  4533. return sTags;
  4534.  
  4535. }
  4536.  
  4537. const onRegistryReadyForDataManipulation = () => {
  4538.  
  4539. function dummy5035(a, b, c) { }
  4540. function dummy411(a, b, c) { }
  4541.  
  4542.  
  4543.  
  4544. customElements.whenDefined("yt-live-chat-participant-list-renderer").then(() => {
  4545.  
  4546. if (!DO_PARTICIPANT_LIST_HACKS) return;
  4547.  
  4548. const tag = "yt-live-chat-participant-list-renderer";
  4549. const cProto = getProto(document.createElement(tag));
  4550. if (!cProto || typeof cProto.attached !== 'function') {
  4551. // for _registered, proto.attached shall exist when the element is defined.
  4552. // for controller extraction, attached shall exist when instance creates.
  4553. console.warn(`proto.attached for ${tag} is unavailable.`);
  4554. return;
  4555. }
  4556.  
  4557.  
  4558. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-participant-list-renderer hacks");
  4559.  
  4560. 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'];
  4561. const fgs = {};
  4562. for (const key of fgsArr) fgs[key] = undefined;
  4563.  
  4564. try {
  4565. const EXPERIMENT_FLAGS = ytcfg.data_.EXPERIMENT_FLAGS;
  4566. for (const key of fgsArr) fgs[key] = EXPERIMENT_FLAGS[key];
  4567. } catch (e) { }
  4568. console1.log(`EXPERIMENT_FLAGS: ${JSON.stringify(fgs, null, 2)}`);
  4569.  
  4570. const canDoReplacement = (() => {
  4571. if (typeof cProto.__notifyPath5035__ === 'function' && cProto.__notifyPath5035__.name !== 'dummy5035') {
  4572. console.warn('YouTube Live Chat Tamer is running.');
  4573. return;
  4574. }
  4575.  
  4576. if (typeof cProto.__attached411__ === 'function' && cProto.__attached411__.name !== 'dummy411') {
  4577. console.warn('YouTube Live Chat Tamer is running.');
  4578. return;
  4579. }
  4580.  
  4581. cProto.__notifyPath5035__ = dummy5035 // just to against Live Chat Tamer
  4582. cProto.__attached411__ = dummy411 // just to against Live Chat Tamer
  4583.  
  4584. if (typeof cProto.flushRenderStamperComponentBindings_ !== 'function' || cProto.flushRenderStamperComponentBindings_.length !== 0) {
  4585. console.warn("ERROR(0xE355): cProto.flushRenderStamperComponentBindings_ not found");
  4586. return;
  4587. }
  4588.  
  4589. if (typeof cProto.flushRenderStamperComponentBindings66_ === 'function') {
  4590. console.warn("ERROR(0xE356): cProto.flushRenderStamperComponentBindings66_");
  4591. return;
  4592. }
  4593.  
  4594. if (typeof cProto.__getAllParticipantsDOMRenderedLength__ === 'function') {
  4595. console.warn("ERROR(0xE357): cProto.__getAllParticipantsDOMRenderedLength__");
  4596. return;
  4597. }
  4598. return true;
  4599. })();
  4600.  
  4601. console1.log(`Data Manipulation Boost = ${canDoReplacement}`);
  4602.  
  4603. assertor(() => fnIntegrity(cProto.attached, '0.32.22')) // just warning
  4604. if (typeof cProto.flushRenderStamperComponentBindings_ === 'function') {
  4605. const fiRSCB = fnIntegrity(cProto.flushRenderStamperComponentBindings_);
  4606. console1.log(`flushRenderStamperComponentBindings_ ### ${fiRSCB} ###`);
  4607. } else {
  4608. console1.log("flushRenderStamperComponentBindings_ - not found");
  4609. }
  4610. // assertor(() => fnIntegrity(cProto.flushRenderStamperComponentBindings_, '0.386.233')) // just warning
  4611.  
  4612. if (typeof cProto.flushRenderStamperComponentBindings_ === 'function') {
  4613. cProto.flushRenderStamperComponentBindings66_ = cProto.flushRenderStamperComponentBindings_;
  4614. cProto.flushRenderStamperComponentBindings_ = function () {
  4615. // console.log('flushRenderStamperComponentBindings_')
  4616. this.flushRenderStamperComponentBindings66_();
  4617. if (this.resolveForDOMRendering781) {
  4618. this.resolveForDOMRendering781();
  4619. this.resolveForDOMRendering781 = null;
  4620. }
  4621. };
  4622. }
  4623.  
  4624. cProto.__getAllParticipantsDOMRenderedLength__ = function () {
  4625. const container = ((this || 0).$ || 0).participants;
  4626. if (!container) return 0;
  4627. return HTMLElement_.prototype.querySelectorAll.call(container, 'yt-live-chat-participant-renderer').length;
  4628. }
  4629.  
  4630. const onPageElements = [...document.querySelectorAll('yt-live-chat-participant-list-renderer:not(.n9fJ3)')];
  4631.  
  4632. cProto.__attached412__ = cProto.attached;
  4633. const fpPList = function (hostElement) {
  4634. const cnt = insp(hostElement);
  4635. if (beforeParticipantsMap.has(cnt)) return;
  4636. hostElement.classList.add('n9fJ3');
  4637.  
  4638. assertor(() => (cnt.__dataEnabled === true && cnt.__dataReady === true));
  4639. if (typeof cnt.notifyPath !== 'function' || typeof cnt.__notifyPath5036__ !== 'undefined') {
  4640. console.warn("ERROR(0xE318): yt-live-chat-participant-list-renderer")
  4641. return;
  4642. }
  4643.  
  4644. groupCollapsed("Participant List attached", "");
  4645. cnt.__notifyPath5036__ = cnt.notifyPath
  4646. const participants = ((cnt.participantsManager || 0).participants || 0);
  4647. assertor(() => (participants.length > -1 && typeof participants.slice === 'function'));
  4648. console1.log(`initial number of participants: ${participants.length}`);
  4649. const newParticipants = (participants.length >= 1 && typeof participants.slice === 'function') ? participants.slice(0) : [];
  4650. beforeParticipantsMap.set(cnt, newParticipants);
  4651. cnt.notifyPath = notifyPath7081;
  4652. console1.log(`CHECK_CHANGE_TO_PARTICIPANT_RENDERER_CONTENT = ${CHECK_CHANGE_TO_PARTICIPANT_RENDERER_CONTENT}`);
  4653. groupEnd();
  4654. }
  4655. cProto.attached = function () {
  4656. fpPList(this.hostElement || this);
  4657. this.__attached412__.apply(this, arguments);
  4658. };
  4659.  
  4660.  
  4661. if (ENABLE_FLAGS_MAINTAIN_STABLE_LIST_FOR_PARTICIPANTS_LIST) {
  4662.  
  4663. /** @type {boolean | (()=>boolean)} */
  4664. let toUseMaintainStableList = USE_MAINTAIN_STABLE_LIST_ONLY_WHEN_KS_FLAG_IS_SET ? (() => ytcfg.data_.EXPERIMENT_FLAGS.kevlar_should_maintain_stable_list === true) : true;
  4665. if (typeof cProto.stampDomArray_ === 'function' && cProto.stampDomArray_.length === 6 && !cProto.stampDomArray_.nIegT && !cProto.stampDomArray66_) {
  4666.  
  4667. let lastMessageDate = 0;
  4668. cProto.stampDomArray66_ = cProto.stampDomArray_;
  4669.  
  4670. cProto.stampDomArray_ = function (...args) {
  4671. if (args[0] && args[0].length > 0 && args[1] === "participants" && args[2] && args[3] === true && !args[5]) {
  4672. if (typeof toUseMaintainStableList === 'function') {
  4673. toUseMaintainStableList = toUseMaintainStableList();
  4674. }
  4675. args[5] = toUseMaintainStableList;
  4676. let currentDate = Date.now();
  4677. if (currentDate - lastMessageDate > 440) {
  4678. lastMessageDate = currentDate;
  4679. console.log('maintain_stable_list for participants list', toUseMaintainStableList);
  4680. }
  4681. }
  4682. return this.stampDomArray66_.apply(this, args);
  4683. }
  4684.  
  4685. cProto.stampDomArray_.nIegT = 1;
  4686.  
  4687. }
  4688. console1.log(`ENABLE_FLAGS_MAINTAIN_STABLE_LIST_FOR_PARTICIPANTS_LIST - OK`);
  4689. } else {
  4690. console1.log(`ENABLE_FLAGS_MAINTAIN_STABLE_LIST_FOR_PARTICIPANTS_LIST - NG`);
  4691. }
  4692.  
  4693. groupEnd();
  4694.  
  4695. if (onPageElements.length >= 1) {
  4696. for (const s of onPageElements) {
  4697. if (insp(s).isAttached === true) {
  4698. fpPList(s);
  4699. }
  4700. }
  4701. }
  4702.  
  4703. }).catch(console.warn);
  4704.  
  4705. };
  4706.  
  4707. if (DO_PARTICIPANT_LIST_HACKS) {
  4708. promiseForCustomYtElementsReady.then(onRegistryReadyForDataManipulation);
  4709. }
  4710.  
  4711.  
  4712.  
  4713. const rafHub = (ENABLE_RAF_HACK_TICKERS || ENABLE_RAF_HACK_DOCKED_MESSAGE || ENABLE_RAF_HACK_INPUT_RENDERER || ENABLE_RAF_HACK_EMOJI_PICKER) ? new RAFHub() : null;
  4714.  
  4715. const transitionEndHooks = new WeakSet();
  4716. const transitionEndAfterFnSimple = new WeakMap();
  4717. let transitionEndAfterFnSimpleEnable = 0;
  4718. // let prevTransitionClosing = null;
  4719.  
  4720. const passiveCapture = typeof IntersectionObserver === 'function' ? { capture: true, passive: true } : true;
  4721.  
  4722.  
  4723. const transitionEndAfterFn = (evt) => {
  4724. if (transitionEndAfterFnSimpleEnable > 0 && evt.propertyName && !evt.pseudoElement) {
  4725. const elm = evt.target;
  4726. const f = transitionEndAfterFnSimple.get(elm);
  4727. if (f) {
  4728. transitionEndAfterFnSimple.delete(elm);
  4729. f.resolve(evt.propertyName);
  4730. }
  4731. }
  4732. };
  4733.  
  4734. const fixChildrenIssue = !!fixChildrenIssue801;
  4735. if (fixChildrenIssue && typeof Object.getOwnPropertyDescriptor === 'function' && typeof Proxy !== 'undefined') {
  4736. let fixChildrenIssue_status = false;
  4737. const divProto = HTMLDivElement.prototype;
  4738. const polymerControllerSetData3 = function (c, d, e) {
  4739. return insp(this).set(c, d, e);
  4740. }
  4741. const polymerControllerSetData2 = function (c, d) {
  4742. return insp(this).set(c, d);
  4743. }
  4744. const dummyFn = function () {
  4745. console.log('dummyFn', ...arguments);
  4746. };
  4747.  
  4748. const wm44 = new Map();
  4749. function unPolymerSet(elem) {
  4750. const is = elem.is;
  4751. if (is && !elem.set) {
  4752. let rt = wm44.get(is);
  4753. if (!rt) {
  4754. rt = 1;
  4755. const cnt = insp(elem);
  4756. if (cnt !== elem && cnt && typeof cnt.set === 'function') {
  4757. const pcSet = cnt.constructor.prototype.set;
  4758. if (pcSet && typeof pcSet === 'function' && pcSet.length === 3) {
  4759. rt = polymerControllerSetData3;
  4760. } else if (pcSet && typeof pcSet === 'function' && pcSet.length === 2) {
  4761. rt = polymerControllerSetData2;
  4762. }
  4763. }
  4764. wm44.set(is, rt);
  4765. }
  4766. if (typeof rt === 'function') {
  4767. elem.set = rt;
  4768. } else {
  4769. elem.set = dummyFn;
  4770. }
  4771. }
  4772. }
  4773. if (!divProto.__children577__ && !divProto.__children578__) {
  4774.  
  4775. const dp = Object.getOwnPropertyDescriptor(Element.prototype, 'children');
  4776. const dp2 = Object.getOwnPropertyDescriptor(HTMLElement_.prototype, 'children');
  4777. const dp3 = Object.getOwnPropertyDescriptor(divProto, 'children');
  4778.  
  4779. if (dp && dp.configurable === true && dp.enumerable === true && typeof dp.get === 'function' && !dp2 && !dp3) {
  4780.  
  4781. if (divProto instanceof HTMLElement_ && divProto instanceof Element) {
  4782.  
  4783. let m = Object.assign({}, dp);
  4784. divProto.__children577__ = dp.get;
  4785. divProto.__children578__ = function () {
  4786. if (this.__children803__) return this.__children803__;
  4787. if (this.__children801__) {
  4788. let arr = [];
  4789. for (let elem = this.firstElementChild; elem !== null; elem = elem.nextElementSibling) {
  4790. if (elem.is) {
  4791. unPolymerSet(elem);
  4792. arr.push(elem);
  4793. }
  4794. }
  4795. if (this.__children801__ === 2) this.__children803__ = arr;
  4796. return arr;
  4797. }
  4798. return 577;
  4799. };
  4800. m.get = function () {
  4801. const r = this.__children578__();
  4802. if (r !== 577) return r;
  4803. return this.__children577__();
  4804. };
  4805. Object.defineProperty(divProto, 'children', m);
  4806.  
  4807. fixChildrenIssue_status = true;
  4808.  
  4809. }
  4810. }
  4811.  
  4812. }
  4813.  
  4814. if (!fixChildrenIssue_status) {
  4815. console.log('fixChildrenIssue - set NG')
  4816. }
  4817.  
  4818.  
  4819. }
  4820.  
  4821.  
  4822. const watchUserCSS = () => {
  4823.  
  4824. // if (!CSS.supports('contain-intrinsic-size', 'auto var(--wsr94)')) return;
  4825.  
  4826. const getElemFromWR = (nr) => {
  4827. const n = kRef(nr);
  4828. if (n && n.isConnected) return n;
  4829. return null;
  4830. }
  4831.  
  4832. const clearContentVisibilitySizing = () => {
  4833. Promise.resolve().then(() => {
  4834.  
  4835. const e = document.querySelector('#show-more[disabled]');
  4836. let btnShowMoreWR = e ? mWeakRef(e) : null;
  4837.  
  4838. let lastVisibleItemWR = null;
  4839. for (const elm of document.querySelectorAll('[wsr93]')) {
  4840. if (elm.getAttribute('wsr93') === 'visible') lastVisibleItemWR = mWeakRef(elm);
  4841. elm.setAttribute('wsr93', '');
  4842. // custom CSS property --wsr94 not working when attribute wsr93 removed
  4843. }
  4844. foregroundPromiseFn().then(() => {
  4845. const btnShowMore = getElemFromWR(btnShowMoreWR); btnShowMoreWR = null;
  4846. if (btnShowMore) btnShowMore.click();
  4847. else {
  4848. // would not work if switch it frequently
  4849. const lastVisibleItem = getElemFromWR(lastVisibleItemWR); lastVisibleItemWR = null;
  4850. if (lastVisibleItem) {
  4851.  
  4852. Promise.resolve()
  4853. .then(() => lastVisibleItem.scrollIntoView())
  4854. .then(() => lastVisibleItem.scrollIntoView(false))
  4855. .then(() => lastVisibleItem.scrollIntoView({ behavior: "instant", block: "end", inline: "nearest" }))
  4856. .catch(e => { }) // break the chain when method not callable
  4857.  
  4858. }
  4859. }
  4860. });
  4861.  
  4862. }).catch(console.warn);
  4863.  
  4864. }
  4865.  
  4866. const mutObserver = new MutationObserver((mutations) => {
  4867. for (const mutation of mutations) {
  4868. if ((mutation.addedNodes || 0).length >= 1) {
  4869. for (const addedNode of mutation.addedNodes) {
  4870. if (addedNode.nodeName === 'STYLE') {
  4871. clearContentVisibilitySizing();
  4872. return;
  4873. }
  4874. }
  4875. }
  4876. if ((mutation.removedNodes || 0).length >= 1) {
  4877. for (const removedNode of mutation.removedNodes) {
  4878. if (removedNode.nodeName === 'STYLE') {
  4879. clearContentVisibilitySizing();
  4880. return;
  4881. }
  4882. }
  4883. }
  4884. }
  4885. });
  4886.  
  4887. mutObserver.observe(document.documentElement, {
  4888. childList: true,
  4889. subtree: false
  4890. });
  4891. mutObserver.observe(document.head, {
  4892. childList: true,
  4893. subtree: false
  4894. });
  4895. mutObserver.observe(document.body, {
  4896. childList: true,
  4897. subtree: false
  4898. });
  4899.  
  4900. }
  4901.  
  4902.  
  4903. const { lcRendererElm, visObserver } = (() => {
  4904.  
  4905. let lcRendererWR = null;
  4906.  
  4907. const lcRendererElm = () => {
  4908. let lcRenderer = kRef(lcRendererWR);
  4909. if (!lcRenderer || !lcRenderer.isConnected) {
  4910. lcRenderer = document.querySelector('yt-live-chat-item-list-renderer.yt-live-chat-renderer');
  4911. lcRendererWR = lcRenderer ? mWeakRef(lcRenderer) : null;
  4912. }
  4913. return lcRenderer;
  4914. };
  4915.  
  4916.  
  4917. let hasFirstShowMore = false;
  4918. // let lastVisible = null;
  4919.  
  4920. const visObserverFn = (entry) => {
  4921.  
  4922. const target = entry.target;
  4923. if (!target || !target.hasAttribute('wsr93')) return;
  4924. // if(target.classList.contains('dont-render')) return;
  4925. let isVisible = entry.isIntersecting === true && entry.intersectionRatio > 0.5;
  4926. // const h = entry.boundingClientRect.height;
  4927. /*
  4928. if (h < 16) { // wrong: 8 (padding/margin); standard: 32; test: 16 or 20
  4929. // e.g. under fullscreen. the element created but not rendered.
  4930. target.setAttribute('wsr93', '');
  4931. return;
  4932. }
  4933. */
  4934. if (isVisible) {
  4935. // target.style.setProperty('--wsr94', h + 'px');
  4936. target.setAttribute('wsr93', 'visible');
  4937. // lastVisible = mWeakRef(target);
  4938. if (nNextElem(target) === null) {
  4939.  
  4940. // firstVisibleItemDetected = true;
  4941. /*
  4942. if (dateNow() - lastScroll < 80) {
  4943. lastLShow = 0;
  4944. lastScroll = 0;
  4945. Promise.resolve().then(clickShowMore);
  4946. } else {
  4947. lastLShow = dateNow();
  4948. }
  4949. */
  4950. // lastLShow = dateNow();
  4951. } else if (!hasFirstShowMore) { // should more than one item being visible
  4952. // implement inside visObserver to ensure there is sufficient delay
  4953. hasFirstShowMore = true;
  4954. // foregroundPromiseFn().then(() => {
  4955. // // foreground page
  4956. // // page visibly ready -> load the latest comments at initial loading
  4957. // const lcRenderer = lcRendererElm();
  4958. // if (lcRenderer) {
  4959. // nextBrowserTick_(() => {
  4960. // const cnt = insp(lcRenderer);
  4961. // if (cnt.isAttached === false || (cnt.hostElement || cnt).isConnected === false) return;
  4962. // cnt.scrollToBottom_();
  4963. // });
  4964. // }
  4965. // });
  4966. }
  4967. }
  4968. else if (target.getAttribute('wsr93') === 'visible') { // ignore target.getAttribute('wsr93') === '' to avoid wrong sizing
  4969.  
  4970. // target.style.setProperty('--wsr94', h + 'px');
  4971. target.setAttribute('wsr93', 'hidden');
  4972. } // note: might consider 0 < entry.intersectionRatio < 0.5 and target.getAttribute('wsr93') === '' <new last item>
  4973.  
  4974. }
  4975.  
  4976.  
  4977.  
  4978. const visObserver = new IntersectionObserver((entries) => {
  4979.  
  4980. for (const entry of entries) {
  4981.  
  4982. Promise.resolve(entry).then(visObserverFn);
  4983.  
  4984. }
  4985.  
  4986. }, {
  4987. rootMargin: "0px",
  4988. threshold: [0.05, 0.95],
  4989. });
  4990.  
  4991.  
  4992. return { lcRendererElm, visObserver }
  4993.  
  4994.  
  4995. })();
  4996.  
  4997. // let itemsResizeObserverAttached = false;
  4998. // const resizeObserverFallback = new IntersectionObserver((mutation, observer) => {
  4999. // const itemScroller = mutation[0].target;
  5000. // observer.unobserve(itemScroller);
  5001. // if (itemScroller.scrollTop === 0) itemScroller.scrollTop = window.screen.height; // scrollTop changing
  5002. // });
  5003.  
  5004. const itemScrollerResizeObserver = typeof ResizeObserver === 'function' && ENABLE_OVERFLOW_ANCHOR ? new ResizeObserver((mutations) => {
  5005. const mutation = mutations[mutations.length - 1];
  5006. // console.log('resizeObserver', mutation)
  5007. const itemScroller = (mutation || 0).target;
  5008. if (!itemScroller) return;
  5009. const listDom = itemScroller.closest('yt-live-chat-item-list-renderer');
  5010. if (!listDom) return;
  5011. const listCnt = insp(listDom);
  5012. if(listCnt.visibleItems.length === 0) return;
  5013. if (listCnt.atBottom !== true) return;
  5014. // if (itemScroller.scrollTop === 0) {
  5015. itemScroller.scrollTop = 16777216; // scrollTop changing
  5016. // }
  5017. }) : null;
  5018.  
  5019. const { setupMutObserver } = (() => {
  5020.  
  5021.  
  5022. const mutFn = (items) => {
  5023. let seqIndex = -1;
  5024. const elementSet = new Set();
  5025. for (let node = nLastElem(items); node !== null; node = nPrevElem(node)) { // from bottom
  5026. let found = node.hasAttribute('wsr93') ? (node.hasAttribute('yt-chat-item-seq') ? 2 : 1) : 0;
  5027. if (found === 1) node.removeAttribute('wsr93'); // reuse -> wsr93: hidden after re-attach
  5028. if (found === 2) {
  5029. seqIndex = parseInt(node.getAttribute('yt-chat-item-seq'), 10);
  5030. break;
  5031. }
  5032. visObserver.unobserve(node); // reuse case
  5033. node.setAttribute('wsr93', '');
  5034. visObserver.observe(node);
  5035. elementSet.add(node);
  5036. }
  5037. let iter = elementSet.values();
  5038. let i = seqIndex + elementSet.size;
  5039. for (let curr; curr = iter.next().value;) { // from bottom
  5040. curr.setAttribute('yt-chat-item-seq', i % 60);
  5041. curr.classList.add('yt-chat-item-' + ((i % 2) ? 'odd' : 'even'));
  5042. i--;
  5043. }
  5044. iter = null;
  5045. elementSet.clear();
  5046. }
  5047.  
  5048. // const itemsResizeObserver = typeof ResizeObserver === 'function' && 0 ? new ResizeObserver((mutations) => {
  5049. // const mutation = mutations[mutations.length - 1];
  5050. // // console.log('resizeObserver', mutation)
  5051. // const items = (mutation || 0).target;
  5052. // if (!items) return;
  5053. // const listDom = items.closest('yt-live-chat-item-list-renderer');
  5054. // if (!listDom) return;
  5055. // const listCnt = insp(listDom);
  5056. // if (listCnt.atBottom !== true) return;
  5057. // const itemScroller = listCnt.itemScroller || listCnt.$['item-scroller'] || listCnt.querySelector('#item-scroller') || 0;
  5058. // // if (itemScroller.scrollTop === 0) {
  5059. // itemScroller.scrollTop = mutation.contentRect.height; // scrollTop changing
  5060. // // }
  5061. // }) : null;
  5062. // itemsResizeObserverAttached = itemsResizeObserver !== null;
  5063.  
  5064. const mutObserver = new MutationObserver((mutations) => {
  5065. const items = (mutations[0] || 0).target;
  5066. if (!items) return;
  5067. mutFn(items);
  5068. });
  5069.  
  5070. const setupMutObserver = (items) => {
  5071. scrollChatFn = null;
  5072. mutObserver.disconnect();
  5073. mutObserver.takeRecords();
  5074. if (items) {
  5075. if (typeof items.__appendChild932__ === 'function') {
  5076. if (typeof items.appendChild === 'function') items.appendChild = items.__appendChild932__;
  5077. if (typeof items.__shady_native_appendChild === 'function') items.__shady_native_appendChild = items.__appendChild932__;
  5078. }
  5079. mutObserver.observe(items, {
  5080. childList: true,
  5081. subtree: false
  5082. });
  5083. mutFn(items);
  5084.  
  5085.  
  5086. // if (itemsResizeObserver) itemsResizeObserver.observe(items);
  5087.  
  5088. // const isFirstList = firstList;
  5089. // firstList = false;
  5090.  
  5091.  
  5092. if (items && items.nextElementSibling === null) {
  5093. items.parentNode.appendChild(dr(document.createElement('item-anchor')));
  5094. WITH_SCROLL_ANCHOR = true;
  5095. if (ENABLE_OVERFLOW_ANCHOR) {
  5096. items.classList.add('no-anchor');
  5097. nodeParent(items).classList.add('no-anchor'); // required
  5098. }
  5099. }
  5100.  
  5101.  
  5102.  
  5103.  
  5104. if (ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX) {
  5105.  
  5106. (() => {
  5107.  
  5108. const tag = 'yt-iframed-player-events-relay'
  5109. const dummy = document.createElement(tag);
  5110.  
  5111. const cProto = getProto(dummy);
  5112. if (!cProto || !cProto.handlePostMessage_) {
  5113. console.warn(`proto.handlePostMessage_ for ${tag} is unavailable.`);
  5114. return;
  5115. }
  5116.  
  5117. if (typeof cProto.handlePostMessage_ === 'function' && !cProto.handlePostMessage66_ && !cProto.handlePostMessage67_ ) {
  5118.  
  5119. cProto.handlePostMessage66_ = cProto.handlePostMessage_;
  5120.  
  5121. const handlePostMessageAfterPromiseA = (da) => {
  5122.  
  5123. if (!da || typeof da !== 'object') return;
  5124.  
  5125. if ('yt-player-state-change' in da) {
  5126.  
  5127. const qc = da['yt-player-state-change'];
  5128.  
  5129.  
  5130. let isQcChanged = false;
  5131.  
  5132. if (qc === 2) { isQcChanged = qc !== _playerState; _playerState = 2; relayCount = 0; } // paused
  5133. else if (qc === 3) { isQcChanged = qc !== _playerState; _playerState = 3; } // playing
  5134. else if (qc === 1) { isQcChanged = qc !== _playerState; _playerState = 1; } // playing
  5135.  
  5136.  
  5137. if ((isQcChanged) && playerState !== _playerState) {
  5138. playerEventsByIframeRelay = true;
  5139. onPlayStateChangePromise = new Promise((resolve) => {
  5140. const k = _playerState;
  5141. foregroundPromiseFn().then(() => {
  5142. if (k === _playerState && playerState !== _playerState) playerState = _playerState;
  5143. onPlayStateChangePromise = null;
  5144. resolve();
  5145. })
  5146. }).catch(console.warn);
  5147.  
  5148. }
  5149.  
  5150. } else if ('yt-player-video-progress' in da) {
  5151. const vp = da['yt-player-video-progress'];
  5152.  
  5153.  
  5154. relayCount++;
  5155. lastPlayerProgress = vp > 0 ? vp : 0; // no use ?
  5156.  
  5157.  
  5158. if (relayPromise && vp > 0 && relayCount >= 2) {
  5159. if (onPlayStateChangePromise) {
  5160. onPlayStateChangePromise.then(() => {
  5161. relayPromise && relayPromise.resolve();
  5162. relayPromise = null;
  5163. })
  5164. } else {
  5165. relayPromise.resolve();
  5166. relayPromise = null;
  5167. }
  5168. }
  5169.  
  5170. }
  5171.  
  5172. };
  5173.  
  5174. cProto.handlePostMessage67_ = function (a) {
  5175.  
  5176. let da = a.data;
  5177. const wNode = mWeakRef(this);
  5178. // const wData = mWeakRef(da);
  5179.  
  5180. playEventsStack = playEventsStack.then(() => {
  5181.  
  5182. const cnt = kRef(wNode);
  5183. // const da = kRef(wData);
  5184.  
  5185. if (!cnt || !a || !da) return;
  5186. handlePostMessageAfterPromiseA(da);
  5187. da = null;
  5188.  
  5189. const r = cnt.handlePostMessage66_(a);
  5190. a = null;
  5191.  
  5192. }).catch(console.warn);
  5193.  
  5194. }
  5195.  
  5196. const handlePostMessageAfterPromiseB = (da) => {
  5197.  
  5198. const lcr = document.querySelector('yt-live-chat-renderer');
  5199. const psc = document.querySelector("yt-player-seek-continuation");
  5200. if (lcr && psc && lcr.replayBuffer_) {
  5201.  
  5202. const rbProgress = lcr.replayBuffer_.lastVideoOffsetTimeMsec;
  5203. const daProgress = da['yt-player-video-progress'] * 1000
  5204. // document.querySelector('yt-live-chat-renderer').playerProgressChanged_(1e-5);
  5205.  
  5206. const front_ = (lcr.replayBuffer_.replayQueue || 0).front_;
  5207. const back_ = (lcr.replayBuffer_.replayQueue || 0).back_;
  5208.  
  5209. // console.log(deepCopy( front_))
  5210. // console.log(deepCopy( back_))
  5211. // console.log(rbProgress, daProgress, )
  5212. if (front_ && back_ && rbProgress > daProgress && back_.length > 2 && back_.some(e => e && +e.videoOffsetTimeMsec > daProgress) && back_.some(e => e && +e.videoOffsetTimeMsec < daProgress)) {
  5213. // no action
  5214. // console.log('ss1')
  5215. } else if (rbProgress < daProgress + 3400 && rbProgress > daProgress - 1200) {
  5216. // daProgress - 1200 < rbProgress < daProgress + 3400
  5217. // console.log('ss2')
  5218. } else {
  5219.  
  5220. lcr.previousProgressSec = 1E-5;
  5221. // lcr._setIsSeeking(!0),
  5222. lcr.replayBuffer_.clear()
  5223. psc.fireSeekContinuation_(da['yt-player-video-progress']);
  5224. }
  5225.  
  5226. }
  5227.  
  5228.  
  5229. };
  5230.  
  5231. cProto.handlePostMessage_ = function (a) {
  5232.  
  5233. let da = (a || 0).data || 0;
  5234. const wNode = mWeakRef(this);
  5235.  
  5236. if (typeof da !== 'object') return;
  5237.  
  5238. if (waitForInitialDataCompletion === 1) return;
  5239.  
  5240. if (!isPlayProgressTriggered) {
  5241. isPlayProgressTriggered = true; // set once
  5242.  
  5243. if ('yt-player-video-progress' in da) {
  5244. waitForInitialDataCompletion = 1;
  5245.  
  5246. const wrapWith = (data) => {
  5247. const { origin } = a;
  5248. return {
  5249. origin,
  5250. data
  5251. };
  5252. }
  5253.  
  5254. this.handlePostMessage67_(wrapWith({
  5255. "yt-iframed-parent-ready": true
  5256. }));
  5257.  
  5258.  
  5259. playEventsStack = playEventsStack.then(() => {
  5260.  
  5261. const cnt = kRef(wNode);
  5262.  
  5263. if (!cnt || !a || !da) return;
  5264.  
  5265. handlePostMessageAfterPromiseB(da);
  5266. da = null;
  5267.  
  5268. waitForInitialDataCompletion = 2;
  5269.  
  5270. const r = cnt.handlePostMessage_(a); // isPlayProgressTriggered is set
  5271. a = null;
  5272.  
  5273. }).catch(console.warn);
  5274.  
  5275. return;
  5276.  
  5277. }
  5278.  
  5279. }
  5280.  
  5281. this.handlePostMessage67_(a);
  5282.  
  5283. }
  5284.  
  5285. }
  5286.  
  5287.  
  5288. })();
  5289.  
  5290. }
  5291.  
  5292.  
  5293. }
  5294. }
  5295.  
  5296. return { setupMutObserver };
  5297.  
  5298.  
  5299.  
  5300. })();
  5301.  
  5302. const setupEvents = () => {
  5303. // not called when boost chat is enabled
  5304.  
  5305. // global - currentMouseDown, lastUserInteraction
  5306.  
  5307. let scrollCount = 0;
  5308. let lastScrollCount = -1;
  5309. let lastMouseDown = 0;
  5310.  
  5311. const passiveCapture = typeof IntersectionObserver === 'function' ? { capture: true, passive: true } : true;
  5312.  
  5313. // const delayFlushActiveItemsAfterUserActionK_ = () => {
  5314.  
  5315. // const lcRenderer = lcRendererElm();
  5316. // if (lcRenderer) {
  5317. // const cnt = insp(lcRenderer);
  5318. // if (!cnt.hasUserJustInteracted11_) return;
  5319. // if (cnt.atBottom && cnt.allowScroll && cnt.activeItems_.length >= 1 && cnt.hasUserJustInteracted11_()) {
  5320. // cnt.delayFlushActiveItemsAfterUserAction11_ && cnt.delayFlushActiveItemsAfterUserAction11_();
  5321. // }
  5322. // }
  5323.  
  5324. // }
  5325.  
  5326. const delayFlushActiveItemsAfterUserActionK_ = null;
  5327.  
  5328. document.addEventListener('scroll', (evt) => {
  5329. if (!evt || !evt.isTrusted) return;
  5330. // lastScroll = dateNow();
  5331. scrollCount = (scrollCount & 1073741823) + 1;
  5332. }, passiveCapture); // support contain => support passive
  5333.  
  5334. document.addEventListener('wheel', (evt) => {
  5335. if (!evt || !evt.isTrusted) return;
  5336. if (lastScrollCount === scrollCount) return;
  5337. lastScrollCount = scrollCount;
  5338. lastWheel = dateNow();
  5339. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5340. }, passiveCapture); // support contain => support passive
  5341.  
  5342. document.addEventListener('mousedown', (evt) => {
  5343. if (!evt || !evt.isTrusted) return;
  5344. if (((evt || 0).target || 0).id !== 'item-scroller') return;
  5345. lastMouseDown = dateNow();
  5346. currentMouseDown = true;
  5347. lastUserInteraction = lastMouseDown;
  5348. }, passiveCapture);
  5349.  
  5350. document.addEventListener('pointerdown', (evt) => {
  5351. if (!evt || !evt.isTrusted) return;
  5352. if (((evt || 0).target || 0).id !== 'item-scroller') return;
  5353. lastMouseDown = dateNow();
  5354. currentMouseDown = true;
  5355. lastUserInteraction = lastMouseDown;
  5356. }, passiveCapture);
  5357.  
  5358. document.addEventListener('click', (evt) => {
  5359. if (!evt || !evt.isTrusted) return;
  5360. if (((evt || 0).target || 0).id !== 'item-scroller') return;
  5361. lastMouseDown = lastMouseUp = dateNow();
  5362. currentMouseDown = false;
  5363. lastUserInteraction = lastMouseDown;
  5364. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5365. }, passiveCapture);
  5366.  
  5367. document.addEventListener('tap', (evt) => {
  5368. if (!evt || !evt.isTrusted) return;
  5369. if (((evt || 0).target || 0).id !== 'item-scroller') return;
  5370. lastMouseDown = lastMouseUp = dateNow();
  5371. currentMouseDown = false;
  5372. lastUserInteraction = lastMouseDown;
  5373. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5374. }, passiveCapture);
  5375.  
  5376.  
  5377. document.addEventListener('mouseup', (evt) => {
  5378. if (!evt || !evt.isTrusted) return;
  5379. if (currentMouseDown) {
  5380. lastMouseUp = dateNow();
  5381. currentMouseDown = false;
  5382. lastUserInteraction = lastMouseUp;
  5383. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5384. }
  5385. }, passiveCapture);
  5386.  
  5387.  
  5388. document.addEventListener('pointerup', (evt) => {
  5389. if (!evt || !evt.isTrusted) return;
  5390. if (currentMouseDown) {
  5391. lastMouseUp = dateNow();
  5392. currentMouseDown = false;
  5393. lastUserInteraction = lastMouseUp;
  5394. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5395. }
  5396. }, passiveCapture);
  5397.  
  5398. document.addEventListener('touchstart', (evt) => {
  5399. if (!evt || !evt.isTrusted) return;
  5400. lastTouchDown = dateNow();
  5401. currentTouchDown = true;
  5402. lastUserInteraction = lastTouchDown;
  5403. }, passiveCapture);
  5404.  
  5405. document.addEventListener('touchmove', (evt) => {
  5406. if (!evt || !evt.isTrusted) return;
  5407. lastTouchDown = dateNow();
  5408. currentTouchDown = true;
  5409. lastUserInteraction = lastTouchDown;
  5410. }, passiveCapture);
  5411.  
  5412. document.addEventListener('touchend', (evt) => {
  5413. if (!evt || !evt.isTrusted) return;
  5414. if (currentTouchDown) {
  5415. lastTouchUp = dateNow();
  5416. currentTouchDown = false;
  5417. lastUserInteraction = lastTouchUp;
  5418. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5419. }
  5420. }, passiveCapture);
  5421.  
  5422. document.addEventListener('touchcancel', (evt) => {
  5423. if (!evt || !evt.isTrusted) return;
  5424. if (currentTouchDown) {
  5425. lastTouchUp = dateNow();
  5426. currentTouchDown = false;
  5427. lastUserInteraction = lastTouchUp;
  5428. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5429. }
  5430. }, passiveCapture);
  5431.  
  5432.  
  5433. }
  5434.  
  5435. // const getTimestampUsec = (itemRenderer) => {
  5436. // if (itemRenderer && 'timestampUsec' in itemRenderer) {
  5437. // return itemRenderer.timestampUsec
  5438. // } else if (itemRenderer && itemRenderer.showItemEndpoint) {
  5439. // const messageRenderer = ((itemRenderer.showItemEndpoint.showLiveChatItemEndpoint || 0).renderer || 0);
  5440. // if (messageRenderer) {
  5441.  
  5442. // const messageRendererKey = firstObjectKey(messageRenderer);
  5443. // if (messageRendererKey && messageRenderer[messageRendererKey]) {
  5444. // const messageRendererData = messageRenderer[messageRendererKey];
  5445. // if (messageRendererData && 'timestampUsec' in messageRendererData) {
  5446. // return messageRendererData.timestampUsec
  5447. // }
  5448. // }
  5449. // }
  5450. // }
  5451. // return null;
  5452. // }
  5453.  
  5454. const onRegistryReadyForDOMOperations = () => {
  5455.  
  5456. let firstCheckedOnYtInit = false;
  5457.  
  5458. const assertorURL = () => assertor(() => location.pathname.startsWith('/live_chat') && (location.search.indexOf('continuation=') > 0 || location.search.indexOf('v=') > 0));
  5459.  
  5460. const mightFirstCheckOnYtInit = () => {
  5461. if (firstCheckedOnYtInit) return;
  5462. firstCheckedOnYtInit = true;
  5463.  
  5464. if (!document.body || !document.head) return;
  5465. if (!assertorURL()) return;
  5466.  
  5467. addCssManaged();
  5468.  
  5469. let efsContainer = document.getElementById('elzm-fonts-yk75g');
  5470. if (efsContainer && efsContainer.parentNode !== document.body) {
  5471. document.body.appendChild(efsContainer);
  5472. }
  5473.  
  5474. };
  5475.  
  5476. if (!assertorURL()) return;
  5477. // if (!assertor(() => document.getElementById('yt-masthead') === null)) return;
  5478.  
  5479.  
  5480. const { weakWrap } = (() => {
  5481.  
  5482.  
  5483. // const tickerFuncProps = new Set([
  5484. // 'animateShowStats', 'animateHideStats', // updateStatsBarAndMaybeShowAnimationRevised
  5485. // 'collapse', // slideDownNoSelfLeakage
  5486. // 'requestRemoval', // collapseNoSelfLeakage
  5487. // 'setContainerWidth', 'get', 'set', // deletedChangedNoSelfLeakage
  5488. // 'computeAriaLabel', //dataChanged
  5489. // 'startCountdown', // dataChanged [in case]
  5490. // ]);
  5491.  
  5492. // const tickerTags = new Set([
  5493. // "yt-live-chat-ticker-renderer",
  5494. // "yt-live-chat-ticker-paid-message-item-renderer",
  5495. // "yt-live-chat-ticker-paid-sticker-item-renderer",
  5496. // "yt-live-chat-ticker-sponsor-item-renderer"
  5497. // ]);
  5498.  
  5499. // const emptySet = new Set();
  5500.  
  5501.  
  5502.  
  5503. // const tickerFuncPropsFn = (cnt) => {
  5504.  
  5505. // const is = `${cnt.is}`;
  5506.  
  5507. // if (tickerTags.has(is)) {
  5508. // let flg = 0;
  5509. // if (cnt.get && cnt.set) flg |= 1;
  5510. // if (cnt.setContainerWidth && cnt.collapse && cnt.requestRemoval) flg |= 2;
  5511. // if (cnt.animateShowStats && cnt.animateHideStats) flg |= 4;
  5512. // if (cnt.startCountdown) flg |= 8;
  5513. // console.log(`DEBUG flag_6877 = ${flg}`, is);
  5514. // // DEBUG flag_6877 = 15 yt-live-chat-ticker-paid-message-item-renderer
  5515. // // DEBUG flag_6877 = 11 yt-live-chat-ticker-sponsor-item-renderer
  5516. // return tickerFuncProps;
  5517. // }
  5518.  
  5519. // return emptySet;
  5520.  
  5521.  
  5522. // }
  5523.  
  5524.  
  5525. // const smb = Symbol();
  5526. const vmb = 'dtz02' // Symbol(); // return kThis for thisArg
  5527. const vmc = 'dtz04' // Symbol(); // whether it is proxied fn
  5528. const vmd = 'dtz08' // Symbol(); // self fn proxy (fn--fn)
  5529.  
  5530.  
  5531.  
  5532.  
  5533. const thisConversionFn = (thisArg) => {
  5534. if (!thisArg) return null;
  5535. const kThis = thisArg[vmb];
  5536. if (kThis) {
  5537. const ref = kThis.ref;
  5538. return (ref ? kRef(ref) : null) || null;
  5539. }
  5540. return thisArg;
  5541. }
  5542.  
  5543. const pFnHandler2 = {
  5544. get(target, prop) {
  5545. if (prop === vmc) return target;
  5546. return Reflect.get(target, prop);
  5547. },
  5548. apply(target, thisArg, argumentsList) {
  5549. thisArg = thisConversionFn(thisArg);
  5550. if (thisArg) return Reflect.apply(target, thisArg, argumentsList);
  5551. }
  5552. }
  5553.  
  5554.  
  5555. const proxySelfHandler = {
  5556. get(target, prop) {
  5557. if(prop === vmb) return target;
  5558. const ref = target.ref;
  5559. const cnt = kRef(ref);
  5560. if (!cnt) return;
  5561. if (typeof cnt[prop] === 'function' && !cnt[prop][vmc] && !cnt[prop][vmb]) {
  5562. if (!cnt[prop][vmd]) cnt[prop][vmd] = new Proxy(cnt[prop], pFnHandler2);
  5563. return cnt[prop][vmd];
  5564. }
  5565. return cnt[prop];
  5566. },
  5567. set(target, prop, value) {
  5568. const cnt = kRef(target.ref);
  5569. if (!cnt) return true;
  5570. if(value && (value[vmc] || value[vmb])){
  5571. cnt[prop] = value[vmc] || thisConversionFn(value);
  5572. return true;
  5573. }
  5574. cnt[prop] = value;
  5575. return true;
  5576. }
  5577. };
  5578.  
  5579. const weakWrap = (thisArg) => {
  5580. thisArg = thisConversionFn(thisArg);
  5581. if (!thisArg) {
  5582. console.error('thisArg is not found');
  5583. return null;
  5584. }
  5585. return new Proxy({ ref: mWeakRef(thisArg) }, proxySelfHandler);
  5586. }
  5587.  
  5588.  
  5589.  
  5590.  
  5591.  
  5592.  
  5593. if (!window.getComputedStyle533 && typeof window.getComputedStyle === 'function') {
  5594. window.getComputedStyle533 = window.getComputedStyle;
  5595. window.getComputedStyle = function (a, ...args) {
  5596. a = thisConversionFn(a);
  5597. if (a) {
  5598. return getComputedStyle533(a, ...args);
  5599. }
  5600. return null;
  5601. }
  5602. }
  5603.  
  5604.  
  5605.  
  5606.  
  5607.  
  5608.  
  5609.  
  5610. // const fnProxySelf = function (...args) {
  5611. // const cnt = kRef(this.ref);
  5612. // if (cnt) {
  5613. // return cnt[this.prop](...args); // might throw error
  5614. // }
  5615. // }
  5616. // const proxySelfHandler = {
  5617. // get(target, prop) {
  5618. // const ref = target.ref;
  5619. // const cnt = kRef(ref);
  5620. // if (!cnt) return;
  5621. // if (prop === 'dtz06') return 1;
  5622. // if (typeof cnt[prop] === 'function') {
  5623. // if (!target.funcs.has(prop)) {
  5624. // console.warn(`proxy get to function | prop: ${prop} | is: ${cnt.is}`);
  5625. // }
  5626. // if (!target[`$$${prop}$$`]) target[`$$${prop}$$`] = fnProxySelf.bind({ prop, ref });
  5627. // return target[`$$${prop}$$`];
  5628. // }
  5629. // return cnt[prop];
  5630. // },
  5631. // set(target, prop, value) {
  5632. // const cnt = kRef(target.ref);
  5633. // if (!cnt) return true;
  5634. // if (typeof value === 'function') {
  5635. // console.warn(`proxy set to function | prop: ${prop} | is: ${cnt.is}`);
  5636. // cnt[prop] = value;
  5637. // return true;
  5638. // }
  5639. // cnt[prop] = value;
  5640. // return true;
  5641. // }
  5642. // };
  5643.  
  5644. // return { tickerFuncPropsFn, proxySelfHandler }
  5645.  
  5646. return {weakWrap}
  5647. })();
  5648.  
  5649.  
  5650.  
  5651. if (document.documentElement && document.head) {
  5652. addCssManaged();
  5653. }
  5654. // console.log(document.body===null)
  5655.  
  5656. const preprocessChatLiveActionsMap = new WeakSet();
  5657.  
  5658. const toLAObj=(aItem)=>{
  5659.  
  5660. if (!aItem || typeof aItem !== 'object') return false;
  5661. const key = firstObjectKey(aItem); // addLiveChatTickerItemAction
  5662. if (!key) return false;
  5663. let obj = aItem[key];
  5664. if (!obj || typeof obj !== 'object') return false;
  5665.  
  5666. if (typeof (obj.item || 0) == 'object' && firstObjectKey(obj) === 'item') {
  5667. obj = obj.item;
  5668. const key = firstObjectKey(obj);
  5669. if (key) {
  5670. obj = obj[key];
  5671. }
  5672. }
  5673.  
  5674. return obj;
  5675.  
  5676. };
  5677.  
  5678. const groupsK38=[];
  5679.  
  5680.  
  5681. function intervalsOverlap(a1, a2, b1, b2) {
  5682. // Order the intervals without using Math functions
  5683. var startA = a1 <= a2 ? a1 : a2;
  5684. var endA = a1 <= a2 ? a2 : a1;
  5685.  
  5686. var startB = b1 <= b2 ? b1 : b2;
  5687. var endB = b1 <= b2 ? b2 : b1;
  5688.  
  5689. // Check for overlap
  5690. return endA >= startB && endB >= startA;
  5691. }
  5692.  
  5693.  
  5694.  
  5695. const insertIntoSortedArrayA28 = (arr, val) => {
  5696. let left = 0;
  5697. const n = arr.length;
  5698. let right = n;
  5699.  
  5700. // Binary search to find the correct insertion index:
  5701. // We want the first index where arr[index][2] >= val[2].
  5702. while (left < right) {
  5703. const mid = (left + right) >>> 1;
  5704. if (arr[mid][0] < val[0]) {
  5705. left = mid + 1;
  5706. } else {
  5707. right = mid;
  5708. }
  5709. }
  5710.  
  5711. // 'left' is now the insertion index
  5712. left === n ? arr.push(val): arr.splice(left, 0, val);
  5713. };
  5714.  
  5715. function removeNullsInPlace(arr, startI = 0) {
  5716. let insertPos = startI;
  5717. for (let i = startI; i < arr.length; i++) {
  5718. if (arr[i] !== null) {
  5719. insertPos !== i && (arr[insertPos] = arr[i]);
  5720. insertPos++;
  5721. }
  5722. }
  5723. arr.length = insertPos; // Remove the trailing nulls.
  5724. }
  5725.  
  5726. let fir = 0;
  5727.  
  5728. const limitAddition = (a, b) => {
  5729. // Number.MAX_SAFE_INTEGER = 9007199254740991
  5730. // formula = Math.round((a + b) / (1 + a * b / k / k))
  5731. // avoid a*b > 9007199254740991
  5732. // say a, b <= 94800000
  5733. // Consider (x+x) - (x+x) / (1 + x^2 / k^2) < 0.49
  5734. // x < 130095
  5735.  
  5736. const w = 130095;
  5737. if (a < w && b < w) return a + b;
  5738. const k2 = 94800000 * 94800000;
  5739. return Math.round((a + b) / (1 + (a * b) / k2));
  5740. }
  5741.  
  5742. const preprocessChatLiveActions = (arr) =>{
  5743.  
  5744. if (!fir) {
  5745.  
  5746. if (!__LCRInjection__) {
  5747. console.error('[yt-chat] preprocessChatLiveActions might fail because of no __LCRInjection__');
  5748. }
  5749.  
  5750. DEBUG_preprocessChatLiveActions && console.log('[yt-chat-debug] 5990', 'preprocessChatLiveActions', arr)
  5751.  
  5752. DEBUG_preprocessChatLiveActions && console.log('[yt-chat-debug] 5991', document.querySelectorAll('yt-live-chat-ticker-renderer #ticker-items [class]').length)
  5753.  
  5754. fir = 1;
  5755. // debugger;
  5756. }
  5757.  
  5758. if (!arr || !arr.length) return arr;
  5759.  
  5760. if (preprocessChatLiveActionsMap.has(arr)) return arr;
  5761. preprocessChatLiveActionsMap.add(arr);
  5762.  
  5763.  
  5764.  
  5765. const ct = Date.now();
  5766.  
  5767. let groups_ = null;
  5768.  
  5769. // console.log(1237005);
  5770. // const conversionMap = new WeakMap();
  5771.  
  5772. const additionalInfo = new WeakMap();
  5773.  
  5774. // const adjustmentMap = new Map();
  5775.  
  5776. if (FIX_TIMESTAMP_FOR_REPLAY) {
  5777.  
  5778. // console.log('group02331')
  5779. // console.time('FIX_TIMESTAMP_FOR_REPLAY')
  5780.  
  5781. // const stack = new Array(arr.length);
  5782. // let stackL = 0;
  5783.  
  5784. // const arrHash = new Array(arr.length);
  5785.  
  5786.  
  5787. const groups = groupsK38;
  5788. // const delta = 2.0; // head-to-tail + 0.5 + 0.5 = 1.0 -> symmetric -> 1.0 * 2 = 2.0
  5789. // (2)
  5790. // (1.5, 2.5)
  5791. // (1.51, 2.49)
  5792. // -> (1.01, 2.01) , (1.99, 2.99)
  5793. // 2.99 - 1.01 = 1.98 -> 2
  5794.  
  5795.  
  5796.  
  5797. const pushToGroup = (t0mu)=>{
  5798.  
  5799. const t0auDv = t0mu - 1e6; // t0buDv - t0auDv = 2e6
  5800. const t0buDv = t0mu + 1e6;
  5801. // const t0auEv = t0mu - 2e6;
  5802. // const t0buEv = t0mu + 2e6;
  5803.  
  5804. let groupK = false;
  5805. // let m = -1;
  5806. // let q= 0;
  5807. //const qq =true;
  5808. //qq && console.log('-------')
  5809.  
  5810. let lastRight = null;
  5811. let lastK = null;
  5812. let deletedStartIndex = -1;
  5813.  
  5814. for (let k = 0, kl = groups.length; k < kl; k++) {
  5815.  
  5816. const group = groups[k];
  5817. const [groupStart, groupEnd, gCount] = group;
  5818. //qq && console.log(`-- ${k} ----- ${groupMid} : [${groupStart},${groupEnd}] || C1 = ${t0buEv < groupMid} || C2 = ${t0auEv > groupMid}`);
  5819.  
  5820. // if (t0bsEv < groupMid) continue; // if(t0m + 1.0 < groupMid - 1.0) continue;
  5821. // if (m < 0) m = k;
  5822. // if (t0asEv > groupMid){
  5823. // continue; // if(t0m - 1.0 > groupMid + 1.0) break;
  5824. // }
  5825.  
  5826.  
  5827. // if (m < 0) m = k;
  5828.  
  5829. if (lastRight > groupStart) {
  5830. if (!groupK) {
  5831. // just in case sth wrong
  5832. console.warn('logic ERROR');
  5833. groups[k] = null;
  5834. if(deletedStartIndex < 0) deletedStartIndex = k;
  5835. break;
  5836. } else {
  5837.  
  5838.  
  5839. // GroupA: N_a' = N_a + n_e{1} ; Note n_e is the only way to shift right to cause " (lastRight > groupStart) "
  5840. // GroupB: N_b
  5841. // Merge Group (A) = N_a' + N_b
  5842.  
  5843. // without entry moditification, no overlap
  5844. // this must be due to entry moditifcation
  5845. // entry is already count. so can be skipped after merging
  5846.  
  5847. // for merging, groupA will move to right side but left than groupB, so no overlap to groupC
  5848.  
  5849. const group = groups[lastK];
  5850. const newN = limitAddition(group[2], gCount);
  5851.  
  5852. const factor = gCount / (group[2] + gCount);
  5853.  
  5854. // group[0] = (group[0] * group[2] + groupStart * gCount) / (group[2] + gCount)
  5855. group[0] += (groupStart - group[0]) * factor;
  5856.  
  5857. // group[1] = lastRight = (group[1] * group[2] + groupEnd * gCount) / (group[2] + gCount)
  5858. group[1] += (groupEnd - group[1]) * factor;
  5859.  
  5860. group[2] = newN;
  5861. // no change of lastK
  5862. groups[k] = null;
  5863. if(deletedStartIndex < 0) deletedStartIndex = k;
  5864. continue;
  5865. }
  5866. }
  5867.  
  5868. const minGroupStart = lastRight; // all groupStart, groupEnd >= minGroupStart for k, k+1, ...
  5869. if (t0buDv < minGroupStart) {
  5870. // no overlapping could be possible
  5871. break;
  5872. }
  5873.  
  5874. if (intervalsOverlap(t0auDv, t0buDv, groupStart, groupEnd)) {
  5875.  
  5876. groupK = true;
  5877.  
  5878. // if (t0auDv > groupStart) group[0] = t0auDv;
  5879. // else if (t0buDv < groupEnd) group[1] = t0buDv;
  5880.  
  5881. // const newStart = (groupStart * gCount + t0auDv) / (gCount + 1);
  5882. const newStart = groupStart + (t0auDv - groupStart) * 1 / (gCount + 1);
  5883.  
  5884. if (newStart < lastRight) {
  5885. // n_e{1} will make N_b shift left
  5886.  
  5887. // GroupA: N_a
  5888. // GroupB: N_b
  5889. // Merge Group (A) = N_a + N_b + n_e{1}
  5890.  
  5891. const group = groups[lastK];
  5892. const newN = limitAddition(limitAddition(group[2], gCount), 1);
  5893. const f1 = gCount / (group[2] + gCount + 1);
  5894. const f2 = 1 / (group[2] + gCount + 1);
  5895.  
  5896. // group[0] = (group[0] * group[2] + groupStart * gCount + t0auDv) / (group[2] + gCount + 1);
  5897. group[0] += (groupStart - group[0]) * f1 + (t0auDv - group[0]) * f2;
  5898.  
  5899. // group[1] = lastRight = (group[1] * group[2] + groupEnd * gCount + t0buDv) / (group[2] + gCount + 1)
  5900. lastRight = (group[1] += (groupEnd - group[1]) * f1 + (t0buDv - group[1]) * f2);
  5901.  
  5902. group[2] = newN;
  5903. // no change of lastK
  5904. groups[k] = null;
  5905. if(deletedStartIndex < 0) deletedStartIndex = k;
  5906. continue;
  5907.  
  5908. } else {
  5909. // n_e{1} will make N_b shift either left or right
  5910.  
  5911. // GroupT: N_t
  5912. // Group (T) = N_t + n_e{1}
  5913.  
  5914. const newN = limitAddition(gCount, 1);
  5915.  
  5916. group[0] = newStart;
  5917. // group[1] = lastRight = (groupEnd * gCount + t0buDv) / (gCount + 1);
  5918. group[1] = lastRight = groupEnd + (t0buDv - groupEnd) * 1 / (gCount + 1);
  5919. group[2] = newN;
  5920.  
  5921. lastK = k;
  5922.  
  5923. // (t0asDv > groupStart) && (t0bsDv < groupEnd) means full containement
  5924. // however, group size is smaller than or equal to t0width
  5925. }
  5926.  
  5927.  
  5928. } else {
  5929. // just update record for next iteration
  5930.  
  5931. lastRight = groupEnd;
  5932. lastK = k;
  5933. }
  5934.  
  5935.  
  5936.  
  5937. }
  5938.  
  5939. if (deletedStartIndex >= 0) {
  5940. // rarely used
  5941.  
  5942. removeNullsInPlace(groups, deletedStartIndex);
  5943.  
  5944. }
  5945. if (!groupK) {
  5946. // groups.push([t0auDv, t0buDv, 1]);
  5947. insertIntoSortedArrayA28(groups, [t0auDv, t0buDv, 1]);
  5948. // insertIntoSortedArrayA27(groups, [t0auDv, t0buDv, t0mu]);
  5949. }
  5950.  
  5951.  
  5952. }
  5953.  
  5954. let autoTimeStampFrameChoose = 0;
  5955.  
  5956. // console.log('group02332')
  5957. for (let j = 0, l = arr.length; j < l; j++) {
  5958. const aItem = arr[j];
  5959.  
  5960. const obj = toLAObj(aItem);
  5961. if (obj === false) continue;
  5962.  
  5963. let p = obj.timestampText;
  5964. let p2, p3=null, p4a=null, p4b=null;
  5965. if(p&&p.simpleText ) p2 = p.simpleText;
  5966.  
  5967. let q = obj.timestampUsec ;
  5968. let q2;
  5969.  
  5970. if(q && +q > 1110553200000000) q2 = +q;
  5971. if (q2 > 0 && !autoTimeStampFrameChoose) {
  5972. const q2cc = Math.round(q2 / 1e6);
  5973. autoTimeStampFrameChoose = q2cc - (q2cc % 10000000);
  5974. if (q2cc - autoTimeStampFrameChoose < 2000000) autoTimeStampFrameChoose -= 10000000;
  5975. // around 10day range
  5976. // exceeded ~10day -> above 10000000
  5977. }
  5978.  
  5979. // console.log('group02333', p2, q2)
  5980. // console.log(3775, q2/1e6, autoTimeStampFrameChoose)
  5981.  
  5982. if(p2 && q2){
  5983.  
  5984. let m;
  5985.  
  5986. if (m = /^\s*(-?)(\d+):(\d+)\s*$/.exec(p2)) {
  5987. let c0z = m[1] ? -1 : 1;
  5988. let c1 = (+m[2]);
  5989. let c2 = (+m[3]);
  5990. if (c0z > 0 && c1 >= 0 && c2 >= 0) {
  5991.  
  5992. p3 = c1 * 60 + c2;
  5993. } else if (c0z < 0 && c1 >= 0 && c2 >= 0) {
  5994. // -4:43 -> -4:42 -> -4:41 ... -> -4:01 -> -4:00 -> -3:59 -> -3:58
  5995. // -> ... -1:01 -> -1:00 -> -0:59 -> ... -> -0:02 -> -0:01 -> -0:00 -> 0:00 -> ...
  5996.  
  5997. p3 = (-c1 * 60) + (-c2);
  5998.  
  5999. }
  6000. if (p3 !== null) {
  6001. // 0:14 -> 13.5s ~ 14.4999s -> [13.5, 14.5)
  6002. p4a = p3 - 0.5;
  6003. p4b = p3 + 0.5;
  6004. }
  6005. } else if (m = /^\s*(-?)(\d+):(\d+):(\d+)\s*$/.exec(p2)) {
  6006.  
  6007. let c0z = m[1] ? -1 : 1;
  6008. let c1 = (+m[2]);
  6009. let c2 = (+m[3]);
  6010. let c3 = (+m[4]);
  6011.  
  6012.  
  6013.  
  6014. if (c0z > 0 && c1 >= 0 && c2 >= 0 && c3 >= 0) {
  6015.  
  6016. p3 = c1 * 60 * 60 + c2 * 60 + c3;
  6017. } else if (c0z < 0 && c1 >= 0 && c2 >= 0 && c3>=0) {
  6018. // -4:43 -> -4:42 -> -4:41 ... -> -4:01 -> -4:00 -> -3:59 -> -3:58
  6019. // -> ... -1:01 -> -1:00 -> -0:59 -> ... -> -0:02 -> -0:01 -> -0:00 -> 0:00 -> ...
  6020.  
  6021. p3 = (-c1 * 60 * 60) + (-c2 * 60) + (-c3);
  6022.  
  6023. }
  6024. if (p3 !== null) {
  6025. // 0:14 -> 13.5s ~ 14.4999s -> [13.5, 14.5)
  6026. p4a = p3 - 0.5;
  6027. p4b = p3 + 0.5;
  6028. }
  6029.  
  6030.  
  6031. }
  6032.  
  6033. }
  6034.  
  6035. if(p4a !== null && p4b !== null && q2 > 0){
  6036.  
  6037. // q2_us = t0_us + dt_us
  6038. // p4a_us <= dt_us < p4b_us
  6039. let p4au = p4a * 1e6;
  6040. let p4bu = p4b * 1e6;
  6041.  
  6042. // p4a_us <= q2_us - t0_us < p4b_us
  6043.  
  6044.  
  6045. // p4a_us - q2_us <= - t0_us < p4b_us - q2_us
  6046.  
  6047. // -p4a_us + q2_us >= t0_us > -p4b_us + q2_us
  6048.  
  6049.  
  6050. let t0au = q2 - p4bu; // q2_us - p4b_us
  6051. let t0bu = q2 - p4au; // q2_us - p4a_us
  6052.  
  6053. // t0 (t0au, t0bu]
  6054.  
  6055. const t0mu = (t0au+t0bu)/2;
  6056.  
  6057. // stack[stackL++]=({
  6058. // id: obj.id,
  6059. // idx: j,
  6060. // p2,
  6061. // // q2s : (q2/ 1e6 - autoTimeStampFrameChoose).toFixed(2),
  6062. // p3,
  6063. // /*
  6064. // timestampText: obj.timestampText,
  6065. // timestampUsec: obj.timestampUsec, // us = 1/1000 ms
  6066. // q2,
  6067. // p4a,
  6068. // p4b,
  6069. // */
  6070. // q2s: +(q2 / 1e6 - autoTimeStampFrameChoose).toFixed(2),
  6071. // t0as: +(t0au / 1e6 - autoTimeStampFrameChoose).toFixed(2),
  6072. // t0bs: +(t0bu /1e6 - autoTimeStampFrameChoose).toFixed(2),
  6073.  
  6074. // t0au,
  6075. // t0bu,
  6076. // t0mu
  6077. // });
  6078.  
  6079. // console.log('group02334')
  6080. let wobj = additionalInfo.get(obj);
  6081. if(!wobj) additionalInfo.set(obj, wobj = {});
  6082.  
  6083. wobj.timestampUsecOriginal = q2;
  6084. // wobj.timestampUsecAdjusted = q2;
  6085. wobj.t0au = t0au;
  6086. wobj.t0bu = t0bu;
  6087. wobj.t0mu = t0mu;
  6088.  
  6089. // arrHash[j] = {
  6090. // index: j,
  6091. // id: obj.id,
  6092. // timestampUsec: q2,
  6093. // t0au,
  6094. // t0bu,
  6095. // t0mu
  6096. // };
  6097.  
  6098. pushToGroup(t0mu);
  6099.  
  6100. // console.log('group02335')
  6101. // console.log('grouping', `${obj.id}.${obj.timestampUsec}`);
  6102.  
  6103. // timestamp (q2) can be incorrect.
  6104.  
  6105. // https://www.youtube.com/watch?v=IKKar5SS29E
  6106. // ChwKGkNQZUxfXzZxLS04Q0ZXNGxyUVlkODZrQzNR
  6107.  
  6108. /*
  6109.  
  6110.  
  6111. [
  6112. {
  6113. "id": "ChwKGkNNWHZqXy1xLS04Q0ZXNGxyUVlkODZrQzNR",
  6114. "p2": "2:04",
  6115. "p3": 124,
  6116. "t0as": 8320733.78,
  6117. "t0bs": 8320734.78
  6118. },
  6119. {
  6120. "id": "ChwKGkNQZUxfXzZxLS04Q0ZXNGxyUVlkODZrQzNR",
  6121. "p2": "2:04",
  6122. "p3": 124,
  6123. "t0as": 8320898.89, // incorrect
  6124. "t0bs": 8320899.89
  6125. }
  6126. ]
  6127.  
  6128.  
  6129. */
  6130.  
  6131. }
  6132.  
  6133.  
  6134.  
  6135.  
  6136. }
  6137.  
  6138. // stack.length = stackL;
  6139.  
  6140.  
  6141. groups_ = groups;
  6142. // console.log('groups', groups)
  6143.  
  6144. }
  6145.  
  6146. // console.log(1237006);
  6147.  
  6148. // console.log(5592,1)
  6149. const groupMids = FIX_TIMESTAMP_FOR_REPLAY ? groups_.map(group=>{
  6150.  
  6151. const [groupStart, groupEnd ] = group;
  6152. const groupMid = (groupStart+groupEnd)/2;
  6153. return groupMid;
  6154. }): null;
  6155. // console.log('groupMids', groupMids)
  6156.  
  6157.  
  6158. // console.log(1237007);
  6159.  
  6160. const adjustTimestampFn = (obj) => {
  6161.  
  6162. const groupCount = groupMids.length;
  6163.  
  6164. if (groupCount < 1) return null;
  6165.  
  6166. // const obj = toLAObj(aItem);
  6167. if (obj === false) return null;
  6168.  
  6169. const wobj = additionalInfo.get(obj);
  6170. if (!wobj) return null;
  6171.  
  6172. const { t0mu } = wobj;
  6173.  
  6174.  
  6175. let i0 = 0;
  6176.  
  6177. if (groupCount >= 3) {
  6178. // For larger arrays, use binary search.
  6179. let low = 0;
  6180. let high = groupCount - 1;
  6181.  
  6182. while (high - low > 1) {
  6183. const mid = (low + high) >>> 1;
  6184. if (groupMids[mid] >= t0mu) {
  6185. high = mid;
  6186. } else {
  6187. low = mid;
  6188. }
  6189. }
  6190. i0 = low;
  6191.  
  6192. }
  6193.  
  6194. let upperDiff = -1;
  6195. let lowerDiff = -1;
  6196. for (let i = i0; i < groupCount; i++) {
  6197. const y = groupMids[i] - t0mu;
  6198. if (y >= 0) {
  6199. upperDiff = y; // >=0, entry > value is found
  6200. break;
  6201. }
  6202. lowerDiff = -y; // >0, cache
  6203. }
  6204.  
  6205.  
  6206. const d1 = upperDiff;
  6207. const d2 = lowerDiff;
  6208.  
  6209.  
  6210. // console.log(5381, index1 ,d1, index2 , d2);
  6211.  
  6212. if (d1 >= 0 && ((d2 < 0) || (d1 <= d2))) {
  6213. wobj.chosenT0 = t0mu + d1; // groupMids[index1];
  6214. } else if (d2 >= 0 && ((d1 < 0) || (d2 <= d1))) {
  6215. wobj.chosenT0 = t0mu - d2; // groupMids[index2];
  6216. } else {
  6217. console.warn('logic error');
  6218. return null;
  6219. }
  6220.  
  6221. const adjusted = wobj.timestampUsecOriginal - wobj.chosenT0;
  6222.  
  6223. wobj.timestampUsecAdjusted = adjusted + 1110553200000000;
  6224.  
  6225. // console.log('adjusted', `${obj.id}.${obj.timestampUsec}`, wobj.timestampUsecOriginal - wobj.chosenT0);
  6226.  
  6227. // adjustmentMap.set(`${obj.id}.${obj.timestampUsec}`, wobj.timestampUsecOriginal - wobj.chosenT0);
  6228.  
  6229. return adjusted;
  6230.  
  6231.  
  6232.  
  6233. };
  6234.  
  6235.  
  6236. // console.log(5592,2)
  6237. // console.log(1237008);
  6238. // if (FIX_TIMESTAMP_FOR_REPLAY) {
  6239.  
  6240.  
  6241. // try{
  6242.  
  6243. // // console.log('groupmid',groupMids, groups);
  6244.  
  6245. // for(let j = 0; j< arr.length;j++){
  6246. // if(groupMids.length<1) break;
  6247.  
  6248. // const aItem = arr[j];
  6249. // const obj = toLAObj(aItem);
  6250. // if (obj === false) continue;
  6251.  
  6252. // const wobj = additionalInfo.get(obj);
  6253. // if(!wobj) continue;
  6254.  
  6255. // // wobj.timestampUsecOriginal = q2;
  6256. // // wobj.timestampUsecAdjusted = q2;
  6257. // // wobj.t0au = t0au;
  6258. // // wobj.t0bu = t0bu;
  6259. // // wobj.t0mu = t0mu;
  6260.  
  6261. // const {t0au, t0bu, t0mu} = wobj;
  6262.  
  6263. // let upper = -1;
  6264.  
  6265. // for(let i = 0; i <groupMids.length;i++){
  6266. // const groupMid = groupMids[i];
  6267. // if(groupMid>= t0mu){
  6268. // upper = i;
  6269. // break;
  6270. // }
  6271. // }
  6272. // let index1, index2;
  6273. // if(upper>-1){
  6274. // index1 = upper-1;
  6275. // index2 = upper;
  6276. // }else{
  6277. // index1 = groups.length-1;
  6278. // index2 = -1;
  6279. // }
  6280. // let d1 = null;
  6281. // if(index1 >=0){
  6282. // d1 = Math.abs(groupMids[index1] - t0mu);
  6283. // }
  6284.  
  6285. // let d2 = null;
  6286. // if(index2 >=0){
  6287. // d2 = Math.abs(groupMids[index2] - t0mu);
  6288. // }
  6289. // // console.log(5381, index1 ,d1, index2 , d2);
  6290. // if(d1 >= 0 && ((d1 <= d2) || (d2 === null)) ){
  6291.  
  6292. // wobj.chosenT0 = groupMids[index1];
  6293. // } else if(d2 >= 0 && ((d2 <= d1) || (d1 === null))){
  6294. // wobj.chosenT0 = groupMids[index2];
  6295. // } else {
  6296. // console.warn('logic error');
  6297. // continue;
  6298. // }
  6299.  
  6300. // wobj.timestampUsecAdjusted = wobj.timestampUsecOriginal - wobj.chosenT0 + 1110553200000000;
  6301.  
  6302. // console.log('adjusted', `${obj.id}.${obj.timestampUsec}`, wobj.timestampUsecOriginal - wobj.chosenT0);
  6303.  
  6304. // adjustmentMap.set(`${obj.id}.${obj.timestampUsec}`, wobj.timestampUsecOriginal - wobj.chosenT0);
  6305. // // conversionMap.set(obj, arrHash[j].adjustedTime);
  6306.  
  6307. // // console.log(5382, index, id, t0mu, arrHash[j].adjustedT0, arrHash[j].timestampUsec, arrHash[j].adjustedTime);
  6308.  
  6309. // }
  6310.  
  6311.  
  6312. // }catch(e){
  6313. // console.warn(e);
  6314. // }
  6315.  
  6316.  
  6317.  
  6318.  
  6319.  
  6320. // // if(stack.length > 1){
  6321. // // stack.sort((a,b)=>{
  6322. // // return a.t0mu - b.t0mu
  6323. // // });
  6324. // // // small to large
  6325. // // // console.log(34588, stack.map(e=>e.t0as))
  6326. // // }
  6327.  
  6328. // // grouping
  6329.  
  6330.  
  6331.  
  6332.  
  6333. // // if (stack.length > 0) {
  6334.  
  6335. // // try {
  6336.  
  6337. // // for (let j = 0, l = stack.length; j < l; j++) {
  6338. // // pushToGroup(stack[j].t0mu);
  6339.  
  6340. // // }
  6341.  
  6342. // // }catch(e){
  6343.  
  6344. // // console.warn(e)
  6345. // // }
  6346.  
  6347. // // // console.log(4882, groups.map(e=>e.slice()), stack.slice())
  6348.  
  6349. // // }
  6350.  
  6351.  
  6352.  
  6353.  
  6354. // // console.log(376, 'group', groups);
  6355.  
  6356.  
  6357. // // consolidated group
  6358. // // const consolidatedGroups = doConsolidation(groups);
  6359.  
  6360.  
  6361.  
  6362.  
  6363.  
  6364.  
  6365. // // if(stack.length > 1){
  6366.  
  6367.  
  6368. // // // // console.log(341, 'consolidatedGroups', consolidatedGroups ,groups.map(e=>{
  6369. // // // // return e.map(noTransform);
  6370. // // // // // return e.map(prettyNum);
  6371. // // // // }))
  6372.  
  6373.  
  6374. // // // console.log(344, 'groups', groups.map(e=>{
  6375. // // // return e.map(noTransform);
  6376. // // // // return e.map(prettyNum);
  6377. // // // }))
  6378.  
  6379. // // // // for(const s of stack){
  6380. // // // // for(const g of consolidatedGroups){
  6381. // // // // if(s.t0as<=g.cen && s.t0bs >=g.cen ){
  6382. // // // // s.cen = g.cen;
  6383. // // // // break;
  6384. // // // // }
  6385. // // // // }
  6386.  
  6387. // // // // }
  6388.  
  6389. // // // console.log(377, stack) // Ms
  6390.  
  6391. // // }
  6392.  
  6393.  
  6394. // // console.timeEnd('FIX_TIMESTAMP_FOR_REPLAY')
  6395.  
  6396. // }
  6397.  
  6398.  
  6399.  
  6400.  
  6401.  
  6402.  
  6403.  
  6404.  
  6405.  
  6406. // console.log(5592,5)
  6407.  
  6408.  
  6409. // console.log('preprocessChatLiveActions', arr)
  6410.  
  6411.  
  6412. const mapper = new Map();
  6413.  
  6414. // without delaying. get the time of request
  6415. // (both streaming and replay, but replay relys on progress update so background operation is suppressed)
  6416.  
  6417. for (let j = 0, l = arr.length; j < l; j++) {
  6418. const aItem = arr[j];
  6419.  
  6420. const obj = toLAObj(aItem);
  6421. if(obj === false) continue;
  6422.  
  6423. if (obj.id && !obj.__timestampActionRequest__) {
  6424. // for all item entries
  6425. obj.__timestampActionRequest__ = ct;
  6426. }
  6427.  
  6428. if (obj.id && obj.__timestampActionRequest__ > 0 && obj.durationSec > 0 && obj.fullDurationSec) {
  6429.  
  6430. // console.log(948700, obj , obj.id, (obj.fullDurationSec - obj.durationSec) * 1000)
  6431. const m = obj.__timestampActionRequest__ - (obj.fullDurationSec - obj.durationSec) * 1000;
  6432.  
  6433. // obj.__t374__ = (obj.fullDurationSec - obj.durationSec) * 1000;
  6434. // obj.__t375__ = obj.__timestampActionRequest__ - (obj.fullDurationSec - obj.durationSec) * 1000;
  6435. // console.log(5993, obj)
  6436. // obj.__orderTime__ = m;
  6437. mapper.set(aItem, m);
  6438.  
  6439.  
  6440. }
  6441.  
  6442. }
  6443.  
  6444. if (mapper.size > 1) {
  6445.  
  6446. const idxices = [];
  6447.  
  6448. // sort ticker
  6449. let mArr1 = arr.filter((aItem,idx) => {
  6450.  
  6451. if (mapper.has(aItem)) {
  6452. idxices.push(idx);
  6453. return true;
  6454. }
  6455. return false;
  6456.  
  6457. });
  6458.  
  6459.  
  6460. let mArr2 = mArr1/*.slice(0)*/.sort((a, b) => {
  6461. return mapper.get(a) - mapper.get(b);
  6462. // low index = oldest = smallest timestamp
  6463. });
  6464.  
  6465.  
  6466.  
  6467. // console.log(948701, arr.slice(0));
  6468. for(let j = 0, l=mArr1.length;j <l;j++){
  6469.  
  6470. const idx = idxices[j];
  6471. // arr[idx] = mArr1[j]
  6472. arr[idx] = mArr2[j];
  6473.  
  6474. // const obj1 = toObj(mArr1[j]);
  6475. // const obj2 = toObj(mArr2[j]);
  6476.  
  6477. // console.log(948705, idx, obj1 , obj1.id, (obj1.fullDurationSec - obj1.durationSec) * 1000, obj1.__orderTime__)
  6478.  
  6479. // console.log(948706, idx, obj2 , obj2.id, (obj2.fullDurationSec - obj2.durationSec) * 1000, obj2.__orderTime__)
  6480.  
  6481. }
  6482.  
  6483. // console.log(5994,arr)
  6484.  
  6485. // console.log(948702, arr.slice(0));
  6486. // console.log(948701, arr);
  6487. // arr = arr.map(aItem => {
  6488. // const idx = mArr1.indexOf(aItem);
  6489. // if (idx < 0) return aItem;
  6490. // return mArr2[idx];
  6491. // });
  6492. // console.log(948702, arr);
  6493.  
  6494. // mostly in order, but some not in order
  6495.  
  6496.  
  6497. // eg
  6498.  
  6499. /*
  6500.  
  6501.  
  6502. 948711 68 '1734488590715474'
  6503. 948711 69 '1734488590909853'
  6504. 948711 70 '1734488594763719'
  6505. 948711 71 '1734488602334615' <
  6506. 948711 72 '1734488602267214' <
  6507. 948711 73 '1734488602751771'
  6508. */
  6509.  
  6510. // arr.filter(aItem=>{
  6511.  
  6512. // const p = toObj(aItem);
  6513. // if(p.timestampUsec) return true;
  6514.  
  6515. // }).forEach((aItem,idx)=>{
  6516.  
  6517. // const p = toObj(aItem);
  6518. // console.log(948711, idx, p.timestampUsec);
  6519. // })
  6520.  
  6521. // return arr;
  6522.  
  6523. }
  6524.  
  6525. // console.log(1237001);
  6526.  
  6527. {
  6528.  
  6529.  
  6530. const mapper = new Map();
  6531.  
  6532.  
  6533. const idxices = [];
  6534.  
  6535.  
  6536. let mArr1 = arr.filter((aItem,idx) => {
  6537.  
  6538. const obj = toLAObj(aItem);
  6539. if (!obj) return false;
  6540.  
  6541. const baseText = obj.timestampText;
  6542. const baseTime = +obj.timestampUsec;
  6543. if (!baseTime || !baseText) return false;
  6544. // const timestampUsec = +toLAObj(aItem).timestampUsec; // +false.x = NaN
  6545. // const timestampUsec = +toLAObj(aItem).adjustedTime;
  6546.  
  6547. let timestampUsec;
  6548.  
  6549. // console.log(1237002)
  6550. if (FIX_TIMESTAMP_FOR_REPLAY) {
  6551.  
  6552. // const adjustmentTime = adjustmentMap.get(`${obj.id}.${obj.timestampUsec}`);
  6553.  
  6554. // // const wobj = additionalInfo.get(obj);
  6555.  
  6556. // // if(!wobj){
  6557. // // console.warn('FIX_TIMESTAMP_FOR_REPLAY - no wobj', obj)
  6558. // // return false;
  6559. // // }
  6560.  
  6561. // // timestampUsec = +wobj.timestampUsecAdjusted;
  6562. // if (!Number.isFinite(adjustmentTime)) {
  6563. // console.warn(`FIX_TIMESTAMP_FOR_REPLAY - no adjustmentTime for ${obj.id}.${obj.timestampUsec}`, obj, [...adjustmentMap])
  6564. // return false;
  6565. // }
  6566. // timestampUsec = adjustmentTime;
  6567.  
  6568.  
  6569. const adjustmentTime = adjustTimestampFn(obj);
  6570.  
  6571. if (!Number.isFinite(adjustmentTime)) {
  6572.  
  6573. console.warn(`FIX_TIMESTAMP_FOR_REPLAY - no adjustmentTime for ${obj.id}.${obj.timestampUsec}`, obj);
  6574. return false;
  6575. }
  6576. timestampUsec = adjustmentTime;
  6577.  
  6578.  
  6579. } else {
  6580.  
  6581. if (!Number.isFinite(baseTime)) {
  6582. console.warn(`no baseTime for ${obj.id}.${obj.timestampUsec}`, obj);
  6583.  
  6584. return false;
  6585. }
  6586. timestampUsec = baseTime;
  6587.  
  6588. }
  6589.  
  6590. // if(timestampUsec > 0){
  6591. idxices.push(idx);
  6592. mapper.set(aItem, timestampUsec)
  6593. return true;
  6594. // }
  6595. // return false;
  6596.  
  6597. });
  6598.  
  6599. if(mapper.size > 1){
  6600.  
  6601.  
  6602. // console.log(1237004)
  6603. let mArr2 = mArr1/*.slice(0)*/.sort((a, b) => {
  6604. return mapper.get(a) - mapper.get(b);
  6605. // low index = oldest = smallest timestamp
  6606. });
  6607.  
  6608.  
  6609.  
  6610. // console.log(948701, arr.slice(0));
  6611. for(let j = 0, l=mArr1.length;j <l;j++){
  6612.  
  6613. const idx = idxices[j];
  6614. arr[idx] = mArr2[j];
  6615.  
  6616. // const obj1 = toObj(mArr1[j]);
  6617. // const obj2 = toObj(mArr2[j]);
  6618.  
  6619.  
  6620. // console.log(948711, idx, obj1 === obj2, obj1, obj1.timestampUsec);
  6621. // console.log(948712, idx, obj1 === obj2, obj2, obj2.timestampUsec);
  6622. }
  6623.  
  6624. }
  6625.  
  6626.  
  6627. }
  6628.  
  6629. // console.log(1237005)
  6630.  
  6631. // console.log(378, arr);
  6632.  
  6633. return arr;
  6634.  
  6635.  
  6636. }
  6637.  
  6638. if (ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION) {
  6639.  
  6640. console.log('[yt-chat-control] ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION is used.')
  6641.  
  6642. // console.log('ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION 0001')
  6643.  
  6644. const pop078 = function () {
  6645. const r = this.pop78();
  6646.  
  6647. if (r && (r.actions || 0).length >= 1 && r.videoOffsetTimeMsec) {
  6648. for (const action of r.actions) {
  6649.  
  6650. const itemActionKey = !action ? null : 'addChatItemAction' in action ? 'addChatItemAction' : 'addLiveChatTickerItemAction' in action ? 'addLiveChatTickerItemAction' : null;
  6651. if (itemActionKey) {
  6652.  
  6653. const itemAction = action[itemActionKey];
  6654. const item = (itemAction || 0).item;
  6655. if (typeof item === 'object') {
  6656.  
  6657. const rendererKey = firstObjectKey(item);
  6658. if (rendererKey) {
  6659. const renderer = item[rendererKey];
  6660. if (renderer && typeof renderer === 'object') {
  6661. renderer.__videoOffsetTimeMsec__ = r.videoOffsetTimeMsec;
  6662. renderer.__progressAt__ = playerProgressChangedArg1;
  6663.  
  6664. // console.log(48117006)
  6665. }
  6666.  
  6667. }
  6668.  
  6669. }
  6670. }
  6671. }
  6672. }
  6673. return r;
  6674. }
  6675.  
  6676.  
  6677.  
  6678. const replayQueueProxyHandler = {
  6679. get(target, prop, receiver) {
  6680. if (prop === 'qe3') return 1;
  6681. const v = target[prop];
  6682. if (prop === 'front_') {
  6683. if (v && typeof v.length === 'number') {
  6684. if (!v.pop78) {
  6685. v.pop78 = v.pop;
  6686. v.pop = pop078;
  6687. }
  6688. }
  6689. }
  6690. return v;
  6691. }
  6692. };
  6693.  
  6694. // lcrFn2 will run twice to ensure the method is successfully injected.
  6695. const lcrFn2 = (lcrDummy)=>{
  6696. // make minimal function overhead by pre-defining all possible outside.
  6697.  
  6698. const tag = "yt-live-chat-renderer"
  6699. const dummy = lcrDummy;
  6700.  
  6701. const cProto = getProto(dummy);
  6702. if (!cProto || !cProto.attached) {
  6703. console.warn(`proto.attached for ${tag} is unavailable.`);
  6704. return;
  6705. }
  6706.  
  6707. // mightFirstCheckOnYtInit();
  6708. // groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-renderer hacks");
  6709. // console.log("[Begin]");
  6710.  
  6711.  
  6712. if (typeof cProto.playerProgressChanged_ === 'function' && !cProto.playerProgressChanged32_) {
  6713.  
  6714. cProto.playerProgressChanged32_ = cProto.playerProgressChanged_;
  6715.  
  6716.  
  6717. cProto.playerProgressChanged_ = function (a, b, c) {
  6718. // console.log(48117005)
  6719. if (a === 0) a = arguments[0] = Number.MIN_VALUE; // avoid issue dealing with zero value
  6720. playerProgressChangedArg1 = a;
  6721. playerProgressChangedArg2 = b;
  6722. playerProgressChangedArg3 = c;
  6723. const replayBuffer_ = this.replayBuffer_;
  6724. if (replayBuffer_) {
  6725. const replayQueue = replayBuffer_.replayQueue
  6726. if (replayQueue && typeof replayQueue === 'object' && !replayQueue.qe3) {
  6727. replayBuffer_.replayQueue = new Proxy(replayBuffer_.replayQueue, replayQueueProxyHandler);
  6728. }
  6729. }
  6730. Promise.resolve().then(updateTickerCurrentTime);
  6731. return this.playerProgressChanged32_.apply(this, arguments);
  6732. };
  6733.  
  6734. }
  6735.  
  6736. // console.log("[End]");
  6737. // groupEnd();
  6738.  
  6739.  
  6740. };
  6741. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  6742.  
  6743.  
  6744. // console.log('ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION 0002')
  6745.  
  6746. // getLCRDummy() must be called for injection
  6747. getLCRDummy().then(lcrFn2);
  6748.  
  6749. }
  6750.  
  6751. const stackDM = (()=>{
  6752.  
  6753. let cm, stack, mo;
  6754.  
  6755. let firstRun = ()=>{
  6756. cm = document.createComment('1');
  6757. stack = new Set();
  6758. mo = new MutationObserver(()=>{
  6759. const stack_ = stack;
  6760. stack = new Set();
  6761. // for(const value of stack_){
  6762. // Promise.resolve(value).then(f=>f());
  6763. // }
  6764. for(const value of stack_){
  6765. value();
  6766. }
  6767. stack_.clear();
  6768. });
  6769. mo.observe(cm, {characterData: true});
  6770.  
  6771. }
  6772.  
  6773.  
  6774. const stackDM = (f) => {
  6775.  
  6776. if (firstRun) firstRun = firstRun();
  6777. stack.add(f);
  6778. cm.data = `${(cm.data & 1) + 1}`;
  6779. }
  6780. return stackDM;
  6781. })();
  6782. window.stackDM = stackDM;
  6783.  
  6784.  
  6785. const widthReq = (()=>{
  6786.  
  6787. let widthIORes;
  6788. let widthIO;
  6789.  
  6790. let firstRun = () => {
  6791. widthIORes = new WeakMap();
  6792. widthIO = new IntersectionObserver((mutations) => {
  6793. const r = new Map();
  6794. for (const mutation of mutations) {
  6795. r.set(mutation.target, mutation.boundingClientRect);
  6796. }
  6797.  
  6798. for (const [elm, rect] of r) {
  6799. widthIO.unobserve(elm);
  6800. const o = widthIORes.get(elm);
  6801. o && widthIORes.delete(elm);
  6802. const { promise, values } = o || {};
  6803. if (promise && values) {
  6804. values.width = rect.width;
  6805. promise.resolve(values);
  6806. }
  6807. }
  6808. });
  6809. };
  6810.  
  6811. const widthReq = (elm) => {
  6812.  
  6813. if (firstRun) firstRun = firstRun();
  6814.  
  6815. {
  6816. const { promise, values } = widthIORes.get(elm) || {};
  6817. if (promise) return promise;
  6818. }
  6819.  
  6820. const promise = new PromiseExternal();
  6821. widthIORes.set(elm, { promise, values: {} });
  6822. widthIO.unobserve(elm);
  6823. widthIO.observe(elm);
  6824.  
  6825. return promise;
  6826.  
  6827. }
  6828. return widthReq;
  6829. })();
  6830.  
  6831.  
  6832.  
  6833.  
  6834. customElements.whenDefined('yt-live-chat-item-list-renderer').then(() => {
  6835.  
  6836.  
  6837. const tag = "yt-live-chat-item-list-renderer"
  6838. const dummy = document.createElement(tag);
  6839.  
  6840. const cProto = getProto(dummy);
  6841. if (!cProto || !cProto.attached) {
  6842. console.warn(`proto.attached for ${tag} is unavailable.`);
  6843. return;
  6844. }
  6845.  
  6846. mightFirstCheckOnYtInit();
  6847. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-item-list-renderer hacks");
  6848. console1.log("[Begin]");
  6849.  
  6850. const mclp = cProto;
  6851. const _flag0281_ = window._flag0281_;
  6852.  
  6853. try {
  6854. assertor(() => typeof mclp.scrollToBottom_ === 'function');
  6855. assertor(() => typeof mclp.flushActiveItems_ === 'function');
  6856. assertor(() => typeof mclp.canScrollToBottom_ === 'function');
  6857. assertor(() => typeof mclp.setAtBottom === 'function');
  6858. assertor(() => typeof mclp.scrollToBottom66_ === 'undefined');
  6859. assertor(() => typeof mclp.flushActiveItems66_ === 'undefined');
  6860. } catch (e) { }
  6861.  
  6862.  
  6863. try {
  6864. assertor(() => typeof mclp.attached === 'function');
  6865. assertor(() => typeof mclp.detached === 'function');
  6866. assertor(() => typeof mclp.canScrollToBottom_ === 'function');
  6867. assertor(() => typeof mclp.isSmoothScrollEnabled_ === 'function');
  6868. assertor(() => typeof mclp.maybeResizeScrollContainer_ === 'function');
  6869. assertor(() => typeof mclp.refreshOffsetContainerHeight_ === 'function');
  6870. assertor(() => typeof mclp.smoothScroll_ === 'function');
  6871. assertor(() => typeof mclp.resetSmoothScroll_ === 'function');
  6872. } catch (e) { }
  6873.  
  6874. mclp.prDelay171 = null;
  6875.  
  6876. let myk = 0; // showNewItems77_
  6877. let mlf = 0; // flushActiveItems77_
  6878. let myw = 0; // onScrollItems77_
  6879. let mzt = 0; // handleLiveChatActions77_
  6880. let mlg = 0; // delayFlushActiveItemsAfterUserAction11_
  6881. let zarr = null;
  6882.  
  6883. if ((_flag0281_ & 0x2000) == 0) {
  6884.  
  6885. if ((mclp.clearList || 0).length === 0) {
  6886. (_flag0281_ & 0x2) == 0 && assertor(() => fnIntegrity(mclp.clearList, '0.106.50'));
  6887. mclp.clearList66 = mclp.clearList;
  6888. mclp.clearList = function () {
  6889. myk = (myk & 1073741823) + 1;
  6890. mlf = (mlf & 1073741823) + 1;
  6891. myw = (myw & 1073741823) + 1;
  6892. mzt = (mzt & 1073741823) + 1;
  6893. mlg = (mlg & 1073741823) + 1;
  6894. zarr = null;
  6895. this.prDelay171 = null;
  6896. this.clearList66();
  6897. };
  6898. console1.log("clearList", "OK");
  6899. } else {
  6900. console1.log("clearList", "NG");
  6901. }
  6902.  
  6903. }
  6904.  
  6905.  
  6906.  
  6907. let onListRendererAttachedDone = false;
  6908.  
  6909. function setList(itemOffset, items) {
  6910.  
  6911. const isFirstTime = onListRendererAttachedDone === false;
  6912.  
  6913. if (isFirstTime) {
  6914. onListRendererAttachedDone = true;
  6915. Promise.resolve().then(watchUserCSS);
  6916. addCssManaged();
  6917.  
  6918. const isBoostChatEnabled = (window._flag0281_ & 0x40000) === 0x40000;
  6919. if (!isBoostChatEnabled) setupEvents();
  6920. }
  6921.  
  6922. setupStyle(itemOffset, items);
  6923.  
  6924. setupMutObserver(items);
  6925.  
  6926. console.log('[yt-chat] setupMutObserver DONE')
  6927. }
  6928.  
  6929.  
  6930. const deferSeqFns = []; // ensure correct sequence
  6931. let deferSeqFnI = 0;
  6932. const deferCallbackLooper = entry => {
  6933. nextBrowserTick_(() => {
  6934. const { a, b } = entry;
  6935. const cnt = kRef(a);
  6936. if (cnt && b) b.call(cnt);
  6937. entry.a = entry.b = null;
  6938. });
  6939. }
  6940. const deferCallback = async (cnt, callback) => {
  6941. const a = cnt.__weakRef9441__ || (cnt.__weakRef9441__ = mWeakRef(cnt));
  6942. deferSeqFns[deferSeqFnI++] = { a, b: callback };
  6943. if (deferSeqFnI > 1) return;
  6944. const pr288 = cnt.prDelay288;
  6945. await pr288;
  6946. wme.data = `${(wme.data & 7) + 1}`;
  6947. await wmp;
  6948. const l = deferSeqFnI;
  6949. deferSeqFnI = 0;
  6950. for (let i = 0; i < l; i++) {
  6951. Promise.resolve(deferSeqFns[i]).then(deferCallbackLooper);
  6952. }
  6953. };
  6954.  
  6955. let showMoreBtnTransitionTrigg = null;
  6956.  
  6957. mclp.__showMoreBtn_transitionstart011__ = function (evt) {
  6958. showMoreBtnTransitionTrigg = true;
  6959. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  6960. if (newVisibility === "visible") {
  6961. const btn = evt.target;
  6962. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  6963. }
  6964. };
  6965.  
  6966.  
  6967. mclp.__showMoreBtn_transitionend011__ = function (evt) {
  6968. showMoreBtnTransitionTrigg = true;
  6969. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  6970. if (newVisibility === "hidden") {
  6971. const btn = evt.target;
  6972. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  6973. }
  6974. };
  6975. mclp.attached419 = async function () {
  6976.  
  6977. if (!this.isAttached) return;
  6978.  
  6979. let maxTrial = 16;
  6980. while (!this.$ || !this.$['item-scroller'] || !this.$['item-offset'] || !this.$['items']) {
  6981. if (--maxTrial < 0 || !this.isAttached) return;
  6982. await nextBrowserTick_();
  6983. // await new Promise(requestAnimationFrame);
  6984. }
  6985.  
  6986. if (this.isAttached !== true) return;
  6987.  
  6988. if (!this.$) {
  6989. console.warn("!this.$");
  6990. return;
  6991. }
  6992. if (!this.$) return;
  6993. /** @type {HTMLElement | null} */
  6994. const itemScroller = this.$['item-scroller'];
  6995. /** @type {HTMLElement | null} */
  6996. const itemOffset = this.$['item-offset'];
  6997. /** @type {HTMLElement | null} */
  6998. const items = this.$['items'];
  6999.  
  7000. if (!itemScroller || !itemOffset || !items) {
  7001. console.warn("items.parentNode !== itemOffset");
  7002. return;
  7003. }
  7004.  
  7005. if (nodeParent(items) !== itemOffset) {
  7006.  
  7007. console.warn("items.parentNode !== itemOffset");
  7008. return;
  7009. }
  7010.  
  7011.  
  7012. if (items.id !== 'items' || itemOffset.id !== "item-offset") {
  7013.  
  7014. console.warn("id incorrect");
  7015. return;
  7016. }
  7017.  
  7018. 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')
  7019.  
  7020. if (!isTargetItems) {
  7021. console.warn("!isTargetItems");
  7022. return;
  7023. }
  7024.  
  7025. setList(itemOffset, items);
  7026.  
  7027. if (WITH_SCROLL_ANCHOR) this.__itemAnchorColl011__ = itemOffset.getElementsByTagName('item-anchor');
  7028. else this.__itemAnchorColl011__ = null;
  7029.  
  7030.  
  7031.  
  7032. // btn-show-more-transition
  7033. const btn = this.$['show-more'];
  7034. if (btn) {
  7035. if (!this.__showMoreBtn_transitionstart012__) this.__showMoreBtn_transitionstart012__ = this.__showMoreBtn_transitionstart011__.bind(this);
  7036. if (!this.__showMoreBtn_transitionend012__) this.__showMoreBtn_transitionend012__ = this.__showMoreBtn_transitionend011__.bind(this);
  7037. btn.addEventListener('transitionrun', this.__showMoreBtn_transitionstart012__, false);
  7038. btn.addEventListener('transitionstart', this.__showMoreBtn_transitionstart012__, false);
  7039. btn.addEventListener('transitionend', this.__showMoreBtn_transitionend012__, false);
  7040. btn.addEventListener('transitioncancel', this.__showMoreBtn_transitionend012__, false);
  7041. }
  7042.  
  7043. // fix panel height changing issue (ENABLE_OVERFLOW_ANCHOR only)
  7044. if (itemScrollerResizeObserver) itemScrollerResizeObserver.observe(this.itemScroller || this.$['item-scroller']);
  7045.  
  7046. }
  7047.  
  7048. mclp.attached331 = mclp.attached;
  7049. mclp.attached = function () {
  7050. this.attached419 && this.attached419();
  7051. return this.attached331();
  7052. }
  7053.  
  7054. mclp.detached331 = mclp.detached;
  7055.  
  7056. mclp.detached = function () {
  7057. setupMutObserver();
  7058. return this.detached331();
  7059. }
  7060.  
  7061. const t29s = document.querySelectorAll("yt-live-chat-item-list-renderer");
  7062. for (const t29 of t29s) {
  7063. const cnt = insp(t29);
  7064. if (cnt.isAttached === true) {
  7065. cnt.attached419();
  7066. }
  7067. }
  7068.  
  7069. if ((mclp.async || 0).length === 2 && (mclp.cancelAsync || 0).length === 1) {
  7070.  
  7071. assertor(() => fnIntegrity(mclp.async, '2.24.15'));
  7072. assertor(() => fnIntegrity(mclp.cancelAsync, '1.15.8'));
  7073.  
  7074. /** @type {Map<number, any>} */
  7075. const aMap = new Map();
  7076. const mcid = setTimeout(() => 0, 0.625);
  7077. const maid = requestAnimationFrame(() => 0);
  7078. clearTimeout(mcid);
  7079. cancelAnimationFrame(maid);
  7080. const count0 = mcid + maid + 1740;
  7081. let count = count0;
  7082. mclp.async66 = mclp.async;
  7083. mclp.async = function (e, f) {
  7084. // ensure the previous operation is done
  7085. // .async is usually after the time consuming functions like flushActiveItems_ and scrollToBottom_
  7086. const hasF = arguments.length === 2;
  7087. if (count > 1e9) count = count0 + 9;
  7088. const resId = ++count;
  7089. aMap.set(resId, e);
  7090. const pr1 = Promise.all([this.prDelay288, wmp, this.prDelay171, Promise.resolve()]);
  7091. const pr2 = autoTimerFn();
  7092. Promise.race([pr1, pr2]).then(() => {
  7093. const rp = aMap.get(resId);
  7094. if (typeof rp !== 'function') {
  7095. return;
  7096. }
  7097. const asyncEn = function () {
  7098. return aMap.delete(resId) && rp.apply(this, arguments);
  7099. };
  7100. aMap.set(resId, hasF ? this.async66(asyncEn, f) : this.async66(asyncEn));
  7101. });
  7102.  
  7103. return resId;
  7104. }
  7105.  
  7106. mclp.cancelAsync66 = mclp.cancelAsync;
  7107. mclp.cancelAsync = function (resId) {
  7108. if (resId <= count0) {
  7109. this.cancelAsync66(resId);
  7110. } else if (aMap.has(resId)) {
  7111. const rp = aMap.get(resId);
  7112. aMap.delete(resId);
  7113. if (typeof rp !== 'function') {
  7114. this.cancelAsync66(rp);
  7115. }
  7116. }
  7117. }
  7118.  
  7119. console1.log("async", "OK");
  7120. } else {
  7121. console1.log("async", "NG");
  7122. }
  7123.  
  7124.  
  7125. if ((_flag0281_ & 0x2) == 0) {
  7126. if ((mclp.showNewItems_ || 0).length === 0 && ENABLE_NO_SMOOTH_TRANSFORM) {
  7127.  
  7128. assertor(() => fnIntegrity(mclp.showNewItems_, '0.170.79'));
  7129. mclp.showNewItems66_ = mclp.showNewItems_;
  7130. mclp.showNewItems_ = function () {
  7131. //
  7132. }
  7133.  
  7134. console1.log("showNewItems_", "OK");
  7135. } else {
  7136. console1.log("showNewItems_", "NG");
  7137. }
  7138.  
  7139. }
  7140.  
  7141.  
  7142.  
  7143. if ((_flag0281_ & 0x2) == 0) {
  7144. if ((mclp.onScrollItems_ || 0).length === 1) {
  7145.  
  7146. if (mclp.onScrollItems3641_) {
  7147.  
  7148. } else {
  7149. assertor(() => fnIntegrity(mclp.onScrollItems_, '1.17.9'));
  7150.  
  7151. }
  7152.  
  7153. if (typeof mclp.setAtBottom === 'function' && mclp.setAtBottom.length === 0) {
  7154.  
  7155. mclp.setAtBottom217 = mclp.setAtBottom;
  7156. mclp.setAtBottom = function () {
  7157. const v = this.ec217;
  7158. if (typeof v !== 'boolean') return this.setAtBottom217();
  7159. const u = this.atBottom;
  7160. if (u !== v && typeof u === 'boolean') this.atBottom = v;
  7161. // this.atBottom = a.scrollTop >= a.scrollHeight - a.clientHeight - 15
  7162. }
  7163.  
  7164. let lastScrollTarget = null;
  7165. mclp.onScrollItems66_ = mclp.onScrollItems_;
  7166. let callback = () => { };
  7167.  
  7168. // let itemScrollerWR = null;
  7169. let lastEvent = null;
  7170.  
  7171. let io2 = null, io1 = null;
  7172. const io2f = (entries, observer) => {
  7173. const entry = entries[entries.length - 1];
  7174. if (entry.target !== lastScrollTarget) return;
  7175. callback(entry);
  7176. };
  7177. const io1f = (entries, observer) => {
  7178. const entry = entries[entries.length - 1];
  7179. observer.unobserve(entry.target);
  7180. if (entry.target !== lastScrollTarget) return;
  7181. lastScrollTarget = null;
  7182. callback(entry);
  7183. };
  7184. mclp.onScrollItems3885cb2_ = function (entry) {
  7185. const v = (entry.isIntersecting === true);
  7186. this.ec217 = v;
  7187. this.onScrollItems66_(lastEvent);
  7188. this.ec217 = null;
  7189. }
  7190. mclp.onScrollItems3885cb1_ = function (entry) {
  7191. const v = (entry.intersectionRatio > 0.98);
  7192. this.ec217 = v;
  7193. this.onScrollItems66_(lastEvent);
  7194. this.ec217 = null;
  7195. };
  7196.  
  7197. mclp.onScrollItems_ = function (evt) {
  7198.  
  7199. if (evt === lastEvent) return;
  7200. if (evt && lastEvent && evt.timeStamp === lastEvent.timeStamp) return;
  7201. lastEvent = evt;
  7202. const ytRendererBehavior = this.ytRendererBehavior || 0;
  7203. if (typeof ytRendererBehavior.onScroll === 'function') ytRendererBehavior.onScroll(evt);
  7204. const coll = this.__itemAnchorColl011__;
  7205. if (coll) {
  7206. const anchorElement = coll.length === 1 ? coll[0] : null;
  7207. if (lastScrollTarget !== anchorElement) {
  7208. if (io2) io2.disconnect();
  7209. lastScrollTarget = anchorElement;
  7210. if (anchorElement) {
  7211. if (!this.onScrollItems3886cb2_) this.onScrollItems3886cb2_ = this.onScrollItems3885cb2_.bind(this);
  7212. callback = this.onScrollItems3886cb2_;
  7213. if (!io2) io2 = new IntersectionObserver(io2f);
  7214. io2.observe(anchorElement);
  7215. }
  7216. }
  7217. } else {
  7218. const items = this.$.items;
  7219. if (!items) return this.onScrollItems66_();
  7220. const lastComponent = lastComponentChildFn(items);
  7221. if (!lastComponent) return this.onScrollItems66_();
  7222. if (lastScrollTarget === lastComponent) return;
  7223. lastScrollTarget = lastComponent;
  7224.  
  7225. if (io1) io1.disconnect();
  7226. if (!this.onScrollItems3886cb1_) this.onScrollItems3886cb1_ = this.onScrollItems3885cb1_.bind(this);
  7227. callback = this.onScrollItems3886cb1_;
  7228. if (!io1) io1 = new IntersectionObserver(io1f);
  7229. io1.observe(lastComponent);
  7230. }
  7231. };
  7232.  
  7233. }
  7234.  
  7235. console1.log("onScrollItems_", "OK");
  7236. } else {
  7237. console1.log("onScrollItems_", "NG");
  7238. }
  7239. }
  7240.  
  7241.  
  7242. if ((_flag0281_ & 0x40) == 0) {
  7243.  
  7244. if (ENABLE_NO_SMOOTH_TRANSFORM && SUPPRESS_refreshOffsetContainerHeight_ && typeof mclp.refreshOffsetContainerHeight_ === 'function' && !mclp.refreshOffsetContainerHeight26_ && mclp.refreshOffsetContainerHeight_.length === 0) {
  7245. assertor(() => fnIntegrity(mclp.refreshOffsetContainerHeight_, '0.31.21'));
  7246. mclp.refreshOffsetContainerHeight26_ = mclp.refreshOffsetContainerHeight_;
  7247. mclp.refreshOffsetContainerHeight_ = function () {
  7248. // var a = this.itemScroller.clientHeight;
  7249. // this.itemOffset.style.height = this.items.clientHeight + "px";
  7250. // this.bottomAlignMessages && (this.itemOffset.style.minHeight = a + "px")
  7251. }
  7252. console1.log("refreshOffsetContainerHeight_", "OK");
  7253. } else {
  7254. console1.log("refreshOffsetContainerHeight_", "NG");
  7255. }
  7256.  
  7257. }
  7258.  
  7259. if ((_flag0281_ & 0x2000) == 0) {
  7260. if ((mclp.flushActiveItems_ || 0).length === 0) {
  7261.  
  7262. if ((_flag0281_ & 0x2) == 0) {
  7263.  
  7264. const sfi = fnIntegrity(mclp.flushActiveItems_);
  7265. if(sfi === '0.158.86'){
  7266.  
  7267. // https://www.youtube.com/s/desktop/c01ea7e3/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  7268.  
  7269.  
  7270. // f.flushActiveItems_ = function() {
  7271. // var a = this;
  7272. // if (this.activeItems_.length > 0)
  7273. // if (this.canScrollToBottom_()) {
  7274. // var b = Math.max(this.visibleItems.length + this.activeItems_.length - this.data.maxItemsToDisplay, 0);
  7275. // b && this.splice("visibleItems", 0, b);
  7276. // if (this.isSmoothScrollEnabled_() || this.dockableMessages.length)
  7277. // this.preinsertHeight_ = this.items.clientHeight;
  7278. // this.activeItems_.unshift("visibleItems");
  7279. // try {
  7280. // this.push.apply(this, this.activeItems_)
  7281. // } catch (c) {
  7282. // Tm(c)
  7283. // }
  7284. // this.activeItems_ = [];
  7285. // this.isSmoothScrollEnabled_() ? this.canScrollToBottom_() && $u(function() {
  7286. // a.showNewItems_()
  7287. // }) : $u(function() {
  7288. // a.refreshOffsetContainerHeight_();
  7289. // a.maybeScrollToBottom_()
  7290. // })
  7291. // } else
  7292. // this.activeItems_.length > this.data.maxItemsToDisplay && this.activeItems_.splice(0, this.activeItems_.length - this.data.maxItemsToDisplay)
  7293. // }
  7294.  
  7295. } else if (sfi === '0.156.86') {
  7296. // https://www.youtube.com/s/desktop/f61c8d85/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  7297.  
  7298. // added "refreshOffsetContainerHeight_"
  7299.  
  7300. // f.flushActiveItems_ = function() {
  7301. // var a = this;
  7302. // if (0 < this.activeItems_.length)
  7303. // if (this.canScrollToBottom_()) {
  7304. // var b = Math.max(this.visibleItems.length + this.activeItems_.length - this.data.maxItemsToDisplay, 0);
  7305. // b && this.splice("visibleItems", 0, b);
  7306. // if (this.isSmoothScrollEnabled_() || this.dockableMessages.length)
  7307. // this.preinsertHeight_ = this.items.clientHeight;
  7308. // this.activeItems_.unshift("visibleItems");
  7309. // try {
  7310. // this.push.apply(this, this.activeItems_)
  7311. // } catch (c) {
  7312. // fm(c)
  7313. // }
  7314. // this.activeItems_ = [];
  7315. // this.isSmoothScrollEnabled_() ? this.canScrollToBottom_() && Mw(function() {
  7316. // a.showNewItems_()
  7317. // }) : Mw(function() {
  7318. // a.refreshOffsetContainerHeight_();
  7319. // a.maybeScrollToBottom_()
  7320. // })
  7321. // } else
  7322. // this.activeItems_.length > this.data.maxItemsToDisplay && this.activeItems_.splice(0, this.activeItems_.length - this.data.maxItemsToDisplay)
  7323. // }
  7324. // ;
  7325.  
  7326. } else if (sfi === '0.150.84') {
  7327. // https://www.youtube.com/s/desktop/e4d15d2c/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  7328. // var b = Math.max(this.visibleItems.length + this.activeItems_.length - this.data.maxItemsToDisplay, 0);
  7329. // b && this.splice("visibleItems", 0, b);
  7330. // if (this.isSmoothScrollEnabled_() || this.dockableMessages.length)
  7331. // this.preinsertHeight_ = this.items.clientHeight;
  7332. // this.activeItems_.unshift("visibleItems");
  7333. // try {
  7334. // this.push.apply(this, this.activeItems_)
  7335. // } catch (c) {
  7336. // nm(c)
  7337. // }
  7338. // this.activeItems_ = [];
  7339. // this.isSmoothScrollEnabled_() ? this.canScrollToBottom_() && zQ(function() {
  7340. // a.showNewItems_()
  7341. // }) : zQ(function() {
  7342. // a.maybeScrollToBottom_()
  7343. // })
  7344. } else if (sfi === '0.137.81' || sfi === '0.138.81') {
  7345. // e.g. https://www.youtube.com/yts/jsbin/live_chat_polymer-vflCyWEBP/live_chat_polymer.js
  7346. } else {
  7347. assertor(() => fnIntegrity(mclp.flushActiveItems_, '0.158.86'))
  7348. || logFn('mclp.flushActiveItems_', mclp.flushActiveItems_)();
  7349. }
  7350. }
  7351.  
  7352. let hasMoreMessageState = !ENABLE_SHOW_MORE_BLINKER ? -1 : 0;
  7353.  
  7354. mclp.flushActiveItems66a_ = mclp.flushActiveItems_;
  7355. // let lastLastRow = null;
  7356.  
  7357.  
  7358. const preloadFn = (acItems) => {
  7359. let waitFor = [];
  7360. /** @type {Set<string>} */
  7361. const imageLinks = new Set();
  7362.  
  7363. if (ENABLE_PRELOAD_THUMBNAIL || EMOJI_IMAGE_SINGLE_THUMBNAIL || AUTHOR_PHOTO_SINGLE_THUMBNAIL) {
  7364. for (const item of acItems) {
  7365. fixLiveChatItem(item, imageLinks);
  7366. }
  7367. }
  7368. if (ENABLE_PRELOAD_THUMBNAIL && kptPF !== null && (kptPF & (8 | 4)) && imageLinks.size > 0) {
  7369.  
  7370. // reference: https://github.com/Yuanfang-fe/Blog-X/issues/34
  7371. const rel = kptPF & 8 ? 'subresource' : kptPF & 16 ? 'preload' : kptPF & 4 ? 'prefetch' : '';
  7372. // preload performs the high priority fetching.
  7373. // prefetch delays the chat display if the video resoruce is demanding.
  7374.  
  7375. if (rel) {
  7376.  
  7377. imageLinks.forEach(imageLink => {
  7378. let d = false;
  7379. if (SKIP_PRELOAD_EMOJI && imageLink.includes('.ggpht.com/')) return;
  7380. const isEmoji = imageLink.includes('/emoji/');
  7381. const pretechedSet = isEmoji ? emojiPrefetched : authorPhotoPrefetched;
  7382. if (!pretechedSet.has(imageLink)) {
  7383. pretechedSet.add(imageLink);
  7384. d = true;
  7385. }
  7386. if (d) {
  7387. waitFor.push(linker(null, rel, imageLink, 'image'));
  7388.  
  7389. }
  7390. })
  7391.  
  7392. }
  7393.  
  7394. }
  7395.  
  7396. return async () => {
  7397. if (waitFor.length > 0) {
  7398. await Promise.race([new Promise(r => setTimeout(r, 250)), Promise.all(waitFor)]);
  7399. }
  7400. waitFor.length = 0;
  7401. waitFor = null;
  7402. };
  7403.  
  7404. };
  7405.  
  7406.  
  7407.  
  7408. if(ENABLE_CHAT_MESSAGES_BOOSTED_STAMPING && `${mclp.flushActiveItems_}`.includes("this.push.apply(this,this.activeItems_)") && `${mclp.flushActiveItems_}`.includes(`this.splice("visibleItems",0,`)){
  7409.  
  7410.  
  7411.  
  7412. {
  7413.  
  7414.  
  7415. rendererStamperFactory(cProto, {
  7416. key: 'proceedStampDomArraySplices381_',
  7417. stamperDomClass: 'style-scope yt-live-chat-item-list-renderer yt-live-chat-item-list-stampdom',
  7418. preloadFn
  7419. });
  7420. // cProto.notifyPath371 = cProto.notifyPath;
  7421.  
  7422.  
  7423. cProto.stampDomArraySplices381_ = cProto.stampDomArraySplices_;
  7424.  
  7425. cProto.stampDomArraySplices_ = function (a, b, c) {
  7426. if (a === 'visibleItems' && b === 'items' && (c || 0).indexSplices) {
  7427. if (this.ec388) {
  7428. const indexSplices = c.indexSplices;
  7429. if (indexSplices.length === 1 || typeof indexSplices.length === "undefined") {
  7430. const indexSplice = indexSplices[0] || indexSplices;
  7431. if (indexSplice.type === 'splice' && (indexSplice.addedCount >= 1 || (indexSplice.removed || []).length >= 1)) {
  7432. // console.log(1059, a, b, indexSplice);
  7433. if (this.proceedStampDomArraySplices381_(a, b, indexSplice)) return;
  7434. }
  7435. }
  7436. } else {
  7437. console.warn('stampDomArraySplices_ warning', ...arguments);
  7438. }
  7439. }
  7440. return this.stampDomArraySplices381_(...arguments);
  7441. }
  7442.  
  7443. cProto.stampDomArray366_ = cProto.stampDomArray_;
  7444. cProto.stampDomArray_ = function (items, containerId, componentConfig, rxConfig, shouldCallback, isStableList) {
  7445. const isTickerRendering = items === this.tickerItems && containerId === 'ticker-items';
  7446. const isMessageListRendering = items === this.visibleItems && containerId === 'items';
  7447. if(!isTickerRendering && !isMessageListRendering){
  7448. console.log('stampDomArray_ warning 0xF501', ...arguments)
  7449. return this.stampDomArray366_(...arguments);
  7450. }
  7451.  
  7452. const container = (this.$ || 0)[containerId];
  7453. if (!container) {
  7454. console.log('stampDomArray_ warning 0xF502', ...arguments)
  7455. return this.stampDomArray366_(...arguments);
  7456. }
  7457.  
  7458. if (container[sFirstElementChild] === null && items.length === 0) {
  7459.  
  7460. } else {
  7461. const cTag = isTickerRendering ? 'tickerItems' : 'visibleItems';
  7462. this.proceedStampDomArraySplices381_(cTag, containerId, {
  7463. addedCount: items.length,
  7464. removedCount: container.childElementCount
  7465. });
  7466. }
  7467.  
  7468. const f = () => {
  7469. this.markDirty && this.markDirty();
  7470. const detail = {
  7471. container
  7472. };
  7473. shouldCallback && this.hostElement.dispatchEvent(new CustomEvent("yt-rendererstamper-finished", {
  7474. bubbles: !0,
  7475. cancelable: !1,
  7476. composed: !0,
  7477. detail
  7478. }));
  7479. detail.container = null;
  7480. };
  7481.  
  7482. if (this.ec389pr) {
  7483. this.ec389pr.then(f)
  7484. } else {
  7485. f();
  7486. }
  7487.  
  7488. };
  7489.  
  7490. mclp.push377 = mclp.push;
  7491. mclp.splice377 = mclp.splice;
  7492.  
  7493.  
  7494.  
  7495. const emptyArr = [];
  7496. emptyArr.push = () => 0;
  7497. emptyArr.unshift = () => 0;
  7498. emptyArr.pop = () => void 0;
  7499. emptyArr.shift = () => void 0;
  7500. emptyArr.splice = () => void 0;
  7501. emptyArr.slice = function () { return this };
  7502.  
  7503.  
  7504. mclp.push = function (cTag, ...fnArgs) {
  7505. if (cTag !== 'visibleItems' || !fnArgs.length || !fnArgs[0]) return this.push377(...arguments);
  7506. const arr = this.visibleItems;
  7507. const len = arr.length;
  7508. const newTotalLen = arr.push(...fnArgs);
  7509. const addedCount = fnArgs.length;
  7510. // console.log('push')
  7511. this.proceedStampDomArraySplices381_('visibleItems', 'items', {
  7512. index: len, addedCount: addedCount, removedCount: 0
  7513. })
  7514. return newTotalLen;
  7515. }
  7516.  
  7517. mclp.splice = function (cTag, ...fnArgs) {
  7518. if (cTag !== 'visibleItems' || !fnArgs.length || (fnArgs.length === 2 && !fnArgs[1]) || (fnArgs.length > 2 && !fnArgs[2])) return this.splice377(...arguments);
  7519. const arr = this.visibleItems;
  7520. const removed = arr.splice(...fnArgs);
  7521. const removedCount = removed.length;
  7522. const addedCount = (fnArgs.length > 2 ? fnArgs.length - 2 : 0);
  7523. if (fnArgs.length >= 2 && removedCount !== fnArgs[1]) {
  7524. console.warn(`incorrect splice count. expected = ${fnArgs[1]}; actual = ${removedCount}`);
  7525. }
  7526. // console.log('splice')
  7527. this.proceedStampDomArraySplices381_('visibleItems', 'items', {
  7528. index: fnArgs[0], addedCount: addedCount, removedCount
  7529. })
  7530. return removed;
  7531. }
  7532.  
  7533.  
  7534.  
  7535. }
  7536.  
  7537. /*
  7538. mclp.flushActiveItems66b_ = function () {
  7539.  
  7540. let prWait = null;
  7541. let shouldProceedNextFlushActiveItems = false;
  7542.  
  7543. try {
  7544.  
  7545.  
  7546. const activeItems_ = this.activeItems_;
  7547. const activeItemsCount = activeItems_.length;
  7548. const maxItemsToDisplay = this.data.maxItemsToDisplay;
  7549. if (activeItemsCount > maxItemsToDisplay) {
  7550. activeItems_.splice(0, activeItemsCount - maxItemsToDisplay);
  7551. }
  7552. const qLen = this.visibleItems.length;
  7553. const pr0 = this.prDelay288;
  7554. const pr = this.prDelay288 = new PromiseExternal();
  7555. this.ec377 = true;
  7556. const ec378 = this.ec378 = new Array(qLen).fill(0).map((e, idx) => idx);
  7557. this.flushActiveItems66a_();
  7558. this.ec377 = false;
  7559. this.ec378 = null;
  7560. this.prDelay288 = pr0;
  7561. this.activeItems_ = typeof activeItems_[0] === 'string' ? activeItems_.slice(1) : activeItems_;
  7562. wme.data = `${(wme.data & 7) + 1}`;
  7563. const isSuccess = this.renderSplicedList323(ec378, qLen, pr);
  7564. if (isSuccess) {
  7565. // console.log('19949 - ok')
  7566. this.prDelay288 = pr;
  7567. shouldProceedNextFlushActiveItems = true;
  7568.  
  7569. wme.data = `${(wme.data & 7) + 1}`;
  7570. prWait = wmp;
  7571.  
  7572. } else if (activeItemsCount === 0 || !this.canScrollToBottom_()) {
  7573. // skip
  7574. } else {
  7575. const ppr = ((slist, qLen, pr) => {
  7576. const deleteCount = (typeof slist[0] === 'number') ? slist[0] : qLen;
  7577. let newAt = qLen - deleteCount;
  7578. if (newAt > 0 && slist[newAt - 1] !== qLen - 1) return 3;
  7579. if (newAt > slist.length) return 4;
  7580. if (newAt < slist.length && typeof slist[newAt] === 'number') return 5;
  7581. const addedCount = slist.length - newAt;
  7582. // if (deleteCount > addedCount) return 6;
  7583.  
  7584. if (deleteCount === 0 && addedCount === 0) return 7;
  7585.  
  7586. })(ec378, qLen, pr);
  7587.  
  7588. console.log('19949 - ng', ppr)
  7589.  
  7590. const pr2 = this.prDelay288 = new PromiseExternal();
  7591. this.flushActiveItems66a_();
  7592. pr2.resolve();
  7593. shouldProceedNextFlushActiveItems = true;
  7594.  
  7595. wme.data = `${(wme.data & 7) + 1}`;
  7596. prWait = wmp;
  7597.  
  7598. }
  7599.  
  7600. } catch (e) {
  7601.  
  7602. console.warn(e);
  7603. }
  7604.  
  7605.  
  7606. const pr5 = this.prDelay288;
  7607.  
  7608. (async ()=>{
  7609. await pr5;
  7610. await prWait;
  7611. flushActiveItemExecuted = false;
  7612. if (shouldProceedNextFlushActiveItems && this.activeItems_.length > 0) setTimeout(() => this.flushActiveItems_(), 0);
  7613. })();
  7614.  
  7615. }
  7616. */
  7617.  
  7618.  
  7619. mclp.flushActiveItemsFix001_ = function () {
  7620.  
  7621. // fix YouTube wrong code
  7622. // var b = Math.max(this.visibleItems.length + this.activeItems_.length - this.data.maxItemsToDisplay, 0);
  7623. // b && this.splice("visibleItems", 0, b);
  7624. // e.g. 0 + 99 - 90 = 9
  7625.  
  7626. const data = this.data;
  7627. if (!data) return;
  7628. const visibleItems = this.visibleItems;
  7629. const activeItems_ = this.activeItems_;
  7630. if (!visibleItems || !activeItems_) return;
  7631. const viLen = visibleItems.length;
  7632. const aiLen = activeItems_.length;
  7633. const maxDisplayLen = data.maxItemsToDisplay;
  7634. if (!maxDisplayLen) return;
  7635. if (viLen + aiLen > maxDisplayLen) {
  7636. if (aiLen > maxDisplayLen) activeItems_.splice(0, aiLen - maxDisplayLen);
  7637. // visibleItems splice done by original flushActiveItems_
  7638. }
  7639. }
  7640.  
  7641. mclp.flushActiveItems3641_ = mclp.flushActiveItems_;
  7642.  
  7643. mclp.__moreItemButtonBlinkingCheck183__ = function () {
  7644. const hasPendingItems = (this.activeItems_ && this.activeItems_.length > 0) ? 1 : 0;
  7645. const shouldChange = (hasMoreMessageState === (1 - hasPendingItems));
  7646. if (shouldChange) {
  7647. hasMoreMessageState = hasPendingItems;
  7648. const showMore = (this.$ || 0)['show-more'];
  7649. if (showMore) {
  7650. showMore.classList.toggle('has-new-messages-miuzp', hasPendingItems ? true : false);
  7651. }
  7652. }
  7653. }
  7654.  
  7655. let ps00 = false;
  7656. mclp.flushActiveItems_ = function () {
  7657. if (ps00) return;
  7658. // console.log('flushActiveItems_')
  7659. ps00 = true;
  7660. deferCallback(this, () => {
  7661. ps00 = false;
  7662. // console.log('flushActiveItems3641_')
  7663. if (this.activeItems_.length > 0) {
  7664. const data = this.data;
  7665. if (data) {
  7666. if (data.maxItemsToDisplay > MAX_ITEMS_FOR_TOTAL_DISPLAY) data.maxItemsToDisplay = MAX_ITEMS_FOR_TOTAL_DISPLAY;
  7667. this.flushActiveItemsFix001_(); // bug fix
  7668. this.flushActiveItems3641_();
  7669. if (ENABLE_SHOW_MORE_BLINKER) {
  7670. this.__moreItemButtonBlinkingCheck183__(); // blink the button if there are activeItems remaining.
  7671. }
  7672. }
  7673. }
  7674. }).catch(console.warn);
  7675. };
  7676.  
  7677. mclp.showNewItems3641_ = mclp.showNewItems_;
  7678. mclp.refreshOffsetContainerHeight3641_ = mclp.refreshOffsetContainerHeight_;
  7679. mclp.maybeScrollToBottom3641_ = mclp.maybeScrollToBottom_;
  7680.  
  7681. let ps01 = false;
  7682. mclp.showNewItems_ = function () {
  7683. if (ps01) return;
  7684. // console.log('showNewItems_')
  7685. ps01 = true;
  7686. deferCallback(this, () => {
  7687. ps01 = false;
  7688. this.showNewItems3641_();
  7689. }).catch(console.warn);
  7690. };
  7691.  
  7692. if (!ENABLE_NO_SMOOTH_TRANSFORM && !mclp.refreshOffsetContainerHeight26_) {
  7693. let ps02 = false;
  7694. mclp.refreshOffsetContainerHeight_ = function () {
  7695. if (ps02) return;
  7696. // console.log('refreshOffsetContainerHeight_')
  7697. ps02 = true;
  7698. deferCallback(this, () => {
  7699. ps02 = false;
  7700. this.refreshOffsetContainerHeight3641_();
  7701. }).catch(console.warn);
  7702. };
  7703. }
  7704.  
  7705.  
  7706. let ps03 = false;
  7707. mclp.maybeScrollToBottom_ = function () {
  7708. if (ps03) return;
  7709. // console.log('maybeScrollToBottom_')
  7710. ps03 = true;
  7711. deferCallback(this, () => {
  7712. ps03 = false;
  7713. if (this.atBottom === true) {
  7714.  
  7715. // if (itemsResizeObserverAttached !== true && this.atBottom === true) {
  7716. // // fallback for old browser
  7717. // const itemScroller = this.itemScroller || this.$['item-scroller'] || this.querySelector('#item-scroller') || 0;
  7718. // if (itemScroller.scrollTop === 0) {
  7719. // resizeObserverFallback.observe(itemScroller);
  7720. // }
  7721. // }
  7722. } else {
  7723.  
  7724. this.maybeScrollToBottom3641_();
  7725. }
  7726. }).catch(console.warn);
  7727. };
  7728.  
  7729. mclp.onScrollItems3641_ = mclp.onScrollItems_;
  7730. mclp.maybeResizeScrollContainer3641_ = mclp.maybeResizeScrollContainer_;
  7731. mclp.handleLiveChatActions3641_ = mclp.handleLiveChatActions_;
  7732.  
  7733. let ps11 = false;
  7734. mclp.onScrollItems_ = function (a) {
  7735. if (ps11) return;
  7736. // console.log('onScrollItems_')
  7737. ps11 = true;
  7738. deferCallback(this, () => {
  7739. ps11 = false;
  7740. this.onScrollItems3641_(a);
  7741. }).catch(console.warn);
  7742. };
  7743.  
  7744. if (!ENABLE_NO_SMOOTH_TRANSFORM) { // no function for ENABLE_NO_SMOOTH_TRANSFORM
  7745. let ps12 = false;
  7746. mclp.maybeResizeScrollContainer_ = function (a) {
  7747. if (ps12) return;
  7748. // console.log('maybeResizeScrollContainer_')
  7749. ps12 = true;
  7750. deferCallback(this, () => {
  7751. ps12 = false;
  7752. this.maybeResizeScrollContainer3641_(a);
  7753. }).catch(console.warn);
  7754. };
  7755. }
  7756.  
  7757. }
  7758.  
  7759. console1.log("flushActiveItems_", "OK");
  7760. } else {
  7761. console1.log("flushActiveItems_", "NG");
  7762. }
  7763. }
  7764.  
  7765.  
  7766. if ((_flag0281_ & 0x40) == 0 ) {
  7767.  
  7768.  
  7769. let showBtnLastState = null;
  7770. let lastAtBottomState = null;
  7771. // let showMoreBtnTransitionTrigg = false;
  7772. mclp.atBottomChanged314_ = mclp.atBottomChanged_;
  7773. mclp.atBottomChanged_ = function () {
  7774.  
  7775. const currentAtBottomState = this.atBottom;
  7776. if(lastAtBottomState === currentAtBottomState) return;
  7777. lastAtBottomState = currentAtBottomState;
  7778.  
  7779. // console.log(1289, showMoreBtnTransitionTrigg)
  7780.  
  7781. /*
  7782. if (!this.___btn3848___) {
  7783. this.___btn3848___ = true;
  7784. const btn = ((this || 0).$ || 0)["show-more"] || 0;
  7785. if (btn) {
  7786. btn.addEventListener('transitionstart', (evt) => {
  7787. showMoreBtnTransitionTrigg = true;
  7788. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7789. if (newVisibility === "visible") {
  7790. const btn = evt.target;
  7791. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7792. }
  7793. });
  7794. btn.addEventListener('transitionend', (evt) => {
  7795. showMoreBtnTransitionTrigg = true;
  7796. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7797. if (newVisibility === "hidden") {
  7798. const btn = evt.target;
  7799. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7800. }
  7801. });
  7802. btn.addEventListener('transitioncancel', (evt) => {
  7803. showMoreBtnTransitionTrigg = true;
  7804. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7805. if (newVisibility === "hidden") {
  7806. const btn = evt.target;
  7807. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7808. }
  7809. });
  7810. }
  7811. }
  7812. */
  7813.  
  7814. // btn-show-more-transition
  7815. if (showMoreBtnTransitionTrigg) return;
  7816.  
  7817. const btn = ((this || 0).$ || 0)["show-more"] || 0;
  7818. if (!btn) return this.atBottomChanged314_();
  7819.  
  7820. const showBtnCurrentState = btn.hasAttribute('disabled');
  7821. if (showBtnLastState === showBtnCurrentState) return;
  7822. showBtnLastState = showBtnCurrentState;
  7823.  
  7824. if (this.visibleItems.length === 0) {
  7825. if (this.atBottom === true) {
  7826. btn.setAttribute('disabled', '');
  7827. showBtnLastState = true;
  7828. }
  7829. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7830. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7831. return;
  7832. }
  7833.  
  7834. nextBrowserTick_(() => {
  7835.  
  7836. if (showMoreBtnTransitionTrigg) return;
  7837.  
  7838. // fallback
  7839.  
  7840. // const isAtBottom = this.atBottom === true;
  7841. // if (isAtBottom) {
  7842. // if (!this.hideShowMoreAsync_) {
  7843. // this.hideShowMoreAsync_ = setTimeoutX0(function () {
  7844. // const btn = ((this || 0).$ || 0)["#show-more"] || 0;
  7845. // if (btn) btn.style.visibility = "hidden";
  7846. // }, 200 - 0.125);
  7847. // }
  7848. // } else {
  7849. // if (this.hideShowMoreAsync_) {
  7850. // clearTimeoutX0(this.hideShowMoreAsync_);
  7851. // this.hideShowMoreAsync_ = null;
  7852. // }
  7853. // const btn = ((this || 0).$ || 0)["#show-more"] || 0;
  7854. // if (btn) btn.style.visibility = "visible";
  7855. // }
  7856.  
  7857. const btn = ((this || 0).$ || 0)["show-more"] || 0;
  7858. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7859.  
  7860. if (newVisibility === "hidden") {
  7861. console.warn('show-more-btn no transition')
  7862. }
  7863.  
  7864. if (btn && btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7865.  
  7866. });
  7867.  
  7868. };
  7869.  
  7870. }
  7871.  
  7872.  
  7873.  
  7874. if ((_flag0281_ & 0x2) == 0) {
  7875. if ((mclp.handleLiveChatActions_ || 0).length === 1) {
  7876.  
  7877. const sfi = fnIntegrity(mclp.handleLiveChatActions_);
  7878. // handleLiveChatActions66_
  7879. if (sfi === '1.40.20') {
  7880. // https://www.youtube.com/s/desktop/c01ea7e3/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  7881.  
  7882.  
  7883. // f.handleLiveChatActions_ = function(a) {
  7884. // var b = this;
  7885. // a.length && (a.forEach(this.handleLiveChatAction_, this),
  7886. // this.maybeResizeScrollContainer_(a),
  7887. // this.flushActiveItems_(),
  7888. // $u(function() {
  7889. // b.maybeScrollToBottom_()
  7890. // }))
  7891. // }
  7892.  
  7893. } else if (sfi === '1.39.20') {
  7894. // TBC
  7895. } else if (sfi === '1.31.17') {
  7896. // original
  7897. } else if (mclp.handleLiveChatActions3641_){
  7898. } else {
  7899. assertor(() => fnIntegrity(mclp.handleLiveChatActions_, '1.40.20'))
  7900. || logFn('mclp.handleLiveChatActions_', mclp.handleLiveChatActions_)();
  7901. }
  7902.  
  7903. mclp.handleLiveChatActions66_ = mclp.handleLiveChatActions_;
  7904.  
  7905. mclp.handleLiveChatActions_ = function (arr) {
  7906.  
  7907. try {
  7908. preprocessChatLiveActions(arr);
  7909. } catch (e) {
  7910. console.warn(e);
  7911. }
  7912.  
  7913. this.handleLiveChatActions66_(arr);
  7914.  
  7915. resistanceUpdateFn_(true);
  7916. }
  7917. console1.log("handleLiveChatActions_", "OK");
  7918. } else {
  7919. console1.log("handleLiveChatActions_", "NG");
  7920. }
  7921. }
  7922.  
  7923. // we do not need to do user interaction check for Boost Chat (0x40000)
  7924. const noScrollToBottomCheckForBoostChat = (_flag0281_ & 0x40000) === 0x40000;
  7925.  
  7926. if (noScrollToBottomCheckForBoostChat === false) {
  7927.  
  7928. mclp.hasUserJustInteracted11_ = () => {
  7929. const t = dateNow();
  7930. return (t - lastWheel < 80) || currentMouseDown || currentTouchDown || (t - lastUserInteraction < 80);
  7931. }
  7932.  
  7933. if ((mclp.canScrollToBottom_ || 0).length === 0 && !mclp.canScrollToBottom157_) {
  7934.  
  7935. assertor(() => fnIntegrity(mclp.canScrollToBottom_, '0.9.5'));
  7936.  
  7937. mclp.canScrollToBottom157_ = mclp.canScrollToBottom_;
  7938. mclp.canScrollToBottom_ = function () {
  7939. return this.canScrollToBottom157_() && !this.hasUserJustInteracted11_();
  7940. }
  7941.  
  7942. console1.log("canScrollToBottom_", "OK");
  7943.  
  7944.  
  7945. } else {
  7946. console1.log("canScrollToBottom_", "NG");
  7947. }
  7948.  
  7949. }
  7950.  
  7951. if (ENABLE_NO_SMOOTH_TRANSFORM) {
  7952.  
  7953. mclp.isSmoothScrollEnabled_ = function () {
  7954. return false;
  7955. }
  7956.  
  7957. mclp.maybeResizeScrollContainer_ = function () {
  7958. //
  7959. }
  7960.  
  7961. mclp.refreshOffsetContainerHeight_ = function () {
  7962. //
  7963. }
  7964.  
  7965. mclp.smoothScroll_ = function () {
  7966. //
  7967. }
  7968.  
  7969. mclp.resetSmoothScroll_ = function () {
  7970. //
  7971. }
  7972. console1.log("ENABLE_NO_SMOOTH_TRANSFORM", "OK");
  7973. } else {
  7974. console1.log("ENABLE_NO_SMOOTH_TRANSFORM", "NG");
  7975. }
  7976.  
  7977. if ((_flag0281_ & 0x8) == 0) {
  7978.  
  7979.  
  7980. if (typeof mclp.forEachItem_ === 'function' && !mclp.forEachItem66_ && skipErrorForhandleAddChatItemAction_ && mclp.forEachItem_.length === 1) {
  7981.  
  7982. mclp.forEachItem66_ = mclp.forEachItem_;
  7983. mclp.forEachItem_ = function (a) {
  7984.  
  7985. if ((this._flag0281_ & 0x8) == 0x8) return this.forEachItem66_(a);
  7986.  
  7987. // ƒ (a){this.visibleItems.forEach(a.bind(this,"visibleItems"));this.activeItems_.forEach(a.bind(this,"activeItems_"))}
  7988.  
  7989. try {
  7990.  
  7991. let items801 = false;
  7992. if (typeof a === 'function') {
  7993. const items = this.items;
  7994. if (items instanceof HTMLDivElement) {
  7995. const ev = this.visibleItems;
  7996. const ea = this.activeItems_;
  7997. if (ev && ea && ev.length >= 0 && ea.length >= 0) {
  7998. items801 = items;
  7999. }
  8000. }
  8001. }
  8002.  
  8003. if (items801) {
  8004. items801.__children801__ = 1;
  8005. const res = this.forEachItem66_(a);
  8006. items801.__children801__ = 0;
  8007. return res;
  8008. }
  8009.  
  8010. } catch (e) { }
  8011. return this.forEachItem66_(a);
  8012.  
  8013.  
  8014. // this.visibleItems.forEach((val, idx, arr)=>{
  8015. // a.call(this, 'visibleItems', val, idx, arr);
  8016. // });
  8017.  
  8018. // this.activeItems_.forEach((val, idx, arr)=>{
  8019. // a.call(this, 'activeItems_', val, idx, arr);
  8020. // });
  8021.  
  8022.  
  8023.  
  8024. }
  8025.  
  8026.  
  8027. }
  8028.  
  8029. }
  8030.  
  8031. if (typeof mclp.handleAddChatItemAction_ === 'function' && !mclp.handleAddChatItemAction66_ && FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION && (EMOJI_IMAGE_SINGLE_THUMBNAIL || AUTHOR_PHOTO_SINGLE_THUMBNAIL)) {
  8032.  
  8033. mclp.handleAddChatItemAction66_ = mclp.handleAddChatItemAction_;
  8034. mclp.handleAddChatItemAction_ = function (a) {
  8035. try {
  8036. if (a && typeof a === 'object' && !('length' in a)) {
  8037. fixLiveChatItem(a.item, null);
  8038. console.assert(arguments[0] === a);
  8039. }
  8040. } catch (e) { console.warn(e) }
  8041. let res;
  8042. if (skipErrorForhandleAddChatItemAction_) { // YouTube Native Engine Issue
  8043. try {
  8044. res = this.handleAddChatItemAction66_.apply(this, arguments);
  8045. } catch (e) {
  8046. if (e && (e.message || '').includes('.querySelector(')) {
  8047. console.log("skipErrorForhandleAddChatItemAction_", e.message);
  8048. } else {
  8049. throw e;
  8050. }
  8051. }
  8052. } else {
  8053. res = this.handleAddChatItemAction66_.apply(this, arguments);
  8054. }
  8055. return res;
  8056. }
  8057.  
  8058. if (FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION) console1.log("handleAddChatItemAction_ [ FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION ]", "OK");
  8059. } else {
  8060.  
  8061. if (FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION) console1.log("handleAddChatItemAction_ [ FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION ]", "OK");
  8062. }
  8063.  
  8064.  
  8065. if (typeof mclp.handleReplaceChatItemAction_ === 'function' && !mclp.handleReplaceChatItemAction66_ && FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT && (EMOJI_IMAGE_SINGLE_THUMBNAIL || AUTHOR_PHOTO_SINGLE_THUMBNAIL)) {
  8066.  
  8067. mclp.handleReplaceChatItemAction66_ = mclp.handleReplaceChatItemAction_;
  8068. mclp.handleReplaceChatItemAction_ = function (a) {
  8069. try {
  8070. if (a && typeof a === 'object' && !('length' in a)) {
  8071. fixLiveChatItem(a.replacementItem, null);
  8072. console.assert(arguments[0] === a);
  8073. }
  8074. } catch (e) { console.warn(e) }
  8075. return this.handleReplaceChatItemAction66_.apply(this, arguments);
  8076. }
  8077.  
  8078. if (FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT) console1.log("handleReplaceChatItemAction_ [ FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT ]", "OK");
  8079. } else {
  8080.  
  8081. if (FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT) console1.log("handleReplaceChatItemAction_ [ FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT ]", "OK");
  8082. }
  8083.  
  8084. console1.log("[End]");
  8085. groupEnd();
  8086.  
  8087. }).catch(console.warn);
  8088.  
  8089.  
  8090. const tickerContainerSetAttribute = function (attrName, attrValue) { // ensure '14.30000001%'.toFixed(1)
  8091.  
  8092. let yd = (this.__dataHost || insp(this).__dataHost || 0).__data;
  8093.  
  8094. if (arguments.length === 2 && attrName === 'style' && yd && attrValue) {
  8095.  
  8096. // let v = yd.containerStyle.privateDoNotAccessOrElseSafeStyleWrappedValue_;
  8097. let v = `${attrValue}`;
  8098. // conside a ticker is 101px width
  8099. // 1% = 1.01px
  8100. // 0.2% = 0.202px
  8101.  
  8102.  
  8103. const ratio1 = (yd.ratio * 100);
  8104. if (ratio1 > -1) { // avoid NaN
  8105.  
  8106. // countdownDurationMs
  8107. // 600000 - 0.2% <1% = 6s> <0.2% = 1.2s>
  8108. // 300000 - 0.5% <1% = 3s> <0.5% = 1.5s>
  8109. // 150000 - 1% <1% = 1.5s>
  8110. // 75000 - 2% <1% =0.75s > <2% = 1.5s>
  8111. // 30000 - 5% <1% =0.3s > <5% = 1.5s>
  8112.  
  8113. // 99px * 5% = 4.95px
  8114.  
  8115. // 15000 - 10% <1% =0.15s > <10% = 1.5s>
  8116.  
  8117.  
  8118. // 1% Duration
  8119.  
  8120. let ratio2 = ratio1;
  8121.  
  8122. const ydd = yd.data;
  8123. if (ydd) {
  8124.  
  8125. const d1 = ydd.durationSec;
  8126. const d2 = ydd.fullDurationSec;
  8127.  
  8128. // @ step timing [min. 0.2%]
  8129. let numOfSteps = 500;
  8130. if ((d1 === d2 || (d1 + 1 === d2)) && d1 > 1) {
  8131. if (d2 > 400) numOfSteps = 500; // 0.2%
  8132. else if (d2 > 200) numOfSteps = 200; // 0.5%
  8133. else if (d2 > 100) numOfSteps = 100; // 1%
  8134. else if (d2 > 50) numOfSteps = 50; // 2%
  8135. else if (d2 > 25) numOfSteps = 20; // 5% (max => 99px * 5% = 4.95px)
  8136. else numOfSteps = 20;
  8137. }
  8138. if (numOfSteps > TICKER_MAX_STEPS_LIMIT) numOfSteps = TICKER_MAX_STEPS_LIMIT;
  8139. if (numOfSteps < 5) numOfSteps = 5;
  8140.  
  8141. const rd = numOfSteps / 100.0;
  8142.  
  8143. ratio2 = Math.round(ratio2 * rd) / rd;
  8144.  
  8145. // ratio2 = Math.round(ratio2 * 5) / 5;
  8146. ratio2 = ratio2.toFixed(1);
  8147. v = v.replace(`${ratio1}%`, `${ratio2}%`).replace(`${ratio1}%`, `${ratio2}%`);
  8148.  
  8149. if (yd.__style_last__ === v) return;
  8150. yd.__style_last__ = v;
  8151. // do not consider any delay here.
  8152. // it shall be inside the looping for all properties changes. all the css background ops are in the same microtask.
  8153.  
  8154. }
  8155. }
  8156.  
  8157. HTMLElement_.prototype.setAttribute.call(dr(this), attrName, v);
  8158.  
  8159.  
  8160. } else {
  8161. HTMLElement_.prototype.setAttribute.apply(dr(this), arguments);
  8162. }
  8163.  
  8164. };
  8165.  
  8166.  
  8167. const fpTicker = (renderer) => {
  8168. const cnt = insp(renderer);
  8169. assertor(() => typeof (cnt || 0).is === 'string');
  8170. assertor(() => ((cnt || 0).hostElement || 0).nodeType === 1);
  8171. const container = (cnt.$ || 0).container;
  8172. if (container) {
  8173. assertor(() => (container || 0).nodeType === 1);
  8174. assertor(() => typeof container.setAttribute === 'function');
  8175. container.setAttribute = tickerContainerSetAttribute;
  8176. } else {
  8177. console.warn(`"container" does not exist in ${cnt.is}`);
  8178. }
  8179. };
  8180.  
  8181.  
  8182. const tags = [
  8183. "yt-live-chat-ticker-renderer",
  8184. "yt-live-chat-ticker-paid-message-item-renderer",
  8185. "yt-live-chat-ticker-paid-sticker-item-renderer",
  8186. "yt-live-chat-ticker-sponsor-item-renderer"
  8187. ];
  8188.  
  8189. const tagsItemRenderer = [
  8190. "yt-live-chat-ticker-renderer",
  8191. "yt-live-chat-ticker-paid-message-item-renderer",
  8192. "yt-live-chat-ticker-paid-sticker-item-renderer",
  8193. "yt-live-chat-ticker-sponsor-item-renderer"
  8194. ];
  8195.  
  8196. // const wmList = new Set;
  8197.  
  8198. Promise.all(tags.map(tag => customElements.whenDefined(tag))).then(() => {
  8199.  
  8200. mightFirstCheckOnYtInit();
  8201. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-ticker-... hacks");
  8202. console1.log("[Begin]");
  8203.  
  8204.  
  8205. let tickerAttachmentId = 0;
  8206.  
  8207.  
  8208. const __requestRemoval__ = function (cnt) {
  8209. if (cnt.hostElement && typeof cnt.requestRemoval === 'function') {
  8210. try {
  8211. const id = (cnt.data || 0).id;
  8212. if (!id) cnt.data = { id: 1 };
  8213. } catch (e) { }
  8214. try {
  8215. cnt.requestRemoval();
  8216. return true;
  8217. } catch (e) { }
  8218. }
  8219. return false;
  8220. }
  8221.  
  8222.  
  8223. const overlayBgMap = new WeakMap();
  8224.  
  8225. const dProto = {
  8226.  
  8227.  
  8228. /**
  8229. *
  8230.  
  8231. f.updateStatsBarAndMaybeShowAnimation = function(a, b, c) {
  8232. var d = this;
  8233. a || c();
  8234. a && this.statsBar && this.username && this.textContent && (this.isMouseOver ? (b(),
  8235. c()) : (a = this.animateShowStats(),
  8236. this.data.animationOrigin && this.data.trackingParams && aB().stateChanged(this.data.trackingParams, {
  8237. animationEventData: {
  8238. origin: this.data.animationOrigin
  8239. }
  8240. }),
  8241. a.finished.then(function() {
  8242. var e;
  8243. setTimeout(function() {
  8244. b();
  8245. c();
  8246. if (!d.isMouseOver) {
  8247. var g, k;
  8248. d.animateHideStats(((g = d.data) == null ? void 0 : g.dynamicStateData.stateSlideDurationMs) || 0, ((k = d.data) == null ? void 0 : k.dynamicStateData.stateUpdateDelayAfterMs) || 0)
  8249. }
  8250. }, ((e = d.data) == null ? void 0 : e.dynamicStateData.stateUpdateDelayBeforeMs) || 0)
  8251. })))
  8252. }
  8253.  
  8254. *
  8255. */
  8256.  
  8257.  
  8258.  
  8259. /**
  8260. *
  8261. *
  8262.  
  8263. f.animateShowStats = function() {
  8264. var a = this.textContent.animate({
  8265. transform: "translateY(-30px)"
  8266. }, {
  8267. duration: this.data.dynamicStateData.stateSlideDurationMs,
  8268. fill: "forwards"
  8269. });
  8270. this.username.animate({
  8271. opacity: 0
  8272. }, {
  8273. duration: 500,
  8274. fill: "forwards"
  8275. });
  8276. this.statsBar.animate({
  8277. opacity: 1
  8278. }, {
  8279. duration: 500,
  8280. fill: "forwards"
  8281. });
  8282. return a
  8283. }
  8284. ;
  8285. f.animateHideStats = function(a, b) {
  8286. this.textContent.animate({
  8287. transform: "translateY(0)"
  8288. }, {
  8289. duration: a,
  8290. fill: "forwards",
  8291. delay: b
  8292. });
  8293. this.username.animate({
  8294. opacity: 1
  8295. }, {
  8296. duration: 300,
  8297. fill: "forwards",
  8298. delay: b
  8299. });
  8300. this.statsBar.animate({
  8301. opacity: 0
  8302. }, {
  8303. duration: 300,
  8304. fill: "forwards",
  8305. delay: b
  8306. })
  8307. }
  8308. *
  8309. */
  8310.  
  8311. updateStatsBarAndMaybeShowAnimationRevised: function (a, b, c) {
  8312. // prevent memory leakage due to d.data was asked in a.finished.then
  8313. try{
  8314. // console.log('updateStatsBarAndMaybeShowAnimation called', this.is)
  8315. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8316. return this.updateStatsBarAndMaybeShowAnimation38.call(this.__proxySelf0__, a, b, c);
  8317. }catch(e){
  8318. console.log('updateStatsBarAndMaybeShowAnimationRevised ERROR');
  8319. console.error(e);
  8320. }
  8321. },
  8322.  
  8323. detachedForMemoryLeakage: function () {
  8324.  
  8325. try{
  8326.  
  8327. this.actionHandlerBehavior.unregisterActionMap(this.behaviorActionMap)
  8328.  
  8329. // this.behaviorActionMap = 0;
  8330. // this.isVisibilityRoot = 0;
  8331.  
  8332.  
  8333. }catch(e){}
  8334.  
  8335. return this.detached582MemoryLeak();
  8336. },
  8337.  
  8338. detachedForTickerInit: function () {
  8339.  
  8340. Promise.resolve(this).then((cnt) => {
  8341. if (cnt.isAttached) return;
  8342. cnt.isAttached === false && ((cnt.$ || 0).container || 0).isConnected === false && __requestRemoval__(cnt);
  8343. cnt.rafId > 1 && rafHub.cancel(cnt.rafId);
  8344. }).catch(console.warn);
  8345.  
  8346.  
  8347. const hostElement = (this || 0).hostElement;
  8348. if (USE_ADVANCED_TICKING && (this || 0).__isTickerItem58__ && hostElement instanceof HTMLElement_) {
  8349. // otherwise the startCountDown not working
  8350. hostElement.style.removeProperty('--ticker-start-time');
  8351. hostElement.style.removeProperty('--ticker-duration-time');
  8352.  
  8353. if (kRef(qWidthAdjustable) === hostElement) {
  8354.  
  8355. // need to update the first ticker
  8356. const q = document.querySelector('.r6-width-adjustable');
  8357. if (q instanceof HTMLElement_ && q.classList.contains('r6-width-adjustable-f')) {
  8358. q.classList.remove('r6-width-adjustable-f');
  8359. }
  8360. qWidthAdjustable = mWeakRef(q);
  8361.  
  8362. }
  8363. }
  8364.  
  8365. let r;
  8366. try {
  8367. r = this.detached77();
  8368. } catch (e) {
  8369. console.warn(e);
  8370. }
  8371. this.__ticker_attachmentId__ = 0;
  8372. return r;
  8373. },
  8374.  
  8375. attachedForTickerInit: function () {
  8376. this.__ticker_attachmentId__ = tickerAttachmentId = (tickerAttachmentId & 1073741823) + 1;
  8377.  
  8378. const hostElement = (this || 0).hostElement;
  8379. if (USE_ADVANCED_TICKING && (this || 0).__isTickerItem58__ && hostElement instanceof HTMLElement_) {
  8380. const prevElement = kRef(qWidthAdjustable);
  8381. if (prevElement instanceof HTMLElement_) {
  8382. prevElement.classList.add('r6-width-adjustable-f');
  8383. }
  8384. if (hostElement.__fgvm573__) {
  8385. hostElement.classList.remove('r6-closing-ticker');
  8386. hostElement.classList.remove('r6-width-adjustable-f');
  8387. } else {
  8388. hostElement.__fgvm573__ = 1;
  8389. hostElement.classList.add('r6-width-adjustable');
  8390. }
  8391. qWidthAdjustable = mWeakRef(hostElement);
  8392. }
  8393.  
  8394.  
  8395. fpTicker(hostElement || this);
  8396. return this.attached77();
  8397.  
  8398. },
  8399.  
  8400.  
  8401.  
  8402. setContainerWidthNoSelfLeakage: function(){
  8403. // prevent memory leakage due ot delay function
  8404. try{
  8405. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8406. return this.setContainerWidth55.call(this.__proxySelf0__);
  8407. }catch(e){
  8408. console.log('setContainerWidthNoSelfLeakage ERROR');
  8409. console.error(e);
  8410. }
  8411.  
  8412. },
  8413.  
  8414. slideDownNoSelfLeakage: function(){
  8415. // prevent memory leakage due ot delay function
  8416. try{
  8417. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8418. return this.slideDown55.call(this.__proxySelf0__);
  8419. }catch(e){
  8420. console.log('slideDownNoSelfLeakage ERROR');
  8421. console.error(e);
  8422. }
  8423.  
  8424. },
  8425.  
  8426. collapseNoSelfLeakage: function(){
  8427. // prevent memory leakage due ot delay function
  8428. try{
  8429. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8430. return this.collapse55.call(this.__proxySelf0__);
  8431. }catch(e){
  8432. console.log('collapseNoSelfLeakage ERROR');
  8433. console.error(e);
  8434. }
  8435. },
  8436.  
  8437. deletedChangedNoSelfLeakage: function(){
  8438. // prevent memory leakage due ot delay function
  8439. try{
  8440. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8441. return this.deletedChanged55.call(this.__proxySelf0__);
  8442. }catch(e){
  8443. console.log('deletedChangedNoSelfLeakage ERROR');
  8444. console.error(e);
  8445. }
  8446.  
  8447. },
  8448.  
  8449.  
  8450.  
  8451.  
  8452. /** @type {()} */
  8453. handlePauseReplayForPlaybackProgressState: function () {
  8454. if (!playerEventsByIframeRelay) return this.handlePauseReplay66.apply(this, arguments);
  8455.  
  8456. const attachementId = this.__ticker_attachmentId__;
  8457. if(!attachementId) return;
  8458.  
  8459. const jr = mWeakRef(this);
  8460.  
  8461. if (onPlayStateChangePromise) {
  8462.  
  8463. const tid = this._Y7rtu = (this._Y7rtu & 1073741823) + 1;
  8464.  
  8465. onPlayStateChangePromise.then(() => {
  8466. const cnt = kRef(jr) || 0;
  8467. if (attachementId !== cnt.__ticker_attachmentId__) return;
  8468. if (cnt.isAttached) {
  8469. if (tid === cnt._Y7rtu && !onPlayStateChangePromise && typeof cnt.handlePauseReplay === 'function' && cnt.hostElement) cnt.handlePauseReplay.apply(cnt, arguments);
  8470. // this.handlePauseReplay can be undefined if it is memory cleaned
  8471. }
  8472. });
  8473.  
  8474. return;
  8475. }
  8476.  
  8477. if (playerState !== 2) return;
  8478. if (this.isAttached) {
  8479. const tid = this._Y7rtk = (this._Y7rtk & 1073741823) + 1;
  8480. const tc = relayCount;
  8481. foregroundPromiseFn().then(() => {
  8482. const cnt = kRef(jr);
  8483. if (attachementId !== (cnt || 0).__ticker_attachmentId__) return;
  8484. if (cnt.isAttached) {
  8485. if (tid === cnt._Y7rtk && tc === relayCount && playerState === 2 && _playerState === playerState && cnt.hostElement) {
  8486. cnt.handlePauseReplay66();
  8487. }
  8488. }
  8489. })
  8490. }
  8491. },
  8492.  
  8493. /** @type {()} */
  8494. handleResumeReplayForPlaybackProgressState: function () {
  8495. if (!playerEventsByIframeRelay) return this.handleResumeReplay66.apply(this, arguments);
  8496.  
  8497. const attachementId = this.__ticker_attachmentId__;
  8498. if(!attachementId) return;
  8499.  
  8500. const jr = mWeakRef(this);
  8501. if (onPlayStateChangePromise) {
  8502.  
  8503. const tid = this._Y7rtv = (this._Y7rtv & 1073741823) + 1;
  8504.  
  8505. onPlayStateChangePromise.then(() => {
  8506. const cnt = kRef(jr);
  8507. if(attachementId !== (cnt || 0).__ticker_attachmentId__) return;
  8508. if (tid === cnt._Y7rtv && !onPlayStateChangePromise && typeof cnt.handleResumeReplay === 'function' && cnt.hostElement) cnt.handleResumeReplay.apply(cnt, arguments);
  8509. // this.handleResumeReplay can be undefined if it is memory cleaned
  8510. });
  8511.  
  8512. return;
  8513. }
  8514.  
  8515.  
  8516. if (playerState !== 1) return;
  8517. if (this.isAttached) {
  8518. const tc = relayCount;
  8519.  
  8520. relayPromise = relayPromise || new PromiseExternal();
  8521. relayPromise.then(() => {
  8522. const cnt = kRef(jr);
  8523. if(attachementId !== (cnt || 0).__ticker_attachmentId__) return;
  8524. if (relayCount > tc && playerState === 1 && _playerState === playerState && cnt.hostElement) {
  8525. cnt.handleResumeReplay66();
  8526. }
  8527. });
  8528. }
  8529. },
  8530.  
  8531. /** @type {(a,)} */
  8532. handleReplayProgressForPlaybackProgressState: function (a) {
  8533. if (this.isAttached) {
  8534. const attachementId = this.__ticker_attachmentId__;
  8535. if(!attachementId) return;
  8536. const tid = this._Y7rtk = (this._Y7rtk & 1073741823) + 1;
  8537. const jr = mWeakRef(kRef(this));
  8538. foregroundPromiseFn().then(() => {
  8539. const cnt = kRef(jr);
  8540. if(attachementId !== (cnt || 0).__ticker_attachmentId__) return;
  8541. if (cnt.isAttached) {
  8542. if (tid === cnt._Y7rtk && cnt.hostElement) {
  8543. cnt.handleReplayProgress66(a);
  8544. }
  8545. }
  8546. })
  8547. }
  8548. }
  8549.  
  8550.  
  8551. }
  8552.  
  8553.  
  8554.  
  8555. const isTickerItemsScrolling = function () {
  8556. const elm = document.querySelector('#ticker-bar.yt-live-chat-ticker-renderer');
  8557. if (!elm) return false;
  8558. return (elm.scrollLeft > 0);
  8559. }
  8560.  
  8561.  
  8562.  
  8563.  
  8564. const u37fn = function (cnt) {
  8565.  
  8566. if (cnt.__dataEnabled === false || cnt.__dataInvalid === true) return;
  8567.  
  8568. if (!__LCRInjection__) {
  8569. console.error('[yt-chat] USE_ADVANCED_TICKING fails because of no __LCRInjection__');
  8570. }
  8571.  
  8572. const cntData = ((cnt || 0).__data || 0).data || (cnt || 0).data || 0;
  8573. if (!cntData) return;
  8574. const cntElement = cnt.hostElement;
  8575. if (!(cntElement instanceof HTMLElement_)) return;
  8576.  
  8577. const duration = (cntData.fullDurationSec || cntData.durationSec || 0);
  8578.  
  8579. let ct;
  8580.  
  8581. if (__LCRInjection__ && cntData && duration > 0 && !('__progressAt__' in cntData)) {
  8582. ct = Date.now();
  8583. cntData.__liveTimestamp__ = (cntData.__timestampActionRequest__ || ct) / 1000 - timeOriginDT / 1000;
  8584. timestampUnderLiveMode = true;
  8585. } else if (__LCRInjection__ && cntData && duration > 0 && cntData.__progressAt__ > 0) {
  8586. timestampUnderLiveMode = false;
  8587. }
  8588. // console.log(48117007, cntData)
  8589.  
  8590. let tk = cntData.__progressAt__ || cntData.__liveTimestamp__;
  8591.  
  8592. if (!tk) {
  8593. console.log('time property is not found', !!__LCRInjection__, !!cntData, !!(duration > 0), !('__progressAt__' in cntData), cntData.__progressAt__, cntData.__liveTimestamp__);
  8594. return;
  8595. }
  8596.  
  8597.  
  8598.  
  8599. const liveOffsetMs = ct > 0 && cntData.__timestampActionRequest__ > 0 ? ct - cntData.__timestampActionRequest__ : 0;
  8600.  
  8601. // console.log(1237, liveOffsetMs, cntData.durationSec)
  8602.  
  8603. if (liveOffsetMs > 0) {
  8604. cntData.durationSec -= Math.floor(liveOffsetMs / 1000);
  8605. if (cntData.durationSec < 0) cntData.durationSec = 0;
  8606. // console.log(1238, liveOffsetMs, cntData.durationSec)
  8607. if (!cntData.durationSec) {
  8608. try {
  8609. cnt.requestRemoval();
  8610. } catch (e) { }
  8611. return;
  8612. }
  8613. }
  8614.  
  8615.  
  8616. let offset = cntData.fullDurationSec - cntData.durationSec; // consider this is live replay video, offset can be > 0
  8617. if (offset > 0) tk -= offset;
  8618. // in livestreaming. tk can be negative as we use performance.timeOrigin for t=0s time frame
  8619.  
  8620.  
  8621.  
  8622. const existingOverlaySelector = `ticker-bg-overlay[ticker-id="${cnt.__ticker_attachmentId__}"]`;
  8623.  
  8624. const q = kRef(overlayBgMap.get(cnt));
  8625.  
  8626. let r = valAssign(cntElement, '--ticker-start-time', tk);
  8627.  
  8628. if ((r || !q || q.isConnected === false) && duration > 0) {
  8629.  
  8630. // t0 ...... 1 ... fullDurationSec
  8631. // tk ...... k ... fullDurationSec-durationSec
  8632. // t0-fullDurationSec ...... 0 ... 0
  8633.  
  8634. // now - (fullDurationSec-durationSec)
  8635.  
  8636.  
  8637. // update dntElementWeak
  8638. const dnt = cnt.parentComponent;
  8639. const dntElement = dnt ? dnt.hostElement || dnt : 0;
  8640. if (dntElement) {
  8641. dntElementWeak = mWeakRef(dntElement);
  8642. resistanceUpdateBusy = false;
  8643. if (!startResistanceUpdaterStarted) startResistanceUpdater();
  8644. else updateTickerCurrentTime();
  8645. }
  8646.  
  8647.  
  8648. // create overlay if needed
  8649. if (!cntElement.querySelector(existingOverlaySelector)) {
  8650.  
  8651. // remove if any
  8652. const oldElement = cntElement.querySelector('ticker-bg-overlay');
  8653. if (oldElement) oldElement.remove();
  8654.  
  8655. // use advancedTicking, ticker enabled
  8656. cnt.__advancedTicking038__ = 1;
  8657.  
  8658. const em = q || document.createElement('ticker-bg-overlay');
  8659.  
  8660. overlayBgMap.set(cnt, mWeakRef(em));
  8661. // const ey = document.createElement('ticker-bg-overlay-end');
  8662. const wy = document.createElement('ticker-bg-overlay-end2');
  8663.  
  8664. const cr1 = cnt.colorFromDecimal(cntData.startBackgroundColor);
  8665. const cr2 = cnt.colorFromDecimal(cntData.endBackgroundColor);
  8666.  
  8667. const container = cnt.$.container;
  8668.  
  8669. em.setAttribute('ticker-id', `${cnt.__ticker_attachmentId__}`);
  8670.  
  8671. const tid = `ticker-${cnt.__ticker_attachmentId__}-${Math.floor(Math.random() * 314159265359 + 314159265359).toString(36)}`;
  8672.  
  8673. em.id = `${tid}-b`;
  8674. em.style.background = `linear-gradient(90deg, ${cr1},${cr1} 50%,${cr2} 50%,${cr2})`;
  8675.  
  8676. if (!(container instanceof HTMLElement_)) {
  8677. // em.insertBefore(ey, em.firstChild);
  8678. insertBeforeNaFn(cntElement, em, cntElement.firstChild); // cntElement.insertBefore(em, cntElement.firstChild);
  8679. cntElement.style.borderRadius = '16px';
  8680. container.style.borderRadius = 'initial';
  8681. } else {
  8682. // em.insertBefore(ey, em.firstChild);
  8683. insertBeforeNaFn(container, em, container.firstChild); // container.insertBefore(em, container.firstChild);
  8684. }
  8685.  
  8686. // em.style.left = '-50%';
  8687. // em.style.left = "clamp(-100%, calc( -100% * ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) ), 0%)";
  8688.  
  8689. if (container instanceof HTMLElement_) {
  8690.  
  8691. container.style.background = 'transparent';
  8692. container.style.backgroundColor = 'transparent';
  8693. // container.style.zIndex = '1';
  8694. }
  8695. // em.style.zIndex = '-1';
  8696. valAssign(cntElement, '--ticker-duration-time', duration)
  8697.  
  8698. valAssign(wy, '--ticker-start-time', tk);
  8699. valAssign(wy, '--ticker-duration-time', duration);
  8700. wy.id = `${tid}-e`;
  8701.  
  8702. appendChildNaFn(dntElement, wy);
  8703.  
  8704. // if (wio instanceof IntersectionObserver) {
  8705. // wio.observe(ey);
  8706. // }
  8707.  
  8708. const wio2 = dProto.wio2;
  8709. if (wio2 instanceof IntersectionObserver) {
  8710. wio2.observe(wy);
  8711. }
  8712.  
  8713. }
  8714. }
  8715. };
  8716.  
  8717.  
  8718.  
  8719. const timeFn748 = async (cnt) => {
  8720.  
  8721.  
  8722. if (cnt.data) {
  8723. const data = cnt.data;
  8724. cnt[`_pr7_${data.id}`] = new PromiseExternal();
  8725. cnt[`_pr9_${data.id}`] = new PromiseExternal();
  8726. } else {
  8727. cnt[`_pr7_${data.id}`] = null;
  8728. cnt[`_pr9_${data.id}`] = null;
  8729. }
  8730.  
  8731.  
  8732. if (cnt && cnt.data) {
  8733. const data = cnt.data;
  8734. const pr = cnt[`_pr7_${data.id}`]
  8735. const pr9 = cnt[`_pr9_${data.id}`]
  8736. if (pr) await pr;
  8737. if (cnt[`_pr7_${data.id}`] === pr) cnt[`_pr7_${data.id}`] = null;
  8738. const parentComponent = cnt.parentComponent;
  8739. if (parentComponent) {
  8740. const pr = insp(parentComponent).ec389pr;
  8741. if (pr) await pr;
  8742. }
  8743. pr9.resolve();
  8744. }
  8745.  
  8746. if(
  8747. cnt
  8748. && (cnt.hostElement && cnt.isAttached && cnt.hostElement.isConnected )
  8749. && cnt.parentComponent // startCountdown is triggered by dataChanged; // not yet attached to the actual dom tree
  8750. && cnt.__ticker_attachmentId__
  8751. ){
  8752. Promise.resolve(cnt).then(u37fn);
  8753.  
  8754. }
  8755.  
  8756.  
  8757.  
  8758.  
  8759. if (cnt.data) {
  8760. const data = cnt.data;
  8761. if (cnt.hostElement && cnt.isAttached, cnt.hostElement?.isConnected && cnt.parentComponent) {
  8762. const pr = cnt[`_pr7_${data.id}`];
  8763. if (pr) {
  8764. cnt[`_pr7_${data.id}`] = null;
  8765. pr.resolve();
  8766. }
  8767. }
  8768. }
  8769. cnt.pz483 = ((cnt.pz483 || 0) & 1073741823) + 1;
  8770.  
  8771. };
  8772.  
  8773. let tagI = 0;
  8774. for (const tag of tagsItemRenderer) { // ##tag##
  8775.  
  8776. tagI++;
  8777.  
  8778. const dummy = document.createElement(tag);
  8779.  
  8780. const cProto = getProto(dummy);
  8781. if (!cProto || !cProto.attached) {
  8782. console1.warn(`proto.attached for ${tag} is unavailable.`);
  8783. continue;
  8784. }
  8785.  
  8786. if (FIX_MEMORY_LEAKAGE_TICKER_ACTIONMAP && typeof cProto.detached582MemoryLeak !== 'function' && typeof cProto.detached === 'function') {
  8787. cProto.detached582MemoryLeak = cProto.detached;
  8788. cProto.detached = dProto.detachedForMemoryLeakage;
  8789. }
  8790.  
  8791. cProto.detached77 = cProto.detached;
  8792. cProto.detached = dProto.detachedForTickerInit;
  8793.  
  8794. cProto.attached77 = cProto.attached;
  8795.  
  8796. cProto.attached = dProto.attachedForTickerInit;
  8797.  
  8798. let flgLeakageFixApplied = 0;
  8799.  
  8800. if (FIX_MEMORY_LEAKAGE_TICKER_STATSBAR && typeof cProto.updateStatsBarAndMaybeShowAnimation === 'function' && !cProto.updateStatsBarAndMaybeShowAnimation38 && cProto.updateStatsBarAndMaybeShowAnimation.length === 3) {
  8801.  
  8802. cProto.updateStatsBarAndMaybeShowAnimation38 = cProto.updateStatsBarAndMaybeShowAnimation;
  8803. cProto.updateStatsBarAndMaybeShowAnimation = dProto.updateStatsBarAndMaybeShowAnimationRevised;
  8804.  
  8805. flgLeakageFixApplied |= 2;
  8806. } else {
  8807. // the function is only in yt-live-chat-ticker-paid-message-item-renderer
  8808. }
  8809.  
  8810.  
  8811. // ------------- withTimerFn_ -------------
  8812.  
  8813. let withTimerFn_ = 0;
  8814. if (typeof cProto.startCountdown === 'function' && typeof cProto.updateTimeout === 'function' && typeof cProto.isAnimationPausedChanged === 'function') {
  8815.  
  8816. // console.log('startCountdown', typeof cProto.startCountdown)
  8817. // console.log('updateTimeout', typeof cProto.updateTimeout)
  8818. // console.log('isAnimationPausedChanged', typeof cProto.isAnimationPausedChanged)
  8819.  
  8820. // <<< to be reviewed cProto.updateTimeout --- isTimingFunctionHackable -- doHack >>>
  8821. const isTimingFunctionHackable = fnIntegrity(cProto.startCountdown, '2.66.37') && fnIntegrity(cProto.updateTimeout, '1.76.45') && fnIntegrity(cProto.isAnimationPausedChanged, '2.56.30')
  8822. if (!isTimingFunctionHackable) console1.log('isTimingFunctionHackable = false');
  8823. withTimerFn_ = isTimingFunctionHackable ? 2 : 1;
  8824. } else {
  8825. let flag = 0;
  8826. if (typeof cProto.startCountdown === 'function') flag |= 1;
  8827. if (typeof cProto.updateTimeout === 'function') flag |= 2;
  8828. if (typeof cProto.isAnimationPausedChanged === 'function') flag |= 4;
  8829.  
  8830. console1.log(`Skip Timing Function Modification[#${tagI}]: ${flag} / ${1 + 2 + 4}`, ` ${tag}`);
  8831. // console.log(Object.getOwnPropertyNames(cProto))
  8832. // continue;
  8833. }
  8834.  
  8835. // ------------- withTimerFn_ -------------
  8836.  
  8837. // ------------- ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX -------------
  8838.  
  8839. let urt = 0;
  8840.  
  8841. if (ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX) {
  8842.  
  8843.  
  8844. /**
  8845. *
  8846. f.handlePauseReplay = function() {
  8847. this.isAnimationPaused = !0;
  8848. this.detlaSincePausedSecs = 0
  8849. }
  8850. */
  8851.  
  8852. /**
  8853. *
  8854.  
  8855. f.handlePauseReplay = function() {
  8856. this.isReplayPaused = !0
  8857. }
  8858. *
  8859. */
  8860.  
  8861. if (typeof cProto.handlePauseReplay === 'function' && !cProto.handlePauseReplay66 && cProto.handlePauseReplay.length === 0) {
  8862. const fi = fnIntegrity(cProto.handlePauseReplay);
  8863. urt++;
  8864. if (fi === '0.8.2' || fi === '0.12.4') {
  8865. } else {
  8866. assertor(() => fnIntegrity(cProto.handlePauseReplay, '0.12.4'));
  8867. }
  8868. } else {
  8869. if (withTimerFn_ > 0) console1.log('Error for setting cProto.handlePauseReplay', tag)
  8870. }
  8871.  
  8872. if (typeof cProto.handleResumeReplay === 'function' && !cProto.handleResumeReplay66 && cProto.handleResumeReplay.length === 0) {
  8873. urt++;
  8874. assertor(() => fnIntegrity(cProto.handleResumeReplay, '0.8.2'));
  8875. } else {
  8876. if (withTimerFn_ > 0) console1.log('Error for setting cProto.handleResumeReplay', tag)
  8877. }
  8878.  
  8879. if (typeof cProto.handleReplayProgress === 'function' && !cProto.handleReplayProgress66 && cProto.handleReplayProgress.length === 1) {
  8880. urt++;
  8881. assertor(() => fnIntegrity(cProto.handleReplayProgress, '1.16.13'));
  8882. } else {
  8883. if (withTimerFn_ > 0) console1.log('Error for setting cProto.handleReplayProgress', tag)
  8884. }
  8885.  
  8886.  
  8887.  
  8888. }
  8889.  
  8890. 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);
  8891. cProto.__ENABLE_VIDEO_PROGRESS_STATE_FIX_AND_URT_PASSED__ = ENABLE_VIDEO_PROGRESS_STATE_FIX_AND_URT_PASSED;
  8892.  
  8893. if (ENABLE_VIDEO_PROGRESS_STATE_FIX_AND_URT_PASSED) {
  8894.  
  8895. cProto._Y7rtk = 0;
  8896. cProto._Y7rtu = 0;
  8897. cProto._Y7rtv = 0;
  8898.  
  8899. cProto.handlePauseReplay66 = cProto.handlePauseReplay;
  8900. cProto.handlePauseReplay = dProto.handlePauseReplayForPlaybackProgressState;
  8901.  
  8902. cProto.handleResumeReplay66 = cProto.handleResumeReplay;
  8903. cProto.handleResumeReplay = dProto.handleResumeReplayForPlaybackProgressState;
  8904.  
  8905. cProto.handleReplayProgress66 = cProto.handleReplayProgress;
  8906. cProto.handleReplayProgress = dProto.handleReplayProgressForPlaybackProgressState;
  8907.  
  8908. }
  8909.  
  8910. // ------------- ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX -------------
  8911.  
  8912. // ------------- FIX_MEMORY_LEAKAGE_TICKER_TIMER -------------
  8913.  
  8914. if (FIX_MEMORY_LEAKAGE_TICKER_TIMER) {
  8915. if (!USE_ADVANCED_TICKING && typeof cProto.setContainerWidth === 'function' && !cProto.setContainerWidth55 && cProto.setContainerWidth.length === 0) {
  8916. cProto.setContainerWidth55 = cProto.setContainerWidth;
  8917. cProto.setContainerWidth = dProto.setContainerWidthNoSelfLeakage;
  8918. flgLeakageFixApplied |= 4;
  8919. }
  8920. if (!USE_ADVANCED_TICKING && typeof cProto.slideDown === 'function' && !cProto.slideDown55 && cProto.slideDown.length === 0) {
  8921. cProto.slideDown55 = cProto.slideDown;
  8922. cProto.slideDown = dProto.slideDownNoSelfLeakage;
  8923. flgLeakageFixApplied |= 8;
  8924. }
  8925. if (!USE_ADVANCED_TICKING && typeof cProto.collapse === 'function' && !cProto.collapse55 && cProto.collapse.length === 0) {
  8926. cProto.collapse55 = cProto.collapse;
  8927. cProto.collapse = dProto.collapseNoSelfLeakage;
  8928. flgLeakageFixApplied |= 16;
  8929. }
  8930. if (typeof cProto.deletedChanged === 'function' && !cProto.deletedChanged55 && cProto.deletedChanged.length === 0) {
  8931.  
  8932. cProto.deletedChanged55 = cProto.deletedChanged;
  8933. cProto.deletedChanged = dProto.deletedChangedNoSelfLeakage;
  8934. flgLeakageFixApplied |= 32;
  8935. }
  8936.  
  8937. }
  8938.  
  8939. const flgTotal = USE_ADVANCED_TICKING ? 1 + 2 + 32 : 1 + 2 + 4 + 8 + 16 + 32;
  8940.  
  8941. console1.log(`FIX_MEMORY_LEAKAGE_TICKER_[#${tagI}]: ${flgLeakageFixApplied} / ${flgTotal}`, cProto.is);
  8942.  
  8943. // ------------- FIX_MEMORY_LEAKAGE_TICKER_TIMER -------------
  8944.  
  8945.  
  8946.  
  8947. const canDoAdvancedTicking = 1 &&
  8948. ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION &&
  8949. typeof cProto.startCountdown === 'function' && !cProto.startCountdown49 && cProto.startCountdown.length === 2 &&
  8950. typeof cProto.updateTimeout === 'function' && !cProto.updateTimeout49 && cProto.updateTimeout.length === 1 &&
  8951. typeof cProto.isAnimationPausedChanged === 'function' && !cProto.isAnimationPausedChanged49 && cProto.isAnimationPausedChanged.length === 2 &&
  8952. typeof cProto.setContainerWidth === 'function' && cProto.setContainerWidth.length === 0 &&
  8953. typeof cProto.requestRemoval === 'function' && !cProto.requestRemoval49 && cProto.requestRemoval.length === 0
  8954. CSS.supports("left","clamp(-100%, calc( -100% * ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) ), 0%)");
  8955.  
  8956.  
  8957.  
  8958. if (USE_ADVANCED_TICKING && canDoAdvancedTicking && ENABLE_TICKERS_BOOSTED_STAMPING) {
  8959. // startResistanceUpdater();
  8960. // live replay video -> 48117005 -> 48117006 keep fire. ->48117007 0 -> 48117007 {...}
  8961. // live stream video -> 48117007 0 -> 48117007 YES
  8962.  
  8963. document.documentElement.setAttribute('r6-advanced-ticking', '');
  8964. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::START`)
  8965.  
  8966. const wio2 = dProto.wio2 || (dProto.wio2 = new IntersectionObserver((mutations) => {
  8967.  
  8968. for (const mutation of mutations) {
  8969. if (mutation.isIntersecting) {
  8970.  
  8971. const marker = mutation.target;
  8972. let endId = marker.id
  8973. if (!endId) continue;
  8974. let tid = endId.substring(0, endId.length - 2);
  8975. if (!tid) continue;
  8976. // let bId = `${tid}-b`;
  8977. const bgElm = document.querySelector(`#${tid}-b`);
  8978. if (!bgElm) continue;
  8979. const overlay = bgElm;
  8980.  
  8981. wio2.unobserve(marker);
  8982. marker.remove();
  8983. let p = overlay || 0;
  8984. let cn = 4;
  8985. while ((p = p.parentElement) instanceof HTMLElement_) {
  8986. if (p instanceof HTMLElement_) {
  8987. const cnt = insp(p);
  8988. if (cnt && typeof cnt.slideDown === 'function' && typeof cnt.setContainerWidth === 'function' && cnt.__advancedTicking038__ === 1) {
  8989.  
  8990. cnt.__advancedTicking038__ = 2;
  8991.  
  8992. let deletionMode = false;
  8993. const cntData = ((cnt || 0).__data || 0).data || (cnt || 0).data || 0;
  8994. if (timestampUnderLiveMode && cntData && cntData.durationSec > 0 && cntData.__timestampActionRequest__ > 0) {
  8995.  
  8996. // time choose - 0.2s for transition (slideDown sliding-down)
  8997. // 60hz = 17ms
  8998. // choose 0.28s
  8999. const targetFutureTime = cntData.__timestampActionRequest__ + cntData.durationSec * 1000;
  9000. // check whether the targetFutureTime is already the past
  9001. if (targetFutureTime + 280 < Date.now()) {
  9002. // just dispose
  9003. deletionMode = true;
  9004. }
  9005. } else if (__LCRInjection__ && !timestampUnderLiveMode && cntData && cntData.durationSec > 0 && cntData.__progressAt__ > 0) {
  9006.  
  9007. const targetFutureTime = (cntData.__progressAt__ + cntData.durationSec);
  9008. // check whether the targetFutureTime is already the past
  9009. if (targetFutureTime + 0.28 < playerProgressChangedArg1) {
  9010. // just dispose
  9011. deletionMode = true;
  9012. }
  9013.  
  9014.  
  9015. }
  9016.  
  9017.  
  9018. if (deletionMode) {
  9019. __requestRemoval__(cnt);
  9020. } else {
  9021.  
  9022. const w = cnt.hostElement.style.width;
  9023. if (w === "auto" || w === "") cnt.setContainerWidth();
  9024. cnt.slideDown();
  9025. }
  9026.  
  9027. break;
  9028. }
  9029. }
  9030. cn--;
  9031. if (!cn) {
  9032. console.log('cnt not found for ticker-bg-overlay');
  9033. break;
  9034. }
  9035. }
  9036.  
  9037.  
  9038. }
  9039. }
  9040.  
  9041. // console.log(mutations);
  9042. }, {
  9043.  
  9044. rootMargin: '0px',
  9045. threshold: [1]
  9046.  
  9047. }));
  9048.  
  9049.  
  9050.  
  9051. cProto.__isTickerItem58__ = 1;
  9052. cProto.attached747 = cProto.attached;
  9053. cProto.attached = function () {
  9054. Promise.resolve().then(()=>{
  9055. if(this.hostElement && this.isAttached && this.hostElement.isConnected && this.parentComponent){
  9056. const data = this.data;
  9057. if(data){
  9058. const pr = this[`_pr7_${data.id}`]
  9059. if(pr){
  9060. this[`_pr7_${data.id}`] = null;
  9061. pr.resolve();
  9062. }
  9063. }
  9064.  
  9065. }
  9066. }).catch(console.warn);
  9067. return this.attached747();
  9068. };
  9069. cProto.setContainerWidth371 = cProto.setContainerWidth;
  9070. cProto.setContainerWidthPr9 = function(){
  9071. if (this.pz485 !== this.pz483) {
  9072. this.pz485 = this.pz483;
  9073. const cnt = this;
  9074. if (cnt && cnt.data) {
  9075. const data = cnt.data;
  9076. const pr9 = cnt[`_pr9_${data.id}`]
  9077. if (pr9) {
  9078. return pr9;
  9079. }
  9080. }
  9081. }
  9082. }
  9083. cProto.startCountdown = dProto.startCountdownAdv || (dProto.startCountdownAdv = function (a, b) {
  9084.  
  9085.  
  9086. timeFn748(kRef(this));
  9087.  
  9088.  
  9089. });
  9090.  
  9091. cProto.updateTimeout = dProto.updateTimeoutAdv || (dProto.updateTimeoutAdv = function (a) {
  9092.  
  9093.  
  9094.  
  9095. });
  9096.  
  9097. cProto.isAnimationPausedChanged = dProto.isAnimationPausedChangedAdv || (dProto.isAnimationPausedChangedAdv = function (a, b) {
  9098.  
  9099.  
  9100.  
  9101. });
  9102.  
  9103.  
  9104. if (typeof cProto.slideDown === 'function' && !cProto.slideDown43 && cProto.slideDown.length === 0) {
  9105.  
  9106. cProto.slideDown43 = cProto.slideDown;
  9107. cProto.slideDown = dProto.slideDownAdv || (dProto.slideDownAdv = async function () {
  9108.  
  9109. // console.log('calling slideDown', Date.now())
  9110. if (this.__advancedTicking038__) {
  9111.  
  9112. if (this.__advancedTicking038__ === 1) this.__advancedTicking038__ = 2; // ignore intersectionobserver detection
  9113.  
  9114.  
  9115. const hostElement = this.hostElement;
  9116. const container = this.$.container;
  9117.  
  9118. const parentComponentCnt = insp(this.parentComponent);
  9119. const parentComponentElm = parentComponentCnt? parentComponentCnt.hostElement : null;
  9120.  
  9121. if (hostElement instanceof HTMLElement_ && container instanceof HTMLElement_ && parentComponentElm instanceof HTMLElement_) {
  9122. // const prevTransitionClosingElm = kRef(prevTransitionClosing);
  9123. // if (prevTransitionClosingElm !== hostElement) {
  9124. // prevTransitionClosingElm && prevTransitionClosingElm.classList.add('ticker-no-transition-time');
  9125. // prevTransitionClosing = mWeakRef(hostElement);
  9126. // }
  9127. // if (hostElement.classList.contains('ticker-no-transition-time')) hostElement.classList.remove('ticker-no-transition-time');
  9128. hostElement.classList.add('r6-closing-ticker');
  9129.  
  9130. if (!transitionEndHooks.has(parentComponentElm)) {
  9131. transitionEndHooks.add(parentComponentElm);
  9132. document.addEventListener('transitionend', transitionEndAfterFn, passiveCapture);
  9133. }
  9134.  
  9135. const pr = new PromiseExternal();
  9136. transitionEndAfterFnSimple.set(hostElement, pr);
  9137. transitionEndAfterFnSimple.set(container, pr);
  9138. transitionEndAfterFnSimpleEnable++;
  9139. hostElement.classList.add("sliding-down");
  9140. await pr.then();
  9141. transitionEndAfterFnSimpleEnable--;
  9142. transitionEndAfterFnSimple.delete(hostElement);
  9143. transitionEndAfterFnSimple.delete(container);
  9144. if (this && this.hostElement instanceof HTMLElement_) {
  9145.  
  9146. this.collapse();
  9147. }
  9148. return;
  9149. }
  9150. }
  9151. this.slideDown43();
  9152.  
  9153. });
  9154.  
  9155.  
  9156. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::slideDown - OK`)
  9157. } else {
  9158.  
  9159. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::slideDown - NG`)
  9160. }
  9161.  
  9162.  
  9163. if (typeof cProto.collapse === 'function' && !cProto.collapse43 && cProto.collapse.length === 0) {
  9164. cProto.collapse43 = cProto.collapse;
  9165. cProto.collapse = dProto.collapseAdv || (dProto.collapseAdv = async function () {
  9166.  
  9167.  
  9168. if (this.__advancedTicking038__) {
  9169.  
  9170.  
  9171. if (this.__advancedTicking038__ === 1) this.__advancedTicking038__ = 2; // ignore intersectionobserver detection
  9172.  
  9173.  
  9174. const hostElement = this.hostElement;
  9175. const container = this.$.container;
  9176.  
  9177. const parentComponentCnt = insp(this.parentComponent);
  9178. const parentComponentElm = parentComponentCnt ? parentComponentCnt.hostElement : null;
  9179.  
  9180. if (hostElement instanceof HTMLElement_ && container instanceof HTMLElement_ && parentComponentElm instanceof HTMLElement_) {
  9181. // const prevTransitionClosingElm = kRef(prevTransitionClosing);
  9182. // if (prevTransitionClosingElm !== hostElement) {
  9183. // prevTransitionClosingElm && prevTransitionClosingElm.classList.add('ticker-no-transition-time');
  9184. // prevTransitionClosing = mWeakRef(hostElement);
  9185. // }
  9186. // if (hostElement.classList.contains('ticker-no-transition-time')) hostElement.classList.remove('ticker-no-transition-time');
  9187. hostElement.classList.add('r6-closing-ticker');
  9188.  
  9189. if (!transitionEndHooks.has(parentComponentElm)) {
  9190. transitionEndHooks.add(parentComponentElm);
  9191. document.addEventListener('transitionend', transitionEndAfterFn, passiveCapture);
  9192. }
  9193.  
  9194. const pr = new PromiseExternal();
  9195. transitionEndAfterFnSimple.set(hostElement, pr);
  9196. transitionEndAfterFnSimple.set(container, pr);
  9197. transitionEndAfterFnSimpleEnable++;
  9198. hostElement.classList.add("collapsing");
  9199. hostElement.style.width = "0";
  9200. await pr.then();
  9201. transitionEndAfterFnSimpleEnable--;
  9202. transitionEndAfterFnSimple.delete(hostElement);
  9203. transitionEndAfterFnSimple.delete(container);
  9204. if (this && this.hostElement instanceof HTMLElement_) {
  9205.  
  9206. this.requestRemoval();
  9207. }
  9208.  
  9209. return;
  9210. }
  9211.  
  9212.  
  9213. }
  9214. this.collapse43();
  9215.  
  9216.  
  9217. });
  9218.  
  9219. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::collapse - OK`)
  9220. } else {
  9221.  
  9222. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::collapse - NG`)
  9223. }
  9224.  
  9225.  
  9226.  
  9227. if (typeof cProto.requestRemoval === 'function' && !cProto.requestRemoval49 && cProto.requestRemoval.length === 0) {
  9228. const removalList = [];
  9229. let removalRes = false;
  9230. const removalFn = () => {
  9231. if (removalList.length === 0) return;
  9232. for (const cnt of removalList) {
  9233. let r;
  9234. try {
  9235. r = cnt?.requestRemoval49();
  9236. } catch (e) { }
  9237. if (r !== undefined && removalRes === false) {
  9238. removalRes = true;
  9239. console.log(`[yt-chat-ticker] requestRemoval49 returns ${r}`);
  9240. }
  9241. }
  9242. removalList.length = 0;
  9243. };
  9244. cProto.requestRemoval49 = cProto.requestRemoval;
  9245. cProto.requestRemoval = dProto.requestRemovalAdv || (dProto.requestRemovalAdv = function () {
  9246. const hostElement = this.hostElement;
  9247. if (this.__advancedTicking038__) {
  9248. try {
  9249. const overlayBg = hostElement.querySelector('ticker-bg-overlay[id]');
  9250. if (overlayBg) {
  9251. const overlayBgId = overlayBg.id;
  9252. const tid = overlayBgId ? overlayBgId.substring(0, overlayBgId.length - 2) : '';
  9253. const endElm = tid ? document.querySelector(`#${tid}-e`) : null;
  9254. if (endElm) {
  9255. wio2.unobserve(endElm);
  9256. endElm.remove();
  9257. }
  9258. }
  9259. } catch (e) { }
  9260. this.__advancedTicking038__ = 2;
  9261. // console.log('requestRemoval!!')
  9262. if (hostElement instanceof HTMLElement_) {
  9263. // otherwise the startCountDown not working
  9264. hostElement.style.removeProperty('--ticker-start-time');
  9265. hostElement.style.removeProperty('--ticker-duration-time');
  9266. }
  9267. if (REUSE_TICKER) {
  9268. const cntData = this.data;
  9269. if (hostElement instanceof HTMLElement_ && cntData.id && cntData.fullDurationSec && !hostElement.hasAttribute('__reuseid__')) {
  9270. hostElement.setAttribute('__reuseid__', reuseId);
  9271. hostElement.setAttribute('__nogc__', ''); // provided to leakage detection script
  9272. // this.__markReuse13__ = true;
  9273. reuseStore.set(`<${this.is}>${cntData.id}:${cntData.fullDurationSec}`, mWeakRef(this));
  9274. }
  9275. }
  9276. }
  9277. if (hostElement instanceof HTMLElement_) {
  9278. // try {
  9279. // // hostElement.remove();
  9280.  
  9281. // if (!hostElement.classList.contains('ticker-no-transition-time')) hostElement.classList.add('ticker-no-transition-time');
  9282. // } catch (e) { }
  9283.  
  9284. try {
  9285.  
  9286. hostElement.classList.remove('r6-closing-ticker');
  9287. hostElement.classList.remove('r6-width-adjustable-f');
  9288. } catch (e) { }
  9289.  
  9290. // if(ADVANCED_TICKING_MEMORY_CLEAN_FOR_REMOVAL){
  9291. // const wr = mWeakRef(hostElement);
  9292. // const wf = ()=>{
  9293. // const element = kRef(wr);
  9294. // if(!element) {
  9295. // console.log('[yt-chat-removalrequest] element was memory cleaned.');
  9296. // return;
  9297. // }
  9298.  
  9299. // setTimeout(wf, 8000);
  9300. // if(element.isConnected){
  9301. // console.log('[yt-chat-removalrequest] element is still connected to DOM Tree.');
  9302. // return;
  9303. // }
  9304.  
  9305. // const cnt = insp(element)
  9306. // if(typeof cnt.requestRemoval !== 'function'){
  9307.  
  9308. // console.log('[yt-chat-removalrequest] element is not connected to cnt.');
  9309. // return;
  9310. // }
  9311. // console.log('[yt-chat-removalrequest] element is not GC.');
  9312. // try{
  9313. // cnt.data = null;
  9314. // }catch(e){}
  9315.  
  9316. // Object.setPrototypeOf(cnt, Object.prototype);
  9317. // for(const k of Object.getOwnPropertyNames(cnt)){
  9318. // try{
  9319. // cnt[k] = null;
  9320. // }catch(e){}
  9321.  
  9322. // try{
  9323. // delete cnt[k];
  9324. // }catch(e){}
  9325. // }
  9326.  
  9327.  
  9328. // for(const k of Object.getOwnPropertySymbols(cnt)){
  9329. // try{
  9330. // cnt[k] = null;
  9331. // }catch(e){}
  9332.  
  9333. // try{
  9334. // delete cnt[k];
  9335. // }catch(e){}
  9336. // }
  9337.  
  9338. // }
  9339. // setTimeout(wf, 8000);
  9340. // }
  9341.  
  9342. removalList.push(this);
  9343. timelineResolve().then(removalFn);
  9344. }
  9345. });
  9346.  
  9347.  
  9348. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::requestRemoval - OK`)
  9349. } else {
  9350.  
  9351. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::requestRemoval - NG`)
  9352. }
  9353.  
  9354.  
  9355. if (typeof cProto.computeContainerStyle === 'function' && !cProto.computeContainerStyle49 && cProto.computeContainerStyle.length === 2) {
  9356. cProto.computeContainerStyle49 = cProto.computeContainerStyle;
  9357. cProto.computeContainerStyle = dProto.computeContainerStyleAdv || (dProto.computeContainerStyleAdv = function (a, b) {
  9358. if (this.__advancedTicking038__) {
  9359. return "";
  9360. }
  9361. return this.computeContainerStyle49(a, b);
  9362. });
  9363.  
  9364.  
  9365. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::computeContainerStyle - OK`)
  9366. } else {
  9367.  
  9368. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::computeContainerStyle - NG`)
  9369. }
  9370.  
  9371.  
  9372.  
  9373. if(ENABLE_TICKERS_BOOSTED_STAMPING && DISABLE_DYNAMIC_TICKER_WIDTH && typeof cProto.updateWidthOnDataChanged === 'function' && cProto.updateWidthOnDataChanged.length === 0 && !cProto.updateWidthOnDataChanged41){
  9374.  
  9375. cProto.updateWidthOnDataChanged41 = cProto.updateWidthOnDataChanged;
  9376. cProto.updateWidthOnDataChanged = dProto.updateWidthOnDataChangedAdv || (dProto.updateWidthOnDataChangedAdv = function(){
  9377. const style = this.hostElement.style;
  9378. style.width = "";
  9379. style.overflow = "";
  9380. });
  9381.  
  9382. }
  9383.  
  9384.  
  9385. if (!cProto.setStandardContainerWidth8447) {
  9386. cProto.setStandardContainerWidth8447 = dProto.setStandardContainerWidthAdv || (dProto.setStandardContainerWidthAdv = async function (kName) {
  9387.  
  9388. if (typeof this.setContainerWidthPr9 === 'function') {
  9389. const pr9 = this.setContainerWidthPr9();
  9390. if (pr9) {
  9391. await pr9;
  9392. }
  9393. }
  9394.  
  9395. const hostElement = (this || 0).hostElement;
  9396. const container = this.$.container;
  9397.  
  9398. let qw = null;
  9399. let qt = '';
  9400.  
  9401. {
  9402.  
  9403. let maxC = 4;
  9404.  
  9405. for (let p = qt = hostElement.getAttribute('r6-ticker-width') || ''; maxC--;) {
  9406.  
  9407. const ed = `${hostElement.id}`
  9408. if (!p || !p.startsWith(`${ed}::`)) {
  9409.  
  9410. const w = hostElement.style.width;
  9411. if (w !== '' && w !== 'auto') hostElement.style.width = 'auto';
  9412.  
  9413. const res = await widthReq(container);
  9414.  
  9415. if (res.width < 1 || !Number.isFinite(res.width)) {
  9416. // just skip due to iron-page hidden
  9417. return;
  9418. }
  9419.  
  9420. hostElement.setAttribute('r6-ticker-width', p = qt = `${ed}::${(res.width).toFixed(2)}`);
  9421.  
  9422. } else {
  9423. qw = p.split('::');
  9424. break;
  9425. }
  9426.  
  9427. }
  9428.  
  9429. }
  9430.  
  9431. if (!qw) {
  9432.  
  9433. console.log('container width failure');
  9434. if(kName === 'setContainerWidth') this.setContainerWidth41(); else this.setRevampContainerWidth41();
  9435. return; // failure
  9436. }
  9437.  
  9438.  
  9439. const shouldAnimateIn = ((this || 0).ytLiveChatTickerItemBehavior || 0).shouldAnimateIn || (this || 0).shouldAnimateIn || false;
  9440. if (shouldAnimateIn) {
  9441.  
  9442. stackDM(async () => {
  9443.  
  9444. if (hostElement.getAttribute('r6-ticker-width') !== qt || hostElement.isConnected !== true) return;
  9445. if (hostElement.previousElementSibling || isTickerItemsScrolling()) {
  9446.  
  9447. hostElement.style.width = `${qw[1]}px`;
  9448.  
  9449. } else {
  9450.  
  9451. const w = hostElement.style.width;
  9452. if (w !== '0px' && w !== '0') hostElement.style.width = '0';
  9453.  
  9454. await widthReq(container);
  9455.  
  9456. hostElement.style.width = `${qw[1]}px`;
  9457. }
  9458.  
  9459.  
  9460. });
  9461.  
  9462.  
  9463. } else {
  9464.  
  9465.  
  9466. stackDM(async () => {
  9467.  
  9468.  
  9469.  
  9470. if (hostElement.getAttribute('r6-ticker-width') !== qt || hostElement.isConnected !== true) return;
  9471.  
  9472. hostElement.style.width = `${qw[1]}px`;
  9473.  
  9474. });
  9475. }
  9476.  
  9477.  
  9478.  
  9479. });
  9480. }
  9481.  
  9482. if (typeof cProto.setRevampContainerWidth === 'function' && !cProto.setRevampContainerWidth41 && cProto.setRevampContainerWidth.length === 0 && typeof cProto.setStandardContainerWidth8447 === 'function' && cProto.setStandardContainerWidth8447.length === 1) {
  9483. cProto.setRevampContainerWidth41 = cProto.setRevampContainerWidth;
  9484. if (ENABLE_TICKERS_BOOSTED_STAMPING && DISABLE_DYNAMIC_TICKER_WIDTH) {
  9485.  
  9486. cProto.setRevampContainerWidth = dProto.setRevampContainerWidthAdv || (dProto.setRevampContainerWidthAdv = async function () {
  9487. const hostElement = this.hostElement;
  9488. if (((hostElement || 0).style || 0).width) hostElement.style.width = '';
  9489. return;
  9490. });
  9491.  
  9492. } else {
  9493.  
  9494.  
  9495.  
  9496. cProto.setRevampContainerWidth = dProto.setRevampContainerWidthAdv || (dProto.setRevampContainerWidthAdv = async function () {
  9497.  
  9498. // not sure the reason for auto instead of pixel.
  9499. // this is a new function in Dec 2024, but not mainly adopted in the coding yet
  9500.  
  9501. /*
  9502. var a = this;
  9503. (R(this.hostElement).querySelector("#container").clientWidth || 0) === 0 ? (this.hostElement.style.overflow = "visible",
  9504. this.hostElement.style.width = "auto") : (this.hostElement.style.overflow = "hidden",
  9505. this.ytLiveChatTickerItemBehavior.shouldAnimateIn ? (this.hostElement.style.width = "0",
  9506. Zu(function() {
  9507. a.hostElement.style.width = "auto"
  9508. }, 1)) : this.hostElement.style.width = "auto")
  9509. */
  9510.  
  9511.  
  9512. return this.setStandardContainerWidth8447('setRevampContainerWidth');
  9513.  
  9514. });
  9515. }
  9516.  
  9517.  
  9518. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::setRevampContainerWidth - OK`)
  9519. } else {
  9520.  
  9521. DEBUG_skipLog001 || console1.log(`USE_ADVANCED_TICKING[#${tagI}]::setRevampContainerWidth - NG (acceptable)`)
  9522. }
  9523.  
  9524.  
  9525. if (typeof cProto.setContainerWidth === 'function' && !cProto.setContainerWidth41 && cProto.setContainerWidth.length === 0 && typeof cProto.setStandardContainerWidth8447 === 'function' && cProto.setStandardContainerWidth8447.length === 1) {
  9526. cProto.setContainerWidth41 = cProto.setContainerWidth;
  9527.  
  9528. if (ENABLE_TICKERS_BOOSTED_STAMPING && DISABLE_DYNAMIC_TICKER_WIDTH) {
  9529.  
  9530. cProto.setContainerWidth = dProto.setContainerWidthAdv || (dProto.setContainerWidthAdv = async function () {
  9531. const hostElement = this.hostElement;
  9532. if (((hostElement || 0).style || 0).width) hostElement.style.width = '';
  9533. return;
  9534. });
  9535.  
  9536. } else {
  9537.  
  9538. cProto.setContainerWidth = dProto.setContainerWidthAdv || (dProto.setContainerWidthAdv = async function () {
  9539.  
  9540.  
  9541.  
  9542. /*
  9543. var a = this
  9544. , b = R(this.hostElement).querySelector("#container").clientWidth || 0;
  9545. b === 0 ? (this.hostElement.style.overflow = "visible",
  9546. this.hostElement.style.width = "auto") : (this.hostElement.style.overflow = "hidden",
  9547. this.shouldAnimateIn ? (this.hostElement.style.width = "0",
  9548. Zu(function() {
  9549. a.hostElement.style.width = b + "px"
  9550. }, 1)) : this.hostElement.style.width = b + "px")
  9551. */
  9552. return this.setStandardContainerWidth8447('setContainerWidth');
  9553.  
  9554. });
  9555.  
  9556. }
  9557.  
  9558.  
  9559.  
  9560. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::setContainerWidth - OK`)
  9561. } else {
  9562.  
  9563.  
  9564. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::setContainerWidth - NG`)
  9565. }
  9566.  
  9567.  
  9568.  
  9569.  
  9570. } else if (USE_ADVANCED_TICKING) {
  9571. console1.log(`USE_ADVANCED_TICKING[#${tagI}] is not injected.`);
  9572. }
  9573.  
  9574.  
  9575.  
  9576. }
  9577.  
  9578. const selector = tags.join(', ');
  9579. const elements = document.querySelectorAll(selector);
  9580. if (elements.length >= 1) {
  9581. for (const elm of elements) {
  9582. if (insp(elm).isAttached === true) {
  9583. fpTicker(elm);
  9584. }
  9585. }
  9586. }
  9587.  
  9588. console1.log("[End]");
  9589. groupEnd();
  9590.  
  9591.  
  9592. }).catch(console.warn);
  9593.  
  9594. if(FIX_MEMORY_LEAKAGE_TICKER_DATACHANGED_setContainerWidth){
  9595.  
  9596. /**
  9597. *
  9598. *
  9599. *
  9600. *
  9601. cT.prototype.dataChanged = function() {
  9602. var a = this;
  9603. this.data && (Q(this.hostElement).querySelector("#content").style.color = this.ytLiveChatTickerItemBehavior.colorFromDecimal(this.data.detailTextColor),
  9604. this.hostElement.ariaLabel = this.computeAriaLabel(this.data),
  9605. this.ytLiveChatTickerItemBehavior.startCountdown(this.data.durationSec, this.data.fullDurationSec),
  9606. qw(function() {
  9607. a.ytLiveChatTickerItemBehavior.setContainerWidth()
  9608. }))
  9609. }
  9610.  
  9611.  
  9612. znb.prototype.dataChanged = function(a) {
  9613. var b = this;
  9614. a && (a.tickerThumbnails.length > 1 && Q(this.hostElement).querySelector("#content").classList.add("multiple-thumbnails"),
  9615. this.ytLiveChatTickerItemBehavior.startCountdown(a.durationSec, a.fullDurationSec),
  9616. qw(function() {
  9617. b.ytLiveChatTickerItemBehavior.setContainerWidth()
  9618. }))
  9619. }
  9620.  
  9621. *
  9622. */
  9623.  
  9624. const dProto = {
  9625. dataChanged54500: function () {
  9626. // prevent memory leakage due to _.ytLiveChatTickerItemBehavior.setContainerWidth() in _.dataChanged
  9627. if (typeof (this.ytLiveChatTickerItemBehavior || 0).setContainerWidth === 'function') {
  9628. try {
  9629. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  9630. return this.dataChanged544.call(this.__proxySelf0__);
  9631. } catch (e) {
  9632. console.log('dataChanged54500 ERROR');
  9633. console.error(e);
  9634. }
  9635. } else {
  9636. return this.dataChanged544();
  9637. }
  9638. },
  9639. dataChanged54501: function (a) {
  9640. // prevent memory leakage due to _.ytLiveChatTickerItemBehavior.setContainerWidth() in _.dataChanged
  9641. if (typeof (this.ytLiveChatTickerItemBehavior || 0).setContainerWidth === 'function') {
  9642. try {
  9643. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  9644. return this.dataChanged544.call(this.__proxySelf0__, a);
  9645. } catch (e) {
  9646. console.log('dataChanged54501 ERROR');
  9647. console.error(e);
  9648. }
  9649. } else {
  9650. return this.dataChanged544(a);
  9651. }
  9652. },
  9653. }
  9654.  
  9655. for (const sto of [
  9656. 'yt-live-chat-ticker-sponsor-item-renderer',
  9657. 'yt-live-chat-ticker-paid-sticker-item-renderer'
  9658. ].map(tag => [tag, customElements.whenDefined(tag)])) {
  9659.  
  9660. const [tag, promise] = sto;
  9661.  
  9662. promise.then(()=>{
  9663.  
  9664. const dummy = document.createElement(tag);
  9665.  
  9666. const cProto = getProto(dummy);
  9667. if (!cProto || !cProto.attached) {
  9668. console.warn(`proto.attached for ${tag} is unavailable.`);
  9669. return;
  9670. }
  9671.  
  9672. if (!cProto.dataChanged || cProto.dataChanged544 || typeof cProto.dataChanged !== 'function' || !(cProto.dataChanged.length >= 0 && cProto.dataChanged.length <= 1)) return;
  9673.  
  9674. cProto.dataChanged544 = cProto.dataChanged;
  9675.  
  9676. if (cProto.dataChanged.length === 0) cProto.dataChanged = dProto.dataChanged54500;
  9677. else if (cProto.dataChanged.length === 1) cProto.dataChanged = dProto.dataChanged54501;
  9678.  
  9679.  
  9680.  
  9681. })
  9682.  
  9683.  
  9684. }
  9685.  
  9686. }
  9687.  
  9688. customElements.whenDefined('yt-live-chat-ticker-renderer').then(() => {
  9689.  
  9690. mightFirstCheckOnYtInit();
  9691. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-ticker-renderer hacks");
  9692. console1.log("[Begin]");
  9693. (() => {
  9694.  
  9695. /* pending!!
  9696.  
  9697. handleLiveChatAction
  9698.  
  9699. removeTickerItemById
  9700.  
  9701. _itemsChanged
  9702. itemsChanged
  9703.  
  9704. handleMarkChatItemAsDeletedAction
  9705. handleMarkChatItemsByAuthorAsDeletedAction
  9706. handleRemoveChatItemByAuthorAction
  9707.  
  9708.  
  9709. */
  9710.  
  9711. const tag = "yt-live-chat-ticker-renderer"
  9712. const dummy = document.createElement(tag);
  9713.  
  9714. const cProto = getProto(dummy);
  9715. if (!cProto || !cProto.attached) {
  9716. console1.warn(`proto.attached for ${tag} is unavailable.`);
  9717. return;
  9718. }
  9719.  
  9720. // const imgCollection = document.getElementsByTagName('IMG');
  9721.  
  9722. if (ENABLE_TICKERS_BOOSTED_STAMPING && typeof cProto.notifyPath === 'function' && cProto.notifyPath.length === 2 && typeof cProto.stampDomArraySplices_ === 'function' && cProto.stampDomArraySplices_.length === 3 && !cProto.notifyPath371) {
  9723.  
  9724. rendererStamperFactory(cProto, {
  9725. key: 'proceedStampDomArraySplices371_',
  9726. stamperDomClass: 'style-scope yt-live-chat-ticker-renderer yt-live-chat-ticker-stampdom'
  9727. });
  9728.  
  9729. cProto.notifyPath371 = cProto.notifyPath;
  9730.  
  9731. cProto.notifyPath = function (a, b) {
  9732. // console.log(a, b);
  9733. if (a === 'tickerItems.splices' && (b||0).indexSplices && !this.ec388) {
  9734. const indexSplices = b.indexSplices;
  9735. if (indexSplices.length === 1 || typeof indexSplices.length === "undefined") {
  9736. const indexSplice = indexSplices[0] || indexSplices;
  9737. if (indexSplice.type === 'splice' && (indexSplice.addedCount >= 1 || (indexSplice.removed || []).length >= 1)) {
  9738. // console.log(1039, a, indexSplice);
  9739. this.ec388 = true;
  9740. const r = this.notifyPath371(a, b);
  9741. this.ec388 = false;
  9742. return r;
  9743. }
  9744. }
  9745. }
  9746.  
  9747. return this.notifyPath371(a, b);
  9748. }
  9749.  
  9750. cProto.stampDomArraySplices371_ = cProto.stampDomArraySplices_;
  9751.  
  9752. cProto.stampDomArraySplices_ = function (a, b, c) {
  9753. if (a === 'tickerItems' && b === 'ticker-items' && (c || 0).indexSplices) {
  9754. if (this.ec388) {
  9755. const indexSplices = c.indexSplices;
  9756. if (indexSplices.length === 1 || typeof indexSplices.length === "undefined") {
  9757. const indexSplice = indexSplices[0] || indexSplices;
  9758. if (indexSplice.type === 'splice' && (indexSplice.addedCount >= 1 || (indexSplice.removed || 0).length >= 1)) {
  9759. // console.log(1059, a, b, indexSplice);
  9760. if (this.proceedStampDomArraySplices371_(a, b, indexSplice)) return;
  9761. }
  9762. }
  9763. } else {
  9764. console.warn('stampDomArraySplices_ warning', ...arguments);
  9765. }
  9766. }
  9767. return this.stampDomArraySplices371_(...arguments);
  9768. };
  9769.  
  9770. cProto.stampDomArray366_ = cProto.stampDomArray_;
  9771. cProto.stampDomArray_ = function (items, containerId, componentConfig, rxConfig, shouldCallback, isStableList) {
  9772. const isTickerRendering = items === this.tickerItems && containerId === 'ticker-items';
  9773. const isMessageListRendering = items === this.visibleItems && containerId === 'items';
  9774.  
  9775. if(!isTickerRendering && !isMessageListRendering){
  9776. console.log('stampDomArray_ warning 0xF501', ...arguments)
  9777. return this.stampDomArray366_(...arguments);
  9778. }
  9779.  
  9780. const container = (this.$ || 0)[containerId];
  9781. if (!container) {
  9782. console.log('stampDomArray_ warning 0xF502', ...arguments)
  9783. return this.stampDomArray366_(...arguments);
  9784. }
  9785.  
  9786. if (container[sFirstElementChild] === null && items.length === 0){
  9787.  
  9788. }else{
  9789. const cTag = isTickerRendering ? 'tickerItems' : 'visibleItems';
  9790. this.proceedStampDomArraySplices371_(cTag, containerId, {
  9791. addedCount: items.length,
  9792. removedCount: container.childElementCount
  9793. });
  9794. }
  9795.  
  9796. const f = () => {
  9797. this.markDirty && this.markDirty();
  9798. const detail = {
  9799. container
  9800. };
  9801. shouldCallback && this.hostElement.dispatchEvent(new CustomEvent("yt-rendererstamper-finished", {
  9802. bubbles: !0,
  9803. cancelable: !1,
  9804. composed: !0,
  9805. detail
  9806. }));
  9807. detail.container = null;
  9808. };
  9809. if (this.ec389pr) {
  9810. this.ec389pr.then(f)
  9811. } else {
  9812. f();
  9813. }
  9814.  
  9815. };
  9816.  
  9817. }
  9818.  
  9819.  
  9820.  
  9821. if(typeof cProto.createComponent_ === 'function' && cProto.createComponent_.length === 3 && !cProto.createComponent58_ ){
  9822.  
  9823. cProto.createComponent58_ = cProto.createComponent_;
  9824. cProto.createComponent_ = function (a, b, c) {
  9825.  
  9826. const z = customCreateComponent(a, b, c);
  9827. if (z !== undefined) return z;
  9828. const r = this.createComponent58_(a, b, c);
  9829. return r;
  9830.  
  9831. }
  9832.  
  9833. }
  9834.  
  9835.  
  9836.  
  9837.  
  9838.  
  9839.  
  9840.  
  9841.  
  9842. /* Dec 2024 */
  9843.  
  9844. /*
  9845.  
  9846.  
  9847. f.handleLiveChatActions = function(a) {
  9848. a.length && (a.forEach(this.handleLiveChatAction, this),
  9849. this.updateHighlightedItem(),
  9850. this.shouldAnimateIn = !0)
  9851. }
  9852. ;
  9853. f.handleLiveChatAction = function(a) {
  9854. var b = z(a, fL)
  9855. , c = z(a, gL)
  9856. , d = z(a, eL)
  9857. , e = z(a, gdb)
  9858. , g = z(a, rdb)
  9859. , k = z(a, Deb);
  9860. a = z(a, Ceb);
  9861. 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)
  9862. }
  9863. */
  9864.  
  9865.  
  9866. if(USE_ADVANCED_TICKING && !cProto.handleLiveChatActions47 && typeof cProto.handleLiveChatActions === 'function' && cProto.handleLiveChatActions.length ===1){
  9867.  
  9868. cProto.handleLiveChatActions47 = cProto.handleLiveChatActions;
  9869.  
  9870. cProto.handleLiveChatActions = function (a) {
  9871.  
  9872. // first loading in livestream. so this is required for sorting.
  9873.  
  9874. try{
  9875. preprocessChatLiveActions(a);
  9876. }catch(e){
  9877. console.warn(e);
  9878. }
  9879. return this.handleLiveChatActions47(a);
  9880.  
  9881. }
  9882.  
  9883. console1.log("USE_ADVANCED_TICKING::handleLiveChatActions - OK");
  9884.  
  9885. }else if(USE_ADVANCED_TICKING){
  9886.  
  9887.  
  9888. console1.log("USE_ADVANCED_TICKING::handleLiveChatActions - NG");
  9889.  
  9890. }
  9891.  
  9892. // yt-live-chat-ticker-renderer hacks
  9893.  
  9894.  
  9895. if (RAF_FIX_keepScrollClamped) {
  9896.  
  9897. // to be improved
  9898.  
  9899. if (typeof cProto.keepScrollClamped === 'function' && !cProto.keepScrollClamped72 && fnIntegrity(cProto.keepScrollClamped) === '0.17.10') {
  9900.  
  9901. cProto.keepScrollClamped72 = cProto.keepScrollClamped;
  9902. cProto.keepScrollClamped = function () {
  9903.  
  9904. const cnt = kRef(this);
  9905. if (!cnt) return;
  9906. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  9907.  
  9908. cnt._bound_keepScrollClamped = cnt._bound_keepScrollClamped || cnt.keepScrollClamped.bind(mWeakRef(cnt));
  9909. cnt.scrollClampRaf = requestAnimationFrame(cnt._bound_keepScrollClamped);
  9910. cnt.maybeClampScroll()
  9911. }
  9912.  
  9913. console1.log('RAF_FIX: keepScrollClamped', tag, "OK")
  9914. } else {
  9915.  
  9916. assertor(() => fnIntegrity(cProto.keepScrollClamped, '0.17.10'));
  9917. console1.log('RAF_FIX: keepScrollClamped', tag, "NG")
  9918. }
  9919.  
  9920. }
  9921.  
  9922.  
  9923. if (RAF_FIX_scrollIncrementally && typeof cProto.startScrolling === 'function' && typeof cProto.scrollIncrementally === 'function'
  9924. && '|1.43.31|1.44.31|'.indexOf('|' + fnIntegrity(cProto.startScrolling) + '|') >= 0
  9925. && '|1.78.45|1.82.43|1.43.31|'.indexOf('|' + fnIntegrity(cProto.scrollIncrementally) + '|') >= 0) {
  9926. // to be replaced by animator
  9927.  
  9928. cProto.startScrolling = function (a) {
  9929.  
  9930. const cnt = kRef(this);
  9931. if (!cnt) return;
  9932. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  9933.  
  9934. cnt.scrollStopHandle && cnt.cancelAsync(cnt.scrollStopHandle);
  9935. cnt.asyncHandle && cancelAnimationFrame(cnt.asyncHandle);
  9936. cnt.lastFrameTimestamp = cnt.scrollStartTime = performance.now();
  9937. cnt.scrollRatePixelsPerSecond = a;
  9938. cnt._bound_scrollIncrementally = cnt._bound_scrollIncrementally || cnt.scrollIncrementally.bind(mWeakRef(cnt));
  9939. cnt.asyncHandle = requestAnimationFrame(cnt._bound_scrollIncrementally)
  9940. };
  9941.  
  9942. // related functions: startScrollBack, startScrollingLeft, startScrollingRight, etc.
  9943.  
  9944. /**
  9945. *
  9946. * // 2024.12.17
  9947. * // https://www.youtube.com/s/desktop/f7495da0/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  9948.  
  9949. f.startScrolling = function(a) {
  9950. this.scrollStopHandle && $u(this.scrollStopHandle);
  9951. this.asyncHandle && window.cancelAnimationFrame(this.asyncHandle);
  9952. this.scrollStartTime = performance.now();
  9953. this.lastFrameTimestamp = performance.now();
  9954. this.scrollRatePixelsPerSecond = a;
  9955. this.asyncHandle = window.requestAnimationFrame(this.scrollIncrementally.bind(this))
  9956. }
  9957. ;
  9958. f.scrollIncrementally = function(a) {
  9959. var b = a - (this.lastFrameTimestamp || 0);
  9960. R(this.hostElement).querySelector(this.tickerBarQuery).scrollLeft += b / 1E3 * (this.scrollRatePixelsPerSecond || 0);
  9961. this.maybeClampScroll();
  9962. this.updateArrows();
  9963. this.lastFrameTimestamp = a;
  9964. R(this.hostElement).querySelector(this.tickerBarQuery).scrollLeft > 0 || this.scrollRatePixelsPerSecond && this.scrollRatePixelsPerSecond > 0 ? this.asyncHandle = window.requestAnimationFrame(this.scrollIncrementally.bind(this)) : this.stopScrolling()
  9965. }
  9966. ;
  9967. *
  9968. */
  9969.  
  9970. /**
  9971. *
  9972. // 2024.12.20
  9973.  
  9974.  
  9975.  
  9976. f.startScrolling = function(a) {
  9977. this.scrollStopHandle && av(this.scrollStopHandle);
  9978. this.asyncHandle && window.cancelAnimationFrame(this.asyncHandle);
  9979. this.scrollStartTime = performance.now();
  9980. this.lastFrameTimestamp = performance.now();
  9981. this.scrollRatePixelsPerSecond = a;
  9982. this.asyncHandle = window.requestAnimationFrame(this.scrollIncrementally.bind(this))
  9983. }
  9984.  
  9985. *
  9986. *
  9987. */
  9988.  
  9989. cProto.__getTickerBarQuery__ = function () {
  9990. const tickerBarQuery = this.tickerBarQuery === '#items' ? this.$.items : this.hostElement.querySelector(this.tickerBarQuery);
  9991. return tickerBarQuery;
  9992. }
  9993.  
  9994. cProto.scrollIncrementally = (RAF_FIX_scrollIncrementally === 2) ? function (a) {
  9995.  
  9996. const cnt = kRef(this);
  9997. if (!cnt) return;
  9998. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  9999.  
  10000. const b = a - (cnt.lastFrameTimestamp || 0);
  10001. const rate = cnt.scrollRatePixelsPerSecond
  10002. const q = b / 1E3 * (rate || 0);
  10003.  
  10004. const tickerBarQuery = cnt.__getTickerBarQuery__();
  10005. const sl = tickerBarQuery.scrollLeft;
  10006. // console.log(rate, sl, q)
  10007. if (cnt.lastFrameTimestamp == cnt.scrollStartTime) {
  10008.  
  10009. } else if (q > -1e-5 && q < 1e-5) {
  10010.  
  10011. } else {
  10012. let cond1 = sl > 0 && rate > 0 && q > 0;
  10013. let cond2 = sl > 0 && rate < 0 && q < 0;
  10014. let cond3 = sl < 1e-5 && sl > -1e-5 && rate > 0 && q > 0;
  10015. if (cond1 || cond2 || cond3) {
  10016. tickerBarQuery.scrollLeft += q;
  10017. cnt.maybeClampScroll();
  10018. cnt.updateArrows();
  10019. }
  10020. }
  10021.  
  10022. cnt.lastFrameTimestamp = a;
  10023. cnt._bound_scrollIncrementally = cnt._bound_scrollIncrementally || cnt.scrollIncrementally.bind(mWeakRef(cnt));
  10024. 0 < tickerBarQuery.scrollLeft || rate && 0 < rate ? cnt.asyncHandle = requestAnimationFrame(cnt._bound_scrollIncrementally) : cnt.stopScrolling()
  10025. } : function (a) {
  10026.  
  10027. const cnt = kRef(this);
  10028. if (!cnt) return;
  10029. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10030.  
  10031. const b = a - (cnt.lastFrameTimestamp || 0);
  10032. const tickerBarQuery = cnt.__getTickerBarQuery__();
  10033. tickerBarQuery.scrollLeft += b / 1E3 * (cnt.scrollRatePixelsPerSecond || 0);
  10034. cnt.maybeClampScroll();
  10035. cnt.updateArrows();
  10036. cnt.lastFrameTimestamp = a;
  10037. cnt._bound_scrollIncrementally = cnt._bound_scrollIncrementally || cnt.scrollIncrementally.bind(mWeakRef(cnt));
  10038. 0 < tickerBarQuery.scrollLeft || cnt.scrollRatePixelsPerSecond && 0 < cnt.scrollRatePixelsPerSecond ? cnt.asyncHandle = requestAnimationFrame(cnt._bound_scrollIncrementally) : cnt.stopScrolling()
  10039. };
  10040.  
  10041. console1.log(`RAF_FIX: scrollIncrementally${RAF_FIX_scrollIncrementally}`, tag, "OK")
  10042. } else {
  10043. assertor(() => fnIntegrity(cProto.startScrolling, '1.43.31'))
  10044. || logFn('cProto.startScrolling', cProto.startScrolling)();
  10045. assertor(() => fnIntegrity(cProto.scrollIncrementally, '1.78.45'))
  10046. || logFn('cProto.scrollIncrementally', cProto.scrollIncrementally)();
  10047. console1.log('RAF_FIX: scrollIncrementally', tag, "NG")
  10048. }
  10049.  
  10050.  
  10051. if (CLOSE_TICKER_PINNED_MESSAGE_WHEN_HEADER_CLICKED && typeof cProto.attached === 'function' && !cProto.attached37 && typeof cProto.detached === 'function' && !cProto.detached37) {
  10052.  
  10053. cProto.attached37 = cProto.attached;
  10054. cProto.detached37 = cProto.detached;
  10055.  
  10056. let naohzId = 0;
  10057. cProto.__naohzId__ = 0;
  10058. cProto.attached = function () {
  10059. Promise.resolve(this).then((cnt) => {
  10060.  
  10061. const hostElement = cnt.hostElement || cnt;
  10062. if (!(hostElement instanceof HTMLElement_)) return;
  10063. if (!HTMLElement_.prototype.matches.call(hostElement, '.yt-live-chat-renderer')) return;
  10064. const ironPage = HTMLElement_.prototype.closest.call(hostElement, 'iron-pages.yt-live-chat-renderer');
  10065. // or #chat-messages
  10066. if (!ironPage) return;
  10067.  
  10068. if (cnt.__naohzId__) removeEventListener.call(ironPage, 'click', cnt.messageBoxClickHandlerForFade, { capture: false, passive: true });
  10069. cnt.__naohzId__ = naohzId = (naohzId & 1073741823) + 1;
  10070. ironPage.setAttribute('naohz', `${+cnt.__naohzId__}`);
  10071.  
  10072. addEventListener.call(ironPage, 'click', cnt.messageBoxClickHandlerForFade, { capture: false, passive: true });
  10073.  
  10074. cnt = null;
  10075.  
  10076. });
  10077. return this.attached37.apply(this, arguments);
  10078. };
  10079. cProto.detached = function () {
  10080. Promise.resolve(this).then((cnt) => {
  10081.  
  10082. const ironPage = document.querySelector(`iron-pages[naohz="${+cnt.__naohzId__}"]`);
  10083. if (!ironPage) return;
  10084.  
  10085. removeEventListener.call(ironPage, 'click', cnt.messageBoxClickHandlerForFade, { capture: false, passive: true });
  10086.  
  10087. cnt = null;
  10088.  
  10089. });
  10090. return this.detached37.apply(this, arguments);
  10091. };
  10092.  
  10093. const clickFade = (u) => {
  10094. u.click();
  10095. };
  10096. cProto.messageBoxClickHandlerForFade = async (evt) => {
  10097.  
  10098. const target = (evt || 0).target || 0;
  10099. if (!target) return;
  10100.  
  10101. for (let p = target; p instanceof HTMLElement_; p = nodeParent(p)) {
  10102. const is = p.is;
  10103. if (typeof is === 'string' && is) {
  10104.  
  10105. if (is === 'yt-live-chat-pinned-message-renderer') {
  10106. return;
  10107. }
  10108. if (is === 'iron-pages' || is === 'yt-live-chat-renderer' || is === 'yt-live-chat-app') {
  10109. const fade = HTMLElement_.prototype.querySelector.call(p, 'yt-live-chat-pinned-message-renderer:not([hidden]) #fade');
  10110. if (fade) {
  10111. Promise.resolve(fade).then(clickFade);
  10112. evt && evt.stopPropagation();
  10113. }
  10114. return;
  10115. }
  10116. if (is !== 'yt-live-chat-ticker-renderer') {
  10117. if (is.startsWith('yt-live-chat-ticker-')) return;
  10118. if (!is.endsWith('-renderer')) return;
  10119. }
  10120.  
  10121. } else {
  10122. if ((p.nodeName || '').includes('BUTTON')) return;
  10123. }
  10124.  
  10125. }
  10126. };
  10127.  
  10128. console1.log("CLOSE_TICKER_PINNED_MESSAGE_WHEN_HEADER_CLICKED - OK")
  10129.  
  10130. } else {
  10131. console1.log("CLOSE_TICKER_PINNED_MESSAGE_WHEN_HEADER_CLICKED - NG")
  10132. }
  10133.  
  10134.  
  10135. })();
  10136.  
  10137. console1.log("[End]");
  10138.  
  10139. groupEnd();
  10140.  
  10141. }).catch(console.warn);
  10142.  
  10143.  
  10144.  
  10145. if (ENABLE_RAF_HACK_INPUT_RENDERER || DELAY_FOCUSEDCHANGED) {
  10146.  
  10147. customElements.whenDefined("yt-live-chat-message-input-renderer").then(() => {
  10148.  
  10149. mightFirstCheckOnYtInit();
  10150. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-message-input-renderer hacks");
  10151. console1.log("[Begin]");
  10152. (() => {
  10153.  
  10154.  
  10155.  
  10156. const tag = "yt-live-chat-message-input-renderer"
  10157. const dummy = document.createElement(tag);
  10158.  
  10159. const cProto = getProto(dummy);
  10160. if (!cProto || !cProto.attached) {
  10161. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10162. return;
  10163. }
  10164.  
  10165.  
  10166. if (ENABLE_RAF_HACK_INPUT_RENDERER && rafHub !== null) {
  10167.  
  10168. let doHack = false;
  10169. if (typeof cProto.handleTimeout === 'function' && typeof cProto.updateTimeout === 'function') {
  10170.  
  10171. // not cancellable
  10172.  
  10173. // <<< to be reviewed cProto.updateTimeout --- isTimingFunctionHackable -- doHack >>>
  10174.  
  10175. doHack = fnIntegrity(cProto.handleTimeout, '1.27.16') && fnIntegrity(cProto.updateTimeout, '1.50.33');
  10176.  
  10177. if (!doHack) console1.log('doHack = false')
  10178.  
  10179. }
  10180. // doHack = false; // M55
  10181.  
  10182. if (doHack) {
  10183.  
  10184. cProto.handleTimeout = function (a) {
  10185.  
  10186. const cnt = kRef(this);
  10187. if (!cnt) return;
  10188. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10189.  
  10190. console.log('cProto.handleTimeout', tag)
  10191. if (!cnt.boundUpdateTimeout38_) cnt.boundUpdateTimeout38_ = cnt.updateTimeout.bind(mWeakRef(cnt));
  10192. cnt.timeoutDurationMs = cnt.timeoutMs = a;
  10193. cnt.countdownRatio = 1;
  10194. 0 === cnt.lastTimeoutTimeMs && rafHub.request(cnt.boundUpdateTimeout38_)
  10195. };
  10196. cProto.updateTimeout = function (a) {
  10197.  
  10198. const cnt = kRef(this);
  10199. if (!cnt) return;
  10200. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10201.  
  10202. console.log('cProto.updateTimeout', tag)
  10203. if (!cnt.boundUpdateTimeout38_) cnt.boundUpdateTimeout38_ = cnt.updateTimeout.bind(mWeakRef(cnt));
  10204. cnt.lastTimeoutTimeMs && (cnt.timeoutMs = Math.max(0, cnt.timeoutMs - (a - cnt.lastTimeoutTimeMs)),
  10205. cnt.countdownRatio = cnt.timeoutMs / cnt.timeoutDurationMs);
  10206. cnt.isAttached && cnt.timeoutMs ? (cnt.lastTimeoutTimeMs = a,
  10207. rafHub.request(cnt.boundUpdateTimeout38_)) : cnt.lastTimeoutTimeMs = 0
  10208. };
  10209.  
  10210. console1.log('RAF_HACK_INPUT_RENDERER', tag, "OK")
  10211. } else {
  10212.  
  10213. console1.log('typeof handleTimeout', typeof cProto.handleTimeout)
  10214. console1.log('typeof updateTimeout', typeof cProto.updateTimeout)
  10215.  
  10216. console1.log('RAF_HACK_INPUT_RENDERER', tag, "NG")
  10217. }
  10218.  
  10219.  
  10220. }
  10221.  
  10222. if (DELAY_FOCUSEDCHANGED && typeof cProto.onFocusedChanged === 'function' && cProto.onFocusedChanged.length === 1 && !cProto.onFocusedChanged372) {
  10223. cProto.onFocusedChanged372 = cProto.onFocusedChanged;
  10224. cProto.onFocusedChanged = function (a) {
  10225. Promise.resolve(this).then((cnt) => {
  10226. if (cnt.isAttached === true) cnt.onFocusedChanged372(a);
  10227. cnt = null;
  10228. }).catch(console.warn);
  10229. }
  10230. }
  10231.  
  10232. })();
  10233.  
  10234. console1.log("[End]");
  10235.  
  10236. groupEnd();
  10237.  
  10238.  
  10239. })
  10240.  
  10241. }
  10242.  
  10243.  
  10244. if (ENABLE_RAF_HACK_EMOJI_PICKER && rafHub !== null) {
  10245.  
  10246. customElements.whenDefined("yt-emoji-picker-renderer").then(() => {
  10247.  
  10248. mightFirstCheckOnYtInit();
  10249. groupCollapsed("YouTube Super Fast Chat", " | yt-emoji-picker-renderer hacks");
  10250. console1.log("[Begin]");
  10251. (() => {
  10252.  
  10253. const tag = "yt-emoji-picker-renderer"
  10254. const dummy = document.createElement(tag);
  10255.  
  10256. const cProto = getProto(dummy);
  10257. if (!cProto || !cProto.attached) {
  10258. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10259. return;
  10260. }
  10261.  
  10262. let doHack = false;
  10263. if (typeof cProto.animateScroll_ === 'function') {
  10264.  
  10265. // not cancellable
  10266. console1.log('animateScroll_: function - OK')
  10267.  
  10268. doHack = fnIntegrity(cProto.animateScroll_, '1.102.49')
  10269.  
  10270. } else {
  10271.  
  10272. console1.log('animateScroll_', typeof cProto.animateScroll_)
  10273. }
  10274.  
  10275. if (doHack) {
  10276.  
  10277. const querySelector = HTMLElement_.prototype.querySelector;
  10278. const U = (element) => ({
  10279. querySelector: (selector) => querySelector.call(element, selector)
  10280. });
  10281.  
  10282. cProto.animateScroll_ = function (a) {
  10283.  
  10284. const cnt = kRef(this);
  10285. if (!cnt) return;
  10286. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10287.  
  10288. // console.log('cProto.animateScroll_', tag) // yt-emoji-picker-renderer
  10289. if (!cnt.boundAnimateScroll39_) cnt.boundAnimateScroll39_ = cnt.animateScroll_.bind(mWeakRef(cnt));
  10290. cnt.lastAnimationTime_ || (cnt.lastAnimationTime_ = a);
  10291. a -= cnt.lastAnimationTime_;
  10292. 200 > a ? (U(cnt.hostElement).querySelector("#categories").scrollTop = cnt.animationStart_ + (cnt.animationEnd_ - cnt.animationStart_) * a / 200,
  10293. rafHub.request(cnt.boundAnimateScroll39_)) : (null != cnt.animationEnd_ && (U(cnt.hostElement).querySelector("#categories").scrollTop = cnt.animationEnd_),
  10294. cnt.animationEnd_ = cnt.animationStart_ = null,
  10295. cnt.lastAnimationTime_ = 0);
  10296. cnt.updateButtons_()
  10297. }
  10298.  
  10299. console1.log('ENABLE_RAF_HACK_EMOJI_PICKER', tag, "OK")
  10300. } else {
  10301.  
  10302. console1.log('ENABLE_RAF_HACK_EMOJI_PICKER', tag, "NG")
  10303. }
  10304.  
  10305. })();
  10306.  
  10307. console1.log("[End]");
  10308.  
  10309. groupEnd();
  10310. });
  10311. }
  10312.  
  10313. if (ENABLE_RAF_HACK_DOCKED_MESSAGE && rafHub !== null) {
  10314.  
  10315. customElements.whenDefined("yt-live-chat-docked-message").then(() => {
  10316.  
  10317. mightFirstCheckOnYtInit();
  10318. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-docked-message hacks");
  10319. console1.log("[Begin]");
  10320. (() => {
  10321.  
  10322. const tag = "yt-live-chat-docked-message"
  10323. const dummy = document.createElement(tag);
  10324.  
  10325. const cProto = getProto(dummy);
  10326. if (!cProto || !cProto.attached) {
  10327. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10328. return;
  10329. }
  10330.  
  10331. let doHack = false;
  10332. if (typeof cProto.detached === 'function' && typeof cProto.checkIntersections === 'function' && typeof cProto.onDockableMessagesChanged === 'function' && typeof cProto.boundCheckIntersections === 'undefined') {
  10333.  
  10334. // cancelable - this.intersectRAF <detached>
  10335. // yt-live-chat-docked-message
  10336. // boundCheckIntersections <-> checkIntersections
  10337. // onDockableMessagesChanged
  10338. // this.intersectRAF = window.requestAnimationFrame(this.boundCheckIntersections);
  10339.  
  10340. console1.log(`detached: function - OK`)
  10341. console1.log('checkIntersections: function - OK')
  10342. console1.log('onDockableMessagesChanged: function - OK')
  10343.  
  10344. doHack = fnIntegrity(cProto.detached, '0.32.22') && fnIntegrity(cProto.checkIntersections, '0.128.85') && fnIntegrity(cProto.onDockableMessagesChanged, '0.20.11')
  10345.  
  10346. } else {
  10347.  
  10348. console1.log('detached', typeof cProto.detached, 'NG')
  10349. console1.log('checkIntersections', typeof cProto.checkIntersections, 'NG')
  10350. console1.log('onDockableMessagesChanged', typeof cProto.onDockableMessagesChanged, 'NG')
  10351. }
  10352.  
  10353. if (doHack) {
  10354.  
  10355. cProto.__boundCheckIntersectionsSubstitutionFn__ = function () {
  10356. const cnt = this;
  10357. if (!cnt.i5zmk && typeof cnt.boundCheckIntersections === 'function' && typeof cnt.checkIntersections === 'function') {
  10358. cnt.i5zmk = 1
  10359. cnt.boundCheckIntersections = cnt.checkIntersections.bind(mWeakRef(cnt));
  10360. }
  10361. }
  10362.  
  10363. cProto.checkIntersections = function () {
  10364.  
  10365. const cnt = kRef(this);
  10366. if (!cnt) return;
  10367. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10368.  
  10369. if(typeof cnt.__boundCheckIntersectionsSubstitutionFn__ === 'function') cnt.__boundCheckIntersectionsSubstitutionFn__();
  10370.  
  10371. // console.log('cProto.checkIntersections', tag)
  10372. if (cnt.dockableMessages.length) {
  10373. cnt.intersectRAF = rafHub.request(cnt.boundCheckIntersections);
  10374. let a = cnt.dockableMessages[0]
  10375. , b = cnt.hostElement.getBoundingClientRect();
  10376. a = a.getBoundingClientRect();
  10377. let c = a.top - b.top
  10378. , d = 8 >= c;
  10379. c = 8 >= c - cnt.hostElement.clientHeight;
  10380. if (d) {
  10381. let e;
  10382. for (; d;) {
  10383. e = cnt.dockableMessages.shift();
  10384. d = cnt.dockableMessages[0];
  10385. if (!d)
  10386. break;
  10387. d = d.getBoundingClientRect();
  10388. c = d.top - b.top;
  10389. let f = 8 >= c;
  10390. if (8 >= c - a.height)
  10391. if (f)
  10392. a = d;
  10393. else
  10394. return;
  10395. d = f
  10396. }
  10397. cnt.dock(e)
  10398. } else
  10399. c && cnt.dockedItem && cnt.clear()
  10400. } else
  10401. cnt.intersectRAF = 0
  10402. }
  10403.  
  10404. cProto.onDockableMessagesChanged = function () {
  10405. const cnt = this;
  10406. if(typeof cnt.__boundCheckIntersectionsSubstitutionFn__ === 'function') cnt.__boundCheckIntersectionsSubstitutionFn__();
  10407. // console.log('cProto.onDockableMessagesChanged', tag) // yt-live-chat-docked-message
  10408. cnt.dockableMessages.length && !cnt.intersectRAF && (cnt.intersectRAF = rafHub.request(cnt.boundCheckIntersections))
  10409. }
  10410.  
  10411. cProto.detached = function () {
  10412. this.intersectRAF && rafHub.cancel(this.intersectRAF)
  10413. }
  10414.  
  10415. console1.log('ENABLE_RAF_HACK_DOCKED_MESSAGE', tag, "OK")
  10416. } else {
  10417.  
  10418. console1.log('ENABLE_RAF_HACK_DOCKED_MESSAGE', tag, "NG")
  10419. }
  10420.  
  10421. })();
  10422.  
  10423. console1.log("[End]");
  10424.  
  10425. groupEnd();
  10426.  
  10427. }).catch(console.warn);
  10428.  
  10429. }
  10430.  
  10431. if (FIX_SETSRC_AND_THUMBNAILCHANGE_) {
  10432.  
  10433. customElements.whenDefined("yt-img-shadow").then(() => {
  10434.  
  10435. mightFirstCheckOnYtInit();
  10436. groupCollapsed("YouTube Super Fast Chat", " | yt-img-shadow hacks");
  10437. console1.log("[Begin]");
  10438. (() => {
  10439.  
  10440. const tag = "yt-img-shadow"
  10441. const dummy = document.createElement(tag);
  10442.  
  10443. const cProto = getProto(dummy);
  10444. if (!cProto || !cProto.attached) {
  10445. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10446. return;
  10447. }
  10448.  
  10449. if (typeof cProto.thumbnailChanged_ === 'function' && !cProto.thumbnailChanged66_) {
  10450.  
  10451. cProto.thumbnailChanged66_ = cProto.thumbnailChanged_;
  10452. cProto.thumbnailChanged_ = function (a) {
  10453.  
  10454. if (this.oldThumbnail_ && this.thumbnail && this.oldThumbnail_.thumbnails === this.thumbnail.thumbnails) return;
  10455. if (!this.oldThumbnail_ && !this.thumbnail) return;
  10456.  
  10457. return this.thumbnailChanged66_.apply(this, arguments)
  10458.  
  10459. }
  10460. console1.log("cProto.thumbnailChanged_ - OK");
  10461.  
  10462. } else {
  10463. console1.log("cProto.thumbnailChanged_ - NG");
  10464.  
  10465. }
  10466. if (typeof cProto.setSrc_ === 'function' && !cProto.setSrc66_) {
  10467.  
  10468. cProto.setSrc66_ = cProto.setSrc_;
  10469. cProto.setSrc_ = function (a) {
  10470. if ((((this || 0).$ || 0).img || 0).src === a) return;
  10471. return this.setSrc66_.apply(this, arguments)
  10472. }
  10473.  
  10474. console1.log("cProto.setSrc_ - OK");
  10475. } else {
  10476.  
  10477. console1.log("cProto.setSrc_ - NG");
  10478. }
  10479.  
  10480. })();
  10481.  
  10482. console1.log("[End]");
  10483.  
  10484. groupEnd();
  10485.  
  10486. }).catch(console.warn);
  10487.  
  10488. }
  10489.  
  10490. if (FIX_THUMBNAIL_DATACHANGED) {
  10491.  
  10492. customElements.whenDefined("yt-live-chat-author-badge-renderer").then(() => {
  10493.  
  10494. mightFirstCheckOnYtInit();
  10495. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-author-badge-renderer hacks");
  10496. console1.log("[Begin]");
  10497. (() => {
  10498.  
  10499. const tag = "yt-live-chat-author-badge-renderer"
  10500. const dummy = document.createElement(tag);
  10501.  
  10502. const cProto = getProto(dummy);
  10503. if (!cProto || !cProto.attached) {
  10504. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10505. return;
  10506. }
  10507.  
  10508. if (typeof cProto.dataChanged === 'function' && !cProto.dataChanged86 && '|0.169.106|'.includes(`|${fnIntegrity(cProto.dataChanged)}|`)) {
  10509.  
  10510. cProto.dataChanged86 = cProto.dataChanged;
  10511. cProto.dataChanged = function () {
  10512.  
  10513. /* 2024.12.15 */
  10514. /*
  10515. zO.prototype.dataChanged = function() {
  10516. for (var a = Ov(R(this.hostElement).querySelector("#image")); a.firstChild; )
  10517. a.removeChild(a.firstChild);
  10518. if (this.data)
  10519. if (this.data.icon) {
  10520. var b = document.createElement("yt-icon");
  10521. this.data.icon.iconType === "MODERATOR" && this.enableNewModeratorBadge ? (b.polymerController.icon = "yt-sys-icons:shield-filled",
  10522. b.polymerController.defaultToFilled = !0) : b.polymerController.icon = "live-chat-badges:" + this.data.icon.iconType.toLowerCase();
  10523. a.appendChild(b)
  10524. } else if (this.data.customThumbnail) {
  10525. b = document.createElement("img");
  10526. var c;
  10527. (c = (c = UA(this.data.customThumbnail.thumbnails, 16)) ? Yb(kc(c)) : null) ? (b.src = c,
  10528. a.appendChild(b),
  10529. b.setAttribute("alt", this.hostElement.ariaLabel || "")) : Fq(new Zn("Could not compute URL for thumbnail",this.data.customThumbnail))
  10530. }
  10531. }
  10532. */
  10533.  
  10534. const a = (this || 0).data;
  10535. const image = ((this || 0).$ || 0).image;
  10536. if (image && a && image.firstElementChild) {
  10537. const exisiting = image.firstElementChild;
  10538. if (exisiting === image.lastElementChild) {
  10539.  
  10540. if (a.icon && exisiting.nodeName.toUpperCase() === 'YT-ICON') {
  10541.  
  10542. const c = exisiting;
  10543. const t = insp(c);
  10544. const w = ('icon' in t || 'defaultToFilled' in t) ? t : c;
  10545. if ("MODERATOR" === a.icon.iconType && this.enableNewModeratorBadge) {
  10546. if (w.icon !== "yt-sys-icons:shield-filled") w.icon = "yt-sys-icons:shield-filled";
  10547. if (w.defaultToFilled !== true) w.defaultToFilled = true;
  10548. } else {
  10549. const p = "live-chat-badges:" + a.icon.iconType.toLowerCase();;
  10550. if (w.icon !== p) w.icon = p;
  10551. if (w.defaultToFilled !== false) w.defaultToFilled = false;
  10552. }
  10553. return;
  10554.  
  10555.  
  10556. } else if (a.customThumbnail && exisiting.nodeName.toUpperCase() == 'IMG') {
  10557.  
  10558. const c = exisiting;
  10559. if (a.customThumbnail.thumbnails.map(e => e.url).includes(c.src)) {
  10560.  
  10561. c.setAttribute("alt", this.hostElement.ariaLabel || "");
  10562. return;
  10563. }
  10564. /*
  10565.  
  10566. var d;
  10567. (d = (d = KC(a.customThumbnail.thumbnails, 16)) ? lc(oc(d)) : null) ? (c.src = d,
  10568.  
  10569. c.setAttribute("alt", this.hostElement.ariaLabel || "")) : lq(new tm("Could not compute URL for thumbnail", a.customThumbnail))
  10570. */
  10571. }
  10572.  
  10573. }
  10574. }
  10575. return this.dataChanged86.apply(this, arguments)
  10576.  
  10577. }
  10578. console1.log("cProto.dataChanged - OK");
  10579.  
  10580. } else if (typeof cProto.dataChanged === 'function' && !cProto.dataChanged86 && '|1.163.100|1.162.100|1.160.97|1.159.97|'.includes(`|${fnIntegrity(cProto.dataChanged)}|`)) {
  10581.  
  10582. cProto.dataChanged86 = cProto.dataChanged;
  10583. cProto.dataChanged = function (a) {
  10584.  
  10585. /*
  10586.  
  10587. for (var b = xC(Z(this.hostElement).querySelector("#image")); b.firstChild; )
  10588. b.removeChild(b.firstChild);
  10589. if (a)
  10590. if (a.icon) {
  10591. var c = document.createElement("yt-icon");
  10592. "MODERATOR" === a.icon.iconType && this.enableNewModeratorBadge ? (c.icon = "yt-sys-icons:shield-filled",
  10593. c.defaultToFilled = !0) : c.icon = "live-chat-badges:" + a.icon.iconType.toLowerCase();
  10594. b.appendChild(c)
  10595. } else if (a.customThumbnail) {
  10596. c = document.createElement("img");
  10597. var d;
  10598. (d = (d = KC(a.customThumbnail.thumbnails, 16)) ? lc(oc(d)) : null) ? (c.src = d,
  10599. b.appendChild(c),
  10600. c.setAttribute("alt", this.hostElement.ariaLabel || "")) : lq(new tm("Could not compute URL for thumbnail",a.customThumbnail))
  10601. }
  10602.  
  10603. */
  10604.  
  10605.  
  10606. /* 2024.04.20 */
  10607. /*
  10608. for (var b = Tx(N(this.hostElement).querySelector("#image")); b.firstChild; )
  10609. b.removeChild(b.firstChild);
  10610. if (a)
  10611. if (a.icon) {
  10612. var c = document.createElement("yt-icon");
  10613. "MODERATOR" === a.icon.iconType && this.enableNewModeratorBadge ? (c.polymerController.icon = "yt-sys-icons:shield-filled",
  10614. c.polymerController.defaultToFilled = !0) : c.polymerController.icon = "live-chat-badges:" + a.icon.iconType.toLowerCase();
  10615. b.appendChild(c)
  10616. } else if (a.customThumbnail) {
  10617. c = document.createElement("img");
  10618. var d;
  10619. (d = (d = WD(a.customThumbnail.thumbnails, 16)) ? Sb(ec(d)) : null) ? (c.src = d,
  10620. b.appendChild(c),
  10621. c.setAttribute("alt", this.hostElement.ariaLabel || "")) : nr(new mn("Could not compute URL for thumbnail",a.customThumbnail))
  10622. }
  10623. */
  10624.  
  10625. const image = ((this || 0).$ || 0).image
  10626. if (image && a && image.firstElementChild) {
  10627. const exisiting = image.firstElementChild;
  10628. if (exisiting === image.lastElementChild) {
  10629.  
  10630. if (a.icon && exisiting.nodeName.toUpperCase() === 'YT-ICON') {
  10631.  
  10632. const c = exisiting;
  10633. const t = insp(c);
  10634. const w = ('icon' in t || 'defaultToFilled' in t) ? t : c;
  10635. if ("MODERATOR" === a.icon.iconType && this.enableNewModeratorBadge) {
  10636. if (w.icon !== "yt-sys-icons:shield-filled") w.icon = "yt-sys-icons:shield-filled";
  10637. if (w.defaultToFilled !== true) w.defaultToFilled = true;
  10638. } else {
  10639. const p = "live-chat-badges:" + a.icon.iconType.toLowerCase();;
  10640. if (w.icon !== p) w.icon = p;
  10641. if (w.defaultToFilled !== false) w.defaultToFilled = false;
  10642. }
  10643. return;
  10644.  
  10645.  
  10646. } else if (a.customThumbnail && exisiting.nodeName.toUpperCase() == 'IMG') {
  10647.  
  10648. const c = exisiting;
  10649. if (a.customThumbnail.thumbnails.map(e => e.url).includes(c.src)) {
  10650.  
  10651. c.setAttribute("alt", this.hostElement.ariaLabel || "");
  10652. return;
  10653. }
  10654. /*
  10655.  
  10656. var d;
  10657. (d = (d = KC(a.customThumbnail.thumbnails, 16)) ? lc(oc(d)) : null) ? (c.src = d,
  10658.  
  10659. c.setAttribute("alt", this.hostElement.ariaLabel || "")) : lq(new tm("Could not compute URL for thumbnail", a.customThumbnail))
  10660. */
  10661. }
  10662.  
  10663. }
  10664. }
  10665. return this.dataChanged86.apply(this, arguments)
  10666.  
  10667. }
  10668. console1.log("cProto.dataChanged - OK");
  10669.  
  10670. } else {
  10671. assertor(() => fnIntegrity(cProto.dataChanged, '0.169.106'));
  10672. console1.log("cProto.dataChanged - NG");
  10673.  
  10674. }
  10675.  
  10676. })();
  10677.  
  10678. console1.log("[End]");
  10679.  
  10680. groupEnd();
  10681.  
  10682. }).catch(console.warn);
  10683.  
  10684.  
  10685. }
  10686.  
  10687. if (USE_ADVANCED_TICKING) {
  10688. // leading the emoji cannot be rendered.
  10689.  
  10690. // const qz38 = lcrPromiseFn();
  10691.  
  10692. // qz38.then((lcrGet) => {
  10693.  
  10694. // const tag = "yt-live-chat-renderer"
  10695. // const dummy = lcrGet();
  10696.  
  10697. const lcrFn2 = (lcrDummy) => {
  10698.  
  10699. const tag = "yt-live-chat-renderer"
  10700. const dummy = lcrDummy;
  10701.  
  10702.  
  10703. const cProto = getProto(dummy);
  10704.  
  10705. // dummy.usePatchedLifecycles = false;
  10706. // dummy.data = null;
  10707. // dummy.__data = null;
  10708. // Object.setPrototypeOf(dummy, Object.prototype);
  10709. if (!cProto || !cProto.attached) {
  10710. console.warn(`proto.attached for ${tag} is unavailable.`);
  10711. return;
  10712. }
  10713.  
  10714. /*
  10715. <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;
  10716. */
  10717.  
  10718. if (cProto && typeof cProto.immediatelyApplyLiveChatActions === 'function' && cProto.immediatelyApplyLiveChatActions.length === 1 && !cProto.immediatelyApplyLiveChatActions82) {
  10719. cProto.immediatelyApplyLiveChatActions82 = cProto.immediatelyApplyLiveChatActions;
  10720. cProto.immediatelyApplyLiveChatActions = function (arr) {
  10721.  
  10722.  
  10723. // console.log(1237)
  10724. try {
  10725. preprocessChatLiveActions(arr);
  10726. } catch (e) {
  10727. console.warn(e);
  10728. }
  10729. return this.immediatelyApplyLiveChatActions82(arr);
  10730. };
  10731. }
  10732.  
  10733.  
  10734. if (cProto && typeof cProto.preprocessActions_ === 'function' && cProto.preprocessActions_.length === 1 && !cProto.preprocessActions82_) {
  10735. cProto.preprocessActions82_ = cProto.preprocessActions_;
  10736. cProto.preprocessActions_ = function (arr) {
  10737.  
  10738. arr = this.preprocessActions82_(arr);
  10739.  
  10740. try {
  10741. preprocessChatLiveActions(arr);
  10742. } catch (e) {
  10743. console.warn(e);
  10744. }
  10745. return arr;
  10746. };
  10747. }
  10748.  
  10749.  
  10750.  
  10751. };
  10752. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  10753. getLCRDummy().then(lcrFn2);
  10754. }
  10755.  
  10756. if (MODIFY_EMIT_MESSAGES_FOR_BOOST_CHAT) {
  10757.  
  10758. const lcrFn2 = (lcrDummy) => {
  10759.  
  10760. const tag = "yt-live-chat-renderer"
  10761. const dummy = lcrDummy;
  10762.  
  10763.  
  10764. const cProto = getProto(dummy);
  10765.  
  10766. // dummy.usePatchedLifecycles = false;
  10767. // dummy.data = null;
  10768. // dummy.__data = null;
  10769. // Object.setPrototypeOf(dummy, Object.prototype);
  10770. if (!cProto || !cProto.attached) {
  10771. console.warn(`proto.attached for ${tag} is unavailable.`);
  10772. return;
  10773. }
  10774.  
  10775. /*
  10776.  
  10777. // https://www.youtube.com/s/desktop/c01ea7e3/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  10778.  
  10779.  
  10780. YP.prototype.emitSmoothedMessages = function() {
  10781. this.JSC$10797_nextUpdateId = null;
  10782. if (this.JSC$10797_messageQueue.length) {
  10783. var a = 1E4;
  10784. this.JSC$10797_estimatedUpdateInterval !== null && this.JSC$10797_lastUpdateTime !== null && (a = this.JSC$10797_estimatedUpdateInterval - Date.now() + this.JSC$10797_lastUpdateTime);
  10785. var b = this.JSC$10797_messageQueue.length < a / 80 ? 1 : Math.ceil(this.JSC$10797_messageQueue.length / (a / 80));
  10786. var c = aba(this.JSC$10797_messageQueue.splice(0, b));
  10787. this.callback && this.callback(c);
  10788. this.JSC$10797_messageQueue.length && (b === 1 ? (b = a / this.JSC$10797_messageQueue.length,
  10789. b *= Math.random() + .5,
  10790. b = Math.min(1E3, b),
  10791. b = Math.max(80, b)) : b = 80,
  10792. this.JSC$10797_nextUpdateId = window.setTimeout(this.emitSmoothedMessages.bind(this), b))
  10793. }
  10794. }
  10795. // emitSmoothedMessages: say b = 1000, 858.24, 529.49, 357.15, 194.96, 82.12, 80, 80, 80 ....
  10796.  
  10797. */
  10798.  
  10799.  
  10800. const _flag0281_ = window._flag0281_;
  10801.  
  10802.  
  10803. if ((_flag0281_ & 0x40000) === 0x40000 && cProto && typeof cProto.preprocessActions_ === 'function' && cProto.preprocessActions_.length === 1 && !cProto.preprocessActions92_) {
  10804. // we can disable smooth message emitting if boost chat is enabled (0x40000)
  10805. let byPass = false;
  10806. let q33 = false;
  10807. let key_estimatedUpdateInterval = '';
  10808. let key_lastUpdateTime = '';
  10809. let key_messageQueue = '';
  10810. const emitSmoothedMessagesInstantFn = function () {
  10811. if (byPass) return this.emitSmoothedMessages018();
  10812. byPass = true;
  10813. try {
  10814. if (!q33) {
  10815. const keys = Object.getOwnPropertyNames(this);
  10816. for (const key of keys) {
  10817. if (`${key}`.endsWith('_estimatedUpdateInterval')) key_estimatedUpdateInterval = key;
  10818. else if (`${key}`.endsWith('_lastUpdateTime')) key_lastUpdateTime = key;
  10819. else if (`${key}`.endsWith('_messageQueue')) key_messageQueue = key;
  10820. else continue;
  10821. if (key_estimatedUpdateInterval && key_lastUpdateTime && key_messageQueue) break;
  10822. }
  10823. if (key_estimatedUpdateInterval && key_lastUpdateTime && key_messageQueue) {
  10824. q33 = true;
  10825. }
  10826. }
  10827. if (key_estimatedUpdateInterval && key_lastUpdateTime) {
  10828. this[key_estimatedUpdateInterval] = 78; // 80 - 2
  10829. this[key_lastUpdateTime] = Date.now() - 1;
  10830. }
  10831. } catch (e) { }
  10832. // console.log(19893,key_estimatedUpdateInterval, key_lastUpdateTime)
  10833. // make a = this.JSC$10797_estimatedUpdateInterval - Date.now() + this.JSC$10797_lastUpdateTime small
  10834.  
  10835. // this.JSC$10797_estimatedUpdateInterval = Date.now() + 1
  10836. // this.JSC$10797_lastUpdateTime = Date.now()
  10837.  
  10838. // if (!window.setTimeout837) {
  10839. // window.setTimeout837 = window.setTimeout;
  10840. // window.setTimeout838 = function (f, d) {
  10841. // if (arguments.length !== 2) return window.setTimeout837(...arguments);
  10842. // console.log(12883, d)
  10843. // return window.setTimeout837(f, d > 80 ? 80 : d)
  10844. // }
  10845. // }
  10846. // else if (window.setTimeout837 !== window.setTimeout) {
  10847. // window.setTimeout837 = window.setTimeout;
  10848. // }
  10849. // let r;
  10850. // if (window.setTimeout837 && window.setTimeout838) {
  10851. // window.setTimeout = window.setTimeout838;
  10852. // r = this.emitSmoothedMessages018();
  10853. // window.setTimeout = window.setTimeout837;
  10854. // } else {
  10855. // r = this.emitSmoothedMessages018();
  10856. // }
  10857. let doInNextCall = false;
  10858. try {
  10859. const messageQueue = key_messageQueue ? this[key_messageQueue] : null;
  10860. if (!messageQueue || !messageQueue.length) {
  10861.  
  10862. } else if (messageQueue.length > 255) {
  10863.  
  10864. } else if (!document.hidden) {
  10865.  
  10866. } else {
  10867. doInNextCall = true;
  10868. }
  10869. } catch (e) { }
  10870.  
  10871. let r;
  10872. if (doInNextCall) {
  10873. setTimeout_(() => this.emitSmoothedMessages019(), 250);
  10874. } else {
  10875. r = this.emitSmoothedMessages018();
  10876. }
  10877. byPass = false;
  10878. return r;
  10879. };
  10880. cProto.preprocessActions92_ = cProto.preprocessActions_;
  10881. cProto.preprocessActions_ = function (arr) {
  10882.  
  10883. arr = this.preprocessActions92_(arr);
  10884.  
  10885. try {
  10886.  
  10887. const smoothedQueue_ = this.smoothedQueue_;
  10888. if (smoothedQueue_ && !smoothedQueue_.__fix018__) {
  10889. smoothedQueue_.__fix018__ = true;
  10890. if (!smoothedQueue_.emitSmoothedMessages018 && typeof smoothedQueue_.emitSmoothedMessages === 'function' && smoothedQueue_.emitSmoothedMessages.length === 0) {
  10891. smoothedQueue_.emitSmoothedMessages018 = smoothedQueue_.emitSmoothedMessages;
  10892. smoothedQueue_.emitSmoothedMessages019 = emitSmoothedMessagesInstantFn;
  10893. smoothedQueue_.emitSmoothedMessages = emitSmoothedMessagesInstantFn;
  10894. }
  10895. }
  10896. } catch (e) {
  10897. console.warn(e);
  10898. }
  10899. return arr;
  10900. };
  10901. }
  10902.  
  10903.  
  10904.  
  10905.  
  10906. };
  10907. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  10908. getLCRDummy().then(lcrFn2);
  10909. }
  10910.  
  10911.  
  10912. if (FIX_TOOLTIP_DISPLAY) {
  10913.  
  10914. // ----------------------------------------------------------------------------------------------------
  10915.  
  10916. const checkPDGet = (pd) => {
  10917. return pd && pd.get && !pd.set && pd.enumerable && pd.configurable;
  10918. }
  10919.  
  10920. const tooltipUIWM = new WeakMap();
  10921. const tooltipInitProps = {};
  10922. const createTooltipIfRequired_ = function () {
  10923. let r;
  10924. if (tooltipUIWM.get(this) === void 0) {
  10925. const w = document.createElement;
  10926. let EU = null;
  10927. tooltipUIWM.set(this, null);
  10928. document.createElement = function () {
  10929. let r = w.apply(this, arguments);
  10930. EU = r;
  10931. return r;
  10932. };
  10933. r = this.createTooltipIfRequired14_();
  10934. document.createElement = w;
  10935. if (EU instanceof HTMLElement_ && EU.is) {
  10936. tooltipUIWM.set(this, EU);
  10937. EU.setAttribute('__nogc__', ''); // avoid gc process script
  10938.  
  10939. if (typeof EU.offset === 'number') tooltipInitProps['offset'] = EU.offset;
  10940. if (typeof EU.fitToVisibleBounds === 'boolean') tooltipInitProps['fitToVisibleBounds'] = EU.fitToVisibleBounds;
  10941. if (typeof EU.position === 'string') tooltipInitProps['position'] = EU.position;
  10942. if (typeof EU.for === 'string') tooltipInitProps['for'] = EU.for;
  10943.  
  10944. // this.__mcT__ = EU.outerHTML;
  10945. // EU.__dataX = JSON.stringify(EU.__data);
  10946. // EU.__dataY = Object.entries(EU);
  10947.  
  10948. // <<< FOR DEBUG >>>
  10949. // let kx;
  10950. // Object.defineProperty(EU, '_target', {
  10951. // get(){
  10952. // return kx;
  10953. // },
  10954. // set(nv){
  10955. // kx= nv;
  10956. // debugger;
  10957. // return true;
  10958. // }
  10959. // });
  10960. // <<< FOR DEBUG >>>
  10961.  
  10962. if (typeof Polymer !== 'undefined' && Polymer.__fixedGetOwnerRoot__ && Polymer.__fixedQuerySelector__) {
  10963.  
  10964. } else {
  10965. let eProto = null;
  10966. const euCnt = insp(EU);
  10967. if (checkPDGet(Object.getOwnPropertyDescriptor(euCnt.constructor.prototype || {}, 'target'))) {
  10968.  
  10969. eProto = euCnt.constructor.prototype;
  10970. } else if (checkPDGet(Object.getOwnPropertyDescriptor(EU.constructor.prototype || {}, 'target'))) {
  10971.  
  10972. eProto = EU.constructor.prototype;
  10973. }
  10974. if (eProto) {
  10975. delete eProto.target;
  10976. /*
  10977.  
  10978. get target() {
  10979. var a = Pv(this).parentNode, b = Pv(this).getOwnerRoot(), c;
  10980. this.for ? c = Pv(b).querySelector("#" + this.for) : c = a.nodeType == Node.DOCUMENT_FRAGMENT_NODE ? b.host : a;
  10981. return c
  10982. },
  10983. */
  10984. Object.defineProperty(eProto, 'target', {
  10985. get() {
  10986. const cnt = insp(this);
  10987. const hostElement = cnt.hostElement || cnt;
  10988. let a = hostElement.parentNode, b = hostElement.getRootNode();
  10989. const fr = cnt.for || hostElement.for;
  10990. return (fr ? b.querySelector("#" + fr) : a)
  10991. }
  10992. })
  10993. }
  10994. }
  10995. // setInterval(()=>EU.updatePosition(), 100)
  10996.  
  10997. } else {
  10998. tooltipUIWM.set(this, null);
  10999. }
  11000. } else {
  11001. r = this.createTooltipIfRequired14_();
  11002. }
  11003.  
  11004. const EU = tooltipUIWM.get(this);
  11005. if (EU) {
  11006. EU.remove();
  11007. if (typeof tooltipInitProps.offset === 'number') EU['offset'] = tooltipInitProps.offset;
  11008. if (typeof tooltipInitProps.fitToVisibleBounds === 'boolean') EU['fitToVisibleBounds'] = tooltipInitProps.fitToVisibleBounds;
  11009. try {
  11010. if (typeof tooltipInitProps.position === 'string') EU['position'] = tooltipInitProps.position;
  11011. if (typeof tooltipInitProps.for === 'string') EU['for'] = tooltipInitProps.for; else delete EU.for;
  11012. } catch (e) { }
  11013. }
  11014.  
  11015. // 2025.01.10 fix
  11016. const CS = EU;
  11017. if (!CS._showing && CS.__shady_parentNode && CS.__shady_parentNode !== CS.parentNode) {
  11018. if (CS.__shady_parentNode) {
  11019. try {
  11020. CS.__shady_parentNode.__shady_removeChild(CS);
  11021. } catch (e) { }
  11022. }
  11023. if (CS.__shady_parentNode) {
  11024. try {
  11025. CS.__shady_parentNode.removeChild(CS);
  11026. } catch (e) { }
  11027. }
  11028. if (CS.__shady_parentNode) {
  11029. try {
  11030. CS.__shady_parentNode.__shady_native_removeChild(CS);
  11031. } catch (e) { }
  11032. }
  11033. if (CS.__shady_parentNode) {
  11034. try {
  11035. __shady_native_removeChild.call(CS.__shady_parentNode, CS);
  11036. } catch (e) { }
  11037. }
  11038. if (CS.parentNode && !CS.__shady_parentNode) {
  11039. try {
  11040. __shady_native_removeChild.call(CS.parentNode, CS);
  11041. } catch (e) { }
  11042. }
  11043. }
  11044.  
  11045. return r;
  11046. };
  11047.  
  11048.  
  11049. // added in 2024.05.02
  11050. const lcrFn2 = (lcrDummy) => {
  11051.  
  11052. // console.log(8171, 99);
  11053. const tag = "yt-live-chat-renderer"
  11054. const dummy = lcrDummy;
  11055.  
  11056. const cProto = getProto(dummy);
  11057. if (!cProto || !cProto.attached) {
  11058. console.warn(`proto.attached for ${tag} is unavailable.`);
  11059. return;
  11060. }
  11061.  
  11062. /*
  11063. <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;
  11064. */
  11065.  
  11066. if (cProto && typeof cProto.createTooltipIfRequired_ === 'function' && cProto.createTooltipIfRequired_.length === 0 && !cProto.createTooltipIfRequired14_) {
  11067. cProto.createTooltipIfRequired14_ = cProto.createTooltipIfRequired_;
  11068. cProto.createTooltipIfRequired_ = createTooltipIfRequired_;
  11069. }
  11070.  
  11071. };
  11072. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  11073. getLCRDummy().then(lcrFn2);
  11074.  
  11075. // ----------------------------------------------------------------------------------------------------
  11076.  
  11077. customElements.whenDefined("tp-yt-paper-tooltip").then(() => {
  11078.  
  11079. mightFirstCheckOnYtInit();
  11080. groupCollapsed("YouTube Super Fast Chat", " | tp-yt-paper-tooltip hacks");
  11081. console1.log("[Begin]");
  11082. (() => {
  11083.  
  11084. const tag = "tp-yt-paper-tooltip"
  11085. const dummy = document.createElement(tag);
  11086.  
  11087. const cProto = getProto(dummy);
  11088. if (!cProto || !cProto.attached) {
  11089. console1.warn(`proto.attached for ${tag} is unavailable.`);
  11090. return;
  11091. }
  11092.  
  11093. if (typeof cProto.attached === 'function' && typeof cProto.detached === 'function' && cProto._readyClients && cProto._attachDom && cProto.ready && !cProto._readyClients43) {
  11094.  
  11095. cProto._readyClients43 = cProto._readyClients;
  11096. cProto._readyClients = function () {
  11097. // console.log(1238)
  11098.  
  11099. let r = cProto._readyClients43.apply(this, arguments);
  11100. if (this.$ && this.$$ && this.$.tooltip) this.root = null; // fix this.root = null != (b = a.root) ? b : this.host
  11101. return r;
  11102. }
  11103.  
  11104. console1.log("_readyClients - OK");
  11105.  
  11106. } else {
  11107. console1.log("_readyClients - NG");
  11108.  
  11109. }
  11110.  
  11111. if (typeof cProto.show === 'function' && !cProto.show17) {
  11112. cProto.show17 = cProto.show;
  11113. cProto.show = function () {
  11114.  
  11115. let r = this.show17.apply(this, arguments);
  11116. this._showing === true && Promise.resolve(this).then((cnt) => {
  11117. const tooltip = (cnt.$ || 0).tooltip;
  11118.  
  11119. if (tooltip && tooltip.firstElementChild === null) {
  11120. let text = tooltip.textContent;
  11121. if (typeof text === 'string' && text.length >= 2) {
  11122. tooltip.textContent = text.trim();
  11123. }
  11124. }
  11125. cnt = null;
  11126. }).catch(console.warn)
  11127. return r;
  11128. }
  11129.  
  11130. console1.log("trim tooltip content - OK");
  11131.  
  11132. } else {
  11133. console1.log("trim tooltip content - NG");
  11134.  
  11135. }
  11136.  
  11137.  
  11138. })();
  11139.  
  11140. console1.log("[End]");
  11141.  
  11142. groupEnd();
  11143.  
  11144. }).catch(console.warn);
  11145.  
  11146. }
  11147.  
  11148.  
  11149. if (FIX_CLICKING_MESSAGE_MENU_DISPLAY_ON_MOUSE_CLICK) {
  11150.  
  11151. const hookDocumentMouseDownSetupFn = () => {
  11152.  
  11153. let muzTimestamp = 0;
  11154. let nszDropdown = null;
  11155.  
  11156. const handlerObject = {
  11157.  
  11158. muHandler282: function (evt) {
  11159. // console.log(evt, 7, document.querySelector('tp-yt-iron-dropdown[focused].style-scope.yt-live-chat-app'))
  11160. if (!evt || !evt.isTrusted || !muzTimestamp) return;
  11161. const dropdown = nszDropdown;
  11162. muzTimestamp = 0;
  11163. nszDropdown = null;
  11164.  
  11165. const kurMPCe = kRef(currentMenuPivotWR) || 0;
  11166. const hostElement = kurMPCe.hostElement || kurMPCe; // should be always hostElement === kurMPCe ?
  11167. if (!hostElement.hasAttribute('menu-visible')) return;
  11168.  
  11169. const chatBanner = HTMLElement_.prototype.closest.call(hostElement, 'yt-live-chat-banner-renderer') || 0;
  11170. if (chatBanner) return;
  11171.  
  11172. if (dropdown && dropdown.positionTarget && hostElement.contains(dropdown.positionTarget)) {
  11173. muzTimestamp = Date.now();
  11174. evt.stopImmediatePropagation();
  11175. evt.stopPropagation();
  11176. Promise.resolve(dropdown).then((dropdown) => {
  11177. dropdown.cancel();
  11178. dropdown = null;
  11179. });
  11180. }
  11181.  
  11182. },
  11183.  
  11184. mlHandler282: function (evt) {
  11185. muzTimestamp = 0;
  11186. nszDropdown = null;
  11187. },
  11188.  
  11189. ckHandler282: function (evt) {
  11190. if (!evt || !evt.isTrusted || !muzTimestamp) return;
  11191. if (Date.now() - muzTimestamp < 40) {
  11192. muzTimestamp = Date.now();
  11193. evt.stopImmediatePropagation();
  11194. evt.stopPropagation();
  11195. }
  11196. },
  11197.  
  11198. tapHandler282: function (evt) {
  11199. if (!evt || !evt.isTrusted || !muzTimestamp) return;
  11200. if (Date.now() - muzTimestamp < 40) {
  11201. muzTimestamp = Date.now();
  11202. evt.stopImmediatePropagation();
  11203. evt.stopPropagation();
  11204. }
  11205. },
  11206.  
  11207. handleEvent(evt) {
  11208. if (evt) {
  11209. const kurMPCe = kRef(currentMenuPivotWR) || 0;
  11210. const kurMPCc = insp(kurMPCe);
  11211. const hostElement = kurMPCc.hostElement || kurMPCc;
  11212. if (!kurMPCc || kurMPCc.isAttached !== true || hostElement.isConnected !== true) return;
  11213. switch (evt.type) {
  11214. case 'mouseup':
  11215. return this.muHandler282(evt);
  11216. case 'mouseleave':
  11217. return this.mlHandler282(evt);
  11218. case 'tap':
  11219. return this.tapHandler282(evt);
  11220. case 'click':
  11221. return this.ckHandler282(evt);
  11222. }
  11223. }
  11224. }
  11225.  
  11226. }
  11227.  
  11228. document.addEventListener('mousedown', function (evt) {
  11229.  
  11230. if (!evt || !evt.isTrusted || !evt.target) return;
  11231.  
  11232. muzTimestamp = 0;
  11233. nszDropdown = null;
  11234.  
  11235. /** @type {HTMLElement | null} */
  11236. const kurMP = kRef(currentMenuPivotWR);
  11237. if (!kurMP) return;
  11238. const kurMPCe = HTMLElement_.prototype.closest.call(kurMP, '[menu-visible]') || 0; // element
  11239.  
  11240. if (!kurMPCe || !kurMPCe.hasAttribute('whole-message-clickable')) return;
  11241.  
  11242. const kurMPCc = insp(kurMPCe); // controller
  11243.  
  11244. if (!kurMPCc.isClickableChatRow111 || !kurMPCc.isClickableChatRow111() || !HTMLElement_.prototype.contains.call(kurMPCe, evt.target)) return;
  11245.  
  11246. const chatBanner = HTMLElement_.prototype.closest.call(kurMPCe, 'yt-live-chat-banner-renderer') || 0;
  11247. if (chatBanner) return;
  11248.  
  11249. let targetDropDown = null;
  11250. for (const dropdown of document.querySelectorAll('tp-yt-iron-dropdown.style-scope.yt-live-chat-app')) {
  11251. if (dropdown && dropdown.positionTarget === kurMP) {
  11252. targetDropDown = dropdown;
  11253. }
  11254. }
  11255.  
  11256. if (!targetDropDown) return;
  11257.  
  11258. if (evt.target.closest('ytd-menu-popup-renderer')) return;
  11259.  
  11260. if ((nszDropdown = targetDropDown)) {
  11261. muzTimestamp = Date.now();
  11262. evt.stopImmediatePropagation();
  11263. evt.stopPropagation();
  11264. currentMenuPivotWR = mWeakRef(kurMPCe);
  11265.  
  11266. const listenOpts = { capture: true, passive: false, once: true };
  11267.  
  11268. // remove unexcecuted eventHandler
  11269. document.removeEventListener('mouseup', handlerObject, listenOpts);
  11270. document.removeEventListener('mouseleave', handlerObject, listenOpts);
  11271. document.removeEventListener('tap', handlerObject, listenOpts);
  11272. document.removeEventListener('click', handlerObject, listenOpts);
  11273.  
  11274. // inject one time eventHandler to by pass events
  11275. document.addEventListener('mouseup', handlerObject, listenOpts);
  11276. document.addEventListener('mouseleave', handlerObject, listenOpts);
  11277. document.addEventListener('tap', handlerObject, listenOpts);
  11278. document.addEventListener('click', handlerObject, listenOpts);
  11279.  
  11280. }
  11281.  
  11282. }, true);
  11283.  
  11284. }
  11285.  
  11286.  
  11287. // yt-live-chat-paid-message-renderer ??
  11288.  
  11289. /*
  11290.  
  11291. [...(new Set([...document.querySelectorAll('*')].filter(e=>e.is&&('shouldSupportWholeItemClick' in e)).map(e=>e.is))).keys()]
  11292.  
  11293.  
  11294. "yt-live-chat-ticker-paid-message-item-renderer"
  11295. "yt-live-chat-ticker-paid-sticker-item-renderer"
  11296. "yt-live-chat-paid-message-renderer"
  11297. "yt-live-chat-text-message-renderer"
  11298. "yt-live-chat-paid-sticker-renderer"
  11299.  
  11300. */
  11301.  
  11302.  
  11303. whenDefinedMultiple([
  11304.  
  11305. "yt-live-chat-paid-message-renderer",
  11306. "yt-live-chat-membership-item-renderer",
  11307. "yt-live-chat-paid-sticker-renderer",
  11308. "yt-live-chat-text-message-renderer",
  11309. "yt-live-chat-auto-mod-message-renderer",
  11310.  
  11311. /*
  11312. "yt-live-chat-ticker-paid-message-item-renderer",
  11313. "yt-live-chat-ticker-paid-sticker-item-renderer",
  11314. "yt-live-chat-paid-message-renderer",
  11315. "yt-live-chat-text-message-renderer",
  11316. "yt-live-chat-paid-sticker-renderer",
  11317.  
  11318. "yt-live-chat-ticker-sponsor-item-renderer",
  11319. "yt-live-chat-banner-header-renderer",
  11320. "ytd-sponsorships-live-chat-gift-purchase-announcement-renderer",
  11321. "ytd-sponsorships-live-chat-header-renderer",
  11322. "ytd-sponsorships-live-chat-gift-redemption-announcement-renderer",
  11323.  
  11324.  
  11325.  
  11326.  
  11327. "yt-live-chat-auto-mod-message-renderer",
  11328. "yt-live-chat-text-message-renderer",
  11329. "yt-live-chat-paid-message-renderer",
  11330.  
  11331. "yt-live-chat-legacy-paid-message-renderer",
  11332. "yt-live-chat-membership-item-renderer",
  11333. "yt-live-chat-paid-sticker-renderer",
  11334. "yt-live-chat-donation-announcement-renderer",
  11335. "yt-live-chat-moderation-message-renderer",
  11336. "ytd-sponsorships-live-chat-gift-purchase-announcement-renderer",
  11337. "ytd-sponsorships-live-chat-gift-redemption-announcement-renderer",
  11338. "yt-live-chat-viewer-engagement-message-renderer",
  11339.  
  11340. */
  11341.  
  11342.  
  11343. ]).then(sTags => {
  11344. // return; // M33
  11345.  
  11346. mightFirstCheckOnYtInit();
  11347. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-message-renderer(s)... hacks");
  11348. console1.log("[Begin]");
  11349. let doMouseHook = false;
  11350.  
  11351. const dProto = {
  11352. isClickableChatRow111: function () {
  11353. return (
  11354. this.data && typeof this.shouldSupportWholeItemClick === 'function' && typeof this.hasModerationOverlayVisible === 'function' &&
  11355. this.data.contextMenuEndpoint && this.wholeMessageClickable && this.shouldSupportWholeItemClick() && !this.hasModerationOverlayVisible()
  11356. ); // follow .onItemTap(a)
  11357. }
  11358. };
  11359.  
  11360. for (const sTag of sTags) { // ##tag##
  11361.  
  11362.  
  11363. (() => {
  11364.  
  11365. const tag = sTag;
  11366. const dummy = document.createElement(tag);
  11367.  
  11368. const cProto = getProto(dummy);
  11369. if (!cProto || !cProto.attached) {
  11370. console1.warn(`proto.attached for ${tag} is unavailable.`);
  11371. return;
  11372. }
  11373.  
  11374. const dCnt = insp(dummy);
  11375. if ('wholeMessageClickable' in dCnt && typeof dCnt.hasModerationOverlayVisible === 'function' && typeof dCnt.shouldSupportWholeItemClick === 'function') {
  11376.  
  11377. cProto.isClickableChatRow111 = dProto.isClickableChatRow111;
  11378.  
  11379. const toHookDocumentMouseDown = typeof cProto.shouldSupportWholeItemClick === 'function' && typeof cProto.hasModerationOverlayVisible === 'function';
  11380.  
  11381. if (toHookDocumentMouseDown) {
  11382. doMouseHook = true;
  11383. }
  11384.  
  11385. console1.log("shouldSupportWholeItemClick - OK", tag);
  11386.  
  11387. } else {
  11388.  
  11389. console1.log("shouldSupportWholeItemClick - NG", tag);
  11390. }
  11391.  
  11392.  
  11393. })();
  11394.  
  11395. }
  11396.  
  11397.  
  11398. if (doMouseHook) {
  11399.  
  11400. hookDocumentMouseDownSetupFn();
  11401.  
  11402. console1.log("FIX_CLICKING_MESSAGE_MENU_DISPLAY_ON_MOUSE_CLICK - Doc MouseEvent OK");
  11403. }
  11404.  
  11405. console1.log("[End]");
  11406.  
  11407. groupEnd();
  11408.  
  11409.  
  11410. }).catch(console.warn);
  11411.  
  11412.  
  11413. // https://www.youtube.com/watch?v=oQzFi1NO7io
  11414.  
  11415.  
  11416. }
  11417.  
  11418. if (NO_ITEM_TAP_FOR_NON_STATIONARY_TAP) {
  11419. let targetElementCntWR = null;
  11420. let _e0 = null;
  11421. document.addEventListener('mousedown', (e) => {
  11422. if (!e || !e.isTrusted) return;
  11423. let element = e.target;
  11424. for (; element instanceof HTMLElement_; element = element.parentNode) {
  11425. if (element.is) break;
  11426. }
  11427. if (!element || !element.is) return;
  11428. if (element.closest('ytd-menu-popup-renderer')) return;
  11429. const cnt = insp(element);
  11430. if (typeof cnt.onItemTap === 'function') {
  11431. cnt._onItemTap_isNonStationary = 0;
  11432. const cProto = getProto(element);
  11433. if (!cProto.onItemTap366 && typeof cProto.onItemTap === 'function' && cProto.onItemTap.length === 1) {
  11434. cProto.onItemTap366 = cProto.onItemTap; // note: [onItemTap] .some(function(){...})
  11435. cProto.onItemTap = function (a) {
  11436. const t = this._onItemTap_isNonStationary;
  11437. this._onItemTap_isNonStationary = 0;
  11438. if (t > Date.now()) return;
  11439. return this.onItemTap366.apply(this, arguments)
  11440. }
  11441. }
  11442. _e0 = e;
  11443. targetElementCntWR = mWeakRef(cnt);
  11444. } else {
  11445. _e0 = null;
  11446. targetElementCntWR = null;
  11447. }
  11448. }, { capture: true, passive: true });
  11449.  
  11450. document.addEventListener('mouseup', (e) => {
  11451. if (!e || !e.isTrusted) return;
  11452. const e0 = _e0;
  11453. _e0 = null;
  11454. if (!e0) return;
  11455. const cnt = kRef(targetElementCntWR);
  11456. targetElementCntWR = null;
  11457. if (!cnt) return;
  11458. if (e.timeStamp - e0.timeStamp > TAP_ACTION_DURATION) {
  11459. cnt._onItemTap_isNonStationary = Date.now() + 40;
  11460. } else if (`${window.getSelection()}`.trim().replace(/[\u2000-\u200a\u202f\u2800\u200B\u200C\u200D\uFEFF]+/g, '').length >= 1) {
  11461. cnt._onItemTap_isNonStationary = Date.now() + 40;
  11462. } else {
  11463. const dx = e.clientX - e0.clientX;
  11464. const dy = e.clientY - e0.clientY;
  11465. const dd = Math.sqrt(dx * dx + dy * dy);
  11466. const ddmm = px2mm(dd);
  11467. if (ddmm > 1.0) {
  11468. cnt._onItemTap_isNonStationary = Date.now() + 40;
  11469. } else {
  11470. cnt._onItemTap_isNonStationary = 0;
  11471. }
  11472. }
  11473. }, { capture: true, passive: true });
  11474.  
  11475. }
  11476.  
  11477.  
  11478. const __showContextMenu_assign_lock_with_external_unlock_ = function (targetCnt) {
  11479.  
  11480. let rr = null;
  11481. const p1 = new Promise(resolve => {
  11482. rr = resolve;
  11483. });
  11484.  
  11485. const p1unlock = () => {
  11486. const f = rr;
  11487. if (f) {
  11488. rr = null;
  11489. f();
  11490. }
  11491. }
  11492.  
  11493. return {
  11494. p1,
  11495. p1unlock,
  11496. assignLock: (targetCnt, timeout) => {
  11497. targetCnt.__showContextMenu_assign_lock__(p1);
  11498. if (timeout) setTimeout(p1unlock, timeout);
  11499. }
  11500. }
  11501.  
  11502. }
  11503.  
  11504. if (PREREQUEST_CONTEXT_MENU_ON_MOUSE_DOWN) {
  11505.  
  11506. document.addEventListener('mousedown', function (evt) {
  11507.  
  11508. const maxloopDOMTreeElements = 4;
  11509. const maxloopYtCompontents = 4;
  11510. let j1 = 0;
  11511. let j2 = 0;
  11512. let target = (evt || 0).target || 0;
  11513. if (!target) return;
  11514. if (target.closest('ytd-menu-popup-renderer')) return;
  11515.  
  11516. while (target instanceof HTMLElement_) {
  11517. if (++j1 > maxloopDOMTreeElements) break;
  11518. if (typeof (target.is || insp(target).is || null) === 'string') break;
  11519. target = nodeParent(target);
  11520. }
  11521. const components = [];
  11522. while (target instanceof HTMLElement_) {
  11523. if (++j2 > maxloopYtCompontents) break;
  11524. const cnt = insp(target);
  11525. if (typeof (target.is || cnt.is || null) === 'string') {
  11526. components.push(target);
  11527. }
  11528. if (typeof cnt.showContextMenu === 'function') break;
  11529. target = target.parentComponent || cnt.parentComponent || null;
  11530. }
  11531. if (!(target instanceof HTMLElement_)) return;
  11532. const targetCnt = insp(target);
  11533. if (typeof targetCnt.handleGetContextMenuResponse_ !== 'function' || typeof targetCnt.handleGetContextMenuError !== 'function') {
  11534. console.log('Error Found: handleGetContextMenuResponse_ OR handleGetContextMenuError is not defined on a component with showContextMenu')
  11535. return;
  11536. }
  11537.  
  11538. const endpoint = (targetCnt.data || 0).contextMenuEndpoint
  11539. if (!endpoint) return;
  11540. if (targetCnt.opened || !targetCnt.isAttached) return;
  11541.  
  11542. if (typeof targetCnt.__cacheResolvedEndpointData__ !== 'function') {
  11543. console.log(`preRequest for showContextMenu in ${targetCnt.is} is not yet supported.`)
  11544. }
  11545.  
  11546. const targetDollar = indr(target);
  11547.  
  11548. let doPreRequest = false;
  11549. if (components.length >= 2 && components[0].id === 'menu-button' && (targetDollar || 0)['menu-button'] === components[0]) {
  11550. doPreRequest = true;
  11551. } else if (components.length === 1 && components[0] === target) {
  11552. doPreRequest = true;
  11553. } else if (components.length >= 2 && components[0].id === 'author-photo' && (targetDollar || 0)['author-photo'] === components[0]) {
  11554. doPreRequest = true;
  11555. }
  11556. if (doPreRequest === false) {
  11557. console.log('doPreRequest = fasle on showContextMenu', components);
  11558. return;
  11559. }
  11560.  
  11561. if (typeof targetCnt.__getCachedEndpointData__ !== 'function' || targetCnt.__getCachedEndpointData__(endpoint)) return;
  11562.  
  11563. if ((typeof targetCnt.__showContextMenu_mutex_unlock_isEmpty__ === 'function') && !targetCnt.__showContextMenu_mutex_unlock_isEmpty__()) {
  11564. console.log('preRequest on showContextMenu aborted due to stacked network request');
  11565. return;
  11566. }
  11567.  
  11568.  
  11569. const onSuccess = (a) => {
  11570. /*
  11571.  
  11572. dQ() && (a = a.response);
  11573. a.liveChatItemContextMenuSupportedRenderers && a.liveChatItemContextMenuSupportedRenderers.menuRenderer && this.showContextMenu_(a.liveChatItemContextMenuSupportedRenderers.menuRenderer);
  11574. a.actions && Eu(this.hostElement, "yt-live-chat-actions", [a.actions])
  11575.  
  11576. */
  11577.  
  11578. a = a.response || a;
  11579.  
  11580. if (!a) {
  11581. console.log('unexpected error in prerequest for showContextMenu.onSuccess');
  11582. return;
  11583. }
  11584.  
  11585. let z = null;
  11586. a.liveChatItemContextMenuSupportedRenderers && a.liveChatItemContextMenuSupportedRenderers.menuRenderer && (z = a.liveChatItemContextMenuSupportedRenderers.menuRenderer);
  11587.  
  11588. if (z) {
  11589. a = z;
  11590. targetCnt.__cacheResolvedEndpointData__(endpoint, a, true);
  11591. }
  11592.  
  11593. };
  11594. const onFailure = (a) => {
  11595.  
  11596. /*
  11597.  
  11598. if (a instanceof Error || a instanceof Object || a instanceof String)
  11599. var b = a;
  11600. hq(new xm("Error encountered calling GetLiveChatItemContextMenu",b))
  11601.  
  11602. */
  11603.  
  11604. targetCnt.__cacheResolvedEndpointData__(endpoint, null);
  11605. // console.log('onFailure', a)
  11606.  
  11607. };
  11608.  
  11609. if (doPreRequest) {
  11610.  
  11611. let propertyCounter = 0;
  11612. const pm1 = __showContextMenu_assign_lock_with_external_unlock_(targetCnt);
  11613. const p1Timeout = 800;
  11614. const proxyKey = '__$$__proxy_to_this__$$__' + Date.now();
  11615.  
  11616. try {
  11617.  
  11618. const onSuccessHelperFn = function () {
  11619. pm1.p1unlock();
  11620. if (propertyCounter !== 5) {
  11621. console.log('Error in prerequest for showContextMenu.onSuccessHelperFn')
  11622. return;
  11623. }
  11624. if (this[proxyKey] !== targetCnt) {
  11625. console.log('Error in prerequest for showContextMenu.this');
  11626. return;
  11627. }
  11628. onSuccess(...arguments);
  11629. };
  11630. const onFailureHelperFn = function () {
  11631. pm1.p1unlock();
  11632. if (propertyCounter !== 5) {
  11633. console.log('Error in prerequest for showContextMenu.onFailureHelperFn')
  11634. return;
  11635. }
  11636. if (this[proxyKey] !== targetCnt) {
  11637. console.log('Error in prerequest for showContextMenu.this');
  11638. return;
  11639. }
  11640. onFailure(...arguments);
  11641.  
  11642. }
  11643. const fakeTargetCnt = new Proxy({
  11644. __showContextMenu_forceNativeRequest__: 1,
  11645. get handleGetContextMenuResponse_() {
  11646. propertyCounter += 2;
  11647. return onSuccessHelperFn;
  11648. },
  11649. get handleGetContextMenuError() {
  11650. propertyCounter += 3;
  11651. return onFailureHelperFn;
  11652. }
  11653. }, {
  11654. get(_, key, receiver) {
  11655. if (key in _) return _[key];
  11656. if (key === proxyKey) return targetCnt;
  11657.  
  11658. let giveNative = false;
  11659. if (key in targetCnt) {
  11660. if (key === 'data') giveNative = true;
  11661. else if (typeof targetCnt[key] === 'function') giveNative = true;
  11662. }
  11663. if (giveNative) return targetCnt[key];
  11664. }
  11665. });
  11666.  
  11667. const fakeEvent = (() => {
  11668. const { target, bubbles, cancelable, cancelBubble, srcElement, timeStamp, defaultPrevented, currentTarget, composed } = evt;
  11669. const nf = function () { }
  11670. const [stopPropagation, stopImmediatePropagation, preventDefault] = [nf, nf, nf];
  11671.  
  11672. return {
  11673. type: 'tap',
  11674. eventPhase: 0,
  11675. isTrusted: false,
  11676. __composed: true,
  11677. bubbles, cancelable, cancelBubble, timeStamp,
  11678. target, srcElement, defaultPrevented, currentTarget, composed,
  11679. stopPropagation, stopImmediatePropagation, preventDefault
  11680. };
  11681. })(evt);
  11682. targetCnt.showContextMenu.call(fakeTargetCnt, fakeEvent);
  11683.  
  11684.  
  11685. } catch (e) {
  11686. console.warn(e);
  11687. propertyCounter = 7;
  11688.  
  11689. }
  11690. if (propertyCounter !== 5) {
  11691. console.log('Error in prerequest for showContextMenu', propertyCounter);
  11692. return;
  11693. }
  11694.  
  11695. pm1.assignLock(targetCnt, p1Timeout);
  11696.  
  11697. }
  11698.  
  11699.  
  11700.  
  11701.  
  11702.  
  11703.  
  11704. }, true);
  11705.  
  11706.  
  11707. }
  11708.  
  11709.  
  11710.  
  11711. /*
  11712.  
  11713. const w=new Set(); for(const a of document.getElementsByTagName('*')) if(a.showContextMenu && a.showContextMenu_) w.add(a.is||''); console.log([...w.keys()])
  11714.  
  11715. */
  11716.  
  11717. whenDefinedMultiple([
  11718. "yt-live-chat-ticker-sponsor-item-renderer",
  11719. "yt-live-chat-ticker-paid-message-item-renderer",
  11720.  
  11721. "yt-live-chat-banner-header-renderer",
  11722. "yt-live-chat-text-message-renderer",
  11723. "ytd-sponsorships-live-chat-gift-purchase-announcement-renderer",
  11724. "ytd-sponsorships-live-chat-header-renderer",
  11725. "ytd-sponsorships-live-chat-gift-redemption-announcement-renderer",
  11726.  
  11727. "yt-live-chat-paid-sticker-renderer",
  11728. "yt-live-chat-viewer-engagement-message-renderer",
  11729. "yt-live-chat-paid-message-renderer"
  11730.  
  11731.  
  11732.  
  11733.  
  11734. ]).then(sTags => {
  11735.  
  11736. mightFirstCheckOnYtInit();
  11737. groupCollapsed("YouTube Super Fast Chat", " | fixShowContextMenu");
  11738. console1.log("[Begin]");
  11739.  
  11740.  
  11741. const __showContextMenu_mutex__ = new Mutex();
  11742. let __showContextMenu_mutex_unlock__ = null;
  11743. let lastShowMenuTarget = null;
  11744.  
  11745.  
  11746.  
  11747.  
  11748. const wm37 = new WeakMap();
  11749.  
  11750. const dProto = {
  11751.  
  11752.  
  11753. // CACHE_SHOW_CONTEXT_MENU_FOR_REOPEN
  11754.  
  11755. __cacheResolvedEndpointData__: (endpoint, a, doDeepCopy) => {
  11756. if (a) {
  11757. if (doDeepCopy) a = deepCopy(a);
  11758. wm37.set(endpoint, a);
  11759. } else {
  11760. wm37.remove(endpoint);
  11761. }
  11762. },
  11763. __getCachedEndpointData__: function (endpoint) {
  11764. endpoint = endpoint || (this.data || 0).contextMenuEndpoint || 0;
  11765. if (endpoint) return wm37.get(endpoint);
  11766. return null;
  11767. },
  11768. /** @type {(resolvedEndpoint: any) => void 0} */
  11769. __showCachedContextMenu__: function (resolvedEndpoint) { // non-null
  11770.  
  11771. resolvedEndpoint = deepCopy(resolvedEndpoint);
  11772. // let b = deepCopy(resolvedEndpoint, ['trackingParams', 'clickTrackingParams'])
  11773. Promise.resolve(resolvedEndpoint).then((resolvedEndpoint) => {
  11774. this.__showContextMenu_skip_cacheResolvedEndpointData__ = 1;
  11775. this.showContextMenu_(resolvedEndpoint);
  11776. this.__showContextMenu_skip_cacheResolvedEndpointData__ = 0;
  11777. resolvedEndpoint = null;
  11778. });
  11779.  
  11780.  
  11781. },
  11782.  
  11783.  
  11784.  
  11785. showContextMenuForCacheReopen: function (a) {
  11786. if (this && this.__showContextMenu_forceNativeRequest__) return this.showContextMenu37(a);
  11787. if (!this || !this.isAttached) return; // in case; avoid Error: No provider for: InjectionToken(NETWORK_TOKEN) in _.showContextMenu
  11788. if (!this.__showContextMenu_forceNativeRequest__) {
  11789. const endpoint = (this.data || 0).contextMenuEndpoint || 0;
  11790. if (endpoint) {
  11791. const resolvedEndpoint = this.__getCachedEndpointData__(endpoint);
  11792. if (resolvedEndpoint) {
  11793. this.__showCachedContextMenu__(resolvedEndpoint);
  11794. a && a.stopPropagation()
  11795. return;
  11796. }
  11797. }
  11798. }
  11799. return this.showContextMenu37(a);
  11800. },
  11801.  
  11802. showContextMenuForCacheReopen_: function (a) {
  11803. if (this && this.__showContextMenu_forceNativeRequest__) return this.showContextMenu37_(a);
  11804. if (!this || !this.isAttached) return; // in case; avoid Error: No provider for: InjectionToken(NETWORK_TOKEN) in _.showContextMenu
  11805. if (!this.__showContextMenu_skip_cacheResolvedEndpointData__) {
  11806. const endpoint = (this.data || 0).contextMenuEndpoint || 0;
  11807. if (endpoint) {
  11808. const f = this.__cacheResolvedEndpointData__;
  11809. if (typeof f === 'function') f(endpoint, a, true);
  11810. }
  11811. }
  11812. return this.showContextMenu37_(a);
  11813. },
  11814.  
  11815. // ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU
  11816.  
  11817. showContextMenuWithDisableScroll: function (a) {
  11818.  
  11819. const endpoint = (this.data || 0).contextMenuEndpoint || 0;
  11820. if (endpoint && typeof this.is === 'string' && this.menuVisible === false && this.menuOpen === false) {
  11821.  
  11822. const parentComponent = this.parentComponent;
  11823. if (parentComponent && parentComponent.is === 'yt-live-chat-item-list-renderer' && parentComponent.contextMenuOpen === false && parentComponent.allowScroll === true) {
  11824. parentComponent.contextMenuOpen = true; // computeAllowScroll_(contextMenuOpen, moderationModeEnabled): allowScroll = !(contextMenuOpen || moderationModeEnabled)
  11825. }
  11826. }
  11827.  
  11828. return this.showContextMenu48.apply(this, arguments);
  11829.  
  11830. },
  11831.  
  11832. // ENABLE_MUTEX_FOR_SHOW_CONTEXT_MENU
  11833.  
  11834. __showContextMenu_mutex_unlock_isEmpty__: () => {
  11835. return __showContextMenu_mutex_unlock__ === null;
  11836. },
  11837.  
  11838. __showContextMenu_assign_lock__: function (p) {
  11839.  
  11840. const mutex = __showContextMenu_mutex__;
  11841.  
  11842. mutex.lockWith(unlock => {
  11843. p.then(unlock);
  11844. p = null;
  11845. unlock = null;
  11846. });
  11847.  
  11848. },
  11849.  
  11850. showContextMenuWithMutex: function (a) {
  11851. if (this.__showContextMenu_forceNativeRequest__) return this.showContextMenu47(a);
  11852. if (!this || !this.isAttached) return; // in case; avoid Error: No provider for: InjectionToken(NETWORK_TOKEN) in _.showContextMenu
  11853. lastShowMenuTarget = this;
  11854. const wNode = mWeakRef(this);
  11855.  
  11856.  
  11857. const mutex = __showContextMenu_mutex__;
  11858.  
  11859. mutex.lockWith(unlock => {
  11860. const cnt = kRef(wNode);
  11861. if (lastShowMenuTarget !== cnt || !cnt) {
  11862. unlock();
  11863. return;
  11864. }
  11865.  
  11866. setTimeout(unlock, 800); // in case network failure
  11867. __showContextMenu_mutex_unlock__ = unlock;
  11868. try {
  11869. cnt.showContextMenu47(a);
  11870. } catch (e) {
  11871. console.warn(e);
  11872. unlock(); // in case function script error
  11873. }
  11874.  
  11875. });
  11876.  
  11877.  
  11878. },
  11879.  
  11880. showContextMenuWithMutex_: function (a) {
  11881.  
  11882. if (__showContextMenu_mutex_unlock__ && this === lastShowMenuTarget) {
  11883. __showContextMenu_mutex_unlock__();
  11884. __showContextMenu_mutex_unlock__ = null;
  11885. }
  11886. return this.showContextMenu47_(a);
  11887.  
  11888. }
  11889.  
  11890. }
  11891.  
  11892. for (const tag of sTags) { // ##tag##
  11893.  
  11894. (() => {
  11895.  
  11896. const dummy = document.createElement(tag);
  11897.  
  11898. const cProto = getProto(dummy);
  11899. if (!cProto || !cProto.attached) {
  11900. console1.warn(`proto.attached for ${tag} is unavailable.`);
  11901. return;
  11902. }
  11903.  
  11904.  
  11905. 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) {
  11906. cProto.showContextMenu37_ = cProto.showContextMenu_;
  11907. cProto.showContextMenu37 = cProto.showContextMenu;
  11908. cProto.__showContextMenu_forceNativeRequest__ = 0;
  11909. cProto.__cacheResolvedEndpointData__ = dProto.__cacheResolvedEndpointData__
  11910. cProto.__getCachedEndpointData__ = dProto.__getCachedEndpointData__
  11911. cProto.__showCachedContextMenu__ = dProto.__showCachedContextMenu__
  11912. cProto.showContextMenu = dProto.showContextMenuForCacheReopen;
  11913. cProto.showContextMenu_ = dProto.showContextMenuForCacheReopen_;
  11914. console1.log("CACHE_SHOW_CONTEXT_MENU_FOR_REOPEN - OK", tag);
  11915. } else {
  11916. console1.log("CACHE_SHOW_CONTEXT_MENU_FOR_REOPEN - NG", tag);
  11917. }
  11918.  
  11919. 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) {
  11920. cProto.showContextMenu48 = cProto.showContextMenu;
  11921. cProto.showContextMenu = dProto.showContextMenuWithDisableScroll;
  11922. console1.log("ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU - OK", tag);
  11923. } else if (!ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU) {
  11924. DEBUG_skipLog001 || console1.log("ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU - N/A", tag);
  11925. } else {
  11926. console1.log("ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU - NG", tag);
  11927. }
  11928.  
  11929.  
  11930. 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) {
  11931. cProto.showContextMenu47_ = cProto.showContextMenu_;
  11932. cProto.showContextMenu47 = cProto.showContextMenu;
  11933. cProto.__showContextMenu_mutex_unlock_isEmpty__ = dProto.__showContextMenu_mutex_unlock_isEmpty__;
  11934. cProto.__showContextMenu_assign_lock__ = dProto.__showContextMenu_assign_lock__;
  11935. cProto.showContextMenu = dProto.showContextMenuWithMutex;
  11936. cProto.showContextMenu_ = dProto.showContextMenuWithMutex_;
  11937. console1.log("ENABLE_MUTEX_FOR_SHOW_CONTEXT_MENU - OK", tag);
  11938. } else {
  11939. console1.log("ENABLE_MUTEX_FOR_SHOW_CONTEXT_MENU - NG", tag);
  11940. }
  11941.  
  11942. })();
  11943.  
  11944. }
  11945.  
  11946. console1.log("[End]");
  11947.  
  11948. groupEnd();
  11949.  
  11950. }).catch(console.warn);
  11951.  
  11952.  
  11953.  
  11954. if (FIX_UNKNOWN_BUG_FOR_OVERLAY) {
  11955. // this is to fix " TypeError: this.backdropElement.prepare is not a function "
  11956.  
  11957. customElements.whenDefined('tp-yt-paper-dialog').then(() => {
  11958.  
  11959.  
  11960. mightFirstCheckOnYtInit();
  11961. groupCollapsed("YouTube Super Fast Chat", " | tp-yt-paper-dialog hacks");
  11962. console1.log("[Begin]");
  11963. (() => {
  11964.  
  11965. const tag = "tp-yt-paper-dialog";
  11966. const dummy = document.createElement(tag);
  11967.  
  11968. const cProto = getProto(dummy);
  11969. if (!cProto || !cProto.attached) {
  11970. console1.warn(`proto.attached for ${tag} is unavailable.`);
  11971. return;
  11972. }
  11973.  
  11974. if (typeof cProto.__openedChanged === 'function' && !cProto.__openedChanged49 && cProto.__openedChanged.length === 0) {
  11975.  
  11976.  
  11977. cProto.__openedChanged49 = cProto.__openedChanged;
  11978.  
  11979. cProto.__openedChanged = function () {
  11980. const manager = (this || 0)._manager || 0;
  11981. if (manager && !manager.trackBackdrop49 && manager.trackBackdrop) {
  11982. manager.trackBackdrop49 = manager.trackBackdrop;
  11983. if (manager.trackBackdrop.length === 0) {
  11984. manager.trackBackdrop = function () {
  11985. try {
  11986. return this.trackBackdrop49();
  11987. } catch (e) {
  11988. let showMessage = true;
  11989. if (e instanceof TypeError && e.message === 'this.backdropElement.prepare is not a function') {
  11990. // this is well known issue.
  11991. showMessage = false;
  11992. }
  11993. showMessage && console.log('manager.trackBackdrop', e);
  11994. }
  11995. }
  11996. }
  11997. }
  11998. return this.__openedChanged49();
  11999. };
  12000.  
  12001.  
  12002. }
  12003.  
  12004.  
  12005. })();
  12006.  
  12007.  
  12008. console1.log("[End]");
  12009.  
  12010. groupEnd();
  12011.  
  12012.  
  12013. }).catch(console.warn);
  12014.  
  12015. }
  12016.  
  12017.  
  12018. customElements.whenDefined('tp-yt-iron-dropdown').then(() => {
  12019.  
  12020. mightFirstCheckOnYtInit();
  12021. groupCollapsed("YouTube Super Fast Chat", " | tp-yt-iron-dropdown hacks");
  12022. console1.log("[Begin]");
  12023. (() => {
  12024.  
  12025. const tag = "tp-yt-iron-dropdown";
  12026. const dummy = document.createElement(tag);
  12027.  
  12028. const cProto = getProto(dummy);
  12029. if (!cProto || !cProto.attached) {
  12030. console1.warn(`proto.attached for ${tag} is unavailable.`);
  12031. return;
  12032. }
  12033.  
  12034. if (USE_VANILLA_DEREF && typeof cProto.__deraf === 'function' && cProto.__deraf.length === 2 && !cProto.__deraf34 && fnIntegrity(cProto.__deraf) === '2.42.24') {
  12035. cProto.__deraf_hn__ = function (sId, fn) {
  12036. const rhKey = `_rafHandler_${sId}`;
  12037. const m = this[rhKey] || (this[rhKey] = new WeakMap());
  12038. if (m.has(fn)) return m.get(fn);
  12039. const resFn = () => {
  12040. this.__rafs[sId] = null;
  12041. fn.call(this)
  12042. };
  12043. m.set(fn, resFn);
  12044. m.set(resFn, resFn);
  12045. return resFn;
  12046. };
  12047. cProto.__deraf34 = cProto.__deraf;
  12048. cProto.__deraf = function (a, b) { // sId, fn
  12049. let c = this.__rafs;
  12050. null !== c[a] && cancelAnimationFrame(c[a]);
  12051. c[a] = requestAnimationFrame(this.__deraf_hn__(a, b));
  12052. };
  12053. console1.log("USE_VANILLA_DEREF - OK");
  12054. } else {
  12055. console1.log("USE_VANILLA_DEREF - NG");
  12056. }
  12057.  
  12058. if (FIX_DROPDOWN_DERAF && typeof cProto.__deraf === 'function' && cProto.__deraf.length === 2 && !cProto.__deraf66) {
  12059. cProto.__deraf66 = cProto.__deraf;
  12060. cProto.__deraf = function (sId, fn) {
  12061. if (this.__byPassRAF__) {
  12062. Promise.resolve(this).then((cnt) => {
  12063. fn.call(cnt);
  12064. cnt = null;
  12065. });
  12066. }
  12067. let r = this.__deraf66.apply(this, arguments);
  12068. return r;
  12069. }
  12070. console1.log("FIX_DROPDOWN_DERAF - OK");
  12071. } else {
  12072. console1.log("FIX_DROPDOWN_DERAF - NG");
  12073. }
  12074.  
  12075.  
  12076. if (BOOST_MENU_OPENCHANGED_RENDERING && typeof cProto.__openedChanged === 'function' && !cProto.__mtChanged__ && fnIntegrity(cProto.__openedChanged) === '0.46.20') {
  12077.  
  12078. let lastClose = null;
  12079. let lastOpen = null;
  12080. let cid = 0;
  12081.  
  12082. cProto.__mtChanged__ = function (b) {
  12083.  
  12084. Promise.resolve(this).then((cnt) => {
  12085. cnt._applyFocus();
  12086. return cnt;
  12087. }).then((cnt) => {
  12088. b ? cnt._renderOpened() : cnt._renderClosed();
  12089. cnt = null;
  12090. }).catch(console.warn);
  12091.  
  12092. };
  12093.  
  12094. const __moChanged__ = () => {
  12095. if (!cid) return;
  12096. // console.log(553, !!lastOpen, !!lastClose);
  12097. cid = 0;
  12098. if (lastOpen && !lastClose && lastOpen.isAttached) {
  12099. lastOpen.__mtChanged__(1)
  12100. } else if (lastClose && !lastOpen && lastClose.isAttached) {
  12101. lastClose.__mtChanged__(0);
  12102. }
  12103. lastOpen = null;
  12104. lastClose = null;
  12105. };
  12106.  
  12107.  
  12108. if (typeof cProto._openedChanged === 'function' && !cProto._openedChanged66) {
  12109. cProto._openedChanged66 = cProto._openedChanged;
  12110. cProto._openedChanged = function () {
  12111. // this.__byPassRAF__ = !lastOpen ? true : false; // or just true?
  12112. this.__byPassRAF__ = true;
  12113. let r = this._openedChanged66.apply(this, arguments);
  12114. this.__byPassRAF__ = false;
  12115. return r;
  12116. }
  12117. }
  12118.  
  12119. const pSetGet = (key, pdThis, pdBase) => {
  12120. // note: this is not really a standard way for the getOwnPropertyDescriptors; but it is sufficient to make the job done
  12121. return {
  12122. get: (pdThis[key] || 0).get || (pdBase[key] || 0).get,
  12123. set: (pdThis[key] || 0).set || (pdBase[key] || 0).set
  12124. };
  12125. };
  12126.  
  12127. cProto.__modifiedMenuPropsFn__ = function () {
  12128. const pdThis = Object.getOwnPropertyDescriptors(this.constructor.prototype)
  12129. const pdBase = Object.getOwnPropertyDescriptors(this)
  12130.  
  12131. const pdAutoFitOnAttach = pSetGet('autoFitOnAttach', pdThis, pdBase);
  12132. const pdExpandSizingTargetForScrollbars = pSetGet('expandSizingTargetForScrollbars', pdThis, pdBase);
  12133. const pdAllowOutsideScroll = pSetGet('allowOutsideScroll', pdThis, pdBase);
  12134.  
  12135. if (pdAutoFitOnAttach.get || pdAutoFitOnAttach.set) {
  12136. console.warn('there is setter/getter for autoFitOnAttach');
  12137. return;
  12138. }
  12139. if (pdExpandSizingTargetForScrollbars.get || pdExpandSizingTargetForScrollbars.set) {
  12140. console.warn('there is setter/getter for expandSizingTargetForScrollbars');
  12141. return;
  12142. }
  12143. if (!pdAllowOutsideScroll.get || !pdAllowOutsideScroll.set) {
  12144. console.warn('there is NO setter-getter for allowOutsideScroll');
  12145. return;
  12146. }
  12147.  
  12148. let { autoFitOnAttach, expandSizingTargetForScrollbars, allowOutsideScroll } = this;
  12149.  
  12150. this.__AllowOutsideScrollPD__ = pdAllowOutsideScroll;
  12151.  
  12152. const fitEnable = CHAT_MENU_REFIT_ALONG_SCROLLING === 2;
  12153.  
  12154. Object.defineProperties(this, {
  12155. autoFitOnAttach: {
  12156. get() {
  12157. if (fitEnable && this._modifiedMenuPropOn062__) return true;
  12158. return autoFitOnAttach;
  12159. },
  12160. set(nv) {
  12161. autoFitOnAttach = nv;
  12162. return true;
  12163. },
  12164. enumerable: true,
  12165. configurable: true
  12166. }, expandSizingTargetForScrollbars: {
  12167. get() {
  12168. if (fitEnable && this._modifiedMenuPropOn062__) return true;
  12169. return expandSizingTargetForScrollbars;
  12170. },
  12171. set(nv) {
  12172. expandSizingTargetForScrollbars = nv;
  12173. return true;
  12174. },
  12175. enumerable: true,
  12176. configurable: true
  12177. }, allowOutsideScroll: {
  12178. get() {
  12179. if (this._modifiedMenuPropOn062__) return true;
  12180. return allowOutsideScroll;
  12181. },
  12182. set(nv) {
  12183. allowOutsideScroll = nv;
  12184. this.__AllowOutsideScrollPD__.set.call(this, nv);
  12185. return true;
  12186. },
  12187. enumerable: true,
  12188. configurable: true
  12189. }
  12190. })
  12191. };
  12192.  
  12193. /*
  12194. // ***** position() to be changed. *****
  12195. tp-yt-iron-dropdown[class], tp-yt-iron-dropdown[class] #contentWrapper, tp-yt-iron-dropdown[class] ytd-menu-popup-renderer[class] {
  12196.  
  12197. overflow: visible !important;
  12198. min-width: max-content !important;
  12199. max-width: max-content !important;
  12200. max-height: max-content !important;
  12201. min-height: max-content !important;
  12202. white-space: nowrap;
  12203. }
  12204.  
  12205. */
  12206. if (FIX_MENU_POSITION_N_SIZING_ON_SHOWN && typeof cProto.position === 'function' && !cProto.position34 && typeof cProto.refit === 'function') {
  12207.  
  12208. let m34 = 0;
  12209. cProto.__refitByPosition__ = function () {
  12210. m34++;
  12211. if (m34 <= 0) m34 = 0;
  12212. if (m34 !== 1) return;
  12213. const hostElement = this.hostElement || this;
  12214. if (document.visibilityState === 'visible') {
  12215. const sizingTarget = this.sizingTarget;
  12216. if (!sizingTarget) {
  12217. m34 = 0;
  12218. return;
  12219. }
  12220. hostElement.setAttribute('rNgzQ', '');
  12221. sizingTarget.setAttribute('rNgzQ', '');
  12222.  
  12223. const gn = () => {
  12224. hostElement.removeAttribute('rNgzQ');
  12225. sizingTarget.removeAttribute('rNgzQ');
  12226. }
  12227.  
  12228. const an = async () => {
  12229. while (m34 >= 1) {
  12230. await renderReadyPn(sizingTarget);
  12231. if (this.opened && this.isAttached && sizingTarget.isConnected === true && sizingTarget === this.sizingTarget) {
  12232. if (sizingTarget.matches('ytd-menu-popup-renderer[slot="dropdown-content"].yt-live-chat-app')) this.refit();
  12233. }
  12234. m34--;
  12235. }
  12236. m34 = 0;
  12237. Promise.resolve().then(gn);
  12238. }
  12239. setTimeout(an, 4); // wait those resizing function calls
  12240.  
  12241.  
  12242. } else {
  12243. m34 = 0;
  12244. }
  12245. }
  12246. cProto.position34 = cProto.position
  12247. cProto.position = function () {
  12248. if (this._positionInitialize_) {
  12249. this._positionInitialize_ = 0;
  12250. this.__refitByPosition__();
  12251. }
  12252. let r = cProto.position34.apply(this, arguments);
  12253. return r;
  12254. }
  12255. console1.log("FIX_MENU_POSITION_ON_SHOWN - OK");
  12256.  
  12257. } else {
  12258.  
  12259. console1.log("FIX_MENU_POSITION_ON_SHOWN - NG");
  12260.  
  12261. }
  12262.  
  12263.  
  12264.  
  12265. cProto.__openedChanged = function () {
  12266. // console.log(123445)
  12267. this._positionInitialize_ = 1;
  12268. // this.removeAttribute('horizontal-align')
  12269. // this.removeAttribute('vertical-align')
  12270. if (typeof this.__menuTypeCheck__ !== 'boolean') {
  12271. this.__menuTypeCheck__ = true;
  12272. if (CHAT_MENU_SCROLL_UNLOCKING) {
  12273. this._modifiedMenuPropOn062__ = false;
  12274. // console.log(513, this.positionTarget && this.positionTarget.classList.contains('yt-live-chat-text-message-renderer'))
  12275. // this.autoFitOnAttach = true;
  12276. // this.expandSizingTargetForScrollbars = true;
  12277. // this.allowOutsideScroll = true;
  12278. // console.log(519,Object.getOwnPropertyDescriptors(this.constructor.prototype))
  12279. this.__modifiedMenuPropsFn__();
  12280. // this.constrain= function(){}
  12281. // this.position= function(){}
  12282.  
  12283. // this.autoFitOnAttach = true;
  12284. // this.expandSizingTargetForScrollbars = true;
  12285. // this.allowOutsideScroll = true;
  12286. }
  12287. }
  12288. if (CHAT_MENU_SCROLL_UNLOCKING && this.opened) {
  12289. let newValue = null;
  12290. const positionTarget = this.positionTarget;
  12291. if (positionTarget && positionTarget.classList.contains('yt-live-chat-text-message-renderer')) {
  12292. if (this._modifiedMenuPropOn062__ === false) {
  12293. newValue = true;
  12294. }
  12295. } else if (this._modifiedMenuPropOn062__ === true) {
  12296. newValue = false;
  12297. }
  12298. if (newValue !== null) {
  12299. const beforeAllowOutsideScroll = this.allowOutsideScroll;
  12300. this._modifiedMenuPropOn062__ = newValue;
  12301. const afterAllowOutsideScroll = this.allowOutsideScroll;
  12302. if (beforeAllowOutsideScroll !== afterAllowOutsideScroll) this.__AllowOutsideScrollPD__.set.call(this, afterAllowOutsideScroll);
  12303. }
  12304. }
  12305.  
  12306. if (this.opened) {
  12307.  
  12308. Promise.resolve().then(() => {
  12309.  
  12310. this._prepareRenderOpened();
  12311. }).then(() => {
  12312. // console.log('[yt-chat-dialog]', this._manager)
  12313. try{
  12314. this._manager.addOverlay(this);
  12315. }catch(e){
  12316. console.log('this._manager.addOverlay(this) fails.')
  12317. }
  12318. if (this._manager._overlays.length === 1) {
  12319. lastOpen = this;
  12320. lastClose = null;
  12321. } else {
  12322. return 1;
  12323. }
  12324. // if (cid) {
  12325. // clearTimeout(cid);
  12326. // cid = -1;
  12327. // this.__moChanged__();
  12328. // cid = 0;
  12329. // } else {
  12330. // cid = -1;
  12331. // this.__moChanged__();
  12332. // cid = 0;
  12333. // }
  12334. // cid = cid > 0 ? clearTimeout(cid) : 0;
  12335. // console.log(580, this.positionTarget && this.positionTarget.classList.contains('yt-live-chat-text-message-renderer'))
  12336. // cid = cid || setTimeout(__moChanged__, delay1);
  12337. cid = cid || requestAnimationFrame(__moChanged__);
  12338. }).then((r) => {
  12339.  
  12340. if (r) this.__mtChanged__(1);
  12341. }).catch(console.warn);
  12342.  
  12343. } else {
  12344. Promise.resolve().then(() => {
  12345. // console.log('[yt-chat-dialog]', this._manager)
  12346. try{
  12347. this._manager.removeOverlay(this);
  12348. }catch(e){
  12349. console.log('this._manager.removeOverlay(this) fails.')
  12350. }
  12351. if (this._manager._overlays.length === 0) {
  12352. lastClose = this;
  12353. lastOpen = null;
  12354. } else {
  12355. return 1;
  12356. }
  12357. // cid = cid > 0 ? clearTimeout(cid) : 0;
  12358. // console.log(581, this.positionTarget && this.positionTarget.classList.contains('yt-live-chat-text-message-renderer'))
  12359. // cid = cid || setTimeout(__moChanged__, delay1);
  12360. cid = cid || requestAnimationFrame(__moChanged__);
  12361. }).then((r) => {
  12362. if (r) this.__mtChanged__(0);
  12363. }).catch(console.warn);
  12364.  
  12365. }
  12366.  
  12367. }
  12368. console1.log("BOOST_MENU_OPENCHANGED_RENDERING - OK");
  12369.  
  12370. } else {
  12371.  
  12372. assertor(() => fnIntegrity(cProto.__openedChanged, '0.46.20'));
  12373. console1.log("FIX_MENU_REOPEN_RENDER_PERFORMANC_1 - NG");
  12374.  
  12375. }
  12376.  
  12377.  
  12378. if (FIX_CLICKING_MESSAGE_MENU_DISPLAY_ON_MOUSE_CLICK && typeof cProto.__openedChanged === 'function' && !cProto.__openedChanged82) {
  12379.  
  12380. cProto.__openedChanged82 = cProto.__openedChanged;
  12381.  
  12382.  
  12383. cProto.__openedChanged = function () {
  12384. const positionTarget = this.positionTarget;
  12385. currentMenuPivotWR = positionTarget ? mWeakRef(positionTarget) : null;
  12386. return this.__openedChanged82.apply(this, arguments);
  12387. }
  12388. }
  12389.  
  12390.  
  12391. })();
  12392.  
  12393. console1.log("[End]");
  12394.  
  12395. groupEnd();
  12396.  
  12397. }).catch(console.warn);
  12398.  
  12399.  
  12400.  
  12401. FIX_ToggleRenderPolymerControllerExtractionBug && customElements.whenDefined('yt-live-chat-toggle-renderer').then(() => {
  12402.  
  12403. mightFirstCheckOnYtInit();
  12404. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-toggle-renderer hacks");
  12405. console1.log("[Begin]");
  12406. (() => {
  12407.  
  12408. const tag = "yt-live-chat-toggle-renderer";
  12409. const dummy = document.createElement(tag);
  12410.  
  12411. const cProto = getProto(dummy);
  12412. if (!cProto || !cProto.attached) {
  12413. console1.warn(`proto.attached for ${tag} is unavailable.`);
  12414. return;
  12415. }
  12416.  
  12417. })();
  12418.  
  12419. console1.log("[End]");
  12420. groupEnd();
  12421.  
  12422. });
  12423.  
  12424. FIX_MOUSEOVER_FN && (() => {
  12425.  
  12426. // this is to show tooltip for emoji
  12427.  
  12428.  
  12429. let lastShow = 0;
  12430.  
  12431. const wm = new WeakSet();
  12432. const mo1 = new MutationObserver((mutations) => {
  12433.  
  12434. for (const p of document.querySelectorAll('[shared-tooltip-text]:not([__a6cwm__])')) {
  12435. p.setAttribute('__a6cwm__', '');
  12436. }
  12437.  
  12438. });
  12439. mo1.observe(document, { subtree: true, attributes: true, attributeFilter: ['shared-tooltip-text'], childList: true });
  12440.  
  12441. const mo2 = new MutationObserver((mutations) => {
  12442.  
  12443. for (const mutation of mutations) {
  12444. const p = mutation.target;
  12445. if (mutation.attributeName) {
  12446. if (p.getAttribute('shared-tooltip-text')) { // allow hack
  12447. wm.add(p);
  12448. for (const e of p.getElementsByTagName('*')) {
  12449. wm.add(e);
  12450. }
  12451. } else {
  12452. if (wm.has(p)) {
  12453. wm.remove(p);
  12454. for (const e of p.getElementsByTagName('*')) {
  12455. wm.remove(e);
  12456. }
  12457. }
  12458. }
  12459. }
  12460. }
  12461. });
  12462. mo2.observe(document, { subtree: true, attributes: true, attributeFilter: ['__a6cwm__', 'shared-tooltip-text'], childList: false });
  12463.  
  12464.  
  12465. let done = 0;
  12466. // lcrFn2 will run twice to ensure the method is successfully injected.
  12467. const lcrFn2 = (lcrDummy) => {
  12468. // make minimal function overhead by pre-defining all possible outside.
  12469.  
  12470. const tag = "yt-live-chat-renderer"
  12471. const dummy = lcrDummy;
  12472.  
  12473. const cProto = getProto(dummy);
  12474. if (!cProto || !cProto.attached) {
  12475. console.warn(`proto.attached for ${tag} is unavailable.`);
  12476. return;
  12477. }
  12478.  
  12479. // mightFirstCheckOnYtInit();
  12480. // groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-renderer hacks");
  12481. // console.log("[Begin]");
  12482.  
  12483.  
  12484.  
  12485. if (done !== 1 && typeof cProto.onMouseOver_ === 'function' && !cProto.onMouseOver37_ && typeof cProto.createTooltipIfRequired_ === 'function' && cProto.createTooltipIfRequired_.length === 0) {
  12486.  
  12487. done = 1;
  12488. const onMouseOver37_ = cProto.onMouseOver37_ = cProto.onMouseOver_;
  12489.  
  12490. const checkMatch = (() => {
  12491.  
  12492.  
  12493. let accessList = [];
  12494. let withError = false;
  12495. try {
  12496.  
  12497. onMouseOver37_.call(lcrDummy, {
  12498. type: 'mouseover',
  12499. target: new Proxy({
  12500. nodeName: 'DIV',
  12501. tagName: 'DIV',
  12502. getAttribute: function () { },
  12503. parentNode: null
  12504. }, {
  12505. get(target, p) {
  12506. accessList.push(`getter:${p}`);
  12507. if (!(p in target)) throw Error(`getter ${p} is not found`);
  12508. },
  12509. set(target, p, v) {
  12510. accessList.push(`setter:${p}`);
  12511. throw Error(`setter ${p} is not found`);
  12512. }
  12513. })
  12514. });
  12515. } catch (e) {
  12516. withError = true;
  12517. // console.warn(e);
  12518. }
  12519.  
  12520. if (withError) return false;
  12521.  
  12522. if (accessList.join(',') !== 'getter:getAttribute,getter:parentNode') return false;
  12523.  
  12524. accessList.length = 0;
  12525.  
  12526. let parent;
  12527. try {
  12528.  
  12529. parent = new Proxy({
  12530. nodeName: 'DIV',
  12531. tagName: 'DIV',
  12532. getAttribute: function (e) {
  12533.  
  12534. accessList.push(`getter:getAttribute(${e})`);
  12535. return e === 'shared-tooltip-text' ? ':cherry_blossom:' : null;
  12536.  
  12537. },
  12538. parentNode: null
  12539. }, {
  12540. get(target, p) {
  12541. accessList.push(`getter:${p}`);
  12542. if (!(p in target)) throw Error(`getter ${p} is not found`);
  12543. return target[p]
  12544. },
  12545. set(target, p, v) {
  12546. accessList.push(`setter:${p}`);
  12547. throw Error(`setter ${p} is not found`);
  12548. }
  12549. });
  12550.  
  12551. onMouseOver37_.call(lcrDummy, {
  12552. type: 'mouseover',
  12553. target: new Proxy({
  12554. nodeName: 'IMG',
  12555. tagName: 'IMG',
  12556. id: 'img',
  12557. getAttribute: function (e) {
  12558.  
  12559. accessList.push(`getter:getAttribute(${e})`);
  12560. return e === 'shared-tooltip-text' ? ':cherry_blossom:' : null;
  12561.  
  12562. },
  12563. get parentNode() {
  12564. return parent
  12565. },
  12566. get parentElement() {
  12567. return parent
  12568. }
  12569. }, {
  12570. get(target, p) {
  12571. accessList.push(`getter:${p}`);
  12572. if (!(p in target)) throw Error(`getter ${p} is not found`);
  12573. return target[p]
  12574. },
  12575. set(target, p, v) {
  12576. accessList.push(`setter:${p}`);
  12577. throw Error(`setter ${p} is not found`);
  12578. }
  12579. })
  12580. });
  12581. } catch (e) {
  12582. withError = true;
  12583. // console.warn(e);
  12584. }
  12585. parent = null;
  12586.  
  12587. 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:$$') {
  12588. return true;
  12589. }
  12590.  
  12591.  
  12592.  
  12593. })();
  12594. if (checkMatch) {
  12595.  
  12596. cProto.onMouseOver_ = function (evt) {
  12597. const p = (evt || 0).target || 0;
  12598. if (p.nodeType === 1 && wm.has(p)) {
  12599. const ct = Date.now();
  12600. if (lastShow + 18 > ct) return;
  12601. const cnt = insp(this);
  12602. lastShow = ct;
  12603. try {
  12604. cnt.onMouseOver37_.call(this, evt);
  12605. } catch (e) {
  12606. console.warn(e);
  12607. }
  12608. }
  12609. };
  12610.  
  12611. const lcrs = [...new Set([lcrDummy, ...document.querySelectorAll('yt-live-chat-renderer')])];
  12612. for (const lcr of lcrs) {
  12613. const cnt = insp(lcr);
  12614. const hostElement = cnt.hostElement;
  12615. if (hostElement && cnt.isAttached === true && cnt.onMouseOver37_ === cProto.onMouseOver37_ && typeof cProto.onMouseOver_ === 'function' && cProto.onMouseOver_ !== cProto.onMouseOver37_ && cnt.onMouseOver_ === cProto.onMouseOver_) {
  12616. hostElement.removeEventListener("mouseover", cProto.onMouseOver37_, !0)
  12617. hostElement.addEventListener("mouseover", cProto.onMouseOver_, !0)
  12618. }
  12619. }
  12620.  
  12621. console.log('[yt-chat-lcr] FIX_MOUSEOVER_FN - OK')
  12622.  
  12623. } else {
  12624.  
  12625. console.log('[yt-chat-lcr] FIX_MOUSEOVER_FN - NG')
  12626.  
  12627. }
  12628.  
  12629. } else if (done !== 1) {
  12630. done = 2;
  12631. console.log('[yt-chat-lcr] FIX_MOUSEOVER_FN - NG')
  12632. }
  12633.  
  12634. // console.log("[End]");
  12635. // groupEnd();
  12636.  
  12637.  
  12638. };
  12639. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  12640. // getLCRDummy() must be called for injection
  12641. getLCRDummy().then(lcrFn2);
  12642.  
  12643. })();
  12644.  
  12645.  
  12646. /*
  12647.  
  12648.  
  12649.  
  12650.  
  12651.  
  12652. var FU = function() {
  12653. var a = this;
  12654. this.nextHandle_ = 1;
  12655. this.clients_ = {};
  12656. this.JSC$10323_callbacks_ = {};
  12657. this.unsubscribeAsyncHandles_ = {};
  12658. this.subscribe = vl(function(b, c, d) {
  12659. var e = Geb(b);
  12660. if (e in a.clients_)
  12661. e in a.unsubscribeAsyncHandles_ && Jq.cancel(a.unsubscribeAsyncHandles_[e]);
  12662. else {
  12663. a: {
  12664. var h = Geb(b), l;
  12665. for (l in a.unsubscribeAsyncHandles_) {
  12666. var m = a.clients_[l];
  12667. if (m instanceof KO) {
  12668. delete a.clients_[l];
  12669. delete a.JSC$10323_callbacks_[l];
  12670. Jq.cancel(a.unsubscribeAsyncHandles_[l]);
  12671. delete a.unsubscribeAsyncHandles_[l];
  12672. i6a(m);
  12673. m.objectId_ = new FQa(h);
  12674. m.register();
  12675. d = m;
  12676. break a
  12677. }
  12678. }
  12679. d.objectSource = b.invalidationId.objectSource;
  12680. d.objectId = h;
  12681. if (b = b.webAuthConfigurationData)
  12682. b.multiUserSessionIndex && (d.sessionIndex = parseInt(b.multiUserSessionIndex, 10)),
  12683. b.pageId && (d.pageId = b.pageId);
  12684. d = new KO(d,a.handleInvalidationData_.bind(a));
  12685. d.register()
  12686. }
  12687. a.clients_[e] = d;
  12688. a.JSC$10323_callbacks_[e] = {}
  12689. }
  12690. d = a.nextHandle_++;
  12691. a.JSC$10323_callbacks_[e][d] = c;
  12692. return d
  12693. })
  12694. };
  12695. FU.prototype.unsubscribe = function(a, b) {
  12696. var c = Geb(a);
  12697. if (c in this.JSC$10323_callbacks_ && (delete this.JSC$10323_callbacks_[c][b],
  12698. !this.JSC$10323_callbacks_[c].length)) {
  12699. var d = this.clients_[c];
  12700. b = Jq.run(function() {
  12701. ei(d);
  12702. delete this.clients_[c];
  12703. delete this.unsubscribeAsyncHandles_[c]
  12704. }
  12705. .bind(this));
  12706. this.unsubscribeAsyncHandles_[c] = b
  12707. }
  12708. }
  12709. ;
  12710.  
  12711.  
  12712. */
  12713.  
  12714.  
  12715. const onManagerFound = (dummyManager) => {
  12716. if (!dummyManager || typeof dummyManager !== 'object') return;
  12717.  
  12718. const mgrProto = dummyManager.constructor.prototype;
  12719.  
  12720. let keyCallbackStore = '';
  12721. for (const [key, v] of Object.entries(dummyManager)) {
  12722. if (key.includes('_callbacks_')) keyCallbackStore = key;
  12723. }
  12724.  
  12725. if (!keyCallbackStore || typeof mgrProto.unsubscribe !== 'function' || mgrProto.unsubscribe.length !== 2) return;
  12726.  
  12727. if (mgrProto.unsubscribe16) return;
  12728.  
  12729. mgrProto.unsubscribe16 = mgrProto.unsubscribe;
  12730.  
  12731. groupCollapsed("YouTube Super Fast Chat", " | *live-chat-manager* hacks");
  12732. console1.log("[Begin]");
  12733.  
  12734. const idMapper = new Map();
  12735.  
  12736. const convertId = function (objectId) {
  12737. if (!objectId || typeof objectId !== 'string') return null;
  12738.  
  12739. let result = idMapper.get(objectId)
  12740. if (result) return result;
  12741. result = atob(objectId.replace(/-/g, "+").replace(/_/g, "/"));
  12742. idMapper.set(objectId, result)
  12743. return result;
  12744. }
  12745.  
  12746.  
  12747. const rafHandleHolder = [];
  12748.  
  12749. let pzw = 0;
  12750. let lza = 0;
  12751. const rafHandlerFn = () => {
  12752. pzw = 0;
  12753. if (rafHandleHolder.length === 1) {
  12754. const f = rafHandleHolder[0];
  12755. rafHandleHolder.length = 0;
  12756. f();
  12757. } else if (rafHandleHolder.length > 1) {
  12758. const arr = rafHandleHolder.slice(0);
  12759. rafHandleHolder.length = 0;
  12760. for (const fn of arr) fn();
  12761. }
  12762. };
  12763.  
  12764.  
  12765. if (CHANGE_MANAGER_UNSUBSCRIBE) {
  12766.  
  12767. const checkIntegrityForSubscribe = (mgr) => {
  12768. if (mgr
  12769. && typeof mgr.unsubscribe16 === 'function' && mgr.unsubscribe16.length === 2
  12770. && typeof mgr.subscribe18 === 'function' && (mgr.subscribe18.length === 0 || mgr.subscribe18.length === 3)) {
  12771.  
  12772. const ns = new Set(Object.keys(mgr));
  12773. const ms = new Set(Object.keys(mgr.constructor.prototype));
  12774.  
  12775. if (ns.size >= 6 && ms.size >= 4) {
  12776. // including 'subscribe18'
  12777. // 'unsubscribe16', 'subscribe19'
  12778.  
  12779. let r = 0;
  12780. for (const k of ['nextHandle_', 'clients_', keyCallbackStore, 'unsubscribeAsyncHandles_', 'subscribe', 'subscribe18']) {
  12781. r += ns.has(k) ? 1 : 0;
  12782. }
  12783. for (const k of ['unsubscribe', 'handleInvalidationData_', 'unsubscribe16', 'subscribe19']) {
  12784. r += ms.has(k) ? 1 : 0;
  12785. }
  12786. if (r === 10) {
  12787. const isObject = (c) => (c || 0).constructor === Object;
  12788.  
  12789. if (isObject(mgr['clients_']) && isObject(mgr[keyCallbackStore]) && isObject(mgr['unsubscribeAsyncHandles_'])) {
  12790.  
  12791. return true;
  12792. }
  12793.  
  12794.  
  12795. }
  12796.  
  12797. }
  12798.  
  12799.  
  12800. }
  12801. return false;
  12802. }
  12803.  
  12804. mgrProto.subscribe19 = function (o, f, opts) {
  12805.  
  12806. const ct_clients_ = this.clients_ || 0;
  12807. const ct_handles_ = this.unsubscribeAsyncHandles_ || 0;
  12808.  
  12809. if (this.__doCustomSubscribe__ !== true || !ct_clients_ || !ct_handles_) return this.subscribe18.apply(this, arguments);
  12810.  
  12811. let objectId = ((o || 0).invalidationId || 0).objectId;
  12812. if (!objectId) return this.subscribe18.apply(this, arguments);
  12813. objectId = convertId(objectId);
  12814.  
  12815. // console.log('subscribe', objectId, ct_clients_[objectId], arguments);
  12816.  
  12817. if (ct_clients_[objectId]) {
  12818. if (ct_handles_[objectId] < 0) delete ct_handles_[objectId];
  12819. }
  12820.  
  12821. return this.subscribe18.apply(this, arguments);
  12822. }
  12823.  
  12824. mgrProto.unsubscribe = function (o, d) {
  12825. if (!this.subscribe18 && typeof this.subscribe === 'function') {
  12826. this.subscribe18 = this.subscribe;
  12827. this.subscribe = this.subscribe19;
  12828. this.__doCustomSubscribe__ = checkIntegrityForSubscribe(this);
  12829. }
  12830. const ct_clients_ = this.clients_;
  12831. const ct_handles_ = this.unsubscribeAsyncHandles_;
  12832. if (this.__doCustomSubscribe__ !== true || !ct_clients_ || !ct_handles_) return this.unsubscribe16.apply(this, arguments);
  12833.  
  12834. let objectId = ((o || 0).invalidationId || 0).objectId;
  12835. if (!objectId) return this.unsubscribe16.apply(this, arguments);
  12836.  
  12837. objectId = convertId(objectId);
  12838.  
  12839.  
  12840. // console.log('unsubscribe', objectId, ct_clients_[objectId], arguments);
  12841.  
  12842. const callbacks = this[keyCallbackStore] || 0;
  12843. const callbackObj = callbacks[objectId] || 0;
  12844.  
  12845.  
  12846. if (callbackObj && (delete callbackObj[d], isEmptyObject(callbackObj))) {
  12847. const w = ct_clients_[objectId];
  12848. lza = (lza & 1073741823) + 1;
  12849. const qta = -lza;
  12850. rafHandleHolder.push(() => {
  12851. if (qta === ct_handles_[objectId]) {
  12852. const o = {
  12853. callbacks, callbackObj,
  12854. client: ct_clients_[objectId],
  12855. handle: ct_handles_[objectId]
  12856. };
  12857. let p = 0;
  12858. try {
  12859. if (ct_clients_[objectId] === w) {
  12860. w && "function" === typeof w.dispose && w.dispose();
  12861. delete ct_clients_[objectId];
  12862. delete ct_handles_[objectId];
  12863. p = 1;
  12864. } else {
  12865. // w && "function" === typeof w.dispose && w.dispose();
  12866. // delete ct_clients_[objectId];
  12867. // delete ct_handles_[objectId];
  12868. p = 2;
  12869. }
  12870. } catch (e) {
  12871. console.warn(e);
  12872. }
  12873. console.log(`unsubscribed: ${p}`, this, o);
  12874. }
  12875. });
  12876. ct_handles_[objectId] = qta;
  12877. if (pzw === 0) {
  12878. pzw = requestAnimationFrame(rafHandlerFn);
  12879. }
  12880. }
  12881. }
  12882.  
  12883.  
  12884. console1.log("CHANGE_MANAGER_UNSUBSCRIBE - OK")
  12885.  
  12886. } else {
  12887.  
  12888. console1.log("CHANGE_MANAGER_UNSUBSCRIBE - NG")
  12889. }
  12890.  
  12891. console1.log("[End]");
  12892.  
  12893. groupEnd();
  12894.  
  12895. }
  12896.  
  12897.  
  12898.  
  12899. /*
  12900.  
  12901.  
  12902. a.prototype.async = function(e, h) {
  12903. return 0 < h ? Iq.run(e.bind(this), h) : ~Kq.run(e.bind(this))
  12904. }
  12905. ;
  12906. a.prototype.cancelAsync = function(e) {
  12907. 0 > e ? Kq.cancel(~e) : Iq.cancel(e)
  12908. }
  12909.  
  12910. */
  12911.  
  12912.  
  12913. (FASTER_ICON_RENDERING && Promise.all(
  12914. [
  12915. customElements.whenDefined("yt-icon-shape"),
  12916. customElements.whenDefined("yt-icon")
  12917. // document.createElement('icon-shape'),
  12918. ]
  12919. )).then(() => {
  12920. let cq = 0;
  12921. let dummys = [document.createElement('yt-icon-shape'), document.createElement('yt-icon')]
  12922. for (const dummy of dummys) {
  12923. let cProto = getProto(dummy);
  12924. if (cProto && typeof cProto.shouldRenderIconShape === 'function' && !cProto.shouldRenderIconShape571 && cProto.shouldRenderIconShape.length === 1) {
  12925. assertor(() => fnIntegrity(cProto.shouldRenderIconShape, '1.70.38'));
  12926. cq++;
  12927. cProto.shouldRenderIconShape571 = cProto.shouldRenderIconShape;
  12928. cProto.shouldRenderIconShape = function (a) {
  12929. if (this.isAnimatedIcon) return this.shouldRenderIconShape571(a);
  12930. if (!this.iconType || !this.iconShapeData) return this.shouldRenderIconShape571(a);
  12931. if (!this.iconName) return this.shouldRenderIconShape571(a);
  12932. return false;
  12933. // console.log(1051, this.iconType)
  12934. // console.log(1052, this.iconShapeData)
  12935. // console.log(1053, this.isAnimatedIcon)
  12936. }
  12937. }
  12938. // if(cProto && cProto.switchTemplateAtRegistration){
  12939. // cProto.switchTemplateAtRegistration = false;
  12940. // }
  12941. }
  12942. if (cq === 1) {
  12943. console.log("modified shouldRenderIconShape - Y")
  12944. } else {
  12945. console.log("modified shouldRenderIconShape - N", cq)
  12946. }
  12947. });
  12948.  
  12949. customElements.whenDefined("yt-invalidation-continuation").then(() => {
  12950.  
  12951. let __dummyManager__ = null;
  12952.  
  12953. mightFirstCheckOnYtInit();
  12954. groupCollapsed("YouTube Super Fast Chat", " | yt-invalidation-continuation hacks");
  12955. console1.log("[Begin]");
  12956. (() => {
  12957.  
  12958. const tag = "yt-invalidation-continuation"
  12959. const dummy = document.createElement(tag);
  12960.  
  12961. const cProto = getProto(dummy);
  12962. if (!cProto || !cProto.attached) {
  12963. console1.warn(`proto.attached for ${tag} is unavailable.`);
  12964. return;
  12965. }
  12966.  
  12967. const dummyManager = insp(dummy).manager_ || 0;
  12968. __dummyManager__ = dummyManager;
  12969.  
  12970.  
  12971. })();
  12972.  
  12973. console1.log("[End]");
  12974.  
  12975. groupEnd();
  12976.  
  12977.  
  12978.  
  12979. onManagerFound(__dummyManager__);
  12980.  
  12981. }).catch(console.warn);
  12982.  
  12983.  
  12984. if (INTERACTIVITY_BACKGROUND_ANIMATION >= 1) {
  12985.  
  12986. customElements.whenDefined("yt-live-interactivity-component-background").then(() => {
  12987.  
  12988. mightFirstCheckOnYtInit();
  12989. groupCollapsed("YouTube Super Fast Chat", " | yt-live-interactivity-component-background hacks");
  12990. console1.log("[Begin]");
  12991. (() => {
  12992.  
  12993. const tag = "yt-live-interactivity-component-background"
  12994. const dummy = document.createElement(tag);
  12995.  
  12996. const cProto = getProto(dummy);
  12997. if (!cProto || !cProto.attached) {
  12998. console1.warn(`proto.attached for ${tag} is unavailable.`);
  12999. return;
  13000. }
  13001.  
  13002. cProto.__toStopAfterRun__ = function (hostElement) {
  13003. let mo = new MutationObserver(() => {
  13004. mo.disconnect();
  13005. mo.takeRecords();
  13006. mo = null;
  13007. this.lottieAnimation && this.lottieAnimation.stop(); // primary
  13008. foregroundPromiseFn().then(() => { // if the lottieAnimation is started with rAf triggering
  13009. this.lottieAnimation && this.lottieAnimation.stop(); // fallback
  13010. });
  13011. });
  13012. mo.observe(hostElement, { subtree: true, childList: true });
  13013. }
  13014.  
  13015. if (INTERACTIVITY_BACKGROUND_ANIMATION >= 1 && typeof cProto.maybeLoadAnimationBackground === 'function' && !cProto.maybeLoadAnimationBackground77 && cProto.maybeLoadAnimationBackground.length === 0) {
  13016.  
  13017. cProto.maybeLoadAnimationBackground77 = cProto.maybeLoadAnimationBackground;
  13018. cProto.maybeLoadAnimationBackground = function () {
  13019. let toRun = true;
  13020. let stopAfterRun = false;
  13021. if (!this.__bypassDisableAnimationBackground__) {
  13022. let doFix = false;
  13023. if (INTERACTIVITY_BACKGROUND_ANIMATION === 1) {
  13024. if (!this.lottieAnimation) {
  13025. doFix = true;
  13026. }
  13027. } else if (INTERACTIVITY_BACKGROUND_ANIMATION === 2) {
  13028. doFix = true;
  13029. }
  13030. if (doFix) {
  13031. if (this.useAnimationBackground === true) {
  13032. console.log('DISABLE_INTERACTIVITY_BACKGROUND_ANIMATION', this.lottieAnimation);
  13033. }
  13034. toRun = true;
  13035. stopAfterRun = true;
  13036. }
  13037. }
  13038. if (toRun) {
  13039. if (stopAfterRun && (this.hostElement instanceof HTMLElement_)) {
  13040. this.__toStopAfterRun__(this.hostElement); // primary
  13041. }
  13042. const r = this.maybeLoadAnimationBackground77.apply(this, arguments);
  13043. if (stopAfterRun && this.lottieAnimation) {
  13044. this.lottieAnimation.stop(); // fallback if no mutation
  13045. }
  13046. return r;
  13047. }
  13048. }
  13049.  
  13050. console1.log(`INTERACTIVITY_BACKGROUND_ANIMATION(${INTERACTIVITY_BACKGROUND_ANIMATION}) - OK`);
  13051.  
  13052. } else {
  13053. console1.log(`INTERACTIVITY_BACKGROUND_ANIMATION(${INTERACTIVITY_BACKGROUND_ANIMATION}) - NG`);
  13054.  
  13055. }
  13056.  
  13057. })();
  13058.  
  13059. console1.log("[End]");
  13060.  
  13061. groupEnd();
  13062.  
  13063.  
  13064. }).catch(console.warn);
  13065.  
  13066. }
  13067.  
  13068.  
  13069. if (DELAY_FOCUSEDCHANGED) {
  13070.  
  13071. customElements.whenDefined("yt-live-chat-text-input-field-renderer").then(() => {
  13072.  
  13073.  
  13074. mightFirstCheckOnYtInit();
  13075. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-text-input-field-renderer hacks");
  13076. console1.log("[Begin]");
  13077. (() => {
  13078.  
  13079. const tag = "yt-live-chat-text-input-field-renderer"
  13080. const dummy = document.createElement(tag);
  13081.  
  13082. const cProto = getProto(dummy);
  13083. if (!cProto || !cProto.attached) {
  13084. console1.warn(`proto.attached for ${tag} is unavailable.`);
  13085. return;
  13086. }
  13087.  
  13088. if (DELAY_FOCUSEDCHANGED && typeof cProto.focusedChanged === 'function' && cProto.focusedChanged.length === 0 && !cProto.focusedChanged372) {
  13089. cProto.focusedChanged372 = cProto.focusedChanged;
  13090. cProto.focusedChanged = function () {
  13091. Promise.resolve(this).then((cnt) => {
  13092. if (cnt.isAttached === true) cnt.focusedChanged372();
  13093. });
  13094. }
  13095. }
  13096.  
  13097. })();
  13098.  
  13099. console1.log("[End]");
  13100.  
  13101. groupEnd();
  13102.  
  13103. });
  13104.  
  13105. }
  13106.  
  13107. }
  13108.  
  13109.  
  13110.  
  13111.  
  13112. promiseForCustomYtElementsReady.then(onRegistryReadyForDOMOperations);
  13113.  
  13114. const fixJsonParse = () => {
  13115.  
  13116. let p1 = window.onerror;
  13117.  
  13118. try {
  13119. JSON.parse("{}");
  13120. } catch (e) {
  13121. console.warn(e);
  13122. }
  13123.  
  13124. let p2 = window.onerror;
  13125.  
  13126. if (p1 !== p2) {
  13127.  
  13128.  
  13129. console.groupCollapsed(`%c${"YouTube Super Fast Chat"}%c${" | JS Engine Issue Found"}`,
  13130. "background-color: #010502; color: #fe806a; font-weight: 700; padding: 2px;",
  13131. "background-color: #010502; color: #fe806a; font-weight: 300; padding: 2px;"
  13132. );
  13133.  
  13134. 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://greatest.deepsurf.us/scripts/473972-youtube-js-engine-tamer to fix the issue.\n");
  13135.  
  13136. console.groupEnd();
  13137.  
  13138. }
  13139.  
  13140. }
  13141.  
  13142. if (CHECK_JSONPRUNE) {
  13143. promiseForCustomYtElementsReady.then(fixJsonParse);
  13144. }
  13145.  
  13146. });
  13147.  
  13148.  
  13149.  
  13150. })({ IntersectionObserver });