YouTube: Force Single Column Mode

8/17/2023, 1:51:20 AM

  1. // ==UserScript==
  2. // @name YouTube: Force Single Column Mode
  3. // @namespace UserScripts
  4. // @match https://www.youtube.com/*
  5. // @grant none
  6. // @unwrap
  7. // @inject-into page
  8. // @version 1.1.1
  9. // @author CY Fung
  10. // @description 8/17/2023, 1:51:20 AM
  11. // @license MIT
  12. // ==/UserScript==
  13.  
  14. (() => {
  15.  
  16. const VIDEO_WH_RATIO_REFERENCE = 16 / 9; // 1.78
  17. const ENABLE_WHEN_CONTENT_OCCUPY_MORE_THAN = 0.2 // 20% or more of other content can be displayed in your browser
  18.  
  19. const insp = o => o ? (o.polymerController || o.inst || o || 0) : (o || 0);
  20.  
  21.  
  22. let ytPreferredMode = null; // true for two-columns_; min-width of side panel = 380px
  23.  
  24. function getShouldSingleColumn() {
  25. if (ytPreferredMode === false) return true;
  26. const { clientHeight, clientWidth } = document.documentElement;
  27. if (clientHeight > clientWidth) {
  28. let referenceVideoHeight = clientWidth / (VIDEO_WH_RATIO_REFERENCE);
  29. let belowSpace = clientHeight - referenceVideoHeight;
  30. if (belowSpace > -1e-3) {
  31. if (belowSpace - ENABLE_WHEN_CONTENT_OCCUPY_MORE_THAN * clientHeight >= -1e-3) {
  32. return true;
  33. }
  34. }
  35. }
  36. return false;
  37. }
  38.  
  39. let isShouldSingleColumn = null;
  40.  
  41. const Promise = (async () => { })().constructor;
  42. const { setInterval, clearInterval } = window;
  43.  
  44. if (location.pathname.indexOf('live_chat') >= 0) return;
  45.  
  46. let resizeBusy = false;
  47. let resizeQuene = Promise.resolve();
  48.  
  49.  
  50. function setIsTwoColumns_(ywf) {
  51. if (!ywf) return;
  52. const cnt = insp(ywf);
  53. const pnt = (cnt.ytdWatchBehavior ? cnt : ywf.ytdWatchBehavior ? ywf : 0) || 0;
  54.  
  55. if (typeof isShouldSingleColumn === 'boolean' && 'isTwoColumns_' in (pnt.ytdWatchBehavior || 0)) {
  56. pnt.ytdWatchBehavior.isTwoColumns_ = !isShouldSingleColumn;
  57. }
  58.  
  59. }
  60. let cid = setInterval.call(window, () => {
  61. const ywf = document.querySelector('ytd-watch-flexy');
  62. if (ywf && isShouldSingleColumn === null) {
  63. isShouldSingleColumn = getShouldSingleColumn();
  64. Window.prototype.addEventListener.call(window, 'resize', function () {
  65. if (resizeBusy) return;
  66. resizeBusy = true;
  67. const ywf = document.querySelector('ytd-watch-flexy');
  68. resizeQuene = resizeQuene.then(() => {
  69. const p = isShouldSingleColumn;
  70. isShouldSingleColumn = getShouldSingleColumn();
  71. resizeBusy = false;
  72. return isShouldSingleColumn !== p
  73. }).then(k => {
  74. if (k) setIsTwoColumns_(ywf);
  75. });
  76. }, { capture: false, passive: true });
  77.  
  78. if (isShouldSingleColumn) {
  79. ywf.removeAttribute('is-two-columns_');
  80. } else {
  81. ywf.setAttribute('is-two-columns_', '');
  82. }
  83.  
  84. const cnt = insp(ywf);
  85. const pnt = (cnt.ytdWatchBehavior ? cnt : ywf.ytdWatchBehavior ? ywf : 0) || 0;
  86.  
  87. if (typeof cnt.updateIsTwoColumnsFromBinding === 'function' && ('isTwoColumns_' in (pnt.ytdWatchBehavior || 0))) {
  88.  
  89. cnt.updateIsTwoColumnsFromBinding = function (a) {
  90. let b = null;
  91. try {
  92. b = a.detail.value;
  93. } catch (e) { }
  94. if (typeof b === 'boolean') ytPreferredMode = b;
  95. };
  96.  
  97. }
  98. Promise.resolve(ywf).then(setIsTwoColumns_)
  99. clearInterval.call(window, cid);
  100. }
  101.  
  102. }, 1);
  103.  
  104. })();

QingJ © 2025

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