From a2d2680393bc5cf2d80d2cd7e00c3ceb74f75d71 Mon Sep 17 00:00:00 2001
From: szialajoscosplay <70654182+k3rielit@users.noreply.github.com>
Date: Sun, 11 Jun 2023 16:01:39 +0200
Subject: [PATCH] added YT Swap
---
youtube/README.md | 21 ++++---
youtube/normalize-links.user.js | 24 --------
youtube/swap.user.js | 98 +++++++++++++++++++++++++++++++++
3 files changed, 110 insertions(+), 33 deletions(-)
delete mode 100644 youtube/normalize-links.user.js
create mode 100644 youtube/swap.user.js
diff --git a/youtube/README.md b/youtube/README.md
index f589b09..a4841aa 100644
--- a/youtube/README.md
+++ b/youtube/README.md
@@ -1,11 +1,14 @@
-## NORMALIZE LINKS
-Just replaces ```youtube.com/redirect``` links with the real one. Mostly pointless though.
-## HOW TO USE
-1. Install the Tampermonkey extension. ([Link](https://www.tampermonkey.net))
-2. [Install](https://github.com/k3rielit/scripts/raw/main/youtube/normalize-links.user.js)
-## UPDATES
-If it breaks, I'll try fixing it
+# Swap
+
+Replaces the top left logo with something more useful:
-(If youtube changes their use of class names, it will break. Which didn't happen to ```yt-formatted-string``` for a long time, but whatever...)
+- [x] Switch between Shorts and Watch UI
+- [x] Smaller home button
+- [ ] [Return YouTube Dislike](https://returnyoutubedislike.com/docs) raw data popup
+- [ ] Display a [QR code](https://davidshimjs.github.io/qrcodejs/) for the video
+- [ ] Replace redirect links with real ones
-Last tested: 2021.12.07.
+## Install
+
+1. Install the Tampermonkey extension. ([Link](https://www.tampermonkey.net))
+2. [Install](https://github.com/k3rielit/scripts/raw/main/youtube/swap.user.js)
diff --git a/youtube/normalize-links.user.js b/youtube/normalize-links.user.js
deleted file mode 100644
index 6a64653..0000000
--- a/youtube/normalize-links.user.js
+++ /dev/null
@@ -1,24 +0,0 @@
-// ==UserScript==
-// @name YT Normalize Links
-// @namespace yt_normalize_links
-// @version 1.0
-// @description replaces external links with the actual url instead of youtube's own redirect page
-// @author k3rielit
-// @match *://*.youtube.com/watch?*
-// @icon https://www.google.com/s2/favicons?domain=youtube.com
-// @grant none
-// ==/UserScript==
-
-(function() {
- 'use strict';
- const callback = () => {
- let redirects = [...document.getElementsByClassName('yt-formatted-string')].filter(f => f.href && f.href.startsWith('https://www.youtube.com/redirect'));
- redirects.forEach(a => {
- let decode = decodeURIComponent(a.href.split('q=')[1]);
- a.href = decode;
- a.innerText = decode.length > 100 ? decode.substring(0,100)+'...' : decode;
- });
- };
- const observer = new MutationObserver(callback);
- observer.observe(document.documentElement || document.body, { attributes: true, childList: true, subtree: true });
-})();
\ No newline at end of file
diff --git a/youtube/swap.user.js b/youtube/swap.user.js
new file mode 100644
index 0000000..70b66ad
--- /dev/null
+++ b/youtube/swap.user.js
@@ -0,0 +1,98 @@
+// ==UserScript==
+// @name YT Swap
+// @namespace k3rielit.ytswap
+// @version 1.0
+// @description Swaps between Shorts and Watch UI for the current video.
+// @author github.com/k3rielit
+// @match *://*.youtube.com/*
+// @match *://*.youtu.be/*
+// @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com
+// @grant none
+// ==/UserScript==
+
+console.log('[YTSwap] Loaded');
+
+// Components
+const components = {
+ lineawesome: ``,
+ flexmincss: `.container,.row>*{width:100%}.row{display:flex;flex-wrap:wrap}.row>*{flex-shrink:0;max-width:100%}.col{flex:1 0 0%}.col-auto{flex:0 0 auto;width:auto}`,
+ buttoncss: `.k-btn{cursor:pointer;border:0;display:inline;border-radius:30px;padding:8px 10px;font-size:20px;max-height:40px;max-width:40px;font-family:Roboto,Arial,sans-serif;font-weight:700;color:var(--yt-spec-text-primary);margin-left:10px}.k-btn:hover{background-color:rgba(255,255,255,.1)}`,
+ buttonHome: ``,
+ buttonSwapToShorts: ``,
+ buttonSwapToWatch: ``,
+ buttonInfo: ``,
+ buttonQRCode: ``,
+};
+
+// Functions
+// https://stackoverflow.com/questions/5525071/how-to-wait-until-an-element-exists
+function waitForElement(selector) {
+ return new Promise(resolve => {
+ if (document.querySelector(selector)) {
+ return resolve(document.querySelector(selector));
+ }
+ console.log('[waitForElement] Waiting for: '+selector);
+ const observer = new MutationObserver((mutationList, observer) => {
+ if (document.querySelector(selector)) {
+ console.log(document.querySelector(selector));
+ resolve(document.querySelector(selector));
+ observer.disconnect();
+ }
+ });
+ observer.observe(document.body, {
+ attributes: true, childList: true, subtree: true
+ });
+ });
+}
+
+function stringToElement(str) {
+ let template = document.createElement('template');
+ template.innerHTML = str.trim();
+ return template.content.firstChild;
+}
+
+function injectCSS(css) {
+ let style = document.createElement('style');
+ style.innerHTML = css;
+ document.head.appendChild(style);
+}
+
+function sleep(ms) {
+ return new Promise(resolve => setTimeout(resolve, ms));
+}
+
+// Main
+(async function() {
+ await waitForElement('div#buttons.style-scope.ytd-masthead yt-icon');
+ const topRightButtonContainer = await waitForElement('div#buttons.style-scope.ytd-masthead');
+ const topLeftLogo = await waitForElement('div#start.style-scope.ytd-masthead > #logo');
+ document.head.appendChild(stringToElement(components.lineawesome));
+ injectCSS(components.flexmincss);
+ injectCSS(components.buttoncss);
+ let lastHref = window.location.href;
+ // YT rerenders UI on route change
+ while(true) {
+ await sleep(111).then(() => {
+ if(lastHref != window.location.href || !document.getElementById('ytsw-home')) {
+ topLeftLogo.innerText = '';
+ // waitForElement('#voice-search-button').then((elem) => elem.remove());
+ // Determine what components to render
+ topLeftLogo.appendChild(stringToElement(components.buttonHome));
+ const currentUI = window.location.pathname.split('/')[1];
+ if(currentUI == 'shorts' || currentUI == 'watch') {
+ const videoId = window.location.href.includes('?v=') ? window.location.href.split('?v=')[1].substring(0,11) : window.location.pathname.split('/')[2];
+ switch(currentUI) {
+ case 'shorts':
+ topLeftLogo.appendChild(stringToElement(components.buttonSwapToWatch.replace(`href="#"`,`href="https://www.youtube.com/watch?v=${videoId}"`)));
+ break;
+ case 'watch':
+ topLeftLogo.appendChild(stringToElement(components.buttonSwapToShorts.replace(`href="#"`,`href="https://www.youtube.com/shorts/${videoId}"`)));
+ break;
+ }
+ topLeftLogo.appendChild(stringToElement(components.buttonInfo));
+ topLeftLogo.appendChild(stringToElement(components.buttonQRCode));
+ }
+ }
+ });
+ }
+})();
\ No newline at end of file