BetterYTM.user.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. // ==UserScript==
  2. // @name BetterYTM
  3. // @namespace https://github.com/Sv443/BetterYTM#readme
  4. // @version 0.1.0
  5. // @description:en Improvements for YouTube Music
  6. // @description:de Verbesserungen für YouTube Music
  7. // @author Sv443
  8. // @license MIT
  9. // @match https://music.youtube.com/*
  10. // @icon https://www.google.com/s2/favicons?domain=music.youtube.com
  11. // @grant none
  12. // @run-at document-start
  13. // ==/UserScript==
  14. /**
  15. * This is where you can enable or disable features
  16. * If this userscript ever becomes something I might add like a menu to toggle these
  17. */
  18. const features = Object.freeze({
  19. /** Whether arrow keys should skip forwards and backwards by 10 seconds */
  20. arrowKeySupport: true,
  21. /** The theme color - accepts any CSS color value - default is "#ff0000" */
  22. themeColor: "#0f0",
  23. });
  24. const info = Object.freeze({
  25. name: GM.info.script.name, // eslint-disable-line no-undef
  26. version: GM.info.script.version, // eslint-disable-line no-undef
  27. namespace: GM.info.script.namespace, // eslint-disable-line no-undef
  28. });
  29. //#MARKER init
  30. function init()
  31. {
  32. console.log(`${info.name} v${info.version} - ${info.namespace}`);
  33. document.addEventListener("DOMContentLoaded", onDomLoad);
  34. }
  35. //#MARKER events
  36. /**
  37. * Called when the DOM has finished loading
  38. */
  39. function onDomLoad()
  40. {
  41. document.addEventListener("keydown", onKeyDown);
  42. if(features.themeColor != "#f00" && features.themeColor != "#ff0000")
  43. applyTheme();
  44. }
  45. /**
  46. * Called when the user presses keys
  47. * @param {KeyboardEvent} evt
  48. */
  49. function onKeyDown(evt)
  50. {
  51. if(features.arrowKeySupport && ["ArrowLeft", "ArrowRight"].includes(evt.code))
  52. {
  53. switch(evt.code)
  54. {
  55. case "ArrowLeft":
  56. // ripped this stuff from the console, most of these are probably unnecessary but this was finnicky af and I am sick and tired of trial and error
  57. document.body.dispatchEvent(new KeyboardEvent("keydown", {
  58. altKey: false,
  59. bubbles: true,
  60. cancelBubble: false,
  61. cancelable: true,
  62. charCode: 0,
  63. code: "KeyH",
  64. composed: true,
  65. ctrlKey: false,
  66. currentTarget: null,
  67. defaultPrevented: evt.defaultPrevented,
  68. explicitOriginalTarget: document.body,
  69. isTrusted: true,
  70. key: "h",
  71. keyCode: 72,
  72. metaKey: false,
  73. originalTarget: document.body,
  74. repeat: false,
  75. shiftKey: false,
  76. srcElement: document.body,
  77. target: document.body,
  78. type: "keydown",
  79. view: window,
  80. which: 72,
  81. }));
  82. break;
  83. case "ArrowRight":
  84. // ripped this stuff from the console, most of these are probably unnecessary but this was finnicky af and I am sick and tired of trial and error
  85. document.body.dispatchEvent(new KeyboardEvent("keydown", {
  86. altKey: false,
  87. bubbles: true,
  88. cancelBubble: false,
  89. cancelable: true,
  90. charCode: 0,
  91. code: "KeyL",
  92. composed: true,
  93. ctrlKey: false,
  94. currentTarget: null,
  95. defaultPrevented: evt.defaultPrevented,
  96. explicitOriginalTarget: document.body,
  97. isTrusted: true,
  98. key: "l",
  99. keyCode: 76,
  100. metaKey: false,
  101. originalTarget: document.body,
  102. repeat: false,
  103. shiftKey: false,
  104. srcElement: document.body,
  105. target: document.body,
  106. type: "keydown",
  107. view: window,
  108. which: 76,
  109. }));
  110. break;
  111. default:
  112. console.warn("Unknown key", evt.code);
  113. break;
  114. }
  115. }
  116. }
  117. /**
  118. * Applies the set theme color
  119. */
  120. function applyTheme()
  121. {
  122. const formatRegex = /^(\d{3}){1,2}$/;
  123. const color = features.themeColor.match(formatRegex) ? `#${color}` : color;
  124. /**
  125. * A list of changes to be made to the page to apply the theme color
  126. */
  127. const themeChanges = [
  128. {
  129. elem: document.querySelector("#progressContainer > #primaryProgress"),
  130. prop: "background",
  131. important: false,
  132. },
  133. {
  134. elem: document.querySelector(),
  135. prop: "",
  136. important: false,
  137. },
  138. {
  139. elem: document.querySelector(),
  140. prop: "",
  141. important: false,
  142. },
  143. ];
  144. themeChanges.forEach(change => {
  145. if(change.elem)
  146. {
  147. const value = change.important === true ? `${color} !important` : color;
  148. change.elem.style[change.prop] = value;
  149. }
  150. });
  151. }
  152. (() => init())();