2020-11-07 05:48:07 +02:00
import { calcImageInBox } from "../helpers/dom" ;
2020-09-17 22:33:23 +03:00
import appDocsManager , { MyDocument } from "../lib/appManagers/appDocsManager" ;
2020-08-26 14:04:37 +03:00
import { wrapVideo } from "./wrappers" ;
import { renderImageFromUrl } from "./misc" ;
2020-09-21 20:34:19 +03:00
import { LazyLoadQueueRepeat2 } from "./lazyLoadQueue" ;
import animationIntersector from "./animationIntersector" ;
2020-10-07 16:57:33 +03:00
import Scrollable from "./scrollable" ;
2020-09-23 23:29:53 +03:00
import { CancellablePromise , deferredPromise } from "../helpers/cancellablePromise" ;
2020-08-26 14:04:37 +03:00
const width = 400 ;
const maxSingleWidth = width - 100 ;
const height = 100 ;
export default class GifsMasonry {
2020-09-21 20:34:19 +03:00
public lazyLoadQueue : LazyLoadQueueRepeat2 ;
private scrollPromise : CancellablePromise < void > = Promise . resolve ( ) ;
constructor ( private element : HTMLElement , private group : string , private scrollable : Scrollable ) {
this . lazyLoadQueue = new LazyLoadQueueRepeat2 ( undefined , ( target , visible ) = > {
if ( visible ) {
this . processVisibleDiv ( target ) ;
} else {
this . processInvisibleDiv ( target ) ;
}
} ) ;
2020-10-04 02:10:57 +03:00
/ * s e t I n t e r v a l ( ( ) = > {
2020-09-21 20:34:19 +03:00
// @ts-ignore
const players = animationIntersector . byGroups [ group ] ;
if ( players ) {
console . log ( ` GIFS RENDERED IN ${ group } : ` , players . length , players . filter ( p = > ! p . animation . paused ) . length , this . lazyLoadQueue . intersector . getVisible ( ) . length ) ;
}
2020-10-04 02:10:57 +03:00
} , . 25 e3 ) ; * /
2020-09-21 20:34:19 +03:00
let timeout = 0 ;
// memory leak
scrollable . container . addEventListener ( 'scroll' , ( ) = > {
if ( timeout ) {
clearTimeout ( timeout ) ;
} else {
this . scrollPromise = deferredPromise < void > ( ) ;
//animationIntersector.checkAnimations(true, group);
}
timeout = window . setTimeout ( ( ) = > {
timeout = 0 ;
this . scrollPromise . resolve ( ) ;
//animationIntersector.checkAnimations(false, group);
} , 150 ) ;
} ) ;
2020-08-26 14:04:37 +03:00
}
2020-10-04 02:10:57 +03:00
processVisibleDiv = ( div : HTMLElement ) = > {
2020-09-21 20:34:19 +03:00
const video = div . querySelector ( 'video' ) ;
if ( video ) {
return ;
}
2020-10-04 02:10:57 +03:00
//console.log('processVisibleDiv');
2020-09-21 20:34:19 +03:00
const load = ( ) = > {
const docID = div . dataset . docID ;
const doc = appDocsManager . getDoc ( docID ) ;
const promise = this . scrollPromise . then ( ( ) = > {
const promise = wrapVideo ( {
doc ,
container : div as HTMLDivElement ,
lazyLoadQueue : null ,
//lazyLoadQueue: EmoticonsDropdown.lazyLoadQueue,
group : this.group ,
noInfo : true ,
} ) ;
promise . finally ( ( ) = > {
const video = div . querySelector ( 'video' ) ;
div . style . opacity = '' ;
const img = div . querySelector ( 'img' ) ;
img && img . classList . add ( 'hide' ) ;
if ( video && ! video . parentElement ) {
setTimeout ( ( ) = > {
video . src = '' ;
video . load ( ) ;
const animations = animationIntersector . getAnimations ( video ) ;
animations . forEach ( item = > {
animationIntersector . checkAnimation ( item , true , true ) ;
} ) ;
} , 0 ) ;
}
//clearTimeout(timeout);
if ( ! this . lazyLoadQueue . intersector . isVisible ( div ) ) {
this . processInvisibleDiv ( div ) ;
}
} ) ;
return promise ;
} ) ;
/ * l e t t i m e o u t = w i n d o w . s e t T i m e o u t ( ( ) = > {
console . error ( 'processVisibleDiv timeout' , div , doc ) ;
} , 1 e3 ) ; * /
return promise ;
} ;
//return load();
this . lazyLoadQueue . push ( { div , load } ) ;
} ;
2020-10-04 02:10:57 +03:00
processInvisibleDiv = async ( div : HTMLElement ) = > {
2020-09-21 20:34:19 +03:00
return this . scrollPromise . then ( async ( ) = > {
//return;
if ( this . lazyLoadQueue . intersector . isVisible ( div ) ) {
return ;
}
const video = div . querySelector ( 'video' ) ;
const img = div . querySelector ( 'img' ) ;
if ( img ) {
img && img . classList . remove ( 'hide' ) ;
await new Promise ( ( resolve ) = > {
window . requestAnimationFrame ( ( ) = > window . requestAnimationFrame ( resolve ) ) ;
} ) ;
}
if ( this . lazyLoadQueue . intersector . isVisible ( div ) ) {
return ;
}
if ( video ) {
video . remove ( ) ;
video . src = '' ;
video . load ( ) ;
const animations = animationIntersector . getAnimations ( video ) ;
animations . forEach ( item = > {
animationIntersector . checkAnimation ( item , true , true ) ;
} ) ;
}
} ) ;
} ;
public add ( doc : MyDocument ) {
2020-08-26 14:04:37 +03:00
let gifWidth = doc . w ;
let gifHeight = doc . h ;
if ( gifHeight < height ) {
gifWidth = height / gifHeight * gifWidth ;
gifHeight = height ;
}
2020-09-21 20:34:19 +03:00
const willUseWidth = Math . min ( maxSingleWidth , width , gifWidth ) ;
const { w , h } = calcImageInBox ( gifWidth , gifHeight , willUseWidth , height ) ;
2020-08-26 14:04:37 +03:00
/ * w a s t e d W i d t h + = w ;
if ( wastedWidth == width || h < height ) {
wastedWidth = 0 ;
console . log ( 'completed line' , i , line ) ;
line = [ ] ;
continue ;
}
line . push ( gif ) ; * /
//console.log('gif:', gif, w, h);
2020-09-21 20:34:19 +03:00
const div = document . createElement ( 'div' ) ;
2020-08-26 14:04:37 +03:00
div . classList . add ( 'gif' , 'fade-in-transition' ) ;
div . style . width = w + 'px' ;
div . style . opacity = '0' ;
//div.style.height = h + 'px';
div . dataset . docID = doc . id ;
this . element . append ( div ) ;
2020-09-21 20:34:19 +03:00
//this.lazyLoadQueue.observe({div, load: this.processVisibleDiv});
this . lazyLoadQueue . observe ( div ) ;
2020-08-26 14:04:37 +03:00
//let preloader = new ProgressivePreloader(div);
2020-08-28 14:25:43 +03:00
const gotThumb = appDocsManager . getThumb ( doc , false ) ;
const willBeAPoster = ! ! gotThumb ;
2020-08-26 14:04:37 +03:00
let img : HTMLImageElement ;
2020-08-28 14:25:43 +03:00
if ( willBeAPoster ) {
2020-08-26 14:04:37 +03:00
img = new Image ( ) ;
2020-08-28 14:25:43 +03:00
if ( ! gotThumb . thumb . url ) {
gotThumb . promise . then ( ( ) = > {
img . src = gotThumb . thumb . url ;
} ) ;
}
2020-08-26 14:04:37 +03:00
}
const afterRender = ( ) = > {
if ( img ) {
div . append ( img ) ;
div . style . opacity = '' ;
}
} ;
2020-08-28 14:25:43 +03:00
( gotThumb ? . thumb ? . url ? renderImageFromUrl ( img , gotThumb . thumb . url , afterRender ) : afterRender ( ) ) ;
2020-08-26 14:04:37 +03:00
}
}