Ver código fonte

feat: expose `getVideoElement()` and `getVideoSelector()` on interface

Sv443 5 meses atrás
pai
commit
3c03dc371f
4 arquivos alterados com 65 adições e 20 exclusões
  1. 5 2
      changelog.md
  2. 49 6
      contributing.md
  3. 4 9
      src/interface.ts
  4. 7 3
      src/types.ts

+ 5 - 2
changelog.md

@@ -10,8 +10,11 @@
 <details><summary>Click to expand internal and plugin changes</summary>
 
 - **Plugin Changes:**
-  - Added authenticated function `reloadTab()` to keep video time and volume and disable BYTM features like initial tab volume
-  - Exposed the constants `initialParams` (initial URLParams object) and `sessionStorageAvailable` (bool) on the BYTM API
+  - Added functions to the BYTM API:
+    - `reloadTab()` to reload the page while keeping video time and volume and disable BYTM features like initial tab volume
+    - `getVideoElement()` to get the video element (if available) on the current page, on both YT and YTM
+    - `getVideoSelector()` to get the CSS selector for the video element on the current page, on both YT and YTM
+  - Exposed the constants `initialParams` (URLSearchParams, the search params at the initial point of loading BYTM) and `sessionStorageAvailable` (boolean) on the BYTM API
 
 </details>
 

+ 49 - 6
contributing.md

