瀏覽代碼

fix: thumbnail overlay race condition

Sv443 11 月之前
父節點
當前提交
87f70a384e

+ 21 - 14
assets/translations/README.md

@@ -17,14 +17,14 @@ To submit or edit a translation, please follow [this guide](../../contributing.m
 |   | Locale | Translated keys | Based on |
 | :----: | ------ | --------------- | :------: |
 | ─ | [`en_US`](./en_US.json) | 213 (default locale) |  |
-| ⚠ | [`de_DE`](./de_DE.json) | `210/213` (98.6%) | ─ |
+| ⚠ | [`de_DE`](./de_DE.json) | `209/213` (98.1%) | ─ |
 | ─ | [`en_UK`](./en_UK.json) | `213/213` (100%) | `en_US` |
-| ⚠ | [`es_ES`](./es_ES.json) | `210/213` (98.6%) | ─ |
-| ⚠ | [`fr_FR`](./fr_FR.json) | `210/213` (98.6%) | ─ |
-| ⚠ | [`hi_IN`](./hi_IN.json) | `210/213` (98.6%) | ─ |
-| ⚠ | [`ja_JA`](./ja_JA.json) | `210/213` (98.6%) | ─ |
-| ⚠ | [`pt_BR`](./pt_BR.json) | `210/213` (98.6%) | ─ |
-| ⚠ | [`zh_CN`](./zh_CN.json) | `210/213` (98.6%) | ─ |
+| ⚠ | [`es_ES`](./es_ES.json) | `209/213` (98.1%) | ─ |
+| ⚠ | [`fr_FR`](./fr_FR.json) | `209/213` (98.1%) | ─ |
+| ⚠ | [`hi_IN`](./hi_IN.json) | `209/213` (98.1%) | ─ |
+| ⚠ | [`ja_JA`](./ja_JA.json) | `209/213` (98.1%) | ─ |
+| ⚠ | [`pt_BR`](./pt_BR.json) | `209/213` (98.1%) | ─ |
+| ⚠ | [`zh_CN`](./zh_CN.json) | `209/213` (98.1%) | ─ |
 
 <sub>
 ✅ - Fully translated
@@ -45,72 +45,79 @@ This means to figure out which keys are untranslated, you will need to manually
 
 ### Missing keys:
 
-<details><summary><code>de_DE</code> - 3 missing keys <i>(click to show)</i></summary><br>
+<details><summary><code>de_DE</code> - 4 missing keys <i>(click to show)</i></summary><br>
 
 | Key | English text |
 | --- | ------------ |
 | `site_selection_none` | `None (disabled)` |
 | `feature_desc_disableDarkReaderSites` | `On which sites should the Dark Reader extension be disabled to fix layout issues?` |
 | `feature_helptext_disableDarkReaderSites` | `The Dark Reader extension can cause issues with the layout of the site.\nThis feature allows you to disable Dark Reader on certain or all sites to prevent those issues.\nIf the extension is not installed, this feature will have no effect and can be left activated.` |
+| `feature_helptext_lyricsCacheMaxSize` | `The lyrics of songs you listen to are stored in a cache to reduce the amount of requests to the lyrics provider.\nThis feature allows you to set the maximum amount of lyrics to keep in the cache.\nWhen the limit is reached, the oldest entry will be removed to make space for any new ones.` |
 
 <br></details>
 
-<details><summary><code>es_ES</code> - 3 missing keys <i>(click to show)</i></summary><br>
+<details><summary><code>es_ES</code> - 4 missing keys <i>(click to show)</i></summary><br>
 
 | Key | English text |
 | --- | ------------ |
 | `site_selection_none` | `None (disabled)` |
 | `feature_desc_disableDarkReaderSites` | `On which sites should the Dark Reader extension be disabled to fix layout issues?` |
 | `feature_helptext_disableDarkReaderSites` | `The Dark Reader extension can cause issues with the layout of the site.\nThis feature allows you to disable Dark Reader on certain or all sites to prevent those issues.\nIf the extension is not installed, this feature will have no effect and can be left activated.` |
+| `feature_helptext_lyricsCacheMaxSize` | `The lyrics of songs you listen to are stored in a cache to reduce the amount of requests to the lyrics provider.\nThis feature allows you to set the maximum amount of lyrics to keep in the cache.\nWhen the limit is reached, the oldest entry will be removed to make space for any new ones.` |
 
 <br></details>
 
-<details><summary><code>fr_FR</code> - 3 missing keys <i>(click to show)</i></summary><br>
+<details><summary><code>fr_FR</code> - 4 missing keys <i>(click to show)</i></summary><br>
 
 | Key | English text |
 | --- | ------------ |
 | `site_selection_none` | `None (disabled)` |
 | `feature_desc_disableDarkReaderSites` | `On which sites should the Dark Reader extension be disabled to fix layout issues?` |
 | `feature_helptext_disableDarkReaderSites` | `The Dark Reader extension can cause issues with the layout of the site.\nThis feature allows you to disable Dark Reader on certain or all sites to prevent those issues.\nIf the extension is not installed, this feature will have no effect and can be left activated.` |
+| `feature_helptext_lyricsCacheMaxSize` | `The lyrics of songs you listen to are stored in a cache to reduce the amount of requests to the lyrics provider.\nThis feature allows you to set the maximum amount of lyrics to keep in the cache.\nWhen the limit is reached, the oldest entry will be removed to make space for any new ones.` |
 
 <br></details>
 
-<details><summary><code>hi_IN</code> - 3 missing keys <i>(click to show)</i></summary><br>
+<details><summary><code>hi_IN</code> - 4 missing keys <i>(click to show)</i></summary><br>
 
 | Key | English text |
 | --- | ------------ |
 | `site_selection_none` | `None (disabled)` |
 | `feature_desc_disableDarkReaderSites` | `On which sites should the Dark Reader extension be disabled to fix layout issues?` |
 | `feature_helptext_disableDarkReaderSites` | `The Dark Reader extension can cause issues with the layout of the site.\nThis feature allows you to disable Dark Reader on certain or all sites to prevent those issues.\nIf the extension is not installed, this feature will have no effect and can be left activated.` |
+| `feature_helptext_lyricsCacheMaxSize` | `The lyrics of songs you listen to are stored in a cache to reduce the amount of requests to the lyrics provider.\nThis feature allows you to set the maximum amount of lyrics to keep in the cache.\nWhen the limit is reached, the oldest entry will be removed to make space for any new ones.` |
 
 <br></details>
 
-<details><summary><code>ja_JA</code> - 3 missing keys <i>(click to show)</i></summary><br>
+<details><summary><code>ja_JA</code> - 4 missing keys <i>(click to show)</i></summary><br>
 
 | Key | English text |
 | --- | ------------ |
 | `site_selection_none` | `None (disabled)` |
 | `feature_desc_disableDarkReaderSites` | `On which sites should the Dark Reader extension be disabled to fix layout issues?` |
 | `feature_helptext_disableDarkReaderSites` | `The Dark Reader extension can cause issues with the layout of the site.\nThis feature allows you to disable Dark Reader on certain or all sites to prevent those issues.\nIf the extension is not installed, this feature will have no effect and can be left activated.` |
+| `feature_helptext_lyricsCacheMaxSize` | `The lyrics of songs you listen to are stored in a cache to reduce the amount of requests to the lyrics provider.\nThis feature allows you to set the maximum amount of lyrics to keep in the cache.\nWhen the limit is reached, the oldest entry will be removed to make space for any new ones.` |
 
 <br></details>
 
-<details><summary><code>pt_BR</code> - 3 missing keys <i>(click to show)</i></summary><br>
+<details><summary><code>pt_BR</code> - 4 missing keys <i>(click to show)</i></summary><br>
 
 | Key | English text |
 | --- | ------------ |
 | `site_selection_none` | `None (disabled)` |
 | `feature_desc_disableDarkReaderSites` | `On which sites should the Dark Reader extension be disabled to fix layout issues?` |
 | `feature_helptext_disableDarkReaderSites` | `The Dark Reader extension can cause issues with the layout of the site.\nThis feature allows you to disable Dark Reader on certain or all sites to prevent those issues.\nIf the extension is not installed, this feature will have no effect and can be left activated.` |
+| `feature_helptext_lyricsCacheMaxSize` | `The lyrics of songs you listen to are stored in a cache to reduce the amount of requests to the lyrics provider.\nThis feature allows you to set the maximum amount of lyrics to keep in the cache.\nWhen the limit is reached, the oldest entry will be removed to make space for any new ones.` |
 
 <br></details>
 
-<details><summary><code>zh_CN</code> - 3 missing keys <i>(click to show)</i></summary><br>
+<details><summary><code>zh_CN</code> - 4 missing keys <i>(click to show)</i></summary><br>
 
 | Key | English text |
 | --- | ------------ |
 | `site_selection_none` | `None (disabled)` |
 | `feature_desc_disableDarkReaderSites` | `On which sites should the Dark Reader extension be disabled to fix layout issues?` |
 | `feature_helptext_disableDarkReaderSites` | `The Dark Reader extension can cause issues with the layout of the site.\nThis feature allows you to disable Dark Reader on certain or all sites to prevent those issues.\nIf the extension is not installed, this feature will have no effect and can be left activated.` |
+| `feature_helptext_lyricsCacheMaxSize` | `The lyrics of songs you listen to are stored in a cache to reduce the amount of requests to the lyrics provider.\nThis feature allows you to set the maximum amount of lyrics to keep in the cache.\nWhen the limit is reached, the oldest entry will be removed to make space for any new ones.` |
 
 <br></details>

+ 0 - 1
assets/translations/de_DE.json

@@ -206,7 +206,6 @@
     "feature_desc_geniUrlToken": "Auth Token deiner geniURL Instanz",
     "feature_helptext_geniUrlToken": "Um das Rate Limiting zu umgehen, kannst du eine Auth Token angeben, das auch in der .env Datei deiner geniURL Instanz definiert ist",
     "feature_desc_lyricsCacheMaxSize": "Maximale Anzahl an Songtexten, die im Cache gespeichert werden sollen",
-    "feature_helptext_lyricsCacheMaxSize": "Die Songtexte der Songs, die du hörst, werden im Cache gespeichert, um die Anzahl der Anfragen an den Songtext-Provider zu reduzieren.\nDiese Funktion ermöglicht es dir, die maximale Anzahl an Songtexten festzulegen, die im Cache gespeichert werden sollen.\nWenn das Limit erreicht ist, wird der Eintrag, der zuletzt verwendet wurde, entfernt, um Platz für neue zu schaffen.",
     "feature_desc_lyricsCacheTTL": "Maximale Anzahl an Tagen, die ein Songtext-Eintrag im Cache bleiben soll",
     "feature_helptext_lyricsCacheTTL": "Der Cache, in dem die Songtexte gespeichert sind, löscht sie automatisch nach dieser Zeit, um sicherzustellen, dass Aktualisierungen der Quelle früher oder später abgerufen werden.\nWenn du sicherstellen möchtest, dass du immer die aktuellsten Songtexte hast, setze diesen Wert auf einen niedrigen Wert wie 4 Tage.",
     "feature_desc_clearLyricsCache": "Lösche den Songtext-Cache manuell",

+ 1 - 1
assets/translations/en_US.json

@@ -209,7 +209,7 @@
     "feature_desc_geniUrlToken": "Auth token for your geniURL instance",
     "feature_helptext_geniUrlToken": "To bypass rate limiting, you can provide an auth token that is also defined in the .env file of your geniURL instance",
     "feature_desc_lyricsCacheMaxSize": "Maximum amount of lyrics to keep in the cache",
-    "feature_helptext_lyricsCacheMaxSize": "The lyrics of songs you listen to are stored in a cache to reduce the amount of requests to the lyrics provider.\nThis feature allows you to set the maximum amount of lyrics to keep in the cache.\nWhen the limit is reached, the entry that was used last will be removed to make space for any new ones.",
+    "feature_helptext_lyricsCacheMaxSize": "The lyrics of songs you listen to are stored in a cache to reduce the amount of requests to the lyrics provider.\nThis feature allows you to set the maximum amount of lyrics to keep in the cache.\nWhen the limit is reached, the oldest entry will be removed to make space for any new ones.",
     "feature_desc_lyricsCacheTTL": "Max amount of days to keep a lyrics entry in the cache",
     "feature_helptext_lyricsCacheTTL": "The cache that lyrics are stored in will automatically delete them after this amount of time to ensure that updates to the source are being fetched sooner or later.\nIf you wanna make sure that you always have the most recent lyrics, set this to a low value like 4 days.",
     "feature_desc_clearLyricsCache": "Clear the lyrics cache manually",

+ 0 - 1
assets/translations/es_ES.json

@@ -206,7 +206,6 @@
     "feature_desc_geniUrlToken": "Token de autenticación para su instancia de geniURL",
     "feature_helptext_geniUrlToken": "Para evitar la limitación de velocidad, puede proporcionar un token de autenticación que también está definido en el archivo .env de su instancia de geniURL",
     "feature_desc_lyricsCacheMaxSize": "Cantidad máxima de letras para mantener en la caché",
-    "feature_helptext_lyricsCacheMaxSize": "Las letras de las canciones que escuchas se almacenan en una caché para reducir la cantidad de solicitudes al proveedor de letras.\nEsta función le permite establecer la cantidad máxima de letras para mantener en la caché.\nCuando se alcanza el límite, la entrada que se usó por última vez se eliminará para dejar espacio para cualquier nueva.",
     "feature_desc_lyricsCacheTTL": "Cantidad máxima de días para mantener una entrada de letras en la caché",
     "feature_helptext_lyricsCacheTTL": "La caché en la que se almacenan las letras eliminará automáticamente las entradas después de este tiempo para asegurarse de que las actualizaciones de la fuente se estén obteniendo más temprano o más tarde.\nSi quieres asegurarte de que siempre tienes las letras más recientes, establece esto en un valor bajo como 4 días.",
     "feature_desc_clearLyricsCache": "Borrar la caché de letras manualmente",

+ 0 - 1
assets/translations/fr_FR.json

@@ -206,7 +206,6 @@
     "feature_desc_geniUrlToken": "Jeton d'authentification pour votre instance geniURL",
     "feature_helptext_geniUrlToken": "Pour contourner la limitation du taux, vous pouvez fournir un jeton d'authentification qui est également défini dans le fichier .env de votre instance geniURL",
     "feature_desc_lyricsCacheMaxSize": "Quantité maximale de paroles à conserver dans le cache",
-    "feature_helptext_lyricsCacheMaxSize": "Les paroles des chansons que vous écoutez sont stockées dans un cache pour réduire le nombre de requêtes au fournisseur de paroles.\nCette fonctionnalité vous permet de définir la quantité maximale de paroles",
     "feature_desc_lyricsCacheTTL": "Quantité maximale de jours pour conserver une entrée de paroles dans le cache",
     "feature_helptext_lyricsCacheTTL": "Le cache dans lequel les paroles sont stockées les supprimera automatiquement après ce laps de temps pour garantir que les mises à jour de la source sont récupérées tôt ou tard.\nSi vous voulez vous assurer d'avoir toujours les paroles les plus récentes, définissez cette valeur sur une faible comme 4 jours.",
     "feature_desc_clearLyricsCache": "Vider le cache des paroles manuellement",

+ 0 - 1
assets/translations/hi_IN.json

@@ -206,7 +206,6 @@
     "feature_desc_geniUrlToken": "आपके geniURL इंस्टेंस के लिए एक ऑथ टोकन",
     "feature_helptext_geniUrlToken": "रेट लिमिटिंग को छोड़ने के लिए, आप एक ऑथ टोकन दे सकते हैं जो आपके geniURL इंस्टेंस के .env फ़ाइल में भी परिभाषित है",
     "feature_desc_lyricsCacheMaxSize": "कैश में रखने के लिए बोलों की अधिकतम संख्या",
-    "feature_helptext_lyricsCacheMaxSize": "आपके द्वारा सुने गए गीतों के बोल कैश में रखे जाते हैं ताकि बोल प्रदाता को अनुरोधों की संख्या कम करने के लिए।\nयह सुविधा आपको कैश में रखने की अधिकतम संख्या को सेट करने की अनुमति देती है।\nजब सीमा पूरी हो जाती है, तो नये बोलों के लिए जगह बनाने के लिए उस एंट्री को हटा दिया जाएगा जिसे अंतिम बार इस्तेमाल किया गया था।",
     "feature_desc_lyricsCacheTTL": "कैश में बोलों को रखने के लिए अधिकतम दिनों की संख्या",
     "feature_helptext_lyricsCacheTTL": "बोलों को रखने के लिए उन्हें इस समय के बाद स्वचालित रूप से हटा दिया जाएगा ताकि स्रोत के अपडेट को निश्चित किया जा सके।\nयदि आप चाहते हैं कि आपके पास हमेशा सबसे हाल के बोल हों, तो इसे 4 दिन जैसे कम समय के लिए सेट करें।",
     "feature_desc_clearLyricsCache": "बोलों कैश को मैन्युअल रूप से साफ़ करें",

+ 0 - 1
assets/translations/ja_JA.json

@@ -206,7 +206,6 @@
     "feature_desc_geniUrlToken": "geniURL インスタンスの認証トークン",
     "feature_helptext_geniUrlToken": "レート制限をバイパスするために、geniURL インスタンスの .env ファイルで定義されている認証トークンを提供することができます。",
     "feature_desc_lyricsCacheMaxSize": "キャッシュに保持する歌詞の最大量",
-    "feature_helptext_lyricsCacheMaxSize": "聞いた曲の歌詞はキャッシュに保存され、歌詞プロバイダへのリクエストの量を減らします。\nこの機能を使用すると、キャッシュに保持する歌詞の最大量を設定できます。\n限界に達すると、最後に使用されたエントリが新しいエントリのためにスペースを確保するために削除されます。",
     "feature_desc_lyricsCacheTTL": "キャッシュに歌詞エントリを保持する最大日数",
     "feature_helptext_lyricsCacheTTL": "歌詞はキャッシュに保存され、更新された歌詞を取得するために定期的に削除されます。\n常に最新の歌詞を持っていたい場合は、4 日などの低い値に設定してください。",
     "feature_desc_clearLyricsCache": "歌詞キャッシュを手動でクリアする",

+ 0 - 1
assets/translations/pt_BR.json

@@ -206,7 +206,6 @@
     "feature_desc_geniUrlToken": "Token de autenticação para sua instância geniURL",
     "feature_helptext_geniUrlToken": "Para evitar limites de taxa, você pode fornecer um token de autenticação que também está definido no arquivo .env de sua instância geniURL",
     "feature_desc_lyricsCacheMaxSize": "Quantidade máxima de letras para manter no cache",
-    "feature_helptext_lyricsCacheMaxSize": "As letras das músicas que você ouve são armazenadas em um cache para reduzir a quantidade de solicitações ao provedor de letras.\nEste recurso permite que você defina a quantidade máxima de letras a serem mantidas no cache.\nQuando o limite é atingido, a entrada que foi usada por último será removida para dar espaço a novas.",
     "feature_desc_lyricsCacheTTL": "Quantidade máxima de dias para manter uma entrada de letras no cache",
     "feature_helptext_lyricsCacheTTL": "O cache que as letras são armazenadas excluirá automaticamente elas após esse tempo para garantir que as atualizações da fonte sejam buscadas mais cedo ou mais tarde.\nSe você quiser garantir que sempre tenha as letras mais recentes, defina isso para um valor baixo, como 4 dias.",
     "feature_desc_clearLyricsCache": "Limpar o cache de letras manualmente",

+ 0 - 1
assets/translations/zh_CN.json

@@ -206,7 +206,6 @@
     "feature_desc_geniUrlToken": "您的 geniURL 实例的身份验证令牌",
     "feature_helptext_geniUrlToken": "为了绕过速率限制,您可以提供一个身份验证令牌,该令牌也在您的 geniURL 实例的 .env 文件中定义",
     "feature_desc_lyricsCacheMaxSize": "在缓存中保留的歌词的最大数量",
-    "feature_helptext_lyricsCacheMaxSize": "您听的歌曲的歌词存储在缓存中,以减少对歌词提供者的请求。\n此功能允许您设置要在缓存中保留的最大歌词数量。\n当达到限制时,将删除最后使用的条目以为任何新条目腾出空间。",
     "feature_desc_lyricsCacheTTL": "在缓存中保留歌词条目的最大天数",
     "feature_helptext_lyricsCacheTTL": "歌词存储在缓存中,以减少对歌词提供者的请求。\n此功能允许您设置要在缓存中保留的歌词的最大天数。\n如果您想确保始终拥有最新的歌词,请将此设置为较低的值,例如 4 天。",
     "feature_desc_clearLyricsCache": "手动清除歌词缓存",

+ 19 - 12
src/features/layout.ts

@@ -3,7 +3,7 @@ import { getFeatures } from "../config";
 import { siteEvents } from "../siteEvents";
 import { addSelectorListener } from "../observers";
 import { error, getResourceUrl, log, warn, t, onInteraction, openInTab, getBestThumbnailUrl, getDomain, addStyle, currentMediaType, domLoaded, waitVideoElementReady, getVideoTime, fetchCss, addStyleFromResource } from "../utils";
-import { scriptInfo } from "../constants";
+import { currentParams, scriptInfo } from "../constants";
 import { openCfgMenu } from "../menu/menu_old";
 import { createCircularBtn } from "../components";
 import type { ResourceKey } from "../types";
@@ -479,9 +479,7 @@ export async function initThumbnailOverlay() {
     return;
 
   // so the script doesn't wait until a /watch page is loaded
-  (async () => {
-    await waitVideoElementReady();
-
+  waitVideoElementReady().then(() => {
     const playerSelector = "ytmusic-player#player";
     const playerEl = document.querySelector<HTMLElement>(playerSelector);
 
@@ -519,13 +517,16 @@ export async function initThumbnailOverlay() {
       }
 
       if(getFeatures().thumbnailOverlayToggleBtnShown) {
-        const toggleBtnElem = document.querySelector<HTMLImageElement>("#bytm-thumbnail-overlay-toggle");
-        const toggleBtnImgElem = document.querySelector<HTMLImageElement>("#bytm-thumbnail-overlay-toggle > img");
-
-        if(toggleBtnImgElem)
-          toggleBtnImgElem.src = await getResourceUrl(`icon-image${showOverlay ? "_filled" : ""}` as "icon-image" | "icon-image_filled");
-        if(toggleBtnElem)
-          toggleBtnElem.ariaLabel = toggleBtnElem.title = t(`thumbnail_overlay_toggle_btn_tooltip${showOverlay ? "_hide" : "_show"}`);
+        addSelectorListener("playerBarMiddleButtons", "#bytm-thumbnail-overlay-toggle", {
+          async listener(toggleBtnElem) {
+            const toggleBtnImgElem = toggleBtnElem.querySelector<HTMLImageElement>("img");
+
+            if(toggleBtnImgElem)
+              toggleBtnImgElem.src = await getResourceUrl(`icon-image${showOverlay ? "_filled" : ""}` as "icon-image" | "icon-image_filled");
+            if(toggleBtnElem)
+              toggleBtnElem.ariaLabel = toggleBtnElem.title = t(`thumbnail_overlay_toggle_btn_tooltip${showOverlay ? "_hide" : "_show"}`);
+          },
+        });
       }
     };
 
@@ -539,6 +540,7 @@ export async function initThumbnailOverlay() {
         if(thumbImgElem)
           thumbImgElem.src = thumbUrl;
       }
+      else error("Couldn't get thumbnail URL for watch ID", watchId);
     };
 
     const unsubWatchIdChanged = siteEvents.on("watchIdChanged", (watchId) => {
@@ -587,6 +589,11 @@ export async function initThumbnailOverlay() {
         applyThumbUrl(watchId);
         updateOverlayVisibility();
       });
+
+      if(currentParams.has("v")) {
+        applyThumbUrl(currentParams.get("v")!);
+        updateOverlayVisibility();
+      }
     
       // toggle button
       if(toggleBtnShown) {
@@ -635,7 +642,7 @@ export async function initThumbnailOverlay() {
           createElements();
       },
     });
-  })();
+  });
 }
 
 //#region hide cursor on idle

+ 7 - 2
src/siteEvents.ts

@@ -161,9 +161,14 @@ export async function initSiteEvents() {
           lastWatchId = newWatchId;
         }
       }
-      setTimeout(checkWatchId, 200);
     };
-    window.addEventListener("bytm:ready", checkWatchId, { once: true });
+
+    window.addEventListener("bytm:ready", () => {
+      checkWatchId();
+      setInterval(checkWatchId, 200);
+    }, {
+      once: true,
+    });
   }
   catch(err) {
     error("Couldn't initialize SiteEvents observers due to an error:\n", err);