Explorar el Código

ref!: remove "remove upgrade tab" feature

Sv443 hace 10 meses
padre
commit
2dd0a8d754

+ 9 - 9
assets/translations/README.md

@@ -16,15 +16,15 @@ To submit or edit a translation, please follow [this guide](../../contributing.m
 ### Translation progress:
 |   | Locale | Translated keys | Based on |
 | :----: | ------ | --------------- | :------: |
-| ─ | [`en_US`](./en_US.json) | 259 (default locale) |  |
-| ‼️ | [`de_DE`](./de_DE.json) | `211/259` (81.5%) | ─ |
-| ─ | [`en_UK`](./en_UK.json) | `259` (100%) | `en_US` |
-| ‼️ | [`es_ES`](./es_ES.json) | `211/259` (81.5%) | ─ |
-| ‼️ | [`fr_FR`](./fr_FR.json) | `211/259` (81.5%) | ─ |
-| ‼️ | [`hi_IN`](./hi_IN.json) | `211/259` (81.5%) | ─ |
-| ‼️ | [`ja_JA`](./ja_JA.json) | `211/259` (81.5%) | ─ |
-| ‼️ | [`pt_BR`](./pt_BR.json) | `211/259` (81.5%) | ─ |
-| ‼️ | [`zh_CN`](./zh_CN.json) | `211/259` (81.5%) | ─ |
+| ─ | [`en_US`](./en_US.json) | 258 (default locale) |  |
+| ‼️ | [`de_DE`](./de_DE.json) | `210/258` (81.4%) | ─ |
+| ─ | [`en_UK`](./en_UK.json) | `258` (100%) | `en_US` |
+| ‼️ | [`es_ES`](./es_ES.json) | `210/258` (81.4%) | ─ |
+| ‼️ | [`fr_FR`](./fr_FR.json) | `210/258` (81.4%) | ─ |
+| ‼️ | [`hi_IN`](./hi_IN.json) | `210/258` (81.4%) | ─ |
+| ‼️ | [`ja_JA`](./ja_JA.json) | `210/258` (81.4%) | ─ |
+| ‼️ | [`pt_BR`](./pt_BR.json) | `210/258` (81.4%) | ─ |
+| ‼️ | [`zh_CN`](./zh_CN.json) | `210/258` (81.4%) | ─ |
 
 <sub>
 ✅ - Fully translated

+ 0 - 1
assets/translations/de_DE.json

@@ -149,7 +149,6 @@
     "feature_desc_fixSpacing": "Behebe diverse Abstandprobleme im Layout",
     "feature_helptext_fixSpacing": "Es gibt verschiedene Stellen im User Interface, an denen der Abstand zwischen Elementen inkonsistent ist. Diese Funktion behebt diese Probleme.",
 
-    "feature_desc_removeUpgradeTab": "Entferne den Upgrade / Premium Tab",
     "feature_desc_volumeSliderLabel": "Füge eine Prozent-Beschriftung neben dem Lautstärkeregler hinzu",
     "feature_desc_volumeSliderSize": "Die Breite des Lautstärkereglers in Pixeln",
     "feature_desc_volumeSliderStep": "Lautstärkeregler-Sensitivität (um wie wenig Prozent die Lautstärke auf einmal geändert werden kann)",

+ 0 - 1
assets/translations/en_US.json

@@ -178,7 +178,6 @@
     "feature_desc_fixSpacing": "Fix spacing issues in the layout",
     "feature_helptext_fixSpacing": "There are various locations in the user interface where the spacing between elements is inconsistent. This feature fixes those issues.",
 
-    "feature_desc_removeUpgradeTab": "Remove the Upgrade / Premium tab",
     "feature_desc_volumeSliderLabel": "Add a percentage label next to the volume slider",
     "feature_desc_volumeSliderSize": "The width of the volume slider in pixels",
     "feature_desc_volumeSliderStep": "Volume slider sensitivity (by how little percent the volume can be changed at a time)",

+ 0 - 1
assets/translations/es_ES.json

@@ -149,7 +149,6 @@
     "feature_desc_fixSpacing": "Solucionar problemas de espaciado en el diseño",
     "feature_helptext_fixSpacing": "Hay varios lugares en la interfaz de usuario donde el espaciado entre elementos es inconsistente. Esta función soluciona esos problemas.",
 
-    "feature_desc_removeUpgradeTab": "Eliminar la pestaña Actualizar / Premium",
     "feature_desc_volumeSliderLabel": "Agregue una etiqueta de porcentaje junto al control deslizante de volumen",
     "feature_desc_volumeSliderSize": "El ancho del control deslizante de volumen en píxeles",
     "feature_desc_volumeSliderStep": "Sensibilidad del control deslizante de volumen (en qué porcentaje se puede cambiar el volumen a la vez)",

+ 0 - 1
assets/translations/fr_FR.json

@@ -149,7 +149,6 @@
     "feature_desc_fixSpacing": "Corriger les problèmes d'espacement dans la mise en page",
     "feature_helptext_fixSpacing": "Il existe divers endroits dans l'interface utilisateur où l'espacement entre les éléments est incohérent. Cette fonctionnalité corrige ces problèmes.",
 
-    "feature_desc_removeUpgradeTab": "Supprimer l'onglet Mise à niveau / Premium",
     "feature_desc_volumeSliderLabel": "Ajouter une étiquette de pourcentage à côté du curseur de volume",
     "feature_desc_volumeSliderSize": "La largeur du curseur de volume en pixels",
     "feature_desc_volumeSliderStep": "Sensibilité du curseur de volume (de combien de pour cent le volume peut être modifié à la fois)",

+ 0 - 1
assets/translations/hi_IN.json

@@ -149,7 +149,6 @@
     "feature_desc_fixSpacing": "लेआउट में स्पेसिंग समस्याओं को ठीक करें",
     "feature_helptext_fixSpacing": "यहां विभिन्न स्थान हैं जहां तत्वों के बीच स्पेसिंग असंगत है। यह सुविधा उन समस्याओं को ठीक करती है।",
 
-    "feature_desc_removeUpgradeTab": "अपग्रेड/प्रीमियम टैब हटाएँ",
     "feature_desc_volumeSliderLabel": "वॉल्यूम स्लाइडर के पास एक प्रतिशत लेबल जोड़ें",
     "feature_desc_volumeSliderSize": "वॉल्यूम स्लाइडर की चौड़ाई पिक्सेल में",
     "feature_desc_volumeSliderStep": "वॉल्यूम स्लाइडर संवेदनशीलता (वॉल्यूम कितने प्रतिशत कम किया जा सकता है)",

+ 0 - 1
assets/translations/ja_JA.json

@@ -149,7 +149,6 @@
     "feature_desc_fixSpacing": "レイアウトのスペーシング問題を修正する",
     "feature_helptext_fixSpacing": "ユーザーインターフェイスには、要素間のスペーシングが一貫していない場所がいくつかあります。この機能はそれらの問題を修正します。",
 
-    "feature_desc_removeUpgradeTab": "アップグレード / プレミアムタブを削除する",
     "feature_desc_volumeSliderLabel": "音量スライダーの横にパーセンテージラベルを追加する",
     "feature_desc_volumeSliderSize": "音量スライダーの幅(ピクセル単位)",
     "feature_desc_volumeSliderStep": "音量スライダーの感度(音量を一度にどれだけのパーセントで変更できるか)",

+ 0 - 1
assets/translations/pt_BR.json

@@ -149,7 +149,6 @@
     "feature_desc_fixSpacing": "Corrigir problemas de espaçamento no layout",
     "feature_helptext_fixSpacing": "Há vários locais na interface do usuário onde o espaçamento entre os elementos é inconsistente. Este recurso corrige esses problemas.",
 
-    "feature_desc_removeUpgradeTab": "Remover a guia Upgrade / Premium",
     "feature_desc_volumeSliderLabel": "Adicionar um rótulo de porcentagem ao lado do controle de volume",
     "feature_desc_volumeSliderSize": "A largura do controle deslizante de volume em pixels",
     "feature_desc_volumeSliderStep": "Sensibilidade do controle deslizante de volume (por quantos porcento o volume pode ser alterado de cada vez)",

+ 0 - 1
assets/translations/zh_CN.json

@@ -149,7 +149,6 @@
     "feature_desc_fixSpacing": "修复布局中的间距问题",
     "feature_helptext_fixSpacing": "在用户界面中有各种位置的元素之间的间距不一致。此功能修复了这些问题。",
 
-    "feature_desc_removeUpgradeTab": "删除升级 / 高级标签",
     "feature_desc_volumeSliderLabel": "在音量滑块旁边添加百分比标签",
     "feature_desc_volumeSliderSize": "音量滑块的宽度(像素)",
     "feature_desc_volumeSliderStep": "音量滑块灵敏度(音量每次可以改变多少百分比)",

+ 1 - 0
changelog.md

@@ -20,6 +20,7 @@
     - Placement of list/queue buttons
   - Added Shift and Ctrl modifier keys to the above-queue buttons that can skip prompts or customize the behavior
   - Arrow key and number key skipping works more reliably and also in the config menu now
+  - Removed broken feature "remove upgrade tab"
 
 <details><summary>Click to expand internal and plugin changes</summary>
 

+ 1 - 1
eslint.config.mjs

@@ -60,7 +60,7 @@ export default [{
       ignoredNodes: ["VariableDeclaration[declarations.length=0]"],
     }],
     "@typescript-eslint/no-non-null-assertion": "off",
-    "@typescript-eslint/no-unused-vars": ["error", {
+    "@typescript-eslint/no-unused-vars": ["warn", {
       vars: "local",
       ignoreRestSiblings: true,
       args: "after-used",

+ 18 - 14
src/config.ts

@@ -70,20 +70,24 @@ export const migrations: DataMigrationsDict = {
     "closeToastsTimeout", "disableDarkReaderSites",
   ]),
   // 5 -> 6 (v2.1)
-  6: (oldData: FeatureConfig) => useNewDefaultIfUnchanged(
-    useDefaultConfig(oldData, [
-      "autoLikeChannels", "autoLikeChannelToggleBtn",
-      "autoLikeTimeout", "autoLikeShowToast",
-      "autoLikeOpenMgmtDialog", "showVotes",
-      "showVotesFormat", "showVoteRatio",
-      "toastDuration", "initTimeout",
-      // forgot to add this to the migration when adding the feature so now will have to do:
-      "volumeSliderLabel",
-    ]), [
-      { key: "rememberSongTimeSites", oldDefault: "ytm" },
-      { key: "volumeSliderScrollStep", oldDefault: 10 },
-    ],
-  ),
+  6: (oldData: FeatureConfig) => {
+    const newData = useNewDefaultIfUnchanged(
+      useDefaultConfig(oldData, [
+        "autoLikeChannels", "autoLikeChannelToggleBtn",
+        "autoLikeTimeout", "autoLikeShowToast",
+        "autoLikeOpenMgmtDialog", "showVotes",
+        "showVotesFormat", "showVoteRatio",
+        "toastDuration", "initTimeout",
+        // forgot to add this to the migration when adding the feature so now will have to do:
+        "volumeSliderLabel",
+      ]), [
+        { key: "rememberSongTimeSites", oldDefault: "ytm" },
+        { key: "volumeSliderScrollStep", oldDefault: 10 },
+      ],
+    );
+    "removeUpgradeTab" in newData && delete newData.removeUpgradeTab;
+    return newData;
+  },
   // TODO(v2.2): use default for "autoLikePlayerBarToggleBtn"
 
   // TODO: once advanced filtering is fully implemented, clear cache on migration to fv6

+ 0 - 6
src/features/index.ts

@@ -144,12 +144,6 @@ export const featInfo = {
     advanced: true,
     textAdornment: () => combineAdornments([adornments.advanced, adornments.reloadRequired]),
   },
-  removeUpgradeTab: {
-    type: "toggle",
-    category: "layout",
-    default: true,
-    textAdornment: adornments.reloadRequired,
-  },
   thumbnailOverlayBehavior: {
     type: "select",
     category: "layout",

+ 4 - 23
src/features/layout.ts

@@ -2,7 +2,7 @@ import { addParent, autoPlural, debounce, fetchAdvanced, pauseFor } from "@sv443
 import { getFeature, getFeatures } from "../config.js";
 import { siteEvents } from "../siteEvents.js";
 import { addSelectorListener } from "../observers.js";
-import { error, getResourceUrl, log, warn, t, onInteraction, openInTab, getBestThumbnailUrl, getDomain, addStyle, currentMediaType, domLoaded, waitVideoElementReady, getVideoTime, fetchCss, addStyleFromResource, fetchVideoVotes, getWatchId, type ReturnYouTubeDislikeVotesObj } from "../utils/index.js";
+import { error, getResourceUrl, log, warn, t, onInteraction, openInTab, getBestThumbnailUrl, getDomain, addStyle, currentMediaType, domLoaded, waitVideoElementReady, getVideoTime, fetchCss, addStyleFromResource, fetchVideoVotes, getWatchId, type VideoVotesObj, dbg } from "../utils/index.js";
 import { mode, scriptInfo } from "../constants.js";
 import { openCfgMenu } from "../menu/menu_old.js";
 import { createCircularBtn, createRipple } from "../components/index.js";
@@ -179,25 +179,6 @@ export async function addConfigMenuOptionYT(container: HTMLElement) {
     return error("Couldn't add config menu option to YT titlebar - couldn't find container element");
 }
 
-//#region upgrade tab
-
-/** Removes the "Upgrade" / YT Music Premium tab from the sidebar */
-export async function removeUpgradeTab() {
-  addSelectorListener("sideBar", "#contentContainer #guide-content #items ytmusic-guide-entry-renderer:nth-of-type(4)", {
-    listener: (tabElemLarge) => {
-      tabElemLarge.remove();
-      log("Removed large upgrade tab");
-    },
-  });
-  // TODO:FIXME: see https://github.com/Sv443/BetterYTM/issues/91
-  addSelectorListener("sideBarMini", "#sections ytmusic-guide-section-renderer[is-primary] #items ytmusic-guide-entry-renderer:nth-of-type(4)", {
-    listener: (tabElemSmall) => {
-      tabElemSmall.remove();
-      log("Removed small upgrade tab");
-    },
-  });
-}
-
 //#region anchor impr.
 
 /** Adds anchors around elements and tweaks existing ones so songs are easier to open in a new tab */
@@ -780,7 +761,7 @@ export async function initShowVotes() {
   });
 }
 
-function addVoteNumbers(voteCont: HTMLElement, voteObj: ReturnYouTubeDislikeVotesObj) {
+function addVoteNumbers(voteCont: HTMLElement, voteObj: VideoVotesObj) {
   const likeBtn = voteCont.querySelector<HTMLElement>("#button-shape-like");
   const dislikeBtn = voteCont.querySelector<HTMLElement>("#button-shape-dislike");
 
@@ -827,6 +808,6 @@ function formatVoteNumber(num: number) {
   );
 }
 
-function addVoteRatio(voteCont: HTMLElement, voteObj: ReturnYouTubeDislikeVotesObj) {
-  console.log("># TODO: addVoteRatio", voteCont, voteObj);
+function addVoteRatio(voteCont: HTMLElement, voteObj: VideoVotesObj) {
+  dbg("># TODO: addVoteRatio", voteCont, voteObj);
 }

+ 3 - 8
src/index.ts

@@ -10,9 +10,9 @@ import { getWelcomeDialog } from "./dialogs/index.js";
 import type { FeatureConfig } from "./types.js";
 import {
   // layout
-  addWatermark, removeUpgradeTab, initRemShareTrackParam,
-  fixSpacing, initThumbnailOverlay, initHideCursorOnIdle,
-  fixHdrIssues, initShowVotes,
+  addWatermark, initRemShareTrackParam, fixSpacing,
+  initThumbnailOverlay, initHideCursorOnIdle, fixHdrIssues,
+  initShowVotes,
   // volume
   initVolumeFeatures,
   // song lists
@@ -38,7 +38,6 @@ import {
   const styleGradient = "background: rgba(165, 38, 38, 1); background: linear-gradient(90deg, rgb(154, 31, 103) 0%, rgb(135, 31, 31) 40%, rgb(184, 64, 41) 100%);";
   const styleCommon = "color: #fff; font-size: 1.3rem;";
 
-  console.log();
   console.log(
     `%c${scriptInfo.name}%c${scriptInfo.version}%c • ${scriptInfo.namespace}%c\n\nBuild #${buildNumber}`,
     `${styleCommon} ${styleGradient} font-weight: bold; padding-left: 6px; padding-right: 6px;`,
@@ -56,7 +55,6 @@ import {
     "─ This markdown parser library: https://github.com/markedjs/marked",
     "─ This fuzzy search library: https://github.com/krisk/Fuse",
   ].join("\n"));
-  console.log();
 }
 
 //#region preInit
@@ -156,9 +154,6 @@ async function onDomLoad() {
       if(feats.fixSpacing)
         ftInit.push(["fixSpacing", fixSpacing()]);
 
-      if(feats.removeUpgradeTab)
-        ftInit.push(["removeUpgradeTab", removeUpgradeTab()]);
-
       ftInit.push(["thumbnailOverlay", initThumbnailOverlay()]);
 
       if(feats.hideCursorOnIdle)

+ 0 - 2
src/types.ts

@@ -342,8 +342,6 @@ export interface FeatureConfig {
   numKeysSkipToTime: boolean;
   /** Fix spacing issues in the layout */
   fixSpacing: boolean;
-  /** Remove the \"Upgrade\" / YT Music Premium tab */
-  removeUpgradeTab: boolean;
   /** Where to show a thumbnail overlay over the video element and whether to show it at all */
   thumbnailOverlayBehavior: "never" | "videosOnly" | "songsOnly" | "always";
   /** Whether to show a button to toggle the thumbnail overlay in the media controls */

+ 49 - 5
src/utils/xhr.ts

@@ -57,7 +57,7 @@ export async function fetchCss(key: ResourceKey & `css-${string}`) {
   }
 }
 
-export type ReturnYouTubeDislikeVotesObj = {
+export type ReturnYouTubeDislikeVotes = {
   /** The watch ID of the video */
   id: string;
   /** ISO timestamp of when the video was uploaded */
@@ -74,16 +74,60 @@ export type ReturnYouTubeDislikeVotesObj = {
   deleted: boolean;
 };
 
+export type VideoVotesObj = {
+  /** The watch ID of the video */
+  id: string;
+  /** Amount of likes */
+  likes: number;
+  /** Amount of dislikes */
+  dislikes: number;
+  /** Like to dislike ratio from 0.0 to 5.0 */
+  rating: number;
+  /** Timestamp of when the data was fetched */
+  timestamp: number;
+};
+
+/** Cache for the vote data of YouTube videos to prevent unnecessary requests */
+const voteCache = new Map<string, VideoVotesObj>();
+/** Time-to-live for the vote cache in milliseconds */
+const voteCacheTTL = 1000 * 60 * 5;
+
 /**
  * Fetches the votes object for a YouTube video from the [Return YouTube Dislike API.](https://returnyoutubedislike.com/docs)
  * @param watchId The watch ID of the video
  */
 export async function fetchVideoVotes(watchId: string) {
   try {
-    return JSON.parse((await sendRequest<ReturnYouTubeDislikeVotesObj>({
-      method: "GET",
-      url: `https://returnyoutubedislikeapi.com/votes?videoId=${watchId}`,
-    })).response) as ReturnYouTubeDislikeVotesObj;
+    if(voteCache.has(watchId)) {
+      const cached = voteCache.get(watchId)!;
+      if(Date.now() - cached.timestamp < voteCacheTTL)
+        return cached;
+      else
+        voteCache.delete(watchId);
+    }
+
+    const votesRaw = JSON.parse(
+      (await sendRequest({
+        method: "GET",
+        url: `https://returnyoutubedislikeapi.com/votes?videoId=${watchId}`,
+      })).response
+    ) as ReturnYouTubeDislikeVotes;
+
+    if(!("id" in votesRaw) || !("likes" in votesRaw) || !("dislikes" in votesRaw) || !("rating" in votesRaw)) {
+      error("Couldn't parse video votes due to an error:", votesRaw);
+      return undefined;
+    }
+
+    const votesObj = {
+      id: votesRaw.id,
+      likes: votesRaw.likes,
+      dislikes: votesRaw.dislikes,
+      rating: votesRaw.rating,
+      timestamp: Date.now(),
+    };
+    voteCache.set(votesObj.id, votesObj);
+
+    return votesObj;
   }
   catch(err) {
     error("Couldn't fetch video votes due to an error:", err);