Ver código fonte

ref!: use new onSelector

Sv443 1 ano atrás
pai
commit
2b40cb3779
5 arquivos alterados com 246 adições e 211 exclusões
  1. 129 112
      dist/BetterYTM.user.js
  2. 68 50
      src/features/layout.ts
  3. 3 3
      src/features/lyrics.ts
  4. 6 6
      src/index.ts
  5. 40 40
      src/utils.ts

Diferenças do arquivo suprimidas por serem muito extensas
+ 129 - 112
dist/BetterYTM.user.js


+ 68 - 50
src/features/layout.ts

@@ -1,9 +1,9 @@
 import type { Event } from "@billjs/event-emitter";
-import { addGlobalStyle, addParent, autoPlural, fetchAdvanced, insertAfter, openInNewTab, pauseFor } from "@sv443-network/userutils";
+import { addGlobalStyle, addParent, autoPlural, fetchAdvanced, insertAfter, onSelector, openInNewTab, pauseFor } from "@sv443-network/userutils";
 import type { FeatureConfig } from "../types";
 import { scriptInfo } from "../constants";
 import { getFeatures } from "../config";
-import { error, getAssetUrl, log, onSelectorExists } from "../utils";
+import { error, getAssetUrl, log } from "../utils";
 import { getEvtData, siteEvents } from "../events";
 import { openMenu } from "./menu/menu_old";
 import { getGeniusUrl, createLyricsBtn, sanitizeArtists, sanitizeSong, getLyricsCacheEntry } from "./lyrics";
