Explorar o código

Merge pull request #511 from RyannDaGreat/main

YouTube Shorts now shows dislike counts
Dmitrii Selivanov %!s(int64=3) %!d(string=hai) anos
pai
achega
c6f1c7d5e5

+ 33 - 5
Extensions/UserScript/Return Youtube Dislike.user.js

@@ -30,13 +30,34 @@ let likesvalue = 0;
 let dislikesvalue = 0;
 
 let isMobile = location.hostname == "m.youtube.com";
+let isShorts = () => location.pathname.startsWith("/shorts")
 let mobileDislikes = 0;
 function cLog(text, subtext = "") {
   subtext = subtext.trim() === "" ? "" : `(${subtext})`;
   console.log(`[Return YouTube Dislikes] ${text} ${subtext}`);
 }
 
+function isInViewport(element) {
+  const rect = element.getBoundingClientRect();
+  const height = innerHeight || document.documentElement.clientHeight;
+  const width = innerWidth || document.documentElement.clientWidth;
+  return (
+      rect.top >= 0 &&
+      rect.left >= 0 &&
+      rect.bottom <= height &&
+      rect.right <= width
+  );
+}
+
 function getButtons() {
+  if(isShorts()) {
+    let elements=document.querySelectorAll(isMobile ? "ytm-like-button-renderer" : "#like-button > ytd-like-button-renderer");
+    for(let element of elements) {
+      if(isInViewport(element)) {
+        return element;
+      }
+    }
+  }
   if (isMobile) {
     return document.querySelector(".slim-video-action-bar-actions");
   }
@@ -214,6 +235,7 @@ function createRateBar(likes, dislikes) {
   }
 }
 
+
 function setState() {
   cLog("Fetching votes...");
   let statsSet = false;
@@ -232,7 +254,6 @@ function setState() {
       }
     });
   });
