Browse Source

fix: thumbnail overlay edge case

Sv443 1 year ago
parent
commit
198b18649d
4 changed files with 22 additions and 11 deletions
  1. 7 4
      src/features/layout.ts
  2. 2 2
      src/features/lyrics.ts
  3. 1 4
      src/observers.ts
  4. 12 1
      src/utils/dom.ts

+ 7 - 4
src/features/layout.ts

@@ -2,7 +2,7 @@ import { addParent, autoPlural, debounce, fetchAdvanced, insertAfter, openInNewT
 import { getFeatures } from "../config";
 import { siteEvents } from "../siteEvents";
 import { addSelectorListener } from "../observers";
-import { error, getResourceUrl, log, warn, t, onInteraction, getBestThumbnailUrl, getDomain, addStyle } from "../utils";
+import { error, getResourceUrl, log, warn, t, onInteraction, getBestThumbnailUrl, getDomain, addStyle, currentMediaType, domLoaded, waitVideoElementReady } from "../utils";
 import { scriptInfo } from "../constants";
 import { openCfgMenu } from "../menu/menu_old";
 import { createGenericBtn } from "../components";
@@ -429,6 +429,8 @@ export async function initThumbnailOverlay() {
   if(behavior === "never" && !toggleBtnShown)
     return;
 
+  await waitVideoElementReady();
+
   const playerSelector = "ytmusic-player#player";
   const playerEl = document.querySelector<HTMLElement>(playerSelector);
 
@@ -437,8 +439,11 @@ export async function initThumbnailOverlay() {
 
   /** Checks and updates the overlay and toggle button states based on the current song type (yt video or ytm song) */
   const updateOverlayVisibility = async () => {
+    if(!domLoaded)
+      return;
+
     let showOverlay = behavior === "always";
-    const isVideo = document.querySelector<HTMLElement>("ytmusic-player")?.hasAttribute("video-mode") ?? false;
+    const isVideo = currentMediaType() === "video";
 
     if(behavior === "videosOnly" && isVideo)
       showOverlay = true;
@@ -471,8 +476,6 @@ export async function initThumbnailOverlay() {
     }
   };
 
-  window.addEventListener("bytm:ready", updateOverlayVisibility, { once: true });
-
   const applyThumbUrl = async (watchId: string) => {
     const thumbUrl = await getBestThumbnailUrl(watchId);
     if(thumbUrl) {

+ 2 - 2
src/features/lyrics.ts

@@ -1,6 +1,6 @@
 import { autoPlural, fetchAdvanced, insertAfter } from "@sv443-network/userutils";
 import Fuse from "fuse.js";
-import { constructUrlString, error, getResourceUrl, info, log, warn, t, tp } from "../utils";
+import { constructUrlString, error, getResourceUrl, info, log, warn, t, tp, currentMediaType } from "../utils";
 import { emitInterface } from "../interface";
 import { mode, scriptInfo } from "../constants";
 import { getFeatures } from "../config";
@@ -154,7 +154,7 @@ export function sanitizeArtists(artists: string) {
 export async function getCurrentLyricsUrl() {
   try {
     // In videos the video title contains both artist and song title, in "regular" YTM songs, the video title only contains the song title
-    const isVideo = typeof document.querySelector("ytmusic-player")?.hasAttribute("video-mode");
+    const isVideo = currentMediaType() === "video";
 
     const songTitleElem = document.querySelector<HTMLElement>(".content-info-wrapper > yt-formatted-string");
     const songMetaElem = document.querySelector<HTMLElement>("span.subtitle > yt-formatted-string :first-child");

+ 1 - 4
src/observers.ts

@@ -157,10 +157,7 @@ export function initObservers() {
       });
 
       globservers.playerBar.addListener(playerBarRightControls, {
-        listener: () => {
-          console.log(">> enable playerBarRightControls");
-          globservers.playerBarRightControls.enable();
-        },
+        listener: () => globservers.playerBarRightControls.enable(),
       });
 
       // #SECTION popupContainer = the container for popups (e.g. the queue popup)

+ 12 - 1
src/utils/dom.ts

@@ -102,7 +102,7 @@ function ytForceShowVideoTime() {
   return true;
 }
 
-/** Waits for the video element to be in its readyState 4 / canplay state and returns it */
+/** Waits for the video element to be in its readyState 4 / canplay state and returns it - resolves immediately if the video is already ready */
 export function waitVideoElementReady(): Promise<HTMLVideoElement> {
   return new Promise((res) => {
     addSelectorListener<HTMLVideoElement>("body", videoSelector, {
@@ -168,3 +168,14 @@ export function addStyle(css: string, ref?: string) {
   elem.id = `bytm-global-style-${ref ?? randomId(5, 36)}`;
   return elem;
 }
+
+/**
+ * Checks if the currently playing media is a song or a video.  
+ * This function should only be called after awaiting `waitVideoElementReady()`!
+ */
+export function currentMediaType(): "video" | "song" {
+  const songImgElem = document.querySelector("ytmusic-player #song-image");
+  if(!songImgElem)
+    throw new Error("Couldn't find the song image element. Use this function only after `await waitVideoElementReady()`!");
+  return getUnsafeWindow().getComputedStyle(songImgElem).display !== "none" ? "song" : "video";
+}