Size
5.7 KB
Version
1.1.3
Created
Jan 24, 2026
Updated
24 days ago
1// ==UserScript==
2// @name YouTube Watch Later Sidebar Button
3// @description A new extension
4// @version 1.1.3
5// @match https://*.youtube.com/*
6// @icon https://www.youtube.com/s/desktop/191847ec/img/favicon_32x32.png
7// ==/UserScript==
8(function() {
9 'use strict';
10
11 // SVG path for Watch Later icon (clock icon)
12 const WATCH_LATER_ICON_PATH = 'M12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22C6.47,22 2,17.5 2,12A10,10 0 0,1 12,2M12.5,7V12.25L17,14.92L16.25,16.15L11,13V7H12.5Z';
13
14 function createWatchLaterButton() {
15 console.log('Creating Watch Later button for sidebar');
16
17 // Find the sidebar items container
18 const sidebar = document.querySelector('ytd-mini-guide-renderer');
19 if (!sidebar) {
20 console.log('Sidebar not found');
21 return false;
22 }
23
24 const itemsContainer = sidebar.querySelector('#items');
25 if (!itemsContainer) {
26 console.log('Items container not found');
27 return false;
28 }
29
30 // Check if Watch Later button already exists
31 const existingButton = Array.from(itemsContainer.querySelectorAll('ytd-mini-guide-entry-renderer')).find(entry => {
32 const link = entry.querySelector('a');
33 return link && link.getAttribute('href') === '/playlist?list=WL';
34 });
35
36 if (existingButton) {
37 console.log('Watch Later button already exists');
38 return true;
39 }
40
41 // Create the Watch Later entry
42 const watchLaterEntry = document.createElement('ytd-mini-guide-entry-renderer');
43 watchLaterEntry.className = 'style-scope ytd-mini-guide-renderer';
44
45 // Create the link element
46 const link = document.createElement('a');
47 link.id = 'endpoint';
48 link.className = 'yt-simple-endpoint style-scope ytd-mini-guide-entry-renderer';
49 link.setAttribute('aria-selected', 'false');
50 link.setAttribute('aria-label', 'Watch Later');
51 link.setAttribute('title', 'Watch Later');
52 link.setAttribute('href', '/playlist?list=WL');
53
54 // Create the icon container
55 const iconContainer = document.createElement('yt-icon');
56 iconContainer.id = 'icon';
57 iconContainer.className = 'guide-icon style-scope ytd-mini-guide-entry-renderer';
58
59 // Create the icon shape
60 const iconShape = document.createElement('span');
61 iconShape.className = 'yt-icon-shape style-scope yt-icon ytSpecIconShapeHost';
62
63 // Create a wrapper div for the SVG
64 const iconWrapper = document.createElement('div');
65 iconWrapper.style.cssText = 'width: 100%; height: 100%; display: block; fill: currentcolor;';
66
67 // Create the SVG icon
68 const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
69 svg.setAttribute('viewBox', '0 0 24 24');
70 svg.setAttribute('height', '24');
71 svg.setAttribute('width', '24');
72 svg.style.cssText = 'pointer-events: none; display: inherit; width: 100%; height: 100%;';
73
74 const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
75 path.setAttribute('d', WATCH_LATER_ICON_PATH);
76
77 svg.appendChild(path);
78 iconWrapper.appendChild(svg);
79 iconShape.appendChild(iconWrapper);
80 iconContainer.appendChild(iconShape);
81
82 // Create the title text
83 const title = document.createElement('span');
84 title.className = 'title style-scope ytd-mini-guide-entry-renderer';
85 title.textContent = 'Watch Later';
86 title.style.color = 'white';
87
88 // Create the interaction element
89 const interaction = document.createElement('yt-interaction');
90 interaction.className = 'style-scope ytd-mini-guide-entry-renderer';
91
92 // Assemble the link
93 link.appendChild(iconContainer);
94 link.appendChild(title);
95 link.appendChild(interaction);
96
97 // Assemble the entry
98 watchLaterEntry.appendChild(link);
99
100 // Insert the Watch Later button after Subscriptions (3rd position)
101 const entries = itemsContainer.querySelectorAll('ytd-mini-guide-entry-renderer');
102 if (entries.length >= 3) {
103 // Insert after Subscriptions
104 entries[2].parentNode.insertBefore(watchLaterEntry, entries[2].nextSibling);
105 } else {
106 // Fallback: append to the end
107 itemsContainer.appendChild(watchLaterEntry);
108 }
109
110 console.log('Watch Later button added successfully');
111 return true;
112 }
113
114 function init() {
115 console.log('YouTube Watch Later Sidebar Button extension started');
116
117 // Wait for the sidebar to be ready
118 const checkAndAdd = () => {
119 if (createWatchLaterButton()) {
120 console.log('Watch Later button initialized');
121 } else {
122 console.log('Retrying to add Watch Later button...');
123 setTimeout(checkAndAdd, 1000);
124 }
125 };
126
127 // Initial attempt
128 if (document.readyState === 'loading') {
129 document.addEventListener('DOMContentLoaded', checkAndAdd);
130 } else {
131 checkAndAdd();
132 }
133
134 // Watch for navigation changes (YouTube is a SPA)
135 const observer = new MutationObserver(() => {
136 createWatchLaterButton();
137 });
138
139 // Observe the body for changes
140 const observeBody = () => {
141 if (document.body) {
142 observer.observe(document.body, {
143 childList: true,
144 subtree: true
145 });
146 } else {
147 setTimeout(observeBody, 100);
148 }
149 };
150
151 observeBody();
152 }
153
154 init();
155})();