Răsfoiți Sursa

feat: finished remove from queue btn

Sv443 1 an în urmă
părinte
comite
b10e1f6e25
4 a modificat fișierele cu 47 adăugiri și 5 ștergeri
  1. 4 0
      src/features/layout.css
  2. 34 3
      src/features/layout.ts
  3. 1 1
      src/features/lyrics.ts
  4. 8 1
      src/utils.ts

+ 4 - 0
src/features/layout.css

@@ -66,3 +66,7 @@
 .side-panel.modular ytmusic-player-queue-item:hover .song-info .bytm-queue-btn-container {
   display: inline-block;
 }
+
+ytmusic-app ytmusic-popup-container tp-yt-iron-dropdown[data-bytm-hidden=true] {
+  display: none !important;
+}

+ 34 - 3
src/features/layout.ts

@@ -2,7 +2,7 @@ import type { Event } from "@billjs/event-emitter";
 import type { FeatureConfig } from "../types";
 import { scriptInfo, triesInterval, triesLimit } from "../constants";
 import { getFeatures } from "../config";
-import { addGlobalStyle, autoPlural, error, getAssetUrl, insertAfter, log, openInNewTab } from "../utils";
+import { addGlobalStyle, autoPlural, error, getAssetUrl, insertAfter, log, openInNewTab, pauseFor } from "../utils";
 import { getEvtData, siteEvents } from "../events";
 import { openMenu } from "./menu/menu_old";
 import { getGeniusUrl, createLyricsBtn, sanitizeArtists, sanitizeSong, getLyricsCacheEntry } from "./lyrics";
@@ -110,6 +110,7 @@ export function initQueueButtons() {
 /**
  * Adds the buttons to each item in the current song queue.  
  * Also observes for changes to add new buttons to new items in the queue.
+ * @param queueItem The element with tagname `ytmusic-player-queue-item` to add queue buttons to
  */
 async function addQueueButtons(queueItem: HTMLElement) {
   const queueBtnsCont = document.createElement("div");
@@ -176,11 +177,41 @@ async function addQueueButtons(queueItem: HTMLElement) {
     deleteBtnElem.style.visibility = "initial";
     deleteBtnElem.style.display = "inline-flex";
 
-    deleteBtnElem.addEventListener("click", () => alert("WIP"));
+    deleteBtnElem.addEventListener("click", async () => {
+      // container of the queue item popup menu - element gets reused for every queue item
+      let queuePopupCont = document.querySelector("ytmusic-app ytmusic-popup-container tp-yt-iron-dropdown") as HTMLElement;
+      try {
+        // three dots button to open the popup menu of a queue item
+        const dotsBtnElem = queueItem.querySelector("ytmusic-menu-renderer yt-button-shape button") as HTMLButtonElement;
+
+        if(queuePopupCont)
+          queuePopupCont.setAttribute("data-bytm-hidden", "true");
+
+        dotsBtnElem.click();
+        await pauseFor(25);
+        queuePopupCont = document.querySelector("ytmusic-app ytmusic-popup-container tp-yt-iron-dropdown") as HTMLElement;
+
+        if(!queuePopupCont.hasAttribute("data-bytm-hidden"))
+          queuePopupCont.setAttribute("data-bytm-hidden", "true");
+
+        // a little bit janky and unreliable but the only way afaik
+        const removeFromQueueBtn = queuePopupCont.querySelector("tp-yt-paper-listbox *[role=option]:nth-child(7)") as HTMLElement;
+
+        await pauseFor(20);
+
+        removeFromQueueBtn.click();
+      }
+      catch(err) {
+        error("Couldn't remove song from queue due to error:", err);
+      }
+      finally {
+        queuePopupCont?.removeAttribute("data-bytm-hidden");
+      }
+    });
 
     const imgElem = document.createElement("img");
     imgElem.className = "bytm-generic-btn-img";
-    imgElem.src = getAssetUrl("close.png");
+    imgElem.src = getAssetUrl("close.png"); // TODO: make own icon for this
 
     deleteBtnElem.appendChild(imgElem);
   }

+ 1 - 1
src/features/lyrics.ts

@@ -200,7 +200,7 @@ export async function getGeniusUrl(artist: string, song: string): Promise<string
       return undefined;
     }
     else if(fetchRes.status < 200 || fetchRes.status >= 300) {
-      error(`Couldn't fetch lyrics URL from geniURL - status: ${fetchRes.status} - response: ${await fetchRes.text()}`);
+      error(`Couldn't fetch lyrics URL from geniURL - status: ${fetchRes.status} - response: ${(await fetchRes.json()).message ?? await fetchRes.text() ?? "(none)"}`);
       return undefined;
     }
     const result = await fetchRes.json();

+ 8 - 1
src/utils.ts

@@ -53,7 +53,7 @@ export function warn(...args: unknown[]): void {
     console.warn(consPrefix, ...args);
 }
 
-/** Logs string-compatible values to the console as an error. */
+/** Logs string-compatible values to the console as an error, no matter the log level. */
 export function error(...args: unknown[]): void {
   console.error(consPrefix, ...args);
 }
@@ -247,3 +247,10 @@ export function autoPlural(word: string, num: number | unknown[]) {
 export function clamp(value: number, min: number, max: number) {
   return Math.max(Math.min(value, max), min);
 }
+
+/** Pauses async execution for the specified time in ms */
+export function pauseFor(time: number) {
+  return new Promise((res) => {
+    setTimeout(res, time);
+  });
+}