Ver código fonte

feat: add sub-second precision when restoring song time

Sv443 1 ano atrás
pai
commit
ba358532ed
4 arquivos alterados com 25 adições e 15 exclusões
  1. 8 5
      contributing.md
  2. 11 5
      src/features/behavior.ts
  3. 1 1
      src/features/input.ts
  4. 5 4
      src/utils/dom.ts

+ 8 - 5
contributing.md

@@ -490,20 +490,23 @@ The usage and example blocks on each are written in TypeScript but can be used i
 > #### getVideoTime()
 > Usage:  
 > ```ts
-> unsafeWindow.BYTM.getVideoTime(): Promise<number | null>
+> unsafeWindow.BYTM.getVideoTime(precision?: number): Promise<number | null>
 > ```
 >   
 > Description:  
-> Returns the current video time (on both YT and YTM).  
-> In case it can't be determined on YT, mouse movement is simulated to bring up the video time element and read it.  
-> In order for that edge case not to throw an error, the function would need to be called in response to a user interaction event (e.g. click) due to the strict automated interaction policy in browsers.  
+> Returns the current video time in seconds, with the given `precision` (2 decimal digits by default).  
+> Rounds down if the precision is set to 0. The maximum average available precision on YTM is 6.  
+>   
+> In case the time can't be determined on YT, mouse movement is simulated to bring up the video time element and read it.  
+> In order for that edge case not to throw an error, the function would need to be called in response to a user interaction event (e.g. click) due to the strict automated interaction policy in browsers, otherwise an error can be thrown.  
 > Resolves with a number of seconds or `null` if the time couldn't be determined.  
 >   
 > <details><summary><b>Example <i>(click to expand)</i></b></summary>
 > 
 > ```ts
 > try {
->   const videoTime = await unsafeWindow.BYTM.getVideoTime();
+>   // get the video time with 3 decimal digits
+>   const videoTime = await unsafeWindow.BYTM.getVideoTime(3);
 >   console.log(`The video time is ${videoTime}s`);
 > }
 > catch(err) {

+ 11 - 5
src/features/behavior.ts

@@ -120,11 +120,17 @@ async function restoreSongTime() {
       else {
         if(isNaN(entry.songTime))
           return;
-        const vidElem = await waitVideoElementReady();
-        const vidRestoreTime = entry.songTime - (getFeatures().rememberSongTimeReduction ?? 0);
-        vidElem.currentTime = clamp(Math.max(vidRestoreTime, 0), 0, vidElem.duration);
-        await delRemSongData(entry.watchID);
-        info(`Restored song time to ${Math.floor(vidRestoreTime / 60)}m, ${(vidRestoreTime % 60).toFixed(1)}s`, LogLevel.Info);
+        const doRestoreTime = async () => {
+          const vidElem = await waitVideoElementReady();
+          const vidRestoreTime = entry.songTime - (getFeatures().rememberSongTimeReduction ?? 0);
+          vidElem.currentTime = clamp(Math.max(vidRestoreTime, 0), 0, vidElem.duration);
+          await delRemSongData(entry.watchID);
+          info(`Restored song time to ${Math.floor(vidRestoreTime / 60)}m, ${(vidRestoreTime % 60).toFixed(1)}s`, LogLevel.Info);
+        };
+        if(!domLoaded)
+          document.addEventListener("DOMContentLoaded", doRestoreTime);
+        else
+          doRestoreTime();
       }
     }
   }

+ 1 - 1
src/features/input.ts

@@ -81,7 +81,7 @@ async function switchSite(newDomain: Domain) {
 
     const { pathname, search, hash } = new URL(location.href);
 
-    const vt = await getVideoTime();
+    const vt = await getVideoTime(0);
 
     log(`Found video time of ${vt} seconds`);
 

+ 5 - 4
src/utils/dom.ts

@@ -7,11 +7,12 @@ import { addSelectorListener } from "src/observers";
 export const videoSelector = getDomain() === "ytm" ? "ytmusic-player video" : "#player-container ytd-player video";
 
 /**
- * Returns the current video time in seconds  
+ * Returns the current video time in seconds, with the given {@linkcode precision} (2 decimal digits by default).  
+ * Rounds down if the precision is set to 0. The maximum average available precision on YTM is 6.  
  * Dispatches mouse movement events in case the video time can't be read from the video or progress bar elements (needs a prior user interaction to work)
  * @returns Returns null if the video time is unavailable or no user interaction has happened prior to calling in case of the fallback behavior being used
  */
-export function getVideoTime() {
+export function getVideoTime(precision = 2) {
   return new Promise<number | null>(async (res) => {
     const domain = getDomain();
 
@@ -21,7 +22,7 @@ export function getVideoTime() {
       if(domain === "ytm") {
         const vidElem = document.querySelector<HTMLVideoElement>(videoSelector);
         if(vidElem)
-          return res(Math.floor(vidElem.currentTime));
+          return res(Number(precision <= 0 ? Math.floor(vidElem.currentTime) : vidElem.currentTime.toFixed(precision)));
 
         addSelectorListener<HTMLProgressElement>("playerBar", "tp-yt-paper-slider#progress-bar tp-yt-paper-progress#sliderBar", {
           listener: (pbEl) =>
@@ -31,7 +32,7 @@ export function getVideoTime() {
       else if(domain === "yt") {
         const vidElem = document.querySelector<HTMLVideoElement>(videoSelector);
         if(vidElem)
-          return res(Math.floor(vidElem.currentTime));
+          return res(Number(precision <= 0 ? Math.floor(vidElem.currentTime) : vidElem.currentTime.toFixed(precision)));
 
         // YT doesn't update the progress bar when it's hidden (contrary to YTM which never hides it)
         ytForceShowVideoTime();