@@ -417,7 +417,7 @@ The usage and example blocks on each are written in TypeScript but can be used i
   - [getDomain()](#getdomain) - Returns the current domain of the page as a constant string (either "yt" or "ytm")
   - [getResourceUrl()](#getresourceurl) - Returns a `blob:` URL provided by the local userscript extension for the specified BYTM resource file
   - [getSessionId()](#getsessionid) - Returns the unique session ID that is generated on every started session
-  - [reloadTab()](#reloadtab) 🔒 - Reloads the current tab while preserving video time and volume and making features like initial tab volume lower priority
+  - [reloadTab()](#reloadtab) - Reloads the current tab while preserving video time and volume and making features like initial tab volume lower priority
 - DOM:
   - [BytmDialog](#bytmdialog) - A class for creating and managing modal, fully customizable dialogs
   - [ExImDialog](#eximdialog) - Subclass of BytmDialog for allowing users to export and import serializable data
@@ -429,6 +429,8 @@ The usage and example blocks on each are written in TypeScript but can be used i
   - [getThumbnailUrl()](#getthumbnailurl) - Returns the URL to the thumbnail of the currently playing video
   - [getBestThumbnailUrl()](#getbestthumbnailurl) - Returns the URL to the best quality thumbnail of the currently playing video
   - [waitVideoElementReady()](#waitvideoelementready) - Waits for the video element to be queryable in the DOM - has to be called after `bytm:observersReady`
+  - [getVideoElement()](#getvideoelement) - Returns the video element on the current page or null if there is none (on both YT and YTM)
+  - [getVideoSelector()](#getvideoselector) - Returns the CSS selector for the video element (on both YT and YTM)
   - [getCurrentMediaType()](#getcurrentmediatype) - (On YTM only) returns the type of media that is currently playing (either "video" or "song")
 - Components:
   - [createHotkeyInput()](#createhotkeyinput) - Creates a hotkey input element
@@ -708,15 +710,12 @@ The usage and example blocks on each are written in TypeScript but can be used i
 > ### reloadTab()
 > Usage:
 > ```ts
-> unsafeWindow.BYTM.reloadTab(token: string | undefined): Promise<void>
+> unsafeWindow.BYTM.reloadTab(): Promise<void>
 > ```
 >  
 > Description:  
 > Reloads the current tab while preserving video time and volume and making features like initial tab volume lower priority.  
-> The tab will be reloaded, whether the video element is queryable in the DOM or not.  
->   
-> Arguments:  
-> - `token` - The private token that was returned when the plugin was registered (if not provided, the function will always return `undefined`)
+> The tab will be reloaded, whether the video element is queryable in the DOM or not, but without video time and volume restoration in the latter case.
 
 <br>
 
@@ -944,6 +943,50 @@ The usage and example blocks on each are written in TypeScript but can be used i
 
 <br>
 
+> ### getVideoElement()
+> Usage:
+> ```ts
+> unsafeWindow.BYTM.getVideoElement(): HTMLVideoElement | null
+> ```
+>   
+> Description:  
+> Returns the video element on the current page or `null` if there is none.  
+> Works on both YouTube and YouTube Music.  
+> 
+> <details><summary><b>Example <i>(click to expand)</i></b></summary>
+> 
+> ```ts
+> // get the current video time and volume:
+> const { currentTime, volume } = unsafeWindow.BYTM.getVideoElement();
+> console.log("Video time:", currentTime, "Video volume:", volume);
+> ```
+> </details>
+
+<br>
+
+> ### getVideoSelector()
+> Usage:
+> ```ts
+> unsafeWindow.BYTM.getVideoSelector(): string
+> ```
+>   
+> Description:  
+> Returns the CSS selector for the video element on the current page.  
+> Works on both YouTube and YouTube Music.  
+> 
+> <details><summary><b>Example <i>(click to expand)</i></b></summary>
+> 
+> ```ts
+> // add CSS to an element that exists within the video element on both YT and YTM:
+> const videoSelector = unsafeWindow.BYTM.getVideoSelector();
+> const css = `${videoSelector} #my-element { border: 2px solid red; }`;
+> const styleElem = unsafeWindow.BYTM.UserUtils.addGlobalStyle(css);
+> styleElem.id = "my-element-style";
+> ```
+> </details>
+
+<br>
+
 > ### getCurrentMediaType()
 > Usage:  
 > ```ts

+ 4 - 9
src/interface.ts

@@ -1,7 +1,7 @@
 import * as UserUtils from "@sv443-network/userutils";
 import * as compareVersions from "compare-versions";
 import { mode, branch, host, buildNumber, compressionFormat, scriptInfo, initialParams, sessionStorageAvailable } from "./constants.js";
-import { getDomain, waitVideoElementReady, getResourceUrl, getSessionId, getVideoTime, log, setLocale, getLocale, hasKey, hasKeyFor, t, tp, type TrLocale, info, error, onInteraction, getThumbnailUrl, getBestThumbnailUrl, fetchVideoVotes, setInnerHtml, getCurrentMediaType, tl, tlp, PluginError, formatNumber, reloadTab } from "./utils/index.js";
+import { getDomain, waitVideoElementReady, getResourceUrl, getSessionId, getVideoTime, log, setLocale, getLocale, hasKey, hasKeyFor, t, tp, type TrLocale, info, error, onInteraction, getThumbnailUrl, getBestThumbnailUrl, fetchVideoVotes, setInnerHtml, getCurrentMediaType, tl, tlp, PluginError, formatNumber, reloadTab, getVideoElement, getVideoSelector } from "./utils/index.js";
 import { addSelectorListener } from "./observers.js";
 import { getFeatures, setFeatures } from "./config.js";
 import { autoLikeStore, featInfo, fetchLyricsUrlTop, getLyricsCacheEntry, sanitizeArtists, sanitizeSong } from "./features/index.js";
@@ -109,7 +109,7 @@ const globalFuncs: InterfaceFunctions = {
   getDomain,
   getResourceUrl,
   getSessionId,
-  reloadTab: reloadTabInterface,
+  reloadTab,
 
   // dom:
   setInnerHtml,
@@ -119,6 +119,8 @@ const globalFuncs: InterfaceFunctions = {
   getThumbnailUrl,
   getBestThumbnailUrl,
   waitVideoElementReady,
+  getVideoElement,
+  getVideoSelector,
   getCurrentMediaType,
 
   // translations:
@@ -413,13 +415,6 @@ export function resolveToken(token: string | undefined): string | undefined {
 
 //#region proxy funcs
 
-/** Reloads the tab in a smarter way by preserving the current video's time and volume and making features like initial tab volume stand down if called */
-export async function reloadTabInterface(token: string | undefined) {
-  if(resolveToken(token) === undefined)
-    return;
-  return await reloadTab();
-}
-
 /**
  * Sets the new locale on the BYTM interface  
  * This is an authenticated function so you must pass the session- and plugin-unique token, retreived at registration.

+ 7 - 3
src/types.ts

@@ -2,9 +2,9 @@ import type { NanoEmitter, Stringifiable } from "@sv443-network/userutils";
 import type * as consts from "./constants.js";
 import type { scriptInfo } from "./constants.js";
 import type { addSelectorListener } from "./observers.js";
-import type { getResourceUrl, getSessionId, getVideoTime, TrLocale, t, tp, fetchVideoVotes, onInteraction, getThumbnailUrl, getBestThumbnailUrl, getLocale, hasKey, hasKeyFor, getDomain, waitVideoElementReady, setInnerHtml, getCurrentMediaType, tl, tlp, formatNumber } from "./utils/index.js";
+import type { getResourceUrl, getSessionId, getVideoTime, TrLocale, t, tp, fetchVideoVotes, onInteraction, getThumbnailUrl, getBestThumbnailUrl, getLocale, hasKey, hasKeyFor, getDomain, waitVideoElementReady, setInnerHtml, getCurrentMediaType, tl, tlp, formatNumber, getVideoElement, getVideoSelector, reloadTab } from "./utils/index.js";
 import type { SiteEventsMap } from "./siteEvents.js";
-import type { InterfaceEventsMap, getAutoLikeDataInterface, getFeaturesInterface, getPluginInfo, reloadTabInterface, saveAutoLikeDataInterface, saveFeaturesInterface, setLocaleInterface } from "./interface.js";
+import type { InterfaceEventsMap, getAutoLikeDataInterface, getFeaturesInterface, getPluginInfo, saveAutoLikeDataInterface, saveFeaturesInterface, setLocaleInterface } from "./interface.js";
 import type { BytmDialog, ExImDialog, createCircularBtn, createHotkeyInput, createRipple, createToggleInput, showIconToast, showToast } from "./components/index.js";
 import type { fetchLyricsUrlTop, sanitizeArtists, sanitizeSong } from "./features/lyrics.js";
 import type { getLyricsCacheEntry } from "./features/lyricsCache.js";
@@ -288,7 +288,7 @@ export type InterfaceFunctions = {
   /** Returns the unique session ID for the current tab */
   getSessionId: typeof getSessionId;
   /** Smarter version of `location.reload()` that remembers video time and volume and makes other features like initial tab volume stand down if used */
-  reloadTab: typeof reloadTabInterface;
+  reloadTab: typeof reloadTab;
 
   // dom:
   /** Sets the innerHTML property of the provided element to a sanitized version of the provided HTML string */
@@ -309,6 +309,10 @@ export type InterfaceFunctions = {
   getBestThumbnailUrl: typeof getBestThumbnailUrl;
   /** Resolves the returned promise when the video element is queryable in the DOM */
   waitVideoElementReady: typeof waitVideoElementReady;
+  /** Returns the video element on the current page for both YTM and YT - returns null if it couldn't be found */
+  getVideoElement: typeof getVideoElement;
+  /** Returns the CSS selector to the video element for both YTM and YT */
+  getVideoSelector: typeof getVideoSelector;
   /** (On YTM only) returns the current media type (video or song) */
   getCurrentMediaType: typeof getCurrentMediaType;