Youtube compact sidebar+

Add more buttons in compact sidebar/mini guide

当前为 2024-06-11 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name                   Youtube compact sidebar+
// @name:pt-BR             Youtube barra lateral+
// @namespace              https://greasyfork.org/users/821661
// @match                  https://www.youtube.com/*
// @grant                  GM_xmlhttpRequest
// @version                0.1
// @author                 hdyzen
// @description            Add more buttons in compact sidebar/mini guide
// @description:pt-BR      Adiciona mais botões a barra lateral
// @license                GPL-3.0
// ==/UserScript==
'use strict';

let channelId; // Channel ID
const defaultLang = 'en'; // If the lang is not in the labels use this language
const lang = document.documentElement.lang; // Lang of HTML

// Labels
const labels = {
    'pt-BR': {
        download: 'Download',
        liked: 'Gostei',
        watchLater: 'Depois',
        yourVideos: 'Videos',
        playlists: 'Playlists',
        history: 'Histórico',
        yourChannel: 'Canal',
    },
    'en': {
        download: 'Download',
        liked: 'Liked',
        watchLater: 'Later',
        yourVideos: 'Videos',
        playlists: 'Playlists',
        history: 'History',
        yourChannel: 'Channel',
    },
};

// Get channel id
async function getChannelId() {
    const urlGet = 'https://studio.youtube.com/';

    GM_xmlhttpRequest({
        url: urlGet,
        onload: e => {
            if (e.finalUrl !== urlGet) {
                console.log('NOT FOUND ID:', e);
            }
            const id = e.responseText.match(/"CHANNEL_ID":"([a-zA-Z0-9]+)"/)?.[1];

            if (!id) {
                console.log('NOT FOUND ID:', e);
            }

            channelId = id;
        },
    });
}
getChannelId();

// Mini guide item template
function getTemplate(path, label, href) {
    return `
    <ytd-mini-guide-entry-renderer class="style-scope ytd-mini-guide-renderer" system-icons="" role="tab" tabindex="0" aria-selected="false" aria-label="${label}">
        <a id="endpoint" tabindex="-1" class="yt-simple-endpoint style-scope ytd-mini-guide-entry-renderer" title="Você" href="${href}">
        <svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24" focusable="false" style="color: inherit; fill: currentColor; pointer-events: none; display: inline-flexbox; display: -moz-inline-box; display: inline-flex; -moz-box-align: center; align-items: center; -moz-box-pack: center; justify-content: center; position: relative; vertical-align: middle; fill: var(--iron-icon-fill-color,currentcolor); stroke: var(--iron-icon-stroke-color,none); width: var(--iron-icon-width,24px); height: var(--iron-icon-height,24px); animation: var(--iron-icon-animation); margin-top: var(--iron-icon-margin-top); margin-right: var(--iron-icon-margin-right); margin-bottom: var(--iron-icon-margin-bottom); margin-left: var(--iron-icon-margin-left); padding: var(--iron-icon-padding);">${path}</svg>
            <span class="title style-scope ytd-mini-guide-entry-renderer">${label}</span>
        </a>
    </ytd-mini-guide-entry-renderer>
`;
}

// Render item in mini guide
function renderItem(element) {
    const lastChild = element[element.length - 1];
    const items = {
        download: { href: '/feed/downloads', path: '<path d="M17 18v1H6v-1h11zm-.5-6.6-.7-.7-3.8 3.7V4h-1v10.4l-3.8-3.8-.7.7 5 5 5-4.9z"></path>' },
        liked: { href: '/playlist?list=LL', path: '<path d="M18.77,11h-4.23l1.52-4.94C16.38,5.03,15.54,4,14.38,4c-0.58,0-1.14,0.24-1.52,0.65L7,11H3v10h4h1h9.43 c1.06,0,1.98-0.67,2.19-1.61l1.34-6C21.23,12.15,20.18,11,18.77,11z M7,20H4v-8h3V20z M19.98,13.17l-1.34,6 C18.54,19.65,18.03,20,17.43,20H8v-8.61l5.6-6.06C13.79,5.12,14.08,5,14.38,5c0.26,0,0.5,0.11,0.63,0.3 c0.07,0.1,0.15,0.26,0.09,0.47l-1.52,4.94L13.18,12h1.35h4.23c0.41,0,0.8,0.17,1.03,0.46C19.92,12.61,20.05,12.86,19.98,13.17z"></path>' },
        watchLater: { href: '/playlist?list=WL', path: '<path d="M14.97 16.95 10 13.87V7h2v5.76l4.03 2.49-1.06 1.7zM12 3c-4.96 0-9 4.04-9 9s4.04 9 9 9 9-4.04 9-9-4.04-9-9-9m0-1c5.52 0 10 4.48 10 10s-4.48 10-10 10S2 17.52 2 12 6.48 2 12 2z"></path>' },
        yourVideos: { href: `https://studio.youtube.com/channel/${channelId}/videos`, path: '<path d="m10 8 6 4-6 4V8zm11-5v18H3V3h18zm-1 1H4v16h16V4z"></path>' },
        playlists: { href: '/feed/playlists', path: '<path d="M22 7H2v1h20V7zm-9 5H2v-1h11v1zm0 4H2v-1h11v1zm2 3v-8l7 4-7 4z"></path>' },
        history: { href: '/feed/history', path: '<g><path d="M14.97 16.95 10 13.87V7h2v5.76l4.03 2.49-1.06 1.7zM22 12c0 5.51-4.49 10-10 10S2 17.51 2 12h1c0 4.96 4.04 9 9 9s9-4.04 9-9-4.04-9-9-9C8.81 3 5.92 4.64 4.28 7.38c-.11.18-.22.37-.31.56L3.94 8H8v1H1.96V3h1v4.74c.04-.09.07-.17.11-.25.11-.22.23-.42.35-.63C5.22 3.86 8.51 2 12 2c5.51 0 10 4.49 10 10z"></path></g>' },
        yourChannel: { href: `/channel/${channelId}`, path: '<path d="M4 20h14v1H3V6h1v14zM6 3v15h15V3H6zm2.02 14c.36-2.13 1.93-4.1 5.48-4.1s5.12 1.97 5.48 4.1H8.02zM11 8.5a2.5 2.5 0 015 0 2.5 2.5 0 01-5 0zm3.21 3.43A3.507 3.507 0 0017 8.5C17 6.57 15.43 5 13.5 5S10 6.57 10 8.5c0 1.69 1.2 3.1 2.79 3.43-3.48.26-5.4 2.42-5.78 5.07H7V4h13v13h-.01c-.38-2.65-2.31-4.81-5.78-5.07z"></path>' },
    };

    Object.entries(items).forEach(([key, value]) => {
        lastChild.insertAdjacentHTML('afterend', getTemplate(value.path, labels[lang] === undefined ? labels[defaultLang][key] : labels[lang][key], value.href));
    });
}

// Wait mini guide childs
const observer = new MutationObserver(mutations => {
    const items = document.getElementsByTagName('ytd-mini-guide-renderer')?.[0]?.children?.[0].children;
    if (items.length === 4) {
        renderItem(items);
        observer.disconnect();
    }
});

observer.observe(document.body, { childList: true, subtree: true });

function addCSS(text) {
    document.documentElement.insertAdjacentHTML('beforeend', `<style rel='stylesheet'>${text}</style>`);
}

// Scroll to mini guide
addCSS(`
ytd-mini-guide-renderer.ytd-app {
    overflow: auto;
} 
`);