Explorar o código

ref: implement `onInteraction`

Sv443 hai 1 ano
pai
achega
913f964116

+ 2 - 3
src/components/hotkeyInput.ts

@@ -1,6 +1,6 @@
 import { getFeatures } from "../config";
 import { siteEvents } from "../siteEvents";
-import { t } from "../utils";
+import { onInteraction, t } from "../utils";
 import type { HotkeyObj } from "../types";
 import "./hotkeyInput.css";
 
@@ -62,8 +62,7 @@ export function createHotkeyInput({ initialValue, onChange }: HotkeyInputProps):
     resetElem.classList.add("bytm-hidden");
   };
 
-  resetElem.addEventListener("click", resetClicked);
-  resetElem.addEventListener("keydown", (e) => ["Enter", " ", "Space"].includes(e.key) && resetClicked(e));
+  onInteraction(resetElem, resetClicked);
 
   if(initialValue)
     infoElem.innerHTML = getHotkeyInfoHtml(initialValue);

+ 5 - 7
src/dialogs/versionNotif.ts

@@ -1,5 +1,5 @@
 import { host, scriptInfo } from "../constants";
-import { getChangelogMd, parseMarkdown, t } from "../utils";
+import { getChangelogMd, onInteraction, parseMarkdown, t } from "../utils";
 import { BytmDialog, createToggleInput } from "../components";
 import { getFeatures, saveFeatures } from "../config";
 import pkg from "../../package.json" assert { type: "json" };
