1- import { isOnInvidious , parseYouTubeVideoIDFromURL } from "../../maze-utils/src/video" ;
1+ import { extractVideoID , isOnInvidious } from "../../maze-utils/src/video" ;
22import Config from "../config" ;
33import { getHasStartSegment , getVideoLabel } from "./videoLabels" ;
44import { getThumbnailSelector , setThumbnailListener } from "../../maze-utils/src/thumbnailManagement" ;
55import { VideoID } from "../types" ;
66import { getSegmentsForVideo } from "./segmentData" ;
7+ import { onMobile } from "../../maze-utils/src/pageInfo" ;
78
89export async function handleThumbnails ( thumbnails : HTMLImageElement [ ] ) : Promise < void > {
910 await Promise . all ( thumbnails . map ( ( t ) => {
@@ -18,7 +19,7 @@ export async function labelThumbnail(thumbnail: HTMLImageElement): Promise<HTMLE
1819 return null ;
1920 }
2021
21- const videoID = extractVideoID ( thumbnail ) ;
22+ const videoID = await extractVideoIDFromElement ( thumbnail ) ;
2223 if ( ! videoID ) {
2324 hideThumbnailLabel ( thumbnail ) ;
2425 return null ;
@@ -61,7 +62,7 @@ function thumbnailHoverListener(e: MouseEvent) {
6162 let fetched = false ;
6263 const preFetch = async ( ) => {
6364 fetched = true ;
64- const videoID = extractVideoID ( thumbnail ) ;
65+ const videoID = await extractVideoIDFromElement ( thumbnail ) ;
6566 if ( videoID && await getHasStartSegment ( videoID ) ) {
6667 void getSegmentsForVideo ( videoID , false ) ;
6768 }
@@ -84,18 +85,28 @@ function thumbnailHoverListener(e: MouseEvent) {
8485function getLink ( thumbnail : HTMLImageElement ) : HTMLAnchorElement | null {
8586 if ( isOnInvidious ( ) ) {
8687 return thumbnail . parentElement as HTMLAnchorElement | null ;
87- } else if ( thumbnail . nodeName . toLowerCase ( ) === "yt-thumbnail-view-model" ) {
88- return thumbnail . closest ( "yt-lockup-view-model" ) ?. querySelector ( "a.yt-lockup-metadata-view-model-wiz__title" ) ;
88+ } else if ( ! onMobile ( ) ) {
89+ const link = thumbnail . querySelector ( "a#thumbnail, a.reel-item-endpoint, a.yt-lockup-metadata-view-model__title, a.yt-lockup-metadata-view-model__title-link, a.yt-lockup-view-model__content-image, a.yt-lockup-metadata-view-model-wiz__title" ) as HTMLAnchorElement ;
90+ if ( link ) {
91+ return link ;
92+ } else if ( thumbnail . nodeName === "YTD-HERO-PLAYLIST-THUMBNAIL-RENDERER"
93+ || thumbnail . nodeName === "YT-THUMBNAIL-VIEW-MODEL"
94+ ) {
95+ return thumbnail . closest ( "a" ) as HTMLAnchorElement ;
96+ } else {
97+ return null ;
98+ }
8999 } else {
90- return thumbnail . querySelector ( "#thumbnail" ) ;
100+ // Big thumbnails, compact thumbnails, shorts, channel feature, playlist header
101+ return thumbnail . querySelector ( "a.media-item-thumbnail-container, a.compact-media-item-image, a.reel-item-endpoint, :scope > a, .amsterdam-playlist-thumbnail-wrapper > a" ) as HTMLAnchorElement ;
91102 }
92103}
93104
94- function extractVideoID ( thumbnail : HTMLImageElement ) : VideoID | null {
105+ async function extractVideoIDFromElement ( thumbnail : HTMLImageElement ) : Promise < VideoID | null > {
95106 const link = getLink ( thumbnail ) ;
96107 if ( ! link || link . nodeName !== "A" || ! link . href ) return null ; // no link found
97108
98- return parseYouTubeVideoIDFromURL ( link . href ) ?. videoID ;
109+ return await extractVideoID ( link ) ;
99110}
100111
101112function getOldThumbnailLabel ( thumbnail : HTMLImageElement ) : HTMLElement | null {
0 commit comments