-  setState = function(){};
 }
 
 function likeClicked() {
@@ -288,6 +309,9 @@ function getVideoId() {
   if (pathname.startsWith("/clip")) {
     return document.querySelector("meta[itemprop='videoId']").content;
   } else {
+    if (pathname.startsWith("/shorts")) {
+      return pathname.substr(8);
+    }
     return urlObject.searchParams.get("v");
   }
 }
@@ -335,17 +359,21 @@ function setEventListeners(evt) {
 
   function checkForJS_Finish(check) {
     console.log();
-    if (getButtons()?.offsetParent && isVideoLoaded()) {
-      clearInterval(jsInitChecktimer);
+    if (isShorts() || getButtons()?.offsetParent && isVideoLoaded()) {
       const buttons = getButtons();
 
       if (!window.returnDislikeButtonlistenersSet) {
         cLog("Registering button listeners...");
-        buttons.children[0].addEventListener("click", likeClicked);
-        buttons.children[1].addEventListener("click", dislikeClicked);
+        try {
+          buttons.children[0].addEventListener("click", likeClicked);
+          buttons.children[1].addEventListener("click", dislikeClicked);
+          buttons.children[0].addEventListener("touchstart", likeClicked);
+          buttons.children[1].addEventListener("touchstart", dislikeClicked);
+        } catch { return } //Don't spam errors into the console
         window.returnDislikeButtonlistenersSet = true;
       }
       setInitialState();
+      clearInterval(jsInitChecktimer);
     }
   }
 

+ 4 - 3
Extensions/combined/ryd.content-script.js

@@ -9,6 +9,7 @@ import {
 //---   Import State Functions   ---//
 import {
   isMobile,
+  isShorts,
   isVideoDisliked,
   isVideoLiked,
   getState,
@@ -35,12 +36,12 @@ let jsInitChecktimer = null;
 
 function setEventListeners(evt) {
   function checkForJS_Finish() {
-    if (getButtons()?.offsetParent && isVideoLoaded()) {
-      clearInterval(jsInitChecktimer);
-      jsInitChecktimer = null;
+    if (isShorts() || getButtons()?.offsetParent && isVideoLoaded()) {
       addLikeDislikeEventListener();
       setInitialState();
       getBrowser().storage.onChanged.addListener(storageChangeHandler);
+      clearInterval(jsInitChecktimer);
+      jsInitChecktimer = null;
     }
   }
 

+ 1 - 1
Extensions/combined/src/bar.js

@@ -1,5 +1,5 @@
 import { getButtons } from "./buttons";
-import { likesDisabledState } from "./state";
+import { isMobile, likesDisabledState } from "./state";
 import { cLog } from "./utils";
 
 function createRateBar(likes, dislikes) {

+ 14 - 1
Extensions/combined/src/buttons.js

@@ -1,6 +1,19 @@
-import { isMobile } from "./state";
+import { isMobile, isShorts } from "./state";
+import { isInViewport } from "./utils";
 
 function getButtons() {
+  //---   If Watching Youtube Shorts:   ---//
+  if(isShorts()) {
+    let elements=document.querySelectorAll(isMobile() ? "ytm-like-button-renderer" : "#like-button > ytd-like-button-renderer"); 
+    for(let element of elements) {
+      //Youtube Shorts can have multiple like/dislike buttons when scrolling through videos
+      //However, only one of them should be visible (no matter how you zoom)
+      if(isInViewport(element)) {
+        return element;
+      }
+    }
+  }
+  //---   If Watching On Mobile:   ---//
   if (isMobile()) {
     return document.querySelector(".slim-video-action-bar-actions");
   }

+ 2 - 0
Extensions/combined/src/events.js

@@ -100,6 +100,8 @@ function addLikeDislikeEventListener() {
   if (!window.returnDislikeButtonlistenersSet) {
     buttons.children[0].addEventListener("click", likeClicked);
     buttons.children[1].addEventListener("click", dislikeClicked);
+    buttons.children[0].addEventListener("touchstart", likeClicked);
+    buttons.children[1].addEventListener("touchstart", dislikeClicked);
     window.returnDislikeButtonlistenersSet = true;
   }
 }

+ 10 - 0
Extensions/combined/src/state.js

@@ -27,6 +27,10 @@ function isMobile() {
   return location.hostname == "m.youtube.com";
 }
 
+function isShorts() {
+  return location.pathname.startsWith("/shorts")
+}
+
 function isVideoLiked() {
   if (isMobile()) {
     return (
@@ -85,6 +89,11 @@ function setDislikes(dislikesCount) {
 }
 
 function getLikeCountFromButton() {
+  if(isShorts()) {
+    //Youtube Shorts don't work with this query. It's not nessecary; we can skip it and still see the results.
+    //It should be possible to fix this function, but it's not critical to showing the dislike count.
+    return 0;
+  }
   let likesStr = getLikeButton()
     .querySelector("button")
     .getAttribute("aria-label")
@@ -156,6 +165,7 @@ function initializeDisableVoteSubmission() {
 
 export {
   isMobile,
+  isShorts,
   isVideoDisliked,
   isVideoLiked,
   getState,

+ 16 - 1
Extensions/combined/src/utils.js

@@ -45,10 +45,25 @@ function getVideoId(url) {
   if (pathname.startsWith("/clip")) {
     return document.querySelector("meta[itemprop='videoId']").content;
   } else {
+    if (pathname.startsWith("/shorts")) {
+      return pathname.substr(8);
+    }
     return urlObject.searchParams.get("v");
   }
 }
 
+function isInViewport(element) {
+  const rect = element.getBoundingClientRect();
+  const height = innerHeight || document.documentElement.clientHeight;
+  const width = innerWidth || document.documentElement.clientWidth;
+  return (
+      rect.top >= 0 &&
+      rect.left >= 0 &&
+      rect.bottom <= height &&
+      rect.right <= width
+  );
+}
+
 function isVideoLoaded() {
   const videoId = getVideoId(window.location.href);
   return (
@@ -67,4 +82,4 @@ function cLog(message, writer) {
   }
 }
 
-export { numberFormat, getBrowser, getVideoId, isVideoLoaded, cLog }
+export { numberFormat, getBrowser, getVideoId, isInViewport, isVideoLoaded, cLog }