Skip to content

Commit

Permalink
Add support for mobile (m.youtube.com)
Browse files Browse the repository at this point in the history
  • Loading branch information
elliotwaite committed Feb 12, 2022
1 parent e65d706 commit e4cbc69
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 25 deletions.
65 changes: 44 additions & 21 deletions extension/content-script.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
// Setting debug to true will turn on console.log messages used for debugging.
let debug = false

// Variables for handling throttling DOM searches.
const THROTTLE_MS = 100
let hasUnseenMutations = false
Expand All @@ -11,7 +8,8 @@ let curTheme = 0 // No theme set yet.
const THEME_MODERN = 1 // The new Material Design theme.
const THEME_CLASSIC = 2 // The classic theme.
const THEME_GAMING = 3 // The YouTube Gaming theme.
const NUM_THEMES = 3
const THEME_MOBILE = 4 // The YouTube mobile theme (m.youtube.com).
const NUM_THEMES = 4

// `isDarkTheme` will be true if the appearance setting is in dark theme mode.
let isDarkTheme = getComputedStyle(document.body).getPropertyValue('--yt-spec-general-background-a') === ' #181818'
Expand Down Expand Up @@ -76,7 +74,7 @@ THUMBNAIL_SELECTORS[THEME_CLASSIC] = '' +
'.pl-header-thumb'

THUMBNAIL_SELECTORS[THEME_GAMING] = '' +
// Gaming all types except video wall. URL is on the great grandparent,
// Gaming all types except video wall. URL is on the great-grandparent,
// except for search result playlists it is on the grandparent.
'ytg-thumbnail' +
':not([avatar])' +
Expand All @@ -86,6 +84,10 @@ THUMBNAIL_SELECTORS[THEME_GAMING] = '' +
':not(.ytg-compact-gaming-event-renderer)' +
':not(.ytg-playlist-header-renderer)'

THUMBNAIL_SELECTORS[THEME_MOBILE] = '' +
'a.media-item-thumbnail-container, ' +
'a.compact-media-item-image'

