@@ -27,8 +27,6 @@ export const youtube = async () => {
2727 setTimeout ( run , 100 ) ;
2828 } ) ;
2929
30- if ( location . host . startsWith ( 'm.' ) ) return console . error ( 'Enhancer for Nebula: YouTube mobile is currently not supported!' ) ;
31-
3230 Array . from ( document . querySelectorAll < HTMLElement > ( '.watch-on-nebula' ) ) . forEach ( n => n . remove ( ) ) ;
3331 setTimeout ( run , 0 ) ;
3432
@@ -40,6 +38,14 @@ export const youtube = async () => {
4038 console . log ( 'VID id' , vidDetails . videoId , 'title' , vidDetails . title , 'CHANNEL author' , vidDetails . author , 'Id' , vidDetails . channelId ) ;
4139 run ( { vidID : vidDetails . videoId , videoTitle : vidDetails . title , channelID : vidDetails . channelId , channelNice : vidDetails . author } ) ;
4240 } ) ;
41+ window . addEventListener ( 'state-navigateend' , ( e : CustomEvent ) => {
42+ console . dev . log ( 'NAVIGATE2' , e ) ;
43+ const vidDetails = e . detail ?. data ?. response ?. playerResponse ?. videoDetails as YouTubePlayer . VideoDetails ;
44+ remove ( ) ;
45+ if ( ! vidDetails ) return ;
46+ console . log ( 'VID id' , vidDetails . videoId , 'title' , vidDetails . title , 'CHANNEL author' , vidDetails . author , 'Id' , vidDetails . channelId ) ;
47+ run ( { vidID : vidDetails . videoId , videoTitle : vidDetails . title , channelID : vidDetails . channelId , channelNice : vidDetails . author } ) ;
48+ } ) ;
4349} ;
4450
4551const action = new CancellableRepeatingAction ( ) ;
@@ -55,8 +61,9 @@ const run = debounce(async ({ vidID, videoTitle, channelID, channelNice }: { vid
5561 if ( ! options . watchnebula ) return Array . from ( document . querySelectorAll < HTMLElement > ( '.watch-on-nebula' ) ) . forEach ( n => n . remove ( ) ) ;
5662 let first = true ;
5763 let channelName = channelNice ;
64+ const isMobile = location . host . startsWith ( 'm.' ) ;
5865
59- async function * videoDetailsFromDOM ( ) {
66+ async function * videoDetailsFromDOMDesktop ( ) {
6067 if ( first && vidID && videoTitle && channelID && channelNice ) return ;
6168
6269 const channelElement = document . querySelector < HTMLAnchorElement > (
@@ -68,7 +75,7 @@ const run = debounce(async ({ vidID, videoTitle, channelID, channelNice }: { vid
6875
6976 // accessing custom attributes is not possible from content scripts, so inject this helper
7077 const foundChannelID = await injectFunctionWithReturn ( document . body , ( ) =>
71- ( document . querySelector ( 'ytd-channel-name .yt-simple-endpoint' ) as any ) . data . browseEndpoint . browseId as string ) ;
78+ ( document . querySelector ( 'ytd-channel-name .yt-simple-endpoint' ) as any ) ? .data ? .browseEndpoint ? .browseId as string ) ;
7279 channelID ??= foundChannelID ;
7380 if ( first && channelID !== foundChannelID ) {
7481 channelName = channelNice ;
@@ -82,8 +89,40 @@ const run = debounce(async ({ vidID, videoTitle, channelID, channelNice }: { vid
8289 vidID ??= idElement . getAttribute ( 'video-id' ) ;
8390 }
8491
92+ async function * videoDetailsFromDOMMobile ( ) {
93+ if ( first && vidID && videoTitle && channelID && channelNice ) return ;
94+
95+ const channelElement = document . querySelector < HTMLAnchorElement > ( 'a.slim-owner-icon-and-title[href^="/@"]' ) ;
96+ const titleElement = document . querySelector < HTMLSpanElement > ( 'h2.slim-video-information-title span' ) ;
97+ const idElement = document . querySelector ( 'ytm-slim-video-metadata-section-renderer' ) ;
98+ console . dev . debug ( 'Elements' , ! ! channelElement , ! ! titleElement , ! ! idElement ) ;
99+ if ( ! channelElement || ! titleElement || ! idElement ) yield true ; // retry
100+
101+ // accessing custom attributes is not possible from content scripts, so inject this helper
102+ const foundChannelID = await injectFunctionWithReturn ( document . body , ( ) =>
103+ ( document . querySelector ( 'ytm-slim-owner-renderer' ) as any ) ?. data ?. navigationEndpoint ?. browseEndpoint ?. browseId as string ) ;
104+ channelID ??= foundChannelID ;
105+ if ( first && channelID !== foundChannelID ) {
106+ channelName = channelNice ;
107+ } else if ( ! first && channelID !== foundChannelID ) {
108+ yield true ; // retry
109+ } else {
110+ channelName = channelElement . href . split ( '/' ) . pop ( ) ;
111+ }
112+
113+ videoTitle ??= titleElement . textContent ;
114+ if ( ! vidID ) {
115+ vidID = await injectFunctionWithReturn ( document . body , ( ) =>
116+ ( document . querySelector ( 'ytm-slim-video-metadata-section-renderer' ) as any ) ?. data ?. videoId as string ) ;
117+ }
118+ }
119+
85120 await action . run ( async function * ( ) {
86- yield * videoDetailsFromDOM ( ) ;
121+ if ( isMobile ) {
122+ yield * videoDetailsFromDOMMobile ( ) ;
123+ } else {
124+ yield * videoDetailsFromDOMDesktop ( ) ;
125+ }
87126 const vid : nebulavideo = await getBrowserInstance ( ) . runtime . sendMessage ( { type : BrowserMessage . GET_VID , channelID, channelName, channelNice, videoTitle } ) ;
88127 console . debug ( 'got video information' ,
89128 '\nchannelID:' , channelID , 'channelName:' , channelName , '(' , channelNice , ')' , 'videoTitle:' , videoTitle , 'vidID:' , vidID ,
@@ -98,11 +137,18 @@ const run = debounce(async ({ vidID, videoTitle, channelID, channelNice }: { vid
98137 console . dev . log ( 'Found video:' , vid ) ;
99138 first = false ;
100139
101- const subscribeElement = document . querySelector < HTMLDivElement > ( 'ytd-watch-metadata #subscribe-button, ytd-video-secondary-info-renderer #subscribe-button' ) ;
140+ const subscribeElement = ! isMobile ?
141+ document . querySelector < HTMLDivElement > ( 'ytd-watch-metadata #subscribe-button, ytd-video-secondary-info-renderer #subscribe-button' ) :
142+ document . querySelector < HTMLDivElement > ( 'ytm-slim-owner-renderer .slim-owner-subscribe-button' ) ;
102143 if ( ! subscribeElement ) yield true ; // retry
103144
104- subscribeElement . before ( constructButton ( vid ) ) ;
105- subscribeElement . closest < HTMLDivElement > ( '#top-row.ytd-watch-metadata' ) . style . display = 'block' ; // not the prettiest, but it works
145+ const button = constructButton ( vid , isMobile ) ;
146+ subscribeElement . before ( button ) ;
147+ if ( ! isMobile ) {
148+ subscribeElement . closest < HTMLDivElement > ( '#top-row.ytd-watch-metadata' ) . style . display = 'block' ; // not the prettiest, but it works
149+ } else {
150+ button . style . marginRight = '5px' ;
151+ }
106152 if ( ( window . history . state || { } ) [ '_enhancer_checked' ] === true ) return console . debug ( 'Ignoring video since already processed' ) ;
107153
108154 const { ytOpenTab : doOpenTab , ytMuteOnly : muteOnly , ytReplaceTab : replaceTab } = options ;
0 commit comments