From e8d3fbf5842d29495b0684f40ce5887bc4e0923b Mon Sep 17 00:00:00 2001 From: B Thejeswar <1ms23cs034@msrit.edu> Date: Thu, 11 Dec 2025 00:29:11 +0530 Subject: [PATCH] feature: double-click to like on Shorts --- features/shortsDoubleTap.js | 84 +++++++++++++++++++++++++++++++++++++ manifest.json | 3 +- 2 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 features/shortsDoubleTap.js diff --git a/features/shortsDoubleTap.js b/features/shortsDoubleTap.js new file mode 100644 index 000000000..085e52510 --- /dev/null +++ b/features/shortsDoubleTap.js @@ -0,0 +1,84 @@ +// shortsDoubleTap.js + +(() => { + console.log("🚀 Shorts Double-Tap Feature Loaded"); + + const DELAY = 250; + let clickTimer = null; + let lastClickTime = 0; + + // The Main Listener + const onShortsClick = (e) => { + // 1. Context Checks + if (!location.href.includes('/shorts/')) return; + + const target = e.target; + // Ensure click is on the video player container, not controls/overlay + const isVideoClick = target.tagName === 'VIDEO' || + target.classList.contains('html5-video-container') || + target.closest('.html5-video-player'); + + if (target.closest('button') || target.closest('a') || target.closest('#actions')) return; + if (!isVideoClick) return; + + // 2. Intercept Event + e.stopPropagation(); + e.stopImmediatePropagation(); + e.preventDefault(); + + // 3. Timing Logic + const currentTime = new Date().getTime(); + const timeDiff = currentTime - lastClickTime; + lastClickTime = currentTime; + + if (timeDiff < DELAY) { + // Double Click + clearTimeout(clickTimer); + triggerLike(); + } else { + // Single Click + clickTimer = setTimeout(() => { + togglePlayPause(); + }, DELAY); + } + }; + + // Helper: Find and click the like button + function triggerLike() { + const activeShort = document.querySelector('ytd-reel-video-renderer[is-active]'); + if (!activeShort) return; + + const allButtons = activeShort.querySelectorAll('button'); + let likeBtn = null; + + for (let btn of allButtons) { + const label = (btn.getAttribute('aria-label') || "").toLowerCase(); + if (label.startsWith('like this video')) { + likeBtn = btn; + break; + } + } + + if (likeBtn) { + const isLiked = likeBtn.getAttribute('aria-pressed') === 'true'; + if (!isLiked) { + likeBtn.click(); + } + } + } + + // Helper: Toggle Play/Pause + function togglePlayPause() { + const activeShort = document.querySelector('ytd-reel-video-renderer[is-active]'); + if (!activeShort) return; + + const video = activeShort.querySelector('video'); + if (video) { + video.paused ? video.play() : video.pause(); + } + } + + // Attach listener with Capture Phase + window.addEventListener('click', onShortsClick, true); + +})(); \ No newline at end of file diff --git a/manifest.json b/manifest.json index 589992ce9..5d5ca1f0e 100644 --- a/manifest.json +++ b/manifest.json @@ -51,7 +51,8 @@ "js&css/extension/www.youtube.com/general/general.js", "js&css/extension/www.youtube.com/appearance/sidebar/sidebar.js", "js&css/extension/www.youtube.com/appearance/comments/comments.js", - "js&css/extension/init.js" + "js&css/extension/init.js", + "features/shortsDoubleTap.js" ], "matches": ["https://www.youtube.com/*"], "run_at": "document_start"