// All themes use this selector for video wall videos.
const THUMBNAIL_SELECTOR_VIDEOWALL = '' +
'a.ytp-videowall-still'
Expand Down Expand Up @@ -225,7 +227,7 @@ function getThumbnailsAndIds(thumbnails) {
$(thumbnails).each(function(_, thumbnail) {
// Find the link tag element of the thumbnail and its URL.
let url
if (curTheme === THEME_MODERN) {
if (curTheme === THEME_MODERN || curTheme === THEME_MOBILE) {
// The URL should be on the current element.
url = $(thumbnail).attr('href')

Expand Down Expand Up @@ -257,7 +259,6 @@ function getThumbnailsAndIds(thumbnails) {
}

if (!url) {
if (debug) console.log('DEBUG: Url not found.', thumbnail, url)
return true
}

Expand All @@ -266,8 +267,18 @@ function getThumbnailsAndIds(thumbnails) {
if (previousUrl) {
// Check if this thumbnail is for the same URL as previously.
if (previousUrl === url) {
// If so, continue the next thumbnail.
return true
// If it is for the same URL, continue the next thumbnail, except on
// mobile where we have to make on additional check.
if (curTheme === THEME_MOBILE) {
// On mobile, we have to check to make sure the bar is still present,
// because thumbnails can sometimes be recreated (such as when they
// are scrolled out of view) which causes the bar to be removed.
if ($(thumbnail).children().last().is('ytrb-bar')) {
return true
}
} else {
return true
}
} else {
// If not, remove the old rating bar.
$(thumbnail).children('ytrb-bar').remove()
Expand All @@ -282,8 +293,6 @@ function getThumbnailsAndIds(thumbnails) {
if (match) {
let id = match[1]
thumbnailsAndVideoIds.push([thumbnail, id])
} else if (debug) {
console.log('DEBUG: Match not found.', thumbnail, url)
}
})
return thumbnailsAndVideoIds
Expand Down Expand Up @@ -318,33 +327,47 @@ async function getVideoData(videoId) {

function addRatingBar(thumbnail, videoData) {
// Add a rating bar to each thumbnail.
$(thumbnail).prepend(getRatingBarHtml(videoData))
$(thumbnail).append(getRatingBarHtml(videoData))
}

function addRatingPercentage(thumbnail, videoData) {
// Add the rating text percentage below or next to the thumbnail.
let metadataLine = $(thumbnail).closest(
'.ytd-rich-item-renderer, ' + // Home page.
'.ytd-grid-renderer, ' + // Trending and subscriptions page.
'.ytd-expanded-shelf-contents-renderer, ' + // Also subscriptions page.
'.yt-horizontal-list-renderer, ' + // Channel page.
'.ytd-item-section-renderer, ' + // History page.
'.ytd-horizontal-card-list-renderer, ' + // Gaming page.
'.ytd-playlist-video-list-renderer' // Playlist page.
).find('#metadata-line').last()
let metadataLine
if (curTheme === THEME_MOBILE) {
metadataLine = $(thumbnail).closest('ytm-media-item').find('ytm-badge-and-byline-renderer').last()
} else {
metadataLine = $(thumbnail).closest(
'.ytd-rich-item-renderer, ' + // Home page.
'.ytd-grid-renderer, ' + // Trending and subscriptions page.
'.ytd-expanded-shelf-contents-renderer, ' + // Subscriptions page.
'.yt-horizontal-list-renderer, ' + // Channel page.
'.ytd-item-section-renderer, ' + // History page.
'.ytd-horizontal-card-list-renderer, ' + // Gaming page.
'.ytd-playlist-video-list-renderer' // Playlist page.
).find('#metadata-line').last()
}

if (metadataLine) {
// Remove any previously added percentages.
for (let oldPercentage of metadataLine.children('.ytrb-percentage')) {
oldPercentage.remove()
}
if (curTheme === THEME_MOBILE) {
for (let oldPercentage of metadataLine.children('.ytrb-percentage-separator')) {
oldPercentage.remove()
}
}

// Add new percentage.
if (videoData.rating != null) {
let ratingPercentageHtml = getRatingPercentageHtml(videoData)
let lastSpan = metadataLine.children('span').last()
if (lastSpan.length) {
lastSpan.after(ratingPercentageHtml)
if (curTheme === THEME_MOBILE) {
// On mobile, we have to add the separator dot manually.
lastSpan.after('<span class="ytm-badge-and-byline-separator ytrb-percentage-separator" aria-hidden="true">•</span>')
}
} else {
// This handles metadata lines that are initially empty, which
// occurs on playlist pages. We prepend the rating percentage as well
Expand Down
24 changes: 23 additions & 1 deletion extension/css/bar-bottom.css
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,26 @@ ytg-thumbnail-overlay-time-status-renderer /* Gaming */
position: absolute !important;
bottom: var(--ytrb-bar-height) !important;
height: 15px !important;
}
}

/* Reposition the thumbnail time (mobile theme). */
ytm-thumbnail-overlay-time-status-renderer {
position: absolute;
bottom: calc(var(--ytrb-bar-height) + 1px) !important
}

/* Reposition the thumbnail playback status (mobile theme). */
ytm-thumbnail-overlay-playback-status-renderer {
position: absolute;
bottom: calc(var(--ytrb-bar-height) + 1px) !important
}

/* Reposition the thumbnail watched bar (mobile theme). */
ytm-app .video-thumbnail-overlay-bottom-group {
top: 0;
}

ytm-thumbnail-overlay-resume-playback-renderer {
position: absolute;
top: 0 !important;
}
19 changes: 18 additions & 1 deletion extension/css/bar.css
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,21 @@ ytrb-dislikes {
/* For YouTube Gaming. Prevents the rating bar from showing over the top menu bar. */
ytg-thumbnail .ytrb-bar {
z-index: 1;
}
}

/* For YouTube mobile. Keeps the rating bar contained in the thumbnail. */
ytm-app a.media-item-thumbnail-container, ytm-app a.compact-media-item-image {
position: relative;
}

/* For YouTube mobile. Keeps the rating bar below the header. */
ytm-app a.media-item-thumbnail-container ytrb-bar, ytm-app a.compact-media-item-image ytrb-bar {
z-index: auto;
}

/* On mobile, make the bar full width. */
ytm-media-item ytrb-bar {
margin-left: -12px;
margin-right: -12px;
width: calc(100% + 24px);
}
4 changes: 2 additions & 2 deletions extension/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"manifest_version": 2,
"name": "Thumbnail Rating Bar for YouTube™",
"version": "1.7.2",
"version": "1.8.1",
"description": "Displays a rating bar (likes/dislikes) on the bottom of every YouTube™ video thumbnail.",
"author": "Elliot Waite",
"icons": {
Expand Down Expand Up @@ -54,4 +54,4 @@
"css/bar-top.css",
"css/bar.css"
]
}
}

0 comments on commit e4cbc69

Please sign in to comment.