YouTube 超快聊天

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

当前为 2025-05-11 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name YouTube Super Fast Chat
  3. // @version 0.101.0
  4. // @license MIT
  5. // @name:ja YouTube スーパーファーストチャット
  6. // @name:zh-TW YouTube 超快聊天
  7. // @name:zh-CN YouTube 超快聊天
  8. // @icon https://raw.githubusercontent.com/cyfung1031/userscript-supports/main/icons/super-fast-chat.png
  9. // @namespace UserScript
  10. // @match https://www.youtube.com/live_chat*
  11. // @match https://www.youtube.com/live_chat_replay*
  12. // @author CY Fung
  13. // @run-at document-start
  14. // @grant none
  15. // @unwrap
  16. // @allFrames true
  17. // @inject-into page
  18. // @require https://update.gf.qytechs.cn/scripts/475632/1361351/ytConfigHacks.js
  19. // @require https://cdn.jsdelivr.net/gh/cyfung1031/userscript-supports@c2b707e4977f77792042d4a5015fb188aae4772e/library/nextBrowserTick.min.js
  20. //
  21. // @compatible firefox Violentmonkey
  22. // @compatible firefox Tampermonkey
  23. // @compatible firefox FireMonkey
  24. // @compatible chrome Violentmonkey
  25. // @compatible chrome Tampermonkey
  26. // @compatible opera Violentmonkey
  27. // @compatible opera Tampermonkey
  28. // @compatible safari Stay
  29. // @compatible edge Violentmonkey
  30. // @compatible edge Tampermonkey
  31. // @compatible brave Violentmonkey
  32. // @compatible brave Tampermonkey
  33. //
  34. // @description Ultimate Performance Boost for YouTube Live Chats
  35. // @description:ja YouTubeのライブチャットの究極のパフォーマンスブースト
  36. // @description:zh-TW YouTube直播聊天的終極性能提升
  37. // @description:zh-CN YouTube直播聊天的终极性能提升
  38. //
  39. // ==/UserScript==
  40.  
  41. ((__CONTEXT__) => {
  42. 'use strict';
  43.  
  44. /** @type {WeakMapConstructor} */
  45. const WeakMap = window.WeakMapOriginal || window.WeakMap;
  46.  
  47. const DEBUG_LOG_GROUP_EXPAND = +localStorage.__debugSuperFastChat__ > 0;
  48. const DEBUG_LOG_HIDE_OK = true;
  49. const DEBUG_skipLog001 = true;
  50. const DEBUG_preprocessChatLiveActions = false;
  51. const DEBUG_customCreateComponent = false;
  52. // const SHOW_DEVTOOL_DEBUG = true; // for debug use
  53. const SHOW_DEVTOOL_DEBUG = typeof ResizeObserver === 'function' && CSS.supports('position-area:center');
  54.  
  55. // *********** DON'T REPORT NOT WORKING DUE TO THE CHANGED SETTINGS ********************
  56. // The settings are FIXED! You might change them to try but if the script does not work due to your change, please, don't report them as issues
  57.  
  58. /// -------------------------------------------------------------------------
  59.  
  60. const USE_ADVANCED_TICKING = true; // DONT CHANGE
  61. // << if USE_ADVANCED_TICKING >>
  62. const FIX_TIMESTAMP_FOR_REPLAY = true;
  63. const ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION = true; // MUST BE true
  64. const REUSE_TICKER = true; // for better memory control; currently it is only available in ADVANCED_TICKING; to be further reviewed << NO EFFECT SINCE ENABLE_TICKERS_BOOSTED_STAMPING IS USED >>
  65. // << end >>
  66.  
  67. const ENABLE_CHAT_MESSAGES_BOOSTED_STAMPING = true; // TRUE to boost chat messages rendering (DONT CHANGE)
  68. const ENABLE_TICKERS_BOOSTED_STAMPING = true; // TRUE to boost chat messages rendering (DONT CHANGE)
  69. const DISABLE_DYNAMIC_TICKER_WIDTH = true; // We use the opacity change instead
  70.  
  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. .r6-width-adjustable {
  1086. min-width: max-content;
  1087. margin-right: 0 !important;
  1088. }
  1089.  
  1090.  
  1091. /*
  1092. .r6-width-adjustable {
  1093. --r6-min-width: 0;
  1094. min-width: var(--r6-min-width);
  1095. }
  1096.  
  1097. .r6-width-adjustable-f {
  1098. --r6-min-width: max-content;
  1099. }
  1100.  
  1101. .r6-closing-ticker[class] {
  1102. --r6-min-width: 0;
  1103. }
  1104.  
  1105. */
  1106.  
  1107. ` : '';
  1108.  
  1109. const cssText20_TICKER_SIZING = ENABLE_TICKERS_BOOSTED_STAMPING && DISABLE_DYNAMIC_TICKER_WIDTH ? `
  1110.  
  1111. :root {
  1112. --ticker-items-gap: 8px;
  1113. }
  1114. #ticker-items.yt-live-chat-ticker-renderer {
  1115. position: relative;
  1116. transform: translateZ(1px);
  1117. box-sizing: border-box;
  1118. contain: style;
  1119. display: flex;
  1120. flex-direction: row;
  1121. gap: var(--ticker-items-gap);
  1122. }
  1123. #container.yt-live-chat-ticker-renderer {
  1124. contain: layout paint style;
  1125. }
  1126.  
  1127. .yt-live-chat-ticker-stampdom {
  1128. position: static;
  1129. width: max-content;
  1130. content-visibility:auto;
  1131. }
  1132. .yt-live-chat-ticker-stampdom[class] {
  1133. transition: none;
  1134. }
  1135. .yt-live-chat-ticker-stampdom-container {
  1136. position: static;
  1137. width: max-content;
  1138. content-visibility:auto;
  1139. }
  1140.  
  1141. .yt-live-chat-ticker-stampdom {
  1142. margin-right:0 !important; /* flex gap 8px */
  1143. }
  1144.  
  1145. /* default animation */
  1146. .yt-live-chat-ticker-stampdom {
  1147. animation: ticker-shown-animation 220ms ease-in 0s 1 normal forwards;
  1148. }
  1149. /* default animation */
  1150. @keyframes ticker-shown-animation {
  1151. 0%, 70%, 100% { opacity: 1; }
  1152. 30% { opacity: 0.2; }
  1153. }
  1154.  
  1155.  
  1156. ` : "";
  1157. // const cssText19_FOR_ADVANCED_TICKING = `
  1158.  
  1159. // ticker-bg-overlay {
  1160. // display: block;
  1161. // position: absolute;
  1162. // z-index: -1;
  1163. // box-sizing: border-box;
  1164. // border: 0;
  1165. // padding: 0;
  1166. // margin: 0;
  1167. // width: 200%;
  1168. // top: 0;
  1169. // bottom: 0;
  1170. // left: clamp(-100%, calc( -100% * ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) ), 0%);
  1171. // contain: strict;
  1172. // }
  1173. // /*
  1174. // ticker-bg-overlay-end {
  1175. // position: absolute;
  1176. // right: 0px;
  1177. // top: 50%;
  1178. // display: block;
  1179. // width: 1px;
  1180. // height: 1px;
  1181. // opacity: 0;
  1182. // pointer-events: none;
  1183. // box-sizing: border-box;
  1184. // border: 0;
  1185. // padding: 0;
  1186. // margin: 0;
  1187. // contain: strict;
  1188. // }
  1189. // */
  1190.  
  1191. // ticker-bg-overlay-end2 {
  1192.  
  1193. // all:unset;
  1194. // position: fixed;
  1195. // display: block;
  1196. // margin-left: -0.5px;
  1197. // top: 8px;
  1198. // left: clamp(-250px, calc( 250px * ( ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) - 1 ) ), 2px);
  1199.  
  1200. // width: 1px;
  1201. // height: 1px;
  1202. // opacity: 0;
  1203. // pointer-events: none;
  1204. // box-sizing: border-box;
  1205. // border: 0;
  1206. // padding: 0;
  1207. // margin: 0;
  1208. // contain: strict;
  1209. // z-index: -1;
  1210. // visibility: collapse;
  1211.  
  1212.  
  1213. // }
  1214.  
  1215. // /* USE_ADVANCED_TICKING */
  1216.  
  1217. // /*
  1218.  
  1219. // .ticker-no-transition-time, .ticker-no-transition-time [id] {
  1220. // transition-duration: 0s !important;
  1221. // }
  1222.  
  1223. // [r6-advanced-ticking] .style-scope.yt-live-chat-ticker-renderer ~ .style-scope.yt-live-chat-ticker-renderer:not(.r6-closing-ticker) {
  1224. // transition-duration: 0s !important;
  1225. // }
  1226.  
  1227. // */
  1228.  
  1229. // .r6-width-adjustable ~ .r6-width-adjustable {
  1230. // --r6-min-width: max-content;
  1231. // }
  1232.  
  1233. // .r6-closing-ticker[class] {
  1234. // --r6-min-width: 0px;
  1235. // }
  1236.  
  1237. // .r6-width-adjustable {
  1238. // min-width: var(--r6-min-width, 0px);
  1239. // }
  1240.  
  1241.  
  1242. // /*
  1243.  
  1244.  
  1245. // .r6-width-adjustable {
  1246. // transition-duration: var(--r6-transition-duration, 0s) !important;
  1247. // }
  1248.  
  1249. // .r6-width-adjustable-first {
  1250. // --r6-transition-duration: 0.2s;
  1251. // }
  1252.  
  1253. // .r6-width-adjustable ~ .r6-width-adjustable-first {
  1254. // --r6-transition-duration: 0s;
  1255. // }
  1256.  
  1257. // .r6-closing-ticker {
  1258. // --r6-transition-duration: 0.2s;
  1259. // }
  1260. // */
  1261.  
  1262. // /*
  1263.  
  1264.  
  1265. // ey.style.position = 'absolute';
  1266. // ey.style.right = '0px';
  1267. // ey.style.top = '50%';
  1268. // ey.style.display='block';
  1269. // ey.style.width='1px';
  1270. // ey.style.height='1px';
  1271. // ey.style.opacity = '0';
  1272.  
  1273. // em.style.display = 'block';
  1274. // em.style.position = 'absolute';
  1275. // em.style.boxSizing = 'border-box';
  1276. // em.style.width = '200%';
  1277. // em.style.top = '0';
  1278. // em.style.bottom = '0';
  1279. // // em.style.height = '100%';
  1280.  
  1281.  
  1282. // // em.style.left = '-50%';
  1283. // // em.style.left = "clamp(-100%, calc( -100% * ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) ), 0%)";
  1284.  
  1285. // */
  1286.  
  1287. // `;
  1288.  
  1289. const addCss = () => `
  1290.  
  1291. yt-live-chat-renderer {
  1292. max-height: 100vh;
  1293. }
  1294.  
  1295. @property --ticker-rtime {
  1296. syntax: "<percentage>";
  1297. inherits: false;
  1298. initial-value: 0%;
  1299. }
  1300.  
  1301. .run-ticker {
  1302. --ticker-bg:linear-gradient(90deg, var(--ticker-c1),var(--ticker-c1) var(--ticker-rtime),var(--ticker-c2) var(--ticker-rtime),var(--ticker-c2));
  1303. }
  1304.  
  1305. .run-ticker,
  1306. yt-live-chat-ticker-renderer #items > * > #container.run-ticker,
  1307. yt-live-chat-ticker-renderer[class] #items[class] > *[class] > #container.run-ticker[class]
  1308. {
  1309. background: var(--ticker-bg) !important;
  1310. }
  1311.  
  1312. yt-live-chat-ticker-dummy777-item-renderer {
  1313. background: #00000001;
  1314. }
  1315.  
  1316. yt-live-chat-ticker-dummy777-item-renderer[dummy777] {
  1317. position: fixed !important;
  1318. top: -1000px !important;
  1319. left: -1000px !important;
  1320. font-size: 1px !important;
  1321. color: transparent !important;
  1322. pointer-events: none !important;
  1323. z-index: -1 !important;
  1324. contain: strict !important;
  1325. box-sizing: border-box !important;
  1326. pointer-events: none !important;
  1327. user-select: none !important;
  1328. max-width: 1px !important;
  1329. max-height: 1px !important;
  1330. overflow: hidden !important;
  1331. visibility: collapse !important;
  1332. display: none !important;
  1333. }
  1334.  
  1335. yt-live-chat-ticker-dummy777-item-renderer #container {
  1336. background: inherit;
  1337. }
  1338.  
  1339.  
  1340. ${cssText8_fonts_pre_render}
  1341.  
  1342. ${cssText9_no_backdrop_filter_when_menu_shown}
  1343.  
  1344. @supports (contain: layout paint style) {
  1345.  
  1346. ${cssText5}
  1347.  
  1348. }
  1349.  
  1350. @supports (color: var(--general)) {
  1351.  
  1352. html {
  1353. --yt-live-chat-item-list-renderer-padding: 0px 0px;
  1354. }
  1355.  
  1356. ${cssText3_smooth_transform_position}
  1357.  
  1358. ${cssText7c_will_change_unset}
  1359.  
  1360. ${cssText7b_content_visibility_unset}
  1361.  
  1362. yt-live-chat-item-list-renderer:not([allow-scroll]) #item-scroller.yt-live-chat-item-list-renderer {
  1363. overflow-y: scroll;
  1364. padding-right: 0;
  1365. }
  1366.  
  1367. ${cssText4_smooth_transform_forced_props}
  1368.  
  1369. yt-icon[icon="down_arrow"] > *, yt-icon-button#show-more > * {
  1370. pointer-events: none !important;
  1371. }
  1372.  
  1373. #continuations, #continuations * {
  1374. contain: strict;
  1375. position: fixed;
  1376. top: 2px;
  1377. height: 1px;
  1378. width: 2px;
  1379. height: 1px;
  1380. visibility: collapse;
  1381. }
  1382.  
  1383. ${cssText6b_show_more_button}
  1384.  
  1385. ${cssText6d_input_panel_border}
  1386.  
  1387. ${cssText6c_input_panel_overflow}
  1388.  
  1389. }
  1390.  
  1391.  
  1392. @supports (overflow-anchor: auto) {
  1393.  
  1394. .no-anchor * {
  1395. overflow-anchor: none;
  1396. }
  1397. .no-anchor > item-anchor {
  1398. overflow-anchor: auto;
  1399. }
  1400. #item-scroller.style-scope.yt-live-chat-item-list-renderer[class] {
  1401. overflow-anchor: initial !important; /* whenever ENABLE_OVERFLOW_ANCHOR or not */
  1402. }
  1403. }
  1404.  
  1405. item-anchor {
  1406.  
  1407. height: 1px;
  1408. width: 100%;
  1409. transform: scaleY(0.00001);
  1410. transform-origin:0 0;
  1411. contain: strict;
  1412. opacity:0;
  1413. display:flex;
  1414. position:relative;
  1415. flex-shrink:0;
  1416. flex-grow:0;
  1417. margin-bottom:0;
  1418. overflow:hidden;
  1419. box-sizing:border-box;
  1420. visibility: visible;
  1421. content-visibility: visible;
  1422. contain-intrinsic-size: auto 1px;
  1423. pointer-events:none !important;
  1424.  
  1425. }
  1426.  
  1427. html item-anchor {
  1428.  
  1429. height: 1px;
  1430. width: 1px;
  1431. top: auto;
  1432. left: auto;
  1433. right: auto;
  1434. bottom: auto;
  1435. transform: translateY(-1px);
  1436. position: absolute;
  1437. z-index: -1;
  1438.  
  1439. }
  1440.  
  1441. @supports (color: var(--pre-rendering)) {
  1442.  
  1443. @keyframes dontRenderAnimation {
  1444. 0% {
  1445. background-position-x: 3px;
  1446. }
  1447. 100% {
  1448. background-position-x: 4px;
  1449. }
  1450. }
  1451.  
  1452. .dont-render[class] {
  1453. /* visibility: collapse !important; */
  1454. /* visibility: collapse will make innerText become "" which conflicts with BetterStreamChat; see https://gf.qytechs.cn/scripts/469878/discussions/197267 */
  1455.  
  1456. transform: scale(0.01) !important;
  1457. transform: scale(0.00001) !important;
  1458. transform: scale(0.0000001) !important;
  1459. transform-origin: 0 0 !important;
  1460. z-index: -1 !important;
  1461. contain: strict !important;
  1462. box-sizing: border-box !important;
  1463.  
  1464. height: 1px !important;
  1465. height: 0.1px !important;
  1466. height: 0.01px !important;
  1467. height: 0.0001px !important;
  1468. height: 0.000001px !important;
  1469.  
  1470. animation: dontRenderAnimation 1ms linear 80ms 1 normal forwards !important;
  1471.  
  1472. pointer-events: none !important;
  1473. user-select: none !important;
  1474.  
  1475. }
  1476.  
  1477. #sk35z {
  1478. display: block !important;
  1479.  
  1480. visibility: collapse !important;
  1481.  
  1482. transform: scale(0.01) !important;
  1483. transform: scale(0.00001) !important;
  1484. transform: scale(0.0000001) !important;
  1485. transform-origin: 0 0 !important;
  1486. z-index: -1 !important;
  1487. contain: strict !important;
  1488. box-sizing: border-box !important;
  1489.  
  1490. height: 1px !important;
  1491. height: 0.1px !important;
  1492. height: 0.01px !important;
  1493. height: 0.0001px !important;
  1494. height: 0.000001px !important;
  1495.  
  1496. position: absolute !important;
  1497. top: -1000px !important;
  1498. left: -1000px !important;
  1499.  
  1500. }
  1501.  
  1502. }
  1503.  
  1504. [rNgzQ] {
  1505. opacity: 0 !important;
  1506. pointer-events: none !important;
  1507. }
  1508.  
  1509.  
  1510. ${cssText10_show_more_blinker}
  1511.  
  1512. ${cssText11_entire_message_clickable}
  1513.  
  1514. ${cssText12_nowrap_tooltip}
  1515.  
  1516. ${cssText13_no_text_select_when_menu_visible}
  1517.  
  1518. ${cssText14_NO_FILTER_DROPDOWN_BORDER}
  1519.  
  1520. ${cssText15_FIX_ANIMATION_TICKER_TEXT_POSITION}
  1521.  
  1522. ${cssText16_FIX_AUTHOR_CHIP_BADGE_POSITION}
  1523.  
  1524. ${cssText17_FIX_overwidth_banner_message}
  1525.  
  1526. ${cssText18_REACTION_ANIMATION_PANEL_CSS_FIX}
  1527.  
  1528. ${cssText19_FOR_ADVANCED_TICKING}
  1529.  
  1530. ${cssText20_TICKER_SIZING}
  1531.  
  1532. `;
  1533.  
  1534. const win = typeof unsafeWindow !== 'undefined' ? unsafeWindow : (this instanceof Window ? this : window);
  1535.  
  1536. // Create a unique key for the script and check if it is already running
  1537. const hkey_script = 'mchbwnoasqph';
  1538. if (win[hkey_script]) throw new Error('Duplicated Userscript Calling'); // avoid duplicated scripting
  1539. win[hkey_script] = true;
  1540.  
  1541. const setTimeoutX0 = setTimeout;
  1542. const clearTimeoutX0 = clearTimeout;
  1543. const setIntervalX0 = setInterval;
  1544. const clearIntervalX0 = clearInterval;
  1545.  
  1546. const __shady_native_appendChild = HTMLElement_.prototype.__shady_native_appendChild || HTMLElement_.prototype.appendChild;
  1547. const __shady_native_removeChild = HTMLElement_.prototype.__shady_native_removeChild || HTMLElement_.prototype.removeChild;
  1548.  
  1549. const isEmptyObject = (obj) => {
  1550. for (const key in obj) {
  1551. if (obj.hasOwnProperty(key)) return false;
  1552. }
  1553. return true;
  1554. }
  1555.  
  1556. const firstObjectKey = (obj) => {
  1557. for (const key in obj) {
  1558. if (obj.hasOwnProperty(key) && typeof obj[key] === 'object') return key;
  1559. }
  1560. return null;
  1561. }
  1562.  
  1563.  
  1564. class LimitedSizeSet extends Set {
  1565. constructor(n) {
  1566. super();
  1567. this.limit = n;
  1568. }
  1569.  
  1570. add(key) {
  1571. if (!super.has(key)) {
  1572. super.add(key);
  1573. let n = super.size - this.limit;
  1574. if (n > 0) {
  1575. const iterator = super.values();
  1576. do {
  1577. const firstKey = iterator.next().value; // Get the first (oldest) key
  1578. super.delete(firstKey); // Delete the oldest key
  1579. } while (--n > 0)
  1580. }
  1581. }
  1582. }
  1583.  
  1584. removeAdd(key) {
  1585. super.delete(key);
  1586. this.add(key);
  1587. }
  1588.  
  1589. }
  1590.  
  1591.  
  1592. function deepCopy(obj, skipKeys) {
  1593. skipKeys = skipKeys || [];
  1594. if (!obj || typeof obj !== 'object') return obj;
  1595. if (Array.isArray(obj)) {
  1596. return obj.map(item => deepCopy(item, skipKeys));
  1597. }
  1598. const copy = {};
  1599. for (let key in obj) {
  1600. if (!skipKeys.includes(key)) {
  1601. copy[key] = deepCopy(obj[key], skipKeys);
  1602. }
  1603. }
  1604. return copy;
  1605. }
  1606.  
  1607. class Mutex {
  1608.  
  1609. constructor() {
  1610. this.p = Promise.resolve()
  1611. }
  1612.  
  1613. /**
  1614. * @param {(lockResolve: () => void)} f
  1615. */
  1616. lockWith(f) {
  1617. this.p = this.p.then(() => new Promise(f).catch(console.warn))
  1618. }
  1619.  
  1620. }
  1621.  
  1622. const PromiseExternal = ((resolve_, reject_) => {
  1623. const h = (resolve, reject) => { resolve_ = resolve; reject_ = reject };
  1624. return class PromiseExternal extends Promise {
  1625. constructor(cb = h) {
  1626. super(cb);
  1627. if (cb === h) {
  1628. /** @type {(value: any) => void} */
  1629. this.resolve = resolve_;
  1630. /** @type {(reason?: any) => void} */
  1631. this.reject = reject_;
  1632. }
  1633. }
  1634. };
  1635. })();
  1636.  
  1637. let ttpHTML = (s) => {
  1638. ttpHTML = s => s;
  1639. if (typeof trustedTypes !== 'undefined' && trustedTypes.defaultPolicy === null) {
  1640. let s = s => s;
  1641. trustedTypes.createPolicy('default', { createHTML: s, createScriptURL: s, createScript: s });
  1642. }
  1643. return s;
  1644. }
  1645.  
  1646. // const nextBrowserTick_ = nextBrowserTick;
  1647. // const nextBrowserTick_ = (f) => {
  1648. // typeof nextBrowserTick === 'function' ? nextBrowserTick(f) : setTimeout(f, Number.MIN_VALUE);
  1649. // };
  1650.  
  1651.  
  1652. // const { accurateTiming, isAccurateTimingUsable } = (() => {
  1653. // let audioCtx_ = null;
  1654. // let sampleRate = 0;
  1655. // const isAccurateTimingUsable = () => sampleRate > 0;
  1656. // const kill = () => {
  1657. // sampleRate = audioCtx_.currentTime;
  1658. // document.removeEventListener('pointerdown', listener, { capture: true, passive: true });
  1659. // document.removeEventListener('keydown', listener, { capture: true, passive: true });
  1660. // };
  1661. // const listener = (e) => {
  1662. // if (e.isTrusted === true) {
  1663. // if (!audioCtx_) {
  1664. // audioCtx_ = new (window.AudioContext || window.webkitAudioContext)();
  1665. // }
  1666. // if (audioCtx_.state === 'suspended') {
  1667. // const p = audioCtx_.resume();
  1668. // if (p && typeof p.then === 'function') p.then(kill);
  1669. // } else if (audioCtx_.state === 'running') {
  1670. // kill();
  1671. // }
  1672. // }
  1673. // };
  1674. // document.addEventListener('pointerdown', listener, { capture: true, passive: true });
  1675. // document.addEventListener('keydown', listener, { capture: true, passive: true });
  1676. // const fnSym = Symbol()
  1677. // const commonOscClean = (osc) => {
  1678. // osc[fnSym] = osc.onended = null;
  1679. // }
  1680. // const commonOscOnEnded = function () {
  1681. // this[fnSym]()
  1682. // Promise.resolve(this).then(commonOscClean)
  1683. // }
  1684. // let buffer_;
  1685. // const accurateTiming = (fn, delay) => {
  1686. // if (!sampleRate) return false;
  1687. // const audioCtx = audioCtx_;
  1688. // const ct = audioCtx.currentTime;
  1689.  
  1690. // if (!(delay >= 0)) delay = 0;
  1691. // const stopTime = ct + delay;
  1692. // let startTime = ct + delay - (1 / sampleRate);
  1693. // if (startTime === stopTime) startTime -= 1;
  1694. // if (startTime < 0) startTime = 0;
  1695.  
  1696. // if (!buffer_) {
  1697. // buffer_ = audioCtx.createBuffer(1, 1, sampleRate);
  1698. // // const data = buffer.getChannelData(0)
  1699. // // data[0] = 1e-20 // tiny pulse – not silent!
  1700. // }
  1701.  
  1702. // const buffer = buffer_;
  1703. // const source = audioCtx.createBufferSource()
  1704. // source.buffer = buffer
  1705. // source.connect(audioCtx.destination) // or silent gain node
  1706.  
  1707. // source[fnSym] = fn
  1708. // source.onended = commonOscOnEnded
  1709. // source.start(startTime) // schedule start
  1710.  
  1711. // return true;
  1712. // }
  1713. // return { accurateTiming, isAccurateTimingUsable }
  1714. // })();
  1715.  
  1716.  
  1717.  
  1718. let qWidthAdjustable = null;
  1719.  
  1720. /** @type {typeof PromiseExternal.prototype | null} */
  1721. let relayPromise = null;
  1722.  
  1723.  
  1724. /** @type {typeof PromiseExternal.prototype | null} */
  1725. let onPlayStateChangePromise = null;
  1726.  
  1727.  
  1728. const reuseId = `${Math.floor(Math.random() * 314159265359 + 314159265359).toString(36)}`;
  1729.  
  1730. const reuseStore = new Map();
  1731.  
  1732. let onPageContainer = null;
  1733.  
  1734. const customCreateComponent = (component, data, bool)=>{
  1735.  
  1736. const componentTag = typeof component === 'string' ? component : typeof (component||0).component === 'string' ? (component||0).component : '';
  1737. if(componentTag){
  1738.  
  1739. if(REUSE_TICKER && data.id && data.fullDurationSec){
  1740. // bool (param c) is true by default; just force it to reuse no matter true or false
  1741.  
  1742. if (!bool) {
  1743. // show a warning if it is false.
  1744. console.warn('[yt-chat] REUSE_TICKER: reuse bool is false');
  1745. }
  1746.  
  1747. const record = reuseStore.get(`<${componentTag}>${data.id}:${data.fullDurationSec}`);
  1748.  
  1749. const cnt = kRef(record);
  1750.  
  1751.  
  1752. if(cnt && cnt.isAttached === false){
  1753.  
  1754. const hostElement = cnt.hostElement;
  1755.  
  1756. if(hostElement instanceof HTMLElement_ && hostElement.isConnected === false && hostElement.parentNode === null && hostElement.getAttribute('__reuseid__')===reuseId ){
  1757.  
  1758. // console.log(952, cnt.hostElement.parentNode)
  1759. // debugger;
  1760. if (hostElement.hasAttribute('__nogc__')) {
  1761.  
  1762. Promise.resolve(hostElement).then((hostElement) => {
  1763. // microtask to provide some time for DOM attachment.
  1764. hostElement.isConnected && hostElement.removeAttribute('__nogc__');
  1765. });
  1766.  
  1767. }
  1768.  
  1769. // ------- follow rm3 -------
  1770.  
  1771. // a.prototype._initializeProtoProperties = function(c) {
  1772. // this.__data = Object.create(c);
  1773. // this.__dataPending = Object.create(c);
  1774. // this.__dataOld = {}
  1775. // }
  1776. // a.prototype._initializeProperties = function() {
  1777. // this.__dataProto && (this._initializeProtoProperties(this.__dataProto),
  1778. // this.__dataProto = null);
  1779. // b.prototype._initializeProperties.call(this)
  1780. // }
  1781. // ;
  1782.  
  1783. if(!cnt.__dataInvalid && cnt.__dataEnabled && cnt.__dataReady ){
  1784.  
  1785. // console.log(12883);
  1786.  
  1787.  
  1788. if (!onPageContainer) {
  1789. let p = document.createElement('noscript');
  1790. p.style.all = 'unset';
  1791. document.body.prepend(p);
  1792. onPageContainer = p;
  1793. }
  1794.  
  1795. onPageContainer.appendChild(hostElement); // to fix some issues for the rendered elements
  1796.  
  1797. cnt.__dataInvalid = false;
  1798. cnt.__dataEnabled = true;
  1799. cnt.__dataReady = true;
  1800. // cnt._initializeProtoProperties(cnt.data)
  1801.  
  1802. // window.meaa = cnt.$.container;
  1803. if (cnt.__data) cnt.__data = Object.assign({}, cnt.__data);
  1804. cnt.__dataPending = {};
  1805. cnt.__dataOld = {}
  1806.  
  1807. try{
  1808. cnt.markDirty();
  1809. }catch(e){}
  1810. try{
  1811. cnt.markDirtyVisibilityObserver();
  1812. }catch(e){}
  1813. try{
  1814. cnt.wasPrescan = cnt.wasVisible = !1
  1815. }catch(e){}
  1816. // try{
  1817. // cnt._setPendingProperty('data', Object.assign({}, cntData), !0);
  1818. // }catch(e){}
  1819. // // cnt.__dataInvalid = false;
  1820. // // cnt._enableProperties();
  1821.  
  1822. // try {
  1823. // cnt._flushProperties();
  1824. // } catch (e) { }
  1825. // cnt.ready();
  1826.  
  1827. return hostElement;
  1828.  
  1829. }
  1830.  
  1831.  
  1832. // console.log(12323)
  1833.  
  1834. // setTimeoutX0(()=>{
  1835. // console.log(window.meaa.parentNode)
  1836. // }, 1000)
  1837.  
  1838.  
  1839. // ------------ commented ------------
  1840. // cnt.__dataInvalid = false;
  1841. // cnt.__dataEnabled = false;
  1842. // if (cnt.__dataPending && typeof cnt.__dataPending === 'object') cnt.__dataPending = null;
  1843. // if (cnt.__dataOld && typeof cnt.__dataOld === 'object') cnt.__dataOld = null;
  1844. // if (cnt.__dataCounter && typeof cnt.__dataCounter === 'number') cnt.__dataCounter = 0;
  1845. // if ('__dataClientsInitialized' in cnt || '__dataClientsReady' in cnt) {
  1846. // cnt.__dataClientsReady = !1;
  1847. // cnt.__dataLinkedPaths = cnt.__dataToNotify = cnt.__dataPendingClients = null;
  1848. // cnt.__dataHasPaths = !1;
  1849. // cnt.__dataCompoundStorage = null; // cnt.__dataCompoundStorage = cnt.__dataCompoundStorage || null;
  1850. // cnt.__dataHost = null; // cnt.__dataHost = cnt.__dataHost || null;
  1851. // if (!cnt.__dataTemp) cnt.__dataTemp = {}; // cnt.__dataTemp = {};
  1852. // cnt.__dataClientsInitialized = !1;
  1853. // }
  1854. // try{
  1855. // cnt._flushProperties();
  1856. // }catch(e){
  1857. // console.warn(e)
  1858. // }
  1859. // for (const elm of cnt.hostElement.getElementsByTagName('*')) {
  1860. // if (elm.is) {
  1861. // const cnt = insp(elm);
  1862. // cnt.__dataInvalid = false;
  1863. // cnt.__dataEnabled = false;
  1864. // if (cnt.__dataPending && typeof cnt.__dataPending === 'object') cnt.__dataPending = null;
  1865. // if (cnt.__dataOld && typeof cnt.__dataOld === 'object') cnt.__dataOld = null;
  1866. // if (cnt.__dataCounter && typeof cnt.__dataCounter === 'number') cnt.__dataCounter = 0;
  1867. // if ('__dataClientsInitialized' in cnt || '__dataClientsReady' in cnt) {
  1868. // cnt.__dataClientsReady = !1;
  1869. // cnt.__dataLinkedPaths = cnt.__dataToNotify = cnt.__dataPendingClients = null;
  1870. // cnt.__dataHasPaths = !1;
  1871. // cnt.__dataCompoundStorage = null; // cnt.__dataCompoundStorage = cnt.__dataCompoundStorage || null;
  1872. // cnt.__dataHost = null; // cnt.__dataHost = cnt.__dataHost || null;
  1873. // if (!cnt.__dataTemp) cnt.__dataTemp = {}; // cnt.__dataTemp = {};
  1874. // cnt.__dataClientsInitialized = !1;
  1875. // }
  1876. // try {
  1877. // cnt._flushProperties();
  1878. // } catch (e) {
  1879. // console.warn(e)
  1880. // }
  1881. // if (elm.nodeName === 'YT-ICON') {
  1882. // // console.log(2133, JSON.stringify( cnt.__data))
  1883. // const qq = Object.assign({}, cnt.__data)
  1884. // console.log(1232466)
  1885. // const _qww = cnt;
  1886. // cnt.__data = new Proxy(Object.assign({}, qq), {
  1887. // get(target, p) {
  1888. // console.log(12838, p)
  1889. // if (p === 'icon') {
  1890. // window.wmk = _qww.hostElement;
  1891. // // debugger;
  1892. // }
  1893. // return target[p]
  1894. // },
  1895. // set(target, p, v) {
  1896. // console.log(12839, p)
  1897. // target[p] = v;
  1898. // if (p === 'icon') debugger;
  1899. // return true;
  1900. // }
  1901. // });
  1902. // Promise.resolve(cnt).then((cnt) => {
  1903. // cnt.__data = Object.assign({}, qq);
  1904. // });
  1905. // }
  1906. // // let q = elm.nextSibling;
  1907. // // let h = elm.parentNode;
  1908. // // elm.remove();
  1909. // // h.insertBefore(elm, q);
  1910. // // console.log(2233, elm)
  1911. // }
  1912. // }
  1913. // ------------ commented ------------
  1914.  
  1915. // ------- follow rm3 -------
  1916.  
  1917. // console.log('[yt-chat] reuse')
  1918.  
  1919.  
  1920.  
  1921. }
  1922.  
  1923. }
  1924.  
  1925. }
  1926.  
  1927. }
  1928. DEBUG_customCreateComponent && console.log(component, data, bool);
  1929. /*
  1930.  
  1931. const cntData = this.data;
  1932. reuseStore.set(`${cntData.id}:${cntData.fullDurationSec}`, mWeakRef(this));
  1933. */
  1934.  
  1935. }
  1936.  
  1937. const valAssign = (elm, attr, val) => {
  1938. if (typeof val === 'number') val = val.toFixed(3);
  1939. if (!(Math.abs(elm.style.getPropertyValue(attr) - val) < 1e-5)) {
  1940. elm.style.setProperty(attr, val);
  1941. return true;
  1942. }
  1943. return false;
  1944. };
  1945.  
  1946. const insp = o => o ? (o.polymerController || o.inst || o || 0) : (o || 0);
  1947. const indr = o => insp(o).$ || o.$ || 0;
  1948.  
  1949.  
  1950. const getAttributes = (node) => {
  1951. const attrs = node.attributes;
  1952. const res = {};
  1953. for (const { name, value } of attrs) {
  1954. res[name] = value;
  1955. }
  1956. res['"'] = attrs.length;
  1957. // const res = new Array(attrs.length);
  1958. // for (let i = 0; i < res.length; i++) {
  1959. // const { name, value } = attrs[i];
  1960. // res[i] = { name, value };
  1961. // }
  1962. return res;
  1963. };
  1964.  
  1965. const __refreshData938o__ = {};
  1966. const __refreshData938__ = function (prop, opt) {
  1967. const d = this[prop];
  1968. if (d) {
  1969. this._setPendingProperty(prop, __refreshData938o__, opt);
  1970. this._setPendingProperty(prop, d, opt);
  1971. this._invalidateProperties();
  1972. }
  1973. };
  1974.  
  1975. const __refreshData933__ = function (prop, opt) {
  1976. const d = this[prop];
  1977. if (d) {
  1978. this.signalProxy.setWithPath([prop], d);
  1979. }
  1980. }
  1981.  
  1982. const setupRefreshData930 = (cnt) => {
  1983. if (cnt.__refreshData930__ !== undefined) return;
  1984. const cProto = Reflect.getPrototypeOf(cnt);
  1985. let r = null;
  1986. let flag = 0;
  1987. if (typeof cnt._setPendingProperty === 'function' && typeof cnt._invalidateProperties === 'function' && cnt._setPendingProperty.length === 3 && cnt._invalidateProperties.length === 0) {
  1988. flag |= 1;
  1989. }
  1990. if (typeof cnt.signalProxy !== "undefined") {
  1991. flag |= 2;
  1992. }
  1993. if (typeof (cnt.signalProxy || 0).setWithPath === 'function' && cnt.signalProxy.setWithPath.length === 2) {
  1994. flag |= 4;
  1995. }
  1996. if (r === 1) r = __refreshData938__;
  1997. // else if (r === 6) r = __refreshData933__;
  1998. cProto.__refreshData930__ = r;
  1999. // ytd-comments-header-renderer : no _invalidateProperties (cnt.signalProxy.setWithPath)
  2000. }
  2001.  
  2002. const __refreshProps938__ = function () {
  2003. const __data = this.__data;
  2004. if (__data) {
  2005. for (const key in __data) {
  2006. const v = __data[key];
  2007. if (typeof v === 'boolean') {
  2008. this._setPendingProperty(key, !v) && this._setPendingProperty(key, v);
  2009. } else if (typeof v === 'string') {
  2010. this._setPendingProperty(key, `!${v}`) && this._setPendingProperty(key, `${v}`);
  2011. } else if (typeof v === 'number') {
  2012. this._setPendingProperty(key, v + 1) && this._setPendingProperty(key, v);
  2013. }
  2014. }
  2015. }
  2016. }
  2017.  
  2018. const setupRefreshProps930 = (cnt) => {
  2019. if (cnt.__refreshProps930__ !== undefined) return;
  2020. const cProto = Reflect.getPrototypeOf(cnt);
  2021. let r = null;
  2022. let flag = 0;
  2023. if (typeof cnt._setPendingProperty === 'function' && typeof cnt._invalidateProperties === 'function' && cnt._setPendingProperty.length === 3 && cnt._invalidateProperties.length === 0) {
  2024. flag |= 1;
  2025. }
  2026. if (typeof cnt.signalProxy !== "undefined") {
  2027. flag |= 2;
  2028. }
  2029. if (typeof (cnt.signalProxy || 0).setWithPath === 'function' && cnt.signalProxy.setWithPath.length === 2) {
  2030. flag |= 4;
  2031. }
  2032. if (r === 1) r = __refreshProps938__;
  2033. cProto.__refreshProps930__ = r;
  2034. // ytd-comments-header-renderer : no _invalidateProperties (cnt.signalProxy.setWithPath)
  2035. }
  2036.  
  2037. const refreshChildrenYtIcons = (node) => {
  2038. let goNext = false;
  2039. for (const iconElm of node.getElementsByTagName('yt-icon')) {
  2040. try {
  2041. const cnt = insp(iconElm);
  2042. setupRefreshProps930(cnt);
  2043. if (cnt.__refreshProps930__) {
  2044. cnt.__refreshProps930__();
  2045. goNext = true;
  2046. }
  2047. // cnt.removeIconShape(); // detach iconShapeDataSignal?
  2048. // cnt._setPendingProperty('isAttached', false);
  2049. } catch (e) { }
  2050. if (!goNext) break;
  2051. }
  2052. }
  2053.  
  2054.  
  2055. const imageFetchCache = new Set();
  2056. const imageFetch = function (imageLink) {
  2057. return new Promise(resolve => {
  2058. let img = null;
  2059. for (const cacheWR of imageFetchCache) {
  2060. let p = kRef(cacheWR);
  2061. if (!p) {
  2062. imageFetchCache.delete(cacheWR);
  2063. } else if (img.busy588 === false) {
  2064. img = p;
  2065. break;
  2066. }
  2067. }
  2068. if (!img) {
  2069. img = new Image_();
  2070. imageFetchCache.add(mWeakRef(img));
  2071. }
  2072. img.busy588 = true;
  2073.  
  2074. window.mkek = imageFetchCache.size;
  2075. let f = () => {
  2076. resolve && resolve();
  2077. resolve = null;
  2078. img.onload = null;
  2079. img.onerror = null;
  2080. img.busy588 = false;
  2081. img = null;
  2082. }
  2083. img.onload = f;
  2084. img.onerror = f;
  2085. img.src = imageLink;
  2086. f = null;
  2087. imageLink = null;
  2088. });
  2089. };
  2090.  
  2091.  
  2092. const autoTimerFn = (() => {
  2093.  
  2094. let p1 = null;
  2095. let p2 = null;
  2096. let p3 = null;
  2097. setInterval(() => {
  2098. if (p1) p1.resolve();
  2099. p1 = p2;
  2100. p2 = p3;
  2101. p3 = null;
  2102. }, 345.00123);
  2103.  
  2104. return () => {
  2105. const p = (p3 || (p3 = new PromiseExternal()));
  2106. return p;
  2107. };
  2108.  
  2109. })();
  2110.  
  2111. const __mockChildren__ = { get length() { return 0 } };
  2112. const mockCommentElement = (x) => {
  2113. // for flow chat
  2114. if (x instanceof Node && x.nodeType !== 1 && !x.children) {
  2115. x.children = __mockChildren__;
  2116. }
  2117. return x;
  2118. }
  2119.  
  2120. const wme = mockCommentElement(document.createComment('1'));
  2121. let wmp = new PromiseExternal();
  2122. const wmo = new MutationObserver(() => {
  2123. wmp.resolve();
  2124. wmp = new PromiseExternal();
  2125. });
  2126. wmo.observe(wme, { characterData: true });
  2127.  
  2128.  
  2129. let playEventsStack = Promise.resolve();
  2130.  
  2131.  
  2132. let playerProgressChangedArg1 = null;
  2133. let playerProgressChangedArg2 = null;
  2134. let playerProgressChangedArg3 = null;
  2135.  
  2136. let dntElementWeak = null;
  2137.  
  2138.  
  2139. let timestampUnderLiveMode = false;
  2140.  
  2141. const updateTickerCurrentTime = () => {
  2142.  
  2143. if (resistanceUpdateDebugMode) {
  2144. console.log('updateTickerCurrentTime')
  2145.  
  2146. if (!dntElementWeak || !kRef(dntElementWeak)) dntElementWeak = mWeakRef(document.querySelector('yt-live-chat-ticker-renderer'));
  2147. timestampUnderLiveMode = true;
  2148. }
  2149.  
  2150. const dntElement = kRef(dntElementWeak);
  2151. const v = timestampUnderLiveMode ? (Date.now() / 1000 - timeOriginDT / 1000) : playerProgressChangedArg1;
  2152. if (dntElement instanceof HTMLElement_ && v >= 0) {
  2153. valAssign(dntElement, '--ticker-current-time', v);
  2154. }
  2155. }
  2156.  
  2157. // ================== FOR USE_ADVANCED_TICKING ================
  2158.  
  2159. const timeOriginDT = +new Date(performance.timeOrigin);
  2160. let startResistanceUpdaterStarted = false;
  2161.  
  2162. const RESISTANCE_UPDATE_OPT = 3;
  2163. let resistanceUpdateLast = 0;
  2164. let resistanceUpdateBusy = false;
  2165. const resistanceUpdateDebugMode = false;
  2166. const allBackgroundOverLays = document.getElementsByTagName('ticker-bg-overlay');
  2167. // const rgFlag = {};
  2168. const resistanceUpdateFn = (b) => {
  2169. if (!resistanceUpdateDebugMode && allBackgroundOverLays.length === 0) return;
  2170. resistanceUpdateBusy = false;
  2171. const t = Date.now();
  2172. const d = t - resistanceUpdateLast;
  2173. if (d > 375) {
  2174. resistanceUpdateLast = t;
  2175. updateTickerCurrentTime();
  2176. }
  2177. }
  2178. const resistanceUpdateFn_ = (forced = false) => {
  2179. if (forced === true || timestampUnderLiveMode) {
  2180. if (!resistanceUpdateBusy) {
  2181. resistanceUpdateBusy = true;
  2182. Promise.resolve().then(resistanceUpdateFn);
  2183. }
  2184. }
  2185. }
  2186. const startResistanceUpdater = () => {
  2187.  
  2188. if (startResistanceUpdaterStarted) return;
  2189. startResistanceUpdaterStarted = true;
  2190.  
  2191. if (RESISTANCE_UPDATE_OPT & 1)
  2192. document.addEventListener('yt-action', () => {
  2193. resistanceUpdateFn_(true);
  2194. }, true)
  2195.  
  2196. resistanceUpdateFn_(true);
  2197. setIntervalX0(resistanceUpdateFn_, 400);
  2198. }
  2199.  
  2200. if(resistanceUpdateDebugMode) startResistanceUpdater();
  2201.  
  2202.  
  2203. function dr(s) {
  2204. // reserved for future use
  2205. return s;
  2206. // return window.deWeakJS ? window.deWeakJS(s) : s;
  2207. }
  2208.  
  2209.  
  2210. const getProto = (element) => {
  2211. if (element) {
  2212. const cnt = insp(element);
  2213. return cnt.constructor.prototype || null;
  2214. }
  2215. return null;
  2216. }
  2217.  
  2218.  
  2219.  
  2220. const logFn = (key, f) => {
  2221. return Function.prototype.bind.call(console.log, console, `%c ${key}`, 'background: #222; color: #bada55', f);
  2222. }
  2223.  
  2224.  
  2225.  
  2226. const assertor = (f) => f() || (console.assert(false, `${f}`), false);
  2227.  
  2228. const fnIntegrity = (f, d) => {
  2229.  
  2230.  
  2231. if (!f || typeof f !== 'function') {
  2232. console.warn('f is not a function', f);
  2233. return;
  2234. }
  2235. // return; // M44
  2236. let p = `${f}`, s = 0, j = -1, w = 0;
  2237. // return; // M44
  2238. for (let i = 0, l = p.length; i < l; i++) {
  2239. const t = p[i];
  2240. if (((t >= 'a' && t <= 'z') || (t >= 'A' && t <= 'Z'))) {
  2241. if (j < i - 1) w++;
  2242. j = i;
  2243. } else {
  2244. s++;
  2245. }
  2246. }
  2247. // if(p.length > 44 && p.length < 50){
  2248.  
  2249. // (window.skam|| (window.skam=[])).push(p);
  2250. // return false;
  2251. // }
  2252.  
  2253. // if(p.length > 405 && p.length < 415 ){ //350 450
  2254.  
  2255.  
  2256. // //  [353, 411, 411, 411]
  2257.  
  2258. // // if(p.length >= 350 && p.length<=450){
  2259.  
  2260. // // (window.skam|| (window.skam=[])).push(p.length);
  2261. // // }
  2262. // (window.skam|| (window.skam=[])).push(p);
  2263. // return false;
  2264. // }
  2265.  
  2266. // if(p.length < 50) return true; else return false;
  2267. // return; // M44
  2268. let itz = `${f.length}.${s}.${w}`;
  2269. if (!d) {
  2270. return itz;
  2271. } else if (itz !== d) {
  2272. console.warn('fnIntegrity=false', itz);
  2273. return false;
  2274. } else {
  2275. return true;
  2276. }
  2277. }
  2278.  
  2279. const px2cm = (px) => px * window.devicePixelRatio * 0.026458333;
  2280. const px2mm = (px) => px * window.devicePixelRatio * 0.26458333;
  2281.  
  2282. // let createElement_fountain_model_fn = null;
  2283. // let createElement_fountain_model_enabled = null;
  2284.  
  2285. // ; (USE_RM_ON_FOUNTAIN_MODEL) && (()=>{
  2286. // document.createElement4719 = document.createElement;
  2287. // document.createElement = function (a) {
  2288. // if (createElement_fountain_model_enabled) {
  2289. // const r = createElement_fountain_model_fn(a);
  2290. // if (r) return r;
  2291. // }
  2292. // return document.createElement4719(a);
  2293. // }
  2294. // })();
  2295.  
  2296. ; (ENABLE_FLAGS_MAINTAIN_STABLE_LIST || ENABLE_FLAGS_REUSE_COMPONENTS || DISABLE_FLAGS_SHADYDOM_FREE) && (() => {
  2297.  
  2298. const _config_ = () => {
  2299. try {
  2300. return ytcfg.data_;
  2301. } catch (e) { }
  2302. return null;
  2303. };
  2304.  
  2305. const flagsFn = (EXPERIMENT_FLAGS) => {
  2306.  
  2307. // console.log(700)
  2308.  
  2309. if (!EXPERIMENT_FLAGS) return;
  2310.  
  2311. if (ENABLE_FLAGS_MAINTAIN_STABLE_LIST) {
  2312. if (USE_MAINTAIN_STABLE_LIST_ONLY_WHEN_KS_FLAG_IS_SET ? EXPERIMENT_FLAGS.kevlar_should_maintain_stable_list === true : true) {
  2313. // EXPERIMENT_FLAGS.kevlar_tuner_should_test_maintain_stable_list = true; // timestamp toggle issue
  2314. EXPERIMENT_FLAGS.kevlar_should_maintain_stable_list = true;
  2315. // console.log(701)
  2316. }
  2317. }
  2318.  
  2319. if (ENABLE_FLAGS_REUSE_COMPONENTS) {
  2320. EXPERIMENT_FLAGS.kevlar_tuner_should_test_reuse_components = true;
  2321. EXPERIMENT_FLAGS.kevlar_tuner_should_reuse_components = true;
  2322. // console.log(702);
  2323. }
  2324.  
  2325. if (DISABLE_FLAGS_SHADYDOM_FREE) {
  2326. EXPERIMENT_FLAGS.enable_shadydom_free_scoped_node_methods = false;
  2327. EXPERIMENT_FLAGS.enable_shadydom_free_scoped_query_methods = false;
  2328. EXPERIMENT_FLAGS.enable_shadydom_free_scoped_readonly_properties_batch_one = false;
  2329. EXPERIMENT_FLAGS.enable_shadydom_free_parent_node = false;
  2330. EXPERIMENT_FLAGS.enable_shadydom_free_children = false;
  2331. EXPERIMENT_FLAGS.enable_shadydom_free_last_child = false;
  2332. }
  2333.  
  2334. // EXPERIMENT_FLAGS.enable_button_behavior_reuse = false;
  2335.  
  2336. };
  2337.  
  2338. const uf = (config_) => {
  2339. config_ = config_ || _config_();
  2340. if (config_) {
  2341. const { EXPERIMENT_FLAGS, EXPERIMENTS_FORCED_FLAGS } = config_;
  2342. if (EXPERIMENT_FLAGS) {
  2343. flagsFn(EXPERIMENT_FLAGS);
  2344. if (EXPERIMENTS_FORCED_FLAGS) flagsFn(EXPERIMENTS_FORCED_FLAGS);
  2345. }
  2346. }
  2347. }
  2348.  
  2349. window._ytConfigHacks.add((config_) => {
  2350. uf(config_);
  2351. });
  2352.  
  2353. uf();
  2354.  
  2355. })();
  2356.  
  2357. if (DISABLE_Translation_By_Google) {
  2358.  
  2359. let mo = new MutationObserver(() => {
  2360.  
  2361. if (!mo) return;
  2362. let h = document.head;
  2363. if (!h) return;
  2364. mo.disconnect();
  2365. mo.takeRecords();
  2366. mo = null;
  2367.  
  2368. let meta = document.createElement('meta');
  2369. meta.setAttribute('name', 'google');
  2370. meta.setAttribute('content', 'notranslate');
  2371. h.appendChild(meta);
  2372.  
  2373.  
  2374. });
  2375. mo.observe(document, { subtree: true, childList: true });
  2376. }
  2377.  
  2378. console.assert(MAX_ITEMS_FOR_TOTAL_DISPLAY > 0)
  2379. // console.assert(MAX_ITEMS_FOR_TOTAL_DISPLAY > 0 && MAX_ITEMS_FOR_FULL_FLUSH > 0 && MAX_ITEMS_FOR_TOTAL_DISPLAY > MAX_ITEMS_FOR_FULL_FLUSH)
  2380.  
  2381. const isContainSupport = CSS.supports('contain', 'layout paint style');
  2382. if (!isContainSupport) {
  2383. console.warn("Your browser does not support css property 'contain'.\nPlease upgrade to the latest version.".trim());
  2384. }
  2385.  
  2386. const isOverflowAnchorSupport = CSS.supports('overflow-anchor', 'auto');
  2387. if (!isOverflowAnchorSupport) {
  2388. console.warn("Your browser does not support css property 'overflow-anchor'.\nPlease upgrade to the latest version.".trim());
  2389. }
  2390.  
  2391. const ENABLE_OVERFLOW_ANCHOR = ENABLE_OVERFLOW_ANCHOR_PREFERRED && isOverflowAnchorSupport && ENABLE_NO_SMOOTH_TRANSFORM && typeof ResizeObserver === 'function';
  2392. let WITH_SCROLL_ANCHOR = false;
  2393.  
  2394. const fxOperator = (proto, propertyName) => {
  2395. let propertyDescriptorGetter = null;
  2396. try {
  2397. propertyDescriptorGetter = Object.getOwnPropertyDescriptor(proto, propertyName).get;
  2398. } catch (e) { }
  2399. return typeof propertyDescriptorGetter === 'function' ? (e) => {
  2400. try {
  2401.  
  2402. return propertyDescriptorGetter.call(dr(e));
  2403. } catch (e) { }
  2404. return e[propertyName];
  2405. } : (e) => e[propertyName];
  2406. };
  2407.  
  2408. const nodeParent = fxOperator(Node.prototype, 'parentNode');
  2409. const nPrevElem = fxOperator(HTMLElement_.prototype, 'previousElementSibling');
  2410. const nNextElem = fxOperator(HTMLElement_.prototype, 'nextElementSibling');
  2411. const nLastElem = fxOperator(HTMLElement_.prototype, 'lastElementChild');
  2412.  
  2413. let groupCI = [];
  2414. let groupDI = 0;
  2415.  
  2416. const [console_] = [console];
  2417. const console1 = {
  2418. log(...args) {
  2419. if (!SHOW_DEVTOOL_DEBUG) return;
  2420. if (groupDI === 1) return grouppedConsoleLog(...args);
  2421. return console_.log(...args);
  2422. },
  2423. warn(...args) {
  2424. if (!SHOW_DEVTOOL_DEBUG) return;
  2425. if (groupDI === 1) return grouppedConsoleWarn(...args);
  2426. return console_.warn(...args);
  2427. },
  2428. debug(...args) {
  2429. if (!SHOW_DEVTOOL_DEBUG) return;
  2430. if (groupDI === 1) return grouppedConsoleDebug(...args);
  2431. return console_.debug(...args);
  2432. }
  2433. }
  2434. const grouppedConsoleLog = (...args) => {
  2435. if (DEBUG_LOG_HIDE_OK) {
  2436. for (const arg of args) {
  2437. if (typeof arg !== 'string') break;
  2438. if (arg.endsWith('OK')) return;
  2439. }
  2440. }
  2441. groupCI.push(['log', ...args]);
  2442. }
  2443. const grouppedConsoleWarn = (...args) => {
  2444. groupCI.push(['warn', ...args]);
  2445. }
  2446. const grouppedConsoleDebug = (...args) => {
  2447. groupCI.push(['debug', ...args]);
  2448. }
  2449. const groupCollapsed = (text1, text2) => {
  2450. if (!SHOW_DEVTOOL_DEBUG) return;
  2451. if (groupDI !== 0) console_.warn('groupDI in groupCollapsed fails', groupDI);
  2452. groupDI++;
  2453. groupCI.length = 0;
  2454.  
  2455. let w = 'groupCollapsed';
  2456. if (DEBUG_LOG_GROUP_EXPAND) w = 'group';
  2457. groupCI.push([w, `%c${text1}%c${text2}`,
  2458. "background-color: #010502; color: #6acafe; font-weight: 700; padding: 2px;",
  2459. "background-color: #010502; color: #6ad9fe; font-weight: 300; padding: 2px;"
  2460. ]);
  2461. }
  2462. const groupEnd = () => {
  2463. if (!SHOW_DEVTOOL_DEBUG) return;
  2464. groupDI--;
  2465. if (groupDI !== 0) console_.warn('groupDI in groupEnd fails', groupDI);
  2466. if (groupCI.length >= 0) {
  2467. let withContent = false;
  2468. for (const entry of groupCI) {
  2469. if (entry[0] === 'group' || entry[0] === 'groupCollapsed') continue;
  2470. if (entry[1] === '[Begin]' || entry[1] === '[End]') continue;
  2471. withContent = true;
  2472. break;
  2473. }
  2474. if (withContent) {
  2475. for (const entry of groupCI) {
  2476. const args = entry.slice(1);
  2477. let colorHighLight = '';
  2478. for (const arg of args) {
  2479. if (typeof arg !== 'string') {
  2480. colorHighLight = '';
  2481. break;
  2482. }
  2483. if (arg === 'OK' || arg === 'NG') {
  2484. colorHighLight = arg;
  2485. } else {
  2486. if (arg.endsWith(' OK')) colorHighLight = 'OK';
  2487. else if (arg.endsWith(' NG')) colorHighLight = 'NG';
  2488. }
  2489. }
  2490. let print = args;
  2491. if (colorHighLight) {
  2492. print = [args.map(e => `%c${e}`).join(' '), ...args.map(e => {
  2493. if (colorHighLight === 'OK' && e.includes(colorHighLight)) return "background-color:rgb(29, 29, 29); color:rgb(57, 215, 83); font-weight: 600;";
  2494. if (colorHighLight === 'NG' && e.includes(colorHighLight)) return "background-color:rgb(29, 29, 29); color:rgb(215, 133, 57); font-weight: 600;";
  2495. return "background-color:rgb(29, 29, 29); color:rgb(231, 231, 231); font-weight: 400;";
  2496. })];
  2497. }
  2498. console[entry[0]](...print);
  2499. }
  2500. console.groupEnd();
  2501. groupCI.length = 0;
  2502. }
  2503. }
  2504. }
  2505.  
  2506. // const microNow = () => performance.now() + (performance.timeOrigin || performance.timing.navigationStart);
  2507.  
  2508.  
  2509. const EVENT_KEY_ON_REGISTRY_READY = "ytI-ce-registry-created";
  2510. const onRegistryReady = (callback) => {
  2511. if (typeof customElements === 'undefined') {
  2512. if (!('__CE_registry' in document)) {
  2513. // https://github.com/webcomponents/polyfills/
  2514. Object.defineProperty(document, '__CE_registry', {
  2515. get() {
  2516. // return undefined
  2517. },
  2518. set(nv) {
  2519. if (typeof nv == 'object') {
  2520. delete this.__CE_registry;
  2521. this.__CE_registry = nv;
  2522. this.dispatchEvent(new CustomEvent(EVENT_KEY_ON_REGISTRY_READY));
  2523. }
  2524. return true;
  2525. },
  2526. enumerable: false,
  2527. configurable: true
  2528. })
  2529. }
  2530. let eventHandler = (evt) => {
  2531. document.removeEventListener(EVENT_KEY_ON_REGISTRY_READY, eventHandler, false);
  2532. const f = callback;
  2533. callback = null;
  2534. eventHandler = null;
  2535. f();
  2536. };
  2537. document.addEventListener(EVENT_KEY_ON_REGISTRY_READY, eventHandler, false);
  2538. } else {
  2539. callback();
  2540. }
  2541. };
  2542.  
  2543. const promiseForCustomYtElementsReady = new Promise(onRegistryReady);
  2544.  
  2545. const renderReadyPn = typeof ResizeObserver !== 'undefined' ? (sizingTarget) => {
  2546.  
  2547. return new Promise(resolve => {
  2548.  
  2549. let ro = new ResizeObserver(entries => {
  2550. if (entries && entries.length >= 1) {
  2551. resolve();
  2552. ro.disconnect();
  2553. ro = null;
  2554. }
  2555. });
  2556. ro.observe(sizingTarget);
  2557.  
  2558.  
  2559.  
  2560. });
  2561.  
  2562. } : (sizingTarget) => {
  2563.  
  2564.  
  2565. return new Promise(resolve => {
  2566.  
  2567. let io = new IntersectionObserver(entries => {
  2568. if (entries && entries.length >= 1) {
  2569. resolve();
  2570. io.disconnect();
  2571. io = null;
  2572. }
  2573. });
  2574. io.observe(sizingTarget);
  2575.  
  2576.  
  2577.  
  2578. });
  2579.  
  2580. };
  2581.  
  2582. /* globals WeakRef:false */
  2583.  
  2584. /** @type {(o: Object | null) => WeakRef | null} */
  2585. const mWeakRef = typeof WeakRef === 'function' ? (o => o ? new WeakRef(o) : null) : (o => o || null);
  2586.  
  2587. /** @type {(wr: Object | null) => Object | null} */
  2588. const kRef = (wr => (wr && wr.deref) ? wr.deref() : wr);
  2589.  
  2590. const { insertBeforeNaFn, appendChildNaFn } = (() => {
  2591. // native methods
  2592.  
  2593. const insertBefore = HTMLElement_.prototype.insertBefore;
  2594. const appendChild = HTMLElement_.prototype.appendChild;
  2595.  
  2596. return {
  2597. insertBeforeNaFn: (parent, node, child) => {
  2598. insertBefore.call(parent, node, child);
  2599. },
  2600. appendChildNaFn: (parent, node) => {
  2601. appendChild.call(parent, node);
  2602. }
  2603. };
  2604.  
  2605. /*
  2606. const insertBeforeFn = (parent, node, child) => {
  2607. if ('__shady_native_insertBefore' in parent) parent.__shady_native_insertBefore(node, child);
  2608. else parent.insertBefore(node, child);
  2609. }
  2610.  
  2611. const appendChildFn = (parent, node) =>{
  2612. if('__shady_native_appendChild' in parent) parent.__shady_native_appendChild(node);
  2613. else parent.appendChild(node);
  2614. }
  2615. */
  2616.  
  2617. })();
  2618.  
  2619.  
  2620.  
  2621. let __LCRInjection__ = 0; // 0 for no injection
  2622. const LCRImmedidates = []; // array of sync. func
  2623.  
  2624. let getLCRDummyP_ = null;
  2625. // lcrPromiseFn
  2626. const getLCRDummy = () => {
  2627.  
  2628. /* remarks */
  2629.  
  2630. /*
  2631.  
  2632. // YouTube uses `<ps-dom-if class="style-scope ytd-live-chat-frame"><template></template></ps-dom-if>` to create yt-live-chat-renderer
  2633. // <ps-dom-if> is located inside ytd-live-chat-frame#chat in main frame
  2634. // <ps-dom-if>.hostElement is located as iframe's yt-live-chat-app > div#contents > yt-live-chat-renderer
  2635.  
  2636. */
  2637.  
  2638.  
  2639. // direct createElement or createComponent_ will make the emoji rendering crashed. reason TBC
  2640.  
  2641. return getLCRDummyP_ || (getLCRDummyP_ = Promise.all([customElements.whenDefined('yt-live-chat-app'), customElements.whenDefined('yt-live-chat-renderer')]).then(async () => {
  2642.  
  2643. const tag = "yt-live-chat-renderer"
  2644. let dummy = document.querySelector(tag);
  2645. if (!dummy) {
  2646.  
  2647. let mo = null;
  2648.  
  2649. const ytLiveChatApp = document.querySelector('yt-live-chat-app') || document.createElement('yt-live-chat-app');
  2650.  
  2651. const lcaProto = getProto(ytLiveChatApp);
  2652. let fz38;
  2653.  
  2654. let qt38=0;
  2655. let bypass = false;
  2656.  
  2657.  
  2658. dummy = await new Promise(resolve => {
  2659.  
  2660.  
  2661. if (typeof lcaProto.createComponent_ === 'function' && !lcaProto.createComponent99_ && lcaProto.createComponent_.length === 3) {
  2662. console.log('[yt-chat-lcr] lcaProto.createComponent_ is found');
  2663.  
  2664. lcaProto.createComponent99_ = lcaProto.createComponent_;
  2665. lcaProto.createComponent98_ = function (a, b, c) {
  2666. const z = customCreateComponent(a,b,c);
  2667. if(z !== undefined) return z;
  2668. // (3) ['yt-live-chat-renderer', {…}, true]
  2669. const r = this.createComponent99_(a, b,c);
  2670. const componentTag = (typeof a === 'string' ? a : (a||0).component) || `${(r||0).nodeName}`.toLowerCase();
  2671. if ( componentTag === 'yt-live-chat-renderer' && !bypass) {
  2672. qt38 = 1;
  2673.  
  2674. __LCRInjection__ = __LCRInjection__ | 1;
  2675.  
  2676. // r.polymerController.__proto__.handleLiveChatActions471_ = r.polymerController.__proto__.handleLiveChatActions_;
  2677. // r.polymerController.__proto__.handleLiveChatActions_ = function (arr) {
  2678.  
  2679.  
  2680. // preprocessChatLiveActions(arr);
  2681.  
  2682. // return this.handleLiveChatActions471_(arr);
  2683.  
  2684.  
  2685. // }
  2686.  
  2687. for (const f of LCRImmedidates) {
  2688. f(r);
  2689. }
  2690. LCRImmedidates.length = 0;
  2691.  
  2692. resolve(r); // note: this dom is not yet adopted, but promise resolve is later than ops.
  2693. console.log('[yt-chat-lcr] element found by method 1');
  2694. }
  2695. return r;
  2696. };
  2697. lcaProto.createComponent_ = lcaProto.createComponent98_;
  2698.  
  2699. if (!USE_OBTAIN_LCR_BY_BOTH_METHODS) return;
  2700.  
  2701. }
  2702.  
  2703. // console.log('[yt-chat] lcaProto traditional');
  2704.  
  2705. const pz38 = document.getElementsByTagName(tag);
  2706. fz38 = () => {
  2707. const t = pz38[0]
  2708. if (t) {
  2709. qt38 = 2;
  2710.  
  2711. __LCRInjection__ = __LCRInjection__ | 2;
  2712. resolve(t);
  2713. console.log('[yt-chat-lcr] element found by method 2');
  2714. }
  2715. };
  2716. mo = new MutationObserver(fz38);
  2717. mo.observe(document, { subtree: true, childList: true, attributes: true });
  2718. document.addEventListener('yt-action', fz38, true);
  2719. fz38();
  2720.  
  2721. });
  2722.  
  2723. bypass = true;
  2724.  
  2725. if (mo) {
  2726. mo.disconnect();
  2727. mo.takeRecords();
  2728. mo = null;
  2729. }
  2730. if (fz38) {
  2731. document.removeEventListener('yt-action', fz38, true);
  2732. fz38 = null;
  2733. }
  2734. console.log(`[yt-chat-lcr] lcr appears, dom = ${document.getElementsByTagName(tag).length}, method = ${qt38}`);
  2735.  
  2736.  
  2737. // if (lcaProto.createComponent99_ && lcaProto.createComponent_ && lcaProto.createComponent98_ === lcaProto.createComponent_) {
  2738. // lcaProto.createComponent_ = lcaProto.createComponent99_;
  2739. // lcaProto.createComponent99_ = null;
  2740. // lcaProto.createComponent98_ = null;
  2741. // }
  2742.  
  2743. } else {
  2744. console.log('[yt-chat-lcr] lcr exists');
  2745. }
  2746. return dummy;
  2747.  
  2748. }));
  2749. }
  2750.  
  2751. const { addCssManaged } = (() => {
  2752.  
  2753. const addFontPreRendering = () => {
  2754.  
  2755. groupCollapsed("YouTube Super Fast Chat", " | Fonts Pre-Rendering");
  2756.  
  2757. let efsContainer = document.createElement('elzm-fonts');
  2758. efsContainer.id = 'elzm-fonts-yk75g'
  2759.  
  2760. const arr = [];
  2761. let p = document.createElement('elzm-font');
  2762. arr.push(p);
  2763.  
  2764. if (ENABLE_FONT_PRE_RENDERING & 1) {
  2765. for (const size of [100, 200, 300, 400, 500, 600, 700, 800, 900]) {
  2766.  
  2767. p = document.createElement('elzm-font');
  2768. p.style.fontWeight = size;
  2769. arr.push(p);
  2770. }
  2771. }
  2772.  
  2773. if (ENABLE_FONT_PRE_RENDERING & 2) {
  2774. for (const size of [100, 200, 300, 400, 500, 600, 700, 800, 900]) {
  2775.  
  2776. p = document.createElement('elzm-font');
  2777. p.style.fontFamily = 'Roboto';
  2778. p.style.fontWeight = size;
  2779. arr.push(p);
  2780. }
  2781. }
  2782.  
  2783. if (ENABLE_FONT_PRE_RENDERING & 4) {
  2784. for (const size of [100, 200, 300, 400, 500, 600, 700, 800, 900]) {
  2785.  
  2786. p = document.createElement('elzm-font');
  2787. p.style.fontFamily = '"YouTube Noto",Roboto,Arial,Helvetica,sans-serif';
  2788. p.style.fontWeight = size;
  2789. arr.push(p);
  2790. }
  2791. }
  2792.  
  2793.  
  2794. if (ENABLE_FONT_PRE_RENDERING & 8) {
  2795. for (const size of [100, 200, 300, 400, 500, 600, 700, 800, 900]) {
  2796.  
  2797. p = document.createElement('elzm-font');
  2798. p.style.fontFamily = '"Noto",Roboto,Arial,Helvetica,sans-serif';
  2799. p.style.fontWeight = size;
  2800. arr.push(p);
  2801. }
  2802. }
  2803.  
  2804.  
  2805. if (ENABLE_FONT_PRE_RENDERING & 16) {
  2806. for (const size of [100, 200, 300, 400, 500, 600, 700, 800, 900]) {
  2807.  
  2808. p = document.createElement('elzm-font');
  2809. p.style.fontFamily = 'sans-serif';
  2810. p.style.fontWeight = size;
  2811. arr.push(p);
  2812. }
  2813. }
  2814.  
  2815. console1.log('number of elzm-font elements', arr.length);
  2816.  
  2817. HTMLElement_.prototype.append.apply(efsContainer, arr);
  2818.  
  2819. (document.body || document.documentElement).appendChild(efsContainer);
  2820.  
  2821.  
  2822. console1.log('elzm-font elements have been added to the page for rendering.');
  2823.  
  2824. groupEnd();
  2825.  
  2826. }
  2827.  
  2828. let isCssAdded = false;
  2829.  
  2830. function addCssElement() {
  2831. let s = document.createElement('style');
  2832. s.id = 'ewRvC';
  2833. return s;
  2834. }
  2835.  
  2836. const addCssManaged = () => {
  2837. if (!isCssAdded && document.documentElement && document.head) {
  2838. isCssAdded = true;
  2839. document.head.appendChild(dr(addCssElement())).textContent = addCss();
  2840. if (ENABLE_FONT_PRE_RENDERING) {
  2841. Promise.resolve().then(addFontPreRendering)
  2842. }
  2843. }
  2844. }
  2845.  
  2846. return { addCssManaged };
  2847. })();
  2848.  
  2849.  
  2850. const { setupStyle } = (() => {
  2851.  
  2852. const sp7 = Symbol();
  2853.  
  2854. const proxyHelperFn = (dummy) => ({
  2855.  
  2856. get(target, prop) {
  2857. return (prop in dummy) ? dummy[prop] : prop === sp7 ? target : target[prop];
  2858. },
  2859. set(target, prop, value) {
  2860. if (!(prop in dummy)) {
  2861. target[prop] = value;
  2862. }
  2863. return true;
  2864. },
  2865. has(target, prop) {
  2866. return (prop in target);
  2867. },
  2868. deleteProperty(target, prop) {
  2869. return true;
  2870. },
  2871. ownKeys(target) {
  2872. return Object.keys(target);
  2873. },
  2874. defineProperty(target, key, descriptor) {
  2875. return Object.defineProperty(target, key, descriptor);
  2876. },
  2877. getOwnPropertyDescriptor(target, key) {
  2878. return Object.getOwnPropertyDescriptor(target, key);
  2879. },
  2880.  
  2881. });
  2882.  
  2883. const setupStyle = (m1, m2) => {
  2884. if (!ENABLE_NO_SMOOTH_TRANSFORM) return;
  2885.  
  2886. const dummy1v = {
  2887. transform: '',
  2888. height: '',
  2889. minHeight: '',
  2890. paddingBottom: '',
  2891. paddingTop: ''
  2892. };
  2893.  
  2894. const dummyStyleFn = (k) => (function () { const style = this[sp7]; return style[k](...arguments); });
  2895. for (const k of ['toString', 'getPropertyPriority', 'getPropertyValue', 'item', 'removeProperty', 'setProperty']) {
  2896. dummy1v[k] = dummyStyleFn(k);
  2897. }
  2898.  
  2899. const dummy1p = proxyHelperFn(dummy1v);
  2900. const sp1v = new Proxy(m1.style, dummy1p);
  2901. const sp2v = new Proxy(m2.style, dummy1p);
  2902. Object.defineProperty(m1, 'style', { get() { return sp1v }, set() { }, enumerable: true, configurable: true });
  2903. Object.defineProperty(m2, 'style', { get() { return sp2v }, set() { }, enumerable: true, configurable: true });
  2904. m1.removeAttribute("style");
  2905. m2.removeAttribute("style");
  2906.  
  2907. }
  2908.  
  2909. return { setupStyle };
  2910.  
  2911. })();
  2912.  
  2913.  
  2914.  
  2915. function setThumbnails(config) {
  2916.  
  2917. const { baseObject, thumbnails, flag0, imageLinks } = config;
  2918.  
  2919. if (flag0 || (ENABLE_PRELOAD_THUMBNAIL && imageLinks)) {
  2920.  
  2921.  
  2922. if (thumbnails && thumbnails.length > 0) {
  2923. if (flag0 > 0 && thumbnails.length > 1) {
  2924. let pSize = 0;
  2925. let newThumbnails = [];
  2926. for (const thumbnail of thumbnails) {
  2927. if (!thumbnail || !thumbnail.url) continue;
  2928. const squarePhoto = thumbnail.width === thumbnail.height && typeof thumbnail.width === 'number';
  2929. const condSize = pSize <= 0 || (flag0 === 1 ? pSize > thumbnail.width : pSize < thumbnail.width);
  2930. const leastSizeFulfilled = squarePhoto ? thumbnail.width >= LEAST_IMAGE_SIZE : true;
  2931. if ((!squarePhoto || condSize) && leastSizeFulfilled) {
  2932. newThumbnails.push(thumbnail);
  2933. if (imageLinks) imageLinks.add(thumbnail.url);
  2934. }
  2935. if (squarePhoto && condSize && leastSizeFulfilled) {
  2936. pSize = thumbnail.width;
  2937. }
  2938. }
  2939. if (thumbnails.length !== newThumbnails.length && thumbnails === baseObject.thumbnails && newThumbnails.length > 0) {
  2940. baseObject.thumbnails = newThumbnails;
  2941. } else {
  2942. newThumbnails.length = 0;
  2943. }
  2944. newThumbnails = null;
  2945. } else {
  2946. for (const thumbnail of thumbnails) {
  2947. if (thumbnail && thumbnail.url) {
  2948. if (imageLinks) imageLinks.add(thumbnail.url);
  2949. }
  2950. }
  2951. }
  2952. }
  2953.  
  2954. }
  2955. }
  2956.  
  2957. function fixLiveChatItem(item, imageLinks) {
  2958. const liveChatTextMessageRenderer = (item || 0).liveChatTextMessageRenderer || 0;
  2959. if (liveChatTextMessageRenderer) {
  2960. const messageRuns = (liveChatTextMessageRenderer.message || 0).runs || 0;
  2961. if (messageRuns && messageRuns.length > 0) {
  2962. for (const run of messageRuns) {
  2963. const emojiImage = (((run || 0).emoji || 0).image || 0);
  2964. setThumbnails({
  2965. baseObject: emojiImage,
  2966. thumbnails: emojiImage.thumbnails,
  2967. flag0: EMOJI_IMAGE_SINGLE_THUMBNAIL,
  2968. imageLinks
  2969. });
  2970. }
  2971. }
  2972. const authorPhoto = liveChatTextMessageRenderer.authorPhoto || 0;
  2973. setThumbnails({
  2974. baseObject: authorPhoto,
  2975. thumbnails: authorPhoto.thumbnails,
  2976. flag0: AUTHOR_PHOTO_SINGLE_THUMBNAIL,
  2977. imageLinks
  2978. });
  2979. }
  2980. }
  2981.  
  2982.  
  2983.  
  2984. let kptPF = null;
  2985. const emojiPrefetched = new LimitedSizeSet(PREFETCH_LIMITED_SIZE_EMOJI);
  2986. const authorPhotoPrefetched = new LimitedSizeSet(PREFETCH_LIMITED_SIZE_AUTHOR_PHOTO);
  2987.  
  2988. const linkerOnload = function () {
  2989. this.resolveFn({
  2990. link: this,
  2991. success: true
  2992. });
  2993. this.remove();
  2994. };
  2995. const linkerOnError = function () {
  2996. this.resolveFn({
  2997. link: this,
  2998. success: false
  2999. });
  3000. this.remove();
  3001. };
  3002. function linker(link, rel, href, _as) {
  3003. return new Promise(resolve => {
  3004. if (!link) link = document.createElement('link');
  3005. link.rel = rel;
  3006. if (_as) link.setAttribute('as', _as);
  3007. link.resolveFn = resolve;
  3008. link.onload = linkerOnload;
  3009. link.onerror = linkerOnError;
  3010. link.href = href;
  3011. document.head.appendChild(link);
  3012. link = null;
  3013. });
  3014. }
  3015.  
  3016. // ------- side process [sideProcesses] -------
  3017. const reuseFixDataViewModel = (elm) => {
  3018. // detach data-view model signal
  3019. return Promise.resolve(elm).then((elm) => {
  3020. for (const node of elm.getElementsByTagName('*')) {
  3021. const cnt = insp(node);
  3022. if (typeof cnt.dispose === 'function' && cnt.dispose.length === 0) {
  3023. try {
  3024. cnt.dispose();
  3025. } catch (e) { }
  3026. } else if (typeof node.dispose === 'function' && node.dispose.length === 0) {
  3027. try {
  3028. node.dispose();
  3029. } catch (e) { }
  3030. }
  3031. }
  3032. }).catch(console.warn);;
  3033. };
  3034. const reuseFixYtIconRendering = (elm) => {
  3035. // make properties fresh for flushing
  3036. return Promise.resolve(elm).then((elm) => {
  3037. refreshChildrenYtIcons(elm);
  3038. }).catch(console.warn);;
  3039. };
  3040. const onVisibleItemStampNodeRemoval = (elmId) =>{
  3041. // set the corresponding ticker [ticker-message-removed]
  3042. return Promise.resolve(elmId).then((elmId) => {
  3043. const tickerElm = document.querySelector(`.style-scope.yt-live-chat-ticker-renderer[id="${elmId}"]`);
  3044. if (tickerElm) {
  3045. tickerElm.setAttribute('ticker-message-removed', '')
  3046. if (tickerElm.matches('[ticker-message-removed]:nth-child(n + 40)')) {
  3047. insp(tickerElm).requestRemoval();
  3048. }
  3049. }
  3050. }).catch(console.warn);;
  3051. };
  3052. let onTickerItemStampNodeAddedwaiting = false;
  3053. const onTickerItemStampNodeAdded = () =>{
  3054. // remove the stale ticker(s)
  3055. if (onTickerItemStampNodeAddedwaiting) return;
  3056. onTickerItemStampNodeAddedwaiting = true;
  3057. return Promise.resolve().then(() => {
  3058. onTickerItemStampNodeAddedwaiting = false;
  3059. const selector = "[ticker-message-removed]:nth-child(n + 40)";
  3060. const tickerElm = document.querySelector(selector);
  3061. if (tickerElm) { // likely false
  3062. const tickerElms = document.querySelectorAll(selector);
  3063. for (const tickerElm of tickerElms) insp(tickerElm).requestRemoval();
  3064. }
  3065. }).catch(console.warn);;
  3066. };
  3067. const mutationDelayedRefreshData = async (cnt) => {
  3068. // ensure data is invalidated correctly after mutation
  3069. return Promise.resolve(cnt).then(async cnt => {
  3070. wme.data = `${(wme.data & 7) + 1}`;
  3071. await wmp;
  3072. cnt.__refreshData930__ && cnt.data && cnt.isAttached && cnt.parentComponent && cnt.__refreshData930__('data', !0);
  3073. });
  3074. }
  3075. // ------- side process [sideProcesses] -------
  3076.  
  3077. const cleanContext = async (win) => {
  3078. const waitFn = requestAnimationFrame; // shall have been binded to window
  3079. try {
  3080. let mx = 16; // MAX TRIAL
  3081. const frameId = 'vanillajs-iframe-v1';
  3082. /** @type {HTMLIFrameElement | null} */
  3083. let frame = document.getElementById(frameId);
  3084. let removeIframeFn = null;
  3085. if (!frame) {
  3086. frame = document.createElement('iframe');
  3087. frame.id = frameId;
  3088. const blobURL = typeof webkitCancelAnimationFrame === 'function' && typeof kagi === 'undefined' ? (frame.src = URL.createObjectURL(new Blob([], { type: 'text/html' }))) : null; // avoid Brave Crash
  3089. frame.sandbox = 'allow-same-origin'; // script cannot be run inside iframe but API can be obtained from iframe
  3090. let n = document.createElement('noscript'); // wrap into NOSCRPIT to avoid reflow (layouting)
  3091. n.appendChild(frame);
  3092. while (!document.documentElement && mx-- > 0) await new Promise(waitFn); // requestAnimationFrame here could get modified by YouTube engine
  3093. const root = document.documentElement;
  3094. root.appendChild(n); // throw error if root is null due to exceeding MAX TRIAL
  3095. if (blobURL) Promise.resolve().then(() => URL.revokeObjectURL(blobURL));
  3096.  
  3097. removeIframeFn = (setTimeout) => {
  3098. const removeIframeOnDocumentReady = (e) => {
  3099. e && win.removeEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false);
  3100. e = n;
  3101. n = win = removeIframeFn = 0;
  3102. setTimeout ? setTimeout(() => e.remove(), 200) : e.remove();
  3103. }
  3104. if (!setTimeout || document.readyState !== 'loading') {
  3105. removeIframeOnDocumentReady();
  3106. } else {
  3107. win.addEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false);
  3108. }
  3109. }
  3110. }
  3111. while (!frame.contentWindow && mx-- > 0) await new Promise(waitFn);
  3112. const fc = frame.contentWindow;
  3113. if (!fc) throw "window is not found."; // throw error if root is null due to exceeding MAX TRIAL
  3114. try {
  3115. const { requestAnimationFrame, setTimeout, cancelAnimationFrame, setInterval, clearInterval, getComputedStyle } = fc;
  3116. const res = { requestAnimationFrame, setTimeout, cancelAnimationFrame, setInterval, clearInterval, getComputedStyle };
  3117. for (let k in res) res[k] = res[k].bind(win); // necessary
  3118. if (removeIframeFn) Promise.resolve(res.setTimeout).then(removeIframeFn);
  3119.  
  3120. /** @type {HTMLElement} */
  3121. const HTMLElementProto = fc.HTMLElement.prototype;
  3122. /** @type {EventTarget} */
  3123. const EventTargetProto = fc.EventTarget.prototype;
  3124. // jsonParseFix = {
  3125. // _JSON: fc.JSON, _parse: fc.JSON.parse
  3126. // }
  3127. return {
  3128. ...res,
  3129. animate: HTMLElementProto.animate,
  3130. addEventListener: EventTargetProto.addEventListener,
  3131. removeEventListener: EventTargetProto.removeEventListener
  3132. };
  3133. } catch (e) {
  3134. if (removeIframeFn) removeIframeFn();
  3135. return null;
  3136. }
  3137. } catch (e) {
  3138. console.warn(e);
  3139. return null;
  3140. }
  3141. };
  3142.  
  3143. let xoIcjPr = null;
  3144. const xoIcjId = `xoIcj${Math.floor(Math.random() * 314159265359 + 314159265359).toString(36)}`;
  3145. const xoIcjPost = window.postMessage.bind(window, xoIcjId);
  3146. window.addEventListener('message', (evt) => {
  3147. if ((evt || 0).data === xoIcjId) {
  3148. const t = xoIcjPr;
  3149. if (t !== null) {
  3150. xoIcjPr = null;
  3151. t.resolve();
  3152. }
  3153. }
  3154. });
  3155. const timelineResolve = async () => {
  3156. let t = xoIcjPr;
  3157. if (t === null) {
  3158. t = xoIcjPr = new PromiseExternal();
  3159. xoIcjPost();
  3160. }
  3161. await t.then();
  3162. }
  3163.  
  3164. cleanContext(win).then(__CONTEXT__ => {
  3165. if (!__CONTEXT__) return null;
  3166.  
  3167. const { requestAnimationFrame, setTimeout, cancelAnimationFrame, setInterval, clearInterval, animate, getComputedStyle, addEventListener, removeEventListener } = __CONTEXT__;
  3168.  
  3169. const wmComputedStyle = new WeakMap();
  3170. const getComputedStyleCached = (elem) => {
  3171. let cs = wmComputedStyle.get(elem);
  3172. if (!cs) {
  3173. cs = getComputedStyle(elem);
  3174. wmComputedStyle.set(elem, cs);
  3175. }
  3176. return cs;
  3177. }
  3178.  
  3179.  
  3180. const isGPUAccelerationAvailable = (() => {
  3181. // https://gist.github.com/cvan/042b2448fcecefafbb6a91469484cdf8
  3182. try {
  3183. const canvas = document.createElement('canvas');
  3184. return !!(canvas.getContext('webgl') || canvas.getContext('experimental-webgl'));
  3185. } catch (e) {
  3186. return false;
  3187. }
  3188. })();
  3189.  
  3190. const foregroundPromiseFn_noGPU = (() => {
  3191.  
  3192. if (isGPUAccelerationAvailable) return null;
  3193.  
  3194. const pd = Object.getOwnPropertyDescriptor(Document.prototype, 'visibilityState');
  3195. if (!pd || typeof pd.get !== 'function') return null;
  3196. const pdGet = pd.get;
  3197.  
  3198. let pr = null;
  3199.  
  3200. let hState = pdGet.call(document) === 'hidden';
  3201. // let cid = 0;
  3202. pureAddEventListener.call(document, 'visibilitychange', (evt) => {
  3203. const newHState = pdGet.call(document) === 'hidden';
  3204. if (hState !== newHState) {
  3205. // if (cid > 0) cid = clearInterval(cid);
  3206. hState = newHState;
  3207. if (!hState && pr) pr = pr.resolve();
  3208. }
  3209. });
  3210.  
  3211. // cid = setInterval(() => {
  3212. // const newHState = document.visibilityState === 'hidden';
  3213. // if (hState !== newHState) {
  3214. // hState = newHState;
  3215. // if (!hState && pr) pr = pr.resolve();
  3216. // }
  3217. // }, 100);
  3218.  
  3219.  
  3220. return (() => {
  3221. if (pr) return pr;
  3222. const w = ((!hState && setTimeout(() => {
  3223. if (!hState && pr === w) pr = pr.resolve();
  3224. })), (pr = new PromiseExternal()));
  3225. return w;
  3226. });
  3227.  
  3228. })();
  3229.  
  3230. // window.foregroundPromiseFn_noGPU = foregroundPromiseFn_noGPU;
  3231.  
  3232. let rafPromise = null;
  3233. const getRafPromise = () => rafPromise || (rafPromise = new Promise(resolve => {
  3234. requestAnimationFrame(hRes => {
  3235. rafPromise = null;
  3236. resolve(hRes);
  3237. });
  3238. }));
  3239. const foregroundPromiseFn = foregroundPromiseFn_noGPU || getRafPromise;
  3240.  
  3241. // const iAFP = foregroundPromiseFn_noGPU ? foregroundPromiseFn_noGPU : typeof IntersectionObserver === 'undefined' ? getRafPromise : (() => {
  3242.  
  3243. // const ioWM = new WeakMap();
  3244. // const ek = Symbol();
  3245. // /** @type {IntersectionObserverCallback} */
  3246. // const ioCb = (entries, observer) => {
  3247. // /** @type {PromiseExternal} */
  3248. // const pr = observer[ek];
  3249. // const resolve = pr.resolve;
  3250. // let target;
  3251. // if (resolve && (target = ((entries ? entries[0] : 0) || 0).target) instanceof Element) {
  3252. // pr.resolve = null;
  3253. // observer.unobserve(target);
  3254. // resolve();
  3255. // }
  3256. // };
  3257. // /**
  3258. // *
  3259. // * @param {Element} elm
  3260. // * @returns {Promise<void>}
  3261. // */
  3262. // const iAFP = (elm) => {
  3263. // let io = ioWM.get(elm);
  3264. // if (!io) {
  3265. // io = new IntersectionObserver(ioCb);
  3266. // ioWM.set(elm, io); // strong reference
  3267. // }
  3268. // let pr = io[ek];
  3269. // if (!pr) {
  3270. // pr = io[ek] = new PromiseExternal();
  3271. // io.observe(elm);
  3272. // }
  3273. // return pr;
  3274. // }
  3275.  
  3276. // return iAFP;
  3277.  
  3278. // })();
  3279.  
  3280. let playerState = null;
  3281. let _playerState = null;
  3282. let lastPlayerProgress = null;
  3283. let relayCount = 0;
  3284. let playerEventsByIframeRelay = false;
  3285. let isPlayProgressTriggered = false;
  3286. let waitForInitialDataCompletion = 0;
  3287.  
  3288.  
  3289.  
  3290. // let aeConstructor = null;
  3291.  
  3292. // << __openedChanged82 >>
  3293. let currentMenuPivotWR = null;
  3294.  
  3295. // << if DO_PARTICIPANT_LIST_HACKS >>
  3296. const beforeParticipantsMap = new WeakMap();
  3297. // << end >>
  3298.  
  3299.  
  3300.  
  3301. // << if onRegistryReadyForDOMOperations >>
  3302.  
  3303. let dt0 = Date.now() - 2000;
  3304. const dateNow = () => Date.now() - dt0;
  3305. // let lastScroll = 0;
  3306. // let lastLShow = 0;
  3307. let lastWheel = 0;
  3308. let lastMouseUp = 0;
  3309. let currentMouseDown = false;
  3310. let lastTouchDown = 0;
  3311. let lastTouchUp = 0;
  3312. let currentTouchDown = false;
  3313. let lastUserInteraction = 0;
  3314.  
  3315. let scrollChatFn = null;
  3316.  
  3317. // let skipDontRender = true; // true first; false by flushActiveItems_
  3318. // let allowDontRender = null;
  3319.  
  3320. // ---- #items mutation ----
  3321. // let firstList = true;
  3322.  
  3323. // << end >>
  3324.  
  3325.  
  3326. const stackMarcoTask = (f) => {
  3327. return new Promise(resolve => {
  3328. nextBrowserTick_(async () => {
  3329. try {
  3330. await f();
  3331. } catch (e) {
  3332. console.warn(e);
  3333. } finally {
  3334. resolve();
  3335. }
  3336. });
  3337. })
  3338. };
  3339.  
  3340.  
  3341. const elementFirstElementChild = Object.getOwnPropertyDescriptor(Element.prototype, 'firstElementChild');
  3342. const sFirstElementChild = Symbol();
  3343. Object.defineProperty(Element.prototype, sFirstElementChild, elementFirstElementChild);
  3344.  
  3345. const elementLastElementChild = Object.getOwnPropertyDescriptor(Element.prototype, 'lastElementChild');
  3346. const sLastElementChild = Symbol();
  3347. Object.defineProperty(Element.prototype, sLastElementChild, elementLastElementChild);
  3348.  
  3349. const elementPrevElementSibling = Object.getOwnPropertyDescriptor(Element.prototype, 'previousElementSibling');
  3350. const sPrevElementSibling = Symbol();
  3351. Object.defineProperty(Element.prototype, sPrevElementSibling, elementPrevElementSibling);
  3352.  
  3353. const elementNextElementSibling = Object.getOwnPropertyDescriptor(Element.prototype, 'nextElementSibling');
  3354. const sNextElementSibling = Symbol();
  3355. Object.defineProperty(Element.prototype, sNextElementSibling, elementNextElementSibling);
  3356.  
  3357. const firstComponentChildFn = (elNode) => {
  3358. elNode = elNode[sFirstElementChild];
  3359. while ((elNode instanceof Element) && !elNode.is) elNode = elNode[sNextElementSibling];
  3360. return elNode;
  3361. }
  3362. const lastComponentChildFn = (elNode) => {
  3363. elNode = elNode[sLastElementChild];
  3364. while ((elNode instanceof Element) && !elNode.is) elNode = elNode[sPrevElementSibling];
  3365. return elNode;
  3366. }
  3367. const nextComponentSiblingFn = (elNode) => {
  3368. do {
  3369. elNode = elNode[sNextElementSibling];
  3370. } while ((elNode instanceof Element) && !elNode.is);
  3371. return elNode;
  3372. }
  3373.  
  3374. const nativeNow = performance.constructor.prototype.now.bind(performance);
  3375.  
  3376. const queueMicrotask_ = typeof queueMicrotask === 'function' ? queueMicrotask : (f) => (Promise.resolve().then(f), void 0);
  3377.  
  3378. const executeTaskBatch = function (taskArr, firstMarco = true) {
  3379. if (!(taskArr || 0).length) throw new TypeError(`Illegal invocation`);
  3380. return new Promise(resolveFinal => {
  3381. let resolveFn = null;
  3382. const len = taskArr.length;
  3383. const results = new Array(len);
  3384. const makePromise = () => new Promise(resolve => { resolveFn = resolve });
  3385. let firedCount = 0;
  3386. const executor = () => {
  3387. if (taskArr.length !== len) throw new TypeError(`Illegal invocation`);
  3388. const resolveFn_ = resolveFn;
  3389. let t0 = 0;
  3390. let next = 0;
  3391. taskArr.forEach((task, idx) => {
  3392. if (typeof (task || 0) !== 'object') throw new TypeError(`Illegal invocation`);
  3393. if (!task.fired) {
  3394. queueMicrotask_(() => {
  3395. if (next || task.fired) return;
  3396. task.fired = true;
  3397. if (++firedCount === len) next |= 2;
  3398. if (!t0) t0 = nativeNow() + 10;
  3399. const { fn } = task;
  3400. results[idx] = fn(task); // sync task only
  3401. if (nativeNow() > t0) next |= 1;
  3402. });
  3403. }
  3404. });
  3405. queueMicrotask_(() => resolveFn_(next))
  3406. }
  3407. const looper = (next) => {
  3408. if (!next) throw new TypeError(`Illegal invocation`);
  3409. if (next & 2) {
  3410. if (next & 1) {
  3411. nextBrowserTick_(() => resolveFinal(results))
  3412. } else {
  3413. resolveFinal(results);
  3414. }
  3415. } else {
  3416. const p = makePromise();
  3417. nextBrowserTick_(executor);
  3418. p.then(looper);
  3419. }
  3420. }
  3421. const p = makePromise();
  3422. firstMarco ? nextBrowserTick_(executor) : executor();
  3423. p.then(looper);
  3424.  
  3425. })
  3426.  
  3427. }
  3428. // window.executeTaskBatch = executeTaskBatch;
  3429.  
  3430.  
  3431. const renderMap = new WeakMap();
  3432.  
  3433.  
  3434.  
  3435.  
  3436. const rendererStamperFactory = (cProto, options) => {
  3437.  
  3438.  
  3439. let pDivResourceEventCountLast = 0;
  3440. let pDivResourceEventCount = 0;
  3441.  
  3442. const pDivOnResource = function (evt) {
  3443. const target = evt.target;
  3444. if (target && target.nodeType === 1 && target.nodeName === "IMG") {
  3445. pDivResourceEventCount = (pDivResourceEventCount & 1073741823) + 1;
  3446. }
  3447. };
  3448.  
  3449. const { key, stamperDomClass, preloadFn } = options;
  3450.  
  3451. // const newDoc = document.implementation.createHTMLDocument("NewDoc");
  3452. const pSpace = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
  3453. document.documentElement.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3454. mockCommentElement(document.documentElement.lastChild);
  3455. document.documentElement.lastChild.replaceWith(pSpace);
  3456. const pNode = document.createElement('ns-538');
  3457. pSpace.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3458. mockCommentElement(pSpace.lastChild);
  3459. pSpace.lastChild.replaceWith(pNode);
  3460.  
  3461. const pDiv = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
  3462. if (typeof pNode.attachShadow === 'function') {
  3463. const pShadow = pNode.attachShadow({ mode: "open" });
  3464. pShadow.replaceChildren(pDiv);
  3465. } else {
  3466. pNode.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3467. mockCommentElement(pNode.lastChild);
  3468. pNode.lastChild.replaceWith(pDiv);
  3469. }
  3470.  
  3471. const pDivNew = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
  3472.  
  3473. pDiv.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3474. mockCommentElement(pDiv.lastChild);
  3475. pDiv.lastChild.replaceWith(pDivNew);
  3476.  
  3477. pDivNew.addEventListener('load', pDivOnResource, true);
  3478. pDivNew.addEventListener('error', pDivOnResource, true);
  3479.  
  3480. const wmRemoved = new Map();
  3481.  
  3482. // const wmMapToItem = new WeakMap();
  3483. // let wmPendingList = null;
  3484.  
  3485. const nullComponents = new Map();
  3486.  
  3487. const componentDefaultAttributes = new WeakMap();
  3488.  
  3489. const fnKeyH = `${key}$$c472`;
  3490.  
  3491. cProto[fnKeyH] = async function (cTag, cId, pr00) {
  3492. // await the current executing task (if any)
  3493. // and avoid stacking in the same marco task
  3494. await Promise.all([pr00, nextBrowserTick_()]);
  3495. if (!this.ec389a && !this.ec389r) return;
  3496. const addedCount0 = this.ec389a;
  3497. const removedCount0 = this.ec389r;
  3498.  
  3499. this.ec389 = false;
  3500. this.ec389a = 0;
  3501. this.ec389r = 0;
  3502.  
  3503. const stampDomMap = this.stampDom[cTag].mapping;
  3504. const isTickerRendering = cTag === 'tickerItems';
  3505. const isMessageListRendering = cTag === 'visibleItems';
  3506.  
  3507. // coming process can be stacked as ec389a and ec389r are reset.
  3508.  
  3509. const deObjectComponent = (itemEntry) => {
  3510. const I = firstObjectKey(itemEntry);
  3511. const L = stampDomMap[I];
  3512. const H = itemEntry[I];
  3513. return [L, H];
  3514. }
  3515.  
  3516. const hostElement = this.hostElement;
  3517.  
  3518. let renderNodeCount = 0;
  3519. const renderList = this[cTag].map((item) => {
  3520. const [L, H] = deObjectComponent(item);
  3521. const node = kRef(renderMap.get(H));
  3522. return node && hostElement.contains(node) ? (renderNodeCount++, node) : item;
  3523. });
  3524.  
  3525. const isRenderListEmpty = renderList.length === 0;
  3526.  
  3527.  
  3528. // this.ec389 = null;
  3529. // this.ec389a = 0;
  3530. // this.ec389r = 0;
  3531.  
  3532. let addedCounter = 0;
  3533. let removedCounter = 0;
  3534.  
  3535. const createNewComponentElm = (insertionObj, L, H, componentName) => {
  3536. // const reusable = false;
  3537. // const componentName = this.getComponentName_(L, H);
  3538. let component;
  3539. if (!nullComponents.has(componentName)) {
  3540. nullComponents.set(componentName, (component = document.createElement(componentName)));
  3541. component.className = stamperDomClass;
  3542. // shadowElm.insertAdjacentElement('beforeend', component);
  3543. } else {
  3544. component = nullComponents.get(componentName);
  3545. }
  3546. component = component.cloneNode(false);
  3547.  
  3548. return component;
  3549. }
  3550.  
  3551. const listDom = this.getStampContainer_(cId);
  3552.  
  3553. const pnForNewItem = (item) => {
  3554.  
  3555. const [L, H] = deObjectComponent(item);
  3556.  
  3557. const componentName = this.getComponentName_(L, H);
  3558.  
  3559. const wmList = wmRemoved.get(componentName.toLowerCase());
  3560.  
  3561. let componentNode = null;
  3562. if (wmList && (componentNode = wmList.firstElementChild)) {
  3563. if (this.telemetry_) this.telemetry_.reuse++;
  3564. // if (!wmPendingList) {
  3565. // wmPendingList = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
  3566. // wmPendingList.setAttributeNS('http://www.w3.org/2000/svg', 'wm-pending', 'true');
  3567. // pDiv.insertAdjacentElement('afterend', wmPendingList);
  3568. // }
  3569. // wmPendingList.insertAdjacentElement('beforeend', connectedComponent);
  3570. pDivNew.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3571. mockCommentElement(pDivNew.lastChild);
  3572. pDivNew.lastChild.replaceWith(componentNode);
  3573. const attrMap = componentNode.attributes;
  3574. const defaultAttrs = componentDefaultAttributes.get(componentNode);
  3575. if (defaultAttrs) {
  3576. for (const attr of attrMap) {
  3577. const name = attr.name;
  3578. if (name in defaultAttrs) attr.value = defaultAttrs[name];
  3579. else attrMap.removeNamedItem(name);
  3580. }
  3581. if (attrMap.length !== defaultAttrs['"']) {
  3582. for (const name in defaultAttrs) {
  3583. if (!attrMap[name] && name !== '"') componentNode.setAttribute(name, defaultAttrs[name]);
  3584. }
  3585. }
  3586. }
  3587.  
  3588. } else {
  3589. componentNode = createNewComponentElm(item, L, H, componentName);
  3590. if (this.telemetry_) this.telemetry_.create++;
  3591. }
  3592. if (isTickerRendering) {
  3593. const container = componentNode.firstElementChild;
  3594. if (container) container.classList.add('yt-live-chat-ticker-stampdom-container');
  3595. }
  3596.  
  3597. const cnt = insp(componentNode);
  3598. // if (cnt.__dataInvalid === false) {
  3599. // cnt.__dataInvalid = true;
  3600. // }
  3601. // if (cnt.__dataEnabled === true) {
  3602. // cnt.__dataEnabled = false;
  3603. // }
  3604.  
  3605. if (cnt.data) {
  3606. try {
  3607. cnt.data = H;
  3608. } catch (e) { }
  3609. }
  3610.  
  3611. return [item, L, H, componentNode];
  3612.  
  3613. };
  3614.  
  3615. let imgPreloadPr = null;
  3616. if (isMessageListRendering) {
  3617. const addedItems = renderList.filter(item => item === 'object' && (item instanceof Node));
  3618. imgPreloadPr = preloadFn(addedItems)();
  3619. }
  3620.  
  3621. // const pt1 = performance.now();
  3622. // const newComponentsEntries = await Promise.all(renderList.map((item) => {
  3623. // return typeof item === 'object' && !(item instanceof Node) ? Promise.resolve(item).then(pnForNewItem) : item;
  3624. // }));
  3625. const newComponentsEntries = isRenderListEmpty ? [] : await executeTaskBatch(renderList.map(item => ({
  3626. item,
  3627. fn(task) {
  3628. const { item } = task;
  3629. return typeof item === 'object' && !(item instanceof Node) ? pnForNewItem(item) : item;
  3630. }
  3631. })));
  3632. // const pt2 = performance.now();
  3633.  
  3634. const imgPromises = [];
  3635.  
  3636. const imgPaths = new Set();
  3637.  
  3638. // wait for network cached images loading
  3639. // let trialMax = 4;
  3640. // while (trialMax--) {
  3641. // wme.data = `${(wme.data & 7) + 1}`;
  3642. // await wmp;
  3643. // if (pDivResourceEventCountLast === pDivResourceEventCount) break;
  3644. // pDivResourceEventCountLast = pDivResourceEventCount;
  3645. // }
  3646.  
  3647. this.flushRenderStamperComponentBindings_(); // ensure all deferred flush render tasks clear.
  3648.  
  3649. // imgPromises.push(imageFetch('data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'));
  3650. if (imgPromises.length > 0) {
  3651. const pr1 = Promise.all(imgPromises).catch(e => { });
  3652. const pr2 = autoTimerFn();
  3653. await Promise.race([pr1, pr2]).catch(e => { });
  3654. imgPaths.clear();
  3655. imgPromises.length = 0;
  3656. }
  3657. if (imgPreloadPr) await imgPreloadPr;
  3658.  
  3659. // const batching = [];
  3660. // let j = 0;
  3661. // let elNode;
  3662.  
  3663. const sideProcesses = [];
  3664.  
  3665. const removeStampNode_ = (elNode) => {
  3666. const elm = elNode;
  3667. const cnt = insp(elm);
  3668. const componentName = elm.nodeName.toLowerCase();
  3669. let wmList = wmRemoved.get(componentName);
  3670. if (!wmList) {
  3671. wmList = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
  3672. wmList.setAttributeNS('http://www.w3.org/2000/svg', 'wm-component', componentName);
  3673. pDiv.insertAdjacentHTML('afterend', ttpHTML('<!---->'));
  3674. mockCommentElement(pDiv.nextSibling);
  3675. pDiv.nextSibling.replaceWith(wmList);
  3676. wmRemoved.set(componentName, wmList);
  3677. }
  3678. wmList.insertAdjacentHTML('beforeend', ttpHTML('<!---->'));
  3679. mockCommentElement(wmList.lastChild);
  3680. wmList.lastChild.replaceWith(elm);
  3681. const data = cnt.data;
  3682. if (data) renderMap.delete(cnt.data);
  3683.  
  3684. sideProcesses.push(reuseFixDataViewModel(elm));
  3685. sideProcesses.push(reuseFixYtIconRendering(elm));
  3686. }
  3687.  
  3688. // const removeStampNode = async () => {
  3689.  
  3690. // removedCounter++;
  3691.  
  3692. // const nextElm = nextComponentSiblingFn(elNode);
  3693. // const elmId = elNode.id;
  3694. // removeStampNode_(elNode);
  3695. // // const dzid = this.getAttribute('dz-component-id');
  3696. // // ---- no-cache ----
  3697. // // try{
  3698. // // elm.remove();
  3699. // // }catch(e){}
  3700. // // ---- no-cache ----
  3701.  
  3702. // if (cTag === 'visibleItems') {
  3703. // sideProcesses.push(onVisibleItemStampNodeRemoval(elmId));
  3704. // }
  3705.  
  3706. // j++;
  3707. // elNode = nextElm;
  3708.  
  3709. // }
  3710.  
  3711. // if (typeof Polymer !== "undefined" && typeof Polymer.flush === "function") {
  3712. // // clear all pending rendering first
  3713. // await stackMarcoTask(async () => {
  3714. // Polymer.flush();
  3715. // });
  3716. // }
  3717.  
  3718. // main UI thread - DOM modification
  3719. await new Promise((resolveDM) => {
  3720. nextBrowserTick_(() => {
  3721.  
  3722. const isAtBottom = this.atBottom === true;
  3723. // if (ENABLE_OVERFLOW_ANCHOR && isAtBottom) {
  3724. // shouldScrollAfterFlush = true;
  3725. // }
  3726.  
  3727.  
  3728. const tasks = [];
  3729.  
  3730. const taskFn = {
  3731. remove: (task) => {
  3732.  
  3733. const { elNode } = task;
  3734.  
  3735. removedCounter++;
  3736.  
  3737. const elmId = elNode.id;
  3738. removeStampNode_(elNode);
  3739. // const dzid = this.getAttribute('dz-component-id');
  3740. // ---- no-cache ----
  3741. // try{
  3742. // elm.remove();
  3743. // }catch(e){}
  3744. // ---- no-cache ----
  3745.  
  3746. if (isMessageListRendering) {
  3747. sideProcesses.push(onVisibleItemStampNodeRemoval(elmId));
  3748. }
  3749.  
  3750. return 2
  3751.  
  3752. },
  3753. append: (task) => {
  3754.  
  3755. const { newNode, nodeAfter, parentNode, item, L, H } = task;
  3756. if (nodeAfter) {
  3757. const p = document.createDocumentFragment();
  3758. p.appendChild(newNode);
  3759. (parentNode.__domApi || parentNode).insertBefore(p, nodeAfter);
  3760. this.deferRenderStamperBinding_(newNode, L, H);
  3761. this.flushRenderStamperComponentBindings_();
  3762.  
  3763. componentDefaultAttributes.set(newNode, getAttributes(newNode));
  3764. } else {
  3765. const p = document.createDocumentFragment();
  3766. p.appendChild(newNode);
  3767. (parentNode.__domApi || parentNode).appendChild(p);
  3768. this.deferRenderStamperBinding_(newNode, L, H);
  3769. this.flushRenderStamperComponentBindings_();
  3770.  
  3771. componentDefaultAttributes.set(newNode, getAttributes(newNode));
  3772. }
  3773.  
  3774. // nodeAfter ? nodeAfter.insertAdjacentElement('beforebegin', newNode) : parentNode.insertAdjacentElement('beforeend', newNode);
  3775. const connectedComponent = newNode;
  3776. const cnt = insp(connectedComponent);
  3777. renderMap.set(cnt.data, mWeakRef(connectedComponent));
  3778. mutationDelayedRefreshData(cnt); // not included to sideProcesses
  3779. addedCounter++;
  3780.  
  3781. if (isTickerRendering) {
  3782. sideProcesses.push(onTickerItemStampNodeAdded());
  3783. }
  3784.  
  3785. if (isMessageListRendering && isAtBottom) {
  3786.  
  3787. const itemScroller = this.itemScroller;
  3788. if (itemScroller && (!ENABLE_OVERFLOW_ANCHOR || typeof webkitCancelAnimationFrame !== "function" || itemScroller.scrollTop === 0)) itemScroller.scrollTop = 16777216;
  3789.  
  3790. }
  3791.  
  3792. return 1
  3793. }
  3794. }
  3795.  
  3796. {
  3797. const indexMap = new WeakMap();
  3798. // let index = 0;
  3799.  
  3800. if (!isRenderListEmpty) {
  3801. for (let elNode_ = firstComponentChildFn(listDom), index = 0; elNode_ instanceof Node; elNode_ = nextComponentSiblingFn(elNode_)) {
  3802. indexMap.set(elNode_, index++);
  3803. }
  3804. }
  3805.  
  3806.  
  3807.  
  3808. const keepIndices = new Array(renderNodeCount);
  3809. let keepIndicesLen = 0, lastKeepIndex = -1, requireSort = false;
  3810. for (let i = 0, l = newComponentsEntries.length; i < l; i++) {
  3811. const entry = newComponentsEntries[i];
  3812. if (entry instanceof Node) {
  3813. const index = indexMap.get(entry);
  3814. keepIndices[keepIndicesLen++] = [index, entry];
  3815. if (index > lastKeepIndex) lastKeepIndex = index;
  3816. else requireSort = true;
  3817. }
  3818. }
  3819. keepIndices.length = keepIndicesLen;
  3820. if (requireSort) keepIndices.sort((a, b) => a[0] - b[0]);
  3821. let dk = 0;
  3822.  
  3823. let j = 0;
  3824. let elNode;
  3825.  
  3826. elNode = firstComponentChildFn(listDom);
  3827.  
  3828. if (!isRenderListEmpty) {
  3829. for (const rcEntry of newComponentsEntries) {
  3830. const index = indexMap.get(rcEntry);
  3831. if (typeof index === 'number') {
  3832. const indexEntry = keepIndices[dk++];
  3833. const [dIdx, dNode] = indexEntry;
  3834. indexMap.delete(rcEntry);
  3835. const idx = dIdx;
  3836. while (j < idx && elNode) {
  3837. tasks.push({
  3838. type: 'remove',
  3839. elNode,
  3840. fn: taskFn.remove
  3841. });
  3842. elNode = nextComponentSiblingFn(elNode);
  3843. j++;
  3844. }
  3845. if (j === idx) {
  3846. if (elNode) {
  3847. // if (dNode !== elNode) tasks.push({
  3848. // type: 'swap',
  3849. // earlyNode: indexEntry[1],
  3850. // laterNode: elNode
  3851. // });
  3852. elNode = nextComponentSiblingFn(elNode);
  3853. j++;
  3854. } else {
  3855. console.warn('elNode is not available?', renderList, addedCount0, removedCount0, j, idx);
  3856. }
  3857. }
  3858. } else if (rcEntry instanceof Node) {
  3859. // interruped by the external like clearList
  3860.  
  3861. tasks.push({
  3862. type: 'remove',
  3863. elNode: rcEntry,
  3864. fn: taskFn.remove
  3865. });
  3866.  
  3867. } else {
  3868. const [item, L, H, componentNode] = rcEntry;
  3869.  
  3870. tasks.push({
  3871. type: 'append',
  3872. newNode: componentNode,
  3873. nodeAfter: elNode,
  3874. parentNode: listDom,
  3875. item,
  3876. L,
  3877. H,
  3878. fn: taskFn.append
  3879. });
  3880.  
  3881. }
  3882.  
  3883. }
  3884. }
  3885.  
  3886. while (elNode) {
  3887.  
  3888. tasks.push({
  3889. type: 'remove',
  3890. elNode,
  3891. fn: taskFn.remove
  3892. });
  3893. elNode = nextComponentSiblingFn(elNode);
  3894.  
  3895. }
  3896.  
  3897. }
  3898.  
  3899.  
  3900. executeTaskBatch(tasks).then(resolveDM).catch(console.warn);
  3901.  
  3902. });
  3903. }).catch(console.warn);
  3904.  
  3905. {
  3906. const arr = this[cTag];
  3907. let b = 0;
  3908. b = b | this._setPendingPropertyOrPath(`${cTag}.splices`, {}, true, true);
  3909. b = b | this._setPendingPropertyOrPath(`${cTag}.length`, arr.length, true, true);
  3910. b && this._invalidateProperties();
  3911. }
  3912.  
  3913. // this.flushRenderStamperComponentBindings_(); // just in case...
  3914.  
  3915. await Promise.all(sideProcesses);
  3916.  
  3917. const detail = {
  3918. container: listDom
  3919. };
  3920. this.stampDom[cTag].events && this.hostElement.dispatchEvent(new CustomEvent("yt-rendererstamper-finished", {
  3921. bubbles: !0,
  3922. cancelable: !1,
  3923. composed: !0,
  3924. detail
  3925. }));
  3926. detail.container = null;
  3927.  
  3928. // if (typeof Polymer !== "undefined" && typeof Polymer.flush === "function") {
  3929. // // clear all remaining rendering before promise resolve
  3930. // await stackMarcoTask(async () => {
  3931. // Polymer.flush();
  3932. // });
  3933. // }
  3934.  
  3935. }
  3936.  
  3937. // proceedStampDomArraySplices371_ // proceedStampDomArraySplices381_
  3938. cProto[key] = function (cTag, cId, indexSplice) {
  3939. // console.log('proceedStampDomArraySplices_')
  3940. // assume no error -> no try catch (performance consideration)
  3941. const { index, addedCount, removed } = indexSplice;
  3942. const removedCount = removed ? removed.length : indexSplice.removedCount;
  3943. indexSplice = null;
  3944. if (!addedCount && !removedCount) {
  3945. console.warn('proceedStampDomArraySplices_', 'Error 001');
  3946. return false;
  3947. }
  3948. // const streamArr = this[cTag];
  3949. if (!this.ec389) {
  3950. if (this.ec389a || this.ec389r) {
  3951. console.warn('proceedStampDomArraySplices_', 'Error 002');
  3952. return false;
  3953. }
  3954. this.ec389 = true;
  3955. this.ec389a = 0;
  3956. this.ec389r = 0;
  3957. }
  3958. const shouldExecute = !this.ec389a && !this.ec389r;
  3959.  
  3960. this.ec389a += addedCount;
  3961. this.ec389r += removedCount;
  3962.  
  3963. if (shouldExecute) {
  3964.  
  3965. // let shouldScrollAfterFlush = false;
  3966. const pr00 = this.ec389pr;
  3967. const ec389pr = this.ec389pr = this[fnKeyH](cTag, cId, pr00).catch(console.warn);
  3968.  
  3969. if (cTag === 'visibleItems') {
  3970. this.prDelay288 = ec389pr;
  3971. // this.hasUserJustInteracted12_ = (this.hasUserJustInteracted11_ || (() => false));
  3972.  
  3973. // the first microtask after promise resolved
  3974. // YYYYYYY
  3975. // ec389pr.then(async () => {
  3976. // if (shouldScrollAfterFlush) {
  3977. // if (this.atBottom === false && this.allowScroll === true && !this.hasUserJustInteracted12_()) this.scrollToBottom_();
  3978. // wme.data = `${(wme.data & 7) + 1}`;
  3979. // await wmp;
  3980. // if (this.atBottom === false && this.allowScroll === true && !this.hasUserJustInteracted12_()) this.scrollToBottom_();
  3981. // }
  3982. // });
  3983.  
  3984. }
  3985.  
  3986. }
  3987.  
  3988. return true;
  3989. }
  3990.  
  3991.  
  3992.  
  3993.  
  3994.  
  3995. }
  3996.  
  3997.  
  3998. class RAFHub {
  3999. constructor() {
  4000. /** @type {number} */
  4001. this.startAt = 8170;
  4002. /** @type {number} */
  4003. this.counter = 0;
  4004. /** @type {number} */
  4005. this.rid = 0;
  4006. /** @type {Map<number, FrameRequestCallback>} */
  4007. this.funcs = new Map();
  4008. const funcs = this.funcs;
  4009. /** @type {FrameRequestCallback} */
  4010. this.bCallback = this.mCallback.bind(this);
  4011. this.pClear = () => funcs.clear();
  4012. this.keepRAF = false;
  4013. }
  4014. /** @param {DOMHighResTimeStamp} highResTime */
  4015. mCallback(highResTime) {
  4016. this.rid = 0;
  4017. Promise.resolve().then(this.pClear);
  4018. this.funcs.forEach(func => Promise.resolve(highResTime).then(func).catch(console.warn));
  4019. }
  4020. /** @param {FrameRequestCallback} f */
  4021. request(f) {
  4022. const cid = this.startAt + (this.counter = (this.counter & 1073741823) + 1);
  4023. this.funcs.set(cid, f);
  4024. if (this.rid === 0) this.rid = requestAnimationFrame(this.bCallback);
  4025. return cid;
  4026. }
  4027. /** @param {number} cid */
  4028. cancel(cid) {
  4029. cid = +cid;
  4030. if (cid > 0) {
  4031. if (cid <= this.startAt) {
  4032. return cancelAnimationFrame(cid);
  4033. }
  4034. if (this.rid > 0) {
  4035. this.funcs.delete(cid);
  4036. if (this.funcs.size === 0 && !this.keepRAF) {
  4037. cancelAnimationFrame(this.rid);
  4038. this.rid = 0;
  4039. }
  4040. }
  4041. }
  4042. }
  4043. }
  4044.  
  4045. function basePrefetching() {
  4046.  
  4047. new Promise(resolve => {
  4048.  
  4049. if (document.readyState !== 'loading') {
  4050. resolve();
  4051. } else {
  4052. win.addEventListener("DOMContentLoaded", resolve, false);
  4053. }
  4054.  
  4055. }).then(() => {
  4056. const hostL1 = [
  4057. 'https://www.youtube.com', 'https://googlevideo.com',
  4058. 'https://googleapis.com', 'https://accounts.youtube.com',
  4059. 'https://www.gstatic.com', 'https://ggpht.com',
  4060. 'https://yt3.ggpht.com', 'https://yt4.ggpht.com'
  4061. ];
  4062.  
  4063. const hostL2 = [
  4064. 'https://youtube.com',
  4065. 'https://fonts.googleapis.com', 'https://fonts.gstatic.com'
  4066. ];
  4067.  
  4068. let link = null;
  4069.  
  4070. function kn() {
  4071.  
  4072. link = document.createElement('link');
  4073. if (link.relList && link.relList.supports) {
  4074. 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)
  4075. } else {
  4076. kptPF = 0;
  4077. }
  4078.  
  4079. groupCollapsed("YouTube Super Fast Chat", " | PREFETCH SUPPORTS");
  4080. if (ENABLE_BASE_PREFETCHING) console1.log('dns-prefetch', (kptPF & 1) ? 'OK' : 'NG');
  4081. if (ENABLE_BASE_PREFETCHING) console1.log('preconnect', (kptPF & 2) ? 'OK' : 'NG');
  4082. if (ENABLE_PRELOAD_THUMBNAIL) console1.log('prefetch', (kptPF & 4) ? 'OK' : 'NG');
  4083. if (ENABLE_PRELOAD_THUMBNAIL) console1.log('preload', (kptPF & 16) ? 'OK' : 'NG');
  4084. groupEnd();
  4085.  
  4086. }
  4087.  
  4088. for (const h of hostL1) {
  4089.  
  4090. if (kptPF === null) kn();
  4091. if (ENABLE_BASE_PREFETCHING) {
  4092. // if (kptPF & 1) {
  4093. // linker(link, 'dns-prefetch', h);
  4094. // link = null;
  4095. // }
  4096. if (kptPF & 2) {
  4097. linker(link, 'preconnect', h);
  4098. link = null;
  4099. }
  4100. }
  4101. }
  4102.  
  4103. for (const h of hostL2) {
  4104. if (kptPF === null) kn();
  4105. if (ENABLE_BASE_PREFETCHING) {
  4106. if (kptPF & 1) {
  4107. linker(link, 'dns-prefetch', h);
  4108. link = null;
  4109. }
  4110. }
  4111. }
  4112.  
  4113. })
  4114.  
  4115.  
  4116. }
  4117.  
  4118. if (DO_LINK_PREFETCH) basePrefetching();
  4119.  
  4120. const { notifyPath7081 } = (() => {
  4121. // DO_PARTICIPANT_LIST_HACKS
  4122.  
  4123. const mutexParticipants = new Mutex();
  4124.  
  4125. let uvid = 0;
  4126. let r95dm = 0;
  4127. let c95dm = -1;
  4128.  
  4129. const foundMap = (base, content) => {
  4130. /*
  4131. let lastSearch = 0;
  4132. let founds = base.map(baseEntry => {
  4133. let search = content.indexOf(baseEntry, lastSearch);
  4134. if (search < 0) return false;
  4135. lastSearch = search + 1;
  4136. return true;
  4137. });
  4138. return founds;
  4139. */
  4140. const contentSet = new Set(content);
  4141. return base.map(baseEntry => contentSet.has(baseEntry));
  4142.  
  4143. }
  4144.  
  4145.  
  4146.  
  4147. let participantsForSpliceWR = null;
  4148.  
  4149. class IndexSpliceEntry {
  4150. /**
  4151. *
  4152. * @param {number} _index
  4153. * @param {number} _addedCount
  4154. * @param {any[]} _removed
  4155. */
  4156. constructor(_index, _addedCount, _removed) {
  4157. this.index = _index;
  4158. this.addedCount = _addedCount;
  4159. this.removed = _removed;
  4160. }
  4161. get __proxy312__() {
  4162. return 1
  4163. }
  4164. get type() {
  4165. return 'splice'
  4166. }
  4167. get object() {
  4168. return kRef(participantsForSpliceWR); // avoid memory leakage
  4169. }
  4170. }
  4171.  
  4172. const spliceIndicesFunc = (beforeParticipants, participants, idsBefore, idsAfter) => {
  4173.  
  4174. let foundsForAfter = foundMap(idsAfter, idsBefore);
  4175. let foundsForBefore = foundMap(idsBefore, idsAfter);
  4176.  
  4177. const nAfter = foundsForAfter.length;
  4178. const nBefore = foundsForBefore.length;
  4179.  
  4180. const indexSplices = [];
  4181. const contentUpdates = [];
  4182. participantsForSpliceWR = null;
  4183. for (let i = 0, j = 0; i < nBefore || j < nAfter;) {
  4184. if (beforeParticipants[i] === participants[j]) {
  4185. i++; j++;
  4186. } else if (idsBefore[i] === idsAfter[j]) {
  4187. // content changed
  4188. contentUpdates.push({ indexI: i, indexJ: j })
  4189. i++; j++;
  4190. } else {
  4191. let addedCount = 0;
  4192. for (let q = j; q < nAfter; q++) {
  4193. if (foundsForAfter[q] === false) addedCount++;
  4194. else break;
  4195. }
  4196. let removedCount = 0;
  4197. for (let q = i; q < nBefore; q++) {
  4198. if (foundsForBefore[q] === false) removedCount++;
  4199. else break;
  4200. }
  4201. if (!addedCount && !removedCount) {
  4202. throw 'ERROR(0xFF32): spliceIndicesFunc';
  4203. }
  4204. const entry = new IndexSpliceEntry(
  4205. j,
  4206. addedCount,
  4207. removedCount >= 1 ? beforeParticipants.slice(i, i + removedCount) : []
  4208. );
  4209. indexSplices.push(entry);
  4210. i += removedCount;
  4211. j += addedCount;
  4212. }
  4213. }
  4214. foundsForBefore = null;
  4215. foundsForAfter = null;
  4216. idsBefore = null;
  4217. idsAfter = null;
  4218. beforeParticipants = null;
  4219. participantsForSpliceWR = indexSplices.length > 0 ? mWeakRef(participants) : null;
  4220. participants = null;
  4221. return { indexSplices, contentUpdates };
  4222.  
  4223. }
  4224.  
  4225. /*
  4226.  
  4227. customElements.get("yt-live-chat-participant-renderer").prototype.notifyPath=function(){ console.log(123); console.log(new Error().stack)}
  4228.  
  4229. VM63631:1 Error
  4230. at customElements.get.notifyPath (<anonymous>:1:122)
  4231. at e.forwardRendererStamperChanges_ (live_chat_polymer.js:4453:35)
  4232. at e.rendererStamperApplyChangeRecord_ (live_chat_polymer.js:4451:12)
  4233. at e.rendererStamperObserver_ (live_chat_polymer.js:4448:149)
  4234. at Object.pu [as fn] (live_chat_polymer.js:1692:118)
  4235. at ju (live_chat_polymer.js:1674:217)
  4236. at a._propertiesChanged (live_chat_polymer.js:1726:122)
  4237. at b._flushProperties (live_chat_polymer.js:1597:200)
  4238. at a._invalidateProperties (live_chat_polymer.js:1718:69)
  4239. at a.notifyPath (live_chat_polymer.js:1741:182)
  4240.  
  4241. */
  4242.  
  4243. function convertToIds(participants) {
  4244. return participants.map(participant => {
  4245. if (!participant || typeof participant !== 'object') {
  4246. console.warn('Error(0xFA41): convertToIds', participant);
  4247. return participant; // just in case
  4248. }
  4249. let keys = Object.keys(participant);
  4250. // liveChatTextMessageRenderer
  4251. // liveChatParticipantRenderer - livestream channel owner [no authorExternalChannelId]
  4252. // liveChatPaidMessageRenderer
  4253. /*
  4254.  
  4255. 'yt-live-chat-participant-renderer' utilizes the following:
  4256. authorName.simpleText: string
  4257. authorPhoto.thumbnails: Object{url:string, width:int, height:int} []
  4258. authorBadges[].liveChatAuthorBadgeRenderer.icon.iconType: string
  4259. authorBadges[].liveChatAuthorBadgeRenderer.tooltip: string
  4260. authorBadges[].liveChatAuthorBadgeRenderer.accessibility.accessibilityData: Object{label:string}
  4261.  
  4262. */
  4263. if (keys.length !== 1) {
  4264. console.warn('Error(0xFA42): convertToIds', participant);
  4265. return participant; // just in case
  4266. }
  4267. let key = keys[0];
  4268. let renderer = (participant[key] || 0);
  4269. let authorName = (renderer.authorName || 0);
  4270. let text = `${authorName.simpleText || authorName.text}`
  4271. let res = participant; // fallback if it is not a vaild entry
  4272. if (typeof text !== 'string') {
  4273. console.warn('Error(0xFA53): convertToIds', participant);
  4274. } else {
  4275. text = `${renderer.authorExternalChannelId || 'null'}|${text || ''}`;
  4276. if (text.length > 1) res = text;
  4277. }
  4278. return res;
  4279. // return renderer?`${renderer.id}|${renderer.authorExternalChannelId}`: '';
  4280. // note: renderer.id will be changed if the user typed something to trigger the update of the participants' record.
  4281. });
  4282. }
  4283.  
  4284. const checkChangeToParticipantRendererContent = CHECK_CHANGE_TO_PARTICIPANT_RENDERER_CONTENT ? (p1, p2) => {
  4285. // just update when content is changed.
  4286. if (p1.authorName !== p2.authorName) return true;
  4287. if (p1.authorPhoto !== p2.authorPhoto) return true;
  4288. if (p1.authorBadges !== p2.authorBadges) return true;
  4289. return false;
  4290. } : (p1, p2) => {
  4291. // keep integrity all the time.
  4292. return p1 !== p2; // always true
  4293. }
  4294.  
  4295. function notifyPath7081(path) { // cnt "yt-live-chat-participant-list-renderer"
  4296.  
  4297. if (PARTICIPANT_UPDATE_ONLY_ONLY_IF_MODIFICATION_DETECTED) {
  4298. if (path !== "participantsManager.participants") {
  4299. return this.__notifyPath5036__.apply(this, arguments);
  4300. }
  4301. if (c95dm === r95dm) return;
  4302. } else {
  4303. const stack = new Error().stack;
  4304. if (path !== "participantsManager.participants" || stack.indexOf('.onParticipantsChanged') < 0) {
  4305. return this.__notifyPath5036__.apply(this, arguments);
  4306. }
  4307. }
  4308.  
  4309. if (uvid > 1e8) uvid = uvid % 100;
  4310. let tid = ++uvid;
  4311.  
  4312.  
  4313. // const cnt = this; // "yt-live-chat-participant-list-renderer"
  4314.  
  4315. const wNode = mWeakRef(this);
  4316.  
  4317. mutexParticipants.lockWith(lockResolve => {
  4318.  
  4319. const cnt = kRef(wNode);
  4320.  
  4321. const participants00 = (((cnt || 0).participantsManager || 0).participants || 0);
  4322.  
  4323. if (tid !== uvid || !cnt || typeof (participants00 || 0).splice !== 'function') {
  4324. lockResolve();
  4325. return;
  4326. }
  4327.  
  4328. let doUpdate = false;
  4329.  
  4330. if (PARTICIPANT_UPDATE_ONLY_ONLY_IF_MODIFICATION_DETECTED) {
  4331.  
  4332. if (!participants00.r94dm) {
  4333. participants00.r94dm = 1;
  4334. r95dm = (r95dm & 1073741823) + 1;
  4335. participants00.push = function () {
  4336. r95dm = (r95dm & 1073741823) + 1;
  4337. return Array.prototype.push.apply(this, arguments);
  4338. }
  4339. participants00.pop = function () {
  4340. r95dm = (r95dm & 1073741823) + 1;
  4341. return Array.prototype.pop.apply(this, arguments);
  4342. }
  4343. participants00.shift = function () {
  4344. r95dm = (r95dm & 1073741823) + 1;
  4345. return Array.prototype.shift.apply(this, arguments);
  4346. }
  4347. participants00.unshift = function () {
  4348. r95dm = (r95dm & 1073741823) + 1;
  4349. return Array.prototype.unshift.apply(this, arguments);
  4350. }
  4351. participants00.splice = function () {
  4352. r95dm = (r95dm & 1073741823) + 1;
  4353. return Array.prototype.splice.apply(this, arguments);
  4354. }
  4355. participants00.sort = function () {
  4356. r95dm = (r95dm & 1073741823) + 1;
  4357. return Array.prototype.sort.apply(this, arguments);
  4358. }
  4359. participants00.reverse = function () {
  4360. r95dm = (r95dm & 1073741823) + 1;
  4361. return Array.prototype.reverse.apply(this, arguments);
  4362. }
  4363. }
  4364.  
  4365. if (c95dm !== r95dm) {
  4366. c95dm = r95dm;
  4367. doUpdate = true;
  4368. }
  4369.  
  4370. } else {
  4371. doUpdate = true;
  4372. }
  4373.  
  4374. if (!doUpdate) {
  4375. lockResolve();
  4376. return;
  4377. }
  4378.  
  4379. const participants = participants00.slice(0);
  4380. const beforeParticipants = beforeParticipantsMap.get(cnt) || [];
  4381. beforeParticipantsMap.set(cnt, participants);
  4382.  
  4383. const resPromise = (async () => {
  4384.  
  4385. if (beforeParticipants.length === 0) {
  4386. // not error
  4387. return 0;
  4388. }
  4389.  
  4390. let countOfElements = cnt.__getAllParticipantsDOMRenderedLength__()
  4391.  
  4392. // console.log(participants.length, doms.length) // different if no requestAnimationFrame
  4393. if (beforeParticipants.length !== countOfElements) {
  4394. // there is somewrong for the cache. - sometimes happen
  4395. return 0;
  4396. }
  4397.  
  4398. const idsBefore = convertToIds(beforeParticipants);
  4399. const idsAfter = convertToIds(participants);
  4400.  
  4401. let { indexSplices, contentUpdates } = spliceIndicesFunc(beforeParticipants, participants, idsBefore, idsAfter);
  4402.  
  4403. let res = 1; // default 1 for no update
  4404.  
  4405. if (indexSplices.length >= 1) {
  4406.  
  4407.  
  4408. // let p2 = participants.slice(indexSplices[0].index, indexSplices[0].index+indexSplices[0].addedCount);
  4409. // let p1 = indexSplices[0].removed;
  4410. // console.log(indexSplices.length, indexSplices ,p1,p2, convertToIds(p1),convertToIds(p2))
  4411.  
  4412. /* folllow
  4413. a.notifyPath(c + ".splices", d);
  4414. a.notifyPath(c + ".length", b.length);
  4415. */
  4416. // stampDomArraySplices_
  4417.  
  4418.  
  4419. await new Promise(resolve => {
  4420. cnt.resolveForDOMRendering781 = resolve;
  4421.  
  4422. cnt.__notifyPath5036__("participantsManager.participants.splices", {
  4423. indexSplices
  4424. });
  4425. indexSplices = null;
  4426. participantsForSpliceWR = null;
  4427. cnt.__notifyPath5036__("participantsManager.participants.length",
  4428. participants.length
  4429. );
  4430.  
  4431. });
  4432.  
  4433. // play safe for the change of 'length'
  4434. await nextBrowserTick_();
  4435.  
  4436. countOfElements = cnt.__getAllParticipantsDOMRenderedLength__();
  4437.  
  4438. const wrongSize = participants.length !== countOfElements
  4439. if (wrongSize) {
  4440. console.warn("ERROR(0xE2C3): notifyPath7081", beforeParticipants.length, participants.length, doms.length)
  4441. return 0;
  4442. }
  4443.  
  4444. res = 2 | 4;
  4445.  
  4446. } else {
  4447.  
  4448. indexSplices = null;
  4449. participantsForSpliceWR = null;
  4450.  
  4451. if (participants.length !== countOfElements) {
  4452. // other unhandled cases
  4453. return 0;
  4454. }
  4455.  
  4456. }
  4457.  
  4458. // participants.length === countOfElements before contentUpdates
  4459. if (contentUpdates.length >= 1) {
  4460. for (const contentUpdate of contentUpdates) {
  4461. let isChanged = checkChangeToParticipantRendererContent(beforeParticipants[contentUpdate.indexI], participants[contentUpdate.indexJ]);
  4462. if (isChanged) {
  4463. cnt.__notifyPath5036__(`participantsManager.participants[${contentUpdate.indexJ}]`);
  4464. res |= 4 | 8;
  4465. }
  4466. }
  4467. }
  4468. contentUpdates = null;
  4469.  
  4470. return res;
  4471.  
  4472.  
  4473. })();
  4474.  
  4475.  
  4476. resPromise.then(async (resValue) => {
  4477. const condition = resValue === 0 ? 1 : (resValue & 4) === 4 ? 2 : 0;
  4478. const isLogRequired = SHOW_PARTICIPANT_CHANGES_IN_CONSOLE && condition > 0;
  4479. isLogRequired && groupCollapsed("Participant List Change", `tid = ${tid}; res = ${resValue}`);
  4480. if (condition === 1) {
  4481. isLogRequired && console1.log("Full Refresh begins");
  4482. await new Promise(resolve => {
  4483. cnt.resolveForDOMRendering781 = resolve;
  4484. cnt.__notifyPath5036__("participantsManager.participants"); // full refresh
  4485. });
  4486. isLogRequired && console1.log("Full Refresh ends");
  4487. } else if (condition === 2) {
  4488. isLogRequired && console1.log(`Number of participants (before): ${beforeParticipants.length}`);
  4489. isLogRequired && console1.log(`Number of participants (after): ${participants.length}`);
  4490. isLogRequired && console1.log(`Total number of rendered participants: ${cnt.__getAllParticipantsDOMRenderedLength__()}`);
  4491. isLogRequired && console1.log(`Participant Renderer Content Updated: ${(resValue & 8) === 8}`);
  4492. // requestAnimationFrame is required to avoid particiant update during DOM changing (stampDomArraySplices_)
  4493. // mutex lock with requestAnimationFrame can also disable participants update in background
  4494. }
  4495. isLogRequired && groupEnd();
  4496. (condition === 2) && (await new Promise(requestAnimationFrame));
  4497. lockResolve();
  4498. });
  4499.  
  4500. });
  4501.  
  4502. }
  4503.  
  4504. return { notifyPath7081 };
  4505.  
  4506. })();
  4507.  
  4508. const whenDefinedMultiple = async (tags) => {
  4509.  
  4510. const sTags = [...new Set(tags)];
  4511. const len = sTags.length;
  4512.  
  4513. const pTags = new Array(len);
  4514. for (let i = 0; i < len; i++) {
  4515. pTags[i] = customElements.whenDefined(sTags[i]);
  4516. }
  4517.  
  4518. await Promise.all(pTags);
  4519. pTags.length = 0;
  4520.  
  4521. return sTags;
  4522.  
  4523. }
  4524.  
  4525. const onRegistryReadyForDataManipulation = () => {
  4526.  
  4527. function dummy5035(a, b, c) { }
  4528. function dummy411(a, b, c) { }
  4529.  
  4530.  
  4531.  
  4532. customElements.whenDefined("yt-live-chat-participant-list-renderer").then(() => {
  4533.  
  4534. if (!DO_PARTICIPANT_LIST_HACKS) return;
  4535.  
  4536. const tag = "yt-live-chat-participant-list-renderer";
  4537. const cProto = getProto(document.createElement(tag));
  4538. if (!cProto || typeof cProto.attached !== 'function') {
  4539. // for _registered, proto.attached shall exist when the element is defined.
  4540. // for controller extraction, attached shall exist when instance creates.
  4541. console.warn(`proto.attached for ${tag} is unavailable.`);
  4542. return;
  4543. }
  4544.  
  4545.  
  4546. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-participant-list-renderer hacks");
  4547.  
  4548. 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'];
  4549. const fgs = {};
  4550. for (const key of fgsArr) fgs[key] = undefined;
  4551.  
  4552. try {
  4553. const EXPERIMENT_FLAGS = ytcfg.data_.EXPERIMENT_FLAGS;
  4554. for (const key of fgsArr) fgs[key] = EXPERIMENT_FLAGS[key];
  4555. } catch (e) { }
  4556. console1.log(`EXPERIMENT_FLAGS: ${JSON.stringify(fgs, null, 2)}`);
  4557.  
  4558. const canDoReplacement = (() => {
  4559. if (typeof cProto.__notifyPath5035__ === 'function' && cProto.__notifyPath5035__.name !== 'dummy5035') {
  4560. console.warn('YouTube Live Chat Tamer is running.');
  4561. return;
  4562. }
  4563.  
  4564. if (typeof cProto.__attached411__ === 'function' && cProto.__attached411__.name !== 'dummy411') {
  4565. console.warn('YouTube Live Chat Tamer is running.');
  4566. return;
  4567. }
  4568.  
  4569. cProto.__notifyPath5035__ = dummy5035 // just to against Live Chat Tamer
  4570. cProto.__attached411__ = dummy411 // just to against Live Chat Tamer
  4571.  
  4572. if (typeof cProto.flushRenderStamperComponentBindings_ !== 'function' || cProto.flushRenderStamperComponentBindings_.length !== 0) {
  4573. console.warn("ERROR(0xE355): cProto.flushRenderStamperComponentBindings_ not found");
  4574. return;
  4575. }
  4576.  
  4577. if (typeof cProto.flushRenderStamperComponentBindings66_ === 'function') {
  4578. console.warn("ERROR(0xE356): cProto.flushRenderStamperComponentBindings66_");
  4579. return;
  4580. }
  4581.  
  4582. if (typeof cProto.__getAllParticipantsDOMRenderedLength__ === 'function') {
  4583. console.warn("ERROR(0xE357): cProto.__getAllParticipantsDOMRenderedLength__");
  4584. return;
  4585. }
  4586. return true;
  4587. })();
  4588.  
  4589. console1.log(`Data Manipulation Boost = ${canDoReplacement}`);
  4590.  
  4591. assertor(() => fnIntegrity(cProto.attached, '0.32.22')) // just warning
  4592. if (typeof cProto.flushRenderStamperComponentBindings_ === 'function') {
  4593. const fiRSCB = fnIntegrity(cProto.flushRenderStamperComponentBindings_);
  4594. console1.log(`flushRenderStamperComponentBindings_ ### ${fiRSCB} ###`);
  4595. } else {
  4596. console1.log("flushRenderStamperComponentBindings_ - not found");
  4597. }
  4598. // assertor(() => fnIntegrity(cProto.flushRenderStamperComponentBindings_, '0.386.233')) // just warning
  4599.  
  4600. if (typeof cProto.flushRenderStamperComponentBindings_ === 'function') {
  4601. cProto.flushRenderStamperComponentBindings66_ = cProto.flushRenderStamperComponentBindings_;
  4602. cProto.flushRenderStamperComponentBindings_ = function () {
  4603. // console.log('flushRenderStamperComponentBindings_')
  4604. this.flushRenderStamperComponentBindings66_();
  4605. if (this.resolveForDOMRendering781) {
  4606. this.resolveForDOMRendering781();
  4607. this.resolveForDOMRendering781 = null;
  4608. }
  4609. };
  4610. }
  4611.  
  4612. cProto.__getAllParticipantsDOMRenderedLength__ = function () {
  4613. const container = ((this || 0).$ || 0).participants;
  4614. if (!container) return 0;
  4615. return HTMLElement_.prototype.querySelectorAll.call(container, 'yt-live-chat-participant-renderer').length;
  4616. }
  4617.  
  4618. const onPageElements = [...document.querySelectorAll('yt-live-chat-participant-list-renderer:not(.n9fJ3)')];
  4619.  
  4620. cProto.__attached412__ = cProto.attached;
  4621. const fpPList = function (hostElement) {
  4622. const cnt = insp(hostElement);
  4623. if (beforeParticipantsMap.has(cnt)) return;
  4624. hostElement.classList.add('n9fJ3');
  4625.  
  4626. assertor(() => (cnt.__dataEnabled === true && cnt.__dataReady === true));
  4627. if (typeof cnt.notifyPath !== 'function' || typeof cnt.__notifyPath5036__ !== 'undefined') {
  4628. console.warn("ERROR(0xE318): yt-live-chat-participant-list-renderer")
  4629. return;
  4630. }
  4631.  
  4632. groupCollapsed("Participant List attached", "");
  4633. cnt.__notifyPath5036__ = cnt.notifyPath
  4634. const participants = ((cnt.participantsManager || 0).participants || 0);
  4635. assertor(() => (participants.length > -1 && typeof participants.slice === 'function'));
  4636. console1.log(`initial number of participants: ${participants.length}`);
  4637. const newParticipants = (participants.length >= 1 && typeof participants.slice === 'function') ? participants.slice(0) : [];
  4638. beforeParticipantsMap.set(cnt, newParticipants);
  4639. cnt.notifyPath = notifyPath7081;
  4640. console1.log(`CHECK_CHANGE_TO_PARTICIPANT_RENDERER_CONTENT = ${CHECK_CHANGE_TO_PARTICIPANT_RENDERER_CONTENT}`);
  4641. groupEnd();
  4642. }
  4643. cProto.attached = function () {
  4644. fpPList(this.hostElement || this);
  4645. this.__attached412__.apply(this, arguments);
  4646. };
  4647.  
  4648.  
  4649. if (ENABLE_FLAGS_MAINTAIN_STABLE_LIST_FOR_PARTICIPANTS_LIST) {
  4650.  
  4651. /** @type {boolean | (()=>boolean)} */
  4652. let toUseMaintainStableList = USE_MAINTAIN_STABLE_LIST_ONLY_WHEN_KS_FLAG_IS_SET ? (() => ytcfg.data_.EXPERIMENT_FLAGS.kevlar_should_maintain_stable_list === true) : true;
  4653. if (typeof cProto.stampDomArray_ === 'function' && cProto.stampDomArray_.length === 6 && !cProto.stampDomArray_.nIegT && !cProto.stampDomArray66_) {
  4654.  
  4655. let lastMessageDate = 0;
  4656. cProto.stampDomArray66_ = cProto.stampDomArray_;
  4657.  
  4658. cProto.stampDomArray_ = function (...args) {
  4659. if (args[0] && args[0].length > 0 && args[1] === "participants" && args[2] && args[3] === true && !args[5]) {
  4660. if (typeof toUseMaintainStableList === 'function') {
  4661. toUseMaintainStableList = toUseMaintainStableList();
  4662. }
  4663. args[5] = toUseMaintainStableList;
  4664. let currentDate = Date.now();
  4665. if (currentDate - lastMessageDate > 440) {
  4666. lastMessageDate = currentDate;
  4667. console.log('maintain_stable_list for participants list', toUseMaintainStableList);
  4668. }
  4669. }
  4670. return this.stampDomArray66_.apply(this, args);
  4671. }
  4672.  
  4673. cProto.stampDomArray_.nIegT = 1;
  4674.  
  4675. }
  4676. console1.log(`ENABLE_FLAGS_MAINTAIN_STABLE_LIST_FOR_PARTICIPANTS_LIST - OK`);
  4677. } else {
  4678. console1.log(`ENABLE_FLAGS_MAINTAIN_STABLE_LIST_FOR_PARTICIPANTS_LIST - NG`);
  4679. }
  4680.  
  4681. groupEnd();
  4682.  
  4683. if (onPageElements.length >= 1) {
  4684. for (const s of onPageElements) {
  4685. if (insp(s).isAttached === true) {
  4686. fpPList(s);
  4687. }
  4688. }
  4689. }
  4690.  
  4691. }).catch(console.warn);
  4692.  
  4693. };
  4694.  
  4695. if (DO_PARTICIPANT_LIST_HACKS) {
  4696. promiseForCustomYtElementsReady.then(onRegistryReadyForDataManipulation);
  4697. }
  4698.  
  4699.  
  4700.  
  4701. const rafHub = (ENABLE_RAF_HACK_TICKERS || ENABLE_RAF_HACK_DOCKED_MESSAGE || ENABLE_RAF_HACK_INPUT_RENDERER || ENABLE_RAF_HACK_EMOJI_PICKER) ? new RAFHub() : null;
  4702.  
  4703. const transitionEndHooks = new WeakSet();
  4704. const transitionEndAfterFnSimple = new WeakMap();
  4705. let transitionEndAfterFnSimpleEnable = 0;
  4706. // let prevTransitionClosing = null;
  4707.  
  4708. const passiveCapture = typeof IntersectionObserver === 'function' ? { capture: true, passive: true } : true;
  4709.  
  4710.  
  4711. const transitionEndAfterFn = (evt) => {
  4712. if (transitionEndAfterFnSimpleEnable > 0 && evt.propertyName && !evt.pseudoElement) {
  4713. const elm = evt.target;
  4714. const f = transitionEndAfterFnSimple.get(elm);
  4715. if (f) {
  4716. transitionEndAfterFnSimple.delete(elm);
  4717. f.resolve(evt.propertyName);
  4718. }
  4719. }
  4720. };
  4721.  
  4722. const fixChildrenIssue = !!fixChildrenIssue801;
  4723. if (fixChildrenIssue && typeof Object.getOwnPropertyDescriptor === 'function' && typeof Proxy !== 'undefined') {
  4724. let fixChildrenIssue_status = false;
  4725. const divProto = HTMLDivElement.prototype;
  4726. const polymerControllerSetData3 = function (c, d, e) {
  4727. return insp(this).set(c, d, e);
  4728. }
  4729. const polymerControllerSetData2 = function (c, d) {
  4730. return insp(this).set(c, d);
  4731. }
  4732. const dummyFn = function () {
  4733. console.log('dummyFn', ...arguments);
  4734. };
  4735.  
  4736. const wm44 = new Map();
  4737. function unPolymerSet(elem) {
  4738. const is = elem.is;
  4739. if (is && !elem.set) {
  4740. let rt = wm44.get(is);
  4741. if (!rt) {
  4742. rt = 1;
  4743. const cnt = insp(elem);
  4744. if (cnt !== elem && cnt && typeof cnt.set === 'function') {
  4745. const pcSet = cnt.constructor.prototype.set;
  4746. if (pcSet && typeof pcSet === 'function' && pcSet.length === 3) {
  4747. rt = polymerControllerSetData3;
  4748. } else if (pcSet && typeof pcSet === 'function' && pcSet.length === 2) {
  4749. rt = polymerControllerSetData2;
  4750. }
  4751. }
  4752. wm44.set(is, rt);
  4753. }
  4754. if (typeof rt === 'function') {
  4755. elem.set = rt;
  4756. } else {
  4757. elem.set = dummyFn;
  4758. }
  4759. }
  4760. }
  4761. if (!divProto.__children577__ && !divProto.__children578__) {
  4762.  
  4763. const dp = Object.getOwnPropertyDescriptor(Element.prototype, 'children');
  4764. const dp2 = Object.getOwnPropertyDescriptor(HTMLElement_.prototype, 'children');
  4765. const dp3 = Object.getOwnPropertyDescriptor(divProto, 'children');
  4766.  
  4767. if (dp && dp.configurable === true && dp.enumerable === true && typeof dp.get === 'function' && !dp2 && !dp3) {
  4768.  
  4769. if (divProto instanceof HTMLElement_ && divProto instanceof Element) {
  4770.  
  4771. let m = Object.assign({}, dp);
  4772. divProto.__children577__ = dp.get;
  4773. divProto.__children578__ = function () {
  4774. if (this.__children803__) return this.__children803__;
  4775. if (this.__children801__) {
  4776. let arr = [];
  4777. for (let elem = this.firstElementChild; elem !== null; elem = elem.nextElementSibling) {
  4778. if (elem.is) {
  4779. unPolymerSet(elem);
  4780. arr.push(elem);
  4781. }
  4782. }
  4783. if (this.__children801__ === 2) this.__children803__ = arr;
  4784. return arr;
  4785. }
  4786. return 577;
  4787. };
  4788. m.get = function () {
  4789. const r = this.__children578__();
  4790. if (r !== 577) return r;
  4791. return this.__children577__();
  4792. };
  4793. Object.defineProperty(divProto, 'children', m);
  4794.  
  4795. fixChildrenIssue_status = true;
  4796.  
  4797. }
  4798. }
  4799.  
  4800. }
  4801.  
  4802. if (!fixChildrenIssue_status) {
  4803. console.log('fixChildrenIssue - set NG')
  4804. }
  4805.  
  4806.  
  4807. }
  4808.  
  4809.  
  4810. const watchUserCSS = () => {
  4811.  
  4812. // if (!CSS.supports('contain-intrinsic-size', 'auto var(--wsr94)')) return;
  4813.  
  4814. const getElemFromWR = (nr) => {
  4815. const n = kRef(nr);
  4816. if (n && n.isConnected) return n;
  4817. return null;
  4818. }
  4819.  
  4820. const clearContentVisibilitySizing = () => {
  4821. Promise.resolve().then(() => {
  4822.  
  4823. const e = document.querySelector('#show-more[disabled]');
  4824. let btnShowMoreWR = e ? mWeakRef(e) : null;
  4825.  
  4826. let lastVisibleItemWR = null;
  4827. for (const elm of document.querySelectorAll('[wsr93]')) {
  4828. if (elm.getAttribute('wsr93') === 'visible') lastVisibleItemWR = mWeakRef(elm);
  4829. elm.setAttribute('wsr93', '');
  4830. // custom CSS property --wsr94 not working when attribute wsr93 removed
  4831. }
  4832. foregroundPromiseFn().then(() => {
  4833. const btnShowMore = getElemFromWR(btnShowMoreWR); btnShowMoreWR = null;
  4834. if (btnShowMore) btnShowMore.click();
  4835. else {
  4836. // would not work if switch it frequently
  4837. const lastVisibleItem = getElemFromWR(lastVisibleItemWR); lastVisibleItemWR = null;
  4838. if (lastVisibleItem) {
  4839.  
  4840. Promise.resolve()
  4841. .then(() => lastVisibleItem.scrollIntoView())
  4842. .then(() => lastVisibleItem.scrollIntoView(false))
  4843. .then(() => lastVisibleItem.scrollIntoView({ behavior: "instant", block: "end", inline: "nearest" }))
  4844. .catch(e => { }) // break the chain when method not callable
  4845.  
  4846. }
  4847. }
  4848. });
  4849.  
  4850. }).catch(console.warn);
  4851.  
  4852. }
  4853.  
  4854. const mutObserver = new MutationObserver((mutations) => {
  4855. for (const mutation of mutations) {
  4856. if ((mutation.addedNodes || 0).length >= 1) {
  4857. for (const addedNode of mutation.addedNodes) {
  4858. if (addedNode.nodeName === 'STYLE') {
  4859. clearContentVisibilitySizing();
  4860. return;
  4861. }
  4862. }
  4863. }
  4864. if ((mutation.removedNodes || 0).length >= 1) {
  4865. for (const removedNode of mutation.removedNodes) {
  4866. if (removedNode.nodeName === 'STYLE') {
  4867. clearContentVisibilitySizing();
  4868. return;
  4869. }
  4870. }
  4871. }
  4872. }
  4873. });
  4874.  
  4875. mutObserver.observe(document.documentElement, {
  4876. childList: true,
  4877. subtree: false
  4878. });
  4879. mutObserver.observe(document.head, {
  4880. childList: true,
  4881. subtree: false
  4882. });
  4883. mutObserver.observe(document.body, {
  4884. childList: true,
  4885. subtree: false
  4886. });
  4887.  
  4888. }
  4889.  
  4890.  
  4891. const { lcRendererElm, visObserver } = (() => {
  4892.  
  4893. let lcRendererWR = null;
  4894.  
  4895. const lcRendererElm = () => {
  4896. let lcRenderer = kRef(lcRendererWR);
  4897. if (!lcRenderer || !lcRenderer.isConnected) {
  4898. lcRenderer = document.querySelector('yt-live-chat-item-list-renderer.yt-live-chat-renderer');
  4899. lcRendererWR = lcRenderer ? mWeakRef(lcRenderer) : null;
  4900. }
  4901. return lcRenderer;
  4902. };
  4903.  
  4904.  
  4905. let hasFirstShowMore = false;
  4906. // let lastVisible = null;
  4907.  
  4908. const visObserverFn = (entry) => {
  4909.  
  4910. const target = entry.target;
  4911. if (!target || !target.hasAttribute('wsr93')) return;
  4912. // if(target.classList.contains('dont-render')) return;
  4913. let isVisible = entry.isIntersecting === true && entry.intersectionRatio > 0.5;
  4914. // const h = entry.boundingClientRect.height;
  4915. /*
  4916. if (h < 16) { // wrong: 8 (padding/margin); standard: 32; test: 16 or 20
  4917. // e.g. under fullscreen. the element created but not rendered.
  4918. target.setAttribute('wsr93', '');
  4919. return;
  4920. }
  4921. */
  4922. if (isVisible) {
  4923. // target.style.setProperty('--wsr94', h + 'px');
  4924. target.setAttribute('wsr93', 'visible');
  4925. // lastVisible = mWeakRef(target);
  4926. if (nNextElem(target) === null) {
  4927.  
  4928. // firstVisibleItemDetected = true;
  4929. /*
  4930. if (dateNow() - lastScroll < 80) {
  4931. lastLShow = 0;
  4932. lastScroll = 0;
  4933. Promise.resolve().then(clickShowMore);
  4934. } else {
  4935. lastLShow = dateNow();
  4936. }
  4937. */
  4938. // lastLShow = dateNow();
  4939. } else if (!hasFirstShowMore) { // should more than one item being visible
  4940. // implement inside visObserver to ensure there is sufficient delay
  4941. hasFirstShowMore = true;
  4942. // foregroundPromiseFn().then(() => {
  4943. // // foreground page
  4944. // // page visibly ready -> load the latest comments at initial loading
  4945. // const lcRenderer = lcRendererElm();
  4946. // if (lcRenderer) {
  4947. // nextBrowserTick_(() => {
  4948. // const cnt = insp(lcRenderer);
  4949. // if (cnt.isAttached === false || (cnt.hostElement || cnt).isConnected === false) return;
  4950. // cnt.scrollToBottom_();
  4951. // });
  4952. // }
  4953. // });
  4954. }
  4955. }
  4956. else if (target.getAttribute('wsr93') === 'visible') { // ignore target.getAttribute('wsr93') === '' to avoid wrong sizing
  4957.  
  4958. // target.style.setProperty('--wsr94', h + 'px');
  4959. target.setAttribute('wsr93', 'hidden');
  4960. } // note: might consider 0 < entry.intersectionRatio < 0.5 and target.getAttribute('wsr93') === '' <new last item>
  4961.  
  4962. }
  4963.  
  4964.  
  4965.  
  4966. const visObserver = new IntersectionObserver((entries) => {
  4967.  
  4968. for (const entry of entries) {
  4969.  
  4970. Promise.resolve(entry).then(visObserverFn);
  4971.  
  4972. }
  4973.  
  4974. }, {
  4975. rootMargin: "0px",
  4976. threshold: [0.05, 0.95],
  4977. });
  4978.  
  4979.  
  4980. return { lcRendererElm, visObserver }
  4981.  
  4982.  
  4983. })();
  4984.  
  4985. // let itemsResizeObserverAttached = false;
  4986. // const resizeObserverFallback = new IntersectionObserver((mutation, observer) => {
  4987. // const itemScroller = mutation[0].target;
  4988. // observer.unobserve(itemScroller);
  4989. // if (itemScroller.scrollTop === 0) itemScroller.scrollTop = window.screen.height; // scrollTop changing
  4990. // });
  4991.  
  4992. const itemScrollerResizeObserver = typeof ResizeObserver === 'function' && ENABLE_OVERFLOW_ANCHOR ? new ResizeObserver((mutations) => {
  4993. const mutation = mutations[mutations.length - 1];
  4994. // console.log('resizeObserver', mutation)
  4995. const itemScroller = (mutation || 0).target;
  4996. if (!itemScroller) return;
  4997. const listDom = itemScroller.closest('yt-live-chat-item-list-renderer');
  4998. if (!listDom) return;
  4999. const listCnt = insp(listDom);
  5000. if(listCnt.visibleItems.length === 0) return;
  5001. if (listCnt.atBottom !== true) return;
  5002. // if (itemScroller.scrollTop === 0) {
  5003. itemScroller.scrollTop = 16777216; // scrollTop changing
  5004. // }
  5005. }) : null;
  5006.  
  5007. const { setupMutObserver } = (() => {
  5008.  
  5009.  
  5010. const mutFn = (items) => {
  5011. let seqIndex = -1;
  5012. const elementSet = new Set();
  5013. for (let node = nLastElem(items); node !== null; node = nPrevElem(node)) { // from bottom
  5014. let found = node.hasAttribute('wsr93') ? (node.hasAttribute('yt-chat-item-seq') ? 2 : 1) : 0;
  5015. if (found === 1) node.removeAttribute('wsr93'); // reuse -> wsr93: hidden after re-attach
  5016. if (found === 2) {
  5017. seqIndex = parseInt(node.getAttribute('yt-chat-item-seq'), 10);
  5018. break;
  5019. }
  5020. visObserver.unobserve(node); // reuse case
  5021. node.setAttribute('wsr93', '');
  5022. visObserver.observe(node);
  5023. elementSet.add(node);
  5024. }
  5025. let iter = elementSet.values();
  5026. let i = seqIndex + elementSet.size;
  5027. for (let curr; curr = iter.next().value;) { // from bottom
  5028. curr.setAttribute('yt-chat-item-seq', i % 60);
  5029. curr.classList.add('yt-chat-item-' + ((i % 2) ? 'odd' : 'even'));
  5030. i--;
  5031. }
  5032. iter = null;
  5033. elementSet.clear();
  5034. }
  5035.  
  5036. // const itemsResizeObserver = typeof ResizeObserver === 'function' && 0 ? new ResizeObserver((mutations) => {
  5037. // const mutation = mutations[mutations.length - 1];
  5038. // // console.log('resizeObserver', mutation)
  5039. // const items = (mutation || 0).target;
  5040. // if (!items) return;
  5041. // const listDom = items.closest('yt-live-chat-item-list-renderer');
  5042. // if (!listDom) return;
  5043. // const listCnt = insp(listDom);
  5044. // if (listCnt.atBottom !== true) return;
  5045. // const itemScroller = listCnt.itemScroller || listCnt.$['item-scroller'] || listCnt.querySelector('#item-scroller') || 0;
  5046. // // if (itemScroller.scrollTop === 0) {
  5047. // itemScroller.scrollTop = mutation.contentRect.height; // scrollTop changing
  5048. // // }
  5049. // }) : null;
  5050. // itemsResizeObserverAttached = itemsResizeObserver !== null;
  5051.  
  5052. const mutObserver = new MutationObserver((mutations) => {
  5053. const items = (mutations[0] || 0).target;
  5054. if (!items) return;
  5055. mutFn(items);
  5056. });
  5057.  
  5058. const setupMutObserver = (items) => {
  5059. scrollChatFn = null;
  5060. mutObserver.disconnect();
  5061. mutObserver.takeRecords();
  5062. if (items) {
  5063. if (typeof items.__appendChild932__ === 'function') {
  5064. if (typeof items.appendChild === 'function') items.appendChild = items.__appendChild932__;
  5065. if (typeof items.__shady_native_appendChild === 'function') items.__shady_native_appendChild = items.__appendChild932__;
  5066. }
  5067. mutObserver.observe(items, {
  5068. childList: true,
  5069. subtree: false
  5070. });
  5071. mutFn(items);
  5072.  
  5073.  
  5074. // if (itemsResizeObserver) itemsResizeObserver.observe(items);
  5075.  
  5076. // const isFirstList = firstList;
  5077. // firstList = false;
  5078.  
  5079.  
  5080. if (items && items.nextElementSibling === null) {
  5081. items.parentNode.appendChild(dr(document.createElement('item-anchor')));
  5082. WITH_SCROLL_ANCHOR = true;
  5083. if (ENABLE_OVERFLOW_ANCHOR) {
  5084. items.classList.add('no-anchor');
  5085. nodeParent(items).classList.add('no-anchor'); // required
  5086. }
  5087. }
  5088.  
  5089.  
  5090.  
  5091.  
  5092. if (ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX) {
  5093.  
  5094. (() => {
  5095.  
  5096. const tag = 'yt-iframed-player-events-relay'
  5097. const dummy = document.createElement(tag);
  5098.  
  5099. const cProto = getProto(dummy);
  5100. if (!cProto || !cProto.handlePostMessage_) {
  5101. console.warn(`proto.handlePostMessage_ for ${tag} is unavailable.`);
  5102. return;
  5103. }
  5104.  
  5105. if (typeof cProto.handlePostMessage_ === 'function' && !cProto.handlePostMessage66_ && !cProto.handlePostMessage67_ ) {
  5106.  
  5107. cProto.handlePostMessage66_ = cProto.handlePostMessage_;
  5108.  
  5109. const handlePostMessageAfterPromiseA = (da) => {
  5110.  
  5111. if (!da || typeof da !== 'object') return;
  5112.  
  5113. if ('yt-player-state-change' in da) {
  5114.  
  5115. const qc = da['yt-player-state-change'];
  5116.  
  5117.  
  5118. let isQcChanged = false;
  5119.  
  5120. if (qc === 2) { isQcChanged = qc !== _playerState; _playerState = 2; relayCount = 0; } // paused
  5121. else if (qc === 3) { isQcChanged = qc !== _playerState; _playerState = 3; } // playing
  5122. else if (qc === 1) { isQcChanged = qc !== _playerState; _playerState = 1; } // playing
  5123.  
  5124.  
  5125. if ((isQcChanged) && playerState !== _playerState) {
  5126. playerEventsByIframeRelay = true;
  5127. onPlayStateChangePromise = new Promise((resolve) => {
  5128. const k = _playerState;
  5129. foregroundPromiseFn().then(() => {
  5130. if (k === _playerState && playerState !== _playerState) playerState = _playerState;
  5131. onPlayStateChangePromise = null;
  5132. resolve();
  5133. })
  5134. }).catch(console.warn);
  5135.  
  5136. }
  5137.  
  5138. } else if ('yt-player-video-progress' in da) {
  5139. const vp = da['yt-player-video-progress'];
  5140.  
  5141.  
  5142. relayCount++;
  5143. lastPlayerProgress = vp > 0 ? vp : 0; // no use ?
  5144.  
  5145.  
  5146. if (relayPromise && vp > 0 && relayCount >= 2) {
  5147. if (onPlayStateChangePromise) {
  5148. onPlayStateChangePromise.then(() => {
  5149. relayPromise && relayPromise.resolve();
  5150. relayPromise = null;
  5151. })
  5152. } else {
  5153. relayPromise.resolve();
  5154. relayPromise = null;
  5155. }
  5156. }
  5157.  
  5158. }
  5159.  
  5160. };
  5161.  
  5162. cProto.handlePostMessage67_ = function (a) {
  5163.  
  5164. let da = a.data;
  5165. const wNode = mWeakRef(this);
  5166. // const wData = mWeakRef(da);
  5167.  
  5168. playEventsStack = playEventsStack.then(() => {
  5169.  
  5170. const cnt = kRef(wNode);
  5171. // const da = kRef(wData);
  5172.  
  5173. if (!cnt || !a || !da) return;
  5174. handlePostMessageAfterPromiseA(da);
  5175. da = null;
  5176.  
  5177. const r = cnt.handlePostMessage66_(a);
  5178. a = null;
  5179.  
  5180. }).catch(console.warn);
  5181.  
  5182. }
  5183.  
  5184. const handlePostMessageAfterPromiseB = (da) => {
  5185.  
  5186. const lcr = document.querySelector('yt-live-chat-renderer');
  5187. const psc = document.querySelector("yt-player-seek-continuation");
  5188. if (lcr && psc && lcr.replayBuffer_) {
  5189.  
  5190. const rbProgress = lcr.replayBuffer_.lastVideoOffsetTimeMsec;
  5191. const daProgress = da['yt-player-video-progress'] * 1000
  5192. // document.querySelector('yt-live-chat-renderer').playerProgressChanged_(1e-5);
  5193.  
  5194. const front_ = (lcr.replayBuffer_.replayQueue || 0).front_;
  5195. const back_ = (lcr.replayBuffer_.replayQueue || 0).back_;
  5196.  
  5197. // console.log(deepCopy( front_))
  5198. // console.log(deepCopy( back_))
  5199. // console.log(rbProgress, daProgress, )
  5200. if (front_ && back_ && rbProgress > daProgress && back_.length > 2 && back_.some(e => e && +e.videoOffsetTimeMsec > daProgress) && back_.some(e => e && +e.videoOffsetTimeMsec < daProgress)) {
  5201. // no action
  5202. // console.log('ss1')
  5203. } else if (rbProgress < daProgress + 3400 && rbProgress > daProgress - 1200) {
  5204. // daProgress - 1200 < rbProgress < daProgress + 3400
  5205. // console.log('ss2')
  5206. } else {
  5207.  
  5208. lcr.previousProgressSec = 1E-5;
  5209. // lcr._setIsSeeking(!0),
  5210. lcr.replayBuffer_.clear()
  5211. psc.fireSeekContinuation_(da['yt-player-video-progress']);
  5212. }
  5213.  
  5214. }
  5215.  
  5216.  
  5217. };
  5218.  
  5219. cProto.handlePostMessage_ = function (a) {
  5220.  
  5221. let da = (a || 0).data || 0;
  5222. const wNode = mWeakRef(this);
  5223.  
  5224. if (typeof da !== 'object') return;
  5225.  
  5226. if (waitForInitialDataCompletion === 1) return;
  5227.  
  5228. if (!isPlayProgressTriggered) {
  5229. isPlayProgressTriggered = true; // set once
  5230.  
  5231. if ('yt-player-video-progress' in da) {
  5232. waitForInitialDataCompletion = 1;
  5233.  
  5234. const wrapWith = (data) => {
  5235. const { origin } = a;
  5236. return {
  5237. origin,
  5238. data
  5239. };
  5240. }
  5241.  
  5242. this.handlePostMessage67_(wrapWith({
  5243. "yt-iframed-parent-ready": true
  5244. }));
  5245.  
  5246.  
  5247. playEventsStack = playEventsStack.then(() => {
  5248.  
  5249. const cnt = kRef(wNode);
  5250.  
  5251. if (!cnt || !a || !da) return;
  5252.  
  5253. handlePostMessageAfterPromiseB(da);
  5254. da = null;
  5255.  
  5256. waitForInitialDataCompletion = 2;
  5257.  
  5258. const r = cnt.handlePostMessage_(a); // isPlayProgressTriggered is set
  5259. a = null;
  5260.  
  5261. }).catch(console.warn);
  5262.  
  5263. return;
  5264.  
  5265. }
  5266.  
  5267. }
  5268.  
  5269. this.handlePostMessage67_(a);
  5270.  
  5271. }
  5272.  
  5273. }
  5274.  
  5275.  
  5276. })();
  5277.  
  5278. }
  5279.  
  5280.  
  5281. }
  5282. }
  5283.  
  5284. return { setupMutObserver };
  5285.  
  5286.  
  5287.  
  5288. })();
  5289.  
  5290. const setupEvents = () => {
  5291. // not called when boost chat is enabled
  5292.  
  5293. // global - currentMouseDown, lastUserInteraction
  5294.  
  5295. let scrollCount = 0;
  5296. let lastScrollCount = -1;
  5297. let lastMouseDown = 0;
  5298.  
  5299. const passiveCapture = typeof IntersectionObserver === 'function' ? { capture: true, passive: true } : true;
  5300.  
  5301. // const delayFlushActiveItemsAfterUserActionK_ = () => {
  5302.  
  5303. // const lcRenderer = lcRendererElm();
  5304. // if (lcRenderer) {
  5305. // const cnt = insp(lcRenderer);
  5306. // if (!cnt.hasUserJustInteracted11_) return;
  5307. // if (cnt.atBottom && cnt.allowScroll && cnt.activeItems_.length >= 1 && cnt.hasUserJustInteracted11_()) {
  5308. // cnt.delayFlushActiveItemsAfterUserAction11_ && cnt.delayFlushActiveItemsAfterUserAction11_();
  5309. // }
  5310. // }
  5311.  
  5312. // }
  5313.  
  5314. const delayFlushActiveItemsAfterUserActionK_ = null;
  5315.  
  5316. document.addEventListener('scroll', (evt) => {
  5317. if (!evt || !evt.isTrusted) return;
  5318. // lastScroll = dateNow();
  5319. scrollCount = (scrollCount & 1073741823) + 1;
  5320. }, passiveCapture); // support contain => support passive
  5321.  
  5322. document.addEventListener('wheel', (evt) => {
  5323. if (!evt || !evt.isTrusted) return;
  5324. if (lastScrollCount === scrollCount) return;
  5325. lastScrollCount = scrollCount;
  5326. lastWheel = dateNow();
  5327. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5328. }, passiveCapture); // support contain => support passive
  5329.  
  5330. document.addEventListener('mousedown', (evt) => {
  5331. if (!evt || !evt.isTrusted) return;
  5332. if (((evt || 0).target || 0).id !== 'item-scroller') return;
  5333. lastMouseDown = dateNow();
  5334. currentMouseDown = true;
  5335. lastUserInteraction = lastMouseDown;
  5336. }, passiveCapture);
  5337.  
  5338. document.addEventListener('pointerdown', (evt) => {
  5339. if (!evt || !evt.isTrusted) return;
  5340. if (((evt || 0).target || 0).id !== 'item-scroller') return;
  5341. lastMouseDown = dateNow();
  5342. currentMouseDown = true;
  5343. lastUserInteraction = lastMouseDown;
  5344. }, passiveCapture);
  5345.  
  5346. document.addEventListener('click', (evt) => {
  5347. if (!evt || !evt.isTrusted) return;
  5348. if (((evt || 0).target || 0).id !== 'item-scroller') return;
  5349. lastMouseDown = lastMouseUp = dateNow();
  5350. currentMouseDown = false;
  5351. lastUserInteraction = lastMouseDown;
  5352. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5353. }, passiveCapture);
  5354.  
  5355. document.addEventListener('tap', (evt) => {
  5356. if (!evt || !evt.isTrusted) return;
  5357. if (((evt || 0).target || 0).id !== 'item-scroller') return;
  5358. lastMouseDown = lastMouseUp = dateNow();
  5359. currentMouseDown = false;
  5360. lastUserInteraction = lastMouseDown;
  5361. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5362. }, passiveCapture);
  5363.  
  5364.  
  5365. document.addEventListener('mouseup', (evt) => {
  5366. if (!evt || !evt.isTrusted) return;
  5367. if (currentMouseDown) {
  5368. lastMouseUp = dateNow();
  5369. currentMouseDown = false;
  5370. lastUserInteraction = lastMouseUp;
  5371. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5372. }
  5373. }, passiveCapture);
  5374.  
  5375.  
  5376. document.addEventListener('pointerup', (evt) => {
  5377. if (!evt || !evt.isTrusted) return;
  5378. if (currentMouseDown) {
  5379. lastMouseUp = dateNow();
  5380. currentMouseDown = false;
  5381. lastUserInteraction = lastMouseUp;
  5382. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5383. }
  5384. }, passiveCapture);
  5385.  
  5386. document.addEventListener('touchstart', (evt) => {
  5387. if (!evt || !evt.isTrusted) return;
  5388. lastTouchDown = dateNow();
  5389. currentTouchDown = true;
  5390. lastUserInteraction = lastTouchDown;
  5391. }, passiveCapture);
  5392.  
  5393. document.addEventListener('touchmove', (evt) => {
  5394. if (!evt || !evt.isTrusted) return;
  5395. lastTouchDown = dateNow();
  5396. currentTouchDown = true;
  5397. lastUserInteraction = lastTouchDown;
  5398. }, passiveCapture);
  5399.  
  5400. document.addEventListener('touchend', (evt) => {
  5401. if (!evt || !evt.isTrusted) return;
  5402. if (currentTouchDown) {
  5403. lastTouchUp = dateNow();
  5404. currentTouchDown = false;
  5405. lastUserInteraction = lastTouchUp;
  5406. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5407. }
  5408. }, passiveCapture);
  5409.  
  5410. document.addEventListener('touchcancel', (evt) => {
  5411. if (!evt || !evt.isTrusted) return;
  5412. if (currentTouchDown) {
  5413. lastTouchUp = dateNow();
  5414. currentTouchDown = false;
  5415. lastUserInteraction = lastTouchUp;
  5416. delayFlushActiveItemsAfterUserActionK_ && delayFlushActiveItemsAfterUserActionK_();
  5417. }
  5418. }, passiveCapture);
  5419.  
  5420.  
  5421. }
  5422.  
  5423. // const getTimestampUsec = (itemRenderer) => {
  5424. // if (itemRenderer && 'timestampUsec' in itemRenderer) {
  5425. // return itemRenderer.timestampUsec
  5426. // } else if (itemRenderer && itemRenderer.showItemEndpoint) {
  5427. // const messageRenderer = ((itemRenderer.showItemEndpoint.showLiveChatItemEndpoint || 0).renderer || 0);
  5428. // if (messageRenderer) {
  5429.  
  5430. // const messageRendererKey = firstObjectKey(messageRenderer);
  5431. // if (messageRendererKey && messageRenderer[messageRendererKey]) {
  5432. // const messageRendererData = messageRenderer[messageRendererKey];
  5433. // if (messageRendererData && 'timestampUsec' in messageRendererData) {
  5434. // return messageRendererData.timestampUsec
  5435. // }
  5436. // }
  5437. // }
  5438. // }
  5439. // return null;
  5440. // }
  5441.  
  5442. const onRegistryReadyForDOMOperations = () => {
  5443.  
  5444. let firstCheckedOnYtInit = false;
  5445.  
  5446. const assertorURL = () => assertor(() => location.pathname.startsWith('/live_chat') && (location.search.indexOf('continuation=') > 0 || location.search.indexOf('v=') > 0));
  5447.  
  5448. const mightFirstCheckOnYtInit = () => {
  5449. if (firstCheckedOnYtInit) return;
  5450. firstCheckedOnYtInit = true;
  5451.  
  5452. if (!document.body || !document.head) return;
  5453. if (!assertorURL()) return;
  5454.  
  5455. addCssManaged();
  5456.  
  5457. let efsContainer = document.getElementById('elzm-fonts-yk75g');
  5458. if (efsContainer && efsContainer.parentNode !== document.body) {
  5459. document.body.appendChild(efsContainer);
  5460. }
  5461.  
  5462. };
  5463.  
  5464. if (!assertorURL()) return;
  5465. // if (!assertor(() => document.getElementById('yt-masthead') === null)) return;
  5466.  
  5467.  
  5468. const { weakWrap } = (() => {
  5469.  
  5470.  
  5471. // const tickerFuncProps = new Set([
  5472. // 'animateShowStats', 'animateHideStats', // updateStatsBarAndMaybeShowAnimationRevised
  5473. // 'collapse', // slideDownNoSelfLeakage
  5474. // 'requestRemoval', // collapseNoSelfLeakage
  5475. // 'setContainerWidth', 'get', 'set', // deletedChangedNoSelfLeakage
  5476. // 'computeAriaLabel', //dataChanged
  5477. // 'startCountdown', // dataChanged [in case]
  5478. // ]);
  5479.  
  5480. // const tickerTags = new Set([
  5481. // "yt-live-chat-ticker-renderer",
  5482. // "yt-live-chat-ticker-paid-message-item-renderer",
  5483. // "yt-live-chat-ticker-paid-sticker-item-renderer",
  5484. // "yt-live-chat-ticker-sponsor-item-renderer"
  5485. // ]);
  5486.  
  5487. // const emptySet = new Set();
  5488.  
  5489.  
  5490.  
  5491. // const tickerFuncPropsFn = (cnt) => {
  5492.  
  5493. // const is = `${cnt.is}`;
  5494.  
  5495. // if (tickerTags.has(is)) {
  5496. // let flg = 0;
  5497. // if (cnt.get && cnt.set) flg |= 1;
  5498. // if (cnt.setContainerWidth && cnt.collapse && cnt.requestRemoval) flg |= 2;
  5499. // if (cnt.animateShowStats && cnt.animateHideStats) flg |= 4;
  5500. // if (cnt.startCountdown) flg |= 8;
  5501. // console.log(`DEBUG flag_6877 = ${flg}`, is);
  5502. // // DEBUG flag_6877 = 15 yt-live-chat-ticker-paid-message-item-renderer
  5503. // // DEBUG flag_6877 = 11 yt-live-chat-ticker-sponsor-item-renderer
  5504. // return tickerFuncProps;
  5505. // }
  5506.  
  5507. // return emptySet;
  5508.  
  5509.  
  5510. // }
  5511.  
  5512.  
  5513. // const smb = Symbol();
  5514. const vmb = 'dtz02' // Symbol(); // return kThis for thisArg
  5515. const vmc = 'dtz04' // Symbol(); // whether it is proxied fn
  5516. const vmd = 'dtz08' // Symbol(); // self fn proxy (fn--fn)
  5517.  
  5518.  
  5519.  
  5520.  
  5521. const thisConversionFn = (thisArg) => {
  5522. if (!thisArg) return null;
  5523. const kThis = thisArg[vmb];
  5524. if (kThis) {
  5525. const ref = kThis.ref;
  5526. return (ref ? kRef(ref) : null) || null;
  5527. }
  5528. return thisArg;
  5529. }
  5530.  
  5531. const pFnHandler2 = {
  5532. get(target, prop) {
  5533. if (prop === vmc) return target;
  5534. return Reflect.get(target, prop);
  5535. },
  5536. apply(target, thisArg, argumentsList) {
  5537. thisArg = thisConversionFn(thisArg);
  5538. if (thisArg) return Reflect.apply(target, thisArg, argumentsList);
  5539. }
  5540. }
  5541.  
  5542.  
  5543. const proxySelfHandler = {
  5544. get(target, prop) {
  5545. if(prop === vmb) return target;
  5546. const ref = target.ref;
  5547. const cnt = kRef(ref);
  5548. if (!cnt) return;
  5549. if (typeof cnt[prop] === 'function' && !cnt[prop][vmc] && !cnt[prop][vmb]) {
  5550. if (!cnt[prop][vmd]) cnt[prop][vmd] = new Proxy(cnt[prop], pFnHandler2);
  5551. return cnt[prop][vmd];
  5552. }
  5553. return cnt[prop];
  5554. },
  5555. set(target, prop, value) {
  5556. const cnt = kRef(target.ref);
  5557. if (!cnt) return true;
  5558. if(value && (value[vmc] || value[vmb])){
  5559. cnt[prop] = value[vmc] || thisConversionFn(value);
  5560. return true;
  5561. }
  5562. cnt[prop] = value;
  5563. return true;
  5564. }
  5565. };
  5566.  
  5567. const weakWrap = (thisArg) => {
  5568. thisArg = thisConversionFn(thisArg);
  5569. if (!thisArg) {
  5570. console.error('thisArg is not found');
  5571. return null;
  5572. }
  5573. return new Proxy({ ref: mWeakRef(thisArg) }, proxySelfHandler);
  5574. }
  5575.  
  5576.  
  5577.  
  5578.  
  5579.  
  5580.  
  5581. if (!window.getComputedStyle533 && typeof window.getComputedStyle === 'function') {
  5582. window.getComputedStyle533 = window.getComputedStyle;
  5583. window.getComputedStyle = function (a, ...args) {
  5584. a = thisConversionFn(a);
  5585. if (a) {
  5586. return getComputedStyle533(a, ...args);
  5587. }
  5588. return null;
  5589. }
  5590. }
  5591.  
  5592.  
  5593.  
  5594.  
  5595.  
  5596.  
  5597.  
  5598. // const fnProxySelf = function (...args) {
  5599. // const cnt = kRef(this.ref);
  5600. // if (cnt) {
  5601. // return cnt[this.prop](...args); // might throw error
  5602. // }
  5603. // }
  5604. // const proxySelfHandler = {
  5605. // get(target, prop) {
  5606. // const ref = target.ref;
  5607. // const cnt = kRef(ref);
  5608. // if (!cnt) return;
  5609. // if (prop === 'dtz06') return 1;
  5610. // if (typeof cnt[prop] === 'function') {
  5611. // if (!target.funcs.has(prop)) {
  5612. // console.warn(`proxy get to function | prop: ${prop} | is: ${cnt.is}`);
  5613. // }
  5614. // if (!target[`$$${prop}$$`]) target[`$$${prop}$$`] = fnProxySelf.bind({ prop, ref });
  5615. // return target[`$$${prop}$$`];
  5616. // }
  5617. // return cnt[prop];
  5618. // },
  5619. // set(target, prop, value) {
  5620. // const cnt = kRef(target.ref);
  5621. // if (!cnt) return true;
  5622. // if (typeof value === 'function') {
  5623. // console.warn(`proxy set to function | prop: ${prop} | is: ${cnt.is}`);
  5624. // cnt[prop] = value;
  5625. // return true;
  5626. // }
  5627. // cnt[prop] = value;
  5628. // return true;
  5629. // }
  5630. // };
  5631.  
  5632. // return { tickerFuncPropsFn, proxySelfHandler }
  5633.  
  5634. return {weakWrap}
  5635. })();
  5636.  
  5637.  
  5638.  
  5639. if (document.documentElement && document.head) {
  5640. addCssManaged();
  5641. }
  5642. // console.log(document.body===null)
  5643.  
  5644. const preprocessChatLiveActionsMap = new WeakSet();
  5645.  
  5646. const toLAObj=(aItem)=>{
  5647.  
  5648. if (!aItem || typeof aItem !== 'object') return false;
  5649. const key = firstObjectKey(aItem); // addLiveChatTickerItemAction
  5650. if (!key) return false;
  5651. let obj = aItem[key];
  5652. if (!obj || typeof obj !== 'object') return false;
  5653.  
  5654. if (typeof (obj.item || 0) == 'object' && firstObjectKey(obj) === 'item') {
  5655. obj = obj.item;
  5656. const key = firstObjectKey(obj);
  5657. if (key) {
  5658. obj = obj[key];
  5659. }
  5660. }
  5661.  
  5662. return obj;
  5663.  
  5664. };
  5665.  
  5666. const groupsK38=[];
  5667.  
  5668.  
  5669. function intervalsOverlap(a1, a2, b1, b2) {
  5670. // Order the intervals without using Math functions
  5671. var startA = a1 <= a2 ? a1 : a2;
  5672. var endA = a1 <= a2 ? a2 : a1;
  5673.  
  5674. var startB = b1 <= b2 ? b1 : b2;
  5675. var endB = b1 <= b2 ? b2 : b1;
  5676.  
  5677. // Check for overlap
  5678. return endA >= startB && endB >= startA;
  5679. }
  5680.  
  5681.  
  5682.  
  5683. const insertIntoSortedArrayA28 = (arr, val) => {
  5684. let left = 0;
  5685. const n = arr.length;
  5686. let right = n;
  5687.  
  5688. // Binary search to find the correct insertion index:
  5689. // We want the first index where arr[index][2] >= val[2].
  5690. while (left < right) {
  5691. const mid = (left + right) >>> 1;
  5692. if (arr[mid][0] < val[0]) {
  5693. left = mid + 1;
  5694. } else {
  5695. right = mid;
  5696. }
  5697. }
  5698.  
  5699. // 'left' is now the insertion index
  5700. left === n ? arr.push(val): arr.splice(left, 0, val);
  5701. };
  5702.  
  5703. function removeNullsInPlace(arr, startI = 0) {
  5704. let insertPos = startI;
  5705. for (let i = startI; i < arr.length; i++) {
  5706. if (arr[i] !== null) {
  5707. insertPos !== i && (arr[insertPos] = arr[i]);
  5708. insertPos++;
  5709. }
  5710. }
  5711. arr.length = insertPos; // Remove the trailing nulls.
  5712. }
  5713.  
  5714. let fir = 0;
  5715.  
  5716. const limitAddition = (a, b) => {
  5717. // Number.MAX_SAFE_INTEGER = 9007199254740991
  5718. // formula = Math.round((a + b) / (1 + a * b / k / k))
  5719. // avoid a*b > 9007199254740991
  5720. // say a, b <= 94800000
  5721. // Consider (x+x) - (x+x) / (1 + x^2 / k^2) < 0.49
  5722. // x < 130095
  5723.  
  5724. const w = 130095;
  5725. if (a < w && b < w) return a + b;
  5726. const k2 = 94800000 * 94800000;
  5727. return Math.round((a + b) / (1 + (a * b) / k2));
  5728. }
  5729.  
  5730. const preprocessChatLiveActions = (arr) =>{
  5731.  
  5732. if (!fir) {
  5733.  
  5734. if (!__LCRInjection__) {
  5735. console.error('[yt-chat] preprocessChatLiveActions might fail because of no __LCRInjection__');
  5736. }
  5737.  
  5738. DEBUG_preprocessChatLiveActions && console.log('[yt-chat-debug] 5990', 'preprocessChatLiveActions', arr)
  5739.  
  5740. DEBUG_preprocessChatLiveActions && console.log('[yt-chat-debug] 5991', document.querySelectorAll('yt-live-chat-ticker-renderer #ticker-items [class]').length)
  5741.  
  5742. fir = 1;
  5743. // debugger;
  5744. }
  5745.  
  5746. if (!arr || !arr.length) return arr;
  5747.  
  5748. if (preprocessChatLiveActionsMap.has(arr)) return arr;
  5749. preprocessChatLiveActionsMap.add(arr);
  5750.  
  5751.  
  5752.  
  5753. const ct = Date.now();
  5754.  
  5755. let groups_ = null;
  5756.  
  5757. // console.log(1237005);
  5758. // const conversionMap = new WeakMap();
  5759.  
  5760. const additionalInfo = new WeakMap();
  5761.  
  5762. // const adjustmentMap = new Map();
  5763.  
  5764. if (FIX_TIMESTAMP_FOR_REPLAY) {
  5765.  
  5766. // console.log('group02331')
  5767. // console.time('FIX_TIMESTAMP_FOR_REPLAY')
  5768.  
  5769. // const stack = new Array(arr.length);
  5770. // let stackL = 0;
  5771.  
  5772. // const arrHash = new Array(arr.length);
  5773.  
  5774.  
  5775. const groups = groupsK38;
  5776. // const delta = 2.0; // head-to-tail + 0.5 + 0.5 = 1.0 -> symmetric -> 1.0 * 2 = 2.0
  5777. // (2)
  5778. // (1.5, 2.5)
  5779. // (1.51, 2.49)
  5780. // -> (1.01, 2.01) , (1.99, 2.99)
  5781. // 2.99 - 1.01 = 1.98 -> 2
  5782.  
  5783.  
  5784.  
  5785. const pushToGroup = (t0mu)=>{
  5786.  
  5787. const t0auDv = t0mu - 1e6; // t0buDv - t0auDv = 2e6
  5788. const t0buDv = t0mu + 1e6;
  5789. // const t0auEv = t0mu - 2e6;
  5790. // const t0buEv = t0mu + 2e6;
  5791.  
  5792. let groupK = false;
  5793. // let m = -1;
  5794. // let q= 0;
  5795. //const qq =true;
  5796. //qq && console.log('-------')
  5797.  
  5798. let lastRight = null;
  5799. let lastK = null;
  5800. let deletedStartIndex = -1;
  5801.  
  5802. for (let k = 0, kl = groups.length; k < kl; k++) {
  5803.  
  5804. const group = groups[k];
  5805. const [groupStart, groupEnd, gCount] = group;
  5806. //qq && console.log(`-- ${k} ----- ${groupMid} : [${groupStart},${groupEnd}] || C1 = ${t0buEv < groupMid} || C2 = ${t0auEv > groupMid}`);
  5807.  
  5808. // if (t0bsEv < groupMid) continue; // if(t0m + 1.0 < groupMid - 1.0) continue;
  5809. // if (m < 0) m = k;
  5810. // if (t0asEv > groupMid){
  5811. // continue; // if(t0m - 1.0 > groupMid + 1.0) break;
  5812. // }
  5813.  
  5814.  
  5815. // if (m < 0) m = k;
  5816.  
  5817. if (lastRight > groupStart) {
  5818. if (!groupK) {
  5819. // just in case sth wrong
  5820. console.warn('logic ERROR');
  5821. groups[k] = null;
  5822. if(deletedStartIndex < 0) deletedStartIndex = k;
  5823. break;
  5824. } else {
  5825.  
  5826.  
  5827. // GroupA: N_a' = N_a + n_e{1} ; Note n_e is the only way to shift right to cause " (lastRight > groupStart) "
  5828. // GroupB: N_b
  5829. // Merge Group (A) = N_a' + N_b
  5830.  
  5831. // without entry moditification, no overlap
  5832. // this must be due to entry moditifcation
  5833. // entry is already count. so can be skipped after merging
  5834.  
  5835. // for merging, groupA will move to right side but left than groupB, so no overlap to groupC
  5836.  
  5837. const group = groups[lastK];
  5838. const newN = limitAddition(group[2], gCount);
  5839.  
  5840. const factor = gCount / (group[2] + gCount);
  5841.  
  5842. // group[0] = (group[0] * group[2] + groupStart * gCount) / (group[2] + gCount)
  5843. group[0] += (groupStart - group[0]) * factor;
  5844.  
  5845. // group[1] = lastRight = (group[1] * group[2] + groupEnd * gCount) / (group[2] + gCount)
  5846. group[1] += (groupEnd - group[1]) * factor;
  5847.  
  5848. group[2] = newN;
  5849. // no change of lastK
  5850. groups[k] = null;
  5851. if(deletedStartIndex < 0) deletedStartIndex = k;
  5852. continue;
  5853. }
  5854. }
  5855.  
  5856. const minGroupStart = lastRight; // all groupStart, groupEnd >= minGroupStart for k, k+1, ...
  5857. if (t0buDv < minGroupStart) {
  5858. // no overlapping could be possible
  5859. break;
  5860. }
  5861.  
  5862. if (intervalsOverlap(t0auDv, t0buDv, groupStart, groupEnd)) {
  5863.  
  5864. groupK = true;
  5865.  
  5866. // if (t0auDv > groupStart) group[0] = t0auDv;
  5867. // else if (t0buDv < groupEnd) group[1] = t0buDv;
  5868.  
  5869. // const newStart = (groupStart * gCount + t0auDv) / (gCount + 1);
  5870. const newStart = groupStart + (t0auDv - groupStart) * 1 / (gCount + 1);
  5871.  
  5872. if (newStart < lastRight) {
  5873. // n_e{1} will make N_b shift left
  5874.  
  5875. // GroupA: N_a
  5876. // GroupB: N_b
  5877. // Merge Group (A) = N_a + N_b + n_e{1}
  5878.  
  5879. const group = groups[lastK];
  5880. const newN = limitAddition(limitAddition(group[2], gCount), 1);
  5881. const f1 = gCount / (group[2] + gCount + 1);
  5882. const f2 = 1 / (group[2] + gCount + 1);
  5883.  
  5884. // group[0] = (group[0] * group[2] + groupStart * gCount + t0auDv) / (group[2] + gCount + 1);
  5885. group[0] += (groupStart - group[0]) * f1 + (t0auDv - group[0]) * f2;
  5886.  
  5887. // group[1] = lastRight = (group[1] * group[2] + groupEnd * gCount + t0buDv) / (group[2] + gCount + 1)
  5888. lastRight = (group[1] += (groupEnd - group[1]) * f1 + (t0buDv - group[1]) * f2);
  5889.  
  5890. group[2] = newN;
  5891. // no change of lastK
  5892. groups[k] = null;
  5893. if(deletedStartIndex < 0) deletedStartIndex = k;
  5894. continue;
  5895.  
  5896. } else {
  5897. // n_e{1} will make N_b shift either left or right
  5898.  
  5899. // GroupT: N_t
  5900. // Group (T) = N_t + n_e{1}
  5901.  
  5902. const newN = limitAddition(gCount, 1);
  5903.  
  5904. group[0] = newStart;
  5905. // group[1] = lastRight = (groupEnd * gCount + t0buDv) / (gCount + 1);
  5906. group[1] = lastRight = groupEnd + (t0buDv - groupEnd) * 1 / (gCount + 1);
  5907. group[2] = newN;
  5908.  
  5909. lastK = k;
  5910.  
  5911. // (t0asDv > groupStart) && (t0bsDv < groupEnd) means full containement
  5912. // however, group size is smaller than or equal to t0width
  5913. }
  5914.  
  5915.  
  5916. } else {
  5917. // just update record for next iteration
  5918.  
  5919. lastRight = groupEnd;
  5920. lastK = k;
  5921. }
  5922.  
  5923.  
  5924.  
  5925. }
  5926.  
  5927. if (deletedStartIndex >= 0) {
  5928. // rarely used
  5929.  
  5930. removeNullsInPlace(groups, deletedStartIndex);
  5931.  
  5932. }
  5933. if (!groupK) {
  5934. // groups.push([t0auDv, t0buDv, 1]);
  5935. insertIntoSortedArrayA28(groups, [t0auDv, t0buDv, 1]);
  5936. // insertIntoSortedArrayA27(groups, [t0auDv, t0buDv, t0mu]);
  5937. }
  5938.  
  5939.  
  5940. }
  5941.  
  5942. let autoTimeStampFrameChoose = 0;
  5943.  
  5944. // console.log('group02332')
  5945. for (let j = 0, l = arr.length; j < l; j++) {
  5946. const aItem = arr[j];
  5947.  
  5948. const obj = toLAObj(aItem);
  5949. if (obj === false) continue;
  5950.  
  5951. let p = obj.timestampText;
  5952. let p2, p3=null, p4a=null, p4b=null;
  5953. if(p&&p.simpleText ) p2 = p.simpleText;
  5954.  
  5955. let q = obj.timestampUsec ;
  5956. let q2;
  5957.  
  5958. if(q && +q > 1110553200000000) q2 = +q;
  5959. if (q2 > 0 && !autoTimeStampFrameChoose) {
  5960. const q2cc = Math.round(q2 / 1e6);
  5961. autoTimeStampFrameChoose = q2cc - (q2cc % 10000000);
  5962. if (q2cc - autoTimeStampFrameChoose < 2000000) autoTimeStampFrameChoose -= 10000000;
  5963. // around 10day range
  5964. // exceeded ~10day -> above 10000000
  5965. }
  5966.  
  5967. // console.log('group02333', p2, q2)
  5968. // console.log(3775, q2/1e6, autoTimeStampFrameChoose)
  5969.  
  5970. if(p2 && q2){
  5971.  
  5972. let m;
  5973.  
  5974. if (m = /^\s*(-?)(\d+):(\d+)\s*$/.exec(p2)) {
  5975. let c0z = m[1] ? -1 : 1;
  5976. let c1 = (+m[2]);
  5977. let c2 = (+m[3]);
  5978. if (c0z > 0 && c1 >= 0 && c2 >= 0) {
  5979.  
  5980. p3 = c1 * 60 + c2;
  5981. } else if (c0z < 0 && c1 >= 0 && c2 >= 0) {
  5982. // -4:43 -> -4:42 -> -4:41 ... -> -4:01 -> -4:00 -> -3:59 -> -3:58
  5983. // -> ... -1:01 -> -1:00 -> -0:59 -> ... -> -0:02 -> -0:01 -> -0:00 -> 0:00 -> ...
  5984.  
  5985. p3 = (-c1 * 60) + (-c2);
  5986.  
  5987. }
  5988. if (p3 !== null) {
  5989. // 0:14 -> 13.5s ~ 14.4999s -> [13.5, 14.5)
  5990. p4a = p3 - 0.5;
  5991. p4b = p3 + 0.5;
  5992. }
  5993. } else if (m = /^\s*(-?)(\d+):(\d+):(\d+)\s*$/.exec(p2)) {
  5994.  
  5995. let c0z = m[1] ? -1 : 1;
  5996. let c1 = (+m[2]);
  5997. let c2 = (+m[3]);
  5998. let c3 = (+m[4]);
  5999.  
  6000.  
  6001.  
  6002. if (c0z > 0 && c1 >= 0 && c2 >= 0 && c3 >= 0) {
  6003.  
  6004. p3 = c1 * 60 * 60 + c2 * 60 + c3;
  6005. } else if (c0z < 0 && c1 >= 0 && c2 >= 0 && c3>=0) {
  6006. // -4:43 -> -4:42 -> -4:41 ... -> -4:01 -> -4:00 -> -3:59 -> -3:58
  6007. // -> ... -1:01 -> -1:00 -> -0:59 -> ... -> -0:02 -> -0:01 -> -0:00 -> 0:00 -> ...
  6008.  
  6009. p3 = (-c1 * 60 * 60) + (-c2 * 60) + (-c3);
  6010.  
  6011. }
  6012. if (p3 !== null) {
  6013. // 0:14 -> 13.5s ~ 14.4999s -> [13.5, 14.5)
  6014. p4a = p3 - 0.5;
  6015. p4b = p3 + 0.5;
  6016. }
  6017.  
  6018.  
  6019. }
  6020.  
  6021. }
  6022.  
  6023. if(p4a !== null && p4b !== null && q2 > 0){
  6024.  
  6025. // q2_us = t0_us + dt_us
  6026. // p4a_us <= dt_us < p4b_us
  6027. let p4au = p4a * 1e6;
  6028. let p4bu = p4b * 1e6;
  6029.  
  6030. // p4a_us <= q2_us - t0_us < p4b_us
  6031.  
  6032.  
  6033. // p4a_us - q2_us <= - t0_us < p4b_us - q2_us
  6034.  
  6035. // -p4a_us + q2_us >= t0_us > -p4b_us + q2_us
  6036.  
  6037.  
  6038. let t0au = q2 - p4bu; // q2_us - p4b_us
  6039. let t0bu = q2 - p4au; // q2_us - p4a_us
  6040.  
  6041. // t0 (t0au, t0bu]
  6042.  
  6043. const t0mu = (t0au+t0bu)/2;
  6044.  
  6045. // stack[stackL++]=({
  6046. // id: obj.id,
  6047. // idx: j,
  6048. // p2,
  6049. // // q2s : (q2/ 1e6 - autoTimeStampFrameChoose).toFixed(2),
  6050. // p3,
  6051. // /*
  6052. // timestampText: obj.timestampText,
  6053. // timestampUsec: obj.timestampUsec, // us = 1/1000 ms
  6054. // q2,
  6055. // p4a,
  6056. // p4b,
  6057. // */
  6058. // q2s: +(q2 / 1e6 - autoTimeStampFrameChoose).toFixed(2),
  6059. // t0as: +(t0au / 1e6 - autoTimeStampFrameChoose).toFixed(2),
  6060. // t0bs: +(t0bu /1e6 - autoTimeStampFrameChoose).toFixed(2),
  6061.  
  6062. // t0au,
  6063. // t0bu,
  6064. // t0mu
  6065. // });
  6066.  
  6067. // console.log('group02334')
  6068. let wobj = additionalInfo.get(obj);
  6069. if(!wobj) additionalInfo.set(obj, wobj = {});
  6070.  
  6071. wobj.timestampUsecOriginal = q2;
  6072. // wobj.timestampUsecAdjusted = q2;
  6073. wobj.t0au = t0au;
  6074. wobj.t0bu = t0bu;
  6075. wobj.t0mu = t0mu;
  6076.  
  6077. // arrHash[j] = {
  6078. // index: j,
  6079. // id: obj.id,
  6080. // timestampUsec: q2,
  6081. // t0au,
  6082. // t0bu,
  6083. // t0mu
  6084. // };
  6085.  
  6086. pushToGroup(t0mu);
  6087.  
  6088. // console.log('group02335')
  6089. // console.log('grouping', `${obj.id}.${obj.timestampUsec}`);
  6090.  
  6091. // timestamp (q2) can be incorrect.
  6092.  
  6093. // https://www.youtube.com/watch?v=IKKar5SS29E
  6094. // ChwKGkNQZUxfXzZxLS04Q0ZXNGxyUVlkODZrQzNR
  6095.  
  6096. /*
  6097.  
  6098.  
  6099. [
  6100. {
  6101. "id": "ChwKGkNNWHZqXy1xLS04Q0ZXNGxyUVlkODZrQzNR",
  6102. "p2": "2:04",
  6103. "p3": 124,
  6104. "t0as": 8320733.78,
  6105. "t0bs": 8320734.78
  6106. },
  6107. {
  6108. "id": "ChwKGkNQZUxfXzZxLS04Q0ZXNGxyUVlkODZrQzNR",
  6109. "p2": "2:04",
  6110. "p3": 124,
  6111. "t0as": 8320898.89, // incorrect
  6112. "t0bs": 8320899.89
  6113. }
  6114. ]
  6115.  
  6116.  
  6117. */
  6118.  
  6119. }
  6120.  
  6121.  
  6122.  
  6123.  
  6124. }
  6125.  
  6126. // stack.length = stackL;
  6127.  
  6128.  
  6129. groups_ = groups;
  6130. // console.log('groups', groups)
  6131.  
  6132. }
  6133.  
  6134. // console.log(1237006);
  6135.  
  6136. // console.log(5592,1)
  6137. const groupMids = FIX_TIMESTAMP_FOR_REPLAY ? groups_.map(group=>{
  6138.  
  6139. const [groupStart, groupEnd ] = group;
  6140. const groupMid = (groupStart+groupEnd)/2;
  6141. return groupMid;
  6142. }): null;
  6143. // console.log('groupMids', groupMids)
  6144.  
  6145.  
  6146. // console.log(1237007);
  6147.  
  6148. const adjustTimestampFn = (obj) => {
  6149.  
  6150. const groupCount = groupMids.length;
  6151.  
  6152. if (groupCount < 1) return null;
  6153.  
  6154. // const obj = toLAObj(aItem);
  6155. if (obj === false) return null;
  6156.  
  6157. const wobj = additionalInfo.get(obj);
  6158. if (!wobj) return null;
  6159.  
  6160. const { t0mu } = wobj;
  6161.  
  6162.  
  6163. let i0 = 0;
  6164.  
  6165. if (groupCount >= 3) {
  6166. // For larger arrays, use binary search.
  6167. let low = 0;
  6168. let high = groupCount - 1;
  6169.  
  6170. while (high - low > 1) {
  6171. const mid = (low + high) >>> 1;
  6172. if (groupMids[mid] >= t0mu) {
  6173. high = mid;
  6174. } else {
  6175. low = mid;
  6176. }
  6177. }
  6178. i0 = low;
  6179.  
  6180. }
  6181.  
  6182. let upperDiff = -1;
  6183. let lowerDiff = -1;
  6184. for (let i = i0; i < groupCount; i++) {
  6185. const y = groupMids[i] - t0mu;
  6186. if (y >= 0) {
  6187. upperDiff = y; // >=0, entry > value is found
  6188. break;
  6189. }
  6190. lowerDiff = -y; // >0, cache
  6191. }
  6192.  
  6193.  
  6194. const d1 = upperDiff;
  6195. const d2 = lowerDiff;
  6196.  
  6197.  
  6198. // console.log(5381, index1 ,d1, index2 , d2);
  6199.  
  6200. if (d1 >= 0 && ((d2 < 0) || (d1 <= d2))) {
  6201. wobj.chosenT0 = t0mu + d1; // groupMids[index1];
  6202. } else if (d2 >= 0 && ((d1 < 0) || (d2 <= d1))) {
  6203. wobj.chosenT0 = t0mu - d2; // groupMids[index2];
  6204. } else {
  6205. console.warn('logic error');
  6206. return null;
  6207. }
  6208.  
  6209. const adjusted = wobj.timestampUsecOriginal - wobj.chosenT0;
  6210.  
  6211. wobj.timestampUsecAdjusted = adjusted + 1110553200000000;
  6212.  
  6213. // console.log('adjusted', `${obj.id}.${obj.timestampUsec}`, wobj.timestampUsecOriginal - wobj.chosenT0);
  6214.  
  6215. // adjustmentMap.set(`${obj.id}.${obj.timestampUsec}`, wobj.timestampUsecOriginal - wobj.chosenT0);
  6216.  
  6217. return adjusted;
  6218.  
  6219.  
  6220.  
  6221. };
  6222.  
  6223.  
  6224. // console.log(5592,2)
  6225. // console.log(1237008);
  6226. // if (FIX_TIMESTAMP_FOR_REPLAY) {
  6227.  
  6228.  
  6229. // try{
  6230.  
  6231. // // console.log('groupmid',groupMids, groups);
  6232.  
  6233. // for(let j = 0; j< arr.length;j++){
  6234. // if(groupMids.length<1) break;
  6235.  
  6236. // const aItem = arr[j];
  6237. // const obj = toLAObj(aItem);
  6238. // if (obj === false) continue;
  6239.  
  6240. // const wobj = additionalInfo.get(obj);
  6241. // if(!wobj) continue;
  6242.  
  6243. // // wobj.timestampUsecOriginal = q2;
  6244. // // wobj.timestampUsecAdjusted = q2;
  6245. // // wobj.t0au = t0au;
  6246. // // wobj.t0bu = t0bu;
  6247. // // wobj.t0mu = t0mu;
  6248.  
  6249. // const {t0au, t0bu, t0mu} = wobj;
  6250.  
  6251. // let upper = -1;
  6252.  
  6253. // for(let i = 0; i <groupMids.length;i++){
  6254. // const groupMid = groupMids[i];
  6255. // if(groupMid>= t0mu){
  6256. // upper = i;
  6257. // break;
  6258. // }
  6259. // }
  6260. // let index1, index2;
  6261. // if(upper>-1){
  6262. // index1 = upper-1;
  6263. // index2 = upper;
  6264. // }else{
  6265. // index1 = groups.length-1;
  6266. // index2 = -1;
  6267. // }
  6268. // let d1 = null;
  6269. // if(index1 >=0){
  6270. // d1 = Math.abs(groupMids[index1] - t0mu);
  6271. // }
  6272.  
  6273. // let d2 = null;
  6274. // if(index2 >=0){
  6275. // d2 = Math.abs(groupMids[index2] - t0mu);
  6276. // }
  6277. // // console.log(5381, index1 ,d1, index2 , d2);
  6278. // if(d1 >= 0 && ((d1 <= d2) || (d2 === null)) ){
  6279.  
  6280. // wobj.chosenT0 = groupMids[index1];
  6281. // } else if(d2 >= 0 && ((d2 <= d1) || (d1 === null))){
  6282. // wobj.chosenT0 = groupMids[index2];
  6283. // } else {
  6284. // console.warn('logic error');
  6285. // continue;
  6286. // }
  6287.  
  6288. // wobj.timestampUsecAdjusted = wobj.timestampUsecOriginal - wobj.chosenT0 + 1110553200000000;
  6289.  
  6290. // console.log('adjusted', `${obj.id}.${obj.timestampUsec}`, wobj.timestampUsecOriginal - wobj.chosenT0);
  6291.  
  6292. // adjustmentMap.set(`${obj.id}.${obj.timestampUsec}`, wobj.timestampUsecOriginal - wobj.chosenT0);
  6293. // // conversionMap.set(obj, arrHash[j].adjustedTime);
  6294.  
  6295. // // console.log(5382, index, id, t0mu, arrHash[j].adjustedT0, arrHash[j].timestampUsec, arrHash[j].adjustedTime);
  6296.  
  6297. // }
  6298.  
  6299.  
  6300. // }catch(e){
  6301. // console.warn(e);
  6302. // }
  6303.  
  6304.  
  6305.  
  6306.  
  6307.  
  6308. // // if(stack.length > 1){
  6309. // // stack.sort((a,b)=>{
  6310. // // return a.t0mu - b.t0mu
  6311. // // });
  6312. // // // small to large
  6313. // // // console.log(34588, stack.map(e=>e.t0as))
  6314. // // }
  6315.  
  6316. // // grouping
  6317.  
  6318.  
  6319.  
  6320.  
  6321. // // if (stack.length > 0) {
  6322.  
  6323. // // try {
  6324.  
  6325. // // for (let j = 0, l = stack.length; j < l; j++) {
  6326. // // pushToGroup(stack[j].t0mu);
  6327.  
  6328. // // }
  6329.  
  6330. // // }catch(e){
  6331.  
  6332. // // console.warn(e)
  6333. // // }
  6334.  
  6335. // // // console.log(4882, groups.map(e=>e.slice()), stack.slice())
  6336.  
  6337. // // }
  6338.  
  6339.  
  6340.  
  6341.  
  6342. // // console.log(376, 'group', groups);
  6343.  
  6344.  
  6345. // // consolidated group
  6346. // // const consolidatedGroups = doConsolidation(groups);
  6347.  
  6348.  
  6349.  
  6350.  
  6351.  
  6352.  
  6353. // // if(stack.length > 1){
  6354.  
  6355.  
  6356. // // // // console.log(341, 'consolidatedGroups', consolidatedGroups ,groups.map(e=>{
  6357. // // // // return e.map(noTransform);
  6358. // // // // // return e.map(prettyNum);
  6359. // // // // }))
  6360.  
  6361.  
  6362. // // // console.log(344, 'groups', groups.map(e=>{
  6363. // // // return e.map(noTransform);
  6364. // // // // return e.map(prettyNum);
  6365. // // // }))
  6366.  
  6367. // // // // for(const s of stack){
  6368. // // // // for(const g of consolidatedGroups){
  6369. // // // // if(s.t0as<=g.cen && s.t0bs >=g.cen ){
  6370. // // // // s.cen = g.cen;
  6371. // // // // break;
  6372. // // // // }
  6373. // // // // }
  6374.  
  6375. // // // // }
  6376.  
  6377. // // // console.log(377, stack) // Ms
  6378.  
  6379. // // }
  6380.  
  6381.  
  6382. // // console.timeEnd('FIX_TIMESTAMP_FOR_REPLAY')
  6383.  
  6384. // }
  6385.  
  6386.  
  6387.  
  6388.  
  6389.  
  6390.  
  6391.  
  6392.  
  6393.  
  6394. // console.log(5592,5)
  6395.  
  6396.  
  6397. // console.log('preprocessChatLiveActions', arr)
  6398.  
  6399.  
  6400. const mapper = new Map();
  6401.  
  6402. // without delaying. get the time of request
  6403. // (both streaming and replay, but replay relys on progress update so background operation is suppressed)
  6404.  
  6405. for (let j = 0, l = arr.length; j < l; j++) {
  6406. const aItem = arr[j];
  6407.  
  6408. const obj = toLAObj(aItem);
  6409. if(obj === false) continue;
  6410.  
  6411. if (obj.id && !obj.__timestampActionRequest__) {
  6412. // for all item entries
  6413. obj.__timestampActionRequest__ = ct;
  6414. }
  6415.  
  6416. if (obj.id && obj.__timestampActionRequest__ > 0 && obj.durationSec > 0 && obj.fullDurationSec) {
  6417.  
  6418. // console.log(948700, obj , obj.id, (obj.fullDurationSec - obj.durationSec) * 1000)
  6419. const m = obj.__timestampActionRequest__ - (obj.fullDurationSec - obj.durationSec) * 1000;
  6420.  
  6421. // obj.__t374__ = (obj.fullDurationSec - obj.durationSec) * 1000;
  6422. // obj.__t375__ = obj.__timestampActionRequest__ - (obj.fullDurationSec - obj.durationSec) * 1000;
  6423. // console.log(5993, obj)
  6424. // obj.__orderTime__ = m;
  6425. mapper.set(aItem, m);
  6426.  
  6427.  
  6428. }
  6429.  
  6430. }
  6431.  
  6432. if (mapper.size > 1) {
  6433.  
  6434. const idxices = [];
  6435.  
  6436. // sort ticker
  6437. let mArr1 = arr.filter((aItem,idx) => {
  6438.  
  6439. if (mapper.has(aItem)) {
  6440. idxices.push(idx);
  6441. return true;
  6442. }
  6443. return false;
  6444.  
  6445. });
  6446.  
  6447.  
  6448. let mArr2 = mArr1/*.slice(0)*/.sort((a, b) => {
  6449. return mapper.get(a) - mapper.get(b);
  6450. // low index = oldest = smallest timestamp
  6451. });
  6452.  
  6453.  
  6454.  
  6455. // console.log(948701, arr.slice(0));
  6456. for(let j = 0, l=mArr1.length;j <l;j++){
  6457.  
  6458. const idx = idxices[j];
  6459. // arr[idx] = mArr1[j]
  6460. arr[idx] = mArr2[j];
  6461.  
  6462. // const obj1 = toObj(mArr1[j]);
  6463. // const obj2 = toObj(mArr2[j]);
  6464.  
  6465. // console.log(948705, idx, obj1 , obj1.id, (obj1.fullDurationSec - obj1.durationSec) * 1000, obj1.__orderTime__)
  6466.  
  6467. // console.log(948706, idx, obj2 , obj2.id, (obj2.fullDurationSec - obj2.durationSec) * 1000, obj2.__orderTime__)
  6468.  
  6469. }
  6470.  
  6471. // console.log(5994,arr)
  6472.  
  6473. // console.log(948702, arr.slice(0));
  6474. // console.log(948701, arr);
  6475. // arr = arr.map(aItem => {
  6476. // const idx = mArr1.indexOf(aItem);
  6477. // if (idx < 0) return aItem;
  6478. // return mArr2[idx];
  6479. // });
  6480. // console.log(948702, arr);
  6481.  
  6482. // mostly in order, but some not in order
  6483.  
  6484.  
  6485. // eg
  6486.  
  6487. /*
  6488.  
  6489.  
  6490. 948711 68 '1734488590715474'
  6491. 948711 69 '1734488590909853'
  6492. 948711 70 '1734488594763719'
  6493. 948711 71 '1734488602334615' <
  6494. 948711 72 '1734488602267214' <
  6495. 948711 73 '1734488602751771'
  6496. */
  6497.  
  6498. // arr.filter(aItem=>{
  6499.  
  6500. // const p = toObj(aItem);
  6501. // if(p.timestampUsec) return true;
  6502.  
  6503. // }).forEach((aItem,idx)=>{
  6504.  
  6505. // const p = toObj(aItem);
  6506. // console.log(948711, idx, p.timestampUsec);
  6507. // })
  6508.  
  6509. // return arr;
  6510.  
  6511. }
  6512.  
  6513. // console.log(1237001);
  6514.  
  6515. {
  6516.  
  6517.  
  6518. const mapper = new Map();
  6519.  
  6520.  
  6521. const idxices = [];
  6522.  
  6523.  
  6524. let mArr1 = arr.filter((aItem,idx) => {
  6525.  
  6526. const obj = toLAObj(aItem);
  6527. if (!obj) return false;
  6528.  
  6529. const baseText = obj.timestampText;
  6530. const baseTime = +obj.timestampUsec;
  6531. if (!baseTime || !baseText) return false;
  6532. // const timestampUsec = +toLAObj(aItem).timestampUsec; // +false.x = NaN
  6533. // const timestampUsec = +toLAObj(aItem).adjustedTime;
  6534.  
  6535. let timestampUsec;
  6536.  
  6537. // console.log(1237002)
  6538. if (FIX_TIMESTAMP_FOR_REPLAY) {
  6539.  
  6540. // const adjustmentTime = adjustmentMap.get(`${obj.id}.${obj.timestampUsec}`);
  6541.  
  6542. // // const wobj = additionalInfo.get(obj);
  6543.  
  6544. // // if(!wobj){
  6545. // // console.warn('FIX_TIMESTAMP_FOR_REPLAY - no wobj', obj)
  6546. // // return false;
  6547. // // }
  6548.  
  6549. // // timestampUsec = +wobj.timestampUsecAdjusted;
  6550. // if (!Number.isFinite(adjustmentTime)) {
  6551. // console.warn(`FIX_TIMESTAMP_FOR_REPLAY - no adjustmentTime for ${obj.id}.${obj.timestampUsec}`, obj, [...adjustmentMap])
  6552. // return false;
  6553. // }
  6554. // timestampUsec = adjustmentTime;
  6555.  
  6556.  
  6557. const adjustmentTime = adjustTimestampFn(obj);
  6558.  
  6559. if (!Number.isFinite(adjustmentTime)) {
  6560.  
  6561. console.warn(`FIX_TIMESTAMP_FOR_REPLAY - no adjustmentTime for ${obj.id}.${obj.timestampUsec}`, obj);
  6562. return false;
  6563. }
  6564. timestampUsec = adjustmentTime;
  6565.  
  6566.  
  6567. } else {
  6568.  
  6569. if (!Number.isFinite(baseTime)) {
  6570. console.warn(`no baseTime for ${obj.id}.${obj.timestampUsec}`, obj);
  6571.  
  6572. return false;
  6573. }
  6574. timestampUsec = baseTime;
  6575.  
  6576. }
  6577.  
  6578. // if(timestampUsec > 0){
  6579. idxices.push(idx);
  6580. mapper.set(aItem, timestampUsec)
  6581. return true;
  6582. // }
  6583. // return false;
  6584.  
  6585. });
  6586.  
  6587. if(mapper.size > 1){
  6588.  
  6589.  
  6590. // console.log(1237004)
  6591. let mArr2 = mArr1/*.slice(0)*/.sort((a, b) => {
  6592. return mapper.get(a) - mapper.get(b);
  6593. // low index = oldest = smallest timestamp
  6594. });
  6595.  
  6596.  
  6597.  
  6598. // console.log(948701, arr.slice(0));
  6599. for(let j = 0, l=mArr1.length;j <l;j++){
  6600.  
  6601. const idx = idxices[j];
  6602. arr[idx] = mArr2[j];
  6603.  
  6604. // const obj1 = toObj(mArr1[j]);
  6605. // const obj2 = toObj(mArr2[j]);
  6606.  
  6607.  
  6608. // console.log(948711, idx, obj1 === obj2, obj1, obj1.timestampUsec);
  6609. // console.log(948712, idx, obj1 === obj2, obj2, obj2.timestampUsec);
  6610. }
  6611.  
  6612. }
  6613.  
  6614.  
  6615. }
  6616.  
  6617. // console.log(1237005)
  6618.  
  6619. // console.log(378, arr);
  6620.  
  6621. return arr;
  6622.  
  6623.  
  6624. }
  6625.  
  6626. if (ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION) {
  6627.  
  6628. console.log('[yt-chat-control] ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION is used.')
  6629.  
  6630. // console.log('ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION 0001')
  6631.  
  6632. const pop078 = function () {
  6633. const r = this.pop78();
  6634.  
  6635. if (r && (r.actions || 0).length >= 1 && r.videoOffsetTimeMsec) {
  6636. for (const action of r.actions) {
  6637.  
  6638. const itemActionKey = !action ? null : 'addChatItemAction' in action ? 'addChatItemAction' : 'addLiveChatTickerItemAction' in action ? 'addLiveChatTickerItemAction' : null;
  6639. if (itemActionKey) {
  6640.  
  6641. const itemAction = action[itemActionKey];
  6642. const item = (itemAction || 0).item;
  6643. if (typeof item === 'object') {
  6644.  
  6645. const rendererKey = firstObjectKey(item);
  6646. if (rendererKey) {
  6647. const renderer = item[rendererKey];
  6648. if (renderer && typeof renderer === 'object') {
  6649. renderer.__videoOffsetTimeMsec__ = r.videoOffsetTimeMsec;
  6650. renderer.__progressAt__ = playerProgressChangedArg1;
  6651.  
  6652. // console.log(48117006)
  6653. }
  6654.  
  6655. }
  6656.  
  6657. }
  6658. }
  6659. }
  6660. }
  6661. return r;
  6662. }
  6663.  
  6664.  
  6665.  
  6666. const replayQueueProxyHandler = {
  6667. get(target, prop, receiver) {
  6668. if (prop === 'qe3') return 1;
  6669. const v = target[prop];
  6670. if (prop === 'front_') {
  6671. if (v && typeof v.length === 'number') {
  6672. if (!v.pop78) {
  6673. v.pop78 = v.pop;
  6674. v.pop = pop078;
  6675. }
  6676. }
  6677. }
  6678. return v;
  6679. }
  6680. };
  6681.  
  6682. // lcrFn2 will run twice to ensure the method is successfully injected.
  6683. const lcrFn2 = (lcrDummy)=>{
  6684. // make minimal function overhead by pre-defining all possible outside.
  6685.  
  6686. const tag = "yt-live-chat-renderer"
  6687. const dummy = lcrDummy;
  6688.  
  6689. const cProto = getProto(dummy);
  6690. if (!cProto || !cProto.attached) {
  6691. console.warn(`proto.attached for ${tag} is unavailable.`);
  6692. return;
  6693. }
  6694.  
  6695. // mightFirstCheckOnYtInit();
  6696. // groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-renderer hacks");
  6697. // console.log("[Begin]");
  6698.  
  6699.  
  6700. if (typeof cProto.playerProgressChanged_ === 'function' && !cProto.playerProgressChanged32_) {
  6701.  
  6702. cProto.playerProgressChanged32_ = cProto.playerProgressChanged_;
  6703.  
  6704.  
  6705. cProto.playerProgressChanged_ = function (a, b, c) {
  6706. // console.log(48117005)
  6707. if (a === 0) a = arguments[0] = Number.MIN_VALUE; // avoid issue dealing with zero value
  6708. playerProgressChangedArg1 = a;
  6709. playerProgressChangedArg2 = b;
  6710. playerProgressChangedArg3 = c;
  6711. const replayBuffer_ = this.replayBuffer_;
  6712. if (replayBuffer_) {
  6713. const replayQueue = replayBuffer_.replayQueue
  6714. if (replayQueue && typeof replayQueue === 'object' && !replayQueue.qe3) {
  6715. replayBuffer_.replayQueue = new Proxy(replayBuffer_.replayQueue, replayQueueProxyHandler);
  6716. }
  6717. }
  6718. Promise.resolve().then(updateTickerCurrentTime);
  6719. return this.playerProgressChanged32_.apply(this, arguments);
  6720. };
  6721.  
  6722. }
  6723.  
  6724. // console.log("[End]");
  6725. // groupEnd();
  6726.  
  6727.  
  6728. };
  6729. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  6730.  
  6731.  
  6732. // console.log('ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION 0002')
  6733.  
  6734. // getLCRDummy() must be called for injection
  6735. getLCRDummy().then(lcrFn2);
  6736.  
  6737. }
  6738.  
  6739. const stackDM = (()=>{
  6740.  
  6741. let cm, stack, mo;
  6742.  
  6743. let firstRun = ()=>{
  6744. cm = mockCommentElement(document.createComment('1'));
  6745. stack = new Set();
  6746. mo = new MutationObserver(()=>{
  6747. const stack_ = stack;
  6748. stack = new Set();
  6749. // for(const value of stack_){
  6750. // Promise.resolve(value).then(f=>f());
  6751. // }
  6752. for(const value of stack_){
  6753. value();
  6754. }
  6755. stack_.clear();
  6756. });
  6757. mo.observe(cm, {characterData: true});
  6758.  
  6759. }
  6760.  
  6761.  
  6762. const stackDM = (f) => {
  6763.  
  6764. if (firstRun) firstRun = firstRun();
  6765. stack.add(f);
  6766. cm.data = `${(cm.data & 1) + 1}`;
  6767. }
  6768. return stackDM;
  6769. })();
  6770. window.stackDM = stackDM;
  6771.  
  6772.  
  6773. const widthReq = (()=>{
  6774.  
  6775. let widthIORes;
  6776. let widthIO;
  6777.  
  6778. let firstRun = () => {
  6779. widthIORes = new WeakMap();
  6780. widthIO = new IntersectionObserver((mutations) => {
  6781. const r = new Map();
  6782. for (const mutation of mutations) {
  6783. r.set(mutation.target, mutation.boundingClientRect);
  6784. }
  6785.  
  6786. for (const [elm, rect] of r) {
  6787. widthIO.unobserve(elm);
  6788. const o = widthIORes.get(elm);
  6789. o && widthIORes.delete(elm);
  6790. const { promise, values } = o || {};
  6791. if (promise && values) {
  6792. values.width = rect.width;
  6793. promise.resolve(values);
  6794. }
  6795. }
  6796. });
  6797. };
  6798.  
  6799. const widthReq = (elm) => {
  6800.  
  6801. if (firstRun) firstRun = firstRun();
  6802.  
  6803. {
  6804. const { promise, values } = widthIORes.get(elm) || {};
  6805. if (promise) return promise;
  6806. }
  6807.  
  6808. const promise = new PromiseExternal();
  6809. widthIORes.set(elm, { promise, values: {} });
  6810. widthIO.unobserve(elm);
  6811. widthIO.observe(elm);
  6812.  
  6813. return promise;
  6814.  
  6815. }
  6816. return widthReq;
  6817. })();
  6818.  
  6819.  
  6820.  
  6821.  
  6822. customElements.whenDefined('yt-live-chat-item-list-renderer').then(() => {
  6823.  
  6824.  
  6825. const tag = "yt-live-chat-item-list-renderer"
  6826. const dummy = document.createElement(tag);
  6827.  
  6828. const cProto = getProto(dummy);
  6829. if (!cProto || !cProto.attached) {
  6830. console.warn(`proto.attached for ${tag} is unavailable.`);
  6831. return;
  6832. }
  6833.  
  6834. mightFirstCheckOnYtInit();
  6835. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-item-list-renderer hacks");
  6836. console1.log("[Begin]");
  6837.  
  6838. const mclp = cProto;
  6839. const _flag0281_ = window._flag0281_;
  6840.  
  6841. try {
  6842. assertor(() => typeof mclp.scrollToBottom_ === 'function');
  6843. assertor(() => typeof mclp.flushActiveItems_ === 'function');
  6844. assertor(() => typeof mclp.canScrollToBottom_ === 'function');
  6845. assertor(() => typeof mclp.setAtBottom === 'function');
  6846. assertor(() => typeof mclp.scrollToBottom66_ === 'undefined');
  6847. assertor(() => typeof mclp.flushActiveItems66_ === 'undefined');
  6848. } catch (e) { }
  6849.  
  6850.  
  6851. try {
  6852. assertor(() => typeof mclp.attached === 'function');
  6853. assertor(() => typeof mclp.detached === 'function');
  6854. assertor(() => typeof mclp.canScrollToBottom_ === 'function');
  6855. assertor(() => typeof mclp.isSmoothScrollEnabled_ === 'function');
  6856. assertor(() => typeof mclp.maybeResizeScrollContainer_ === 'function');
  6857. assertor(() => typeof mclp.refreshOffsetContainerHeight_ === 'function');
  6858. assertor(() => typeof mclp.smoothScroll_ === 'function');
  6859. assertor(() => typeof mclp.resetSmoothScroll_ === 'function');
  6860. } catch (e) { }
  6861.  
  6862. mclp.prDelay171 = null;
  6863.  
  6864. let myk = 0; // showNewItems77_
  6865. let mlf = 0; // flushActiveItems77_
  6866. let myw = 0; // onScrollItems77_
  6867. let mzt = 0; // handleLiveChatActions77_
  6868. let mlg = 0; // delayFlushActiveItemsAfterUserAction11_
  6869. let zarr = null;
  6870.  
  6871. if ((_flag0281_ & 0x2000) == 0) {
  6872.  
  6873. if ((mclp.clearList || 0).length === 0) {
  6874. (_flag0281_ & 0x2) == 0 && assertor(() => fnIntegrity(mclp.clearList, '0.106.50'));
  6875. mclp.clearList66 = mclp.clearList;
  6876. mclp.clearList = function () {
  6877. myk = (myk & 1073741823) + 1;
  6878. mlf = (mlf & 1073741823) + 1;
  6879. myw = (myw & 1073741823) + 1;
  6880. mzt = (mzt & 1073741823) + 1;
  6881. mlg = (mlg & 1073741823) + 1;
  6882. zarr = null;
  6883. this.prDelay171 = null;
  6884. this.clearList66();
  6885. };
  6886. console1.log("clearList", "OK");
  6887. } else {
  6888. console1.log("clearList", "NG");
  6889. }
  6890.  
  6891. }
  6892.  
  6893.  
  6894.  
  6895. let onListRendererAttachedDone = false;
  6896.  
  6897. function setList(itemOffset, items) {
  6898.  
  6899. const isFirstTime = onListRendererAttachedDone === false;
  6900.  
  6901. if (isFirstTime) {
  6902. onListRendererAttachedDone = true;
  6903. Promise.resolve().then(watchUserCSS);
  6904. addCssManaged();
  6905.  
  6906. const isBoostChatEnabled = (window._flag0281_ & 0x40000) === 0x40000;
  6907. if (!isBoostChatEnabled) setupEvents();
  6908. }
  6909.  
  6910. setupStyle(itemOffset, items);
  6911.  
  6912. setupMutObserver(items);
  6913.  
  6914. console.log('[yt-chat] setupMutObserver DONE')
  6915. }
  6916.  
  6917.  
  6918. const deferSeqFns = []; // ensure correct sequence
  6919. let deferSeqFnI = 0;
  6920. const deferCallbackLooper = entry => {
  6921. nextBrowserTick_(() => {
  6922. const { a, b } = entry;
  6923. const cnt = kRef(a);
  6924. if (cnt && b) b.call(cnt);
  6925. entry.a = entry.b = null;
  6926. });
  6927. }
  6928. const deferCallback = async (cnt, callback) => {
  6929. const a = cnt.__weakRef9441__ || (cnt.__weakRef9441__ = mWeakRef(cnt));
  6930. deferSeqFns[deferSeqFnI++] = { a, b: callback };
  6931. if (deferSeqFnI > 1) return;
  6932. const pr288 = cnt.prDelay288;
  6933. await pr288;
  6934. wme.data = `${(wme.data & 7) + 1}`;
  6935. await wmp;
  6936. const l = deferSeqFnI;
  6937. deferSeqFnI = 0;
  6938. for (let i = 0; i < l; i++) {
  6939. Promise.resolve(deferSeqFns[i]).then(deferCallbackLooper);
  6940. }
  6941. };
  6942.  
  6943. let showMoreBtnTransitionTrigg = null;
  6944.  
  6945. mclp.__showMoreBtn_transitionstart011__ = function (evt) {
  6946. showMoreBtnTransitionTrigg = true;
  6947. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  6948. if (newVisibility === "visible") {
  6949. const btn = evt.target;
  6950. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  6951. }
  6952. };
  6953.  
  6954.  
  6955. mclp.__showMoreBtn_transitionend011__ = function (evt) {
  6956. showMoreBtnTransitionTrigg = true;
  6957. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  6958. if (newVisibility === "hidden") {
  6959. const btn = evt.target;
  6960. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  6961. }
  6962. };
  6963. mclp.attached419 = async function () {
  6964.  
  6965. if (!this.isAttached) return;
  6966.  
  6967. let maxTrial = 16;
  6968. while (!this.$ || !this.$['item-scroller'] || !this.$['item-offset'] || !this.$['items']) {
  6969. if (--maxTrial < 0 || !this.isAttached) return;
  6970. await nextBrowserTick_();
  6971. // await new Promise(requestAnimationFrame);
  6972. }
  6973.  
  6974. if (this.isAttached !== true) return;
  6975.  
  6976. if (!this.$) {
  6977. console.warn("!this.$");
  6978. return;
  6979. }
  6980. if (!this.$) return;
  6981. /** @type {HTMLElement | null} */
  6982. const itemScroller = this.$['item-scroller'];
  6983. /** @type {HTMLElement | null} */
  6984. const itemOffset = this.$['item-offset'];
  6985. /** @type {HTMLElement | null} */
  6986. const items = this.$['items'];
  6987.  
  6988. if (!itemScroller || !itemOffset || !items) {
  6989. console.warn("items.parentNode !== itemOffset");
  6990. return;
  6991. }
  6992.  
  6993. if (nodeParent(items) !== itemOffset) {
  6994.  
  6995. console.warn("items.parentNode !== itemOffset");
  6996. return;
  6997. }
  6998.  
  6999.  
  7000. if (items.id !== 'items' || itemOffset.id !== "item-offset") {
  7001.  
  7002. console.warn("id incorrect");
  7003. return;
  7004. }
  7005.  
  7006. 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')
  7007.  
  7008. if (!isTargetItems) {
  7009. console.warn("!isTargetItems");
  7010. return;
  7011. }
  7012.  
  7013. setList(itemOffset, items);
  7014.  
  7015. if (WITH_SCROLL_ANCHOR) this.__itemAnchorColl011__ = itemOffset.getElementsByTagName('item-anchor');
  7016. else this.__itemAnchorColl011__ = null;
  7017.  
  7018.  
  7019.  
  7020. // btn-show-more-transition
  7021. const btn = this.$['show-more'];
  7022. if (btn) {
  7023. if (!this.__showMoreBtn_transitionstart012__) this.__showMoreBtn_transitionstart012__ = this.__showMoreBtn_transitionstart011__.bind(this);
  7024. if (!this.__showMoreBtn_transitionend012__) this.__showMoreBtn_transitionend012__ = this.__showMoreBtn_transitionend011__.bind(this);
  7025. btn.addEventListener('transitionrun', this.__showMoreBtn_transitionstart012__, false);
  7026. btn.addEventListener('transitionstart', this.__showMoreBtn_transitionstart012__, false);
  7027. btn.addEventListener('transitionend', this.__showMoreBtn_transitionend012__, false);
  7028. btn.addEventListener('transitioncancel', this.__showMoreBtn_transitionend012__, false);
  7029. }
  7030.  
  7031. // fix panel height changing issue (ENABLE_OVERFLOW_ANCHOR only)
  7032. if (itemScrollerResizeObserver) itemScrollerResizeObserver.observe(this.itemScroller || this.$['item-scroller']);
  7033.  
  7034. }
  7035.  
  7036. mclp.attached331 = mclp.attached;
  7037. mclp.attached = function () {
  7038. this.attached419 && this.attached419();
  7039. return this.attached331();
  7040. }
  7041.  
  7042. mclp.detached331 = mclp.detached;
  7043.  
  7044. mclp.detached = function () {
  7045. setupMutObserver();
  7046. return this.detached331();
  7047. }
  7048.  
  7049. const t29s = document.querySelectorAll("yt-live-chat-item-list-renderer");
  7050. for (const t29 of t29s) {
  7051. const cnt = insp(t29);
  7052. if (cnt.isAttached === true) {
  7053. cnt.attached419();
  7054. }
  7055. }
  7056.  
  7057. if ((mclp.async || 0).length === 2 && (mclp.cancelAsync || 0).length === 1) {
  7058.  
  7059. assertor(() => fnIntegrity(mclp.async, '2.24.15'));
  7060. assertor(() => fnIntegrity(mclp.cancelAsync, '1.15.8'));
  7061.  
  7062. /** @type {Map<number, any>} */
  7063. const aMap = new Map();
  7064. const mcid = setTimeout(() => 0, 0.625);
  7065. const maid = requestAnimationFrame(() => 0);
  7066. clearTimeout(mcid);
  7067. cancelAnimationFrame(maid);
  7068. const count0 = mcid + maid + 1740;
  7069. let count = count0;
  7070. mclp.async66 = mclp.async;
  7071. mclp.async = function (e, f) {
  7072. // ensure the previous operation is done
  7073. // .async is usually after the time consuming functions like flushActiveItems_ and scrollToBottom_
  7074. const hasF = arguments.length === 2;
  7075. if (count > 1e9) count = count0 + 9;
  7076. const resId = ++count;
  7077. aMap.set(resId, e);
  7078. const pr1 = Promise.all([this.prDelay288, wmp, this.prDelay171, Promise.resolve()]);
  7079. const pr2 = autoTimerFn();
  7080. Promise.race([pr1, pr2]).then(() => {
  7081. const rp = aMap.get(resId);
  7082. if (typeof rp !== 'function') {
  7083. return;
  7084. }
  7085. const asyncEn = function () {
  7086. return aMap.delete(resId) && rp.apply(this, arguments);
  7087. };
  7088. aMap.set(resId, hasF ? this.async66(asyncEn, f) : this.async66(asyncEn));
  7089. });
  7090.  
  7091. return resId;
  7092. }
  7093.  
  7094. mclp.cancelAsync66 = mclp.cancelAsync;
  7095. mclp.cancelAsync = function (resId) {
  7096. if (resId <= count0) {
  7097. this.cancelAsync66(resId);
  7098. } else if (aMap.has(resId)) {
  7099. const rp = aMap.get(resId);
  7100. aMap.delete(resId);
  7101. if (typeof rp !== 'function') {
  7102. this.cancelAsync66(rp);
  7103. }
  7104. }
  7105. }
  7106.  
  7107. console1.log("async", "OK");
  7108. } else {
  7109. console1.log("async", "NG");
  7110. }
  7111.  
  7112.  
  7113. if ((_flag0281_ & 0x2) == 0) {
  7114. if ((mclp.showNewItems_ || 0).length === 0 && ENABLE_NO_SMOOTH_TRANSFORM) {
  7115.  
  7116. assertor(() => fnIntegrity(mclp.showNewItems_, '0.170.79'));
  7117. mclp.showNewItems66_ = mclp.showNewItems_;
  7118. mclp.showNewItems_ = function () {
  7119. //
  7120. }
  7121.  
  7122. console1.log("showNewItems_", "OK");
  7123. } else {
  7124. console1.log("showNewItems_", "NG");
  7125. }
  7126.  
  7127. }
  7128.  
  7129.  
  7130.  
  7131. if ((_flag0281_ & 0x2) == 0) {
  7132. if ((mclp.onScrollItems_ || 0).length === 1) {
  7133.  
  7134. if (mclp.onScrollItems3641_) {
  7135.  
  7136. } else {
  7137. assertor(() => fnIntegrity(mclp.onScrollItems_, '1.17.9'));
  7138.  
  7139. }
  7140.  
  7141. if (typeof mclp.setAtBottom === 'function' && mclp.setAtBottom.length === 0) {
  7142.  
  7143. mclp.setAtBottom217 = mclp.setAtBottom;
  7144. mclp.setAtBottom = function () {
  7145. const v = this.ec217;
  7146. if (typeof v !== 'boolean') return this.setAtBottom217();
  7147. const u = this.atBottom;
  7148. if (u !== v && typeof u === 'boolean') this.atBottom = v;
  7149. // this.atBottom = a.scrollTop >= a.scrollHeight - a.clientHeight - 15
  7150. }
  7151.  
  7152. let lastScrollTarget = null;
  7153. mclp.onScrollItems66_ = mclp.onScrollItems_;
  7154. let callback = () => { };
  7155.  
  7156. // let itemScrollerWR = null;
  7157. let lastEvent = null;
  7158.  
  7159. let io2 = null, io1 = null;
  7160. const io2f = (entries, observer) => {
  7161. const entry = entries[entries.length - 1];
  7162. if (entry.target !== lastScrollTarget) return;
  7163. callback(entry);
  7164. };
  7165. const io1f = (entries, observer) => {
  7166. const entry = entries[entries.length - 1];
  7167. observer.unobserve(entry.target);
  7168. if (entry.target !== lastScrollTarget) return;
  7169. lastScrollTarget = null;
  7170. callback(entry);
  7171. };
  7172. mclp.onScrollItems3885cb2_ = function (entry) {
  7173. const v = (entry.isIntersecting === true);
  7174. this.ec217 = v;
  7175. this.onScrollItems66_(lastEvent);
  7176. this.ec217 = null;
  7177. }
  7178. mclp.onScrollItems3885cb1_ = function (entry) {
  7179. const v = (entry.intersectionRatio > 0.98);
  7180. this.ec217 = v;
  7181. this.onScrollItems66_(lastEvent);
  7182. this.ec217 = null;
  7183. };
  7184.  
  7185. mclp.onScrollItems_ = function (evt) {
  7186.  
  7187. if (evt === lastEvent) return;
  7188. if (evt && lastEvent && evt.timeStamp === lastEvent.timeStamp) return;
  7189. lastEvent = evt;
  7190. const ytRendererBehavior = this.ytRendererBehavior || 0;
  7191. if (typeof ytRendererBehavior.onScroll === 'function') ytRendererBehavior.onScroll(evt);
  7192. const coll = this.__itemAnchorColl011__;
  7193. if (coll) {
  7194. const anchorElement = coll.length === 1 ? coll[0] : null;
  7195. if (lastScrollTarget !== anchorElement) {
  7196. if (io2) io2.disconnect();
  7197. lastScrollTarget = anchorElement;
  7198. if (anchorElement) {
  7199. if (!this.onScrollItems3886cb2_) this.onScrollItems3886cb2_ = this.onScrollItems3885cb2_.bind(this);
  7200. callback = this.onScrollItems3886cb2_;
  7201. if (!io2) io2 = new IntersectionObserver(io2f);
  7202. io2.observe(anchorElement);
  7203. }
  7204. }
  7205. } else {
  7206. const items = this.$.items;
  7207. if (!items) return this.onScrollItems66_();
  7208. const lastComponent = lastComponentChildFn(items);
  7209. if (!lastComponent) return this.onScrollItems66_();
  7210. if (lastScrollTarget === lastComponent) return;
  7211. lastScrollTarget = lastComponent;
  7212.  
  7213. if (io1) io1.disconnect();
  7214. if (!this.onScrollItems3886cb1_) this.onScrollItems3886cb1_ = this.onScrollItems3885cb1_.bind(this);
  7215. callback = this.onScrollItems3886cb1_;
  7216. if (!io1) io1 = new IntersectionObserver(io1f);
  7217. io1.observe(lastComponent);
  7218. }
  7219. };
  7220.  
  7221. }
  7222.  
  7223. console1.log("onScrollItems_", "OK");
  7224. } else {
  7225. console1.log("onScrollItems_", "NG");
  7226. }
  7227. }
  7228.  
  7229.  
  7230. if ((_flag0281_ & 0x40) == 0) {
  7231.  
  7232. if (ENABLE_NO_SMOOTH_TRANSFORM && SUPPRESS_refreshOffsetContainerHeight_ && typeof mclp.refreshOffsetContainerHeight_ === 'function' && !mclp.refreshOffsetContainerHeight26_ && mclp.refreshOffsetContainerHeight_.length === 0) {
  7233. assertor(() => fnIntegrity(mclp.refreshOffsetContainerHeight_, '0.31.21'));
  7234. mclp.refreshOffsetContainerHeight26_ = mclp.refreshOffsetContainerHeight_;
  7235. mclp.refreshOffsetContainerHeight_ = function () {
  7236. // var a = this.itemScroller.clientHeight;
  7237. // this.itemOffset.style.height = this.items.clientHeight + "px";
  7238. // this.bottomAlignMessages && (this.itemOffset.style.minHeight = a + "px")
  7239. }
  7240. console1.log("refreshOffsetContainerHeight_", "OK");
  7241. } else {
  7242. console1.log("refreshOffsetContainerHeight_", "NG");
  7243. }
  7244.  
  7245. }
  7246.  
  7247. if ((_flag0281_ & 0x2000) == 0) {
  7248. if ((mclp.flushActiveItems_ || 0).length === 0) {
  7249.  
  7250. if ((_flag0281_ & 0x2) == 0) {
  7251.  
  7252. const sfi = fnIntegrity(mclp.flushActiveItems_);
  7253. if(sfi === '0.158.86'){
  7254.  
  7255. // https://www.youtube.com/s/desktop/c01ea7e3/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  7256.  
  7257.  
  7258. // f.flushActiveItems_ = function() {
  7259. // var a = this;
  7260. // if (this.activeItems_.length > 0)
  7261. // if (this.canScrollToBottom_()) {
  7262. // var b = Math.max(this.visibleItems.length + this.activeItems_.length - this.data.maxItemsToDisplay, 0);
  7263. // b && this.splice("visibleItems", 0, b);
  7264. // if (this.isSmoothScrollEnabled_() || this.dockableMessages.length)
  7265. // this.preinsertHeight_ = this.items.clientHeight;
  7266. // this.activeItems_.unshift("visibleItems");
  7267. // try {
  7268. // this.push.apply(this, this.activeItems_)
  7269. // } catch (c) {
  7270. // Tm(c)
  7271. // }
  7272. // this.activeItems_ = [];
  7273. // this.isSmoothScrollEnabled_() ? this.canScrollToBottom_() && $u(function() {
  7274. // a.showNewItems_()
  7275. // }) : $u(function() {
  7276. // a.refreshOffsetContainerHeight_();
  7277. // a.maybeScrollToBottom_()
  7278. // })
  7279. // } else
  7280. // this.activeItems_.length > this.data.maxItemsToDisplay && this.activeItems_.splice(0, this.activeItems_.length - this.data.maxItemsToDisplay)
  7281. // }
  7282.  
  7283. } else if (sfi === '0.156.86') {
  7284. // https://www.youtube.com/s/desktop/f61c8d85/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  7285.  
  7286. // added "refreshOffsetContainerHeight_"
  7287.  
  7288. // f.flushActiveItems_ = function() {
  7289. // var a = this;
  7290. // if (0 < this.activeItems_.length)
  7291. // if (this.canScrollToBottom_()) {
  7292. // var b = Math.max(this.visibleItems.length + this.activeItems_.length - this.data.maxItemsToDisplay, 0);
  7293. // b && this.splice("visibleItems", 0, b);
  7294. // if (this.isSmoothScrollEnabled_() || this.dockableMessages.length)
  7295. // this.preinsertHeight_ = this.items.clientHeight;
  7296. // this.activeItems_.unshift("visibleItems");
  7297. // try {
  7298. // this.push.apply(this, this.activeItems_)
  7299. // } catch (c) {
  7300. // fm(c)
  7301. // }
  7302. // this.activeItems_ = [];
  7303. // this.isSmoothScrollEnabled_() ? this.canScrollToBottom_() && Mw(function() {
  7304. // a.showNewItems_()
  7305. // }) : Mw(function() {
  7306. // a.refreshOffsetContainerHeight_();
  7307. // a.maybeScrollToBottom_()
  7308. // })
  7309. // } else
  7310. // this.activeItems_.length > this.data.maxItemsToDisplay && this.activeItems_.splice(0, this.activeItems_.length - this.data.maxItemsToDisplay)
  7311. // }
  7312. // ;
  7313.  
  7314. } else if (sfi === '0.150.84') {
  7315. // https://www.youtube.com/s/desktop/e4d15d2c/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  7316. // var b = Math.max(this.visibleItems.length + this.activeItems_.length - this.data.maxItemsToDisplay, 0);
  7317. // b && this.splice("visibleItems", 0, b);
  7318. // if (this.isSmoothScrollEnabled_() || this.dockableMessages.length)
  7319. // this.preinsertHeight_ = this.items.clientHeight;
  7320. // this.activeItems_.unshift("visibleItems");
  7321. // try {
  7322. // this.push.apply(this, this.activeItems_)
  7323. // } catch (c) {
  7324. // nm(c)
  7325. // }
  7326. // this.activeItems_ = [];
  7327. // this.isSmoothScrollEnabled_() ? this.canScrollToBottom_() && zQ(function() {
  7328. // a.showNewItems_()
  7329. // }) : zQ(function() {
  7330. // a.maybeScrollToBottom_()
  7331. // })
  7332. } else if (sfi === '0.137.81' || sfi === '0.138.81') {
  7333. // e.g. https://www.youtube.com/yts/jsbin/live_chat_polymer-vflCyWEBP/live_chat_polymer.js
  7334. } else {
  7335. assertor(() => fnIntegrity(mclp.flushActiveItems_, '0.158.86'))
  7336. || logFn('mclp.flushActiveItems_', mclp.flushActiveItems_)();
  7337. }
  7338. }
  7339.  
  7340. let hasMoreMessageState = !ENABLE_SHOW_MORE_BLINKER ? -1 : 0;
  7341.  
  7342. mclp.flushActiveItems66a_ = mclp.flushActiveItems_;
  7343. // let lastLastRow = null;
  7344.  
  7345.  
  7346. const preloadFn = (acItems) => {
  7347. let waitFor = [];
  7348. /** @type {Set<string>} */
  7349. const imageLinks = new Set();
  7350.  
  7351. if (ENABLE_PRELOAD_THUMBNAIL || EMOJI_IMAGE_SINGLE_THUMBNAIL || AUTHOR_PHOTO_SINGLE_THUMBNAIL) {
  7352. for (const item of acItems) {
  7353. fixLiveChatItem(item, imageLinks);
  7354. }
  7355. }
  7356. if (ENABLE_PRELOAD_THUMBNAIL && kptPF !== null && (kptPF & (8 | 4)) && imageLinks.size > 0) {
  7357.  
  7358. // reference: https://github.com/Yuanfang-fe/Blog-X/issues/34
  7359. const rel = kptPF & 8 ? 'subresource' : kptPF & 16 ? 'preload' : kptPF & 4 ? 'prefetch' : '';
  7360. // preload performs the high priority fetching.
  7361. // prefetch delays the chat display if the video resoruce is demanding.
  7362.  
  7363. if (rel) {
  7364.  
  7365. imageLinks.forEach(imageLink => {
  7366. let d = false;
  7367. if (SKIP_PRELOAD_EMOJI && imageLink.includes('.ggpht.com/')) return;
  7368. const isEmoji = imageLink.includes('/emoji/');
  7369. const pretechedSet = isEmoji ? emojiPrefetched : authorPhotoPrefetched;
  7370. if (!pretechedSet.has(imageLink)) {
  7371. pretechedSet.add(imageLink);
  7372. d = true;
  7373. }
  7374. if (d) {
  7375. waitFor.push(linker(null, rel, imageLink, 'image'));
  7376.  
  7377. }
  7378. })
  7379.  
  7380. }
  7381.  
  7382. }
  7383.  
  7384. return async () => {
  7385. if (waitFor.length > 0) {
  7386. await Promise.race([new Promise(r => setTimeout(r, 250)), Promise.all(waitFor)]);
  7387. }
  7388. waitFor.length = 0;
  7389. waitFor = null;
  7390. };
  7391.  
  7392. };
  7393.  
  7394.  
  7395.  
  7396. if(ENABLE_CHAT_MESSAGES_BOOSTED_STAMPING && `${mclp.flushActiveItems_}`.includes("this.push.apply(this,this.activeItems_)") && `${mclp.flushActiveItems_}`.includes(`this.splice("visibleItems",0,`)){
  7397.  
  7398.  
  7399.  
  7400. {
  7401.  
  7402.  
  7403. rendererStamperFactory(cProto, {
  7404. key: 'proceedStampDomArraySplices381_',
  7405. stamperDomClass: 'style-scope yt-live-chat-item-list-renderer yt-live-chat-item-list-stampdom',
  7406. preloadFn
  7407. });
  7408.  
  7409. cProto.stampDomArraySplices381_ = cProto.stampDomArraySplices_;
  7410.  
  7411. cProto.stampDomArraySplices_ = function (a, b, c) {
  7412. if (a === 'visibleItems' && b === 'items' && (c || 0).indexSplices) {
  7413. // if (this.ec388) {
  7414. const indexSplices = c.indexSplices;
  7415. if (indexSplices.length === 1 || typeof indexSplices.length === "undefined") {
  7416. const indexSplice = indexSplices[0] || indexSplices;
  7417. if (indexSplice.type === 'splice' && (indexSplice.addedCount >= 1 || (indexSplice.removed || []).length >= 1)) {
  7418. // console.log(1059, a, b, indexSplice);
  7419. if (this.proceedStampDomArraySplices381_(a, b, indexSplice)) return;
  7420. }
  7421. }
  7422. // } else {
  7423. // console.warn('stampDomArraySplices_ warning', ...arguments);
  7424. // }
  7425. }
  7426. return this.stampDomArraySplices381_(...arguments);
  7427. }
  7428.  
  7429. cProto.stampDomArray366_ = cProto.stampDomArray_;
  7430. cProto.stampDomArray_ = function (items, containerId, componentConfig, rxConfig, shouldCallback, isStableList) {
  7431. const isTickerRendering = items === this.tickerItems && containerId === 'ticker-items';
  7432. const isMessageListRendering = items === this.visibleItems && containerId === 'items';
  7433. if(!isTickerRendering && !isMessageListRendering){
  7434. console.log('stampDomArray_ warning 0xF501', ...arguments)
  7435. return this.stampDomArray366_(...arguments);
  7436. }
  7437.  
  7438. const container = (this.$ || 0)[containerId];
  7439. if (!container) {
  7440. console.log('stampDomArray_ warning 0xF502', ...arguments)
  7441. return this.stampDomArray366_(...arguments);
  7442. }
  7443.  
  7444. if (container[sFirstElementChild] === null && items.length === 0) {
  7445.  
  7446. } else {
  7447. const cTag = isTickerRendering ? 'tickerItems' : 'visibleItems';
  7448. this.proceedStampDomArraySplices381_(cTag, containerId, {
  7449. addedCount: items.length,
  7450. removedCount: container.childElementCount
  7451. });
  7452. }
  7453.  
  7454. const f = () => {
  7455. this.markDirty && this.markDirty();
  7456. const detail = {
  7457. container
  7458. };
  7459. shouldCallback && this.hostElement.dispatchEvent(new CustomEvent("yt-rendererstamper-finished", {
  7460. bubbles: !0,
  7461. cancelable: !1,
  7462. composed: !0,
  7463. detail
  7464. }));
  7465. detail.container = null;
  7466. };
  7467.  
  7468. if (this.ec389pr) {
  7469. this.ec389pr.then(f)
  7470. } else {
  7471. f();
  7472. }
  7473.  
  7474. };
  7475.  
  7476. mclp.push377 = mclp.push;
  7477. mclp.splice377 = mclp.splice;
  7478.  
  7479.  
  7480.  
  7481. const emptyArr = [];
  7482. emptyArr.push = () => 0;
  7483. emptyArr.unshift = () => 0;
  7484. emptyArr.pop = () => void 0;
  7485. emptyArr.shift = () => void 0;
  7486. emptyArr.splice = () => void 0;
  7487. emptyArr.slice = function () { return this };
  7488.  
  7489.  
  7490. mclp.push = function (cTag, ...fnArgs) {
  7491. if (cTag !== 'visibleItems' || !fnArgs.length || !fnArgs[0]) return this.push377(...arguments);
  7492. const arr = this.visibleItems;
  7493. const len = arr.length;
  7494. const newTotalLen = arr.push(...fnArgs);
  7495. const addedCount = fnArgs.length;
  7496. // console.log('push')
  7497. this.proceedStampDomArraySplices381_('visibleItems', 'items', {
  7498. index: len, addedCount: addedCount, removedCount: 0
  7499. })
  7500. return newTotalLen;
  7501. }
  7502.  
  7503. mclp.splice = function (cTag, ...fnArgs) {
  7504. if (cTag !== 'visibleItems' || !fnArgs.length || (fnArgs.length === 2 && !fnArgs[1]) || (fnArgs.length > 2 && !fnArgs[2])) return this.splice377(...arguments);
  7505. const arr = this.visibleItems;
  7506. const removed = arr.splice(...fnArgs);
  7507. const removedCount = removed.length;
  7508. const addedCount = (fnArgs.length > 2 ? fnArgs.length - 2 : 0);
  7509. if (fnArgs.length >= 2 && removedCount !== fnArgs[1]) {
  7510. console.warn(`incorrect splice count. expected = ${fnArgs[1]}; actual = ${removedCount}`);
  7511. }
  7512. // console.log('splice')
  7513. this.proceedStampDomArraySplices381_('visibleItems', 'items', {
  7514. index: fnArgs[0], addedCount: addedCount, removedCount
  7515. })
  7516. return removed;
  7517. }
  7518.  
  7519.  
  7520.  
  7521. }
  7522.  
  7523. /*
  7524. mclp.flushActiveItems66b_ = function () {
  7525.  
  7526. let prWait = null;
  7527. let shouldProceedNextFlushActiveItems = false;
  7528.  
  7529. try {
  7530.  
  7531.  
  7532. const activeItems_ = this.activeItems_;
  7533. const activeItemsCount = activeItems_.length;
  7534. const maxItemsToDisplay = this.data.maxItemsToDisplay;
  7535. if (activeItemsCount > maxItemsToDisplay) {
  7536. activeItems_.splice(0, activeItemsCount - maxItemsToDisplay);
  7537. }
  7538. const qLen = this.visibleItems.length;
  7539. const pr0 = this.prDelay288;
  7540. const pr = this.prDelay288 = new PromiseExternal();
  7541. this.ec377 = true;
  7542. const ec378 = this.ec378 = new Array(qLen).fill(0).map((e, idx) => idx);
  7543. this.flushActiveItems66a_();
  7544. this.ec377 = false;
  7545. this.ec378 = null;
  7546. this.prDelay288 = pr0;
  7547. this.activeItems_ = typeof activeItems_[0] === 'string' ? activeItems_.slice(1) : activeItems_;
  7548. wme.data = `${(wme.data & 7) + 1}`;
  7549. const isSuccess = this.renderSplicedList323(ec378, qLen, pr);
  7550. if (isSuccess) {
  7551. // console.log('19949 - ok')
  7552. this.prDelay288 = pr;
  7553. shouldProceedNextFlushActiveItems = true;
  7554.  
  7555. wme.data = `${(wme.data & 7) + 1}`;
  7556. prWait = wmp;
  7557.  
  7558. } else if (activeItemsCount === 0 || !this.canScrollToBottom_()) {
  7559. // skip
  7560. } else {
  7561. const ppr = ((slist, qLen, pr) => {
  7562. const deleteCount = (typeof slist[0] === 'number') ? slist[0] : qLen;
  7563. let newAt = qLen - deleteCount;
  7564. if (newAt > 0 && slist[newAt - 1] !== qLen - 1) return 3;
  7565. if (newAt > slist.length) return 4;
  7566. if (newAt < slist.length && typeof slist[newAt] === 'number') return 5;
  7567. const addedCount = slist.length - newAt;
  7568. // if (deleteCount > addedCount) return 6;
  7569.  
  7570. if (deleteCount === 0 && addedCount === 0) return 7;
  7571.  
  7572. })(ec378, qLen, pr);
  7573.  
  7574. console.log('19949 - ng', ppr)
  7575.  
  7576. const pr2 = this.prDelay288 = new PromiseExternal();
  7577. this.flushActiveItems66a_();
  7578. pr2.resolve();
  7579. shouldProceedNextFlushActiveItems = true;
  7580.  
  7581. wme.data = `${(wme.data & 7) + 1}`;
  7582. prWait = wmp;
  7583.  
  7584. }
  7585.  
  7586. } catch (e) {
  7587.  
  7588. console.warn(e);
  7589. }
  7590.  
  7591.  
  7592. const pr5 = this.prDelay288;
  7593.  
  7594. (async ()=>{
  7595. await pr5;
  7596. await prWait;
  7597. flushActiveItemExecuted = false;
  7598. if (shouldProceedNextFlushActiveItems && this.activeItems_.length > 0) setTimeout(() => this.flushActiveItems_(), 0);
  7599. })();
  7600.  
  7601. }
  7602. */
  7603.  
  7604.  
  7605. mclp.flushActiveItemsFix001_ = function () {
  7606.  
  7607. // fix YouTube wrong code
  7608. // var b = Math.max(this.visibleItems.length + this.activeItems_.length - this.data.maxItemsToDisplay, 0);
  7609. // b && this.splice("visibleItems", 0, b);
  7610. // e.g. 0 + 99 - 90 = 9
  7611.  
  7612. const data = this.data;
  7613. if (!data) return;
  7614. const visibleItems = this.visibleItems;
  7615. const activeItems_ = this.activeItems_;
  7616. if (!visibleItems || !activeItems_) return;
  7617. const viLen = visibleItems.length;
  7618. const aiLen = activeItems_.length;
  7619. const maxDisplayLen = data.maxItemsToDisplay;
  7620. if (!maxDisplayLen) return;
  7621. if (viLen + aiLen > maxDisplayLen) {
  7622. if (aiLen > maxDisplayLen) activeItems_.splice(0, aiLen - maxDisplayLen);
  7623. // visibleItems splice done by original flushActiveItems_
  7624. }
  7625. }
  7626.  
  7627. mclp.flushActiveItems3641_ = mclp.flushActiveItems_;
  7628.  
  7629. mclp.__moreItemButtonBlinkingCheck183__ = function () {
  7630. const hasPendingItems = (this.activeItems_ && this.activeItems_.length > 0) ? 1 : 0;
  7631. const shouldChange = (hasMoreMessageState === (1 - hasPendingItems));
  7632. if (shouldChange) {
  7633. hasMoreMessageState = hasPendingItems;
  7634. const showMore = (this.$ || 0)['show-more'];
  7635. if (showMore) {
  7636. showMore.classList.toggle('has-new-messages-miuzp', hasPendingItems ? true : false);
  7637. }
  7638. }
  7639. }
  7640.  
  7641. let ps00 = false;
  7642. mclp.flushActiveItems_ = function () {
  7643. if (ps00) return;
  7644. // console.log('flushActiveItems_')
  7645. ps00 = true;
  7646. deferCallback(this, () => {
  7647. ps00 = false;
  7648. // console.log('flushActiveItems3641_')
  7649. if (this.activeItems_.length > 0) {
  7650. const data = this.data;
  7651. if (data) {
  7652. if (data.maxItemsToDisplay > MAX_ITEMS_FOR_TOTAL_DISPLAY) data.maxItemsToDisplay = MAX_ITEMS_FOR_TOTAL_DISPLAY;
  7653. this.flushActiveItemsFix001_(); // bug fix
  7654. this.flushActiveItems3641_();
  7655. if (ENABLE_SHOW_MORE_BLINKER) {
  7656. this.__moreItemButtonBlinkingCheck183__(); // blink the button if there are activeItems remaining.
  7657. }
  7658. }
  7659. }
  7660. }).catch(console.warn);
  7661. };
  7662.  
  7663. mclp.showNewItems3641_ = mclp.showNewItems_;
  7664. mclp.refreshOffsetContainerHeight3641_ = mclp.refreshOffsetContainerHeight_;
  7665. mclp.maybeScrollToBottom3641_ = mclp.maybeScrollToBottom_;
  7666.  
  7667. let ps01 = false;
  7668. mclp.showNewItems_ = function () {
  7669. if (ps01) return;
  7670. // console.log('showNewItems_')
  7671. ps01 = true;
  7672. deferCallback(this, () => {
  7673. ps01 = false;
  7674. this.showNewItems3641_();
  7675. }).catch(console.warn);
  7676. };
  7677.  
  7678. if (!ENABLE_NO_SMOOTH_TRANSFORM && !mclp.refreshOffsetContainerHeight26_) {
  7679. let ps02 = false;
  7680. mclp.refreshOffsetContainerHeight_ = function () {
  7681. if (ps02) return;
  7682. // console.log('refreshOffsetContainerHeight_')
  7683. ps02 = true;
  7684. deferCallback(this, () => {
  7685. ps02 = false;
  7686. this.refreshOffsetContainerHeight3641_();
  7687. }).catch(console.warn);
  7688. };
  7689. }
  7690.  
  7691.  
  7692. let ps03 = false;
  7693. mclp.maybeScrollToBottom_ = function () {
  7694. if (ps03) return;
  7695. // console.log('maybeScrollToBottom_')
  7696. ps03 = true;
  7697. deferCallback(this, () => {
  7698. ps03 = false;
  7699. if (this.atBottom === true) {
  7700.  
  7701. // if (itemsResizeObserverAttached !== true && this.atBottom === true) {
  7702. // // fallback for old browser
  7703. // const itemScroller = this.itemScroller || this.$['item-scroller'] || this.querySelector('#item-scroller') || 0;
  7704. // if (itemScroller.scrollTop === 0) {
  7705. // resizeObserverFallback.observe(itemScroller);
  7706. // }
  7707. // }
  7708. } else {
  7709.  
  7710. this.maybeScrollToBottom3641_();
  7711. }
  7712. }).catch(console.warn);
  7713. };
  7714.  
  7715. mclp.onScrollItems3641_ = mclp.onScrollItems_;
  7716. mclp.maybeResizeScrollContainer3641_ = mclp.maybeResizeScrollContainer_;
  7717. mclp.handleLiveChatActions3641_ = mclp.handleLiveChatActions_;
  7718.  
  7719. let ps11 = false;
  7720. mclp.onScrollItems_ = function (a) {
  7721. if (ps11) return;
  7722. // console.log('onScrollItems_')
  7723. ps11 = true;
  7724. deferCallback(this, () => {
  7725. ps11 = false;
  7726. this.onScrollItems3641_(a);
  7727. }).catch(console.warn);
  7728. };
  7729.  
  7730. if (!ENABLE_NO_SMOOTH_TRANSFORM) { // no function for ENABLE_NO_SMOOTH_TRANSFORM
  7731. let ps12 = false;
  7732. mclp.maybeResizeScrollContainer_ = function (a) {
  7733. if (ps12) return;
  7734. // console.log('maybeResizeScrollContainer_')
  7735. ps12 = true;
  7736. deferCallback(this, () => {
  7737. ps12 = false;
  7738. this.maybeResizeScrollContainer3641_(a);
  7739. }).catch(console.warn);
  7740. };
  7741. }
  7742.  
  7743. }
  7744.  
  7745. console1.log("flushActiveItems_", "OK");
  7746. } else {
  7747. console1.log("flushActiveItems_", "NG");
  7748. }
  7749. }
  7750.  
  7751.  
  7752. if ((_flag0281_ & 0x40) == 0 ) {
  7753.  
  7754.  
  7755. let showBtnLastState = null;
  7756. let lastAtBottomState = null;
  7757. // let showMoreBtnTransitionTrigg = false;
  7758. mclp.atBottomChanged314_ = mclp.atBottomChanged_;
  7759. mclp.atBottomChanged_ = function () {
  7760.  
  7761. const currentAtBottomState = this.atBottom;
  7762. if(lastAtBottomState === currentAtBottomState) return;
  7763. lastAtBottomState = currentAtBottomState;
  7764.  
  7765. // console.log(1289, showMoreBtnTransitionTrigg)
  7766.  
  7767. /*
  7768. if (!this.___btn3848___) {
  7769. this.___btn3848___ = true;
  7770. const btn = ((this || 0).$ || 0)["show-more"] || 0;
  7771. if (btn) {
  7772. btn.addEventListener('transitionstart', (evt) => {
  7773. showMoreBtnTransitionTrigg = true;
  7774. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7775. if (newVisibility === "visible") {
  7776. const btn = evt.target;
  7777. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7778. }
  7779. });
  7780. btn.addEventListener('transitionend', (evt) => {
  7781. showMoreBtnTransitionTrigg = true;
  7782. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7783. if (newVisibility === "hidden") {
  7784. const btn = evt.target;
  7785. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7786. }
  7787. });
  7788. btn.addEventListener('transitioncancel', (evt) => {
  7789. showMoreBtnTransitionTrigg = true;
  7790. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7791. if (newVisibility === "hidden") {
  7792. const btn = evt.target;
  7793. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7794. }
  7795. });
  7796. }
  7797. }
  7798. */
  7799.  
  7800. // btn-show-more-transition
  7801. if (showMoreBtnTransitionTrigg) return;
  7802.  
  7803. const btn = ((this || 0).$ || 0)["show-more"] || 0;
  7804. if (!btn) return this.atBottomChanged314_();
  7805.  
  7806. const showBtnCurrentState = btn.hasAttribute('disabled');
  7807. if (showBtnLastState === showBtnCurrentState) return;
  7808. showBtnLastState = showBtnCurrentState;
  7809.  
  7810. if (this.visibleItems.length === 0) {
  7811. if (this.atBottom === true) {
  7812. btn.setAttribute('disabled', '');
  7813. showBtnLastState = true;
  7814. }
  7815. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7816. if (btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7817. return;
  7818. }
  7819.  
  7820. nextBrowserTick_(() => {
  7821.  
  7822. if (showMoreBtnTransitionTrigg) return;
  7823.  
  7824. // fallback
  7825.  
  7826. // const isAtBottom = this.atBottom === true;
  7827. // if (isAtBottom) {
  7828. // if (!this.hideShowMoreAsync_) {
  7829. // this.hideShowMoreAsync_ = setTimeoutX0(function () {
  7830. // const btn = ((this || 0).$ || 0)["#show-more"] || 0;
  7831. // if (btn) btn.style.visibility = "hidden";
  7832. // }, 200 - 0.125);
  7833. // }
  7834. // } else {
  7835. // if (this.hideShowMoreAsync_) {
  7836. // clearTimeoutX0(this.hideShowMoreAsync_);
  7837. // this.hideShowMoreAsync_ = null;
  7838. // }
  7839. // const btn = ((this || 0).$ || 0)["#show-more"] || 0;
  7840. // if (btn) btn.style.visibility = "visible";
  7841. // }
  7842.  
  7843. const btn = ((this || 0).$ || 0)["show-more"] || 0;
  7844. const newVisibility = (this.atBottom === true) ? "hidden" : "visible";
  7845.  
  7846. if (newVisibility === "hidden") {
  7847. console.warn('show-more-btn no transition')
  7848. }
  7849.  
  7850. if (btn && btn.style.visibility !== newVisibility) btn.style.visibility = newVisibility;
  7851.  
  7852. });
  7853.  
  7854. };
  7855.  
  7856. }
  7857.  
  7858.  
  7859.  
  7860. if ((_flag0281_ & 0x2) == 0) {
  7861. if ((mclp.handleLiveChatActions_ || 0).length === 1) {
  7862.  
  7863. const sfi = fnIntegrity(mclp.handleLiveChatActions_);
  7864. // handleLiveChatActions66_
  7865. if (sfi === '1.40.20') {
  7866. // https://www.youtube.com/s/desktop/c01ea7e3/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  7867.  
  7868.  
  7869. // f.handleLiveChatActions_ = function(a) {
  7870. // var b = this;
  7871. // a.length && (a.forEach(this.handleLiveChatAction_, this),
  7872. // this.maybeResizeScrollContainer_(a),
  7873. // this.flushActiveItems_(),
  7874. // $u(function() {
  7875. // b.maybeScrollToBottom_()
  7876. // }))
  7877. // }
  7878.  
  7879. } else if (sfi === '1.39.20') {
  7880. // TBC
  7881. } else if (sfi === '1.31.17') {
  7882. // original
  7883. } else if (mclp.handleLiveChatActions3641_){
  7884. } else {
  7885. assertor(() => fnIntegrity(mclp.handleLiveChatActions_, '1.40.20'))
  7886. || logFn('mclp.handleLiveChatActions_', mclp.handleLiveChatActions_)();
  7887. }
  7888.  
  7889. mclp.handleLiveChatActions66_ = mclp.handleLiveChatActions_;
  7890.  
  7891. mclp.handleLiveChatActions_ = function (arr) {
  7892.  
  7893. try {
  7894. preprocessChatLiveActions(arr);
  7895. } catch (e) {
  7896. console.warn(e);
  7897. }
  7898.  
  7899. this.handleLiveChatActions66_(arr);
  7900.  
  7901. resistanceUpdateFn_(true);
  7902. }
  7903. console1.log("handleLiveChatActions_", "OK");
  7904. } else {
  7905. console1.log("handleLiveChatActions_", "NG");
  7906. }
  7907. }
  7908.  
  7909. // we do not need to do user interaction check for Boost Chat (0x40000)
  7910. const noScrollToBottomCheckForBoostChat = (_flag0281_ & 0x40000) === 0x40000;
  7911.  
  7912. if (noScrollToBottomCheckForBoostChat === false) {
  7913.  
  7914. mclp.hasUserJustInteracted11_ = () => {
  7915. const t = dateNow();
  7916. return (t - lastWheel < 80) || currentMouseDown || currentTouchDown || (t - lastUserInteraction < 80);
  7917. }
  7918.  
  7919. if ((mclp.canScrollToBottom_ || 0).length === 0 && !mclp.canScrollToBottom157_) {
  7920.  
  7921. assertor(() => fnIntegrity(mclp.canScrollToBottom_, '0.9.5'));
  7922.  
  7923. mclp.canScrollToBottom157_ = mclp.canScrollToBottom_;
  7924. mclp.canScrollToBottom_ = function () {
  7925. return this.canScrollToBottom157_() && !this.hasUserJustInteracted11_();
  7926. }
  7927.  
  7928. console1.log("canScrollToBottom_", "OK");
  7929.  
  7930.  
  7931. } else {
  7932. console1.log("canScrollToBottom_", "NG");
  7933. }
  7934.  
  7935. }
  7936.  
  7937. if (ENABLE_NO_SMOOTH_TRANSFORM) {
  7938.  
  7939. mclp.isSmoothScrollEnabled_ = function () {
  7940. return false;
  7941. }
  7942.  
  7943. mclp.maybeResizeScrollContainer_ = function () {
  7944. //
  7945. }
  7946.  
  7947. mclp.refreshOffsetContainerHeight_ = function () {
  7948. //
  7949. }
  7950.  
  7951. mclp.smoothScroll_ = function () {
  7952. //
  7953. }
  7954.  
  7955. mclp.resetSmoothScroll_ = function () {
  7956. //
  7957. }
  7958. console1.log("ENABLE_NO_SMOOTH_TRANSFORM", "OK");
  7959. } else {
  7960. console1.log("ENABLE_NO_SMOOTH_TRANSFORM", "NG");
  7961. }
  7962.  
  7963. if ((_flag0281_ & 0x8) == 0) {
  7964.  
  7965.  
  7966. if (typeof mclp.forEachItem_ === 'function' && !mclp.forEachItem66_ && skipErrorForhandleAddChatItemAction_ && mclp.forEachItem_.length === 1) {
  7967.  
  7968. mclp.forEachItem66_ = mclp.forEachItem_;
  7969. mclp.forEachItem_ = function (a) {
  7970.  
  7971. if ((this._flag0281_ & 0x8) == 0x8) return this.forEachItem66_(a);
  7972.  
  7973. // ƒ (a){this.visibleItems.forEach(a.bind(this,"visibleItems"));this.activeItems_.forEach(a.bind(this,"activeItems_"))}
  7974.  
  7975. try {
  7976.  
  7977. let items801 = false;
  7978. if (typeof a === 'function') {
  7979. const items = this.items;
  7980. if (items instanceof HTMLDivElement) {
  7981. const ev = this.visibleItems;
  7982. const ea = this.activeItems_;
  7983. if (ev && ea && ev.length >= 0 && ea.length >= 0) {
  7984. items801 = items;
  7985. }
  7986. }
  7987. }
  7988.  
  7989. if (items801) {
  7990. items801.__children801__ = 1;
  7991. const res = this.forEachItem66_(a);
  7992. items801.__children801__ = 0;
  7993. return res;
  7994. }
  7995.  
  7996. } catch (e) { }
  7997. return this.forEachItem66_(a);
  7998.  
  7999.  
  8000. // this.visibleItems.forEach((val, idx, arr)=>{
  8001. // a.call(this, 'visibleItems', val, idx, arr);
  8002. // });
  8003.  
  8004. // this.activeItems_.forEach((val, idx, arr)=>{
  8005. // a.call(this, 'activeItems_', val, idx, arr);
  8006. // });
  8007.  
  8008.  
  8009.  
  8010. }
  8011.  
  8012.  
  8013. }
  8014.  
  8015. }
  8016.  
  8017. if (typeof mclp.handleAddChatItemAction_ === 'function' && !mclp.handleAddChatItemAction66_ && FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION && (EMOJI_IMAGE_SINGLE_THUMBNAIL || AUTHOR_PHOTO_SINGLE_THUMBNAIL)) {
  8018.  
  8019. mclp.handleAddChatItemAction66_ = mclp.handleAddChatItemAction_;
  8020. mclp.handleAddChatItemAction_ = function (a) {
  8021. try {
  8022. if (a && typeof a === 'object' && !('length' in a)) {
  8023. fixLiveChatItem(a.item, null);
  8024. console.assert(arguments[0] === a);
  8025. }
  8026. } catch (e) { console.warn(e) }
  8027. let res;
  8028. if (skipErrorForhandleAddChatItemAction_) { // YouTube Native Engine Issue
  8029. try {
  8030. res = this.handleAddChatItemAction66_.apply(this, arguments);
  8031. } catch (e) {
  8032. if (e && (e.message || '').includes('.querySelector(')) {
  8033. console.log("skipErrorForhandleAddChatItemAction_", e.message);
  8034. } else {
  8035. throw e;
  8036. }
  8037. }
  8038. } else {
  8039. res = this.handleAddChatItemAction66_.apply(this, arguments);
  8040. }
  8041. return res;
  8042. }
  8043.  
  8044. if (FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION) console1.log("handleAddChatItemAction_ [ FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION ]", "OK");
  8045. } else {
  8046.  
  8047. if (FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION) console1.log("handleAddChatItemAction_ [ FIX_THUMBNAIL_SIZE_ON_ITEM_ADDITION ]", "OK");
  8048. }
  8049.  
  8050.  
  8051. if (typeof mclp.handleReplaceChatItemAction_ === 'function' && !mclp.handleReplaceChatItemAction66_ && FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT && (EMOJI_IMAGE_SINGLE_THUMBNAIL || AUTHOR_PHOTO_SINGLE_THUMBNAIL)) {
  8052.  
  8053. mclp.handleReplaceChatItemAction66_ = mclp.handleReplaceChatItemAction_;
  8054. mclp.handleReplaceChatItemAction_ = function (a) {
  8055. try {
  8056. if (a && typeof a === 'object' && !('length' in a)) {
  8057. fixLiveChatItem(a.replacementItem, null);
  8058. console.assert(arguments[0] === a);
  8059. }
  8060. } catch (e) { console.warn(e) }
  8061. return this.handleReplaceChatItemAction66_.apply(this, arguments);
  8062. }
  8063.  
  8064. if (FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT) console1.log("handleReplaceChatItemAction_ [ FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT ]", "OK");
  8065. } else {
  8066.  
  8067. if (FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT) console1.log("handleReplaceChatItemAction_ [ FIX_THUMBNAIL_SIZE_ON_ITEM_REPLACEMENT ]", "OK");
  8068. }
  8069.  
  8070. console1.log("[End]");
  8071. groupEnd();
  8072.  
  8073. }).catch(console.warn);
  8074.  
  8075.  
  8076. const tickerContainerSetAttribute = function (attrName, attrValue) { // ensure '14.30000001%'.toFixed(1)
  8077.  
  8078. let yd = (this.__dataHost || insp(this).__dataHost || 0).__data;
  8079.  
  8080. if (arguments.length === 2 && attrName === 'style' && yd && attrValue) {
  8081.  
  8082. // let v = yd.containerStyle.privateDoNotAccessOrElseSafeStyleWrappedValue_;
  8083. let v = `${attrValue}`;
  8084. // conside a ticker is 101px width
  8085. // 1% = 1.01px
  8086. // 0.2% = 0.202px
  8087.  
  8088.  
  8089. const ratio1 = (yd.ratio * 100);
  8090. if (ratio1 > -1) { // avoid NaN
  8091.  
  8092. // countdownDurationMs
  8093. // 600000 - 0.2% <1% = 6s> <0.2% = 1.2s>
  8094. // 300000 - 0.5% <1% = 3s> <0.5% = 1.5s>
  8095. // 150000 - 1% <1% = 1.5s>
  8096. // 75000 - 2% <1% =0.75s > <2% = 1.5s>
  8097. // 30000 - 5% <1% =0.3s > <5% = 1.5s>
  8098.  
  8099. // 99px * 5% = 4.95px
  8100.  
  8101. // 15000 - 10% <1% =0.15s > <10% = 1.5s>
  8102.  
  8103.  
  8104. // 1% Duration
  8105.  
  8106. let ratio2 = ratio1;
  8107.  
  8108. const ydd = yd.data;
  8109. if (ydd) {
  8110.  
  8111. const d1 = ydd.durationSec;
  8112. const d2 = ydd.fullDurationSec;
  8113.  
  8114. // @ step timing [min. 0.2%]
  8115. let numOfSteps = 500;
  8116. if ((d1 === d2 || (d1 + 1 === d2)) && d1 > 1) {
  8117. if (d2 > 400) numOfSteps = 500; // 0.2%
  8118. else if (d2 > 200) numOfSteps = 200; // 0.5%
  8119. else if (d2 > 100) numOfSteps = 100; // 1%
  8120. else if (d2 > 50) numOfSteps = 50; // 2%
  8121. else if (d2 > 25) numOfSteps = 20; // 5% (max => 99px * 5% = 4.95px)
  8122. else numOfSteps = 20;
  8123. }
  8124. if (numOfSteps > TICKER_MAX_STEPS_LIMIT) numOfSteps = TICKER_MAX_STEPS_LIMIT;
  8125. if (numOfSteps < 5) numOfSteps = 5;
  8126.  
  8127. const rd = numOfSteps / 100.0;
  8128.  
  8129. ratio2 = Math.round(ratio2 * rd) / rd;
  8130.  
  8131. // ratio2 = Math.round(ratio2 * 5) / 5;
  8132. ratio2 = ratio2.toFixed(1);
  8133. v = v.replace(`${ratio1}%`, `${ratio2}%`).replace(`${ratio1}%`, `${ratio2}%`);
  8134.  
  8135. if (yd.__style_last__ === v) return;
  8136. yd.__style_last__ = v;
  8137. // do not consider any delay here.
  8138. // it shall be inside the looping for all properties changes. all the css background ops are in the same microtask.
  8139.  
  8140. }
  8141. }
  8142.  
  8143. HTMLElement_.prototype.setAttribute.call(dr(this), attrName, v);
  8144.  
  8145.  
  8146. } else {
  8147. HTMLElement_.prototype.setAttribute.apply(dr(this), arguments);
  8148. }
  8149.  
  8150. };
  8151.  
  8152.  
  8153. const fpTicker = (renderer) => {
  8154. const cnt = insp(renderer);
  8155. assertor(() => typeof (cnt || 0).is === 'string');
  8156. assertor(() => ((cnt || 0).hostElement || 0).nodeType === 1);
  8157. const container = (cnt.$ || 0).container;
  8158. if (container) {
  8159. assertor(() => (container || 0).nodeType === 1);
  8160. assertor(() => typeof container.setAttribute === 'function');
  8161. container.setAttribute = tickerContainerSetAttribute;
  8162. } else {
  8163. console.warn(`"container" does not exist in ${cnt.is}`);
  8164. }
  8165. };
  8166.  
  8167.  
  8168. const tags = [
  8169. "yt-live-chat-ticker-renderer",
  8170. "yt-live-chat-ticker-paid-message-item-renderer",
  8171. "yt-live-chat-ticker-paid-sticker-item-renderer",
  8172. "yt-live-chat-ticker-sponsor-item-renderer"
  8173. ];
  8174.  
  8175. const tagsItemRenderer = [
  8176. "yt-live-chat-ticker-renderer",
  8177. "yt-live-chat-ticker-paid-message-item-renderer",
  8178. "yt-live-chat-ticker-paid-sticker-item-renderer",
  8179. "yt-live-chat-ticker-sponsor-item-renderer"
  8180. ];
  8181.  
  8182. // const wmList = new Set;
  8183.  
  8184. Promise.all(tags.map(tag => customElements.whenDefined(tag))).then(() => {
  8185.  
  8186. mightFirstCheckOnYtInit();
  8187. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-ticker-... hacks");
  8188. console1.log("[Begin]");
  8189.  
  8190.  
  8191. let tickerAttachmentId = 0;
  8192.  
  8193.  
  8194. const __requestRemoval__ = function (cnt) {
  8195. if (cnt.hostElement && typeof cnt.requestRemoval === 'function') {
  8196. try {
  8197. const id = (cnt.data || 0).id;
  8198. if (!id) cnt.data = { id: 1 };
  8199. } catch (e) { }
  8200. try {
  8201. cnt.requestRemoval();
  8202. return true;
  8203. } catch (e) { }
  8204. }
  8205. return false;
  8206. }
  8207.  
  8208.  
  8209. const overlayBgMap = new WeakMap();
  8210.  
  8211. const dProto = {
  8212.  
  8213.  
  8214. /**
  8215. *
  8216.  
  8217. f.updateStatsBarAndMaybeShowAnimation = function(a, b, c) {
  8218. var d = this;
  8219. a || c();
  8220. a && this.statsBar && this.username && this.textContent && (this.isMouseOver ? (b(),
  8221. c()) : (a = this.animateShowStats(),
  8222. this.data.animationOrigin && this.data.trackingParams && aB().stateChanged(this.data.trackingParams, {
  8223. animationEventData: {
  8224. origin: this.data.animationOrigin
  8225. }
  8226. }),
  8227. a.finished.then(function() {
  8228. var e;
  8229. setTimeout(function() {
  8230. b();
  8231. c();
  8232. if (!d.isMouseOver) {
  8233. var g, k;
  8234. d.animateHideStats(((g = d.data) == null ? void 0 : g.dynamicStateData.stateSlideDurationMs) || 0, ((k = d.data) == null ? void 0 : k.dynamicStateData.stateUpdateDelayAfterMs) || 0)
  8235. }
  8236. }, ((e = d.data) == null ? void 0 : e.dynamicStateData.stateUpdateDelayBeforeMs) || 0)
  8237. })))
  8238. }
  8239.  
  8240. *
  8241. */
  8242.  
  8243.  
  8244.  
  8245. /**
  8246. *
  8247. *
  8248.  
  8249. f.animateShowStats = function() {
  8250. var a = this.textContent.animate({
  8251. transform: "translateY(-30px)"
  8252. }, {
  8253. duration: this.data.dynamicStateData.stateSlideDurationMs,
  8254. fill: "forwards"
  8255. });
  8256. this.username.animate({
  8257. opacity: 0
  8258. }, {
  8259. duration: 500,
  8260. fill: "forwards"
  8261. });
  8262. this.statsBar.animate({
  8263. opacity: 1
  8264. }, {
  8265. duration: 500,
  8266. fill: "forwards"
  8267. });
  8268. return a
  8269. }
  8270. ;
  8271. f.animateHideStats = function(a, b) {
  8272. this.textContent.animate({
  8273. transform: "translateY(0)"
  8274. }, {
  8275. duration: a,
  8276. fill: "forwards",
  8277. delay: b
  8278. });
  8279. this.username.animate({
  8280. opacity: 1
  8281. }, {
  8282. duration: 300,
  8283. fill: "forwards",
  8284. delay: b
  8285. });
  8286. this.statsBar.animate({
  8287. opacity: 0
  8288. }, {
  8289. duration: 300,
  8290. fill: "forwards",
  8291. delay: b
  8292. })
  8293. }
  8294. *
  8295. */
  8296.  
  8297. updateStatsBarAndMaybeShowAnimationRevised: function (a, b, c) {
  8298. // prevent memory leakage due to d.data was asked in a.finished.then
  8299. try{
  8300. // console.log('updateStatsBarAndMaybeShowAnimation called', this.is)
  8301. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8302. return this.updateStatsBarAndMaybeShowAnimation38.call(this.__proxySelf0__, a, b, c);
  8303. }catch(e){
  8304. console.log('updateStatsBarAndMaybeShowAnimationRevised ERROR');
  8305. console.error(e);
  8306. }
  8307. },
  8308.  
  8309. detachedForMemoryLeakage: function () {
  8310.  
  8311. try{
  8312.  
  8313. this.actionHandlerBehavior.unregisterActionMap(this.behaviorActionMap)
  8314.  
  8315. // this.behaviorActionMap = 0;
  8316. // this.isVisibilityRoot = 0;
  8317.  
  8318.  
  8319. }catch(e){}
  8320.  
  8321. return this.detached582MemoryLeak();
  8322. },
  8323.  
  8324. detachedForTickerInit: function () {
  8325.  
  8326. Promise.resolve(this).then((cnt) => {
  8327. if (cnt.isAttached) return;
  8328. cnt.isAttached === false && ((cnt.$ || 0).container || 0).isConnected === false && __requestRemoval__(cnt);
  8329. cnt.rafId > 1 && rafHub.cancel(cnt.rafId);
  8330. }).catch(console.warn);
  8331.  
  8332.  
  8333. const hostElement = (this || 0).hostElement;
  8334. if (USE_ADVANCED_TICKING && (this || 0).__isTickerItem58__ && hostElement instanceof HTMLElement_) {
  8335. // otherwise the startCountDown not working
  8336. hostElement.style.removeProperty('--ticker-start-time');
  8337. hostElement.style.removeProperty('--ticker-duration-time');
  8338.  
  8339. if (kRef(qWidthAdjustable) === hostElement) {
  8340.  
  8341. // need to update the first ticker
  8342. const q = document.querySelector('.r6-width-adjustable');
  8343. if (q instanceof HTMLElement_ && q.classList.contains('r6-width-adjustable-f')) {
  8344. q.classList.remove('r6-width-adjustable-f');
  8345. }
  8346. qWidthAdjustable = mWeakRef(q);
  8347.  
  8348. }
  8349. }
  8350.  
  8351. let r;
  8352. try {
  8353. r = this.detached77();
  8354. } catch (e) {
  8355. console.warn(e);
  8356. }
  8357. this.__ticker_attachmentId__ = 0;
  8358. return r;
  8359. },
  8360.  
  8361. attachedForTickerInit: function () {
  8362. this.__ticker_attachmentId__ = tickerAttachmentId = (tickerAttachmentId & 1073741823) + 1;
  8363.  
  8364. const hostElement = (this || 0).hostElement;
  8365. if (USE_ADVANCED_TICKING && (this || 0).__isTickerItem58__ && hostElement instanceof HTMLElement_) {
  8366. const prevElement = kRef(qWidthAdjustable);
  8367. if (prevElement instanceof HTMLElement_) {
  8368. prevElement.classList.add('r6-width-adjustable-f');
  8369. }
  8370. if (hostElement.__fgvm573__) {
  8371. hostElement.classList.remove('r6-closing-ticker');
  8372. hostElement.classList.remove('r6-width-adjustable-f');
  8373. } else {
  8374. hostElement.__fgvm573__ = 1;
  8375. hostElement.classList.add('r6-width-adjustable');
  8376. }
  8377. qWidthAdjustable = mWeakRef(hostElement);
  8378. }
  8379.  
  8380.  
  8381. fpTicker(hostElement || this);
  8382. return this.attached77();
  8383.  
  8384. },
  8385.  
  8386.  
  8387.  
  8388. setContainerWidthNoSelfLeakage: function(){
  8389. // prevent memory leakage due ot delay function
  8390. try{
  8391. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8392. return this.setContainerWidth55.call(this.__proxySelf0__);
  8393. }catch(e){
  8394. console.log('setContainerWidthNoSelfLeakage ERROR');
  8395. console.error(e);
  8396. }
  8397.  
  8398. },
  8399.  
  8400. slideDownNoSelfLeakage: function(){
  8401. // prevent memory leakage due ot delay function
  8402. try{
  8403. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8404. return this.slideDown55.call(this.__proxySelf0__);
  8405. }catch(e){
  8406. console.log('slideDownNoSelfLeakage ERROR');
  8407. console.error(e);
  8408. }
  8409.  
  8410. },
  8411.  
  8412. collapseNoSelfLeakage: function(){
  8413. // prevent memory leakage due ot delay function
  8414. try{
  8415. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8416. return this.collapse55.call(this.__proxySelf0__);
  8417. }catch(e){
  8418. console.log('collapseNoSelfLeakage ERROR');
  8419. console.error(e);
  8420. }
  8421. },
  8422.  
  8423. deletedChangedNoSelfLeakage: function(){
  8424. // prevent memory leakage due ot delay function
  8425. try{
  8426. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  8427. return this.deletedChanged55.call(this.__proxySelf0__);
  8428. }catch(e){
  8429. console.log('deletedChangedNoSelfLeakage ERROR');
  8430. console.error(e);
  8431. }
  8432.  
  8433. },
  8434.  
  8435.  
  8436.  
  8437.  
  8438. /** @type {()} */
  8439. handlePauseReplayForPlaybackProgressState: function () {
  8440. if (!playerEventsByIframeRelay) return this.handlePauseReplay66.apply(this, arguments);
  8441.  
  8442. const attachementId = this.__ticker_attachmentId__;
  8443. if(!attachementId) return;
  8444.  
  8445. const jr = mWeakRef(this);
  8446.  
  8447. if (onPlayStateChangePromise) {
  8448.  
  8449. const tid = this._Y7rtu = (this._Y7rtu & 1073741823) + 1;
  8450.  
  8451. onPlayStateChangePromise.then(() => {
  8452. const cnt = kRef(jr) || 0;
  8453. if (attachementId !== cnt.__ticker_attachmentId__) return;
  8454. if (cnt.isAttached) {
  8455. if (tid === cnt._Y7rtu && !onPlayStateChangePromise && typeof cnt.handlePauseReplay === 'function' && cnt.hostElement) cnt.handlePauseReplay.apply(cnt, arguments);
  8456. // this.handlePauseReplay can be undefined if it is memory cleaned
  8457. }
  8458. });
  8459.  
  8460. return;
  8461. }
  8462.  
  8463. if (playerState !== 2) return;
  8464. if (this.isAttached) {
  8465. const tid = this._Y7rtk = (this._Y7rtk & 1073741823) + 1;
  8466. const tc = relayCount;
  8467. foregroundPromiseFn().then(() => {
  8468. const cnt = kRef(jr);
  8469. if (attachementId !== (cnt || 0).__ticker_attachmentId__) return;
  8470. if (cnt.isAttached) {
  8471. if (tid === cnt._Y7rtk && tc === relayCount && playerState === 2 && _playerState === playerState && cnt.hostElement) {
  8472. cnt.handlePauseReplay66();
  8473. }
  8474. }
  8475. })
  8476. }
  8477. },
  8478.  
  8479. /** @type {()} */
  8480. handleResumeReplayForPlaybackProgressState: function () {
  8481. if (!playerEventsByIframeRelay) return this.handleResumeReplay66.apply(this, arguments);
  8482.  
  8483. const attachementId = this.__ticker_attachmentId__;
  8484. if(!attachementId) return;
  8485.  
  8486. const jr = mWeakRef(this);
  8487. if (onPlayStateChangePromise) {
  8488.  
  8489. const tid = this._Y7rtv = (this._Y7rtv & 1073741823) + 1;
  8490.  
  8491. onPlayStateChangePromise.then(() => {
  8492. const cnt = kRef(jr);
  8493. if(attachementId !== (cnt || 0).__ticker_attachmentId__) return;
  8494. if (tid === cnt._Y7rtv && !onPlayStateChangePromise && typeof cnt.handleResumeReplay === 'function' && cnt.hostElement) cnt.handleResumeReplay.apply(cnt, arguments);
  8495. // this.handleResumeReplay can be undefined if it is memory cleaned
  8496. });
  8497.  
  8498. return;
  8499. }
  8500.  
  8501.  
  8502. if (playerState !== 1) return;
  8503. if (this.isAttached) {
  8504. const tc = relayCount;
  8505.  
  8506. relayPromise = relayPromise || new PromiseExternal();
  8507. relayPromise.then(() => {
  8508. const cnt = kRef(jr);
  8509. if(attachementId !== (cnt || 0).__ticker_attachmentId__) return;
  8510. if (relayCount > tc && playerState === 1 && _playerState === playerState && cnt.hostElement) {
  8511. cnt.handleResumeReplay66();
  8512. }
  8513. });
  8514. }
  8515. },
  8516.  
  8517. /** @type {(a,)} */
  8518. handleReplayProgressForPlaybackProgressState: function (a) {
  8519. if (this.isAttached) {
  8520. const attachementId = this.__ticker_attachmentId__;
  8521. if(!attachementId) return;
  8522. const tid = this._Y7rtk = (this._Y7rtk & 1073741823) + 1;
  8523. const jr = mWeakRef(kRef(this));
  8524. foregroundPromiseFn().then(() => {
  8525. const cnt = kRef(jr);
  8526. if(attachementId !== (cnt || 0).__ticker_attachmentId__) return;
  8527. if (cnt.isAttached) {
  8528. if (tid === cnt._Y7rtk && cnt.hostElement) {
  8529. cnt.handleReplayProgress66(a);
  8530. }
  8531. }
  8532. })
  8533. }
  8534. }
  8535.  
  8536.  
  8537. }
  8538.  
  8539.  
  8540.  
  8541. const isTickerItemsScrolling = function () {
  8542. const elm = document.querySelector('#ticker-bar.yt-live-chat-ticker-renderer');
  8543. if (!elm) return false;
  8544. return (elm.scrollLeft > 0);
  8545. }
  8546.  
  8547.  
  8548.  
  8549.  
  8550. const u37fn = function (cnt) {
  8551.  
  8552. if (cnt.__dataEnabled === false || cnt.__dataInvalid === true) return;
  8553.  
  8554. if (!__LCRInjection__) {
  8555. console.error('[yt-chat] USE_ADVANCED_TICKING fails because of no __LCRInjection__');
  8556. }
  8557.  
  8558. const cntData = ((cnt || 0).__data || 0).data || (cnt || 0).data || 0;
  8559. if (!cntData) return;
  8560. const cntElement = cnt.hostElement;
  8561. if (!(cntElement instanceof HTMLElement_)) return;
  8562.  
  8563. const duration = (cntData.fullDurationSec || cntData.durationSec || 0);
  8564.  
  8565. let ct;
  8566.  
  8567. if (__LCRInjection__ && cntData && duration > 0 && !('__progressAt__' in cntData)) {
  8568. ct = Date.now();
  8569. cntData.__liveTimestamp__ = (cntData.__timestampActionRequest__ || ct) / 1000 - timeOriginDT / 1000;
  8570. timestampUnderLiveMode = true;
  8571. } else if (__LCRInjection__ && cntData && duration > 0 && cntData.__progressAt__ > 0) {
  8572. timestampUnderLiveMode = false;
  8573. }
  8574. // console.log(48117007, cntData)
  8575.  
  8576. let tk = cntData.__progressAt__ || cntData.__liveTimestamp__;
  8577.  
  8578. if (!tk) {
  8579. console.log('time property is not found', !!__LCRInjection__, !!cntData, !!(duration > 0), !('__progressAt__' in cntData), cntData.__progressAt__, cntData.__liveTimestamp__);
  8580. return;
  8581. }
  8582.  
  8583.  
  8584.  
  8585. const liveOffsetMs = ct > 0 && cntData.__timestampActionRequest__ > 0 ? ct - cntData.__timestampActionRequest__ : 0;
  8586.  
  8587. // console.log(1237, liveOffsetMs, cntData.durationSec)
  8588.  
  8589. if (liveOffsetMs > 0) {
  8590. cntData.durationSec -= Math.floor(liveOffsetMs / 1000);
  8591. if (cntData.durationSec < 0) cntData.durationSec = 0;
  8592. // console.log(1238, liveOffsetMs, cntData.durationSec)
  8593. if (!cntData.durationSec) {
  8594. try {
  8595. cnt.requestRemoval();
  8596. } catch (e) { }
  8597. return;
  8598. }
  8599. }
  8600.  
  8601.  
  8602. let offset = cntData.fullDurationSec - cntData.durationSec; // consider this is live replay video, offset can be > 0
  8603. if (offset > 0) tk -= offset;
  8604. // in livestreaming. tk can be negative as we use performance.timeOrigin for t=0s time frame
  8605.  
  8606.  
  8607.  
  8608. const existingOverlaySelector = `ticker-bg-overlay[ticker-id="${cnt.__ticker_attachmentId__}"]`;
  8609.  
  8610. const q = kRef(overlayBgMap.get(cnt));
  8611.  
  8612. let r = valAssign(cntElement, '--ticker-start-time', tk);
  8613.  
  8614. if ((r || !q || q.isConnected === false) && duration > 0) {
  8615.  
  8616. // t0 ...... 1 ... fullDurationSec
  8617. // tk ...... k ... fullDurationSec-durationSec
  8618. // t0-fullDurationSec ...... 0 ... 0
  8619.  
  8620. // now - (fullDurationSec-durationSec)
  8621.  
  8622.  
  8623. // update dntElementWeak
  8624. const dnt = cnt.parentComponent;
  8625. const dntElement = dnt ? dnt.hostElement || dnt : 0;
  8626. if (dntElement) {
  8627. dntElementWeak = mWeakRef(dntElement);
  8628. resistanceUpdateBusy = false;
  8629. if (!startResistanceUpdaterStarted) startResistanceUpdater();
  8630. else updateTickerCurrentTime();
  8631. }
  8632.  
  8633.  
  8634. // create overlay if needed
  8635. if (!cntElement.querySelector(existingOverlaySelector)) {
  8636.  
  8637. // remove if any
  8638. const oldElement = cntElement.querySelector('ticker-bg-overlay');
  8639. if (oldElement) oldElement.remove();
  8640.  
  8641. // use advancedTicking, ticker enabled
  8642. cnt.__advancedTicking038__ = 1;
  8643.  
  8644. const em = q || document.createElement('ticker-bg-overlay');
  8645.  
  8646. overlayBgMap.set(cnt, mWeakRef(em));
  8647. // const ey = document.createElement('ticker-bg-overlay-end');
  8648. const wy = document.createElement('ticker-bg-overlay-end2');
  8649.  
  8650. const cr1 = cnt.colorFromDecimal(cntData.startBackgroundColor);
  8651. const cr2 = cnt.colorFromDecimal(cntData.endBackgroundColor);
  8652.  
  8653. const container = cnt.$.container;
  8654.  
  8655. em.setAttribute('ticker-id', `${cnt.__ticker_attachmentId__}`);
  8656.  
  8657. const tid = `ticker-${cnt.__ticker_attachmentId__}-${Math.floor(Math.random() * 314159265359 + 314159265359).toString(36)}`;
  8658.  
  8659. em.id = `${tid}-b`;
  8660. em.style.background = `linear-gradient(90deg, ${cr1},${cr1} 50%,${cr2} 50%,${cr2})`;
  8661.  
  8662. if (!(container instanceof HTMLElement_)) {
  8663. // em.insertBefore(ey, em.firstChild);
  8664. insertBeforeNaFn(cntElement, em, cntElement.firstChild); // cntElement.insertBefore(em, cntElement.firstChild);
  8665. cntElement.style.borderRadius = '16px';
  8666. container.style.borderRadius = 'initial';
  8667. } else {
  8668. // em.insertBefore(ey, em.firstChild);
  8669. insertBeforeNaFn(container, em, container.firstChild); // container.insertBefore(em, container.firstChild);
  8670. }
  8671.  
  8672. // em.style.left = '-50%';
  8673. // em.style.left = "clamp(-100%, calc( -100% * ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) ), 0%)";
  8674.  
  8675. if (container instanceof HTMLElement_) {
  8676.  
  8677. container.style.background = 'transparent';
  8678. container.style.backgroundColor = 'transparent';
  8679. // container.style.zIndex = '1';
  8680. }
  8681. // em.style.zIndex = '-1';
  8682. valAssign(cntElement, '--ticker-duration-time', duration)
  8683.  
  8684. valAssign(wy, '--ticker-start-time', tk);
  8685. valAssign(wy, '--ticker-duration-time', duration);
  8686. wy.id = `${tid}-e`;
  8687.  
  8688. appendChildNaFn(dntElement, wy);
  8689.  
  8690. // if (wio instanceof IntersectionObserver) {
  8691. // wio.observe(ey);
  8692. // }
  8693.  
  8694. const wio2 = dProto.wio2;
  8695. if (wio2 instanceof IntersectionObserver) {
  8696. wio2.observe(wy);
  8697. }
  8698.  
  8699. }
  8700. }
  8701. };
  8702.  
  8703.  
  8704.  
  8705. const timeFn748 = async (cnt) => {
  8706.  
  8707.  
  8708. if (cnt.data) {
  8709. const data = cnt.data;
  8710. cnt[`_pr7_${data.id}`] = new PromiseExternal();
  8711. cnt[`_pr9_${data.id}`] = new PromiseExternal();
  8712. } else {
  8713. cnt[`_pr7_${data.id}`] = null;
  8714. cnt[`_pr9_${data.id}`] = null;
  8715. }
  8716.  
  8717.  
  8718. if (cnt && cnt.data) {
  8719. const data = cnt.data;
  8720. const pr = cnt[`_pr7_${data.id}`]
  8721. const pr9 = cnt[`_pr9_${data.id}`]
  8722. if (pr) await pr;
  8723. if (cnt[`_pr7_${data.id}`] === pr) cnt[`_pr7_${data.id}`] = null;
  8724. const parentComponent = cnt.parentComponent;
  8725. if (parentComponent) {
  8726. const pr = insp(parentComponent).ec389pr;
  8727. if (pr) await pr;
  8728. }
  8729. pr9.resolve();
  8730. }
  8731.  
  8732. if(
  8733. cnt
  8734. && (cnt.hostElement && cnt.isAttached && cnt.hostElement.isConnected )
  8735. && cnt.parentComponent // startCountdown is triggered by dataChanged; // not yet attached to the actual dom tree
  8736. && cnt.__ticker_attachmentId__
  8737. ){
  8738. Promise.resolve(cnt).then(u37fn);
  8739.  
  8740. }
  8741.  
  8742.  
  8743.  
  8744.  
  8745. if (cnt.data) {
  8746. const data = cnt.data;
  8747. if (cnt.hostElement && cnt.isAttached, cnt.hostElement?.isConnected && cnt.parentComponent) {
  8748. const pr = cnt[`_pr7_${data.id}`];
  8749. if (pr) {
  8750. cnt[`_pr7_${data.id}`] = null;
  8751. pr.resolve();
  8752. }
  8753. }
  8754. }
  8755. cnt.pz483 = ((cnt.pz483 || 0) & 1073741823) + 1;
  8756.  
  8757. };
  8758.  
  8759. let tagI = 0;
  8760. for (const tag of tagsItemRenderer) { // ##tag##
  8761.  
  8762. tagI++;
  8763.  
  8764. const dummy = document.createElement(tag);
  8765.  
  8766. const cProto = getProto(dummy);
  8767. if (!cProto || !cProto.attached) {
  8768. console1.warn(`proto.attached for ${tag} is unavailable.`);
  8769. continue;
  8770. }
  8771.  
  8772. if (FIX_MEMORY_LEAKAGE_TICKER_ACTIONMAP && typeof cProto.detached582MemoryLeak !== 'function' && typeof cProto.detached === 'function') {
  8773. cProto.detached582MemoryLeak = cProto.detached;
  8774. cProto.detached = dProto.detachedForMemoryLeakage;
  8775. }
  8776.  
  8777. cProto.detached77 = cProto.detached;
  8778. cProto.detached = dProto.detachedForTickerInit;
  8779.  
  8780. cProto.attached77 = cProto.attached;
  8781.  
  8782. cProto.attached = dProto.attachedForTickerInit;
  8783.  
  8784. let flgLeakageFixApplied = 0;
  8785.  
  8786. if (FIX_MEMORY_LEAKAGE_TICKER_STATSBAR && typeof cProto.updateStatsBarAndMaybeShowAnimation === 'function' && !cProto.updateStatsBarAndMaybeShowAnimation38 && cProto.updateStatsBarAndMaybeShowAnimation.length === 3) {
  8787.  
  8788. cProto.updateStatsBarAndMaybeShowAnimation38 = cProto.updateStatsBarAndMaybeShowAnimation;
  8789. cProto.updateStatsBarAndMaybeShowAnimation = dProto.updateStatsBarAndMaybeShowAnimationRevised;
  8790.  
  8791. flgLeakageFixApplied |= 2;
  8792. } else {
  8793. // the function is only in yt-live-chat-ticker-paid-message-item-renderer
  8794. }
  8795.  
  8796.  
  8797. // ------------- withTimerFn_ -------------
  8798.  
  8799. let withTimerFn_ = 0;
  8800. if (typeof cProto.startCountdown === 'function' && typeof cProto.updateTimeout === 'function' && typeof cProto.isAnimationPausedChanged === 'function') {
  8801.  
  8802. // console.log('startCountdown', typeof cProto.startCountdown)
  8803. // console.log('updateTimeout', typeof cProto.updateTimeout)
  8804. // console.log('isAnimationPausedChanged', typeof cProto.isAnimationPausedChanged)
  8805.  
  8806. // <<< to be reviewed cProto.updateTimeout --- isTimingFunctionHackable -- doHack >>>
  8807. const isTimingFunctionHackable = fnIntegrity(cProto.startCountdown, '2.66.37') && fnIntegrity(cProto.updateTimeout, '1.76.45') && fnIntegrity(cProto.isAnimationPausedChanged, '2.56.30')
  8808. if (!isTimingFunctionHackable) console1.log('isTimingFunctionHackable = false');
  8809. withTimerFn_ = isTimingFunctionHackable ? 2 : 1;
  8810. } else {
  8811. let flag = 0;
  8812. if (typeof cProto.startCountdown === 'function') flag |= 1;
  8813. if (typeof cProto.updateTimeout === 'function') flag |= 2;
  8814. if (typeof cProto.isAnimationPausedChanged === 'function') flag |= 4;
  8815.  
  8816. console1.log(`Skip Timing Function Modification[#${tagI}]: ${flag} / ${1 + 2 + 4}`, ` ${tag}`);
  8817. // console.log(Object.getOwnPropertyNames(cProto))
  8818. // continue;
  8819. }
  8820.  
  8821. // ------------- withTimerFn_ -------------
  8822.  
  8823. // ------------- ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX -------------
  8824.  
  8825. let urt = 0;
  8826.  
  8827. if (ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX) {
  8828.  
  8829.  
  8830. /**
  8831. *
  8832. f.handlePauseReplay = function() {
  8833. this.isAnimationPaused = !0;
  8834. this.detlaSincePausedSecs = 0
  8835. }
  8836. */
  8837.  
  8838. /**
  8839. *
  8840.  
  8841. f.handlePauseReplay = function() {
  8842. this.isReplayPaused = !0
  8843. }
  8844. *
  8845. */
  8846.  
  8847. if (typeof cProto.handlePauseReplay === 'function' && !cProto.handlePauseReplay66 && cProto.handlePauseReplay.length === 0) {
  8848. const fi = fnIntegrity(cProto.handlePauseReplay);
  8849. urt++;
  8850. if (fi === '0.8.2' || fi === '0.12.4') {
  8851. } else {
  8852. assertor(() => fnIntegrity(cProto.handlePauseReplay, '0.12.4'));
  8853. }
  8854. } else {
  8855. if (withTimerFn_ > 0) console1.log('Error for setting cProto.handlePauseReplay', tag)
  8856. }
  8857.  
  8858. if (typeof cProto.handleResumeReplay === 'function' && !cProto.handleResumeReplay66 && cProto.handleResumeReplay.length === 0) {
  8859. urt++;
  8860. assertor(() => fnIntegrity(cProto.handleResumeReplay, '0.8.2'));
  8861. } else {
  8862. if (withTimerFn_ > 0) console1.log('Error for setting cProto.handleResumeReplay', tag)
  8863. }
  8864.  
  8865. if (typeof cProto.handleReplayProgress === 'function' && !cProto.handleReplayProgress66 && cProto.handleReplayProgress.length === 1) {
  8866. urt++;
  8867. assertor(() => fnIntegrity(cProto.handleReplayProgress, '1.16.13'));
  8868. } else {
  8869. if (withTimerFn_ > 0) console1.log('Error for setting cProto.handleReplayProgress', tag)
  8870. }
  8871.  
  8872.  
  8873.  
  8874. }
  8875.  
  8876. 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);
  8877. cProto.__ENABLE_VIDEO_PROGRESS_STATE_FIX_AND_URT_PASSED__ = ENABLE_VIDEO_PROGRESS_STATE_FIX_AND_URT_PASSED;
  8878.  
  8879. if (ENABLE_VIDEO_PROGRESS_STATE_FIX_AND_URT_PASSED) {
  8880.  
  8881. cProto._Y7rtk = 0;
  8882. cProto._Y7rtu = 0;
  8883. cProto._Y7rtv = 0;
  8884.  
  8885. cProto.handlePauseReplay66 = cProto.handlePauseReplay;
  8886. cProto.handlePauseReplay = dProto.handlePauseReplayForPlaybackProgressState;
  8887.  
  8888. cProto.handleResumeReplay66 = cProto.handleResumeReplay;
  8889. cProto.handleResumeReplay = dProto.handleResumeReplayForPlaybackProgressState;
  8890.  
  8891. cProto.handleReplayProgress66 = cProto.handleReplayProgress;
  8892. cProto.handleReplayProgress = dProto.handleReplayProgressForPlaybackProgressState;
  8893.  
  8894. }
  8895.  
  8896. // ------------- ENABLE_VIDEO_PLAYBACK_PROGRESS_STATE_FIX -------------
  8897.  
  8898. // ------------- FIX_MEMORY_LEAKAGE_TICKER_TIMER -------------
  8899.  
  8900. if (FIX_MEMORY_LEAKAGE_TICKER_TIMER) {
  8901. if (!USE_ADVANCED_TICKING && typeof cProto.setContainerWidth === 'function' && !cProto.setContainerWidth55 && cProto.setContainerWidth.length === 0) {
  8902. cProto.setContainerWidth55 = cProto.setContainerWidth;
  8903. cProto.setContainerWidth = dProto.setContainerWidthNoSelfLeakage;
  8904. flgLeakageFixApplied |= 4;
  8905. }
  8906. if (!USE_ADVANCED_TICKING && typeof cProto.slideDown === 'function' && !cProto.slideDown55 && cProto.slideDown.length === 0) {
  8907. cProto.slideDown55 = cProto.slideDown;
  8908. cProto.slideDown = dProto.slideDownNoSelfLeakage;
  8909. flgLeakageFixApplied |= 8;
  8910. }
  8911. if (!USE_ADVANCED_TICKING && typeof cProto.collapse === 'function' && !cProto.collapse55 && cProto.collapse.length === 0) {
  8912. cProto.collapse55 = cProto.collapse;
  8913. cProto.collapse = dProto.collapseNoSelfLeakage;
  8914. flgLeakageFixApplied |= 16;
  8915. }
  8916. if (typeof cProto.deletedChanged === 'function' && !cProto.deletedChanged55 && cProto.deletedChanged.length === 0) {
  8917.  
  8918. cProto.deletedChanged55 = cProto.deletedChanged;
  8919. cProto.deletedChanged = dProto.deletedChangedNoSelfLeakage;
  8920. flgLeakageFixApplied |= 32;
  8921. }
  8922.  
  8923. }
  8924.  
  8925. const flgTotal = USE_ADVANCED_TICKING ? 1 + 2 + 32 : 1 + 2 + 4 + 8 + 16 + 32;
  8926.  
  8927. console1.log(`FIX_MEMORY_LEAKAGE_TICKER_[#${tagI}]: ${flgLeakageFixApplied} / ${flgTotal}`, cProto.is);
  8928.  
  8929. // ------------- FIX_MEMORY_LEAKAGE_TICKER_TIMER -------------
  8930.  
  8931.  
  8932.  
  8933. const canDoAdvancedTicking = 1 &&
  8934. ATTEMPT_TICKER_ANIMATION_START_TIME_DETECTION &&
  8935. typeof cProto.startCountdown === 'function' && !cProto.startCountdown49 && cProto.startCountdown.length === 2 &&
  8936. typeof cProto.updateTimeout === 'function' && !cProto.updateTimeout49 && cProto.updateTimeout.length === 1 &&
  8937. typeof cProto.isAnimationPausedChanged === 'function' && !cProto.isAnimationPausedChanged49 && cProto.isAnimationPausedChanged.length === 2 &&
  8938. typeof cProto.setContainerWidth === 'function' && cProto.setContainerWidth.length === 0 &&
  8939. typeof cProto.requestRemoval === 'function' && !cProto.requestRemoval49 && cProto.requestRemoval.length === 0
  8940. CSS.supports("left","clamp(-100%, calc( -100% * ( var(--ticker-current-time) - var(--ticker-start-time) ) / var(--ticker-duration-time) ), 0%)");
  8941.  
  8942.  
  8943.  
  8944. if (USE_ADVANCED_TICKING && canDoAdvancedTicking && ENABLE_TICKERS_BOOSTED_STAMPING) {
  8945. // startResistanceUpdater();
  8946. // live replay video -> 48117005 -> 48117006 keep fire. ->48117007 0 -> 48117007 {...}
  8947. // live stream video -> 48117007 0 -> 48117007 YES
  8948.  
  8949. document.documentElement.setAttribute('r6-advanced-ticking', '');
  8950. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::START`)
  8951.  
  8952. const wio2 = dProto.wio2 || (dProto.wio2 = new IntersectionObserver((mutations) => {
  8953.  
  8954. for (const mutation of mutations) {
  8955. if (mutation.isIntersecting) {
  8956.  
  8957. const marker = mutation.target;
  8958. let endId = marker.id
  8959. if (!endId) continue;
  8960. let tid = endId.substring(0, endId.length - 2);
  8961. if (!tid) continue;
  8962. // let bId = `${tid}-b`;
  8963. const bgElm = document.querySelector(`#${tid}-b`);
  8964. if (!bgElm) continue;
  8965. const overlay = bgElm;
  8966.  
  8967. wio2.unobserve(marker);
  8968. marker.remove();
  8969. let p = overlay || 0;
  8970. let cn = 4;
  8971. while ((p = p.parentElement) instanceof HTMLElement_) {
  8972. if (p instanceof HTMLElement_) {
  8973. const cnt = insp(p);
  8974. if (cnt && typeof cnt.slideDown === 'function' && typeof cnt.setContainerWidth === 'function' && cnt.__advancedTicking038__ === 1) {
  8975.  
  8976. cnt.__advancedTicking038__ = 2;
  8977.  
  8978. let deletionMode = false;
  8979. const cntData = ((cnt || 0).__data || 0).data || (cnt || 0).data || 0;
  8980. if (timestampUnderLiveMode && cntData && cntData.durationSec > 0 && cntData.__timestampActionRequest__ > 0) {
  8981.  
  8982. // time choose - 0.2s for transition (slideDown sliding-down)
  8983. // 60hz = 17ms
  8984. // choose 0.28s
  8985. const targetFutureTime = cntData.__timestampActionRequest__ + cntData.durationSec * 1000;
  8986. // check whether the targetFutureTime is already the past
  8987. if (targetFutureTime + 280 < Date.now()) {
  8988. // just dispose
  8989. deletionMode = true;
  8990. }
  8991. } else if (__LCRInjection__ && !timestampUnderLiveMode && cntData && cntData.durationSec > 0 && cntData.__progressAt__ > 0) {
  8992.  
  8993. const targetFutureTime = (cntData.__progressAt__ + cntData.durationSec);
  8994. // check whether the targetFutureTime is already the past
  8995. if (targetFutureTime + 0.28 < playerProgressChangedArg1) {
  8996. // just dispose
  8997. deletionMode = true;
  8998. }
  8999.  
  9000.  
  9001. }
  9002.  
  9003.  
  9004. if (deletionMode) {
  9005. __requestRemoval__(cnt);
  9006. } else {
  9007.  
  9008. const w = cnt.hostElement.style.width;
  9009. if (w === "auto" || w === "") cnt.setContainerWidth();
  9010. cnt.slideDown();
  9011. }
  9012.  
  9013. break;
  9014. }
  9015. }
  9016. cn--;
  9017. if (!cn) {
  9018. console.log('cnt not found for ticker-bg-overlay');
  9019. break;
  9020. }
  9021. }
  9022.  
  9023.  
  9024. }
  9025. }
  9026.  
  9027. // console.log(mutations);
  9028. }, {
  9029.  
  9030. rootMargin: '0px',
  9031. threshold: [1]
  9032.  
  9033. }));
  9034.  
  9035.  
  9036.  
  9037. cProto.__isTickerItem58__ = 1;
  9038. cProto.attached747 = cProto.attached;
  9039. cProto.attached = function () {
  9040. Promise.resolve().then(()=>{
  9041. if(this.hostElement && this.isAttached && this.hostElement.isConnected && this.parentComponent){
  9042. const data = this.data;
  9043. if(data){
  9044. const pr = this[`_pr7_${data.id}`]
  9045. if(pr){
  9046. this[`_pr7_${data.id}`] = null;
  9047. pr.resolve();
  9048. }
  9049. }
  9050.  
  9051. }
  9052. }).catch(console.warn);
  9053. return this.attached747();
  9054. };
  9055. cProto.setContainerWidth371 = cProto.setContainerWidth;
  9056. cProto.setContainerWidthPr9 = function(){
  9057. if (this.pz485 !== this.pz483) {
  9058. this.pz485 = this.pz483;
  9059. const cnt = this;
  9060. if (cnt && cnt.data) {
  9061. const data = cnt.data;
  9062. const pr9 = cnt[`_pr9_${data.id}`]
  9063. if (pr9) {
  9064. return pr9;
  9065. }
  9066. }
  9067. }
  9068. }
  9069. cProto.startCountdown = dProto.startCountdownAdv || (dProto.startCountdownAdv = function (a, b) {
  9070.  
  9071.  
  9072. timeFn748(kRef(this));
  9073.  
  9074.  
  9075. });
  9076.  
  9077. cProto.updateTimeout = dProto.updateTimeoutAdv || (dProto.updateTimeoutAdv = function (a) {
  9078.  
  9079.  
  9080.  
  9081. });
  9082.  
  9083. cProto.isAnimationPausedChanged = dProto.isAnimationPausedChangedAdv || (dProto.isAnimationPausedChangedAdv = function (a, b) {
  9084.  
  9085.  
  9086.  
  9087. });
  9088.  
  9089.  
  9090. if (typeof cProto.slideDown === 'function' && !cProto.slideDown43 && cProto.slideDown.length === 0) {
  9091.  
  9092. cProto.slideDown43 = cProto.slideDown;
  9093. cProto.slideDown = dProto.slideDownAdv || (dProto.slideDownAdv = async function () {
  9094.  
  9095. // console.log('calling slideDown', Date.now())
  9096. if (this.__advancedTicking038__) {
  9097.  
  9098. if (this.__advancedTicking038__ === 1) this.__advancedTicking038__ = 2; // ignore intersectionobserver detection
  9099.  
  9100.  
  9101. const hostElement = this.hostElement;
  9102. const container = this.$.container;
  9103.  
  9104. const parentComponentCnt = insp(this.parentComponent);
  9105. const parentComponentElm = parentComponentCnt? parentComponentCnt.hostElement : null;
  9106.  
  9107. if (hostElement instanceof HTMLElement_ && container instanceof HTMLElement_ && parentComponentElm instanceof HTMLElement_) {
  9108. // const prevTransitionClosingElm = kRef(prevTransitionClosing);
  9109. // if (prevTransitionClosingElm !== hostElement) {
  9110. // prevTransitionClosingElm && prevTransitionClosingElm.classList.add('ticker-no-transition-time');
  9111. // prevTransitionClosing = mWeakRef(hostElement);
  9112. // }
  9113. // if (hostElement.classList.contains('ticker-no-transition-time')) hostElement.classList.remove('ticker-no-transition-time');
  9114. hostElement.classList.add('r6-closing-ticker');
  9115.  
  9116. if (!transitionEndHooks.has(parentComponentElm)) {
  9117. transitionEndHooks.add(parentComponentElm);
  9118. document.addEventListener('transitionend', transitionEndAfterFn, passiveCapture);
  9119. }
  9120.  
  9121. const pr = new PromiseExternal();
  9122. transitionEndAfterFnSimple.set(hostElement, pr);
  9123. transitionEndAfterFnSimple.set(container, pr);
  9124. transitionEndAfterFnSimpleEnable++;
  9125. hostElement.classList.add("sliding-down");
  9126. await pr.then();
  9127. transitionEndAfterFnSimpleEnable--;
  9128. transitionEndAfterFnSimple.delete(hostElement);
  9129. transitionEndAfterFnSimple.delete(container);
  9130. if (this && this.hostElement instanceof HTMLElement_) {
  9131.  
  9132. this.collapse();
  9133. }
  9134. return;
  9135. }
  9136. }
  9137. this.slideDown43();
  9138.  
  9139. });
  9140.  
  9141.  
  9142. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::slideDown - OK`)
  9143. } else {
  9144.  
  9145. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::slideDown - NG`)
  9146. }
  9147.  
  9148.  
  9149. if (typeof cProto.collapse === 'function' && !cProto.collapse43 && cProto.collapse.length === 0) {
  9150. cProto.collapse43 = cProto.collapse;
  9151. cProto.collapse = dProto.collapseAdv || (dProto.collapseAdv = async function () {
  9152.  
  9153.  
  9154. if (this.__advancedTicking038__) {
  9155.  
  9156.  
  9157. if (this.__advancedTicking038__ === 1) this.__advancedTicking038__ = 2; // ignore intersectionobserver detection
  9158.  
  9159.  
  9160. const hostElement = this.hostElement;
  9161. const container = this.$.container;
  9162.  
  9163. const parentComponentCnt = insp(this.parentComponent);
  9164. const parentComponentElm = parentComponentCnt ? parentComponentCnt.hostElement : null;
  9165.  
  9166. if (hostElement instanceof HTMLElement_ && container instanceof HTMLElement_ && parentComponentElm instanceof HTMLElement_) {
  9167. // const prevTransitionClosingElm = kRef(prevTransitionClosing);
  9168. // if (prevTransitionClosingElm !== hostElement) {
  9169. // prevTransitionClosingElm && prevTransitionClosingElm.classList.add('ticker-no-transition-time');
  9170. // prevTransitionClosing = mWeakRef(hostElement);
  9171. // }
  9172. // if (hostElement.classList.contains('ticker-no-transition-time')) hostElement.classList.remove('ticker-no-transition-time');
  9173. hostElement.classList.add('r6-closing-ticker');
  9174.  
  9175. if (!transitionEndHooks.has(parentComponentElm)) {
  9176. transitionEndHooks.add(parentComponentElm);
  9177. document.addEventListener('transitionend', transitionEndAfterFn, passiveCapture);
  9178. }
  9179.  
  9180. const pr = new PromiseExternal();
  9181. transitionEndAfterFnSimple.set(hostElement, pr);
  9182. transitionEndAfterFnSimple.set(container, pr);
  9183. transitionEndAfterFnSimpleEnable++;
  9184. hostElement.classList.add("collapsing");
  9185. hostElement.style.width = "0";
  9186. await pr.then();
  9187. transitionEndAfterFnSimpleEnable--;
  9188. transitionEndAfterFnSimple.delete(hostElement);
  9189. transitionEndAfterFnSimple.delete(container);
  9190. if (this && this.hostElement instanceof HTMLElement_) {
  9191.  
  9192. this.requestRemoval();
  9193. }
  9194.  
  9195. return;
  9196. }
  9197.  
  9198.  
  9199. }
  9200. this.collapse43();
  9201.  
  9202.  
  9203. });
  9204.  
  9205. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::collapse - OK`)
  9206. } else {
  9207.  
  9208. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::collapse - NG`)
  9209. }
  9210.  
  9211.  
  9212.  
  9213. if (typeof cProto.requestRemoval === 'function' && !cProto.requestRemoval49 && cProto.requestRemoval.length === 0) {
  9214. const removalList = [];
  9215. let removalRes = false;
  9216. const removalFn = () => {
  9217. if (removalList.length === 0) return;
  9218. for (const cnt of removalList) {
  9219. let r;
  9220. try {
  9221. r = cnt?.requestRemoval49();
  9222. } catch (e) { }
  9223. if (r !== undefined && removalRes === false) {
  9224. removalRes = true;
  9225. console.log(`[yt-chat-ticker] requestRemoval49 returns ${r}`);
  9226. }
  9227. }
  9228. removalList.length = 0;
  9229. };
  9230. cProto.requestRemoval49 = cProto.requestRemoval;
  9231. cProto.requestRemoval = dProto.requestRemovalAdv || (dProto.requestRemovalAdv = function () {
  9232. const hostElement = this.hostElement;
  9233. if (this.__advancedTicking038__) {
  9234. try {
  9235. const overlayBg = hostElement.querySelector('ticker-bg-overlay[id]');
  9236. if (overlayBg) {
  9237. const overlayBgId = overlayBg.id;
  9238. const tid = overlayBgId ? overlayBgId.substring(0, overlayBgId.length - 2) : '';
  9239. const endElm = tid ? document.querySelector(`#${tid}-e`) : null;
  9240. if (endElm) {
  9241. wio2.unobserve(endElm);
  9242. endElm.remove();
  9243. }
  9244. }
  9245. } catch (e) { }
  9246. this.__advancedTicking038__ = 2;
  9247. // console.log('requestRemoval!!')
  9248. if (hostElement instanceof HTMLElement_) {
  9249. // otherwise the startCountDown not working
  9250. hostElement.style.removeProperty('--ticker-start-time');
  9251. hostElement.style.removeProperty('--ticker-duration-time');
  9252. }
  9253. if (REUSE_TICKER) {
  9254. const cntData = this.data;
  9255. if (hostElement instanceof HTMLElement_ && cntData.id && cntData.fullDurationSec && !hostElement.hasAttribute('__reuseid__')) {
  9256. hostElement.setAttribute('__reuseid__', reuseId);
  9257. hostElement.setAttribute('__nogc__', ''); // provided to leakage detection script
  9258. // this.__markReuse13__ = true;
  9259. reuseStore.set(`<${this.is}>${cntData.id}:${cntData.fullDurationSec}`, mWeakRef(this));
  9260. }
  9261. }
  9262. }
  9263. if (hostElement instanceof HTMLElement_) {
  9264. // try {
  9265. // // hostElement.remove();
  9266.  
  9267. // if (!hostElement.classList.contains('ticker-no-transition-time')) hostElement.classList.add('ticker-no-transition-time');
  9268. // } catch (e) { }
  9269.  
  9270. try {
  9271.  
  9272. hostElement.classList.remove('r6-closing-ticker');
  9273. hostElement.classList.remove('r6-width-adjustable-f');
  9274. } catch (e) { }
  9275.  
  9276. // if(ADVANCED_TICKING_MEMORY_CLEAN_FOR_REMOVAL){
  9277. // const wr = mWeakRef(hostElement);
  9278. // const wf = ()=>{
  9279. // const element = kRef(wr);
  9280. // if(!element) {
  9281. // console.log('[yt-chat-removalrequest] element was memory cleaned.');
  9282. // return;
  9283. // }
  9284.  
  9285. // setTimeout(wf, 8000);
  9286. // if(element.isConnected){
  9287. // console.log('[yt-chat-removalrequest] element is still connected to DOM Tree.');
  9288. // return;
  9289. // }
  9290.  
  9291. // const cnt = insp(element)
  9292. // if(typeof cnt.requestRemoval !== 'function'){
  9293.  
  9294. // console.log('[yt-chat-removalrequest] element is not connected to cnt.');
  9295. // return;
  9296. // }
  9297. // console.log('[yt-chat-removalrequest] element is not GC.');
  9298. // try{
  9299. // cnt.data = null;
  9300. // }catch(e){}
  9301.  
  9302. // Object.setPrototypeOf(cnt, Object.prototype);
  9303. // for(const k of Object.getOwnPropertyNames(cnt)){
  9304. // try{
  9305. // cnt[k] = null;
  9306. // }catch(e){}
  9307.  
  9308. // try{
  9309. // delete cnt[k];
  9310. // }catch(e){}
  9311. // }
  9312.  
  9313.  
  9314. // for(const k of Object.getOwnPropertySymbols(cnt)){
  9315. // try{
  9316. // cnt[k] = null;
  9317. // }catch(e){}
  9318.  
  9319. // try{
  9320. // delete cnt[k];
  9321. // }catch(e){}
  9322. // }
  9323.  
  9324. // }
  9325. // setTimeout(wf, 8000);
  9326. // }
  9327.  
  9328. removalList.push(this);
  9329. timelineResolve().then(removalFn);
  9330. }
  9331. });
  9332.  
  9333.  
  9334. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::requestRemoval - OK`)
  9335. } else {
  9336.  
  9337. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::requestRemoval - NG`)
  9338. }
  9339.  
  9340.  
  9341. if (typeof cProto.computeContainerStyle === 'function' && !cProto.computeContainerStyle49 && cProto.computeContainerStyle.length === 2) {
  9342. cProto.computeContainerStyle49 = cProto.computeContainerStyle;
  9343. cProto.computeContainerStyle = dProto.computeContainerStyleAdv || (dProto.computeContainerStyleAdv = function (a, b) {
  9344. if (this.__advancedTicking038__) {
  9345. return "";
  9346. }
  9347. return this.computeContainerStyle49(a, b);
  9348. });
  9349.  
  9350.  
  9351. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::computeContainerStyle - OK`)
  9352. } else {
  9353.  
  9354. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::computeContainerStyle - NG`)
  9355. }
  9356.  
  9357.  
  9358.  
  9359. if(ENABLE_TICKERS_BOOSTED_STAMPING && DISABLE_DYNAMIC_TICKER_WIDTH && typeof cProto.updateWidthOnDataChanged === 'function' && cProto.updateWidthOnDataChanged.length === 0 && !cProto.updateWidthOnDataChanged41){
  9360.  
  9361. cProto.updateWidthOnDataChanged41 = cProto.updateWidthOnDataChanged;
  9362. cProto.updateWidthOnDataChanged = dProto.updateWidthOnDataChangedAdv || (dProto.updateWidthOnDataChangedAdv = function(){
  9363. const style = this.hostElement.style;
  9364. style.width = "";
  9365. style.overflow = "";
  9366. });
  9367.  
  9368. }
  9369.  
  9370.  
  9371. if (!cProto.setStandardContainerWidth8447) {
  9372. cProto.setStandardContainerWidth8447 = dProto.setStandardContainerWidthAdv || (dProto.setStandardContainerWidthAdv = async function (kName) {
  9373.  
  9374. if (typeof this.setContainerWidthPr9 === 'function') {
  9375. const pr9 = this.setContainerWidthPr9();
  9376. if (pr9) {
  9377. await pr9;
  9378. }
  9379. }
  9380.  
  9381. const hostElement = (this || 0).hostElement;
  9382. const container = this.$.container;
  9383.  
  9384. let qw = null;
  9385. let qt = '';
  9386.  
  9387. {
  9388.  
  9389. let maxC = 4;
  9390.  
  9391. for (let p = qt = hostElement.getAttribute('r6-ticker-width') || ''; maxC--;) {
  9392.  
  9393. const ed = `${hostElement.id}`
  9394. if (!p || !p.startsWith(`${ed}::`)) {
  9395.  
  9396. const w = hostElement.style.width;
  9397. if (w !== '' && w !== 'auto') hostElement.style.width = 'auto';
  9398.  
  9399. const res = await widthReq(container);
  9400.  
  9401. if (res.width < 1 || !Number.isFinite(res.width)) {
  9402. // just skip due to iron-page hidden
  9403. return;
  9404. }
  9405.  
  9406. hostElement.setAttribute('r6-ticker-width', p = qt = `${ed}::${(res.width).toFixed(2)}`);
  9407.  
  9408. } else {
  9409. qw = p.split('::');
  9410. break;
  9411. }
  9412.  
  9413. }
  9414.  
  9415. }
  9416.  
  9417. if (!qw) {
  9418.  
  9419. console.log('container width failure');
  9420. if(kName === 'setContainerWidth') this.setContainerWidth41(); else this.setRevampContainerWidth41();
  9421. return; // failure
  9422. }
  9423.  
  9424.  
  9425. const shouldAnimateIn = ((this || 0).ytLiveChatTickerItemBehavior || 0).shouldAnimateIn || (this || 0).shouldAnimateIn || false;
  9426. if (shouldAnimateIn) {
  9427.  
  9428. stackDM(async () => {
  9429.  
  9430. if (hostElement.getAttribute('r6-ticker-width') !== qt || hostElement.isConnected !== true) return;
  9431. if (hostElement.previousElementSibling || isTickerItemsScrolling()) {
  9432.  
  9433. hostElement.style.width = `${qw[1]}px`;
  9434.  
  9435. } else {
  9436.  
  9437. const w = hostElement.style.width;
  9438. if (w !== '0px' && w !== '0') hostElement.style.width = '0';
  9439.  
  9440. await widthReq(container);
  9441.  
  9442. hostElement.style.width = `${qw[1]}px`;
  9443. }
  9444.  
  9445.  
  9446. });
  9447.  
  9448.  
  9449. } else {
  9450.  
  9451.  
  9452. stackDM(async () => {
  9453.  
  9454.  
  9455.  
  9456. if (hostElement.getAttribute('r6-ticker-width') !== qt || hostElement.isConnected !== true) return;
  9457.  
  9458. hostElement.style.width = `${qw[1]}px`;
  9459.  
  9460. });
  9461. }
  9462.  
  9463.  
  9464.  
  9465. });
  9466. }
  9467.  
  9468. if (typeof cProto.setRevampContainerWidth === 'function' && !cProto.setRevampContainerWidth41 && cProto.setRevampContainerWidth.length === 0 && typeof cProto.setStandardContainerWidth8447 === 'function' && cProto.setStandardContainerWidth8447.length === 1) {
  9469. cProto.setRevampContainerWidth41 = cProto.setRevampContainerWidth;
  9470. if (ENABLE_TICKERS_BOOSTED_STAMPING && DISABLE_DYNAMIC_TICKER_WIDTH) {
  9471.  
  9472. cProto.setRevampContainerWidth = dProto.setRevampContainerWidthAdv || (dProto.setRevampContainerWidthAdv = async function () {
  9473. const hostElement = this.hostElement;
  9474. if (((hostElement || 0).style || 0).width) hostElement.style.width = '';
  9475. return;
  9476. });
  9477.  
  9478. } else {
  9479.  
  9480.  
  9481.  
  9482. cProto.setRevampContainerWidth = dProto.setRevampContainerWidthAdv || (dProto.setRevampContainerWidthAdv = async function () {
  9483.  
  9484. // not sure the reason for auto instead of pixel.
  9485. // this is a new function in Dec 2024, but not mainly adopted in the coding yet
  9486.  
  9487. /*
  9488. var a = this;
  9489. (R(this.hostElement).querySelector("#container").clientWidth || 0) === 0 ? (this.hostElement.style.overflow = "visible",
  9490. this.hostElement.style.width = "auto") : (this.hostElement.style.overflow = "hidden",
  9491. this.ytLiveChatTickerItemBehavior.shouldAnimateIn ? (this.hostElement.style.width = "0",
  9492. Zu(function() {
  9493. a.hostElement.style.width = "auto"
  9494. }, 1)) : this.hostElement.style.width = "auto")
  9495. */
  9496.  
  9497.  
  9498. return this.setStandardContainerWidth8447('setRevampContainerWidth');
  9499.  
  9500. });
  9501. }
  9502.  
  9503.  
  9504. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::setRevampContainerWidth - OK`)
  9505. } else {
  9506.  
  9507. DEBUG_skipLog001 || console1.log(`USE_ADVANCED_TICKING[#${tagI}]::setRevampContainerWidth - NG (acceptable)`)
  9508. }
  9509.  
  9510.  
  9511. if (typeof cProto.setContainerWidth === 'function' && !cProto.setContainerWidth41 && cProto.setContainerWidth.length === 0 && typeof cProto.setStandardContainerWidth8447 === 'function' && cProto.setStandardContainerWidth8447.length === 1) {
  9512. cProto.setContainerWidth41 = cProto.setContainerWidth;
  9513.  
  9514. if (ENABLE_TICKERS_BOOSTED_STAMPING && DISABLE_DYNAMIC_TICKER_WIDTH) {
  9515.  
  9516. cProto.setContainerWidth = dProto.setContainerWidthAdv || (dProto.setContainerWidthAdv = async function () {
  9517. const hostElement = this.hostElement;
  9518. if (((hostElement || 0).style || 0).width) hostElement.style.width = '';
  9519. return;
  9520. });
  9521.  
  9522. } else {
  9523.  
  9524. cProto.setContainerWidth = dProto.setContainerWidthAdv || (dProto.setContainerWidthAdv = async function () {
  9525.  
  9526.  
  9527.  
  9528. /*
  9529. var a = this
  9530. , b = R(this.hostElement).querySelector("#container").clientWidth || 0;
  9531. b === 0 ? (this.hostElement.style.overflow = "visible",
  9532. this.hostElement.style.width = "auto") : (this.hostElement.style.overflow = "hidden",
  9533. this.shouldAnimateIn ? (this.hostElement.style.width = "0",
  9534. Zu(function() {
  9535. a.hostElement.style.width = b + "px"
  9536. }, 1)) : this.hostElement.style.width = b + "px")
  9537. */
  9538. return this.setStandardContainerWidth8447('setContainerWidth');
  9539.  
  9540. });
  9541.  
  9542. }
  9543.  
  9544.  
  9545.  
  9546. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::setContainerWidth - OK`)
  9547. } else {
  9548.  
  9549.  
  9550. console1.log(`USE_ADVANCED_TICKING[#${tagI}]::setContainerWidth - NG`)
  9551. }
  9552.  
  9553.  
  9554.  
  9555.  
  9556. } else if (USE_ADVANCED_TICKING) {
  9557. console1.log(`USE_ADVANCED_TICKING[#${tagI}] is not injected.`);
  9558. }
  9559.  
  9560.  
  9561.  
  9562. }
  9563.  
  9564. const selector = tags.join(', ');
  9565. const elements = document.querySelectorAll(selector);
  9566. if (elements.length >= 1) {
  9567. for (const elm of elements) {
  9568. if (insp(elm).isAttached === true) {
  9569. fpTicker(elm);
  9570. }
  9571. }
  9572. }
  9573.  
  9574. console1.log("[End]");
  9575. groupEnd();
  9576.  
  9577.  
  9578. }).catch(console.warn);
  9579.  
  9580. if(FIX_MEMORY_LEAKAGE_TICKER_DATACHANGED_setContainerWidth){
  9581.  
  9582. /**
  9583. *
  9584. *
  9585. *
  9586. *
  9587. cT.prototype.dataChanged = function() {
  9588. var a = this;
  9589. this.data && (Q(this.hostElement).querySelector("#content").style.color = this.ytLiveChatTickerItemBehavior.colorFromDecimal(this.data.detailTextColor),
  9590. this.hostElement.ariaLabel = this.computeAriaLabel(this.data),
  9591. this.ytLiveChatTickerItemBehavior.startCountdown(this.data.durationSec, this.data.fullDurationSec),
  9592. qw(function() {
  9593. a.ytLiveChatTickerItemBehavior.setContainerWidth()
  9594. }))
  9595. }
  9596.  
  9597.  
  9598. znb.prototype.dataChanged = function(a) {
  9599. var b = this;
  9600. a && (a.tickerThumbnails.length > 1 && Q(this.hostElement).querySelector("#content").classList.add("multiple-thumbnails"),
  9601. this.ytLiveChatTickerItemBehavior.startCountdown(a.durationSec, a.fullDurationSec),
  9602. qw(function() {
  9603. b.ytLiveChatTickerItemBehavior.setContainerWidth()
  9604. }))
  9605. }
  9606.  
  9607. *
  9608. */
  9609.  
  9610. const dProto = {
  9611. dataChanged54500: function () {
  9612. // prevent memory leakage due to _.ytLiveChatTickerItemBehavior.setContainerWidth() in _.dataChanged
  9613. if (typeof (this.ytLiveChatTickerItemBehavior || 0).setContainerWidth === 'function') {
  9614. try {
  9615. if (!this.__proxySelf0__) this.__proxySelf0__ = weakWrap(this);
  9616. return this.dataChanged544.call(this.__proxySelf0__);
  9617. } catch (e) {
  9618. console.log('dataChanged54500 ERROR');
  9619. console.error(e);
  9620. }
  9621. } else {
  9622. return this.dataChanged544();
  9623. }
  9624. },
  9625. dataChanged54501: function (a) {
  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__, a);
  9631. } catch (e) {
  9632. console.log('dataChanged54501 ERROR');
  9633. console.error(e);
  9634. }
  9635. } else {
  9636. return this.dataChanged544(a);
  9637. }
  9638. },
  9639. }
  9640.  
  9641. for (const sto of [
  9642. 'yt-live-chat-ticker-sponsor-item-renderer',
  9643. 'yt-live-chat-ticker-paid-sticker-item-renderer'
  9644. ].map(tag => [tag, customElements.whenDefined(tag)])) {
  9645.  
  9646. const [tag, promise] = sto;
  9647.  
  9648. promise.then(()=>{
  9649.  
  9650. const dummy = document.createElement(tag);
  9651.  
  9652. const cProto = getProto(dummy);
  9653. if (!cProto || !cProto.attached) {
  9654. console.warn(`proto.attached for ${tag} is unavailable.`);
  9655. return;
  9656. }
  9657.  
  9658. if (!cProto.dataChanged || cProto.dataChanged544 || typeof cProto.dataChanged !== 'function' || !(cProto.dataChanged.length >= 0 && cProto.dataChanged.length <= 1)) return;
  9659.  
  9660. cProto.dataChanged544 = cProto.dataChanged;
  9661.  
  9662. if (cProto.dataChanged.length === 0) cProto.dataChanged = dProto.dataChanged54500;
  9663. else if (cProto.dataChanged.length === 1) cProto.dataChanged = dProto.dataChanged54501;
  9664.  
  9665.  
  9666.  
  9667. })
  9668.  
  9669.  
  9670. }
  9671.  
  9672. }
  9673.  
  9674. customElements.whenDefined('yt-live-chat-ticker-renderer').then(() => {
  9675.  
  9676. mightFirstCheckOnYtInit();
  9677. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-ticker-renderer hacks");
  9678. console1.log("[Begin]");
  9679. (() => {
  9680.  
  9681. /* pending!!
  9682.  
  9683. handleLiveChatAction
  9684.  
  9685. removeTickerItemById
  9686.  
  9687. _itemsChanged
  9688. itemsChanged
  9689.  
  9690. handleMarkChatItemAsDeletedAction
  9691. handleMarkChatItemsByAuthorAsDeletedAction
  9692. handleRemoveChatItemByAuthorAction
  9693.  
  9694.  
  9695. */
  9696.  
  9697. const tag = "yt-live-chat-ticker-renderer"
  9698. const dummy = document.createElement(tag);
  9699.  
  9700. const cProto = getProto(dummy);
  9701. if (!cProto || !cProto.attached) {
  9702. console1.warn(`proto.attached for ${tag} is unavailable.`);
  9703. return;
  9704. }
  9705.  
  9706. // const imgCollection = document.getElementsByTagName('IMG');
  9707.  
  9708. if (ENABLE_TICKERS_BOOSTED_STAMPING && typeof cProto.notifyPath === 'function' && cProto.notifyPath.length === 2 && typeof cProto.stampDomArraySplices_ === 'function' && cProto.stampDomArraySplices_.length === 3) {
  9709.  
  9710. rendererStamperFactory(cProto, {
  9711. key: 'proceedStampDomArraySplices371_',
  9712. stamperDomClass: 'style-scope yt-live-chat-ticker-renderer yt-live-chat-ticker-stampdom'
  9713. });
  9714.  
  9715. cProto.stampDomArraySplices371_ = cProto.stampDomArraySplices_;
  9716.  
  9717. cProto.stampDomArraySplices_ = function (a, b, c) {
  9718. if (a === 'tickerItems' && b === 'ticker-items' && (c || 0).indexSplices) {
  9719. // if (this.ec388) {
  9720. const indexSplices = c.indexSplices;
  9721. if (indexSplices.length === 1 || typeof indexSplices.length === "undefined") {
  9722. const indexSplice = indexSplices[0] || indexSplices;
  9723. if (indexSplice.type === 'splice' && (indexSplice.addedCount >= 1 || (indexSplice.removed || 0).length >= 1)) {
  9724. // console.log(1059, a, b, indexSplice);
  9725. if (this.proceedStampDomArraySplices371_(a, b, indexSplice)) return;
  9726. }
  9727. }
  9728. // } else {
  9729. // console.warn('stampDomArraySplices_ warning', ...arguments);
  9730. // }
  9731. }
  9732. return this.stampDomArraySplices371_(...arguments);
  9733. };
  9734.  
  9735. cProto.stampDomArray366_ = cProto.stampDomArray_;
  9736. cProto.stampDomArray_ = function (items, containerId, componentConfig, rxConfig, shouldCallback, isStableList) {
  9737. const isTickerRendering = items === this.tickerItems && containerId === 'ticker-items';
  9738. const isMessageListRendering = items === this.visibleItems && containerId === 'items';
  9739.  
  9740. if(!isTickerRendering && !isMessageListRendering){
  9741. console.log('stampDomArray_ warning 0xF501', ...arguments)
  9742. return this.stampDomArray366_(...arguments);
  9743. }
  9744.  
  9745. const container = (this.$ || 0)[containerId];
  9746. if (!container) {
  9747. console.log('stampDomArray_ warning 0xF502', ...arguments)
  9748. return this.stampDomArray366_(...arguments);
  9749. }
  9750.  
  9751. if (container[sFirstElementChild] === null && items.length === 0){
  9752.  
  9753. }else{
  9754. const cTag = isTickerRendering ? 'tickerItems' : 'visibleItems';
  9755. this.proceedStampDomArraySplices371_(cTag, containerId, {
  9756. addedCount: items.length,
  9757. removedCount: container.childElementCount
  9758. });
  9759. }
  9760.  
  9761. const f = () => {
  9762. this.markDirty && this.markDirty();
  9763. const detail = {
  9764. container
  9765. };
  9766. shouldCallback && this.hostElement.dispatchEvent(new CustomEvent("yt-rendererstamper-finished", {
  9767. bubbles: !0,
  9768. cancelable: !1,
  9769. composed: !0,
  9770. detail
  9771. }));
  9772. detail.container = null;
  9773. };
  9774. if (this.ec389pr) {
  9775. this.ec389pr.then(f)
  9776. } else {
  9777. f();
  9778. }
  9779.  
  9780. };
  9781.  
  9782. }
  9783.  
  9784.  
  9785.  
  9786. if(typeof cProto.createComponent_ === 'function' && cProto.createComponent_.length === 3 && !cProto.createComponent58_ ){
  9787.  
  9788. cProto.createComponent58_ = cProto.createComponent_;
  9789. cProto.createComponent_ = function (a, b, c) {
  9790.  
  9791. const z = customCreateComponent(a, b, c);
  9792. if (z !== undefined) return z;
  9793. const r = this.createComponent58_(a, b, c);
  9794. return r;
  9795.  
  9796. }
  9797.  
  9798. }
  9799.  
  9800.  
  9801.  
  9802.  
  9803.  
  9804.  
  9805.  
  9806.  
  9807. /* Dec 2024 */
  9808.  
  9809. /*
  9810.  
  9811.  
  9812. f.handleLiveChatActions = function(a) {
  9813. a.length && (a.forEach(this.handleLiveChatAction, this),
  9814. this.updateHighlightedItem(),
  9815. this.shouldAnimateIn = !0)
  9816. }
  9817. ;
  9818. f.handleLiveChatAction = function(a) {
  9819. var b = z(a, fL)
  9820. , c = z(a, gL)
  9821. , d = z(a, eL)
  9822. , e = z(a, gdb)
  9823. , g = z(a, rdb)
  9824. , k = z(a, Deb);
  9825. a = z(a, Ceb);
  9826. 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)
  9827. }
  9828. */
  9829.  
  9830.  
  9831. if(USE_ADVANCED_TICKING && !cProto.handleLiveChatActions47 && typeof cProto.handleLiveChatActions === 'function' && cProto.handleLiveChatActions.length ===1){
  9832.  
  9833. cProto.handleLiveChatActions47 = cProto.handleLiveChatActions;
  9834.  
  9835. cProto.handleLiveChatActions = function (a) {
  9836.  
  9837. // first loading in livestream. so this is required for sorting.
  9838.  
  9839. try{
  9840. preprocessChatLiveActions(a);
  9841. }catch(e){
  9842. console.warn(e);
  9843. }
  9844. return this.handleLiveChatActions47(a);
  9845.  
  9846. }
  9847.  
  9848. console1.log("USE_ADVANCED_TICKING::handleLiveChatActions - OK");
  9849.  
  9850. }else if(USE_ADVANCED_TICKING){
  9851.  
  9852.  
  9853. console1.log("USE_ADVANCED_TICKING::handleLiveChatActions - NG");
  9854.  
  9855. }
  9856.  
  9857. // yt-live-chat-ticker-renderer hacks
  9858.  
  9859.  
  9860. if (RAF_FIX_keepScrollClamped) {
  9861.  
  9862. // to be improved
  9863.  
  9864. if (typeof cProto.keepScrollClamped === 'function' && !cProto.keepScrollClamped72 && fnIntegrity(cProto.keepScrollClamped) === '0.17.10') {
  9865.  
  9866. cProto.keepScrollClamped72 = cProto.keepScrollClamped;
  9867. cProto.keepScrollClamped = function () {
  9868.  
  9869. const cnt = kRef(this);
  9870. if (!cnt) return;
  9871. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  9872.  
  9873. cnt._bound_keepScrollClamped = cnt._bound_keepScrollClamped || cnt.keepScrollClamped.bind(mWeakRef(cnt));
  9874. cnt.scrollClampRaf = requestAnimationFrame(cnt._bound_keepScrollClamped);
  9875. cnt.maybeClampScroll()
  9876. }
  9877.  
  9878. console1.log('RAF_FIX: keepScrollClamped', tag, "OK")
  9879. } else {
  9880.  
  9881. assertor(() => fnIntegrity(cProto.keepScrollClamped, '0.17.10'));
  9882. console1.log('RAF_FIX: keepScrollClamped', tag, "NG")
  9883. }
  9884.  
  9885. }
  9886.  
  9887.  
  9888. if (RAF_FIX_scrollIncrementally && typeof cProto.startScrolling === 'function' && typeof cProto.scrollIncrementally === 'function'
  9889. && '|1.43.31|1.44.31|'.indexOf('|' + fnIntegrity(cProto.startScrolling) + '|') >= 0
  9890. && '|1.78.45|1.82.43|1.43.31|'.indexOf('|' + fnIntegrity(cProto.scrollIncrementally) + '|') >= 0) {
  9891. // to be replaced by animator
  9892.  
  9893. cProto.startScrolling = function (a) {
  9894.  
  9895. const cnt = kRef(this);
  9896. if (!cnt) return;
  9897. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  9898.  
  9899. cnt.scrollStopHandle && cnt.cancelAsync(cnt.scrollStopHandle);
  9900. cnt.asyncHandle && cancelAnimationFrame(cnt.asyncHandle);
  9901. cnt.lastFrameTimestamp = cnt.scrollStartTime = performance.now();
  9902. cnt.scrollRatePixelsPerSecond = a;
  9903. cnt._bound_scrollIncrementally = cnt._bound_scrollIncrementally || cnt.scrollIncrementally.bind(mWeakRef(cnt));
  9904. cnt.asyncHandle = requestAnimationFrame(cnt._bound_scrollIncrementally)
  9905. };
  9906.  
  9907. // related functions: startScrollBack, startScrollingLeft, startScrollingRight, etc.
  9908.  
  9909. /**
  9910. *
  9911. * // 2024.12.17
  9912. * // https://www.youtube.com/s/desktop/f7495da0/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  9913.  
  9914. f.startScrolling = function(a) {
  9915. this.scrollStopHandle && $u(this.scrollStopHandle);
  9916. this.asyncHandle && window.cancelAnimationFrame(this.asyncHandle);
  9917. this.scrollStartTime = performance.now();
  9918. this.lastFrameTimestamp = performance.now();
  9919. this.scrollRatePixelsPerSecond = a;
  9920. this.asyncHandle = window.requestAnimationFrame(this.scrollIncrementally.bind(this))
  9921. }
  9922. ;
  9923. f.scrollIncrementally = function(a) {
  9924. var b = a - (this.lastFrameTimestamp || 0);
  9925. R(this.hostElement).querySelector(this.tickerBarQuery).scrollLeft += b / 1E3 * (this.scrollRatePixelsPerSecond || 0);
  9926. this.maybeClampScroll();
  9927. this.updateArrows();
  9928. this.lastFrameTimestamp = a;
  9929. R(this.hostElement).querySelector(this.tickerBarQuery).scrollLeft > 0 || this.scrollRatePixelsPerSecond && this.scrollRatePixelsPerSecond > 0 ? this.asyncHandle = window.requestAnimationFrame(this.scrollIncrementally.bind(this)) : this.stopScrolling()
  9930. }
  9931. ;
  9932. *
  9933. */
  9934.  
  9935. /**
  9936. *
  9937. // 2024.12.20
  9938.  
  9939.  
  9940.  
  9941. f.startScrolling = function(a) {
  9942. this.scrollStopHandle && av(this.scrollStopHandle);
  9943. this.asyncHandle && window.cancelAnimationFrame(this.asyncHandle);
  9944. this.scrollStartTime = performance.now();
  9945. this.lastFrameTimestamp = performance.now();
  9946. this.scrollRatePixelsPerSecond = a;
  9947. this.asyncHandle = window.requestAnimationFrame(this.scrollIncrementally.bind(this))
  9948. }
  9949.  
  9950. *
  9951. *
  9952. */
  9953.  
  9954. cProto.__getTickerBarQuery__ = function () {
  9955. const tickerBarQuery = this.tickerBarQuery === '#items' ? this.$.items : this.hostElement.querySelector(this.tickerBarQuery);
  9956. return tickerBarQuery;
  9957. }
  9958.  
  9959. cProto.scrollIncrementally = (RAF_FIX_scrollIncrementally === 2) ? function (a) {
  9960.  
  9961. const cnt = kRef(this);
  9962. if (!cnt) return;
  9963. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  9964.  
  9965. const b = a - (cnt.lastFrameTimestamp || 0);
  9966. const rate = cnt.scrollRatePixelsPerSecond
  9967. const q = b / 1E3 * (rate || 0);
  9968.  
  9969. const tickerBarQuery = cnt.__getTickerBarQuery__();
  9970. const sl = tickerBarQuery.scrollLeft;
  9971. // console.log(rate, sl, q)
  9972. if (cnt.lastFrameTimestamp == cnt.scrollStartTime) {
  9973.  
  9974. } else if (q > -1e-5 && q < 1e-5) {
  9975.  
  9976. } else {
  9977. let cond1 = sl > 0 && rate > 0 && q > 0;
  9978. let cond2 = sl > 0 && rate < 0 && q < 0;
  9979. let cond3 = sl < 1e-5 && sl > -1e-5 && rate > 0 && q > 0;
  9980. if (cond1 || cond2 || cond3) {
  9981. tickerBarQuery.scrollLeft += q;
  9982. cnt.maybeClampScroll();
  9983. cnt.updateArrows();
  9984. }
  9985. }
  9986.  
  9987. cnt.lastFrameTimestamp = a;
  9988. cnt._bound_scrollIncrementally = cnt._bound_scrollIncrementally || cnt.scrollIncrementally.bind(mWeakRef(cnt));
  9989. 0 < tickerBarQuery.scrollLeft || rate && 0 < rate ? cnt.asyncHandle = requestAnimationFrame(cnt._bound_scrollIncrementally) : cnt.stopScrolling()
  9990. } : function (a) {
  9991.  
  9992. const cnt = kRef(this);
  9993. if (!cnt) return;
  9994. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  9995.  
  9996. const b = a - (cnt.lastFrameTimestamp || 0);
  9997. const tickerBarQuery = cnt.__getTickerBarQuery__();
  9998. tickerBarQuery.scrollLeft += b / 1E3 * (cnt.scrollRatePixelsPerSecond || 0);
  9999. cnt.maybeClampScroll();
  10000. cnt.updateArrows();
  10001. cnt.lastFrameTimestamp = a;
  10002. cnt._bound_scrollIncrementally = cnt._bound_scrollIncrementally || cnt.scrollIncrementally.bind(mWeakRef(cnt));
  10003. 0 < tickerBarQuery.scrollLeft || cnt.scrollRatePixelsPerSecond && 0 < cnt.scrollRatePixelsPerSecond ? cnt.asyncHandle = requestAnimationFrame(cnt._bound_scrollIncrementally) : cnt.stopScrolling()
  10004. };
  10005.  
  10006. console1.log(`RAF_FIX: scrollIncrementally${RAF_FIX_scrollIncrementally}`, tag, "OK")
  10007. } else {
  10008. assertor(() => fnIntegrity(cProto.startScrolling, '1.43.31'))
  10009. || logFn('cProto.startScrolling', cProto.startScrolling)();
  10010. assertor(() => fnIntegrity(cProto.scrollIncrementally, '1.78.45'))
  10011. || logFn('cProto.scrollIncrementally', cProto.scrollIncrementally)();
  10012. console1.log('RAF_FIX: scrollIncrementally', tag, "NG")
  10013. }
  10014.  
  10015.  
  10016. if (CLOSE_TICKER_PINNED_MESSAGE_WHEN_HEADER_CLICKED && typeof cProto.attached === 'function' && !cProto.attached37 && typeof cProto.detached === 'function' && !cProto.detached37) {
  10017.  
  10018. cProto.attached37 = cProto.attached;
  10019. cProto.detached37 = cProto.detached;
  10020.  
  10021. let naohzId = 0;
  10022. cProto.__naohzId__ = 0;
  10023. cProto.attached = function () {
  10024. Promise.resolve(this).then((cnt) => {
  10025.  
  10026. const hostElement = cnt.hostElement || cnt;
  10027. if (!(hostElement instanceof HTMLElement_)) return;
  10028. if (!HTMLElement_.prototype.matches.call(hostElement, '.yt-live-chat-renderer')) return;
  10029. const ironPage = HTMLElement_.prototype.closest.call(hostElement, 'iron-pages.yt-live-chat-renderer');
  10030. // or #chat-messages
  10031. if (!ironPage) return;
  10032.  
  10033. if (cnt.__naohzId__) removeEventListener.call(ironPage, 'click', cnt.messageBoxClickHandlerForFade, { capture: false, passive: true });
  10034. cnt.__naohzId__ = naohzId = (naohzId & 1073741823) + 1;
  10035. ironPage.setAttribute('naohz', `${+cnt.__naohzId__}`);
  10036.  
  10037. addEventListener.call(ironPage, 'click', cnt.messageBoxClickHandlerForFade, { capture: false, passive: true });
  10038.  
  10039. cnt = null;
  10040.  
  10041. });
  10042. return this.attached37.apply(this, arguments);
  10043. };
  10044. cProto.detached = function () {
  10045. Promise.resolve(this).then((cnt) => {
  10046.  
  10047. const ironPage = document.querySelector(`iron-pages[naohz="${+cnt.__naohzId__}"]`);
  10048. if (!ironPage) return;
  10049.  
  10050. removeEventListener.call(ironPage, 'click', cnt.messageBoxClickHandlerForFade, { capture: false, passive: true });
  10051.  
  10052. cnt = null;
  10053.  
  10054. });
  10055. return this.detached37.apply(this, arguments);
  10056. };
  10057.  
  10058. const clickFade = (u) => {
  10059. u.click();
  10060. };
  10061. cProto.messageBoxClickHandlerForFade = async (evt) => {
  10062.  
  10063. const target = (evt || 0).target || 0;
  10064. if (!target) return;
  10065.  
  10066. for (let p = target; p instanceof HTMLElement_; p = nodeParent(p)) {
  10067. const is = p.is;
  10068. if (typeof is === 'string' && is) {
  10069.  
  10070. if (is === 'yt-live-chat-pinned-message-renderer') {
  10071. return;
  10072. }
  10073. if (is === 'iron-pages' || is === 'yt-live-chat-renderer' || is === 'yt-live-chat-app') {
  10074. const fade = HTMLElement_.prototype.querySelector.call(p, 'yt-live-chat-pinned-message-renderer:not([hidden]) #fade');
  10075. if (fade) {
  10076. Promise.resolve(fade).then(clickFade);
  10077. evt && evt.stopPropagation();
  10078. }
  10079. return;
  10080. }
  10081. if (is !== 'yt-live-chat-ticker-renderer') {
  10082. if (is.startsWith('yt-live-chat-ticker-')) return;
  10083. if (!is.endsWith('-renderer')) return;
  10084. }
  10085.  
  10086. } else {
  10087. if ((p.nodeName || '').includes('BUTTON')) return;
  10088. }
  10089.  
  10090. }
  10091. };
  10092.  
  10093. console1.log("CLOSE_TICKER_PINNED_MESSAGE_WHEN_HEADER_CLICKED - OK")
  10094.  
  10095. } else {
  10096. console1.log("CLOSE_TICKER_PINNED_MESSAGE_WHEN_HEADER_CLICKED - NG")
  10097. }
  10098.  
  10099.  
  10100. })();
  10101.  
  10102. console1.log("[End]");
  10103.  
  10104. groupEnd();
  10105.  
  10106. }).catch(console.warn);
  10107.  
  10108.  
  10109.  
  10110. if (ENABLE_RAF_HACK_INPUT_RENDERER || DELAY_FOCUSEDCHANGED) {
  10111.  
  10112. customElements.whenDefined("yt-live-chat-message-input-renderer").then(() => {
  10113.  
  10114. mightFirstCheckOnYtInit();
  10115. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-message-input-renderer hacks");
  10116. console1.log("[Begin]");
  10117. (() => {
  10118.  
  10119.  
  10120.  
  10121. const tag = "yt-live-chat-message-input-renderer"
  10122. const dummy = document.createElement(tag);
  10123.  
  10124. const cProto = getProto(dummy);
  10125. if (!cProto || !cProto.attached) {
  10126. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10127. return;
  10128. }
  10129.  
  10130.  
  10131. if (ENABLE_RAF_HACK_INPUT_RENDERER && rafHub !== null) {
  10132.  
  10133. let doHack = false;
  10134. if (typeof cProto.handleTimeout === 'function' && typeof cProto.updateTimeout === 'function') {
  10135.  
  10136. // not cancellable
  10137.  
  10138. // <<< to be reviewed cProto.updateTimeout --- isTimingFunctionHackable -- doHack >>>
  10139.  
  10140. doHack = fnIntegrity(cProto.handleTimeout, '1.27.16') && fnIntegrity(cProto.updateTimeout, '1.50.33');
  10141.  
  10142. if (!doHack) console1.log('doHack = false')
  10143.  
  10144. }
  10145. // doHack = false; // M55
  10146.  
  10147. if (doHack) {
  10148.  
  10149. cProto.handleTimeout = function (a) {
  10150.  
  10151. const cnt = kRef(this);
  10152. if (!cnt) return;
  10153. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10154.  
  10155. console.log('cProto.handleTimeout', tag)
  10156. if (!cnt.boundUpdateTimeout38_) cnt.boundUpdateTimeout38_ = cnt.updateTimeout.bind(mWeakRef(cnt));
  10157. cnt.timeoutDurationMs = cnt.timeoutMs = a;
  10158. cnt.countdownRatio = 1;
  10159. 0 === cnt.lastTimeoutTimeMs && rafHub.request(cnt.boundUpdateTimeout38_)
  10160. };
  10161. cProto.updateTimeout = function (a) {
  10162.  
  10163. const cnt = kRef(this);
  10164. if (!cnt) return;
  10165. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10166.  
  10167. console.log('cProto.updateTimeout', tag)
  10168. if (!cnt.boundUpdateTimeout38_) cnt.boundUpdateTimeout38_ = cnt.updateTimeout.bind(mWeakRef(cnt));
  10169. cnt.lastTimeoutTimeMs && (cnt.timeoutMs = Math.max(0, cnt.timeoutMs - (a - cnt.lastTimeoutTimeMs)),
  10170. cnt.countdownRatio = cnt.timeoutMs / cnt.timeoutDurationMs);
  10171. cnt.isAttached && cnt.timeoutMs ? (cnt.lastTimeoutTimeMs = a,
  10172. rafHub.request(cnt.boundUpdateTimeout38_)) : cnt.lastTimeoutTimeMs = 0
  10173. };
  10174.  
  10175. console1.log('RAF_HACK_INPUT_RENDERER', tag, "OK")
  10176. } else {
  10177.  
  10178. console1.log('typeof handleTimeout', typeof cProto.handleTimeout)
  10179. console1.log('typeof updateTimeout', typeof cProto.updateTimeout)
  10180.  
  10181. console1.log('RAF_HACK_INPUT_RENDERER', tag, "NG")
  10182. }
  10183.  
  10184.  
  10185. }
  10186.  
  10187. if (DELAY_FOCUSEDCHANGED && typeof cProto.onFocusedChanged === 'function' && cProto.onFocusedChanged.length === 1 && !cProto.onFocusedChanged372) {
  10188. cProto.onFocusedChanged372 = cProto.onFocusedChanged;
  10189. cProto.onFocusedChanged = function (a) {
  10190. Promise.resolve(this).then((cnt) => {
  10191. if (cnt.isAttached === true) cnt.onFocusedChanged372(a);
  10192. cnt = null;
  10193. }).catch(console.warn);
  10194. }
  10195. }
  10196.  
  10197. })();
  10198.  
  10199. console1.log("[End]");
  10200.  
  10201. groupEnd();
  10202.  
  10203.  
  10204. })
  10205.  
  10206. }
  10207.  
  10208.  
  10209. if (ENABLE_RAF_HACK_EMOJI_PICKER && rafHub !== null) {
  10210.  
  10211. customElements.whenDefined("yt-emoji-picker-renderer").then(() => {
  10212.  
  10213. mightFirstCheckOnYtInit();
  10214. groupCollapsed("YouTube Super Fast Chat", " | yt-emoji-picker-renderer hacks");
  10215. console1.log("[Begin]");
  10216. (() => {
  10217.  
  10218. const tag = "yt-emoji-picker-renderer"
  10219. const dummy = document.createElement(tag);
  10220.  
  10221. const cProto = getProto(dummy);
  10222. if (!cProto || !cProto.attached) {
  10223. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10224. return;
  10225. }
  10226.  
  10227. let doHack = false;
  10228. if (typeof cProto.animateScroll_ === 'function') {
  10229.  
  10230. // not cancellable
  10231. console1.log('animateScroll_: function - OK')
  10232.  
  10233. doHack = fnIntegrity(cProto.animateScroll_, '1.102.49')
  10234.  
  10235. } else {
  10236.  
  10237. console1.log('animateScroll_', typeof cProto.animateScroll_)
  10238. }
  10239.  
  10240. if (doHack) {
  10241.  
  10242. const querySelector = HTMLElement_.prototype.querySelector;
  10243. const U = (element) => ({
  10244. querySelector: (selector) => querySelector.call(element, selector)
  10245. });
  10246.  
  10247. cProto.animateScroll_ = function (a) {
  10248.  
  10249. const cnt = kRef(this);
  10250. if (!cnt) return;
  10251. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10252.  
  10253. // console.log('cProto.animateScroll_', tag) // yt-emoji-picker-renderer
  10254. if (!cnt.boundAnimateScroll39_) cnt.boundAnimateScroll39_ = cnt.animateScroll_.bind(mWeakRef(cnt));
  10255. cnt.lastAnimationTime_ || (cnt.lastAnimationTime_ = a);
  10256. a -= cnt.lastAnimationTime_;
  10257. 200 > a ? (U(cnt.hostElement).querySelector("#categories").scrollTop = cnt.animationStart_ + (cnt.animationEnd_ - cnt.animationStart_) * a / 200,
  10258. rafHub.request(cnt.boundAnimateScroll39_)) : (null != cnt.animationEnd_ && (U(cnt.hostElement).querySelector("#categories").scrollTop = cnt.animationEnd_),
  10259. cnt.animationEnd_ = cnt.animationStart_ = null,
  10260. cnt.lastAnimationTime_ = 0);
  10261. cnt.updateButtons_()
  10262. }
  10263.  
  10264. console1.log('ENABLE_RAF_HACK_EMOJI_PICKER', tag, "OK")
  10265. } else {
  10266.  
  10267. console1.log('ENABLE_RAF_HACK_EMOJI_PICKER', tag, "NG")
  10268. }
  10269.  
  10270. })();
  10271.  
  10272. console1.log("[End]");
  10273.  
  10274. groupEnd();
  10275. });
  10276. }
  10277.  
  10278. if (ENABLE_RAF_HACK_DOCKED_MESSAGE && rafHub !== null) {
  10279.  
  10280. customElements.whenDefined("yt-live-chat-docked-message").then(() => {
  10281.  
  10282. mightFirstCheckOnYtInit();
  10283. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-docked-message hacks");
  10284. console1.log("[Begin]");
  10285. (() => {
  10286.  
  10287. const tag = "yt-live-chat-docked-message"
  10288. const dummy = document.createElement(tag);
  10289.  
  10290. const cProto = getProto(dummy);
  10291. if (!cProto || !cProto.attached) {
  10292. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10293. return;
  10294. }
  10295.  
  10296. let doHack = false;
  10297. if (typeof cProto.detached === 'function' && typeof cProto.checkIntersections === 'function' && typeof cProto.onDockableMessagesChanged === 'function' && typeof cProto.boundCheckIntersections === 'undefined') {
  10298.  
  10299. // cancelable - this.intersectRAF <detached>
  10300. // yt-live-chat-docked-message
  10301. // boundCheckIntersections <-> checkIntersections
  10302. // onDockableMessagesChanged
  10303. // this.intersectRAF = window.requestAnimationFrame(this.boundCheckIntersections);
  10304.  
  10305. console1.log(`detached: function - OK`)
  10306. console1.log('checkIntersections: function - OK')
  10307. console1.log('onDockableMessagesChanged: function - OK')
  10308.  
  10309. doHack = fnIntegrity(cProto.detached, '0.32.22') && fnIntegrity(cProto.checkIntersections, '0.128.85') && fnIntegrity(cProto.onDockableMessagesChanged, '0.20.11')
  10310.  
  10311. } else {
  10312.  
  10313. console1.log('detached', typeof cProto.detached, 'NG')
  10314. console1.log('checkIntersections', typeof cProto.checkIntersections, 'NG')
  10315. console1.log('onDockableMessagesChanged', typeof cProto.onDockableMessagesChanged, 'NG')
  10316. }
  10317.  
  10318. if (doHack) {
  10319.  
  10320. cProto.__boundCheckIntersectionsSubstitutionFn__ = function () {
  10321. const cnt = this;
  10322. if (!cnt.i5zmk && typeof cnt.boundCheckIntersections === 'function' && typeof cnt.checkIntersections === 'function') {
  10323. cnt.i5zmk = 1
  10324. cnt.boundCheckIntersections = cnt.checkIntersections.bind(mWeakRef(cnt));
  10325. }
  10326. }
  10327.  
  10328. cProto.checkIntersections = function () {
  10329.  
  10330. const cnt = kRef(this);
  10331. if (!cnt) return;
  10332. if (!cnt.hostElement) return; // memory leakage. to be reviewed
  10333.  
  10334. if(typeof cnt.__boundCheckIntersectionsSubstitutionFn__ === 'function') cnt.__boundCheckIntersectionsSubstitutionFn__();
  10335.  
  10336. // console.log('cProto.checkIntersections', tag)
  10337. if (cnt.dockableMessages.length) {
  10338. cnt.intersectRAF = rafHub.request(cnt.boundCheckIntersections);
  10339. let a = cnt.dockableMessages[0]
  10340. , b = cnt.hostElement.getBoundingClientRect();
  10341. a = a.getBoundingClientRect();
  10342. let c = a.top - b.top
  10343. , d = 8 >= c;
  10344. c = 8 >= c - cnt.hostElement.clientHeight;
  10345. if (d) {
  10346. let e;
  10347. for (; d;) {
  10348. e = cnt.dockableMessages.shift();
  10349. d = cnt.dockableMessages[0];
  10350. if (!d)
  10351. break;
  10352. d = d.getBoundingClientRect();
  10353. c = d.top - b.top;
  10354. let f = 8 >= c;
  10355. if (8 >= c - a.height)
  10356. if (f)
  10357. a = d;
  10358. else
  10359. return;
  10360. d = f
  10361. }
  10362. cnt.dock(e)
  10363. } else
  10364. c && cnt.dockedItem && cnt.clear()
  10365. } else
  10366. cnt.intersectRAF = 0
  10367. }
  10368.  
  10369. cProto.onDockableMessagesChanged = function () {
  10370. const cnt = this;
  10371. if(typeof cnt.__boundCheckIntersectionsSubstitutionFn__ === 'function') cnt.__boundCheckIntersectionsSubstitutionFn__();
  10372. // console.log('cProto.onDockableMessagesChanged', tag) // yt-live-chat-docked-message
  10373. cnt.dockableMessages.length && !cnt.intersectRAF && (cnt.intersectRAF = rafHub.request(cnt.boundCheckIntersections))
  10374. }
  10375.  
  10376. cProto.detached = function () {
  10377. this.intersectRAF && rafHub.cancel(this.intersectRAF)
  10378. }
  10379.  
  10380. console1.log('ENABLE_RAF_HACK_DOCKED_MESSAGE', tag, "OK")
  10381. } else {
  10382.  
  10383. console1.log('ENABLE_RAF_HACK_DOCKED_MESSAGE', tag, "NG")
  10384. }
  10385.  
  10386. })();
  10387.  
  10388. console1.log("[End]");
  10389.  
  10390. groupEnd();
  10391.  
  10392. }).catch(console.warn);
  10393.  
  10394. }
  10395.  
  10396. if (FIX_SETSRC_AND_THUMBNAILCHANGE_) {
  10397.  
  10398. customElements.whenDefined("yt-img-shadow").then(() => {
  10399.  
  10400. mightFirstCheckOnYtInit();
  10401. groupCollapsed("YouTube Super Fast Chat", " | yt-img-shadow hacks");
  10402. console1.log("[Begin]");
  10403. (() => {
  10404.  
  10405. const tag = "yt-img-shadow"
  10406. const dummy = document.createElement(tag);
  10407.  
  10408. const cProto = getProto(dummy);
  10409. if (!cProto || !cProto.attached) {
  10410. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10411. return;
  10412. }
  10413.  
  10414. if (typeof cProto.thumbnailChanged_ === 'function' && !cProto.thumbnailChanged66_) {
  10415.  
  10416. cProto.thumbnailChanged66_ = cProto.thumbnailChanged_;
  10417. cProto.thumbnailChanged_ = function (a) {
  10418.  
  10419. if (this.oldThumbnail_ && this.thumbnail && this.oldThumbnail_.thumbnails === this.thumbnail.thumbnails) return;
  10420. if (!this.oldThumbnail_ && !this.thumbnail) return;
  10421.  
  10422. return this.thumbnailChanged66_.apply(this, arguments)
  10423.  
  10424. }
  10425. console1.log("cProto.thumbnailChanged_ - OK");
  10426.  
  10427. } else {
  10428. console1.log("cProto.thumbnailChanged_ - NG");
  10429.  
  10430. }
  10431. if (typeof cProto.setSrc_ === 'function' && !cProto.setSrc66_) {
  10432.  
  10433. cProto.setSrc66_ = cProto.setSrc_;
  10434. cProto.setSrc_ = function (a) {
  10435. if ((((this || 0).$ || 0).img || 0).src === a) return;
  10436. return this.setSrc66_.apply(this, arguments)
  10437. }
  10438.  
  10439. console1.log("cProto.setSrc_ - OK");
  10440. } else {
  10441.  
  10442. console1.log("cProto.setSrc_ - NG");
  10443. }
  10444.  
  10445. })();
  10446.  
  10447. console1.log("[End]");
  10448.  
  10449. groupEnd();
  10450.  
  10451. }).catch(console.warn);
  10452.  
  10453. }
  10454.  
  10455. if (FIX_THUMBNAIL_DATACHANGED) {
  10456.  
  10457. customElements.whenDefined("yt-live-chat-author-badge-renderer").then(() => {
  10458.  
  10459. mightFirstCheckOnYtInit();
  10460. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-author-badge-renderer hacks");
  10461. console1.log("[Begin]");
  10462. (() => {
  10463.  
  10464. const tag = "yt-live-chat-author-badge-renderer"
  10465. const dummy = document.createElement(tag);
  10466.  
  10467. const cProto = getProto(dummy);
  10468. if (!cProto || !cProto.attached) {
  10469. console1.warn(`proto.attached for ${tag} is unavailable.`);
  10470. return;
  10471. }
  10472.  
  10473. if (typeof cProto.dataChanged === 'function' && !cProto.dataChanged86 && '|0.169.106|'.includes(`|${fnIntegrity(cProto.dataChanged)}|`)) {
  10474.  
  10475. cProto.dataChanged86 = cProto.dataChanged;
  10476. cProto.dataChanged = function () {
  10477.  
  10478. /* 2024.12.15 */
  10479. /*
  10480. zO.prototype.dataChanged = function() {
  10481. for (var a = Ov(R(this.hostElement).querySelector("#image")); a.firstChild; )
  10482. a.removeChild(a.firstChild);
  10483. if (this.data)
  10484. if (this.data.icon) {
  10485. var b = document.createElement("yt-icon");
  10486. this.data.icon.iconType === "MODERATOR" && this.enableNewModeratorBadge ? (b.polymerController.icon = "yt-sys-icons:shield-filled",
  10487. b.polymerController.defaultToFilled = !0) : b.polymerController.icon = "live-chat-badges:" + this.data.icon.iconType.toLowerCase();
  10488. a.appendChild(b)
  10489. } else if (this.data.customThumbnail) {
  10490. b = document.createElement("img");
  10491. var c;
  10492. (c = (c = UA(this.data.customThumbnail.thumbnails, 16)) ? Yb(kc(c)) : null) ? (b.src = c,
  10493. a.appendChild(b),
  10494. b.setAttribute("alt", this.hostElement.ariaLabel || "")) : Fq(new Zn("Could not compute URL for thumbnail",this.data.customThumbnail))
  10495. }
  10496. }
  10497. */
  10498.  
  10499. const a = (this || 0).data;
  10500. const image = ((this || 0).$ || 0).image;
  10501. if (image && a && image.firstElementChild) {
  10502. const exisiting = image.firstElementChild;
  10503. if (exisiting === image.lastElementChild) {
  10504.  
  10505. if (a.icon && exisiting.nodeName.toUpperCase() === 'YT-ICON') {
  10506.  
  10507. const c = exisiting;
  10508. const t = insp(c);
  10509. const w = ('icon' in t || 'defaultToFilled' in t) ? t : c;
  10510. if ("MODERATOR" === a.icon.iconType && this.enableNewModeratorBadge) {
  10511. if (w.icon !== "yt-sys-icons:shield-filled") w.icon = "yt-sys-icons:shield-filled";
  10512. if (w.defaultToFilled !== true) w.defaultToFilled = true;
  10513. } else {
  10514. const p = "live-chat-badges:" + a.icon.iconType.toLowerCase();;
  10515. if (w.icon !== p) w.icon = p;
  10516. if (w.defaultToFilled !== false) w.defaultToFilled = false;
  10517. }
  10518. return;
  10519.  
  10520.  
  10521. } else if (a.customThumbnail && exisiting.nodeName.toUpperCase() == 'IMG') {
  10522.  
  10523. const c = exisiting;
  10524. if (a.customThumbnail.thumbnails.map(e => e.url).includes(c.src)) {
  10525.  
  10526. c.setAttribute("alt", this.hostElement.ariaLabel || "");
  10527. return;
  10528. }
  10529. /*
  10530.  
  10531. var d;
  10532. (d = (d = KC(a.customThumbnail.thumbnails, 16)) ? lc(oc(d)) : null) ? (c.src = d,
  10533.  
  10534. c.setAttribute("alt", this.hostElement.ariaLabel || "")) : lq(new tm("Could not compute URL for thumbnail", a.customThumbnail))
  10535. */
  10536. }
  10537.  
  10538. }
  10539. }
  10540. return this.dataChanged86.apply(this, arguments)
  10541.  
  10542. }
  10543. console1.log("cProto.dataChanged - OK");
  10544.  
  10545. } else if (typeof cProto.dataChanged === 'function' && !cProto.dataChanged86 && '|1.163.100|1.162.100|1.160.97|1.159.97|'.includes(`|${fnIntegrity(cProto.dataChanged)}|`)) {
  10546.  
  10547. cProto.dataChanged86 = cProto.dataChanged;
  10548. cProto.dataChanged = function (a) {
  10549.  
  10550. /*
  10551.  
  10552. for (var b = xC(Z(this.hostElement).querySelector("#image")); b.firstChild; )
  10553. b.removeChild(b.firstChild);
  10554. if (a)
  10555. if (a.icon) {
  10556. var c = document.createElement("yt-icon");
  10557. "MODERATOR" === a.icon.iconType && this.enableNewModeratorBadge ? (c.icon = "yt-sys-icons:shield-filled",
  10558. c.defaultToFilled = !0) : c.icon = "live-chat-badges:" + a.icon.iconType.toLowerCase();
  10559. b.appendChild(c)
  10560. } else if (a.customThumbnail) {
  10561. c = document.createElement("img");
  10562. var d;
  10563. (d = (d = KC(a.customThumbnail.thumbnails, 16)) ? lc(oc(d)) : null) ? (c.src = d,
  10564. b.appendChild(c),
  10565. c.setAttribute("alt", this.hostElement.ariaLabel || "")) : lq(new tm("Could not compute URL for thumbnail",a.customThumbnail))
  10566. }
  10567.  
  10568. */
  10569.  
  10570.  
  10571. /* 2024.04.20 */
  10572. /*
  10573. for (var b = Tx(N(this.hostElement).querySelector("#image")); b.firstChild; )
  10574. b.removeChild(b.firstChild);
  10575. if (a)
  10576. if (a.icon) {
  10577. var c = document.createElement("yt-icon");
  10578. "MODERATOR" === a.icon.iconType && this.enableNewModeratorBadge ? (c.polymerController.icon = "yt-sys-icons:shield-filled",
  10579. c.polymerController.defaultToFilled = !0) : c.polymerController.icon = "live-chat-badges:" + a.icon.iconType.toLowerCase();
  10580. b.appendChild(c)
  10581. } else if (a.customThumbnail) {
  10582. c = document.createElement("img");
  10583. var d;
  10584. (d = (d = WD(a.customThumbnail.thumbnails, 16)) ? Sb(ec(d)) : null) ? (c.src = d,
  10585. b.appendChild(c),
  10586. c.setAttribute("alt", this.hostElement.ariaLabel || "")) : nr(new mn("Could not compute URL for thumbnail",a.customThumbnail))
  10587. }
  10588. */
  10589.  
  10590. const image = ((this || 0).$ || 0).image
  10591. if (image && a && image.firstElementChild) {
  10592. const exisiting = image.firstElementChild;
  10593. if (exisiting === image.lastElementChild) {
  10594.  
  10595. if (a.icon && exisiting.nodeName.toUpperCase() === 'YT-ICON') {
  10596.  
  10597. const c = exisiting;
  10598. const t = insp(c);
  10599. const w = ('icon' in t || 'defaultToFilled' in t) ? t : c;
  10600. if ("MODERATOR" === a.icon.iconType && this.enableNewModeratorBadge) {
  10601. if (w.icon !== "yt-sys-icons:shield-filled") w.icon = "yt-sys-icons:shield-filled";
  10602. if (w.defaultToFilled !== true) w.defaultToFilled = true;
  10603. } else {
  10604. const p = "live-chat-badges:" + a.icon.iconType.toLowerCase();;
  10605. if (w.icon !== p) w.icon = p;
  10606. if (w.defaultToFilled !== false) w.defaultToFilled = false;
  10607. }
  10608. return;
  10609.  
  10610.  
  10611. } else if (a.customThumbnail && exisiting.nodeName.toUpperCase() == 'IMG') {
  10612.  
  10613. const c = exisiting;
  10614. if (a.customThumbnail.thumbnails.map(e => e.url).includes(c.src)) {
  10615.  
  10616. c.setAttribute("alt", this.hostElement.ariaLabel || "");
  10617. return;
  10618. }
  10619. /*
  10620.  
  10621. var d;
  10622. (d = (d = KC(a.customThumbnail.thumbnails, 16)) ? lc(oc(d)) : null) ? (c.src = d,
  10623.  
  10624. c.setAttribute("alt", this.hostElement.ariaLabel || "")) : lq(new tm("Could not compute URL for thumbnail", a.customThumbnail))
  10625. */
  10626. }
  10627.  
  10628. }
  10629. }
  10630. return this.dataChanged86.apply(this, arguments)
  10631.  
  10632. }
  10633. console1.log("cProto.dataChanged - OK");
  10634.  
  10635. } else {
  10636. assertor(() => fnIntegrity(cProto.dataChanged, '0.169.106'));
  10637. console1.log("cProto.dataChanged - NG");
  10638.  
  10639. }
  10640.  
  10641. })();
  10642.  
  10643. console1.log("[End]");
  10644.  
  10645. groupEnd();
  10646.  
  10647. }).catch(console.warn);
  10648.  
  10649.  
  10650. }
  10651.  
  10652. if (USE_ADVANCED_TICKING) {
  10653. // leading the emoji cannot be rendered.
  10654.  
  10655. // const qz38 = lcrPromiseFn();
  10656.  
  10657. // qz38.then((lcrGet) => {
  10658.  
  10659. // const tag = "yt-live-chat-renderer"
  10660. // const dummy = lcrGet();
  10661.  
  10662. const lcrFn2 = (lcrDummy) => {
  10663.  
  10664. const tag = "yt-live-chat-renderer"
  10665. const dummy = lcrDummy;
  10666.  
  10667.  
  10668. const cProto = getProto(dummy);
  10669.  
  10670. // dummy.usePatchedLifecycles = false;
  10671. // dummy.data = null;
  10672. // dummy.__data = null;
  10673. // Object.setPrototypeOf(dummy, Object.prototype);
  10674. if (!cProto || !cProto.attached) {
  10675. console.warn(`proto.attached for ${tag} is unavailable.`);
  10676. return;
  10677. }
  10678.  
  10679. /*
  10680. <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;
  10681. */
  10682.  
  10683. if (cProto && typeof cProto.immediatelyApplyLiveChatActions === 'function' && cProto.immediatelyApplyLiveChatActions.length === 1 && !cProto.immediatelyApplyLiveChatActions82) {
  10684. cProto.immediatelyApplyLiveChatActions82 = cProto.immediatelyApplyLiveChatActions;
  10685. cProto.immediatelyApplyLiveChatActions = function (arr) {
  10686.  
  10687.  
  10688. // console.log(1237)
  10689. try {
  10690. preprocessChatLiveActions(arr);
  10691. } catch (e) {
  10692. console.warn(e);
  10693. }
  10694. return this.immediatelyApplyLiveChatActions82(arr);
  10695. };
  10696. }
  10697.  
  10698.  
  10699. if (cProto && typeof cProto.preprocessActions_ === 'function' && cProto.preprocessActions_.length === 1 && !cProto.preprocessActions82_) {
  10700. cProto.preprocessActions82_ = cProto.preprocessActions_;
  10701. cProto.preprocessActions_ = function (arr) {
  10702.  
  10703. arr = this.preprocessActions82_(arr);
  10704.  
  10705. try {
  10706. preprocessChatLiveActions(arr);
  10707. } catch (e) {
  10708. console.warn(e);
  10709. }
  10710. return arr;
  10711. };
  10712. }
  10713.  
  10714.  
  10715.  
  10716. };
  10717. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  10718. getLCRDummy().then(lcrFn2);
  10719. }
  10720.  
  10721. if (MODIFY_EMIT_MESSAGES_FOR_BOOST_CHAT) {
  10722.  
  10723. const lcrFn2 = (lcrDummy) => {
  10724.  
  10725. const tag = "yt-live-chat-renderer"
  10726. const dummy = lcrDummy;
  10727.  
  10728.  
  10729. const cProto = getProto(dummy);
  10730.  
  10731. // dummy.usePatchedLifecycles = false;
  10732. // dummy.data = null;
  10733. // dummy.__data = null;
  10734. // Object.setPrototypeOf(dummy, Object.prototype);
  10735. if (!cProto || !cProto.attached) {
  10736. console.warn(`proto.attached for ${tag} is unavailable.`);
  10737. return;
  10738. }
  10739.  
  10740. /*
  10741.  
  10742. // https://www.youtube.com/s/desktop/c01ea7e3/jsbin/live_chat_polymer.vflset/live_chat_polymer.js
  10743.  
  10744.  
  10745. YP.prototype.emitSmoothedMessages = function() {
  10746. this.JSC$10797_nextUpdateId = null;
  10747. if (this.JSC$10797_messageQueue.length) {
  10748. var a = 1E4;
  10749. this.JSC$10797_estimatedUpdateInterval !== null && this.JSC$10797_lastUpdateTime !== null && (a = this.JSC$10797_estimatedUpdateInterval - Date.now() + this.JSC$10797_lastUpdateTime);
  10750. var b = this.JSC$10797_messageQueue.length < a / 80 ? 1 : Math.ceil(this.JSC$10797_messageQueue.length / (a / 80));
  10751. var c = aba(this.JSC$10797_messageQueue.splice(0, b));
  10752. this.callback && this.callback(c);
  10753. this.JSC$10797_messageQueue.length && (b === 1 ? (b = a / this.JSC$10797_messageQueue.length,
  10754. b *= Math.random() + .5,
  10755. b = Math.min(1E3, b),
  10756. b = Math.max(80, b)) : b = 80,
  10757. this.JSC$10797_nextUpdateId = window.setTimeout(this.emitSmoothedMessages.bind(this), b))
  10758. }
  10759. }
  10760. // emitSmoothedMessages: say b = 1000, 858.24, 529.49, 357.15, 194.96, 82.12, 80, 80, 80 ....
  10761.  
  10762. */
  10763.  
  10764.  
  10765. const _flag0281_ = window._flag0281_;
  10766.  
  10767.  
  10768. if ((_flag0281_ & 0x40000) === 0x40000 && cProto && typeof cProto.preprocessActions_ === 'function' && cProto.preprocessActions_.length === 1 && !cProto.preprocessActions92_) {
  10769. // we can disable smooth message emitting if boost chat is enabled (0x40000)
  10770. let byPass = false;
  10771. let q33 = false;
  10772. let key_estimatedUpdateInterval = '';
  10773. let key_lastUpdateTime = '';
  10774. let key_messageQueue = '';
  10775. const emitSmoothedMessagesInstantFn = function () {
  10776. if (byPass) return this.emitSmoothedMessages018();
  10777. byPass = true;
  10778. try {
  10779. if (!q33) {
  10780. const keys = Object.getOwnPropertyNames(this);
  10781. for (const key of keys) {
  10782. if (`${key}`.endsWith('_estimatedUpdateInterval')) key_estimatedUpdateInterval = key;
  10783. else if (`${key}`.endsWith('_lastUpdateTime')) key_lastUpdateTime = key;
  10784. else if (`${key}`.endsWith('_messageQueue')) key_messageQueue = key;
  10785. else continue;
  10786. if (key_estimatedUpdateInterval && key_lastUpdateTime && key_messageQueue) break;
  10787. }
  10788. if (key_estimatedUpdateInterval && key_lastUpdateTime && key_messageQueue) {
  10789. q33 = true;
  10790. }
  10791. }
  10792. if (key_estimatedUpdateInterval && key_lastUpdateTime) {
  10793. this[key_estimatedUpdateInterval] = 78; // 80 - 2
  10794. this[key_lastUpdateTime] = Date.now() - 1;
  10795. }
  10796. } catch (e) { }
  10797. // console.log(19893,key_estimatedUpdateInterval, key_lastUpdateTime)
  10798. // make a = this.JSC$10797_estimatedUpdateInterval - Date.now() + this.JSC$10797_lastUpdateTime small
  10799.  
  10800. // this.JSC$10797_estimatedUpdateInterval = Date.now() + 1
  10801. // this.JSC$10797_lastUpdateTime = Date.now()
  10802.  
  10803. // if (!window.setTimeout837) {
  10804. // window.setTimeout837 = window.setTimeout;
  10805. // window.setTimeout838 = function (f, d) {
  10806. // if (arguments.length !== 2) return window.setTimeout837(...arguments);
  10807. // console.log(12883, d)
  10808. // return window.setTimeout837(f, d > 80 ? 80 : d)
  10809. // }
  10810. // }
  10811. // else if (window.setTimeout837 !== window.setTimeout) {
  10812. // window.setTimeout837 = window.setTimeout;
  10813. // }
  10814. // let r;
  10815. // if (window.setTimeout837 && window.setTimeout838) {
  10816. // window.setTimeout = window.setTimeout838;
  10817. // r = this.emitSmoothedMessages018();
  10818. // window.setTimeout = window.setTimeout837;
  10819. // } else {
  10820. // r = this.emitSmoothedMessages018();
  10821. // }
  10822. let doInNextCall = false;
  10823. try {
  10824. const messageQueue = key_messageQueue ? this[key_messageQueue] : null;
  10825. if (!messageQueue || !messageQueue.length) {
  10826.  
  10827. } else if (messageQueue.length > 255) {
  10828.  
  10829. } else if (!document.hidden) {
  10830.  
  10831. } else {
  10832. doInNextCall = true;
  10833. }
  10834. } catch (e) { }
  10835.  
  10836. let r;
  10837. if (doInNextCall) {
  10838. setTimeout_(() => this.emitSmoothedMessages019(), 250);
  10839. } else {
  10840. r = this.emitSmoothedMessages018();
  10841. }
  10842. byPass = false;
  10843. return r;
  10844. };
  10845. cProto.preprocessActions92_ = cProto.preprocessActions_;
  10846. cProto.preprocessActions_ = function (arr) {
  10847.  
  10848. arr = this.preprocessActions92_(arr);
  10849.  
  10850. try {
  10851.  
  10852. const smoothedQueue_ = this.smoothedQueue_;
  10853. if (smoothedQueue_ && !smoothedQueue_.__fix018__) {
  10854. smoothedQueue_.__fix018__ = true;
  10855. if (!smoothedQueue_.emitSmoothedMessages018 && typeof smoothedQueue_.emitSmoothedMessages === 'function' && smoothedQueue_.emitSmoothedMessages.length === 0) {
  10856. smoothedQueue_.emitSmoothedMessages018 = smoothedQueue_.emitSmoothedMessages;
  10857. smoothedQueue_.emitSmoothedMessages019 = emitSmoothedMessagesInstantFn;
  10858. smoothedQueue_.emitSmoothedMessages = emitSmoothedMessagesInstantFn;
  10859. }
  10860. }
  10861. } catch (e) {
  10862. console.warn(e);
  10863. }
  10864. return arr;
  10865. };
  10866. }
  10867.  
  10868.  
  10869.  
  10870.  
  10871. };
  10872. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  10873. getLCRDummy().then(lcrFn2);
  10874. }
  10875.  
  10876.  
  10877. if (FIX_TOOLTIP_DISPLAY) {
  10878.  
  10879. // ----------------------------------------------------------------------------------------------------
  10880.  
  10881. const checkPDGet = (pd) => {
  10882. return pd && pd.get && !pd.set && pd.enumerable && pd.configurable;
  10883. }
  10884.  
  10885. const tooltipUIWM = new WeakMap();
  10886. const tooltipInitProps = {};
  10887. const createTooltipIfRequired_ = function () {
  10888. let r;
  10889. if (tooltipUIWM.get(this) === void 0) {
  10890. const w = document.createElement;
  10891. let EU = null;
  10892. tooltipUIWM.set(this, null);
  10893. document.createElement = function () {
  10894. let r = w.apply(this, arguments);
  10895. EU = r;
  10896. return r;
  10897. };
  10898. r = this.createTooltipIfRequired14_();
  10899. document.createElement = w;
  10900. if (EU instanceof HTMLElement_ && EU.is) {
  10901. tooltipUIWM.set(this, EU);
  10902. EU.setAttribute('__nogc__', ''); // avoid gc process script
  10903.  
  10904. if (typeof EU.offset === 'number') tooltipInitProps['offset'] = EU.offset;
  10905. if (typeof EU.fitToVisibleBounds === 'boolean') tooltipInitProps['fitToVisibleBounds'] = EU.fitToVisibleBounds;
  10906. if (typeof EU.position === 'string') tooltipInitProps['position'] = EU.position;
  10907. if (typeof EU.for === 'string') tooltipInitProps['for'] = EU.for;
  10908.  
  10909. // this.__mcT__ = EU.outerHTML;
  10910. // EU.__dataX = JSON.stringify(EU.__data);
  10911. // EU.__dataY = Object.entries(EU);
  10912.  
  10913. // <<< FOR DEBUG >>>
  10914. // let kx;
  10915. // Object.defineProperty(EU, '_target', {
  10916. // get(){
  10917. // return kx;
  10918. // },
  10919. // set(nv){
  10920. // kx= nv;
  10921. // debugger;
  10922. // return true;
  10923. // }
  10924. // });
  10925. // <<< FOR DEBUG >>>
  10926.  
  10927. if (typeof Polymer !== 'undefined' && Polymer.__fixedGetOwnerRoot__ && Polymer.__fixedQuerySelector__) {
  10928.  
  10929. } else {
  10930. let eProto = null;
  10931. const euCnt = insp(EU);
  10932. if (checkPDGet(Object.getOwnPropertyDescriptor(euCnt.constructor.prototype || {}, 'target'))) {
  10933.  
  10934. eProto = euCnt.constructor.prototype;
  10935. } else if (checkPDGet(Object.getOwnPropertyDescriptor(EU.constructor.prototype || {}, 'target'))) {
  10936.  
  10937. eProto = EU.constructor.prototype;
  10938. }
  10939. if (eProto) {
  10940. delete eProto.target;
  10941. /*
  10942.  
  10943. get target() {
  10944. var a = Pv(this).parentNode, b = Pv(this).getOwnerRoot(), c;
  10945. this.for ? c = Pv(b).querySelector("#" + this.for) : c = a.nodeType == Node.DOCUMENT_FRAGMENT_NODE ? b.host : a;
  10946. return c
  10947. },
  10948. */
  10949. Object.defineProperty(eProto, 'target', {
  10950. get() {
  10951. const cnt = insp(this);
  10952. const hostElement = cnt.hostElement || cnt;
  10953. let a = hostElement.parentNode, b = hostElement.getRootNode();
  10954. const fr = cnt.for || hostElement.for;
  10955. return (fr ? b.querySelector("#" + fr) : a)
  10956. }
  10957. })
  10958. }
  10959. }
  10960. // setInterval(()=>EU.updatePosition(), 100)
  10961.  
  10962. } else {
  10963. tooltipUIWM.set(this, null);
  10964. }
  10965. } else {
  10966. r = this.createTooltipIfRequired14_();
  10967. }
  10968.  
  10969. const EU = tooltipUIWM.get(this);
  10970. if (EU) {
  10971. EU.remove();
  10972. if (typeof tooltipInitProps.offset === 'number') EU['offset'] = tooltipInitProps.offset;
  10973. if (typeof tooltipInitProps.fitToVisibleBounds === 'boolean') EU['fitToVisibleBounds'] = tooltipInitProps.fitToVisibleBounds;
  10974. try {
  10975. if (typeof tooltipInitProps.position === 'string') EU['position'] = tooltipInitProps.position;
  10976. if (typeof tooltipInitProps.for === 'string') EU['for'] = tooltipInitProps.for; else delete EU.for;
  10977. } catch (e) { }
  10978. }
  10979.  
  10980. // 2025.01.10 fix
  10981. const CS = EU;
  10982. if (!CS._showing && CS.__shady_parentNode && CS.__shady_parentNode !== CS.parentNode) {
  10983. if (CS.__shady_parentNode) {
  10984. try {
  10985. CS.__shady_parentNode.__shady_removeChild(CS);
  10986. } catch (e) { }
  10987. }
  10988. if (CS.__shady_parentNode) {
  10989. try {
  10990. CS.__shady_parentNode.removeChild(CS);
  10991. } catch (e) { }
  10992. }
  10993. if (CS.__shady_parentNode) {
  10994. try {
  10995. CS.__shady_parentNode.__shady_native_removeChild(CS);
  10996. } catch (e) { }
  10997. }
  10998. if (CS.__shady_parentNode) {
  10999. try {
  11000. __shady_native_removeChild.call(CS.__shady_parentNode, CS);
  11001. } catch (e) { }
  11002. }
  11003. if (CS.parentNode && !CS.__shady_parentNode) {
  11004. try {
  11005. __shady_native_removeChild.call(CS.parentNode, CS);
  11006. } catch (e) { }
  11007. }
  11008. }
  11009.  
  11010. return r;
  11011. };
  11012.  
  11013.  
  11014. // added in 2024.05.02
  11015. const lcrFn2 = (lcrDummy) => {
  11016.  
  11017. // console.log(8171, 99);
  11018. const tag = "yt-live-chat-renderer"
  11019. const dummy = lcrDummy;
  11020.  
  11021. const cProto = getProto(dummy);
  11022. if (!cProto || !cProto.attached) {
  11023. console.warn(`proto.attached for ${tag} is unavailable.`);
  11024. return;
  11025. }
  11026.  
  11027. /*
  11028. <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;
  11029. */
  11030.  
  11031. if (cProto && typeof cProto.createTooltipIfRequired_ === 'function' && cProto.createTooltipIfRequired_.length === 0 && !cProto.createTooltipIfRequired14_) {
  11032. cProto.createTooltipIfRequired14_ = cProto.createTooltipIfRequired_;
  11033. cProto.createTooltipIfRequired_ = createTooltipIfRequired_;
  11034. }
  11035.  
  11036. };
  11037. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  11038. getLCRDummy().then(lcrFn2);
  11039.  
  11040. // ----------------------------------------------------------------------------------------------------
  11041.  
  11042. customElements.whenDefined("tp-yt-paper-tooltip").then(() => {
  11043.  
  11044. mightFirstCheckOnYtInit();
  11045. groupCollapsed("YouTube Super Fast Chat", " | tp-yt-paper-tooltip hacks");
  11046. console1.log("[Begin]");
  11047. (() => {
  11048.  
  11049. const tag = "tp-yt-paper-tooltip"
  11050. const dummy = document.createElement(tag);
  11051.  
  11052. const cProto = getProto(dummy);
  11053. if (!cProto || !cProto.attached) {
  11054. console1.warn(`proto.attached for ${tag} is unavailable.`);
  11055. return;
  11056. }
  11057.  
  11058. if (typeof cProto.attached === 'function' && typeof cProto.detached === 'function' && cProto._readyClients && cProto._attachDom && cProto.ready && !cProto._readyClients43) {
  11059.  
  11060. cProto._readyClients43 = cProto._readyClients;
  11061. cProto._readyClients = function () {
  11062. // console.log(1238)
  11063.  
  11064. let r = cProto._readyClients43.apply(this, arguments);
  11065. if (this.$ && this.$$ && this.$.tooltip) this.root = null; // fix this.root = null != (b = a.root) ? b : this.host
  11066. return r;
  11067. }
  11068.  
  11069. console1.log("_readyClients - OK");
  11070.  
  11071. } else {
  11072. console1.log("_readyClients - NG");
  11073.  
  11074. }
  11075.  
  11076. if (typeof cProto.show === 'function' && !cProto.show17) {
  11077. cProto.show17 = cProto.show;
  11078. cProto.show = function () {
  11079.  
  11080. let r = this.show17.apply(this, arguments);
  11081. this._showing === true && Promise.resolve(this).then((cnt) => {
  11082. const tooltip = (cnt.$ || 0).tooltip;
  11083.  
  11084. if (tooltip && tooltip.firstElementChild === null) {
  11085. let text = tooltip.textContent;
  11086. if (typeof text === 'string' && text.length >= 2) {
  11087. tooltip.textContent = text.trim();
  11088. }
  11089. }
  11090. cnt = null;
  11091. }).catch(console.warn)
  11092. return r;
  11093. }
  11094.  
  11095. console1.log("trim tooltip content - OK");
  11096.  
  11097. } else {
  11098. console1.log("trim tooltip content - NG");
  11099.  
  11100. }
  11101.  
  11102.  
  11103. })();
  11104.  
  11105. console1.log("[End]");
  11106.  
  11107. groupEnd();
  11108.  
  11109. }).catch(console.warn);
  11110.  
  11111. }
  11112.  
  11113.  
  11114. if (FIX_CLICKING_MESSAGE_MENU_DISPLAY_ON_MOUSE_CLICK) {
  11115.  
  11116. const hookDocumentMouseDownSetupFn = () => {
  11117.  
  11118. let muzTimestamp = 0;
  11119. let nszDropdown = null;
  11120.  
  11121. const handlerObject = {
  11122.  
  11123. muHandler282: function (evt) {
  11124. // console.log(evt, 7, document.querySelector('tp-yt-iron-dropdown[focused].style-scope.yt-live-chat-app'))
  11125. if (!evt || !evt.isTrusted || !muzTimestamp) return;
  11126. const dropdown = nszDropdown;
  11127. muzTimestamp = 0;
  11128. nszDropdown = null;
  11129.  
  11130. const kurMPCe = kRef(currentMenuPivotWR) || 0;
  11131. const hostElement = kurMPCe.hostElement || kurMPCe; // should be always hostElement === kurMPCe ?
  11132. if (!hostElement.hasAttribute('menu-visible')) return;
  11133.  
  11134. const chatBanner = HTMLElement_.prototype.closest.call(hostElement, 'yt-live-chat-banner-renderer') || 0;
  11135. if (chatBanner) return;
  11136.  
  11137. if (dropdown && dropdown.positionTarget && hostElement.contains(dropdown.positionTarget)) {
  11138. muzTimestamp = Date.now();
  11139. evt.stopImmediatePropagation();
  11140. evt.stopPropagation();
  11141. Promise.resolve(dropdown).then((dropdown) => {
  11142. dropdown.cancel();
  11143. dropdown = null;
  11144. });
  11145. }
  11146.  
  11147. },
  11148.  
  11149. mlHandler282: function (evt) {
  11150. muzTimestamp = 0;
  11151. nszDropdown = null;
  11152. },
  11153.  
  11154. ckHandler282: function (evt) {
  11155. if (!evt || !evt.isTrusted || !muzTimestamp) return;
  11156. if (Date.now() - muzTimestamp < 40) {
  11157. muzTimestamp = Date.now();
  11158. evt.stopImmediatePropagation();
  11159. evt.stopPropagation();
  11160. }
  11161. },
  11162.  
  11163. tapHandler282: function (evt) {
  11164. if (!evt || !evt.isTrusted || !muzTimestamp) return;
  11165. if (Date.now() - muzTimestamp < 40) {
  11166. muzTimestamp = Date.now();
  11167. evt.stopImmediatePropagation();
  11168. evt.stopPropagation();
  11169. }
  11170. },
  11171.  
  11172. handleEvent(evt) {
  11173. if (evt) {
  11174. const kurMPCe = kRef(currentMenuPivotWR) || 0;
  11175. const kurMPCc = insp(kurMPCe);
  11176. const hostElement = kurMPCc.hostElement || kurMPCc;
  11177. if (!kurMPCc || kurMPCc.isAttached !== true || hostElement.isConnected !== true) return;
  11178. switch (evt.type) {
  11179. case 'mouseup':
  11180. return this.muHandler282(evt);
  11181. case 'mouseleave':
  11182. return this.mlHandler282(evt);
  11183. case 'tap':
  11184. return this.tapHandler282(evt);
  11185. case 'click':
  11186. return this.ckHandler282(evt);
  11187. }
  11188. }
  11189. }
  11190.  
  11191. }
  11192.  
  11193. document.addEventListener('mousedown', function (evt) {
  11194.  
  11195. if (!evt || !evt.isTrusted || !evt.target) return;
  11196.  
  11197. muzTimestamp = 0;
  11198. nszDropdown = null;
  11199.  
  11200. /** @type {HTMLElement | null} */
  11201. const kurMP = kRef(currentMenuPivotWR);
  11202. if (!kurMP) return;
  11203. const kurMPCe = HTMLElement_.prototype.closest.call(kurMP, '[menu-visible]') || 0; // element
  11204.  
  11205. if (!kurMPCe || !kurMPCe.hasAttribute('whole-message-clickable')) return;
  11206.  
  11207. const kurMPCc = insp(kurMPCe); // controller
  11208.  
  11209. if (!kurMPCc.isClickableChatRow111 || !kurMPCc.isClickableChatRow111() || !HTMLElement_.prototype.contains.call(kurMPCe, evt.target)) return;
  11210.  
  11211. const chatBanner = HTMLElement_.prototype.closest.call(kurMPCe, 'yt-live-chat-banner-renderer') || 0;
  11212. if (chatBanner) return;
  11213.  
  11214. let targetDropDown = null;
  11215. for (const dropdown of document.querySelectorAll('tp-yt-iron-dropdown.style-scope.yt-live-chat-app')) {
  11216. if (dropdown && dropdown.positionTarget === kurMP) {
  11217. targetDropDown = dropdown;
  11218. }
  11219. }
  11220.  
  11221. if (!targetDropDown) return;
  11222.  
  11223. if (evt.target.closest('ytd-menu-popup-renderer')) return;
  11224.  
  11225. if ((nszDropdown = targetDropDown)) {
  11226. muzTimestamp = Date.now();
  11227. evt.stopImmediatePropagation();
  11228. evt.stopPropagation();
  11229. currentMenuPivotWR = mWeakRef(kurMPCe);
  11230.  
  11231. const listenOpts = { capture: true, passive: false, once: true };
  11232.  
  11233. // remove unexcecuted eventHandler
  11234. document.removeEventListener('mouseup', handlerObject, listenOpts);
  11235. document.removeEventListener('mouseleave', handlerObject, listenOpts);
  11236. document.removeEventListener('tap', handlerObject, listenOpts);
  11237. document.removeEventListener('click', handlerObject, listenOpts);
  11238.  
  11239. // inject one time eventHandler to by pass events
  11240. document.addEventListener('mouseup', handlerObject, listenOpts);
  11241. document.addEventListener('mouseleave', handlerObject, listenOpts);
  11242. document.addEventListener('tap', handlerObject, listenOpts);
  11243. document.addEventListener('click', handlerObject, listenOpts);
  11244.  
  11245. }
  11246.  
  11247. }, true);
  11248.  
  11249. }
  11250.  
  11251.  
  11252. // yt-live-chat-paid-message-renderer ??
  11253.  
  11254. /*
  11255.  
  11256. [...(new Set([...document.querySelectorAll('*')].filter(e=>e.is&&('shouldSupportWholeItemClick' in e)).map(e=>e.is))).keys()]
  11257.  
  11258.  
  11259. "yt-live-chat-ticker-paid-message-item-renderer"
  11260. "yt-live-chat-ticker-paid-sticker-item-renderer"
  11261. "yt-live-chat-paid-message-renderer"
  11262. "yt-live-chat-text-message-renderer"
  11263. "yt-live-chat-paid-sticker-renderer"
  11264.  
  11265. */
  11266.  
  11267.  
  11268. whenDefinedMultiple([
  11269.  
  11270. "yt-live-chat-paid-message-renderer",
  11271. "yt-live-chat-membership-item-renderer",
  11272. "yt-live-chat-paid-sticker-renderer",
  11273. "yt-live-chat-text-message-renderer",
  11274. "yt-live-chat-auto-mod-message-renderer",
  11275.  
  11276. /*
  11277. "yt-live-chat-ticker-paid-message-item-renderer",
  11278. "yt-live-chat-ticker-paid-sticker-item-renderer",
  11279. "yt-live-chat-paid-message-renderer",
  11280. "yt-live-chat-text-message-renderer",
  11281. "yt-live-chat-paid-sticker-renderer",
  11282.  
  11283. "yt-live-chat-ticker-sponsor-item-renderer",
  11284. "yt-live-chat-banner-header-renderer",
  11285. "ytd-sponsorships-live-chat-gift-purchase-announcement-renderer",
  11286. "ytd-sponsorships-live-chat-header-renderer",
  11287. "ytd-sponsorships-live-chat-gift-redemption-announcement-renderer",
  11288.  
  11289.  
  11290.  
  11291.  
  11292. "yt-live-chat-auto-mod-message-renderer",
  11293. "yt-live-chat-text-message-renderer",
  11294. "yt-live-chat-paid-message-renderer",
  11295.  
  11296. "yt-live-chat-legacy-paid-message-renderer",
  11297. "yt-live-chat-membership-item-renderer",
  11298. "yt-live-chat-paid-sticker-renderer",
  11299. "yt-live-chat-donation-announcement-renderer",
  11300. "yt-live-chat-moderation-message-renderer",
  11301. "ytd-sponsorships-live-chat-gift-purchase-announcement-renderer",
  11302. "ytd-sponsorships-live-chat-gift-redemption-announcement-renderer",
  11303. "yt-live-chat-viewer-engagement-message-renderer",
  11304.  
  11305. */
  11306.  
  11307.  
  11308. ]).then(sTags => {
  11309. // return; // M33
  11310.  
  11311. mightFirstCheckOnYtInit();
  11312. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-message-renderer(s)... hacks");
  11313. console1.log("[Begin]");
  11314. let doMouseHook = false;
  11315.  
  11316. const dProto = {
  11317. isClickableChatRow111: function () {
  11318. return (
  11319. this.data && typeof this.shouldSupportWholeItemClick === 'function' && typeof this.hasModerationOverlayVisible === 'function' &&
  11320. this.data.contextMenuEndpoint && this.wholeMessageClickable && this.shouldSupportWholeItemClick() && !this.hasModerationOverlayVisible()
  11321. ); // follow .onItemTap(a)
  11322. }
  11323. };
  11324.  
  11325. for (const sTag of sTags) { // ##tag##
  11326.  
  11327.  
  11328. (() => {
  11329.  
  11330. const tag = sTag;
  11331. const dummy = document.createElement(tag);
  11332.  
  11333. const cProto = getProto(dummy);
  11334. if (!cProto || !cProto.attached) {
  11335. console1.warn(`proto.attached for ${tag} is unavailable.`);
  11336. return;
  11337. }
  11338.  
  11339. const dCnt = insp(dummy);
  11340. if ('wholeMessageClickable' in dCnt && typeof dCnt.hasModerationOverlayVisible === 'function' && typeof dCnt.shouldSupportWholeItemClick === 'function') {
  11341.  
  11342. cProto.isClickableChatRow111 = dProto.isClickableChatRow111;
  11343.  
  11344. const toHookDocumentMouseDown = typeof cProto.shouldSupportWholeItemClick === 'function' && typeof cProto.hasModerationOverlayVisible === 'function';
  11345.  
  11346. if (toHookDocumentMouseDown) {
  11347. doMouseHook = true;
  11348. }
  11349.  
  11350. console1.log("shouldSupportWholeItemClick - OK", tag);
  11351.  
  11352. } else {
  11353.  
  11354. console1.log("shouldSupportWholeItemClick - NG", tag);
  11355. }
  11356.  
  11357.  
  11358. })();
  11359.  
  11360. }
  11361.  
  11362.  
  11363. if (doMouseHook) {
  11364.  
  11365. hookDocumentMouseDownSetupFn();
  11366.  
  11367. console1.log("FIX_CLICKING_MESSAGE_MENU_DISPLAY_ON_MOUSE_CLICK - Doc MouseEvent OK");
  11368. }
  11369.  
  11370. console1.log("[End]");
  11371.  
  11372. groupEnd();
  11373.  
  11374.  
  11375. }).catch(console.warn);
  11376.  
  11377.  
  11378. // https://www.youtube.com/watch?v=oQzFi1NO7io
  11379.  
  11380.  
  11381. }
  11382.  
  11383. if (NO_ITEM_TAP_FOR_NON_STATIONARY_TAP) {
  11384. let targetElementCntWR = null;
  11385. let _e0 = null;
  11386. document.addEventListener('mousedown', (e) => {
  11387. if (!e || !e.isTrusted) return;
  11388. let element = e.target;
  11389. for (; element instanceof HTMLElement_; element = element.parentNode) {
  11390. if (element.is) break;
  11391. }
  11392. if (!element || !element.is) return;
  11393. if (element.closest('ytd-menu-popup-renderer')) return;
  11394. const cnt = insp(element);
  11395. if (typeof cnt.onItemTap === 'function') {
  11396. cnt._onItemTap_isNonStationary = 0;
  11397. const cProto = getProto(element);
  11398. if (!cProto.onItemTap366 && typeof cProto.onItemTap === 'function' && cProto.onItemTap.length === 1) {
  11399. cProto.onItemTap366 = cProto.onItemTap; // note: [onItemTap] .some(function(){...})
  11400. cProto.onItemTap = function (a) {
  11401. const t = this._onItemTap_isNonStationary;
  11402. this._onItemTap_isNonStationary = 0;
  11403. if (t > Date.now()) return;
  11404. return this.onItemTap366.apply(this, arguments)
  11405. }
  11406. }
  11407. _e0 = e;
  11408. targetElementCntWR = mWeakRef(cnt);
  11409. } else {
  11410. _e0 = null;
  11411. targetElementCntWR = null;
  11412. }
  11413. }, { capture: true, passive: true });
  11414.  
  11415. document.addEventListener('mouseup', (e) => {
  11416. if (!e || !e.isTrusted) return;
  11417. const e0 = _e0;
  11418. _e0 = null;
  11419. if (!e0) return;
  11420. const cnt = kRef(targetElementCntWR);
  11421. targetElementCntWR = null;
  11422. if (!cnt) return;
  11423. if (e.timeStamp - e0.timeStamp > TAP_ACTION_DURATION) {
  11424. cnt._onItemTap_isNonStationary = Date.now() + 40;
  11425. } else if (`${window.getSelection()}`.trim().replace(/[\u2000-\u200a\u202f\u2800\u200B\u200C\u200D\uFEFF]+/g, '').length >= 1) {
  11426. cnt._onItemTap_isNonStationary = Date.now() + 40;
  11427. } else {
  11428. const dx = e.clientX - e0.clientX;
  11429. const dy = e.clientY - e0.clientY;
  11430. const dd = Math.sqrt(dx * dx + dy * dy);
  11431. const ddmm = px2mm(dd);
  11432. if (ddmm > 1.0) {
  11433. cnt._onItemTap_isNonStationary = Date.now() + 40;
  11434. } else {
  11435. cnt._onItemTap_isNonStationary = 0;
  11436. }
  11437. }
  11438. }, { capture: true, passive: true });
  11439.  
  11440. }
  11441.  
  11442.  
  11443. const __showContextMenu_assign_lock_with_external_unlock_ = function (targetCnt) {
  11444.  
  11445. let rr = null;
  11446. const p1 = new Promise(resolve => {
  11447. rr = resolve;
  11448. });
  11449.  
  11450. const p1unlock = () => {
  11451. const f = rr;
  11452. if (f) {
  11453. rr = null;
  11454. f();
  11455. }
  11456. }
  11457.  
  11458. return {
  11459. p1,
  11460. p1unlock,
  11461. assignLock: (targetCnt, timeout) => {
  11462. targetCnt.__showContextMenu_assign_lock__(p1);
  11463. if (timeout) setTimeout(p1unlock, timeout);
  11464. }
  11465. }
  11466.  
  11467. }
  11468.  
  11469. if (PREREQUEST_CONTEXT_MENU_ON_MOUSE_DOWN) {
  11470.  
  11471. document.addEventListener('mousedown', function (evt) {
  11472.  
  11473. const maxloopDOMTreeElements = 4;
  11474. const maxloopYtCompontents = 4;
  11475. let j1 = 0;
  11476. let j2 = 0;
  11477. let target = (evt || 0).target || 0;
  11478. if (!target) return;
  11479. if (target.closest('ytd-menu-popup-renderer')) return;
  11480.  
  11481. while (target instanceof HTMLElement_) {
  11482. if (++j1 > maxloopDOMTreeElements) break;
  11483. if (typeof (target.is || insp(target).is || null) === 'string') break;
  11484. target = nodeParent(target);
  11485. }
  11486. const components = [];
  11487. while (target instanceof HTMLElement_) {
  11488. if (++j2 > maxloopYtCompontents) break;
  11489. const cnt = insp(target);
  11490. if (typeof (target.is || cnt.is || null) === 'string') {
  11491. components.push(target);
  11492. }
  11493. if (typeof cnt.showContextMenu === 'function') break;
  11494. target = target.parentComponent || cnt.parentComponent || null;
  11495. }
  11496. if (!(target instanceof HTMLElement_)) return;
  11497. const targetCnt = insp(target);
  11498. if (typeof targetCnt.handleGetContextMenuResponse_ !== 'function' || typeof targetCnt.handleGetContextMenuError !== 'function') {
  11499. console.log('Error Found: handleGetContextMenuResponse_ OR handleGetContextMenuError is not defined on a component with showContextMenu')
  11500. return;
  11501. }
  11502.  
  11503. const endpoint = (targetCnt.data || 0).contextMenuEndpoint
  11504. if (!endpoint) return;
  11505. if (targetCnt.opened || !targetCnt.isAttached) return;
  11506.  
  11507. if (typeof targetCnt.__cacheResolvedEndpointData__ !== 'function') {
  11508. console.log(`preRequest for showContextMenu in ${targetCnt.is} is not yet supported.`)
  11509. }
  11510.  
  11511. const targetDollar = indr(target);
  11512.  
  11513. let doPreRequest = false;
  11514. if (components.length >= 2 && components[0].id === 'menu-button' && (targetDollar || 0)['menu-button'] === components[0]) {
  11515. doPreRequest = true;
  11516. } else if (components.length === 1 && components[0] === target) {
  11517. doPreRequest = true;
  11518. } else if (components.length >= 2 && components[0].id === 'author-photo' && (targetDollar || 0)['author-photo'] === components[0]) {
  11519. doPreRequest = true;
  11520. }
  11521. if (doPreRequest === false) {
  11522. console.log('doPreRequest = fasle on showContextMenu', components);
  11523. return;
  11524. }
  11525.  
  11526. if (typeof targetCnt.__getCachedEndpointData__ !== 'function' || targetCnt.__getCachedEndpointData__(endpoint)) return;
  11527.  
  11528. if ((typeof targetCnt.__showContextMenu_mutex_unlock_isEmpty__ === 'function') && !targetCnt.__showContextMenu_mutex_unlock_isEmpty__()) {
  11529. console.log('preRequest on showContextMenu aborted due to stacked network request');
  11530. return;
  11531. }
  11532.  
  11533.  
  11534. const onSuccess = (a) => {
  11535. /*
  11536.  
  11537. dQ() && (a = a.response);
  11538. a.liveChatItemContextMenuSupportedRenderers && a.liveChatItemContextMenuSupportedRenderers.menuRenderer && this.showContextMenu_(a.liveChatItemContextMenuSupportedRenderers.menuRenderer);
  11539. a.actions && Eu(this.hostElement, "yt-live-chat-actions", [a.actions])
  11540.  
  11541. */
  11542.  
  11543. a = a.response || a;
  11544.  
  11545. if (!a) {
  11546. console.log('unexpected error in prerequest for showContextMenu.onSuccess');
  11547. return;
  11548. }
  11549.  
  11550. let z = null;
  11551. a.liveChatItemContextMenuSupportedRenderers && a.liveChatItemContextMenuSupportedRenderers.menuRenderer && (z = a.liveChatItemContextMenuSupportedRenderers.menuRenderer);
  11552.  
  11553. if (z) {
  11554. a = z;
  11555. targetCnt.__cacheResolvedEndpointData__(endpoint, a, true);
  11556. }
  11557.  
  11558. };
  11559. const onFailure = (a) => {
  11560.  
  11561. /*
  11562.  
  11563. if (a instanceof Error || a instanceof Object || a instanceof String)
  11564. var b = a;
  11565. hq(new xm("Error encountered calling GetLiveChatItemContextMenu",b))
  11566.  
  11567. */
  11568.  
  11569. targetCnt.__cacheResolvedEndpointData__(endpoint, null);
  11570. // console.log('onFailure', a)
  11571.  
  11572. };
  11573.  
  11574. if (doPreRequest) {
  11575.  
  11576. let propertyCounter = 0;
  11577. const pm1 = __showContextMenu_assign_lock_with_external_unlock_(targetCnt);
  11578. const p1Timeout = 800;
  11579. const proxyKey = '__$$__proxy_to_this__$$__' + Date.now();
  11580.  
  11581. try {
  11582.  
  11583. const onSuccessHelperFn = function () {
  11584. pm1.p1unlock();
  11585. if (propertyCounter !== 5) {
  11586. console.log('Error in prerequest for showContextMenu.onSuccessHelperFn')
  11587. return;
  11588. }
  11589. if (this[proxyKey] !== targetCnt) {
  11590. console.log('Error in prerequest for showContextMenu.this');
  11591. return;
  11592. }
  11593. onSuccess(...arguments);
  11594. };
  11595. const onFailureHelperFn = function () {
  11596. pm1.p1unlock();
  11597. if (propertyCounter !== 5) {
  11598. console.log('Error in prerequest for showContextMenu.onFailureHelperFn')
  11599. return;
  11600. }
  11601. if (this[proxyKey] !== targetCnt) {
  11602. console.log('Error in prerequest for showContextMenu.this');
  11603. return;
  11604. }
  11605. onFailure(...arguments);
  11606.  
  11607. }
  11608. const fakeTargetCnt = new Proxy({
  11609. __showContextMenu_forceNativeRequest__: 1,
  11610. get handleGetContextMenuResponse_() {
  11611. propertyCounter += 2;
  11612. return onSuccessHelperFn;
  11613. },
  11614. get handleGetContextMenuError() {
  11615. propertyCounter += 3;
  11616. return onFailureHelperFn;
  11617. }
  11618. }, {
  11619. get(_, key, receiver) {
  11620. if (key in _) return _[key];
  11621. if (key === proxyKey) return targetCnt;
  11622.  
  11623. let giveNative = false;
  11624. if (key in targetCnt) {
  11625. if (key === 'data') giveNative = true;
  11626. else if (typeof targetCnt[key] === 'function') giveNative = true;
  11627. }
  11628. if (giveNative) return targetCnt[key];
  11629. }
  11630. });
  11631.  
  11632. const fakeEvent = (() => {
  11633. const { target, bubbles, cancelable, cancelBubble, srcElement, timeStamp, defaultPrevented, currentTarget, composed } = evt;
  11634. const nf = function () { }
  11635. const [stopPropagation, stopImmediatePropagation, preventDefault] = [nf, nf, nf];
  11636.  
  11637. return {
  11638. type: 'tap',
  11639. eventPhase: 0,
  11640. isTrusted: false,
  11641. __composed: true,
  11642. bubbles, cancelable, cancelBubble, timeStamp,
  11643. target, srcElement, defaultPrevented, currentTarget, composed,
  11644. stopPropagation, stopImmediatePropagation, preventDefault
  11645. };
  11646. })(evt);
  11647. targetCnt.showContextMenu.call(fakeTargetCnt, fakeEvent);
  11648.  
  11649.  
  11650. } catch (e) {
  11651. console.warn(e);
  11652. propertyCounter = 7;
  11653.  
  11654. }
  11655. if (propertyCounter !== 5) {
  11656. console.log('Error in prerequest for showContextMenu', propertyCounter);
  11657. return;
  11658. }
  11659.  
  11660. pm1.assignLock(targetCnt, p1Timeout);
  11661.  
  11662. }
  11663.  
  11664.  
  11665.  
  11666.  
  11667.  
  11668.  
  11669. }, true);
  11670.  
  11671.  
  11672. }
  11673.  
  11674.  
  11675.  
  11676. /*
  11677.  
  11678. const w=new Set(); for(const a of document.getElementsByTagName('*')) if(a.showContextMenu && a.showContextMenu_) w.add(a.is||''); console.log([...w.keys()])
  11679.  
  11680. */
  11681.  
  11682. whenDefinedMultiple([
  11683. "yt-live-chat-ticker-sponsor-item-renderer",
  11684. "yt-live-chat-ticker-paid-message-item-renderer",
  11685.  
  11686. "yt-live-chat-banner-header-renderer",
  11687. "yt-live-chat-text-message-renderer",
  11688. "ytd-sponsorships-live-chat-gift-purchase-announcement-renderer",
  11689. "ytd-sponsorships-live-chat-header-renderer",
  11690. "ytd-sponsorships-live-chat-gift-redemption-announcement-renderer",
  11691.  
  11692. "yt-live-chat-paid-sticker-renderer",
  11693. "yt-live-chat-viewer-engagement-message-renderer",
  11694. "yt-live-chat-paid-message-renderer"
  11695.  
  11696.  
  11697.  
  11698.  
  11699. ]).then(sTags => {
  11700.  
  11701. mightFirstCheckOnYtInit();
  11702. groupCollapsed("YouTube Super Fast Chat", " | fixShowContextMenu");
  11703. console1.log("[Begin]");
  11704.  
  11705.  
  11706. const __showContextMenu_mutex__ = new Mutex();
  11707. let __showContextMenu_mutex_unlock__ = null;
  11708. let lastShowMenuTarget = null;
  11709.  
  11710.  
  11711.  
  11712.  
  11713. const wm37 = new WeakMap();
  11714.  
  11715. const dProto = {
  11716.  
  11717.  
  11718. // CACHE_SHOW_CONTEXT_MENU_FOR_REOPEN
  11719.  
  11720. __cacheResolvedEndpointData__: (endpoint, a, doDeepCopy) => {
  11721. if (a) {
  11722. if (doDeepCopy) a = deepCopy(a);
  11723. wm37.set(endpoint, a);
  11724. } else {
  11725. wm37.remove(endpoint);
  11726. }
  11727. },
  11728. __getCachedEndpointData__: function (endpoint) {
  11729. endpoint = endpoint || (this.data || 0).contextMenuEndpoint || 0;
  11730. if (endpoint) return wm37.get(endpoint);
  11731. return null;
  11732. },
  11733. /** @type {(resolvedEndpoint: any) => void 0} */
  11734. __showCachedContextMenu__: function (resolvedEndpoint) { // non-null
  11735.  
  11736. resolvedEndpoint = deepCopy(resolvedEndpoint);
  11737. // let b = deepCopy(resolvedEndpoint, ['trackingParams', 'clickTrackingParams'])
  11738. Promise.resolve(resolvedEndpoint).then((resolvedEndpoint) => {
  11739. this.__showContextMenu_skip_cacheResolvedEndpointData__ = 1;
  11740. this.showContextMenu_(resolvedEndpoint);
  11741. this.__showContextMenu_skip_cacheResolvedEndpointData__ = 0;
  11742. resolvedEndpoint = null;
  11743. });
  11744.  
  11745.  
  11746. },
  11747.  
  11748.  
  11749.  
  11750. showContextMenuForCacheReopen: function (a) {
  11751. if (this && this.__showContextMenu_forceNativeRequest__) return this.showContextMenu37(a);
  11752. if (!this || !this.isAttached) return; // in case; avoid Error: No provider for: InjectionToken(NETWORK_TOKEN) in _.showContextMenu
  11753. if (!this.__showContextMenu_forceNativeRequest__) {
  11754. const endpoint = (this.data || 0).contextMenuEndpoint || 0;
  11755. if (endpoint) {
  11756. const resolvedEndpoint = this.__getCachedEndpointData__(endpoint);
  11757. if (resolvedEndpoint) {
  11758. this.__showCachedContextMenu__(resolvedEndpoint);
  11759. a && a.stopPropagation()
  11760. return;
  11761. }
  11762. }
  11763. }
  11764. return this.showContextMenu37(a);
  11765. },
  11766.  
  11767. showContextMenuForCacheReopen_: function (a) {
  11768. if (this && this.__showContextMenu_forceNativeRequest__) return this.showContextMenu37_(a);
  11769. if (!this || !this.isAttached) return; // in case; avoid Error: No provider for: InjectionToken(NETWORK_TOKEN) in _.showContextMenu
  11770. if (!this.__showContextMenu_skip_cacheResolvedEndpointData__) {
  11771. const endpoint = (this.data || 0).contextMenuEndpoint || 0;
  11772. if (endpoint) {
  11773. const f = this.__cacheResolvedEndpointData__;
  11774. if (typeof f === 'function') f(endpoint, a, true);
  11775. }
  11776. }
  11777. return this.showContextMenu37_(a);
  11778. },
  11779.  
  11780. // ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU
  11781.  
  11782. showContextMenuWithDisableScroll: function (a) {
  11783.  
  11784. const endpoint = (this.data || 0).contextMenuEndpoint || 0;
  11785. if (endpoint && typeof this.is === 'string' && this.menuVisible === false && this.menuOpen === false) {
  11786.  
  11787. const parentComponent = this.parentComponent;
  11788. if (parentComponent && parentComponent.is === 'yt-live-chat-item-list-renderer' && parentComponent.contextMenuOpen === false && parentComponent.allowScroll === true) {
  11789. parentComponent.contextMenuOpen = true; // computeAllowScroll_(contextMenuOpen, moderationModeEnabled): allowScroll = !(contextMenuOpen || moderationModeEnabled)
  11790. }
  11791. }
  11792.  
  11793. return this.showContextMenu48.apply(this, arguments);
  11794.  
  11795. },
  11796.  
  11797. // ENABLE_MUTEX_FOR_SHOW_CONTEXT_MENU
  11798.  
  11799. __showContextMenu_mutex_unlock_isEmpty__: () => {
  11800. return __showContextMenu_mutex_unlock__ === null;
  11801. },
  11802.  
  11803. __showContextMenu_assign_lock__: function (p) {
  11804.  
  11805. const mutex = __showContextMenu_mutex__;
  11806.  
  11807. mutex.lockWith(unlock => {
  11808. p.then(unlock);
  11809. p = null;
  11810. unlock = null;
  11811. });
  11812.  
  11813. },
  11814.  
  11815. showContextMenuWithMutex: function (a) {
  11816. if (this.__showContextMenu_forceNativeRequest__) return this.showContextMenu47(a);
  11817. if (!this || !this.isAttached) return; // in case; avoid Error: No provider for: InjectionToken(NETWORK_TOKEN) in _.showContextMenu
  11818. lastShowMenuTarget = this;
  11819. const wNode = mWeakRef(this);
  11820.  
  11821.  
  11822. const mutex = __showContextMenu_mutex__;
  11823.  
  11824. mutex.lockWith(unlock => {
  11825. const cnt = kRef(wNode);
  11826. if (lastShowMenuTarget !== cnt || !cnt) {
  11827. unlock();
  11828. return;
  11829. }
  11830.  
  11831. setTimeout(unlock, 800); // in case network failure
  11832. __showContextMenu_mutex_unlock__ = unlock;
  11833. try {
  11834. cnt.showContextMenu47(a);
  11835. } catch (e) {
  11836. console.warn(e);
  11837. unlock(); // in case function script error
  11838. }
  11839.  
  11840. });
  11841.  
  11842.  
  11843. },
  11844.  
  11845. showContextMenuWithMutex_: function (a) {
  11846.  
  11847. if (__showContextMenu_mutex_unlock__ && this === lastShowMenuTarget) {
  11848. __showContextMenu_mutex_unlock__();
  11849. __showContextMenu_mutex_unlock__ = null;
  11850. }
  11851. return this.showContextMenu47_(a);
  11852.  
  11853. }
  11854.  
  11855. }
  11856.  
  11857. for (const tag of sTags) { // ##tag##
  11858.  
  11859. (() => {
  11860.  
  11861. const dummy = document.createElement(tag);
  11862.  
  11863. const cProto = getProto(dummy);
  11864. if (!cProto || !cProto.attached) {
  11865. console1.warn(`proto.attached for ${tag} is unavailable.`);
  11866. return;
  11867. }
  11868.  
  11869.  
  11870. 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) {
  11871. cProto.showContextMenu37_ = cProto.showContextMenu_;
  11872. cProto.showContextMenu37 = cProto.showContextMenu;
  11873. cProto.__showContextMenu_forceNativeRequest__ = 0;
  11874. cProto.__cacheResolvedEndpointData__ = dProto.__cacheResolvedEndpointData__
  11875. cProto.__getCachedEndpointData__ = dProto.__getCachedEndpointData__
  11876. cProto.__showCachedContextMenu__ = dProto.__showCachedContextMenu__
  11877. cProto.showContextMenu = dProto.showContextMenuForCacheReopen;
  11878. cProto.showContextMenu_ = dProto.showContextMenuForCacheReopen_;
  11879. console1.log("CACHE_SHOW_CONTEXT_MENU_FOR_REOPEN - OK", tag);
  11880. } else {
  11881. console1.log("CACHE_SHOW_CONTEXT_MENU_FOR_REOPEN - NG", tag);
  11882. }
  11883.  
  11884. 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) {
  11885. cProto.showContextMenu48 = cProto.showContextMenu;
  11886. cProto.showContextMenu = dProto.showContextMenuWithDisableScroll;
  11887. console1.log("ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU - OK", tag);
  11888. } else if (!ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU) {
  11889. DEBUG_skipLog001 || console1.log("ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU - N/A", tag);
  11890. } else {
  11891. console1.log("ADVANCED_NOT_ALLOW_SCROLL_FOR_SHOW_CONTEXT_MENU - NG", tag);
  11892. }
  11893.  
  11894.  
  11895. 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) {
  11896. cProto.showContextMenu47_ = cProto.showContextMenu_;
  11897. cProto.showContextMenu47 = cProto.showContextMenu;
  11898. cProto.__showContextMenu_mutex_unlock_isEmpty__ = dProto.__showContextMenu_mutex_unlock_isEmpty__;
  11899. cProto.__showContextMenu_assign_lock__ = dProto.__showContextMenu_assign_lock__;
  11900. cProto.showContextMenu = dProto.showContextMenuWithMutex;
  11901. cProto.showContextMenu_ = dProto.showContextMenuWithMutex_;
  11902. console1.log("ENABLE_MUTEX_FOR_SHOW_CONTEXT_MENU - OK", tag);
  11903. } else {
  11904. console1.log("ENABLE_MUTEX_FOR_SHOW_CONTEXT_MENU - NG", tag);
  11905. }
  11906.  
  11907. })();
  11908.  
  11909. }
  11910.  
  11911. console1.log("[End]");
  11912.  
  11913. groupEnd();
  11914.  
  11915. }).catch(console.warn);
  11916.  
  11917.  
  11918.  
  11919. if (FIX_UNKNOWN_BUG_FOR_OVERLAY) {
  11920. // this is to fix " TypeError: this.backdropElement.prepare is not a function "
  11921.  
  11922. customElements.whenDefined('tp-yt-paper-dialog').then(() => {
  11923.  
  11924.  
  11925. mightFirstCheckOnYtInit();
  11926. groupCollapsed("YouTube Super Fast Chat", " | tp-yt-paper-dialog hacks");
  11927. console1.log("[Begin]");
  11928. (() => {
  11929.  
  11930. const tag = "tp-yt-paper-dialog";
  11931. const dummy = document.createElement(tag);
  11932.  
  11933. const cProto = getProto(dummy);
  11934. if (!cProto || !cProto.attached) {
  11935. console1.warn(`proto.attached for ${tag} is unavailable.`);
  11936. return;
  11937. }
  11938.  
  11939. if (typeof cProto.__openedChanged === 'function' && !cProto.__openedChanged49 && cProto.__openedChanged.length === 0) {
  11940.  
  11941.  
  11942. cProto.__openedChanged49 = cProto.__openedChanged;
  11943.  
  11944. cProto.__openedChanged = function () {
  11945. const manager = (this || 0)._manager || 0;
  11946. if (manager && !manager.trackBackdrop49 && manager.trackBackdrop) {
  11947. manager.trackBackdrop49 = manager.trackBackdrop;
  11948. if (manager.trackBackdrop.length === 0) {
  11949. manager.trackBackdrop = function () {
  11950. try {
  11951. return this.trackBackdrop49();
  11952. } catch (e) {
  11953. let showMessage = true;
  11954. if (e instanceof TypeError && e.message === 'this.backdropElement.prepare is not a function') {
  11955. // this is well known issue.
  11956. showMessage = false;
  11957. }
  11958. showMessage && console.log('manager.trackBackdrop', e);
  11959. }
  11960. }
  11961. }
  11962. }
  11963. return this.__openedChanged49();
  11964. };
  11965.  
  11966.  
  11967. }
  11968.  
  11969.  
  11970. })();
  11971.  
  11972.  
  11973. console1.log("[End]");
  11974.  
  11975. groupEnd();
  11976.  
  11977.  
  11978. }).catch(console.warn);
  11979.  
  11980. }
  11981.  
  11982.  
  11983. customElements.whenDefined('tp-yt-iron-dropdown').then(() => {
  11984.  
  11985. mightFirstCheckOnYtInit();
  11986. groupCollapsed("YouTube Super Fast Chat", " | tp-yt-iron-dropdown hacks");
  11987. console1.log("[Begin]");
  11988. (() => {
  11989.  
  11990. const tag = "tp-yt-iron-dropdown";
  11991. const dummy = document.createElement(tag);
  11992.  
  11993. const cProto = getProto(dummy);
  11994. if (!cProto || !cProto.attached) {
  11995. console1.warn(`proto.attached for ${tag} is unavailable.`);
  11996. return;
  11997. }
  11998.  
  11999. if (USE_VANILLA_DEREF && typeof cProto.__deraf === 'function' && cProto.__deraf.length === 2 && !cProto.__deraf34 && fnIntegrity(cProto.__deraf) === '2.42.24') {
  12000. cProto.__deraf_hn__ = function (sId, fn) {
  12001. const rhKey = `_rafHandler_${sId}`;
  12002. const m = this[rhKey] || (this[rhKey] = new WeakMap());
  12003. if (m.has(fn)) return m.get(fn);
  12004. const resFn = () => {
  12005. this.__rafs[sId] = null;
  12006. fn.call(this)
  12007. };
  12008. m.set(fn, resFn);
  12009. m.set(resFn, resFn);
  12010. return resFn;
  12011. };
  12012. cProto.__deraf34 = cProto.__deraf;
  12013. cProto.__deraf = function (a, b) { // sId, fn
  12014. let c = this.__rafs;
  12015. null !== c[a] && cancelAnimationFrame(c[a]);
  12016. c[a] = requestAnimationFrame(this.__deraf_hn__(a, b));
  12017. };
  12018. console1.log("USE_VANILLA_DEREF - OK");
  12019. } else {
  12020. console1.log("USE_VANILLA_DEREF - NG");
  12021. }
  12022.  
  12023. if (FIX_DROPDOWN_DERAF && typeof cProto.__deraf === 'function' && cProto.__deraf.length === 2 && !cProto.__deraf66) {
  12024. cProto.__deraf66 = cProto.__deraf;
  12025. cProto.__deraf = function (sId, fn) {
  12026. if (this.__byPassRAF__) {
  12027. Promise.resolve(this).then((cnt) => {
  12028. fn.call(cnt);
  12029. cnt = null;
  12030. });
  12031. }
  12032. let r = this.__deraf66.apply(this, arguments);
  12033. return r;
  12034. }
  12035. console1.log("FIX_DROPDOWN_DERAF - OK");
  12036. } else {
  12037. console1.log("FIX_DROPDOWN_DERAF - NG");
  12038. }
  12039.  
  12040.  
  12041. if (BOOST_MENU_OPENCHANGED_RENDERING && typeof cProto.__openedChanged === 'function' && !cProto.__mtChanged__ && fnIntegrity(cProto.__openedChanged) === '0.46.20') {
  12042.  
  12043. let lastClose = null;
  12044. let lastOpen = null;
  12045. let cid = 0;
  12046.  
  12047. cProto.__mtChanged__ = function (b) {
  12048.  
  12049. Promise.resolve(this).then((cnt) => {
  12050. cnt._applyFocus();
  12051. return cnt;
  12052. }).then((cnt) => {
  12053. b ? cnt._renderOpened() : cnt._renderClosed();
  12054. cnt = null;
  12055. }).catch(console.warn);
  12056.  
  12057. };
  12058.  
  12059. const __moChanged__ = () => {
  12060. if (!cid) return;
  12061. // console.log(553, !!lastOpen, !!lastClose);
  12062. cid = 0;
  12063. if (lastOpen && !lastClose && lastOpen.isAttached) {
  12064. lastOpen.__mtChanged__(1)
  12065. } else if (lastClose && !lastOpen && lastClose.isAttached) {
  12066. lastClose.__mtChanged__(0);
  12067. }
  12068. lastOpen = null;
  12069. lastClose = null;
  12070. };
  12071.  
  12072.  
  12073. if (typeof cProto._openedChanged === 'function' && !cProto._openedChanged66) {
  12074. cProto._openedChanged66 = cProto._openedChanged;
  12075. cProto._openedChanged = function () {
  12076. // this.__byPassRAF__ = !lastOpen ? true : false; // or just true?
  12077. this.__byPassRAF__ = true;
  12078. let r = this._openedChanged66.apply(this, arguments);
  12079. this.__byPassRAF__ = false;
  12080. return r;
  12081. }
  12082. }
  12083.  
  12084. const pSetGet = (key, pdThis, pdBase) => {
  12085. // note: this is not really a standard way for the getOwnPropertyDescriptors; but it is sufficient to make the job done
  12086. return {
  12087. get: (pdThis[key] || 0).get || (pdBase[key] || 0).get,
  12088. set: (pdThis[key] || 0).set || (pdBase[key] || 0).set
  12089. };
  12090. };
  12091.  
  12092. cProto.__modifiedMenuPropsFn__ = function () {
  12093. const pdThis = Object.getOwnPropertyDescriptors(this.constructor.prototype)
  12094. const pdBase = Object.getOwnPropertyDescriptors(this)
  12095.  
  12096. const pdAutoFitOnAttach = pSetGet('autoFitOnAttach', pdThis, pdBase);
  12097. const pdExpandSizingTargetForScrollbars = pSetGet('expandSizingTargetForScrollbars', pdThis, pdBase);
  12098. const pdAllowOutsideScroll = pSetGet('allowOutsideScroll', pdThis, pdBase);
  12099.  
  12100. if (pdAutoFitOnAttach.get || pdAutoFitOnAttach.set) {
  12101. console.warn('there is setter/getter for autoFitOnAttach');
  12102. return;
  12103. }
  12104. if (pdExpandSizingTargetForScrollbars.get || pdExpandSizingTargetForScrollbars.set) {
  12105. console.warn('there is setter/getter for expandSizingTargetForScrollbars');
  12106. return;
  12107. }
  12108. if (!pdAllowOutsideScroll.get || !pdAllowOutsideScroll.set) {
  12109. console.warn('there is NO setter-getter for allowOutsideScroll');
  12110. return;
  12111. }
  12112.  
  12113. let { autoFitOnAttach, expandSizingTargetForScrollbars, allowOutsideScroll } = this;
  12114.  
  12115. this.__AllowOutsideScrollPD__ = pdAllowOutsideScroll;
  12116.  
  12117. const fitEnable = CHAT_MENU_REFIT_ALONG_SCROLLING === 2;
  12118.  
  12119. Object.defineProperties(this, {
  12120. autoFitOnAttach: {
  12121. get() {
  12122. if (fitEnable && this._modifiedMenuPropOn062__) return true;
  12123. return autoFitOnAttach;
  12124. },
  12125. set(nv) {
  12126. autoFitOnAttach = nv;
  12127. return true;
  12128. },
  12129. enumerable: true,
  12130. configurable: true
  12131. }, expandSizingTargetForScrollbars: {
  12132. get() {
  12133. if (fitEnable && this._modifiedMenuPropOn062__) return true;
  12134. return expandSizingTargetForScrollbars;
  12135. },
  12136. set(nv) {
  12137. expandSizingTargetForScrollbars = nv;
  12138. return true;
  12139. },
  12140. enumerable: true,
  12141. configurable: true
  12142. }, allowOutsideScroll: {
  12143. get() {
  12144. if (this._modifiedMenuPropOn062__) return true;
  12145. return allowOutsideScroll;
  12146. },
  12147. set(nv) {
  12148. allowOutsideScroll = nv;
  12149. this.__AllowOutsideScrollPD__.set.call(this, nv);
  12150. return true;
  12151. },
  12152. enumerable: true,
  12153. configurable: true
  12154. }
  12155. })
  12156. };
  12157.  
  12158. /*
  12159. // ***** position() to be changed. *****
  12160. tp-yt-iron-dropdown[class], tp-yt-iron-dropdown[class] #contentWrapper, tp-yt-iron-dropdown[class] ytd-menu-popup-renderer[class] {
  12161.  
  12162. overflow: visible !important;
  12163. min-width: max-content !important;
  12164. max-width: max-content !important;
  12165. max-height: max-content !important;
  12166. min-height: max-content !important;
  12167. white-space: nowrap;
  12168. }
  12169.  
  12170. */
  12171. if (FIX_MENU_POSITION_N_SIZING_ON_SHOWN && typeof cProto.position === 'function' && !cProto.position34 && typeof cProto.refit === 'function') {
  12172.  
  12173. let m34 = 0;
  12174. cProto.__refitByPosition__ = function () {
  12175. m34++;
  12176. if (m34 <= 0) m34 = 0;
  12177. if (m34 !== 1) return;
  12178. const hostElement = this.hostElement || this;
  12179. if (document.visibilityState === 'visible') {
  12180. const sizingTarget = this.sizingTarget;
  12181. if (!sizingTarget) {
  12182. m34 = 0;
  12183. return;
  12184. }
  12185. hostElement.setAttribute('rNgzQ', '');
  12186. sizingTarget.setAttribute('rNgzQ', '');
  12187.  
  12188. const gn = () => {
  12189. hostElement.removeAttribute('rNgzQ');
  12190. sizingTarget.removeAttribute('rNgzQ');
  12191. }
  12192.  
  12193. const an = async () => {
  12194. while (m34 >= 1) {
  12195. await renderReadyPn(sizingTarget);
  12196. if (this.opened && this.isAttached && sizingTarget.isConnected === true && sizingTarget === this.sizingTarget) {
  12197. if (sizingTarget.matches('ytd-menu-popup-renderer[slot="dropdown-content"].yt-live-chat-app')) this.refit();
  12198. }
  12199. m34--;
  12200. }
  12201. m34 = 0;
  12202. Promise.resolve().then(gn);
  12203. }
  12204. setTimeout(an, 4); // wait those resizing function calls
  12205.  
  12206.  
  12207. } else {
  12208. m34 = 0;
  12209. }
  12210. }
  12211. cProto.position34 = cProto.position
  12212. cProto.position = function () {
  12213. if (this._positionInitialize_) {
  12214. this._positionInitialize_ = 0;
  12215. this.__refitByPosition__();
  12216. }
  12217. let r = cProto.position34.apply(this, arguments);
  12218. return r;
  12219. }
  12220. console1.log("FIX_MENU_POSITION_ON_SHOWN - OK");
  12221.  
  12222. } else {
  12223.  
  12224. console1.log("FIX_MENU_POSITION_ON_SHOWN - NG");
  12225.  
  12226. }
  12227.  
  12228.  
  12229.  
  12230. cProto.__openedChanged = function () {
  12231. // console.log(123445)
  12232. this._positionInitialize_ = 1;
  12233. // this.removeAttribute('horizontal-align')
  12234. // this.removeAttribute('vertical-align')
  12235. if (typeof this.__menuTypeCheck__ !== 'boolean') {
  12236. this.__menuTypeCheck__ = true;
  12237. if (CHAT_MENU_SCROLL_UNLOCKING) {
  12238. this._modifiedMenuPropOn062__ = false;
  12239. // console.log(513, this.positionTarget && this.positionTarget.classList.contains('yt-live-chat-text-message-renderer'))
  12240. // this.autoFitOnAttach = true;
  12241. // this.expandSizingTargetForScrollbars = true;
  12242. // this.allowOutsideScroll = true;
  12243. // console.log(519,Object.getOwnPropertyDescriptors(this.constructor.prototype))
  12244. this.__modifiedMenuPropsFn__();
  12245. // this.constrain= function(){}
  12246. // this.position= function(){}
  12247.  
  12248. // this.autoFitOnAttach = true;
  12249. // this.expandSizingTargetForScrollbars = true;
  12250. // this.allowOutsideScroll = true;
  12251. }
  12252. }
  12253. if (CHAT_MENU_SCROLL_UNLOCKING && this.opened) {
  12254. let newValue = null;
  12255. const positionTarget = this.positionTarget;
  12256. if (positionTarget && positionTarget.classList.contains('yt-live-chat-text-message-renderer')) {
  12257. if (this._modifiedMenuPropOn062__ === false) {
  12258. newValue = true;
  12259. }
  12260. } else if (this._modifiedMenuPropOn062__ === true) {
  12261. newValue = false;
  12262. }
  12263. if (newValue !== null) {
  12264. const beforeAllowOutsideScroll = this.allowOutsideScroll;
  12265. this._modifiedMenuPropOn062__ = newValue;
  12266. const afterAllowOutsideScroll = this.allowOutsideScroll;
  12267. if (beforeAllowOutsideScroll !== afterAllowOutsideScroll) this.__AllowOutsideScrollPD__.set.call(this, afterAllowOutsideScroll);
  12268. }
  12269. }
  12270.  
  12271. if (this.opened) {
  12272.  
  12273. Promise.resolve().then(() => {
  12274.  
  12275. this._prepareRenderOpened();
  12276. }).then(() => {
  12277. // console.log('[yt-chat-dialog]', this._manager)
  12278. try{
  12279. this._manager.addOverlay(this);
  12280. }catch(e){
  12281. console.log('this._manager.addOverlay(this) fails.')
  12282. }
  12283. if (this._manager._overlays.length === 1) {
  12284. lastOpen = this;
  12285. lastClose = null;
  12286. } else {
  12287. return 1;
  12288. }
  12289. // if (cid) {
  12290. // clearTimeout(cid);
  12291. // cid = -1;
  12292. // this.__moChanged__();
  12293. // cid = 0;
  12294. // } else {
  12295. // cid = -1;
  12296. // this.__moChanged__();
  12297. // cid = 0;
  12298. // }
  12299. // cid = cid > 0 ? clearTimeout(cid) : 0;
  12300. // console.log(580, this.positionTarget && this.positionTarget.classList.contains('yt-live-chat-text-message-renderer'))
  12301. // cid = cid || setTimeout(__moChanged__, delay1);
  12302. cid = cid || requestAnimationFrame(__moChanged__);
  12303. }).then((r) => {
  12304.  
  12305. if (r) this.__mtChanged__(1);
  12306. }).catch(console.warn);
  12307.  
  12308. } else {
  12309. Promise.resolve().then(() => {
  12310. // console.log('[yt-chat-dialog]', this._manager)
  12311. try{
  12312. this._manager.removeOverlay(this);
  12313. }catch(e){
  12314. console.log('this._manager.removeOverlay(this) fails.')
  12315. }
  12316. if (this._manager._overlays.length === 0) {
  12317. lastClose = this;
  12318. lastOpen = null;
  12319. } else {
  12320. return 1;
  12321. }
  12322. // cid = cid > 0 ? clearTimeout(cid) : 0;
  12323. // console.log(581, this.positionTarget && this.positionTarget.classList.contains('yt-live-chat-text-message-renderer'))
  12324. // cid = cid || setTimeout(__moChanged__, delay1);
  12325. cid = cid || requestAnimationFrame(__moChanged__);
  12326. }).then((r) => {
  12327. if (r) this.__mtChanged__(0);
  12328. }).catch(console.warn);
  12329.  
  12330. }
  12331.  
  12332. }
  12333. console1.log("BOOST_MENU_OPENCHANGED_RENDERING - OK");
  12334.  
  12335. } else {
  12336.  
  12337. assertor(() => fnIntegrity(cProto.__openedChanged, '0.46.20'));
  12338. console1.log("FIX_MENU_REOPEN_RENDER_PERFORMANC_1 - NG");
  12339.  
  12340. }
  12341.  
  12342.  
  12343. if (FIX_CLICKING_MESSAGE_MENU_DISPLAY_ON_MOUSE_CLICK && typeof cProto.__openedChanged === 'function' && !cProto.__openedChanged82) {
  12344.  
  12345. cProto.__openedChanged82 = cProto.__openedChanged;
  12346.  
  12347.  
  12348. cProto.__openedChanged = function () {
  12349. const positionTarget = this.positionTarget;
  12350. currentMenuPivotWR = positionTarget ? mWeakRef(positionTarget) : null;
  12351. return this.__openedChanged82.apply(this, arguments);
  12352. }
  12353. }
  12354.  
  12355.  
  12356. })();
  12357.  
  12358. console1.log("[End]");
  12359.  
  12360. groupEnd();
  12361.  
  12362. }).catch(console.warn);
  12363.  
  12364.  
  12365.  
  12366. FIX_ToggleRenderPolymerControllerExtractionBug && customElements.whenDefined('yt-live-chat-toggle-renderer').then(() => {
  12367.  
  12368. mightFirstCheckOnYtInit();
  12369. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-toggle-renderer hacks");
  12370. console1.log("[Begin]");
  12371. (() => {
  12372.  
  12373. const tag = "yt-live-chat-toggle-renderer";
  12374. const dummy = document.createElement(tag);
  12375.  
  12376. const cProto = getProto(dummy);
  12377. if (!cProto || !cProto.attached) {
  12378. console1.warn(`proto.attached for ${tag} is unavailable.`);
  12379. return;
  12380. }
  12381.  
  12382. })();
  12383.  
  12384. console1.log("[End]");
  12385. groupEnd();
  12386.  
  12387. });
  12388.  
  12389. FIX_MOUSEOVER_FN && (() => {
  12390.  
  12391. // this is to show tooltip for emoji
  12392.  
  12393.  
  12394. let lastShow = 0;
  12395.  
  12396. const wm = new WeakSet();
  12397. const mo1 = new MutationObserver((mutations) => {
  12398.  
  12399. for (const p of document.querySelectorAll('[shared-tooltip-text]:not([__a6cwm__])')) {
  12400. p.setAttribute('__a6cwm__', '');
  12401. }
  12402.  
  12403. });
  12404. mo1.observe(document, { subtree: true, attributes: true, attributeFilter: ['shared-tooltip-text'], childList: true });
  12405.  
  12406. const mo2 = new MutationObserver((mutations) => {
  12407.  
  12408. for (const mutation of mutations) {
  12409. const p = mutation.target;
  12410. if (mutation.attributeName) {
  12411. if (p.getAttribute('shared-tooltip-text')) { // allow hack
  12412. wm.add(p);
  12413. for (const e of p.getElementsByTagName('*')) {
  12414. wm.add(e);
  12415. }
  12416. } else {
  12417. if (wm.has(p)) {
  12418. wm.remove(p);
  12419. for (const e of p.getElementsByTagName('*')) {
  12420. wm.remove(e);
  12421. }
  12422. }
  12423. }
  12424. }
  12425. }
  12426. });
  12427. mo2.observe(document, { subtree: true, attributes: true, attributeFilter: ['__a6cwm__', 'shared-tooltip-text'], childList: false });
  12428.  
  12429.  
  12430. let done = 0;
  12431. // lcrFn2 will run twice to ensure the method is successfully injected.
  12432. const lcrFn2 = (lcrDummy) => {
  12433. // make minimal function overhead by pre-defining all possible outside.
  12434.  
  12435. const tag = "yt-live-chat-renderer"
  12436. const dummy = lcrDummy;
  12437.  
  12438. const cProto = getProto(dummy);
  12439. if (!cProto || !cProto.attached) {
  12440. console.warn(`proto.attached for ${tag} is unavailable.`);
  12441. return;
  12442. }
  12443.  
  12444. // mightFirstCheckOnYtInit();
  12445. // groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-renderer hacks");
  12446. // console.log("[Begin]");
  12447.  
  12448.  
  12449.  
  12450. if (done !== 1 && typeof cProto.onMouseOver_ === 'function' && !cProto.onMouseOver37_ && typeof cProto.createTooltipIfRequired_ === 'function' && cProto.createTooltipIfRequired_.length === 0) {
  12451.  
  12452. done = 1;
  12453. const onMouseOver37_ = cProto.onMouseOver37_ = cProto.onMouseOver_;
  12454.  
  12455. const checkMatch = (() => {
  12456.  
  12457.  
  12458. let accessList = [];
  12459. let withError = false;
  12460. try {
  12461.  
  12462. onMouseOver37_.call(lcrDummy, {
  12463. type: 'mouseover',
  12464. target: new Proxy({
  12465. nodeName: 'DIV',
  12466. tagName: 'DIV',
  12467. getAttribute: function () { },
  12468. parentNode: null
  12469. }, {
  12470. get(target, p) {
  12471. accessList.push(`getter:${p}`);
  12472. if (!(p in target)) throw Error(`getter ${p} is not found`);
  12473. },
  12474. set(target, p, v) {
  12475. accessList.push(`setter:${p}`);
  12476. throw Error(`setter ${p} is not found`);
  12477. }
  12478. })
  12479. });
  12480. } catch (e) {
  12481. withError = true;
  12482. // console.warn(e);
  12483. }
  12484.  
  12485. if (withError) return false;
  12486.  
  12487. if (accessList.join(',') !== 'getter:getAttribute,getter:parentNode') return false;
  12488.  
  12489. accessList.length = 0;
  12490.  
  12491. let parent;
  12492. try {
  12493.  
  12494. parent = new Proxy({
  12495. nodeName: 'DIV',
  12496. tagName: 'DIV',
  12497. getAttribute: function (e) {
  12498.  
  12499. accessList.push(`getter:getAttribute(${e})`);
  12500. return e === 'shared-tooltip-text' ? ':cherry_blossom:' : null;
  12501.  
  12502. },
  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. return target[p]
  12509. },
  12510. set(target, p, v) {
  12511. accessList.push(`setter:${p}`);
  12512. throw Error(`setter ${p} is not found`);
  12513. }
  12514. });
  12515.  
  12516. onMouseOver37_.call(lcrDummy, {
  12517. type: 'mouseover',
  12518. target: new Proxy({
  12519. nodeName: 'IMG',
  12520. tagName: 'IMG',
  12521. id: 'img',
  12522. getAttribute: function (e) {
  12523.  
  12524. accessList.push(`getter:getAttribute(${e})`);
  12525. return e === 'shared-tooltip-text' ? ':cherry_blossom:' : null;
  12526.  
  12527. },
  12528. get parentNode() {
  12529. return parent
  12530. },
  12531. get parentElement() {
  12532. return parent
  12533. }
  12534. }, {
  12535. get(target, p) {
  12536. accessList.push(`getter:${p}`);
  12537. if (!(p in target)) throw Error(`getter ${p} is not found`);
  12538. return target[p]
  12539. },
  12540. set(target, p, v) {
  12541. accessList.push(`setter:${p}`);
  12542. throw Error(`setter ${p} is not found`);
  12543. }
  12544. })
  12545. });
  12546. } catch (e) {
  12547. withError = true;
  12548. // console.warn(e);
  12549. }
  12550. parent = null;
  12551.  
  12552. 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:$$') {
  12553. return true;
  12554. }
  12555.  
  12556.  
  12557.  
  12558. })();
  12559. if (checkMatch) {
  12560.  
  12561. cProto.onMouseOver_ = function (evt) {
  12562. const p = (evt || 0).target || 0;
  12563. if (p.nodeType === 1 && wm.has(p)) {
  12564. const ct = Date.now();
  12565. if (lastShow + 18 > ct) return;
  12566. const cnt = insp(this);
  12567. lastShow = ct;
  12568. try {
  12569. cnt.onMouseOver37_.call(this, evt);
  12570. } catch (e) {
  12571. console.warn(e);
  12572. }
  12573. }
  12574. };
  12575.  
  12576. const lcrs = [...new Set([lcrDummy, ...document.querySelectorAll('yt-live-chat-renderer')])];
  12577. for (const lcr of lcrs) {
  12578. const cnt = insp(lcr);
  12579. const hostElement = cnt.hostElement;
  12580. if (hostElement && cnt.isAttached === true && cnt.onMouseOver37_ === cProto.onMouseOver37_ && typeof cProto.onMouseOver_ === 'function' && cProto.onMouseOver_ !== cProto.onMouseOver37_ && cnt.onMouseOver_ === cProto.onMouseOver_) {
  12581. hostElement.removeEventListener("mouseover", cProto.onMouseOver37_, !0)
  12582. hostElement.addEventListener("mouseover", cProto.onMouseOver_, !0)
  12583. }
  12584. }
  12585.  
  12586. console.log('[yt-chat-lcr] FIX_MOUSEOVER_FN - OK')
  12587.  
  12588. } else {
  12589.  
  12590. console.log('[yt-chat-lcr] FIX_MOUSEOVER_FN - NG')
  12591.  
  12592. }
  12593.  
  12594. } else if (done !== 1) {
  12595. done = 2;
  12596. console.log('[yt-chat-lcr] FIX_MOUSEOVER_FN - NG')
  12597. }
  12598.  
  12599. // console.log("[End]");
  12600. // groupEnd();
  12601.  
  12602.  
  12603. };
  12604. !__LCRInjection__ && LCRImmedidates.push(lcrFn2);
  12605. // getLCRDummy() must be called for injection
  12606. getLCRDummy().then(lcrFn2);
  12607.  
  12608. })();
  12609.  
  12610.  
  12611. /*
  12612.  
  12613.  
  12614.  
  12615.  
  12616.  
  12617. var FU = function() {
  12618. var a = this;
  12619. this.nextHandle_ = 1;
  12620. this.clients_ = {};
  12621. this.JSC$10323_callbacks_ = {};
  12622. this.unsubscribeAsyncHandles_ = {};
  12623. this.subscribe = vl(function(b, c, d) {
  12624. var e = Geb(b);
  12625. if (e in a.clients_)
  12626. e in a.unsubscribeAsyncHandles_ && Jq.cancel(a.unsubscribeAsyncHandles_[e]);
  12627. else {
  12628. a: {
  12629. var h = Geb(b), l;
  12630. for (l in a.unsubscribeAsyncHandles_) {
  12631. var m = a.clients_[l];
  12632. if (m instanceof KO) {
  12633. delete a.clients_[l];
  12634. delete a.JSC$10323_callbacks_[l];
  12635. Jq.cancel(a.unsubscribeAsyncHandles_[l]);
  12636. delete a.unsubscribeAsyncHandles_[l];
  12637. i6a(m);
  12638. m.objectId_ = new FQa(h);
  12639. m.register();
  12640. d = m;
  12641. break a
  12642. }
  12643. }
  12644. d.objectSource = b.invalidationId.objectSource;
  12645. d.objectId = h;
  12646. if (b = b.webAuthConfigurationData)
  12647. b.multiUserSessionIndex && (d.sessionIndex = parseInt(b.multiUserSessionIndex, 10)),
  12648. b.pageId && (d.pageId = b.pageId);
  12649. d = new KO(d,a.handleInvalidationData_.bind(a));
  12650. d.register()
  12651. }
  12652. a.clients_[e] = d;
  12653. a.JSC$10323_callbacks_[e] = {}
  12654. }
  12655. d = a.nextHandle_++;
  12656. a.JSC$10323_callbacks_[e][d] = c;
  12657. return d
  12658. })
  12659. };
  12660. FU.prototype.unsubscribe = function(a, b) {
  12661. var c = Geb(a);
  12662. if (c in this.JSC$10323_callbacks_ && (delete this.JSC$10323_callbacks_[c][b],
  12663. !this.JSC$10323_callbacks_[c].length)) {
  12664. var d = this.clients_[c];
  12665. b = Jq.run(function() {
  12666. ei(d);
  12667. delete this.clients_[c];
  12668. delete this.unsubscribeAsyncHandles_[c]
  12669. }
  12670. .bind(this));
  12671. this.unsubscribeAsyncHandles_[c] = b
  12672. }
  12673. }
  12674. ;
  12675.  
  12676.  
  12677. */
  12678.  
  12679.  
  12680. const onManagerFound = (dummyManager) => {
  12681. if (!dummyManager || typeof dummyManager !== 'object') return;
  12682.  
  12683. const mgrProto = dummyManager.constructor.prototype;
  12684.  
  12685. let keyCallbackStore = '';
  12686. for (const [key, v] of Object.entries(dummyManager)) {
  12687. if (key.includes('_callbacks_')) keyCallbackStore = key;
  12688. }
  12689.  
  12690. if (!keyCallbackStore || typeof mgrProto.unsubscribe !== 'function' || mgrProto.unsubscribe.length !== 2) return;
  12691.  
  12692. if (mgrProto.unsubscribe16) return;
  12693.  
  12694. mgrProto.unsubscribe16 = mgrProto.unsubscribe;
  12695.  
  12696. groupCollapsed("YouTube Super Fast Chat", " | *live-chat-manager* hacks");
  12697. console1.log("[Begin]");
  12698.  
  12699. const idMapper = new Map();
  12700.  
  12701. const convertId = function (objectId) {
  12702. if (!objectId || typeof objectId !== 'string') return null;
  12703.  
  12704. let result = idMapper.get(objectId)
  12705. if (result) return result;
  12706. result = atob(objectId.replace(/-/g, "+").replace(/_/g, "/"));
  12707. idMapper.set(objectId, result)
  12708. return result;
  12709. }
  12710.  
  12711.  
  12712. const rafHandleHolder = [];
  12713.  
  12714. let pzw = 0;
  12715. let lza = 0;
  12716. const rafHandlerFn = () => {
  12717. pzw = 0;
  12718. if (rafHandleHolder.length === 1) {
  12719. const f = rafHandleHolder[0];
  12720. rafHandleHolder.length = 0;
  12721. f();
  12722. } else if (rafHandleHolder.length > 1) {
  12723. const arr = rafHandleHolder.slice(0);
  12724. rafHandleHolder.length = 0;
  12725. for (const fn of arr) fn();
  12726. }
  12727. };
  12728.  
  12729.  
  12730. if (CHANGE_MANAGER_UNSUBSCRIBE) {
  12731.  
  12732. const checkIntegrityForSubscribe = (mgr) => {
  12733. if (mgr
  12734. && typeof mgr.unsubscribe16 === 'function' && mgr.unsubscribe16.length === 2
  12735. && typeof mgr.subscribe18 === 'function' && (mgr.subscribe18.length === 0 || mgr.subscribe18.length === 3)) {
  12736.  
  12737. const ns = new Set(Object.keys(mgr));
  12738. const ms = new Set(Object.keys(mgr.constructor.prototype));
  12739.  
  12740. if (ns.size >= 6 && ms.size >= 4) {
  12741. // including 'subscribe18'
  12742. // 'unsubscribe16', 'subscribe19'
  12743.  
  12744. let r = 0;
  12745. for (const k of ['nextHandle_', 'clients_', keyCallbackStore, 'unsubscribeAsyncHandles_', 'subscribe', 'subscribe18']) {
  12746. r += ns.has(k) ? 1 : 0;
  12747. }
  12748. for (const k of ['unsubscribe', 'handleInvalidationData_', 'unsubscribe16', 'subscribe19']) {
  12749. r += ms.has(k) ? 1 : 0;
  12750. }
  12751. if (r === 10) {
  12752. const isObject = (c) => (c || 0).constructor === Object;
  12753.  
  12754. if (isObject(mgr['clients_']) && isObject(mgr[keyCallbackStore]) && isObject(mgr['unsubscribeAsyncHandles_'])) {
  12755.  
  12756. return true;
  12757. }
  12758.  
  12759.  
  12760. }
  12761.  
  12762. }
  12763.  
  12764.  
  12765. }
  12766. return false;
  12767. }
  12768.  
  12769. mgrProto.subscribe19 = function (o, f, opts) {
  12770.  
  12771. const ct_clients_ = this.clients_ || 0;
  12772. const ct_handles_ = this.unsubscribeAsyncHandles_ || 0;
  12773.  
  12774. if (this.__doCustomSubscribe__ !== true || !ct_clients_ || !ct_handles_) return this.subscribe18.apply(this, arguments);
  12775.  
  12776. let objectId = ((o || 0).invalidationId || 0).objectId;
  12777. if (!objectId) return this.subscribe18.apply(this, arguments);
  12778. objectId = convertId(objectId);
  12779.  
  12780. // console.log('subscribe', objectId, ct_clients_[objectId], arguments);
  12781.  
  12782. if (ct_clients_[objectId]) {
  12783. if (ct_handles_[objectId] < 0) delete ct_handles_[objectId];
  12784. }
  12785.  
  12786. return this.subscribe18.apply(this, arguments);
  12787. }
  12788.  
  12789. mgrProto.unsubscribe = function (o, d) {
  12790. if (!this.subscribe18 && typeof this.subscribe === 'function') {
  12791. this.subscribe18 = this.subscribe;
  12792. this.subscribe = this.subscribe19;
  12793. this.__doCustomSubscribe__ = checkIntegrityForSubscribe(this);
  12794. }
  12795. const ct_clients_ = this.clients_;
  12796. const ct_handles_ = this.unsubscribeAsyncHandles_;
  12797. if (this.__doCustomSubscribe__ !== true || !ct_clients_ || !ct_handles_) return this.unsubscribe16.apply(this, arguments);
  12798.  
  12799. let objectId = ((o || 0).invalidationId || 0).objectId;
  12800. if (!objectId) return this.unsubscribe16.apply(this, arguments);
  12801.  
  12802. objectId = convertId(objectId);
  12803.  
  12804.  
  12805. // console.log('unsubscribe', objectId, ct_clients_[objectId], arguments);
  12806.  
  12807. const callbacks = this[keyCallbackStore] || 0;
  12808. const callbackObj = callbacks[objectId] || 0;
  12809.  
  12810.  
  12811. if (callbackObj && (delete callbackObj[d], isEmptyObject(callbackObj))) {
  12812. const w = ct_clients_[objectId];
  12813. lza = (lza & 1073741823) + 1;
  12814. const qta = -lza;
  12815. rafHandleHolder.push(() => {
  12816. if (qta === ct_handles_[objectId]) {
  12817. const o = {
  12818. callbacks, callbackObj,
  12819. client: ct_clients_[objectId],
  12820. handle: ct_handles_[objectId]
  12821. };
  12822. let p = 0;
  12823. try {
  12824. if (ct_clients_[objectId] === w) {
  12825. w && "function" === typeof w.dispose && w.dispose();
  12826. delete ct_clients_[objectId];
  12827. delete ct_handles_[objectId];
  12828. p = 1;
  12829. } else {
  12830. // w && "function" === typeof w.dispose && w.dispose();
  12831. // delete ct_clients_[objectId];
  12832. // delete ct_handles_[objectId];
  12833. p = 2;
  12834. }
  12835. } catch (e) {
  12836. console.warn(e);
  12837. }
  12838. console.log(`unsubscribed: ${p}`, this, o);
  12839. }
  12840. });
  12841. ct_handles_[objectId] = qta;
  12842. if (pzw === 0) {
  12843. pzw = requestAnimationFrame(rafHandlerFn);
  12844. }
  12845. }
  12846. }
  12847.  
  12848.  
  12849. console1.log("CHANGE_MANAGER_UNSUBSCRIBE - OK")
  12850.  
  12851. } else {
  12852.  
  12853. console1.log("CHANGE_MANAGER_UNSUBSCRIBE - NG")
  12854. }
  12855.  
  12856. console1.log("[End]");
  12857.  
  12858. groupEnd();
  12859.  
  12860. }
  12861.  
  12862.  
  12863.  
  12864. /*
  12865.  
  12866.  
  12867. a.prototype.async = function(e, h) {
  12868. return 0 < h ? Iq.run(e.bind(this), h) : ~Kq.run(e.bind(this))
  12869. }
  12870. ;
  12871. a.prototype.cancelAsync = function(e) {
  12872. 0 > e ? Kq.cancel(~e) : Iq.cancel(e)
  12873. }
  12874.  
  12875. */
  12876.  
  12877.  
  12878. (FASTER_ICON_RENDERING && Promise.all(
  12879. [
  12880. customElements.whenDefined("yt-icon-shape"),
  12881. customElements.whenDefined("yt-icon")
  12882. // document.createElement('icon-shape'),
  12883. ]
  12884. )).then(() => {
  12885. let cq = 0;
  12886. let dummys = [document.createElement('yt-icon-shape'), document.createElement('yt-icon')]
  12887. for (const dummy of dummys) {
  12888. let cProto = getProto(dummy);
  12889. if (cProto && typeof cProto.shouldRenderIconShape === 'function' && !cProto.shouldRenderIconShape571 && cProto.shouldRenderIconShape.length === 1) {
  12890. assertor(() => fnIntegrity(cProto.shouldRenderIconShape, '1.70.38'));
  12891. cq++;
  12892. cProto.shouldRenderIconShape571 = cProto.shouldRenderIconShape;
  12893. cProto.shouldRenderIconShape = function (a) {
  12894. if (this.isAnimatedIcon) return this.shouldRenderIconShape571(a);
  12895. if (!this.iconType || !this.iconShapeData) return this.shouldRenderIconShape571(a);
  12896. if (!this.iconName) return this.shouldRenderIconShape571(a);
  12897. return false;
  12898. // console.log(1051, this.iconType)
  12899. // console.log(1052, this.iconShapeData)
  12900. // console.log(1053, this.isAnimatedIcon)
  12901. }
  12902. }
  12903. // if(cProto && cProto.switchTemplateAtRegistration){
  12904. // cProto.switchTemplateAtRegistration = false;
  12905. // }
  12906. }
  12907. if (cq === 1) {
  12908. console.log("modified shouldRenderIconShape - Y")
  12909. } else {
  12910. console.log("modified shouldRenderIconShape - N", cq)
  12911. }
  12912. });
  12913.  
  12914. customElements.whenDefined("yt-invalidation-continuation").then(() => {
  12915.  
  12916. let __dummyManager__ = null;
  12917.  
  12918. mightFirstCheckOnYtInit();
  12919. groupCollapsed("YouTube Super Fast Chat", " | yt-invalidation-continuation hacks");
  12920. console1.log("[Begin]");
  12921. (() => {
  12922.  
  12923. const tag = "yt-invalidation-continuation"
  12924. const dummy = document.createElement(tag);
  12925.  
  12926. const cProto = getProto(dummy);
  12927. if (!cProto || !cProto.attached) {
  12928. console1.warn(`proto.attached for ${tag} is unavailable.`);
  12929. return;
  12930. }
  12931.  
  12932. const dummyManager = insp(dummy).manager_ || 0;
  12933. __dummyManager__ = dummyManager;
  12934.  
  12935.  
  12936. })();
  12937.  
  12938. console1.log("[End]");
  12939.  
  12940. groupEnd();
  12941.  
  12942.  
  12943.  
  12944. onManagerFound(__dummyManager__);
  12945.  
  12946. }).catch(console.warn);
  12947.  
  12948.  
  12949. if (INTERACTIVITY_BACKGROUND_ANIMATION >= 1) {
  12950.  
  12951. customElements.whenDefined("yt-live-interactivity-component-background").then(() => {
  12952.  
  12953. mightFirstCheckOnYtInit();
  12954. groupCollapsed("YouTube Super Fast Chat", " | yt-live-interactivity-component-background hacks");
  12955. console1.log("[Begin]");
  12956. (() => {
  12957.  
  12958. const tag = "yt-live-interactivity-component-background"
  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. cProto.__toStopAfterRun__ = function (hostElement) {
  12968. let mo = new MutationObserver(() => {
  12969. mo.disconnect();
  12970. mo.takeRecords();
  12971. mo = null;
  12972. this.lottieAnimation && this.lottieAnimation.stop(); // primary
  12973. foregroundPromiseFn().then(() => { // if the lottieAnimation is started with rAf triggering
  12974. this.lottieAnimation && this.lottieAnimation.stop(); // fallback
  12975. });
  12976. });
  12977. mo.observe(hostElement, { subtree: true, childList: true });
  12978. }
  12979.  
  12980. if (INTERACTIVITY_BACKGROUND_ANIMATION >= 1 && typeof cProto.maybeLoadAnimationBackground === 'function' && !cProto.maybeLoadAnimationBackground77 && cProto.maybeLoadAnimationBackground.length === 0) {
  12981.  
  12982. cProto.maybeLoadAnimationBackground77 = cProto.maybeLoadAnimationBackground;
  12983. cProto.maybeLoadAnimationBackground = function () {
  12984. let toRun = true;
  12985. let stopAfterRun = false;
  12986. if (!this.__bypassDisableAnimationBackground__) {
  12987. let doFix = false;
  12988. if (INTERACTIVITY_BACKGROUND_ANIMATION === 1) {
  12989. if (!this.lottieAnimation) {
  12990. doFix = true;
  12991. }
  12992. } else if (INTERACTIVITY_BACKGROUND_ANIMATION === 2) {
  12993. doFix = true;
  12994. }
  12995. if (doFix) {
  12996. if (this.useAnimationBackground === true) {
  12997. console.log('DISABLE_INTERACTIVITY_BACKGROUND_ANIMATION', this.lottieAnimation);
  12998. }
  12999. toRun = true;
  13000. stopAfterRun = true;
  13001. }
  13002. }
  13003. if (toRun) {
  13004. if (stopAfterRun && (this.hostElement instanceof HTMLElement_)) {
  13005. this.__toStopAfterRun__(this.hostElement); // primary
  13006. }
  13007. const r = this.maybeLoadAnimationBackground77.apply(this, arguments);
  13008. if (stopAfterRun && this.lottieAnimation) {
  13009. this.lottieAnimation.stop(); // fallback if no mutation
  13010. }
  13011. return r;
  13012. }
  13013. }
  13014.  
  13015. console1.log(`INTERACTIVITY_BACKGROUND_ANIMATION(${INTERACTIVITY_BACKGROUND_ANIMATION}) - OK`);
  13016.  
  13017. } else {
  13018. console1.log(`INTERACTIVITY_BACKGROUND_ANIMATION(${INTERACTIVITY_BACKGROUND_ANIMATION}) - NG`);
  13019.  
  13020. }
  13021.  
  13022. })();
  13023.  
  13024. console1.log("[End]");
  13025.  
  13026. groupEnd();
  13027.  
  13028.  
  13029. }).catch(console.warn);
  13030.  
  13031. }
  13032.  
  13033.  
  13034. if (DELAY_FOCUSEDCHANGED) {
  13035.  
  13036. customElements.whenDefined("yt-live-chat-text-input-field-renderer").then(() => {
  13037.  
  13038.  
  13039. mightFirstCheckOnYtInit();
  13040. groupCollapsed("YouTube Super Fast Chat", " | yt-live-chat-text-input-field-renderer hacks");
  13041. console1.log("[Begin]");
  13042. (() => {
  13043.  
  13044. const tag = "yt-live-chat-text-input-field-renderer"
  13045. const dummy = document.createElement(tag);
  13046.  
  13047. const cProto = getProto(dummy);
  13048. if (!cProto || !cProto.attached) {
  13049. console1.warn(`proto.attached for ${tag} is unavailable.`);
  13050. return;
  13051. }
  13052.  
  13053. if (DELAY_FOCUSEDCHANGED && typeof cProto.focusedChanged === 'function' && cProto.focusedChanged.length === 0 && !cProto.focusedChanged372) {
  13054. cProto.focusedChanged372 = cProto.focusedChanged;
  13055. cProto.focusedChanged = function () {
  13056. Promise.resolve(this).then((cnt) => {
  13057. if (cnt.isAttached === true) cnt.focusedChanged372();
  13058. });
  13059. }
  13060. }
  13061.  
  13062. })();
  13063.  
  13064. console1.log("[End]");
  13065.  
  13066. groupEnd();
  13067.  
  13068. });
  13069.  
  13070. }
  13071.  
  13072. }
  13073.  
  13074.  
  13075.  
  13076.  
  13077. promiseForCustomYtElementsReady.then(onRegistryReadyForDOMOperations);
  13078.  
  13079. const fixJsonParse = () => {
  13080.  
  13081. let p1 = window.onerror;
  13082.  
  13083. try {
  13084. JSON.parse("{}");
  13085. } catch (e) {
  13086. console.warn(e);
  13087. }
  13088.  
  13089. let p2 = window.onerror;
  13090.  
  13091. if (p1 !== p2) {
  13092.  
  13093.  
  13094. console.groupCollapsed(`%c${"YouTube Super Fast Chat"}%c${" | JS Engine Issue Found"}`,
  13095. "background-color: #010502; color: #fe806a; font-weight: 700; padding: 2px;",
  13096. "background-color: #010502; color: #fe806a; font-weight: 300; padding: 2px;"
  13097. );
  13098.  
  13099. console.warn("\nJSON.parse is hacked (e.g. Brave's script injection) which causes window.onerror changes on every JSON.parse call.\nPlease install https://gf.qytechs.cn/scripts/473972-youtube-js-engine-tamer to fix the issue.\n");
  13100.  
  13101. console.groupEnd();
  13102.  
  13103. }
  13104.  
  13105. }
  13106.  
  13107. if (CHECK_JSONPRUNE) {
  13108. promiseForCustomYtElementsReady.then(fixJsonParse);
  13109. }
  13110.  
  13111. });
  13112.  
  13113.  
  13114.  
  13115. })({ IntersectionObserver });

QingJ © 2025

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