@@ -66,17 +66,19 @@ async function improveLogo() {
     const res = await fetchAdvanced("https://music.youtube.com/img/on_platform_logo_dark.svg");
     const svg = await res.text();
     
-    onSelectorExists("ytmusic-logo a", (logoElem) => {
-      logoElem.classList.add("bytm-mod-logo", "bytm-no-select");
-      logoElem.innerHTML = svg;
+    onSelector("ytmusic-logo a", {
+      listener: (logoElem) => {
+        logoElem.classList.add("bytm-mod-logo", "bytm-no-select");
+        logoElem.innerHTML = svg;
 
-      logoElem.querySelectorAll("ellipse").forEach((e) => {
-        e.classList.add("bytm-mod-logo-ellipse");
-      });
+        logoElem.querySelectorAll("ellipse").forEach((e) => {
+          e.classList.add("bytm-mod-logo-ellipse");
+        });
 
-      logoElem.querySelector("path")?.classList.add("bytm-mod-logo-path");
+        logoElem.querySelector("path")?.classList.add("bytm-mod-logo-path");
 
-      log("Swapped logo to inline SVG");
+        log("Swapped logo to inline SVG");
+      },
     });
   }
   catch(err) {
@@ -86,26 +88,28 @@ async function improveLogo() {
 
 /** Exchanges the default YTM logo into BetterYTM's logo with a sick ass animation */
 function exchangeLogo() {
-  onSelectorExists(".bytm-mod-logo", (logoElem) => {
-    if(logoElem.classList.contains("bytm-logo-exchanged"))
-      return;
+  onSelector(".bytm-mod-logo", {
+    listener: (logoElem) => {
+      if(logoElem.classList.contains("bytm-logo-exchanged"))
+        return;
 
-    logoExchanged = true;
-    logoElem.classList.add("bytm-logo-exchanged");
+      logoExchanged = true;
+      logoElem.classList.add("bytm-logo-exchanged");
 
-    const newLogo = document.createElement("img");
-    newLogo.className = "bytm-mod-logo-img";
-    newLogo.src = getAssetUrl("icon/icon.png");
+      const newLogo = document.createElement("img");
+      newLogo.className = "bytm-mod-logo-img";
+      newLogo.src = getAssetUrl("icon/icon.png");
 
-    logoElem.insertBefore(newLogo, logoElem.querySelector("svg"));
+      logoElem.insertBefore(newLogo, logoElem.querySelector("svg"));
 
-    document.head.querySelectorAll<HTMLLinkElement>("link[rel=\"icon\"]").forEach(e => {
-      e.href = getAssetUrl("icon/icon.png");
-    });
+      document.head.querySelectorAll<HTMLLinkElement>("link[rel=\"icon\"]").forEach(e => {
+        e.href = getAssetUrl("icon/icon.png");
+      });
 
-    setTimeout(() => {
-      logoElem.querySelectorAll(".bytm-mod-logo-ellipse").forEach(e => e.remove());
-    }, 1000);
+      setTimeout(() => {
+        logoElem.querySelectorAll(".bytm-mod-logo-ellipse").forEach(e => e.remove());
+      }, 1000);
+    },
   });
 }
 
@@ -150,13 +154,17 @@ export function addConfigMenuOption(container: HTMLElement) {
 
 /** Removes the "Upgrade" / YT Music Premium tab from the sidebar */
 export function removeUpgradeTab() {
-  onSelectorExists("ytmusic-app-layout tp-yt-app-drawer #contentContainer #guide-content #items ytmusic-guide-entry-renderer:nth-child(4)", (tabElemLarge) => {
-    tabElemLarge.remove();
-    log("Removed large upgrade tab");
+  onSelector("ytmusic-app-layout tp-yt-app-drawer #contentContainer #guide-content #items ytmusic-guide-entry-renderer:nth-child(4)", {
+    listener: (tabElemLarge) => {
+      tabElemLarge.remove();
+      log("Removed large upgrade tab");
+    },
   });
-  onSelectorExists("ytmusic-app-layout #mini-guide ytmusic-guide-renderer #sections ytmusic-guide-section-renderer #items ytmusic-guide-entry-renderer:nth-child(4)", (tabElemSmall) => {
-    tabElemSmall.remove();
-    log("Removed small upgrade tab");
+  onSelector("ytmusic-app-layout #mini-guide ytmusic-guide-renderer #sections ytmusic-guide-section-renderer #items ytmusic-guide-entry-renderer:nth-child(4)", {
+    listener: (tabElemSmall) => {
+      tabElemSmall.remove();
+      log("Removed small upgrade tab");
+    },
   });
 }
 
@@ -372,9 +380,11 @@ export function addAnchorImprovements() {
     };
 
     // initial three shelves aren't included in the event fire
-    onSelectorExists("ytmusic-carousel-shelf-renderer", () => {
-      const carouselShelves = document.body.querySelectorAll<HTMLElement>("ytmusic-carousel-shelf-renderer");
-      carouselShelves.forEach(condCarouselImprovements);
+    onSelector("ytmusic-carousel-shelf-renderer", {
+      listener: () => {
+        const carouselShelves = document.body.querySelectorAll<HTMLElement>("ytmusic-carousel-shelf-renderer");
+        carouselShelves.forEach(condCarouselImprovements);
+      },
     });
 
     // every shelf that's loaded by scrolling:
@@ -398,18 +408,22 @@ export function addAnchorImprovements() {
 
     const relatedTabContentsSelector = "ytmusic-section-list-renderer[page-type=\"MUSIC_PAGE_TYPE_TRACK_RELATED\"] #contents";
 
-    onSelectorExists("ytmusic-tab-renderer[page-type=\"MUSIC_PAGE_TYPE_TRACK_RELATED\"]", (relatedTabContainer) => {
-      const relatedTabObserver = new MutationObserver(([ { addedNodes, removedNodes } ]) => {
-        if(addedNodes.length > 0 || removedNodes.length > 0)
-          relatedTabAnchorImprovements(document.querySelector<HTMLElement>(relatedTabContentsSelector)!);
-      });
-      relatedTabObserver.observe(relatedTabContainer, {
-        childList: true,
-      });
+    onSelector("ytmusic-tab-renderer[page-type=\"MUSIC_PAGE_TYPE_TRACK_RELATED\"]", {
+      listener: (relatedTabContainer) => {
+        const relatedTabObserver = new MutationObserver(([ { addedNodes, removedNodes } ]) => {
+          if(addedNodes.length > 0 || removedNodes.length > 0)
+            relatedTabAnchorImprovements(document.querySelector<HTMLElement>(relatedTabContentsSelector)!);
+        });
+        relatedTabObserver.observe(relatedTabContainer, {
+          childList: true,
+        });
+      },
     });
 
-    onSelectorExists(relatedTabContentsSelector, (relatedTabContents) => {
-      relatedTabAnchorImprovements(relatedTabContents);
+    onSelector(relatedTabContentsSelector, {
+      listener: (relatedTabContents) => {
+        relatedTabAnchorImprovements(relatedTabContents);
+      },
     });
   }
   catch(err) {
@@ -425,14 +439,18 @@ export function addAnchorImprovements() {
       return items.length;
     };
 
-    onSelectorExists("ytmusic-app-layout tp-yt-app-drawer #contentContainer #guide-content #items ytmusic-guide-entry-renderer", (sidebarCont) => {
-      const itemsAmt = addSidebarAnchors(sidebarCont);
-      log(`Added anchors around ${itemsAmt} sidebar ${autoPlural("item", itemsAmt)}`);
+    onSelector("ytmusic-app-layout tp-yt-app-drawer #contentContainer #guide-content #items ytmusic-guide-entry-renderer", {
+      listener: (sidebarCont) => {
+        const itemsAmt = addSidebarAnchors(sidebarCont);
+        log(`Added anchors around ${itemsAmt} sidebar ${autoPlural("item", itemsAmt)}`);
+      },
     });
 
-    onSelectorExists("ytmusic-app-layout #mini-guide ytmusic-guide-renderer ytmusic-guide-section-renderer #items ytmusic-guide-entry-renderer", (miniSidebarCont) => {
-      const itemsAmt = addSidebarAnchors(miniSidebarCont);
-      log(`Added anchors around ${itemsAmt} mini sidebar ${autoPlural("item", itemsAmt)}`);
+    onSelector("ytmusic-app-layout #mini-guide ytmusic-guide-renderer ytmusic-guide-section-renderer #items ytmusic-guide-entry-renderer", {
+      listener: (miniSidebarCont) => {
+        const itemsAmt = addSidebarAnchors(miniSidebarCont);
+        log(`Added anchors around ${itemsAmt} mini sidebar ${autoPlural("item", itemsAmt)}`);
+      },
     });
   }
   catch(err) {

+ 3 - 3
src/features/lyrics.ts

@@ -1,5 +1,5 @@
-import { clamp, fetchAdvanced, insertAfter } from "@sv443-network/userutils";
-import { error, getAssetUrl, info, log, onSelectorExists } from "../utils";
+import { clamp, fetchAdvanced, insertAfter, onSelector } from "@sv443-network/userutils";
+import { error, getAssetUrl, info, log } from "../utils";
 
 /** Base URL of geniURL */
 export const geniUrlBase = "https://api.sv443.net/geniurl";
@@ -45,7 +45,7 @@ let mcCurrentSongTitle = "";
 
 /** Adds a lyrics button to the media controls bar */
 export function addMediaCtrlLyricsBtn(): void {
-  onSelectorExists(".middle-controls-buttons ytmusic-like-button-renderer#like-button-renderer", addActualMediaCtrlLyricsBtn);
+  onSelector(".middle-controls-buttons ytmusic-like-button-renderer#like-button-renderer", { listener: addActualMediaCtrlLyricsBtn });
 }
 
 // TODO: add error.svg if the request fails

+ 6 - 6
src/index.ts

@@ -1,7 +1,7 @@
-import { addGlobalStyle, autoPlural, preloadImages } from "@sv443-network/userutils";
+import { addGlobalStyle, autoPlural, preloadImages, initOnSelector, onSelector } from "@sv443-network/userutils";
 import { loadFeatureConf } from "./config";
 import { logLevel, scriptInfo } from "./constants";
-import { error, getAssetUrl, getDomain, initSelectorExistsCheck, log, onSelectorExists, setLogLevel } from "./utils";
+import { error, getAssetUrl, getDomain, log, setLogLevel } from "./utils";
 import { initSiteEvents } from "./events";
 import {
   // layout
@@ -77,12 +77,12 @@ async function init() {
 
 /** Called when the DOM has finished loading and can be queried and altered by the userscript */
 async function onDomLoad() {
-  // post-build these double quotes are replaced by backticks (if backticks are used here, webpack converts them to double quotes)
+  // post-build these double quotes are replaced by backticks (because if backticks are used here, webpack converts them to double quotes)
   addGlobalStyle("{{GLOBAL_STYLE}}");
 
-  const features = await loadFeatureConf();
+  initOnSelector();
 
-  initSelectorExistsCheck();
+  const features = await loadFeatureConf();
 
   log(`Initializing features for domain "${domain}"...`);
 
@@ -97,7 +97,7 @@ async function onDomLoad() {
 
       initSiteEvents();
 
-      onSelectorExists("tp-yt-iron-dropdown #contentWrapper ytd-multi-page-menu-renderer #container.menu-container", addConfigMenuOption);
+      onSelector("tp-yt-iron-dropdown #contentWrapper ytd-multi-page-menu-renderer #container.menu-container", { listener: addConfigMenuOption });
 
       if(features.arrowKeySupport)
         initArrowKeySkip();

+ 40 - 40
src/utils.ts

@@ -1,4 +1,4 @@
-import { clamp, getUnsafeWindow } from "@sv443-network/userutils";
+import { clamp, getUnsafeWindow, onSelector } from "@sv443-network/userutils";
 import { branch, scriptInfo } from "./constants";
 import type { Domain, LogLevel } from "./types";
 
@@ -106,7 +106,7 @@ export function getVideoTime() {
         };
 
         if(!progElem)
-          return onSelectorExists(pbSelector, observe);
+          return onSelector(pbSelector, { listener: observe });
         else
           return observe(progElem);
       }
@@ -167,45 +167,45 @@ function ytForceShowVideoTime() {
 //   return isNaN(finalTime) ? 0 : finalTime;
 // }
 
-const selectorExistsMap = new Map<string, Array<(element: HTMLElement) => void>>();
-
-/**
- * Calls the `listener` as soon as the `selector` exists in the DOM.  
- * Listeners are deleted as soon as they are called once.  
- * Multiple listeners with the same selector may be registered.
- */
-export function onSelectorExists(selector: string, listener: (element: HTMLElement) => void) {
-  const el = document.querySelector<HTMLElement>(selector);
-
-  if(el)
-    listener(el);
-  else {
-    if(selectorExistsMap.get(selector))
-      selectorExistsMap.set(selector, [...selectorExistsMap.get(selector)!, listener]);
-    else
-      selectorExistsMap.set(selector, [listener]);
-  }
-}
-
-/** Initializes the MutationObserver responsible for checking selectors registered in `onSelectorExists()` */
-export function initSelectorExistsCheck() {
-  const observer = new MutationObserver(() => {
-    for(const [selector, listeners] of selectorExistsMap.entries()) {
-      const el = document.querySelector<HTMLElement>(selector);
-      if(el) {
-        listeners.forEach(listener => listener(el));
-        selectorExistsMap.delete(selector);
-      }
-    }
-  });
-
-  observer.observe(document.body, {
-    subtree: true,
-    childList: true,
-  });
+// const selectorExistsMap = new Map<string, Array<(element: HTMLElement) => void>>();
+
+// /**
+//  * Calls the `listener` as soon as the `selector` exists in the DOM.  
+//  * Listeners are deleted as soon as they are called once.  
+//  * Multiple listeners with the same selector may be registered.
+//  */
+// export function onSelectorExists(selector: string, listener: (element: HTMLElement) => void) {
+//   const el = document.querySelector<HTMLElement>(selector);
+
+//   if(el)
+//     listener(el);
+//   else {
+//     if(selectorExistsMap.get(selector))
+//       selectorExistsMap.set(selector, [...selectorExistsMap.get(selector)!, listener]);
+//     else
+//       selectorExistsMap.set(selector, [listener]);
+//   }
+// }
 
-  log("Initialized \"selector exists\" MutationObserver");
-}
+// /** Initializes the MutationObserver responsible for checking selectors registered in `onSelectorExists()` */
+// export function initSelectorExistsCheck() {
+//   const observer = new MutationObserver(() => {
+//     for(const [selector, listeners] of selectorExistsMap.entries()) {
+//       const el = document.querySelector<HTMLElement>(selector);
+//       if(el) {
+//         listeners.forEach(listener => listener(el));
+//         selectorExistsMap.delete(selector);
+//       }
+//     }
+//   });
+
+//   observer.observe(document.body, {
+//     subtree: true,
+//     childList: true,
+//   });
+
+//   log("Initialized \"selector exists\" MutationObserver");
+// }
 
 /**
  * Returns the current domain as a constant string representation

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff