22// @name Improve Adult Experience
33// @description Skip intros, set better default quality/duration filters, make unwanted video previews transparent, workaround load failures. Supported websites: pornhub.com, xvideos.com, anysex.com, spankbang.com, porntrex.com, txxx.com, xnxx.com, xhamster.com, vxxx.com
44// @icon https://external-content.duckduckgo.com/ip3/pornhub.com.ico
5- // @version 0.32
5+ // @version 0.33
66// @downloadURL https://userscripts.codonaft.com/improve-adult-experience.user.js
77// ==/UserScript==
88
@@ -27,15 +27,32 @@ if (document.head?.querySelector('link[type="application/opensearchdescription+x
2727const UNWANTED = '__unwanted' ;
2828const HIDE = '__hide' ;
2929
30+ let unmuted = false ;
31+ let pageIsHidden = true ;
32+ let willRedirect = false ;
33+
3034const origin = window . location . origin ;
3135const validLink = node => node ?. tagName === 'A' && node ?. href ?. startsWith ( origin ) ;
3236const redirect = href => {
37+ if ( willRedirect ) return ;
3338 window . stop ( ) ;
34- window . location . href = href
39+ if ( pageIsHidden ) {
40+ willRedirect = true ;
41+ window . addEventListener ( 'focus' , _ => window . location . href = href , { once : true } ) ;
42+ return ;
43+ }
44+ window . location . href = href ;
3545} ;
3646const refresh = _ => redirect ( window . location ) ;
3747const refreshWithNoHistory = _ => {
48+ if ( willRedirect ) return ;
49+ console . log ( 'refreshWithNoHistory' ) ;
3850 window . stop ( ) ;
51+ if ( pageIsHidden ) {
52+ willRedirect = true ;
53+ window . addEventListener ( 'focus' , _ => window . location . replace ( window . location ) , { once : true } ) ;
54+ return ;
55+ }
3956 window . location . replace ( window . location ) ;
4057} ;
4158
@@ -201,7 +218,6 @@ const init = args => {
201218 video . currentTime = time ;
202219 }
203220 playIfPaused ( video ) ;
204- //video.muted = false; // TODO
205221 playbackInitiated = true ;
206222 } , { once : true } ) ;
207223
@@ -213,7 +229,6 @@ const init = args => {
213229 } ;
214230
215231 let lastHref = window . location . href ;
216- //let focusInterval;
217232 let disallowGeneralAutoplay = false ;
218233 subscribeOnChanges ( body , 'a, div, input, li, span, var, video' , ( node , _observer ) => {
219234 const newHref = window . location . href ;
@@ -224,13 +239,10 @@ const init = args => {
224239 loadedMetadata = false ;
225240 playbackInitiated = false ;
226241 playbackStarted = false ;
227- //if (focusInterval) {
228- // clearInterval(focusInterval);
229- if ( refreshOnPageChange ) {
230- refreshWithNoHistory ( ) ;
231- return true ;
232- }
233- //}
242+ if ( refreshOnPageChange ) {
243+ refreshWithNoHistory ( ) ;
244+ return false ;
245+ }
234246 }
235247
236248 if ( MINOR_IMPROVEMENTS && HIDE_EXTERNAL_LINKS && node . tagName === 'A' && node . href . length > 0 && ! validLink ( node ) ) {
@@ -248,6 +260,7 @@ const init = args => {
248260 }
249261
250262 document . addEventListener ( 'keydown' , event => {
263+ pageIsHidden = false ;
251264 if ( event . ctrlKey || event . altKey || event . metaKey || document . activeElement . tagName === 'INPUT' ) return ;
252265
253266 if ( [ 'KeyS' , 'Slash' ] . includes ( event . code ) ) {
@@ -269,12 +282,10 @@ const init = args => {
269282 }
270283 } ;
271284
272- // TODO: subscribe on both?
273285 if ( formOrButton ?. tagName === 'BUTTON' ) {
274286 formOrButton . addEventListener ( 'click' , handleSearch , true ) ;
275- } else {
276- searchForm ?. addEventListener ( 'submit' , handleSearch , true ) ;
277287 }
288+ searchForm ?. addEventListener ( 'submit' , handleSearch , true ) ;
278289 return true ;
279290 }
280291
@@ -328,57 +339,94 @@ const init = args => {
328339
329340 console . log ( 'detected main video' , video ) ;
330341
331- [ 'loadstart' , 'loadedmetadata' , 'loadeddata' , 'seeked' , 'play' ] . forEach ( i => {
342+ const maybeUnmute = _ => {
343+ if ( unmuted || pageIsHidden ) return ;
344+
345+ console . log ( 'unmute' ) ;
346+ video . muted = false ;
347+ unmuted = true ;
348+ } ;
349+
350+ const maybeSetRandomPosition = _ => {
351+ if ( RANDOM_POSITION && ! playbackStarted && video . duration > 0 && video . currentTime === 0 ) {
352+ console . log ( 'set random position' ) ;
353+ video . currentTime = random ( video . duration / 4 , video . duration / 3 )
354+ }
355+ } ;
356+
357+ [ 'loadstart' , 'loadeddata' , 'seeked' ] . forEach ( i => {
332358 video . addEventListener ( i , _ => {
333359 console . log ( i ) ;
334- if ( RANDOM_POSITION && ! playbackStarted && video . duration > 0 && video . currentTime === 0 ) {
335- console . log ( 'set random position' ) ;
336- video . currentTime = random ( video . duration / 4 , video . duration / 3 )
337- }
338- } ) ;
360+ maybeSetRandomPosition ( ) ;
361+ } , { once : true } ) ;
339362 } ) ;
340363
341364 video . addEventListener ( 'loadedmetadata' , _ => {
342- loadedMetadata = true ;
343365 console . log ( 'loadedmetadata, duration' , video . duration ) ;
344- } ) ;
366+ loadedMetadata = true ;
367+ maybeSetRandomPosition ( ) ;
368+ } , { once : true } ) ;
345369
346370 video . addEventListener ( 'play' , _ => {
347371 console . log ( 'playback is initiated' ) ;
348372 playbackInitiated = true ;
349- } ) ;
373+ maybeSetRandomPosition ( ) ;
374+ } , { once : true } ) ;
350375
351376 video . addEventListener ( 'playing' , _ => {
352377 console . log ( 'playback is started' )
353378 playbackStarted = true ;
354379 video . focus ( ) ;
355- } ) ;
380+ } , { once : true } ) ;
356381
357- video . addEventListener ( 'stalled' , refresh ) ;
382+ video . addEventListener ( 'stalled' , _ => {
383+ console . log ( 'stalled' ) ;
384+ refresh ( ) ;
385+ } , { once : true } ) ;
358386
359387 if ( AUTOPLAY ) {
360388 console . log ( 'setting autoplay' ) ;
361389 video . addEventListener ( 'loadstart' , _ => {
362390 console . log ( 'loadstart autoplay' ) ;
391+ maybeSetRandomPosition ( ) ;
363392 playIfPaused ( video ) ;
364393 } , { once : true } ) ;
394+
395+ document . addEventListener ( 'mousemove' , _ => {
396+ console . log ( 'mousemove' ) ;
397+ pageIsHidden = false ;
398+ maybeUnmute ( ) ;
399+ if ( ! playbackStarted ) {
400+ playIfPaused ( video ) ; // TODO: xnxx
401+ }
402+ } , { once : true } ) ;
403+
404+ document . addEventListener ( 'visibilitychange' , _ => {
405+ pageIsHidden = document . hidden ;
406+ console . log ( 'visibilitychange pageIsHidden' , pageIsHidden ) ;
407+ maybeUnmute ( ) ;
408+ } , { once : true } ) ;
365409 }
366410
367411 if ( MINOR_IMPROVEMENTS ) {
368412 video . tabindex = - 1 ;
369- // TODO: stop when page is not visible
370- /*focusInterval = setInterval(_ => {
413+ setInterval ( _ => {
371414 const active = document . activeElement ;
372- if (active !== video && active.tagName !== 'INPUT') {
373- console.log('restore focus to player');
374- video.focus({ preventScroll: true });
415+ if ( ! pageIsHidden && active !== video && active . tagName !== 'INPUT' ) {
416+ console . log ( 'restoring focus to player' ) ;
417+ video . focus ( { preventScroll : true } ) ; // FIXME
375418 }
376- }, 3000);*/
419+ } , 3000 ) ;
377420 }
378421
379422 initializedVideo = true ;
380- console . log ( 'load' ) ;
381- video . load ( ) ;
423+ if ( playSelector ) {
424+ maybeSetRandomPosition ( ) ; // TODO
425+ playIfPaused ( video ) ;
426+ } else {
427+ console . log ( 'load' ) ;
428+ video . load ( ) ;
429+ }
382430
383431 return true ;
384432 } ) ;
@@ -492,6 +540,7 @@ if (IGNORE_HOSTS.includes(shortDomain)) {
492540 console . log ( 'normal player' , normalPlayer . duration , normalPlayer . paused , normalPlayer ) ;
493541 setTimeout ( _ => {
494542 if ( normalPlayer . paused ) {
543+ console . log ( 'still paused, refreshing' ) ;
495544 refresh ( ) ;
496545 }
497546 } , 25000 ) ;
@@ -601,14 +650,14 @@ if (IGNORE_HOSTS.includes(shortDomain)) {
601650 if ( video . paused ) {
602651 simulateClick ( document , playButton ) ;
603652 }
604- } ) ;
653+ } , { once : true } ) ;
605654 }
606655 video . addEventListener ( 'loadedmetadata' , _ => {
607656 if ( disliked ( body ) ) {
608657 setUnwanted ( url , Number . MAX_SAFE_INTEGER ) ;
609658 }
610659 video . currentTime = random ( video . duration / 4 , video . duration / 3 ) ;
611- } ) ;
660+ } , { once : true } ) ;
612661 body . querySelector ( 'div.mgp_gridMenu' ) ?. addEventListener ( 'click' , _ => setTimeout ( _ => {
613662 if ( video . paused ) {
614663 console . log ( 'paused on grid menu' ) ;
@@ -900,6 +949,8 @@ if (IGNORE_HOSTS.includes(shortDomain)) {
900949 css : '.gold-plate, .premium-results-line { display: none !important }' ,
901950 searchInputSelector : 'input[type="text"][name="k"][placeholder="Search..."], input[type="text"]' ,
902951 onSearch : ( query , _form ) => redirect ( `${ searchPath } /${ query } ` ) ,
952+ playSelector : 'div#html5video span[title="Play"]' ,
953+ videoSelector : 'div#html5video video' ,
903954 // TODO: thumbnailSelector: 'div.thumb',
904955 // TODO: qualitySelector: 'div.video-hd',
905956 // TODO: durationSelector: 'span.right',
0 commit comments