@@ -135,20 +135,18 @@ async function renderBody({
   btnUpdate.className = "bytm-btn";
   btnUpdate.tabIndex = 0;
   btnUpdate.textContent = t("open_update_page_install_manually", hostPlatformNames[host]);
-  const btnUpdateClicked = () => {
+
+  onInteraction(btnUpdate, () => {
     window.open(pkg.updates[host]);
     verNotifDialog?.close();
-  };
-  btnUpdate.addEventListener("click", btnUpdateClicked);
-  btnUpdate.addEventListener("keydown", (e) => e.key === "Enter" && btnUpdateClicked());
+  });
 
   const btnClose = document.createElement("button");
   btnClose.className = "bytm-btn";
   btnClose.tabIndex = 0;
   btnClose.textContent = t("close_and_ignore_for_24h");
 
-  btnClose.addEventListener("click", () => verNotifDialog?.close());
-  btnClose.addEventListener("keydown", (e) => e.key === "Enter" && verNotifDialog?.close());
+  onInteraction(btnClose, () => verNotifDialog?.close());
 
   btnWrapper.appendChild(btnUpdate);
   btnWrapper.appendChild(btnClose);

+ 10 - 12
src/features/layout.ts

@@ -1,7 +1,7 @@
 import { addGlobalStyle, addParent, autoPlural, fetchAdvanced, insertAfter, pauseFor, type Stringifiable } from "@sv443-network/userutils";
 import type { FeatureConfig } from "../types";
 import { scriptInfo } from "../constants";
-import { error, getResourceUrl, log, onSelectorOld, warn, t, resourceToHTMLString } from "../utils";
+import { error, getResourceUrl, log, onSelectorOld, warn, t, resourceToHTMLString, onInteraction } from "../utils";
 import { siteEvents } from "../siteEvents";
 import { openCfgMenu } from "../menu/menu_old";
 import { getFeatures } from "../config";
@@ -39,8 +39,7 @@ export async function addWatermark() {
       exchangeLogo();
   };
 
-  watermark.addEventListener("click", watermarkOpenMenu);
-  watermark.addEventListener("keydown", (e) => e.key === "Enter" && watermarkOpenMenu(e));
+  onInteraction(watermark, watermarkOpenMenu);
 
   onSelectorOld("ytmusic-nav-bar #left-content", {
     listener: (logoElem) => insertAfter(logoElem, watermark),
@@ -118,7 +117,8 @@ export async function addConfigMenuOption(container: HTMLElement) {
   cfgOptItemElem.role = "button";
   cfgOptItemElem.tabIndex = 0;
   cfgOptItemElem.ariaLabel = cfgOptItemElem.title = t("open_menu_tooltip", scriptInfo.name);
-  const cfgOptItemClicked = async (e: MouseEvent | KeyboardEvent) => {
+
+  onInteraction(cfgOptItemElem, async (e: MouseEvent | KeyboardEvent) => {
     const settingsBtnElem = document.querySelector<HTMLElement>("ytmusic-nav-bar ytmusic-settings-button tp-yt-paper-icon-button");
     settingsBtnElem?.click();
 
@@ -128,9 +128,7 @@ export async function addConfigMenuOption(container: HTMLElement) {
       openCfgMenu();
     if(!logoExchanged && (e.shiftKey || e.ctrlKey))
       exchangeLogo();
-  };
-  cfgOptItemElem.addEventListener("click", cfgOptItemClicked);
-  cfgOptItemElem.addEventListener("keydown", (e) => e.key === "Enter" && cfgOptItemClicked(e));
+  });
 
   const cfgOptIconElem = document.createElement("img");
   cfgOptIconElem.className = "bytm-cfg-menu-option-icon";
@@ -515,6 +513,7 @@ export async function addScrollToActiveBtn() {
 
       const linkElem = document.createElement("div");
       linkElem.id = "bytm-scroll-to-active-btn";
+      linkElem.tabIndex = 0;
       linkElem.className = "ytmusic-player-bar bytm-generic-btn";
       linkElem.ariaLabel = linkElem.title = t("scroll_to_playing");
       linkElem.role = "button";
@@ -523,20 +522,19 @@ export async function addScrollToActiveBtn() {
       imgElem.className = "bytm-generic-btn-img";
       imgElem.src = await getResourceUrl("icon-skip_to");
 
-      linkElem.addEventListener("click", (e) => {
+      const scrollToActiveInteraction = () => {
         const activeItem = document.querySelector<HTMLElement>("#side-panel .ytmusic-player-queue ytmusic-player-queue-item[play-button-state=\"loading\"], #side-panel .ytmusic-player-queue ytmusic-player-queue-item[play-button-state=\"playing\"], #side-panel .ytmusic-player-queue ytmusic-player-queue-item[play-button-state=\"paused\"]");
         if(!activeItem)
           return;
 
-        e.preventDefault();
-        e.stopImmediatePropagation();
-
         activeItem.scrollIntoView({
           behavior: "smooth",
           block: "center",
           inline: "center",
         });
-      });
+      };
+
+      onInteraction(linkElem, scrollToActiveInteraction);
 
       linkElem.appendChild(imgElem);
       containerElem.appendChild(linkElem);

+ 5 - 11
src/features/songLists.ts

@@ -1,5 +1,5 @@
 import { autoPlural, openInNewTab, pauseFor } from "@sv443-network/userutils";
-import { clearInner, error, getResourceUrl, log, onSelectorOld, t, warn } from "../utils";
+import { clearInner, error, getResourceUrl, log, onInteraction, onSelectorOld, t, warn } from "../utils";
 import { SiteEventsMap, siteEvents } from "../siteEvents";
 import { emitInterface } from "../interface";
 import { fetchLyricsUrlTop, createLyricsBtn, sanitizeArtists, sanitizeSong, splitVideoTitle } from "./lyrics";
@@ -110,7 +110,7 @@ async function addQueueButtons(
     lyricsBtnElem.role = "link";
     lyricsBtnElem.tabIndex = 0;
 
-    const lyricsBtnClicked = async (e: MouseEvent | KeyboardEvent) => {
+    onInteraction(lyricsBtnElem, async (e: MouseEvent | KeyboardEvent) => {
       e.preventDefault();
       e.stopImmediatePropagation();
 
@@ -199,10 +199,7 @@ async function addQueueButtons(
       }
 
       lyricsUrl && openInNewTab(lyricsUrl);
-    };
-
-    lyricsBtnElem.addEventListener("click", lyricsBtnClicked);
-    lyricsBtnElem.addEventListener("keydown", (e) => e.key === "Enter" && lyricsBtnClicked(e));
+    });
   }
 
   //#SECTION delete from queue btn
@@ -220,7 +217,7 @@ async function addQueueButtons(
     imgElem.classList.add("bytm-generic-btn-img");
     imgElem.src = deleteIconUrl;
 
-    const deleteBtnClicked = async (e: MouseEvent | KeyboardEvent) => {
+    onInteraction(deleteBtnElem, async (e: MouseEvent | KeyboardEvent) => {
       e.preventDefault();
       e.stopImmediatePropagation();
 
@@ -269,10 +266,7 @@ async function addQueueButtons(
       finally {
         queuePopupCont?.removeAttribute("data-bytm-hidden");
       }
-    };
-
-    deleteBtnElem.addEventListener("click", deleteBtnClicked);
-    deleteBtnElem.addEventListener("keydown", (e) => e.key === "Enter" && deleteBtnClicked(e));
+    });
 
     deleteBtnElem.appendChild(imgElem);
   }

+ 19 - 35
src/menu/menu_old.ts

@@ -2,7 +2,7 @@ import { compress, decompress, debounce, isScrollable } from "@sv443-network/use
 import { defaultConfig, getFeatures, migrations, saveFeatures, setDefaultFeatures } from "../config";
 import { buildNumber, compressionFormat, host, mode, scriptInfo } from "../constants";
 import { featInfo, disableBeforeUnload } from "../features/index";
-import { error, getResourceUrl, info, log, resourceToHTMLString, warn, getLocale, hasKey, initTranslations, setLocale, t, compressionSupported, getChangelogHtmlWithDetails, arrayWithSeparators, tp, type TrKey } from "../utils";
+import { error, getResourceUrl, info, log, resourceToHTMLString, warn, getLocale, hasKey, initTranslations, setLocale, t, compressionSupported, getChangelogHtmlWithDetails, arrayWithSeparators, tp, type TrKey, onInteraction } from "../utils";
 import { formatVersion } from "../config";
 import { emitSiteEvent, siteEvents } from "../siteEvents";
 import type { FeatureCategory, FeatureKey, FeatureConfig, HotkeyObj, FeatureInfo } from "../types";
@@ -137,8 +137,7 @@ async function addCfgMenu() {
   closeElem.tabIndex = 0;
   closeElem.src = await getResourceUrl("img-close");
   closeElem.ariaLabel = closeElem.title = t("close_menu_tooltip");
-  closeElem.addEventListener("click", closeCfgMenu);
-  closeElem.addEventListener("keydown", ({ key }) => key === "Enter" && closeCfgMenu());
+  onInteraction(closeElem, closeCfgMenu);
 
   titleCont.appendChild(titleElem);
   titleCont.appendChild(linksCont);
@@ -340,14 +339,12 @@ async function addCfgMenu() {
             helpElem.role = "button";
             helpElem.tabIndex = 0;
             helpElem.innerHTML = helpElemImgHtml;
-            const helpElemClicked = (e: MouseEvent | KeyboardEvent) => {
+            onInteraction(helpElem, (e: MouseEvent | KeyboardEvent) => {
               e.preventDefault();
               e.stopPropagation();
 
               openHelpDialog(featKey as FeatureKey);
-            };
-            helpElem.addEventListener("click", helpElemClicked);
-            helpElem.addEventListener("keydown", (e) => e.key === "Enter" && helpElemClicked(e));
+            });
           }
           else {
             error(`Couldn't create help button SVG element for feature '${featKey}'`);
@@ -412,7 +409,7 @@ async function addCfgMenu() {
           advCopyHiddenBtn.textContent = t("copy_hidden_value");
           advCopyHiddenBtn.ariaLabel = advCopyHiddenBtn.title = t("copy_hidden_tooltip");
 
-          const copyHiddenClicked = (e: MouseEvent | KeyboardEvent) => {
+          const copyHiddenInteraction = (e: MouseEvent | KeyboardEvent) => {
             e.preventDefault();
             e.stopPropagation();
 
@@ -427,8 +424,7 @@ async function addCfgMenu() {
             }
           };
 
-          advCopyHiddenBtn.addEventListener("click", copyHiddenClicked);
-          advCopyHiddenBtn.addEventListener("keydown", (e) => ["Enter", " ", "Space"].includes(e.key) && copyHiddenClicked(e));
+          onInteraction(advCopyHiddenBtn, copyHiddenInteraction);
 
           advCopyHiddenCont = document.createElement("span");
 
@@ -659,15 +655,13 @@ async function addCfgMenu() {
   versionEl.tabIndex = 0;
   versionEl.ariaLabel = versionEl.title = t("version_tooltip", scriptInfo.version, buildNumber);
   versionEl.textContent = `v${scriptInfo.version} (#${buildNumber})`;
-  const versionElemClicked = async (e: MouseEvent | KeyboardEvent) => {
+  onInteraction(versionEl, async (e: MouseEvent | KeyboardEvent) => {
     e.preventDefault();
     e.stopPropagation();
 
     await openChangelogMenu("cfgMenu");
     closeCfgMenu(undefined, false);
-  };
-  versionEl.addEventListener("click", versionElemClicked);
-  versionEl.addEventListener("keydown", (e) => e.key === "Enter" && versionElemClicked(e));
+  });
 
   subtitleElemCont.appendChild(versionEl);
   titleElem.appendChild(subtitleElemCont);
@@ -805,8 +799,7 @@ async function openHelpDialog(featureKey: FeatureKey) {
     closeElem.tabIndex = 0;
     closeElem.src = await getResourceUrl("img-close");
     closeElem.ariaLabel = closeElem.title = t("close_menu_tooltip");
-    closeElem.addEventListener("click", (e) => closeHelpDialog(e));
-    closeElem.addEventListener("keydown", (e) => e.key === "Enter" && closeHelpDialog(e));
+    onInteraction(closeElem, closeHelpDialog);
 
     headerElem.appendChild(titleCont);
     headerElem.appendChild(closeElem);
@@ -944,12 +937,10 @@ async function addExportMenu() {
   closeElem.tabIndex = 0;
   closeElem.src = await getResourceUrl("img-close");
   closeElem.ariaLabel = closeElem.title = t("close_menu_tooltip");
-  const closeExportMenuClicked = (e: MouseEvent | KeyboardEvent) => {
+  onInteraction(closeElem, (e: MouseEvent | KeyboardEvent) => {
     closeExportMenu(e);
     openCfgMenu();
-  };
-  closeElem.addEventListener("click", (e) => closeExportMenuClicked(e));
-  closeElem.addEventListener("keydown", (e) => e.key === "Enter" && closeExportMenuClicked(e));
+  });
 
   titleCont.appendChild(titleElem);
 
@@ -972,15 +963,14 @@ async function addExportMenu() {
   textAreaElem.value = t("click_to_reveal_sensitive_info");
   textAreaElem.setAttribute("revealed", "false");
 
-  const textAreaClicked = async () => {
+  const textAreaInteraction = async () => {
     const cfgString = JSON.stringify({ formatVersion, data: getFeatures() });
     lastUncompressedCfgString = JSON.stringify({ formatVersion, data: getFeatures() }, undefined, 2);
     textAreaElem.value = canCompress ? await compress(cfgString, compressionFormat, "string") : cfgString;
     textAreaElem.setAttribute("revealed", "true");
   };
 
-  textAreaElem.addEventListener("click", textAreaClicked);
-  textAreaElem.addEventListener("keydown", (e) => ["Enter", " ", "Space"].includes(e.key) && textAreaClicked());
+  onInteraction(textAreaElem, textAreaInteraction);
 
   siteEvents.on("configChanged", async (data) => {
     const textAreaElem = document.querySelector<HTMLTextAreaElement>("#bytm-export-menu-textarea");
@@ -1008,7 +998,7 @@ async function addExportMenu() {
   copiedTextElem.textContent = t("copied");
   copiedTextElem.style.display = "none";
 
-  const copyBtnClicked = async (evt: MouseEvent | KeyboardEvent) => {
+  onInteraction(copyBtnElem, async (evt: MouseEvent | KeyboardEvent) => {
     evt?.bubbles && evt.stopPropagation();
     GM.setClipboard(String(evt?.shiftKey || evt?.ctrlKey ? lastUncompressedCfgString : await compress(JSON.stringify({ formatVersion, data: getFeatures() }), compressionFormat, "string")));
     copiedTextElem.style.display = "inline-block";
@@ -1018,9 +1008,7 @@ async function addExportMenu() {
         copiedTxtTimeout = undefined;
       }, 3000) as unknown as number;
     }
-  };
-  copyBtnElem.addEventListener("click", copyBtnClicked);
-  copyBtnElem.addEventListener("keydown", (e) => e.key === "Enter" && copyBtnClicked(e));
+  });
 
   // flex-direction is row-reverse
   footerElem.appendChild(copyBtnElem);
@@ -1142,12 +1130,10 @@ async function addImportMenu() {
   closeElem.tabIndex = 0;
   closeElem.src = await getResourceUrl("img-close");
   closeElem.ariaLabel = closeElem.title = t("close_menu_tooltip");
-  const closeImportMenuClicked = (e: MouseEvent | KeyboardEvent) => {
+  onInteraction(closeElem, (e: MouseEvent | KeyboardEvent) => {
     closeImportMenu(e);
     openCfgMenu();
-  };
-  closeElem.addEventListener("click", closeImportMenuClicked);
-  closeElem.addEventListener("keydown", (e) => e.key === "Enter" && closeImportMenuClicked(e));
+  });
 
   titleCont.appendChild(titleElem);
 
@@ -1356,13 +1342,11 @@ async function addChangelogMenu() {
   closeElem.tabIndex = 0;
   closeElem.src = await getResourceUrl("img-close");
   closeElem.ariaLabel = closeElem.title = t("close_menu_tooltip");
-  const closeChangelogMenuClicked = (e: MouseEvent | KeyboardEvent) => {
+  onInteraction(closeElem, (e: MouseEvent | KeyboardEvent) => {
     closeChangelogMenu(e);
     if(menuBgElem.dataset.returnTo === "cfgMenu")
       openCfgMenu();
-  };
-  closeElem.addEventListener("click", closeChangelogMenuClicked);
-  closeElem.addEventListener("keydown", (e) => e.key === "Enter" && closeChangelogMenuClicked(e));
+  });
 
   titleCont.appendChild(titleElem);