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 });