utils.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. import { extConfig } from "./state";
  2. function numberFormat(numberState) {
  3. return getNumberFormatter(extConfig.numberDisplayFormat).format(
  4. numberState
  5. );
  6. }
  7. function getNumberFormatter(optionSelect) {
  8. let userLocales;
  9. if (document.documentElement.lang) {
  10. userLocales = document.documentElement.lang;
  11. } else if (navigator.language) {
  12. userLocales = navigator.language;
  13. } else {
  14. try {
  15. userLocales = new URL(
  16. Array.from(document.querySelectorAll("head > link[rel='search']"))
  17. ?.find((n) => n?.getAttribute("href")?.includes("?locale="))
  18. ?.getAttribute("href")
  19. )?.searchParams?.get("locale");
  20. } catch {
  21. cLog(
  22. "Cannot find browser locale. Use en as default for number formatting."
  23. );
  24. userLocales = "en";
  25. }
  26. }
  27. let formatterNotation;
  28. let formatterCompactDisplay;
  29. switch (optionSelect) {
  30. case "compactLong":
  31. formatterNotation = "compact";
  32. formatterCompactDisplay = "long";
  33. break;
  34. case "standard":
  35. formatterNotation = "standard";
  36. formatterCompactDisplay = "short";
  37. break;
  38. case "compactShort":
  39. default:
  40. formatterNotation = "compact";
  41. formatterCompactDisplay = "short";
  42. }
  43. const formatter = Intl.NumberFormat(userLocales, {
  44. notation: formatterNotation,
  45. compactDisplay: formatterCompactDisplay,
  46. });
  47. return formatter;
  48. }
  49. function localize(localeString) {
  50. return chrome.i18n.getMessage(localeString);
  51. }
  52. function getBrowser() {
  53. if (typeof chrome !== "undefined" && typeof chrome.runtime !== "undefined") {
  54. return chrome;
  55. } else if (
  56. typeof browser !== "undefined" &&
  57. typeof browser.runtime !== "undefined"
  58. ) {
  59. return browser;
  60. } else {
  61. console.log("browser is not supported");
  62. return false;
  63. }
  64. }
  65. function getVideoId(url) {
  66. const urlObject = new URL(url);
  67. const pathname = urlObject.pathname;
  68. if (pathname.startsWith("/clip")) {
  69. return document.querySelector("meta[itemprop='videoId']").content;
  70. } else {
  71. if (pathname.startsWith("/shorts")) {
  72. return pathname.slice(8);
  73. }
  74. return urlObject.searchParams.get("v");
  75. }
  76. }
  77. function isInViewport(element) {
  78. const rect = element.getBoundingClientRect();
  79. const height = innerHeight || document.documentElement.clientHeight;
  80. const width = innerWidth || document.documentElement.clientWidth;
  81. return (
  82. // When short (channel) is ignored, the element (like/dislike AND short itself) is
  83. // hidden with a 0 DOMRect. In this case, consider it outside of Viewport
  84. !(rect.top == 0 && rect.left == 0 && rect.bottom == 0 && rect.right == 0) &&
  85. rect.top >= 0 &&
  86. rect.left >= 0 &&
  87. rect.bottom <= height &&
  88. rect.right <= width
  89. );
  90. }
  91. function isVideoLoaded() {
  92. const videoId = getVideoId(window.location.href);
  93. return (
  94. document.querySelector(`ytd-watch-flexy[video-id='${videoId}']`) !== null ||
  95. // mobile: no video-id attribute
  96. document.querySelector('#player[loading="false"]:not([hidden])') !== null
  97. );
  98. }
  99. function cLog(message, writer) {
  100. message = `[return youtube dislike]: ${message}`;
  101. if (writer) {
  102. writer(message);
  103. } else {
  104. console.log(message);
  105. }
  106. }
  107. function getColorFromTheme(voteIsLike) {
  108. let colorString;
  109. switch (extConfig.colorTheme) {
  110. case "accessible":
  111. if (voteIsLike === true) {
  112. colorString = "dodgerblue";
  113. } else {
  114. colorString = "gold";
  115. }
  116. break;
  117. case "neon":
  118. if (voteIsLike === true) {
  119. colorString = "aqua";
  120. } else {
  121. colorString = "magenta";
  122. }
  123. break;
  124. case "classic":
  125. default:
  126. if (voteIsLike === true) {
  127. colorString = "lime";
  128. } else {
  129. colorString = "red";
  130. }
  131. }
  132. return colorString;
  133. }
  134. export {
  135. numberFormat,
  136. getBrowser,
  137. getVideoId,
  138. isInViewport,
  139. isVideoLoaded,
  140. cLog,
  141. getColorFromTheme,
  142. localize,
  143. };