Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name YouTube Subscriptions – List Layout + Inline Descriptions (Fixed Flex)
- // @namespace marty-listview
- // @version 1.2
- // @description Horizontal list with 160px thumbs and inline descriptions.
- // @match https://www.youtube.com/feed/subscriptions*
- // @run-at document-end
- // ==/UserScript==
- (function() {
- 'use strict';
- const THUMB_WIDTH = 160;
- const css = `
- /* Each item becomes a full-width row */
- ytd-rich-item-renderer.ytd-rich-grid-renderer {
- display: block !important;
- width: 100% !important;
- padding: 0 !important;
- margin-bottom: 16px !important;
- margin-left: 16px !important;
- border-bottom: 1px solid var(--yt-spec-10-percent-layer) !important;
- }
- ytd-rich-item-renderer.ytd-rich-shelf-renderer {
- max-width: 15vw !important;
- }
- .shortsLockupViewModelHost {
- width: 12vw !important;
- }
- /* Remove clicking anywhere on the item from opening the video, only title and thumbnails should open video */
- .yt-lockup-view-model {
- cursor: auto !important;
- pointer-events: none;
- }
- .yt-lockup-view-model__content-image, .yt-lockup-metadata-view-model__title, .yt-lockup-metadata-view-model__menu-button {
- pointer-events: all;
- }
- /* THE REAL FLEX TARGET — THIS IS THE FIX */
- .yt-lockup-view-model.yt-lockup-view-model--vertical {
- display: flex !important;
- flex-direction: row !important;
- align-items: flex-start !important;
- gap: 16px !important;
- }
- /* Thumbnail */
- .yt-lockup-view-model__content-image {
- width: ${THUMB_WIDTH}px !important;
- min-width: ${THUMB_WIDTH}px !important;
- max-width: ${THUMB_WIDTH}px !important;
- flex-shrink: 0 !important;
- }
- .yt-lockup-view-model__content-image img {
- width: 100% !important;
- height: auto !important;
- border-radius: 6px !important;
- object-fit: cover !important;
- }
- /* Text column */
- yt-lockup-metadata-view-model {
- flex: 1 !important;
- max-width: 100% !important;
- }
- /* Title */
- .yt-lockup-metadata-view-model__title {
- font-size: 1.15rem !important;
- font-weight: 600 !important;
- margin-bottom: 6px !important;
- line-height: 1.3 !important;
- white-space: normal !important;
- }
- .yt-lockup-metadata-view-model__text-container .yt-lockup-metadata-view-model__heading-reset .yt-lockup-metadata-view-model__title span.yt-core-attributed-string.yt-core-attributed-string--white-space-pre-wrap {
- font-size: 1.75rem !important;
- }
- /* Metadata */
- .marty-meta-inline {
- font-size: 1.1rem !important;
- color: var(--yt-spec-text-secondary) !important;
- margin-bottom: 4px !important;
- }
- /* Description */
- .marty-desc {
- font-size: 1.5rem !important;
- color: var(--yt-spec-text-secondary) !important;
- line-height: 1.45 !important;
- white-space: normal !important;
- }
- .yt-lockup-view-model__metadata {
- position: relative;
- display: flex;
- min-width: 0;
- flex-direction: column;
- width: 80%;
- }
- /* put menu button after Avatar (for easier access) */
- .yt-lockup-metadata-view-model__avatar {
- order: 0;
- }
- .yt-lockup-metadata-view-model__menu-button {
- position: relative !important;
- order: 1;
- right: 0 !important;
- }
- .yt-lockup-metadata-view-model__text-container {
- order: 2;
- }
- `;
- function extractVideoId(href) {
- try {
- const url = new URL(href, location.origin);
- return url.searchParams.get('v');
- } catch {
- const m = href.match(/v=([^&]+)/);
- return m ? m[1] : null;
- }
- }
- async function fetchDescription(videoId) {
- if (!videoId) return '';
- try {
- const res = await fetch(`https://www.youtube.com/watch?v=${videoId}`, {
- credentials: 'same-origin'
- });
- const html = await res.text();
- const match = html.match(/ytInitialPlayerResponse\s*=\s*(\{.*?\});/s);
- if (!match) return '';
- const json = JSON.parse(match[1]);
- let desc = json?.videoDetails?.shortDescription || '';
- const sentences = desc.match(/[^.!?]+[.!?]+/g) || [];
- desc = sentences.slice(0, 2).join(' ').trim();
- return desc
- //return desc.replace(/\n+/g, ' ').replace(/\s+/g, ' ').trim().slice(0, 330) + (desc.length > 330 ? '…' : '');
- } catch {
- return '';
- }
- }
- async function enhanceDescriptions() {
- const items = document.querySelectorAll('ytd-rich-item-renderer yt-lockup-view-model');
- if (!items.length) return;
- for (const lockup of items) {
- if (lockup.dataset.martyDone === '1') continue;
- const thumbLink = lockup.querySelector('a.yt-lockup-view-model__content-image');
- if (!thumbLink) continue;
- const href = new URL(thumbLink.getAttribute('href'), location.origin).href;
- const videoId = extractVideoId(href);
- if (!videoId) continue;
- const metaContainer =
- lockup.querySelector('.yt-lockup-metadata-view-model__text-container') ||
- lockup.querySelector('yt-lockup-metadata-view-model');
- if (!metaContainer) continue;
- const metaRows = lockup.querySelectorAll('.yt-content-metadata-view-model__metadata-row span');
- const channel = metaRows?.[0]?.innerText?.trim() || '';
- const views = metaRows?.[1]?.innerText?.trim() || '';
- const timeAgo = metaRows?.[2]?.innerText?.trim() || '';
- const metaLine = [channel, views, timeAgo].filter(Boolean).join(' • ');
- const metaDiv = document.createElement('div');
- metaDiv.className = 'marty-meta-inline';
- metaDiv.textContent = metaLine;
- const descDiv = document.createElement('div');
- descDiv.className = 'marty-desc';
- descDiv.textContent = '…';
- metaContainer.appendChild(metaDiv);
- metaContainer.appendChild(descDiv);
- lockup.dataset.martyDone = '1';
- const desc = await fetchDescription(videoId);
- descDiv.textContent = desc;
- }
- }
- function init() {
- const ele = document.getElementById('fixSubscriptionListViewStyle');
- if (window.location.pathname === '/feed/subscriptions' && !ele) {
- const style = document.createElement('style');
- style.textContent = css;
- style.id = 'fixSubscriptionListViewStyle';
- document.head.appendChild(style);
- setTimeout(enhanceDescriptions, 800);
- setTimeout(enhanceDescriptions, 2000);
- } else if (window.location.pathname !== '/feed/subscriptions' && ele) {
- ele.parentElement.removeChild(ele);
- }
- }
- window.addEventListener('yt-navigate-finish', init);
- window.addEventListener('load', init);
- })();
Advertisement
Add Comment
Please, Sign In to add comment