Browse Source

feat: arrow key volume change

Sv443 2 days ago
parent
commit
6abc474978
1 changed files with 35 additions and 73 deletions
  1. 35 73
      src/features/input.ts

+ 35 - 73
src/features/input.ts

@@ -1,7 +1,6 @@
 import { DataStore, clamp, compress, decompress } from "@sv443-network/userutils";
-import { error, getVideoTime, info, log, warn, getDomain, compressionSupported, t, clearNode, resourceAsString, getCurrentChannelId, getCurrentMediaType, sanitizeChannelId, addStyleFromResource, isValidChannelId, getVideoElement, setInnerHtml } from "../utils/index.js";
-import type { AutoLikeData, Domain } from "../types.js";
-import { enableDiscardBeforeUnload } from "./behavior.js";
+import { error, info, log, warn, getDomain, compressionSupported, t, clearNode, resourceAsString, getCurrentChannelId, getCurrentMediaType, sanitizeChannelId, addStyleFromResource, isValidChannelId, getVideoElement, setInnerHtml } from "../utils/index.js";
+import type { AutoLikeData } from "../types.js";
 import { emitSiteEvent, siteEvents } from "../siteEvents.js";
 import { featInfo } from "./index.js";
 import { getFeature } from "../config.js";
@@ -17,11 +16,20 @@ export const inputIgnoreTagNames = ["INPUT", "TEXTAREA", "SELECT", "BUTTON", "A"
 
 //#region arrow key skip
 
+let sliderEl: HTMLInputElement | undefined;
+
 export async function initArrowKeySkip() {
+  addSelectorListener<HTMLInputElement>("playerBarRightControls", "tp-yt-paper-slider#volume-slider", {
+    listener: (el) => sliderEl = el,
+  });
+
   document.addEventListener("keydown", (evt) => {
     if(!getFeature("arrowKeySupport"))
       return;
 
+    if(["ArrowUp", "ArrowDown"].includes(evt.code))
+      return handleVolumeKeyPress(evt);
+
     if(!["ArrowLeft", "ArrowRight"].includes(evt.code))
       return;
 
@@ -52,6 +60,30 @@ export async function initArrowKeySkip() {
   log("Added arrow key press listener");
 }
 
+function handleVolumeKeyPress(evt: KeyboardEvent) {
+  evt.preventDefault();
+  evt.stopImmediatePropagation();
+
+  if(!sliderEl || !getVideoElement())
+    return warn("Couldn't find video or volume slider element, so the keypress is ignored");
+
+  const step = Number(sliderEl.step);
+  const newVol = clamp(
+    Number(sliderEl.value)
+      + (evt.code === "ArrowUp" ? 1 : -1)
+      * clamp((getFeature("arrowKeyVolumeStep") ?? featInfo.arrowKeyVolumeStep.default), isNaN(step) ? 5 : step, 100),
+    0,
+    100,
+  );
+
+  if(newVol !== Number(sliderEl.value)) {
+    sliderEl.value = String(newVol);
+    sliderEl.dispatchEvent(new Event("change", { bubbles: true }));
+
+    log(`Captured key '${evt.code}' - changed volume to ${newVol}%`);
+  }
+}
+
 //#region frame skip
 
 /** Initializes the feature that lets users skip by a frame with the period and comma keys while the video is paused */
@@ -82,76 +114,6 @@ export async function initFrameSkip() {
   log("Added frame skip key press listener");
 }
 
-//#region site switch
-
-/** switch sites only if current video time is greater than this value */
-const videoTimeThreshold = 3;
-let siteSwitchEnabled = true;
-
-/** Initializes the site switch feature */
-export async function initSiteSwitch(domain: Domain) {
-  document.addEventListener("keydown", (e) => {
-    if(!getFeature("switchBetweenSites"))
-      return;
-    if(inputIgnoreTagNames.includes(document.activeElement?.tagName ?? ""))
-      return;
-    const hk = getFeature("switchSitesHotkey");
-    if(siteSwitchEnabled && e.code === hk.code && e.shiftKey === hk.shift && e.ctrlKey === hk.ctrl && e.altKey === hk.alt)
-      switchSite(domain === "yt" ? "ytm" : "yt");
-  });
-  siteEvents.on("hotkeyInputActive", (state) => {
-    if(!getFeature("switchBetweenSites"))
-      return;
-    siteSwitchEnabled = !state;
-  });
-  log("Initialized site switch listener");
-}
-
-/** Switches to the other site (between YT and YTM) */
-async function switchSite(newDomain: Domain) {
-  try {
-    if(!(["/watch", "/playlist"].some(v => location.pathname.startsWith(v))))
-      return warn("Not on a supported page, so the site switch is ignored");
-
-    let subdomain;
-    if(newDomain === "ytm")
-      subdomain = "music";
-    else if(newDomain === "yt")
-      subdomain = "www";
-
-    if(!subdomain)
-      throw new Error(`Unrecognized domain '${newDomain}'`);
-
-    enableDiscardBeforeUnload();
-
-    const { pathname, search, hash } = new URL(location.href);
-
-    const vt = await getVideoTime(0);
-
-    log(`Found video time of ${vt} seconds`);
-
-    const cleanSearch = search.split("&")
-      .filter((param) => !param.match(/^\??(t|time_continue)=/))
-      .join("&");
-
-    const newSearch = typeof vt === "number" && vt > videoTimeThreshold ?
-      cleanSearch.includes("?")
-        ? `${cleanSearch.startsWith("?")
-          ? cleanSearch
-          : "?" + cleanSearch
-        }&time_continue=${vt}`
-        : `?time_continue=${vt}`
-      : cleanSearch;
-    const newUrl = `https://${subdomain}.youtube.com${pathname}${newSearch}${hash}`;
-
-    info(`Switching to domain '${newDomain}' at ${newUrl}`);
-    location.assign(newUrl);
-  }
-  catch(err) {
-    error("Error while switching site:", err);
-  }
-}
-
 //#region num keys skip
 
 const numKeysIgnoreTagNames = [...inputIgnoreTagNames];