Explorar el Código

feat: finish like & dislike labels feature

Sv443 hace 10 meses
padre
commit
48b89d7dc3

+ 14 - 14
assets/translations/README.md

@@ -75,9 +75,9 @@ This means to figure out which keys are untranslated, you will need to manually
 | `votes_format_short` | `Shortened` |
 | `votes_format_short` | `Shortened` |
 | `votes_format_full` | `Full number` |
 | `votes_format_full` | `Full number` |
 | `feature_desc_showVotes` | `Show the amount of likes and dislikes on the currently playing song` |
 | `feature_desc_showVotes` | `Show the amount of likes and dislikes on the currently playing song` |
-| `feature_helptext_showVotes` | `This feature is powered by ReturnYoutubeDislikes and will show the approximate amount of likes and dislikes on the currently playing song.` |
+| `feature_helptext_showVotes` | `This feature is powered by Return YouTube Dislike and will show the approximate amount of likes and dislikes on the currently playing song.` |
 | `feature_desc_showVotesFormat` | `How should the likes and dislikes be formatted?` |
 | `feature_desc_showVotesFormat` | `How should the likes and dislikes be formatted?` |
-| `feature_desc_showVoteRatio` | `Show a colored bar that represents the ratio of likes and dislikes of the currently playing song` |
+| `feature_desc_showVoteRatio` | `TODO: Show a colored bar that represents the ratio of likes and dislikes of the currently playing song` |
 | `feature_desc_deleteFromQueueButton` | `Add a button to each song in a list to quickly remove it` |
 | `feature_desc_deleteFromQueueButton` | `Add a button to each song in a list to quickly remove it` |
 | `feature_desc_listButtonsPlacement` | `Where should the list buttons show up?` |
 | `feature_desc_listButtonsPlacement` | `Where should the list buttons show up?` |
 | `feature_desc_autoLikeChannels` | `Automatically like all songs and videos of certain channels` |
 | `feature_desc_autoLikeChannels` | `Automatically like all songs and videos of certain channels` |
@@ -130,9 +130,9 @@ This means to figure out which keys are untranslated, you will need to manually
 | `votes_format_short` | `Shortened` |
 | `votes_format_short` | `Shortened` |
 | `votes_format_full` | `Full number` |
 | `votes_format_full` | `Full number` |
 | `feature_desc_showVotes` | `Show the amount of likes and dislikes on the currently playing song` |
 | `feature_desc_showVotes` | `Show the amount of likes and dislikes on the currently playing song` |
-| `feature_helptext_showVotes` | `This feature is powered by ReturnYoutubeDislikes and will show the approximate amount of likes and dislikes on the currently playing song.` |
+| `feature_helptext_showVotes` | `This feature is powered by Return YouTube Dislike and will show the approximate amount of likes and dislikes on the currently playing song.` |
 | `feature_desc_showVotesFormat` | `How should the likes and dislikes be formatted?` |
 | `feature_desc_showVotesFormat` | `How should the likes and dislikes be formatted?` |
-| `feature_desc_showVoteRatio` | `Show a colored bar that represents the ratio of likes and dislikes of the currently playing song` |
+| `feature_desc_showVoteRatio` | `TODO: Show a colored bar that represents the ratio of likes and dislikes of the currently playing song` |
 | `feature_desc_deleteFromQueueButton` | `Add a button to each song in a list to quickly remove it` |
 | `feature_desc_deleteFromQueueButton` | `Add a button to each song in a list to quickly remove it` |
 | `feature_desc_listButtonsPlacement` | `Where should the list buttons show up?` |
 | `feature_desc_listButtonsPlacement` | `Where should the list buttons show up?` |
 | `feature_desc_autoLikeChannels` | `Automatically like all songs and videos of certain channels` |
 | `feature_desc_autoLikeChannels` | `Automatically like all songs and videos of certain channels` |
@@ -185,9 +185,9 @@ This means to figure out which keys are untranslated, you will need to manually
 | `votes_format_short` | `Shortened` |
 | `votes_format_short` | `Shortened` |
 | `votes_format_full` | `Full number` |
 | `votes_format_full` | `Full number` |
 | `feature_desc_showVotes` | `Show the amount of likes and dislikes on the currently playing song` |
 | `feature_desc_showVotes` | `Show the amount of likes and dislikes on the currently playing song` |
-| `feature_helptext_showVotes` | `This feature is powered by ReturnYoutubeDislikes and will show the approximate amount of likes and dislikes on the currently playing song.` |
+| `feature_helptext_showVotes` | `This feature is powered by Return YouTube Dislike and will show the approximate amount of likes and dislikes on the currently playing song.` |
 | `feature_desc_showVotesFormat` | `How should the likes and dislikes be formatted?` |
 | `feature_desc_showVotesFormat` | `How should the likes and dislikes be formatted?` |
-| `feature_desc_showVoteRatio` | `Show a colored bar that represents the ratio of likes and dislikes of the currently playing song` |
+| `feature_desc_showVoteRatio` | `TODO: Show a colored bar that represents the ratio of likes and dislikes of the currently playing song` |
 | `feature_desc_deleteFromQueueButton` | `Add a button to each song in a list to quickly remove it` |
 | `feature_desc_deleteFromQueueButton` | `Add a button to each song in a list to quickly remove it` |
 | `feature_desc_listButtonsPlacement` | `Where should the list buttons show up?` |
 | `feature_desc_listButtonsPlacement` | `Where should the list buttons show up?` |
 | `feature_desc_autoLikeChannels` | `Automatically like all songs and videos of certain channels` |
 | `feature_desc_autoLikeChannels` | `Automatically like all songs and videos of certain channels` |
@@ -240,9 +240,9 @@ This means to figure out which keys are untranslated, you will need to manually
 | `votes_format_short` | `Shortened` |
 | `votes_format_short` | `Shortened` |
 | `votes_format_full` | `Full number` |
 | `votes_format_full` | `Full number` |
 | `feature_desc_showVotes` | `Show the amount of likes and dislikes on the currently playing song` |
 | `feature_desc_showVotes` | `Show the amount of likes and dislikes on the currently playing song` |
-| `feature_helptext_showVotes` | `This feature is powered by ReturnYoutubeDislikes and will show the approximate amount of likes and dislikes on the currently playing song.` |
+| `feature_helptext_showVotes` | `This feature is powered by Return YouTube Dislike and will show the approximate amount of likes and dislikes on the currently playing song.` |
 | `feature_desc_showVotesFormat` | `How should the likes and dislikes be formatted?` |
 | `feature_desc_showVotesFormat` | `How should the likes and dislikes be formatted?` |
-| `feature_desc_showVoteRatio` | `Show a colored bar that represents the ratio of likes and dislikes of the currently playing song` |
+| `feature_desc_showVoteRatio` | `TODO: Show a colored bar that represents the ratio of likes and dislikes of the currently playing song` |
 | `feature_desc_deleteFromQueueButton` | `Add a button to each song in a list to quickly remove it` |
 | `feature_desc_deleteFromQueueButton` | `Add a button to each song in a list to quickly remove it` |
 | `feature_desc_listButtonsPlacement` | `Where should the list buttons show up?` |
 | `feature_desc_listButtonsPlacement` | `Where should the list buttons show up?` |
 | `feature_desc_autoLikeChannels` | `Automatically like all songs and videos of certain channels` |
 | `feature_desc_autoLikeChannels` | `Automatically like all songs and videos of certain channels` |
@@ -295,9 +295,9 @@ This means to figure out which keys are untranslated, you will need to manually
 | `votes_format_short` | `Shortened` |
 | `votes_format_short` | `Shortened` |
 | `votes_format_full` | `Full number` |
 | `votes_format_full` | `Full number` |
 | `feature_desc_showVotes` | `Show the amount of likes and dislikes on the currently playing song` |
 | `feature_desc_showVotes` | `Show the amount of likes and dislikes on the currently playing song` |
-| `feature_helptext_showVotes` | `This feature is powered by ReturnYoutubeDislikes and will show the approximate amount of likes and dislikes on the currently playing song.` |
+| `feature_helptext_showVotes` | `This feature is powered by Return YouTube Dislike and will show the approximate amount of likes and dislikes on the currently playing song.` |
 | `feature_desc_showVotesFormat` | `How should the likes and dislikes be formatted?` |
 | `feature_desc_showVotesFormat` | `How should the likes and dislikes be formatted?` |
-| `feature_desc_showVoteRatio` | `Show a colored bar that represents the ratio of likes and dislikes of the currently playing song` |
+| `feature_desc_showVoteRatio` | `TODO: Show a colored bar that represents the ratio of likes and dislikes of the currently playing song` |
 | `feature_desc_deleteFromQueueButton` | `Add a button to each song in a list to quickly remove it` |
 | `feature_desc_deleteFromQueueButton` | `Add a button to each song in a list to quickly remove it` |
 | `feature_desc_listButtonsPlacement` | `Where should the list buttons show up?` |
 | `feature_desc_listButtonsPlacement` | `Where should the list buttons show up?` |
 | `feature_desc_autoLikeChannels` | `Automatically like all songs and videos of certain channels` |
 | `feature_desc_autoLikeChannels` | `Automatically like all songs and videos of certain channels` |
@@ -350,9 +350,9 @@ This means to figure out which keys are untranslated, you will need to manually
 | `votes_format_short` | `Shortened` |
 | `votes_format_short` | `Shortened` |
 | `votes_format_full` | `Full number` |
 | `votes_format_full` | `Full number` |
 | `feature_desc_showVotes` | `Show the amount of likes and dislikes on the currently playing song` |
 | `feature_desc_showVotes` | `Show the amount of likes and dislikes on the currently playing song` |
-| `feature_helptext_showVotes` | `This feature is powered by ReturnYoutubeDislikes and will show the approximate amount of likes and dislikes on the currently playing song.` |
+| `feature_helptext_showVotes` | `This feature is powered by Return YouTube Dislike and will show the approximate amount of likes and dislikes on the currently playing song.` |
 | `feature_desc_showVotesFormat` | `How should the likes and dislikes be formatted?` |
 | `feature_desc_showVotesFormat` | `How should the likes and dislikes be formatted?` |
-| `feature_desc_showVoteRatio` | `Show a colored bar that represents the ratio of likes and dislikes of the currently playing song` |
+| `feature_desc_showVoteRatio` | `TODO: Show a colored bar that represents the ratio of likes and dislikes of the currently playing song` |
 | `feature_desc_deleteFromQueueButton` | `Add a button to each song in a list to quickly remove it` |
 | `feature_desc_deleteFromQueueButton` | `Add a button to each song in a list to quickly remove it` |
 | `feature_desc_listButtonsPlacement` | `Where should the list buttons show up?` |
 | `feature_desc_listButtonsPlacement` | `Where should the list buttons show up?` |
 | `feature_desc_autoLikeChannels` | `Automatically like all songs and videos of certain channels` |
 | `feature_desc_autoLikeChannels` | `Automatically like all songs and videos of certain channels` |
@@ -405,9 +405,9 @@ This means to figure out which keys are untranslated, you will need to manually
 | `votes_format_short` | `Shortened` |
 | `votes_format_short` | `Shortened` |
 | `votes_format_full` | `Full number` |
 | `votes_format_full` | `Full number` |
 | `feature_desc_showVotes` | `Show the amount of likes and dislikes on the currently playing song` |
 | `feature_desc_showVotes` | `Show the amount of likes and dislikes on the currently playing song` |
-| `feature_helptext_showVotes` | `This feature is powered by ReturnYoutubeDislikes and will show the approximate amount of likes and dislikes on the currently playing song.` |
+| `feature_helptext_showVotes` | `This feature is powered by Return YouTube Dislike and will show the approximate amount of likes and dislikes on the currently playing song.` |
 | `feature_desc_showVotesFormat` | `How should the likes and dislikes be formatted?` |
 | `feature_desc_showVotesFormat` | `How should the likes and dislikes be formatted?` |
-| `feature_desc_showVoteRatio` | `Show a colored bar that represents the ratio of likes and dislikes of the currently playing song` |
+| `feature_desc_showVoteRatio` | `TODO: Show a colored bar that represents the ratio of likes and dislikes of the currently playing song` |
 | `feature_desc_deleteFromQueueButton` | `Add a button to each song in a list to quickly remove it` |
 | `feature_desc_deleteFromQueueButton` | `Add a button to each song in a list to quickly remove it` |
 | `feature_desc_listButtonsPlacement` | `Where should the list buttons show up?` |
 | `feature_desc_listButtonsPlacement` | `Where should the list buttons show up?` |
 | `feature_desc_autoLikeChannels` | `Automatically like all songs and videos of certain channels` |
 | `feature_desc_autoLikeChannels` | `Automatically like all songs and videos of certain channels` |

+ 2 - 2
assets/translations/en_US.json

@@ -202,9 +202,9 @@
     "feature_desc_disableDarkReaderSites": "On which sites should the Dark Reader extension be disabled to fix layout issues?",
     "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_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_desc_showVotes": "Show the amount of likes and dislikes on the currently playing song",
     "feature_desc_showVotes": "Show the amount of likes and dislikes on the currently playing song",
-    "feature_helptext_showVotes": "This feature is powered by ReturnYoutubeDislikes and will show the approximate amount of likes and dislikes on the currently playing song.",
+    "feature_helptext_showVotes": "This feature is powered by Return YouTube Dislike and will show the approximate amount of likes and dislikes on the currently playing song.",
     "feature_desc_showVotesFormat": "How should the likes and dislikes be formatted?",
     "feature_desc_showVotesFormat": "How should the likes and dislikes be formatted?",
-    "feature_desc_showVoteRatio": "Show a colored bar that represents the ratio of likes and dislikes of the currently playing song",
+    "feature_desc_showVoteRatio": "TODO: Show a colored bar that represents the ratio of likes and dislikes of the currently playing song",
 
 
     "feature_desc_lyricsQueueButton": "Add a button to each song in a queue to quickly open its lyrics page",
     "feature_desc_lyricsQueueButton": "Add a button to each song in a queue to quickly open its lyrics page",
     "feature_desc_deleteFromQueueButton": "Add a button to each song in a list to quickly remove it",
     "feature_desc_deleteFromQueueButton": "Add a button to each song in a list to quickly remove it",

+ 6 - 1
dist/BetterYTM.css

@@ -1647,7 +1647,12 @@ ytmusic-player#player #bezel {
 .bytm-vote-label {
 .bytm-vote-label {
   cursor: pointer;
   cursor: pointer;
   font-size: 1.25rem;
   font-size: 1.25rem;
-  padding: 4px;
+  padding: 6px;
+  padding-left: 3px;
+}
+
+.bytm-vote-label:last-child {
+  padding-right: 0px;
 }
 }
 
 
 :root {
 :root {

+ 6 - 1
src/features/layout.css

@@ -388,5 +388,10 @@ ytmusic-player#player #bezel {
 .bytm-vote-label {
 .bytm-vote-label {
   cursor: pointer;
   cursor: pointer;
   font-size: 1.25rem;
   font-size: 1.25rem;
-  padding: 4px;
+  padding: 6px;
+  padding-left: 3px;
+}
+
+.bytm-vote-label:last-child {
+  padding-right: 0px;
 }
 }

+ 34 - 20
src/features/layout.ts

@@ -2,7 +2,7 @@ import { addParent, autoPlural, debounce, fetchAdvanced, pauseFor } from "@sv443
 import { getFeature, getFeatures } from "../config.js";
 import { getFeature, getFeatures } from "../config.js";
 import { siteEvents } from "../siteEvents.js";
 import { siteEvents } from "../siteEvents.js";
 import { addSelectorListener } from "../observers.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 ReturnYoutubeDislikesVotesObj } from "../utils/index.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 { mode, scriptInfo } from "../constants.js";
 import { mode, scriptInfo } from "../constants.js";
 import { openCfgMenu } from "../menu/menu_old.js";
 import { openCfgMenu } from "../menu/menu_old.js";
 import { createCircularBtn, createRipple } from "../components/index.js";
 import { createCircularBtn, createRipple } from "../components/index.js";
@@ -757,22 +757,30 @@ export async function initShowVotes() {
   });
   });
 
 
   siteEvents.on("watchIdChanged", async (watchId) => {
   siteEvents.on("watchIdChanged", async (watchId) => {
-    const voteObj = await fetchVideoVotes(watchId);
-    if(!voteObj || !("likes" in voteObj) || !("dislikes" in voteObj) || !("rating" in voteObj))
-      return error("Couldn't fetch votes from ReturnYouTubeDislikes API");
-
     const labelLikes = document.querySelector<HTMLElement>("ytmusic-like-button-renderer .bytm-vote-label.likes");
     const labelLikes = document.querySelector<HTMLElement>("ytmusic-like-button-renderer .bytm-vote-label.likes");
     const labelDislikes = document.querySelector<HTMLElement>("ytmusic-like-button-renderer .bytm-vote-label.dislikes");
     const labelDislikes = document.querySelector<HTMLElement>("ytmusic-like-button-renderer .bytm-vote-label.dislikes");
 
 
     if(!labelLikes || !labelDislikes)
     if(!labelLikes || !labelDislikes)
       return error("Couldn't find vote label elements while updating like and dislike counts");
       return error("Couldn't find vote label elements while updating like and dislike counts");
 
 
-    labelLikes.textContent = voteObj.likes.toLocaleString(undefined, getVoteNumberFormat());
-    labelDislikes.textContent = voteObj.dislikes.toLocaleString(undefined, getVoteNumberFormat());
+    if(labelLikes.dataset.watchId === watchId && labelDislikes.dataset.watchId === watchId)
+      return log("Vote labels already updated for this video");
+
+    const voteObj = await fetchVideoVotes(watchId);
+    if(!voteObj || !("likes" in voteObj) || !("dislikes" in voteObj) || !("rating" in voteObj))
+      return error("Couldn't fetch votes from ReturnYouTubeDislikes API");
+
+    labelLikes.dataset.watchId = getWatchId() ?? "";
+    labelLikes.textContent = formatVoteNumber(voteObj.likes);
+    labelLikes.title = labelLikes.ariaLabel = t("vote_label_likes", voteObj.likes);
+
+    labelDislikes.textContent = formatVoteNumber(voteObj.dislikes);
+    labelDislikes.title = labelDislikes.ariaLabel = t("vote_label_dislikes", voteObj.dislikes);
+    labelDislikes.dataset.watchId = getWatchId() ?? "";
   });
   });
 }
 }
 
 
-function addVoteNumbers(voteCont: HTMLElement, voteObj: ReturnYoutubeDislikesVotesObj) {
+function addVoteNumbers(voteCont: HTMLElement, voteObj: ReturnYouTubeDislikeVotesObj) {
   const likeBtn = voteCont.querySelector<HTMLElement>("#button-shape-like");
   const likeBtn = voteCont.querySelector<HTMLElement>("#button-shape-like");
   const dislikeBtn = voteCont.querySelector<HTMLElement>("#button-shape-dislike");
   const dislikeBtn = voteCont.querySelector<HTMLElement>("#button-shape-dislike");
 
 
@@ -782,8 +790,9 @@ function addVoteNumbers(voteCont: HTMLElement, voteObj: ReturnYoutubeDislikesVot
   const createLabel = (amount: number, type: "likes" | "dislikes"): HTMLElement => {
   const createLabel = (amount: number, type: "likes" | "dislikes"): HTMLElement => {
     const label = document.createElement("span");
     const label = document.createElement("span");
     label.classList.add("bytm-vote-label", "bytm-no-select", type);
     label.classList.add("bytm-vote-label", "bytm-no-select", type);
-    label.textContent = amount.toLocaleString(undefined, getVoteNumberFormat());
+    label.textContent = String(formatVoteNumber(amount));
     label.title = label.ariaLabel = t(`vote_label_${type}`, amount);
     label.title = label.ariaLabel = t(`vote_label_${type}`, amount);
+    label.dataset.watchId = getWatchId() ?? "";
     label.addEventListener("click", (e) => {
     label.addEventListener("click", (e) => {
       e.preventDefault();
       e.preventDefault();
       e.stopPropagation();
       e.stopPropagation();
@@ -801,18 +810,23 @@ function addVoteNumbers(voteCont: HTMLElement, voteObj: ReturnYoutubeDislikesVot
   dislikeBtn.insertAdjacentElement("afterend", dislikeLblEl);
   dislikeBtn.insertAdjacentElement("afterend", dislikeLblEl);
 }
 }
 
 
-function getVoteNumberFormat(): Partial<Intl.NumberFormatOptions> {
-  return getFeature("showVotesFormat") === "short"
-    ? {
-      notation: "compact",
-      compactDisplay: "short",
-    }
-    : {
-      style: "decimal",
-      maximumFractionDigits: 0,
-    };
+/** Formats a number with the notation based on the config */
+function formatVoteNumber(num: number) {
+  return num.toLocaleString(
+    undefined,
+    getFeature("showVotesFormat") === "short"
+      ? {
+        notation: "compact",
+        compactDisplay: "short",
+        maximumFractionDigits: 1,
+      }
+      : {
+        style: "decimal",
+        maximumFractionDigits: 0,
+      },
+  );
 }
 }
 
 
-function addVoteRatio(voteCont: HTMLElement, voteObj: ReturnYoutubeDislikesVotesObj) {
+function addVoteRatio(voteCont: HTMLElement, voteObj: ReturnYouTubeDislikeVotesObj) {
   console.log("># TODO: addVoteRatio", voteCont, voteObj);
   console.log("># TODO: addVoteRatio", voteCont, voteObj);
 }
 }

+ 4 - 4
src/utils/xhr.ts

@@ -57,7 +57,7 @@ export async function fetchCss(key: ResourceKey & `css-${string}`) {
   }
   }
 }
 }
 
 
-export type ReturnYoutubeDislikesVotesObj = {
+export type ReturnYouTubeDislikeVotesObj = {
   /** The watch ID of the video */
   /** The watch ID of the video */
   id: string;
   id: string;
   /** ISO timestamp of when the video was uploaded */
   /** ISO timestamp of when the video was uploaded */
@@ -75,15 +75,15 @@ export type ReturnYoutubeDislikesVotesObj = {
 };
 };
 
 
 /**
 /**
- * Fetches the votes object for a YouTube video from the [Return YouTube Dislikes API.](https://returnyoutubedislike.com/docs)
+ * 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
  * @param watchId The watch ID of the video
  */
  */
 export async function fetchVideoVotes(watchId: string) {
 export async function fetchVideoVotes(watchId: string) {
   try {
   try {
-    return JSON.parse((await sendRequest<ReturnYoutubeDislikesVotesObj>({
+    return JSON.parse((await sendRequest<ReturnYouTubeDislikeVotesObj>({
       method: "GET",
       method: "GET",
       url: `https://returnyoutubedislikeapi.com/votes?videoId=${watchId}`,
       url: `https://returnyoutubedislikeapi.com/votes?videoId=${watchId}`,
-    })).response) as ReturnYoutubeDislikesVotesObj;
+    })).response) as ReturnYouTubeDislikeVotesObj;
   }
   }
   catch(err) {
   catch(err) {
     error("Couldn't fetch video votes due to an error:", err);
     error("Couldn't fetch video votes due to an error:", err);