Adds a button linking to the channel's playlist on YouTube channel pages
// ==UserScript==
// @name YouTube Channel Playlist Button
// @namespace https://greasyfork.org/en/users/703184-floriegl
// @version 1.3
// @description Adds a button linking to the channel's playlist on YouTube channel pages
// @author floriegl
// @match https://www.youtube.com/*
// @license MIT
// @grant none
// ==/UserScript==
(function () {
'use strict';
let actionModel = undefined;
let channelId = undefined;
const readdObserver = new MutationObserver(() => {
if (!document.getElementById('channel-playlist-link')) {
addPlaylistButton();
}
});
function addPlaylistButton() {
readdObserver.disconnect();
readdObserver.observe(actionModel, { childList: true, subtree: false });
if (!document.getElementById('channel-playlist-link')) {
const link = document.createElement("a");
link.className = "ytFlexibleActionsViewModelAction";
link.id = "channel-playlist-link";
link.style.textDecoration = "none";
const buttonView = document.createElement("button-view-model");
buttonView.className = "ytSpecButtonViewModelHost";
link.appendChild(buttonView);
const button = document.createElement("button");
button.className = "yt-spec-button-shape-next yt-spec-button-shape-next--outline yt-spec-button-shape-next--mono yt-spec-button-shape-next--size-m yt-spec-button-shape-next--enable-backdrop-filter-experiment";
button.setAttribute("aria-label", "Go to Channel Playlist");
buttonView.appendChild(button);
const buttonText = document.createElement("div");
buttonText.className = "yt-spec-button-shape-next__button-text-content";
buttonText.textContent = "Channel Playlist";
button.appendChild(buttonText);
const actionModelRow = actionModel.querySelector('.ytFlexibleActionsViewModelActionRow');
if (actionModelRow) {
link.classList.add("ytFlexibleActionsViewModelActionRowAction");
actionModelRow.appendChild(link);
} else {
actionModel.appendChild(link);
}
}
document.getElementById('channel-playlist-link').href = `/playlist?list=UU${channelId.substring(2)}`;
}
window.addEventListener('yt-navigate-finish', async (e) => {
if (e.detail && e.detail.pageType === 'channel' && e.detail.endpoint && e.detail.endpoint.browseEndpoint && typeof e.detail.endpoint.browseEndpoint.browseId === 'string' && e.detail.endpoint.browseEndpoint.browseId.startsWith('UC')) {
channelId = e.detail.endpoint.browseEndpoint.browseId;
actionModel = document.querySelector('yt-flexible-actions-view-model');
if (!actionModel) {
actionModel = await new Promise((resolve) => {
new MutationObserver((mutations, obs) => {
const item = document.querySelector('yt-flexible-actions-view-model');
if (item) {
resolve(item);
obs.disconnect();
}
}).observe(document, { childList: true, subtree: true });
});
}
addPlaylistButton();
} else {
channelId = null;
readdObserver.disconnect();
}
});
window.addEventListener("resize", () => {
if (actionModel !== document.querySelector('yt-flexible-actions-view-model')) {
actionModel = document.querySelector('yt-flexible-actions-view-model');
if (channelId && actionModel) {
addPlaylistButton();
}
}
});
})();