2020-11-07 05:48:07 +02:00
import { getEmojiToneIndex } from '../emoji' ;
2020-10-11 22:12:17 +03:00
import { readBlobAsText } from '../helpers/blob' ;
import { deferredPromise } from '../helpers/cancellablePromise' ;
2020-12-25 14:53:20 +02:00
import { formatDateAccordingToToday , months } from '../helpers/date' ;
2020-10-11 22:12:17 +03:00
import mediaSizes from '../helpers/mediaSizes' ;
2020-11-07 05:48:07 +02:00
import { formatBytes } from '../helpers/number' ;
2020-10-31 00:39:36 +02:00
import { isAppleMobile , isSafari } from '../helpers/userAgent' ;
2020-10-11 22:12:17 +03:00
import { PhotoSize } from '../layer' ;
2020-09-17 22:33:23 +03:00
import appDocsManager , { MyDocument } from "../lib/appManagers/appDocsManager" ;
2020-10-11 22:12:17 +03:00
import { DownloadBlob } from '../lib/appManagers/appDownloadManager' ;
import appMessagesManager from '../lib/appManagers/appMessagesManager' ;
import appPhotosManager , { MyPhoto } from '../lib/appManagers/appPhotosManager' ;
import LottieLoader from '../lib/lottieLoader' ;
import VideoPlayer from '../lib/mediaPlayer' ;
2020-12-12 18:30:01 +02:00
import { attachClickEvent , cancelEvent , isInDOM } from "../helpers/dom" ;
2020-10-11 22:12:17 +03:00
import webpWorkerController from '../lib/webp/webpWorkerController' ;
import animationIntersector from './animationIntersector' ;
import appMediaPlaybackController from './appMediaPlaybackController' ;
import AudioElement from './audio' ;
import ReplyContainer from './chat/replyContainer' ;
import { Layouter , RectPart } from './groupedLayout' ;
2020-02-11 22:35:57 +07:00
import LazyLoadQueue from './lazyLoadQueue' ;
2020-08-28 14:25:43 +03:00
import { renderImageFromUrl } from './misc' ;
2020-05-09 15:02:07 +03:00
import PollElement from './poll' ;
2020-10-11 22:12:17 +03:00
import ProgressivePreloader from './preloader' ;
2020-11-07 05:48:07 +02:00
import './middleEllipsis' ;
2020-12-08 21:48:44 +02:00
import { nextRandomInt } from '../helpers/random' ;
2020-12-10 01:58:20 +02:00
import RichTextProcessor from '../lib/richtextprocessor' ;
2020-12-13 01:29:12 +02:00
import appImManager from '../lib/appManagers/appImManager' ;
2020-12-16 05:22:58 +02:00
import Chat from './chat/chat' ;
2020-12-25 14:53:20 +02:00
import { SearchSuperContext } from './appSearchSuper.' ;
2021-01-10 20:10:02 +04:00
import rootScope from '../lib/rootScope' ;
2020-02-11 22:35:57 +07:00
2020-10-28 20:20:01 +02:00
const MAX_VIDEO_AUTOPLAY_SIZE = 50 * 1024 * 1024 ; // 50 MB
2021-01-18 22:34:41 +04:00
export function wrapVideo ( { doc , container , message , boxWidth , boxHeight , withTail , isOut , middleware , lazyLoadQueue , noInfo , group , onlyPreview , withoutPreloader , loadPromises , noPlayButton } : {
2020-09-17 22:33:23 +03:00
doc : MyDocument ,
2020-11-12 00:43:09 +02:00
container? : HTMLElement ,
2020-08-24 17:09:31 +03:00
message? : any ,
boxWidth? : number ,
boxHeight? : number ,
2020-04-20 00:40:00 +03:00
withTail? : boolean ,
isOut? : boolean ,
2020-08-24 17:09:31 +03:00
middleware ? : ( ) = > boolean ,
lazyLoadQueue? : LazyLoadQueue ,
noInfo? : true ,
2021-01-18 22:34:41 +04:00
noPlayButton? : boolean ,
2021-01-10 20:10:02 +04:00
group? : string ,
onlyPreview? : boolean ,
withoutPreloader? : boolean ,
loadPromises? : Promise < any > [ ]
2020-04-20 00:40:00 +03:00
} ) {
2020-10-28 20:20:01 +02:00
const isAlbumItem = ! ( boxWidth && boxHeight ) ;
const canAutoplay = doc . type != 'video' || ( doc . size <= MAX_VIDEO_AUTOPLAY_SIZE && ! isAlbumItem ) ;
let spanTime : HTMLElement ;
2020-08-24 17:09:31 +03:00
if ( ! noInfo ) {
2021-01-18 22:34:41 +04:00
if ( doc . type !== 'round' ) {
2020-10-28 20:20:01 +02:00
spanTime = document . createElement ( 'span' ) ;
spanTime . classList . add ( 'video-time' ) ;
container . append ( spanTime ) ;
2020-08-24 17:09:31 +03:00
2021-01-18 22:34:41 +04:00
if ( doc . type !== 'gif' ) {
2020-10-28 20:20:01 +02:00
spanTime . innerText = ( doc . duration + '' ) . toHHMMSS ( false ) ;
2021-01-18 22:34:41 +04:00
if ( ! noPlayButton ) {
if ( canAutoplay ) {
spanTime . classList . add ( 'tgico' , 'can-autoplay' ) ;
} else {
const spanPlay = document . createElement ( 'span' ) ;
spanPlay . classList . add ( 'video-play' , 'tgico-largeplay' , 'btn-circle' , 'position-center' ) ;
container . append ( spanPlay ) ;
}
2020-10-28 20:20:01 +02:00
}
2020-08-24 17:09:31 +03:00
} else {
2020-10-28 20:20:01 +02:00
spanTime . innerText = 'GIF' ;
2020-08-24 17:09:31 +03:00
}
2020-06-16 23:48:08 +03:00
}
}
2021-01-10 20:10:02 +04:00
let res : {
thumb? : typeof photoRes ,
loadPromise : Promise < any >
} = { } as any ;
2021-01-18 22:34:41 +04:00
if ( doc . mime_type === 'image/gif' ) {
2021-01-10 20:10:02 +04:00
const photoRes = wrapPhoto ( {
2020-12-11 04:06:16 +02:00
photo : doc ,
message ,
container ,
boxWidth ,
boxHeight ,
withTail ,
isOut ,
lazyLoadQueue ,
2021-01-10 20:10:02 +04:00
middleware ,
withoutPreloader ,
loadPromises
2020-12-11 04:06:16 +02:00
} ) ;
2021-01-10 20:10:02 +04:00
res . thumb = photoRes ;
res . loadPromise = photoRes . loadPromises . full ;
return res ;
2020-08-25 19:26:49 +03:00
}
2020-08-29 14:45:37 +03:00
/ * c o n s t v i d e o = d o c . t y p e = = ' r o u n d ' ? a p p M e d i a P l a y b a c k C o n t r o l l e r . a d d M e d i a ( d o c , m e s s a g e . m i d ) a s H T M L V i d e o E l e m e n t : d o c u m e n t . c r e a t e E l e m e n t ( ' v i d e o ' ) ;
if ( video . parentElement ) {
video . remove ( ) ;
} * /
2020-08-24 17:09:31 +03:00
const video = document . createElement ( 'video' ) ;
2021-01-10 20:10:02 +04:00
video . classList . add ( 'media-video' ) ;
2020-08-30 13:43:57 +03:00
video . muted = true ;
2020-10-31 00:39:36 +02:00
video . setAttribute ( 'playsinline' , 'true' ) ;
2021-01-18 22:34:41 +04:00
if ( doc . type === 'round' ) {
2020-08-30 13:43:57 +03:00
//video.muted = true;
2020-12-16 05:22:58 +02:00
const globalVideo = appMediaPlaybackController . addMedia ( message . peerId , doc , message . mid ) ;
2020-08-29 14:45:37 +03:00
video . addEventListener ( 'canplay' , ( ) = > {
if ( globalVideo . currentTime > 0 ) {
video . currentTime = globalVideo . currentTime ;
}
if ( ! globalVideo . paused ) {
// с закоментированными настройками - хром выключал видео при скролле, для этого нужно было включить видео - выйти из диалога, зайти заново и проскроллить вверх
/ * v i d e o . a u t o p l a y = t r u e ;
video . loop = false ; * /
video . play ( ) ;
}
} , { once : true } ) ;
const clear = ( ) = > {
//console.log('clearing video');
globalVideo . removeEventListener ( 'timeupdate' , onTimeUpdate ) ;
globalVideo . removeEventListener ( 'play' , onGlobalPlay ) ;
globalVideo . removeEventListener ( 'pause' , onGlobalPause ) ;
video . removeEventListener ( 'play' , onVideoPlay ) ;
video . removeEventListener ( 'pause' , onVideoPause ) ;
} ;
const onTimeUpdate = ( ) = > {
if ( ! isInDOM ( video ) ) {
clear ( ) ;
}
} ;
const onGlobalPlay = ( ) = > {
video . play ( ) ;
} ;
const onGlobalPause = ( ) = > {
video . pause ( ) ;
} ;
const onVideoPlay = ( ) = > {
globalVideo . play ( ) ;
} ;
const onVideoPause = ( ) = > {
//console.log('video pause event');
if ( isInDOM ( video ) ) {
globalVideo . pause ( ) ;
} else {
clear ( ) ;
}
} ;
globalVideo . addEventListener ( 'timeupdate' , onTimeUpdate ) ;
globalVideo . addEventListener ( 'play' , onGlobalPlay ) ;
globalVideo . addEventListener ( 'pause' , onGlobalPause ) ;
video . addEventListener ( 'play' , onVideoPlay ) ;
video . addEventListener ( 'pause' , onVideoPause ) ;
2020-08-30 13:43:57 +03:00
} else {
video . autoplay = true ; // для safari
2020-08-29 14:45:37 +03:00
}
2021-01-10 20:10:02 +04:00
let photoRes : ReturnType < typeof wrapPhoto > ;
2020-08-24 17:09:31 +03:00
if ( message ) {
2021-01-10 20:10:02 +04:00
photoRes = wrapPhoto ( {
photo : doc ,
message ,
container ,
boxWidth ,
boxHeight ,
withTail ,
isOut ,
lazyLoadQueue ,
middleware ,
withoutPreloader : true ,
loadPromises
} ) ;
2020-08-24 17:09:31 +03:00
2021-01-10 20:10:02 +04:00
res . thumb = photoRes ;
2020-08-25 19:26:49 +03:00
2021-01-10 20:10:02 +04:00
if ( ! canAutoplay || onlyPreview ) {
res . loadPromise = photoRes . loadPromises . full ;
return res ;
2020-08-24 17:09:31 +03:00
}
2020-05-23 08:31:18 +03:00
2020-08-24 17:09:31 +03:00
if ( withTail ) {
2021-01-10 20:10:02 +04:00
const foreignObject = ( photoRes . images . thumb || photoRes . images . full ) . parentElement ;
2020-08-24 17:09:31 +03:00
video . width = + foreignObject . getAttributeNS ( null , 'width' ) ;
video . height = + foreignObject . getAttributeNS ( null , 'height' ) ;
foreignObject . append ( video ) ;
2020-04-08 18:46:43 +03:00
}
2021-01-10 20:10:02 +04:00
} else { // * gifs masonry
2020-08-28 14:25:43 +03:00
const gotThumb = appDocsManager . getThumb ( doc , false ) ;
if ( gotThumb ) {
gotThumb . promise . then ( ( ) = > {
video . poster = gotThumb . thumb . url ;
} ) ;
2020-08-24 17:09:31 +03:00
}
2020-06-13 11:19:39 +03:00
}
2020-06-16 23:48:08 +03:00
2020-08-24 17:09:31 +03:00
if ( ! video . parentElement && container ) {
2020-05-23 08:31:18 +03:00
container . append ( video ) ;
2020-04-08 18:46:43 +03:00
}
2020-08-21 14:17:16 +03:00
const loadVideo = async ( ) = > {
2020-08-25 19:26:49 +03:00
if ( middleware && ! middleware ( ) ) {
return ;
}
let preloader : ProgressivePreloader ;
2020-08-24 17:09:31 +03:00
if ( message ? . media ? . preloader ) { // means upload
2020-08-25 19:26:49 +03:00
preloader = message . media . preloader as ProgressivePreloader ;
2020-12-24 07:26:29 +02:00
preloader . attach ( container , false ) ;
2020-08-25 19:26:49 +03:00
} else if ( ! doc . downloaded && ! doc . supportsStreaming ) {
2021-01-18 22:34:41 +04:00
const promise = appDocsManager . downloadDoc ( doc , lazyLoadQueue ? . queueId ) ;
preloader = new ProgressivePreloader ( {
attachMethod : 'prepend'
} ) ;
2020-10-16 13:08:28 +03:00
preloader . attach ( container , true , promise ) ;
2020-08-25 19:26:49 +03:00
await promise ;
2020-10-28 20:20:01 +02:00
if ( middleware && ! middleware ( ) ) {
return ;
}
2020-08-26 19:14:23 +03:00
} else if ( doc . supportsStreaming ) {
2021-01-18 22:34:41 +04:00
preloader = new ProgressivePreloader ( {
cancelable : false ,
attachMethod : 'prepend'
} ) ;
2020-10-16 13:08:28 +03:00
preloader . attach ( container , false , null ) ;
2020-10-28 20:20:01 +02:00
video . addEventListener ( isSafari ? 'timeupdate' : 'canplay' , ( ) = > {
2020-08-26 19:14:23 +03:00
preloader . detach ( ) ;
} , { once : true } ) ;
2020-04-28 20:30:54 +03:00
}
2020-10-28 20:20:01 +02:00
2020-06-06 23:38:48 +03:00
//console.log('loaded doc:', doc, doc.url, container);
2020-06-16 23:48:08 +03:00
2020-09-21 20:34:19 +03:00
const deferred = deferredPromise < void > ( ) ;
2020-08-25 19:26:49 +03:00
//if(doc.type == 'gif'/* || true */) {
2020-10-31 00:39:36 +02:00
video . addEventListener ( isAppleMobile ? 'loadeddata' : 'canplay' , ( ) = > {
2020-06-16 23:48:08 +03:00
/ * i f ( ! v i d e o . p a u s e d ) {
video . pause ( ) ;
} * /
2021-01-10 20:10:02 +04:00
if ( doc . type !== 'round' && group ) {
2020-08-24 17:09:31 +03:00
animationIntersector . addAnimation ( video , group ) ;
}
2020-09-21 20:34:19 +03:00
// test lazyLoadQueue
//setTimeout(() => {
deferred . resolve ( ) ;
//}, 5000);
2020-06-16 23:48:08 +03:00
} , { once : true } ) ;
2020-08-25 19:26:49 +03:00
//}
2021-01-18 22:34:41 +04:00
if ( doc . type === 'video' ) {
2020-10-28 20:20:01 +02:00
video . addEventListener ( 'timeupdate' , ( ) = > {
spanTime . innerText = ( video . duration - video . currentTime + '' ) . toHHMMSS ( false ) ;
} ) ;
}
2020-10-04 02:10:57 +03:00
video . addEventListener ( 'error' , ( e ) = > {
deferred . resolve ( ) ;
} ) ;
2020-09-21 20:34:19 +03:00
2021-01-18 22:34:41 +04:00
renderImageFromUrl ( video , doc . url ) ;
2020-08-30 13:43:57 +03:00
2021-01-18 22:34:41 +04:00
if ( doc . type === 'round' ) {
2020-10-28 20:20:01 +02:00
video . dataset . ckin = 'circle' ;
video . dataset . overlay = '1' ;
new VideoPlayer ( video ) ;
} else {
2020-06-06 23:38:48 +03:00
video . muted = true ;
2020-05-18 04:21:58 +03:00
video . loop = true ;
2020-06-13 11:19:39 +03:00
//video.play();
video . autoplay = true ;
2020-05-18 04:21:58 +03:00
}
2020-09-21 20:34:19 +03:00
return deferred ;
2020-02-11 22:35:57 +07:00
} ;
2020-04-28 20:30:54 +03:00
2020-06-16 23:48:08 +03:00
/ * i f ( d o c . s i z e > = 2 0 e 6 & & ! d o c . d o w n l o a d e d ) {
2020-04-28 20:30:54 +03:00
let downloadDiv = document . createElement ( 'div' ) ;
downloadDiv . classList . add ( 'download' ) ;
let span = document . createElement ( 'span' ) ;
2020-05-06 04:03:31 +03:00
span . classList . add ( 'btn-circle' , 'tgico-download' ) ;
2020-04-28 20:30:54 +03:00
downloadDiv . append ( span ) ;
downloadDiv . addEventListener ( 'click' , ( ) = > {
downloadDiv . remove ( ) ;
loadVideo ( ) ;
2020-02-11 22:35:57 +07:00
} ) ;
2020-04-28 20:30:54 +03:00
2020-05-06 04:03:31 +03:00
container . prepend ( downloadDiv ) ;
2020-04-28 20:30:54 +03:00
return ;
2020-06-16 23:48:08 +03:00
} * /
2020-08-24 17:09:31 +03:00
2021-01-10 20:10:02 +04:00
res . loadPromise = ! lazyLoadQueue ? loadVideo ( ) : ( lazyLoadQueue . push ( { div : container , load : loadVideo } ) , Promise . resolve ( ) ) ;
return res ;
2020-02-11 22:35:57 +07:00
}
2020-06-13 11:19:39 +03:00
export const formatDate = ( timestamp : number , monthShort = false , withYear = true ) = > {
2020-04-28 20:30:54 +03:00
const date = new Date ( timestamp * 1000 ) ;
2020-06-13 11:19:39 +03:00
let month = months [ date . getMonth ( ) ] ;
if ( monthShort ) month = month . slice ( 0 , 3 ) ;
let str = month + ' ' + date . getDate ( ) ;
if ( withYear ) {
str += ', ' + date . getFullYear ( ) ;
}
return str + ' at ' + date . getHours ( ) + ':' + ( '0' + date . getMinutes ( ) ) . slice ( - 2 ) ;
2020-04-28 20:30:54 +03:00
} ;
2021-01-10 20:10:02 +04:00
export function wrapDocument ( { message , withTime , fontWeight , voiceAsMusic , showSender , searchContext , loadPromises } : {
2020-12-19 03:07:24 +02:00
message : any ,
withTime? : boolean ,
2020-12-25 14:53:20 +02:00
fontWeight? : number ,
voiceAsMusic? : boolean ,
showSender? : boolean ,
2021-01-10 20:10:02 +04:00
searchContext? : SearchSuperContext ,
loadPromises? : Promise < any > [ ]
2020-12-19 03:07:24 +02:00
} ) : HTMLElement {
if ( ! fontWeight ) fontWeight = 500 ;
2020-12-20 06:41:42 +02:00
const uploading = message . pFlags . is_outgoing ;
2020-12-20 05:54:35 +02:00
const doc = message . media . document || message . media . webpage . document ;
2021-01-18 22:34:41 +04:00
if ( doc . type === 'audio' || doc . type === 'voice' ) {
2020-12-19 03:07:24 +02:00
const audioElement = new AudioElement ( ) ;
audioElement . setAttribute ( 'message-id' , '' + message . mid ) ;
audioElement . setAttribute ( 'peer-id' , '' + message . peerId ) ;
audioElement . withTime = withTime ;
audioElement . message = message ;
2020-12-25 14:53:20 +02:00
if ( voiceAsMusic ) audioElement . voiceAsMusic = voiceAsMusic ;
if ( searchContext ) audioElement . searchContext = searchContext ;
if ( showSender ) audioElement . showSender = showSender ;
2021-01-18 22:34:41 +04:00
const isPending = message . pFlags . is_outgoing ;
if ( isPending ) {
audioElement . preloader = message . media . preloader ;
}
2020-11-07 05:48:07 +02:00
audioElement . dataset . fontWeight = '' + fontWeight ;
2020-12-24 10:19:56 +02:00
audioElement . render ( ) ;
2020-11-07 05:48:07 +02:00
return audioElement ;
2020-02-15 22:20:38 +07:00
}
2020-04-28 20:30:54 +03:00
2020-02-11 22:35:57 +07:00
let extSplitted = doc . file_name ? doc . file_name . split ( '.' ) : '' ;
let ext = '' ;
ext = extSplitted . length > 1 && Array . isArray ( extSplitted ) ? extSplitted . pop ( ) . toLowerCase ( ) : 'file' ;
2020-04-28 20:30:54 +03:00
let docDiv = document . createElement ( 'div' ) ;
docDiv . classList . add ( 'document' , ` ext- ${ ext } ` ) ;
2020-09-19 14:37:19 +03:00
const icoDiv = document . createElement ( 'div' ) ;
icoDiv . classList . add ( 'document-ico' ) ;
2020-12-10 01:58:20 +02:00
if ( doc . thumbs ? . length || ( uploading && doc . url && doc . type == 'photo' ) ) {
2020-10-16 15:35:44 +03:00
docDiv . classList . add ( 'document-with-thumb' ) ;
2020-09-19 14:37:19 +03:00
if ( uploading ) {
icoDiv . innerHTML = ` <img src=" ${ doc . url } "> ` ;
} else {
2020-12-11 04:06:16 +02:00
wrapPhoto ( {
photo : doc ,
message : null ,
container : icoDiv ,
boxWidth : 54 ,
2021-01-10 20:10:02 +04:00
boxHeight : 54 ,
2021-01-18 22:34:41 +04:00
loadPromises ,
withoutPreloader : true
2020-12-11 04:06:16 +02:00
} ) ;
2020-09-19 14:37:19 +03:00
icoDiv . style . width = icoDiv . style . height = '' ;
}
const img = icoDiv . querySelector ( 'img' ) ;
if ( img ) img . classList . add ( 'document-thumb' ) ;
} else {
icoDiv . innerText = ext ;
2020-02-11 22:35:57 +07:00
}
2020-09-19 14:37:19 +03:00
2020-11-07 05:48:07 +02:00
//let fileName = stringMiddleOverflow(doc.file_name || 'Unknown.file', 26);
2020-02-11 22:35:57 +07:00
let fileName = doc . file_name || 'Unknown.file' ;
let size = formatBytes ( doc . size ) ;
if ( withTime ) {
2020-04-28 20:30:54 +03:00
size += ' · ' + formatDate ( doc . date ) ;
2020-02-11 22:35:57 +07:00
}
2020-12-25 14:53:20 +02:00
if ( showSender ) {
size += ' · ' + appMessagesManager . getSenderToPeerText ( message ) ;
}
let titleAdditionHTML = '' ;
if ( showSender ) {
titleAdditionHTML = ` <div class="sent-time"> ${ formatDateAccordingToToday ( new Date ( message . date * 1000 ) ) } </div> ` ;
}
2020-02-11 22:35:57 +07:00
docDiv . innerHTML = `
2021-01-18 22:34:41 +04:00
$ { ! uploading ? ` <div class="document-download"></div> ` : '' }
2020-12-25 14:53:20 +02:00
< div class = "document-name" > < middle - ellipsis - element data-font-weight = "${fontWeight}" > $ { fileName } < / m i d d l e - e l l i p s i s - e l e m e n t > $ { t i t l e A d d i t i o n H T M L } < / d i v >
2020-02-11 22:35:57 +07:00
< div class = "document-size" > $ { size } < / div >
` ;
2020-09-19 14:37:19 +03:00
docDiv . prepend ( icoDiv ) ;
2020-02-16 02:03:27 +07:00
if ( ! uploading ) {
2021-01-18 22:34:41 +04:00
const downloadDiv = docDiv . querySelector ( '.document-download' ) as HTMLDivElement ;
const preloader = new ProgressivePreloader ( ) ;
const load = ( ) = > {
const download = appDocsManager . saveDocFile ( doc , appImManager . chat . bubbles . lazyLoadQueue . queueId ) ;
2020-08-22 19:53:59 +03:00
2021-01-18 22:34:41 +04:00
download . then ( ( ) = > {
downloadDiv . classList . add ( 'downloaded' ) ;
setTimeout ( ( ) = > {
2020-08-22 19:53:59 +03:00
downloadDiv . remove ( ) ;
2021-01-18 22:34:41 +04:00
} , 200 ) ;
} ) ;
preloader . attach ( downloadDiv , true , download ) ;
return { download } ;
} ;
preloader . construct ( ) ;
preloader . setManual ( ) ;
preloader . attach ( downloadDiv ) ;
preloader . setDownloadFunction ( load ) ;
attachClickEvent ( docDiv , ( e ) = > {
preloader . onClick ( e ) ;
2020-02-16 02:03:27 +07:00
} ) ;
2021-01-18 22:34:41 +04:00
} else if ( message . media ? . preloader ) {
const icoDiv = docDiv . querySelector ( '.document-ico' ) ;
message . media . preloader . attach ( icoDiv , false ) ;
2020-02-16 02:03:27 +07:00
}
2020-02-11 22:35:57 +07:00
return docDiv ;
}
2020-11-12 00:43:09 +02:00
function wrapMediaWithTail ( photo : MyPhoto | MyDocument , message : { mid : number , message : string } , container : HTMLElement , boxWidth : number , boxHeight : number , isOut : boolean ) {
2020-08-25 19:26:49 +03:00
const svg = document . createElementNS ( "http://www.w3.org/2000/svg" , "svg" ) ;
2020-04-08 18:46:43 +03:00
svg . classList . add ( 'bubble__media-container' , isOut ? 'is-out' : 'is-in' ) ;
2020-02-11 22:35:57 +07:00
2020-08-25 19:26:49 +03:00
const foreignObject = document . createElementNS ( "http://www.w3.org/2000/svg" , 'foreignObject' ) ;
2021-01-10 20:10:02 +04:00
const gotThumb = appPhotosManager . getStrippedThumbIfNeeded ( photo ) ;
if ( gotThumb ) {
foreignObject . append ( gotThumb . image ) ;
}
appPhotosManager . setAttachmentSize ( photo , foreignObject , boxWidth , boxHeight ) ;
2020-05-23 08:31:18 +03:00
2020-08-25 19:26:49 +03:00
const width = + foreignObject . getAttributeNS ( null , 'width' ) ;
const height = + foreignObject . getAttributeNS ( null , 'height' ) ;
2020-05-23 08:31:18 +03:00
svg . setAttributeNS ( null , 'width' , '' + width ) ;
svg . setAttributeNS ( null , 'height' , '' + height ) ;
2020-04-14 18:46:31 +03:00
2020-06-05 19:01:06 +03:00
svg . setAttributeNS ( null , 'viewBox' , '0 0 ' + width + ' ' + height ) ;
svg . setAttributeNS ( null , 'preserveAspectRatio' , 'none' ) ;
2020-12-11 04:06:16 +02:00
const clipId = 'clip' + message . mid + '_' + nextRandomInt ( 9999 ) ;
svg . dataset . clipId = clipId ;
2020-02-11 22:35:57 +07:00
2020-08-25 19:26:49 +03:00
const defs = document . createElementNS ( "http://www.w3.org/2000/svg" , 'defs' ) ;
2020-04-14 18:46:31 +03:00
let clipPathHTML : string = '' ;
2020-04-08 18:46:43 +03:00
if ( message . message ) {
//clipPathHTML += `<rect width="${width}" height="${height}"></rect>`;
} else {
if ( isOut ) {
clipPathHTML += `
< use href = "#message-tail" transform = "translate(${width - 2}, ${height}) scale(-1, -1)" > < / use >
< path / >
` ;
} else {
clipPathHTML += `
< use href = "#message-tail" transform = "translate(2, ${height}) scale(1, -1)" > < / use >
< path / >
` ;
}
}
2020-04-14 18:46:31 +03:00
2020-12-11 04:06:16 +02:00
defs . innerHTML = ` <clipPath id=" ${ clipId } "> ${ clipPathHTML } </clipPath> ` ;
2020-04-08 18:46:43 +03:00
2020-05-23 08:31:18 +03:00
container . style . width = parseInt ( container . style . width ) - 9 + 'px' ;
2020-06-13 11:19:39 +03:00
container . classList . add ( 'with-tail' ) ;
2020-05-23 08:31:18 +03:00
svg . append ( defs , foreignObject ) ;
container . append ( svg ) ;
let img = foreignObject . firstElementChild as HTMLImageElement ;
if ( ! img ) {
foreignObject . append ( img = new Image ( ) ) ;
}
2020-04-08 18:46:43 +03:00
2020-05-23 08:31:18 +03:00
return img ;
2020-04-08 18:46:43 +03:00
}
2021-01-10 20:10:02 +04:00
export function wrapPhoto ( { photo , message , container , boxWidth , boxHeight , withTail , isOut , lazyLoadQueue , middleware , size , withoutPreloader , loadPromises } : {
2020-12-11 04:06:16 +02:00
photo : MyPhoto | MyDocument ,
message : any ,
container : HTMLElement ,
boxWidth? : number ,
boxHeight? : number ,
withTail? : boolean ,
isOut? : boolean ,
lazyLoadQueue? : LazyLoadQueue ,
middleware ? : ( ) = > boolean ,
2021-01-10 20:10:02 +04:00
size? : PhotoSize ,
withoutPreloader? : boolean ,
loadPromises? : Promise < any > [ ]
2020-12-11 04:06:16 +02:00
} ) {
2021-01-10 20:10:02 +04:00
if ( ! ( ( photo as MyPhoto ) . sizes || ( photo as MyDocument ) . thumbs ) ) {
2021-01-18 22:34:41 +04:00
if ( boxWidth && boxHeight && photo . _ === 'document' ) {
size = appPhotosManager . setAttachmentSize ( photo , container , boxWidth , boxHeight ) ;
}
2021-01-10 20:10:02 +04:00
return {
loadPromises : {
thumb : Promise.resolve ( ) ,
full : Promise.resolve ( )
} ,
images : {
thumb : null ,
full : null
}
} ;
}
2021-01-18 22:34:41 +04:00
if ( boxWidth === undefined ) boxWidth = mediaSizes . active . regular . width ;
if ( boxHeight === undefined ) boxHeight = mediaSizes . active . regular . height ;
2020-12-11 04:06:16 +02:00
2021-01-10 20:10:02 +04:00
let loadThumbPromise : Promise < any > ;
let thumbImage : HTMLImageElement ;
2020-05-23 08:31:18 +03:00
let image : HTMLImageElement ;
2020-04-08 18:46:43 +03:00
if ( withTail ) {
image = wrapMediaWithTail ( photo , message , container , boxWidth , boxHeight , isOut ) ;
2020-05-23 08:31:18 +03:00
} else {
2021-01-10 20:10:02 +04:00
image = new Image ( ) ;
2020-08-25 19:26:49 +03:00
2021-01-10 20:10:02 +04:00
if ( boxWidth && boxHeight ) { // !album
size = appPhotosManager . setAttachmentSize ( photo , container , boxWidth , boxHeight ) ;
2020-05-02 00:28:40 +03:00
}
2021-01-10 20:10:02 +04:00
const gotThumb = appPhotosManager . getStrippedThumbIfNeeded ( photo ) ;
if ( gotThumb ) {
loadThumbPromise = gotThumb . loadPromise ;
thumbImage = gotThumb . image ;
thumbImage . classList . add ( 'media-photo' ) ;
container . append ( thumbImage ) ;
2020-04-08 18:46:43 +03:00
}
}
2020-10-31 04:10:44 +02:00
2021-01-10 20:10:02 +04:00
image . classList . add ( 'media-photo' ) ;
2020-05-06 04:03:31 +03:00
//console.log('wrapPhoto downloaded:', photo, photo.downloaded, container);
2021-01-10 20:10:02 +04:00
2020-08-25 12:39:39 +03:00
const cacheContext = appPhotosManager . getCacheContext ( photo ) ;
2020-04-26 04:45:07 +03:00
2021-01-10 20:10:02 +04:00
const needFadeIn = ( thumbImage || ! cacheContext . downloaded ) && rootScope . settings . animationsEnabled ;
if ( needFadeIn ) {
image . classList . add ( 'fade-in' ) ;
}
2020-04-14 18:46:31 +03:00
let preloader : ProgressivePreloader ;
2020-09-19 14:37:19 +03:00
if ( message ? . media ? . preloader ) { // means upload
2021-01-18 22:34:41 +04:00
preloader = message . media . preloader ;
preloader . attach ( container ) ;
} else {
preloader = new ProgressivePreloader ( {
attachMethod : 'prepend'
} ) ;
2020-05-02 00:28:40 +03:00
}
2021-01-18 22:34:41 +04:00
const getDownloadPromise = ( ) = > {
2021-01-10 20:10:02 +04:00
const promise = photo . _ === 'document' && photo . mime_type === 'image/gif' ?
2021-01-11 19:21:03 +04:00
appDocsManager . downloadDoc ( photo , /* undefined, */ lazyLoadQueue ? . queueId ) :
2020-12-11 04:06:16 +02:00
appPhotosManager . preloadPhoto ( photo , size , lazyLoadQueue ? . queueId ) ;
2020-08-25 12:39:39 +03:00
2021-01-18 22:34:41 +04:00
return promise ;
} ;
2020-08-28 14:25:43 +03:00
2021-01-18 22:34:41 +04:00
const onLoad = ( ) = > {
if ( middleware && ! middleware ( ) ) return Promise . resolve ( ) ;
2020-04-15 23:55:08 +03:00
2021-01-18 22:34:41 +04:00
return new Promise ( ( resolve ) = > {
renderImageFromUrl ( image , cacheContext . url || photo . url , ( ) = > {
container . append ( image ) ;
2021-01-10 20:10:02 +04:00
2021-01-18 22:34:41 +04:00
window . requestAnimationFrame ( ( ) = > {
resolve ( ) ;
2021-01-10 20:10:02 +04:00
} ) ;
2021-01-18 22:34:41 +04:00
//resolve();
if ( needFadeIn ) {
setTimeout ( ( ) = > {
image . classList . remove ( 'fade-in' ) ;
if ( thumbImage ) {
thumbImage . remove ( ) ;
}
} , 200 ) ;
}
2021-01-10 20:10:02 +04:00
} ) ;
2020-02-14 18:04:39 +07:00
} ) ;
} ;
2021-01-18 22:34:41 +04:00
let loadPromise : Promise < any > ;
const load = ( ) = > {
const promise = getDownloadPromise ( ) ;
if ( ! cacheContext . downloaded && ! withoutPreloader ) {
preloader . attach ( container , false , promise ) ;
}
return { download : promise , render : promise.then ( onLoad ) } ;
} ;
preloader . setDownloadFunction ( load ) ;
2021-01-10 20:10:02 +04:00
if ( cacheContext . downloaded ) {
2021-01-18 22:34:41 +04:00
loadThumbPromise = loadPromise = load ( ) . render ;
2021-01-10 20:10:02 +04:00
} else {
2021-01-18 22:34:41 +04:00
if ( ! lazyLoadQueue ) loadPromise = load ( ) . render ;
else lazyLoadQueue . push ( { div : container , load : ( ) = > load ( ) . download } ) ;
2021-01-10 20:10:02 +04:00
}
2021-01-18 22:34:41 +04:00
if ( loadPromises && loadThumbPromise ) {
2021-01-10 20:10:02 +04:00
loadPromises . push ( loadThumbPromise ) ;
}
return {
loadPromises : {
thumb : loadThumbPromise ,
full : loadPromise || Promise . resolve ( )
} ,
images : {
thumb : thumbImage ,
full : image
}
} ;
2020-02-11 22:35:57 +07:00
}
2021-01-11 19:21:03 +04:00
export function wrapSticker ( { doc , div , middleware , lazyLoadQueue , group , play , onlyThumb , emoji , width , height , withThumb , loop , loadPromises } : {
2020-09-17 22:33:23 +03:00
doc : MyDocument ,
2020-11-25 21:36:18 +02:00
div : HTMLElement ,
2020-05-26 18:04:06 +03:00
middleware ? : ( ) = > boolean ,
lazyLoadQueue? : LazyLoadQueue ,
group? : string ,
play? : boolean ,
onlyThumb? : boolean ,
2020-06-13 11:19:39 +03:00
emoji? : string ,
width? : number ,
height? : number ,
withThumb? : boolean ,
2021-01-11 19:21:03 +04:00
loop? : boolean ,
loadPromises? : Promise < any > [ ]
2020-05-26 18:04:06 +03:00
} ) {
2020-08-28 14:25:43 +03:00
const stickerType = doc . sticker ;
2020-04-14 18:46:31 +03:00
2020-06-13 11:19:39 +03:00
if ( ! width ) {
width = ! emoji ? 200 : undefined ;
}
if ( ! height ) {
height = ! emoji ? 200 : undefined ;
}
2020-04-14 18:46:31 +03:00
if ( stickerType == 2 && ! LottieLoader . loaded ) {
2020-05-30 09:44:54 +03:00
//LottieLoader.loadLottie();
LottieLoader . loadLottieWorkers ( ) ;
2020-04-14 18:46:31 +03:00
}
2020-02-11 22:35:57 +07:00
if ( ! stickerType ) {
2020-05-09 15:02:07 +03:00
console . error ( 'wrong doc for wrapSticker!' , doc ) ;
2020-05-23 08:31:18 +03:00
throw new Error ( 'wrong doc for wrapSticker!' ) ;
2020-02-11 22:35:57 +07:00
}
2020-05-23 08:31:18 +03:00
2020-12-11 04:06:16 +02:00
div . dataset . docId = doc . id ;
2020-02-11 22:35:57 +07:00
2020-05-09 15:02:07 +03:00
//console.log('wrap sticker', doc, div, onlyThumb);
2020-05-26 18:04:06 +03:00
const toneIndex = emoji ? getEmojiToneIndex ( emoji ) : - 1 ;
2020-02-11 22:35:57 +07:00
2021-01-11 19:21:03 +04:00
let loadThumbPromise = deferredPromise < void > ( ) ;
let haveThumbCached = false ;
2020-11-27 21:09:05 +02:00
if ( ( doc . thumbs ? . length || doc . stickerCachedThumbs ) && ! div . firstElementChild && ( ! doc . downloaded || stickerType == 2 || onlyThumb ) /* && doc.thumbs[0]._ != 'photoSizeEmpty' */ ) {
2020-11-28 17:56:28 +02:00
let thumb = doc . stickerCachedThumbs && doc . stickerCachedThumbs [ toneIndex ] || doc . thumbs [ 0 ] ;
2020-04-08 18:46:43 +03:00
2020-04-19 00:55:20 +03:00
//console.log('wrap sticker', thumb, div);
2020-08-23 15:12:08 +03:00
2021-01-11 19:21:03 +04:00
let thumbImage : HTMLImageElement ;
2020-08-23 15:12:08 +03:00
const afterRender = ( ) = > {
if ( ! div . childElementCount ) {
2021-01-11 19:21:03 +04:00
thumbImage . classList . add ( 'media-sticker' , 'thumbnail' ) ;
div . append ( thumbImage ) ;
loadThumbPromise . resolve ( ) ;
2020-08-23 15:12:08 +03:00
}
} ;
2020-09-17 22:33:23 +03:00
if ( 'url' in thumb ) {
2021-01-11 19:21:03 +04:00
thumbImage = new Image ( ) ;
renderImageFromUrl ( thumbImage , thumb . url , afterRender ) ;
haveThumbCached = true ;
2020-09-17 22:33:23 +03:00
} else if ( 'bytes' in thumb ) {
2021-01-11 19:21:03 +04:00
if ( thumb . _ === 'photoPathSize' ) {
2020-11-28 17:56:28 +02:00
if ( thumb . bytes . length ) {
const d = appPhotosManager . getPathFromPhotoPathSize ( thumb ) ;
2021-01-11 20:09:20 +04:00
div . innerHTML = ` <svg class="rlottie-vector media-sticker thumbnail" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 ${ doc . w || 512 } ${ doc . h || 512 } " xml:space="preserve">
2020-11-28 17:56:28 +02:00
< path d = "${d}" / >
< / svg > ` ;
} else {
thumb = doc . thumbs . find ( t = > ( t as PhotoSize . photoStrippedSize ) . bytes ? . length ) || thumb ;
}
}
2021-01-11 19:21:03 +04:00
if ( thumb && thumb . _ !== 'photoPathSize' && toneIndex <= 0 ) {
thumbImage = new Image ( ) ;
2020-11-27 21:09:05 +02:00
if ( ( webpWorkerController . isWebpSupported ( ) || doc . pFlags . stickerThumbConverted || thumb . url ) /* && false */ ) {
2021-01-11 19:21:03 +04:00
renderImageFromUrl ( thumbImage , appPhotosManager . getPreviewURLFromThumb ( thumb as PhotoSize . photoStrippedSize , true ) , afterRender ) ;
haveThumbCached = true ;
2020-11-27 21:09:05 +02:00
} else {
2020-11-28 17:56:28 +02:00
webpWorkerController . convert ( doc . id , ( thumb as PhotoSize . photoStrippedSize ) . bytes as Uint8Array ) . then ( bytes = > {
( thumb as PhotoSize . photoStrippedSize ) . bytes = bytes ;
2020-11-27 21:09:05 +02:00
doc . pFlags . stickerThumbConverted = true ;
if ( middleware && ! middleware ( ) ) return ;
if ( ! div . childElementCount ) {
2021-01-11 19:21:03 +04:00
renderImageFromUrl ( thumbImage , appPhotosManager . getPreviewURLFromThumb ( thumb as PhotoSize . photoStrippedSize , true ) , afterRender ) ;
2020-11-27 21:09:05 +02:00
}
} ) . catch ( ( ) = > { } ) ;
}
2020-05-23 08:31:18 +03:00
}
2020-11-27 21:09:05 +02:00
} else if ( stickerType == 2 && ( withThumb || onlyThumb ) && toneIndex <= 0 ) {
2021-01-11 19:21:03 +04:00
thumbImage = new Image ( ) ;
2020-08-28 14:25:43 +03:00
2020-08-24 17:09:31 +03:00
const load = ( ) = > {
2020-06-16 23:48:08 +03:00
if ( div . childElementCount || ( middleware && ! middleware ( ) ) ) return ;
2020-08-28 14:25:43 +03:00
const r = ( ) = > {
if ( div . childElementCount || ( middleware && ! middleware ( ) ) ) return ;
2021-01-11 19:21:03 +04:00
renderImageFromUrl ( thumbImage , ( thumb as PhotoSize . photoStrippedSize ) . url , afterRender ) ;
2020-08-28 14:25:43 +03:00
} ;
2020-11-28 17:56:28 +02:00
if ( ( thumb as PhotoSize . photoStrippedSize ) . url ) {
2020-08-28 14:25:43 +03:00
r ( ) ;
return Promise . resolve ( ) ;
} else {
2020-11-28 17:56:28 +02:00
return appDocsManager . getThumbURL ( doc , thumb as PhotoSize . photoStrippedSize ) . promise . then ( r ) ;
2020-08-28 14:25:43 +03:00
}
2020-08-24 17:09:31 +03:00
} ;
2020-04-08 18:46:43 +03:00
2020-08-28 14:25:43 +03:00
if ( lazyLoadQueue && onlyThumb ) {
lazyLoadQueue . push ( { div , load } ) ;
return Promise . resolve ( ) ;
} else {
load ( ) ;
2021-01-11 19:21:03 +04:00
if ( ( thumb as any ) . url ) {
haveThumbCached = true ;
}
2020-08-28 14:25:43 +03:00
}
2020-02-11 22:35:57 +07:00
}
}
2020-05-23 08:31:18 +03:00
2021-01-11 19:21:03 +04:00
if ( loadPromises && haveThumbCached ) {
loadPromises . push ( loadThumbPromise ) ;
}
2020-08-28 14:25:43 +03:00
if ( onlyThumb ) { // for sticker panel
return Promise . resolve ( ) ;
2020-02-27 00:52:59 +07:00
}
2020-02-11 22:35:57 +07:00
2020-05-06 04:03:31 +03:00
let downloaded = doc . downloaded ;
2020-08-23 15:12:08 +03:00
let load = async ( ) = > {
2020-02-11 22:35:57 +07:00
if ( middleware && ! middleware ( ) ) return ;
2020-05-23 08:31:18 +03:00
2020-02-11 22:35:57 +07:00
if ( stickerType == 2 ) {
2020-08-23 15:12:08 +03:00
/ * i f ( d o c . i d = = ' 1 8 6 0 7 4 9 7 6 3 0 0 8 2 6 6 3 0 1 ' ) {
console . log ( 'loaded sticker:' , doc , div ) ;
} * /
2020-04-14 18:46:31 +03:00
2020-11-27 21:09:05 +02:00
//await new Promise((resolve) => setTimeout(resolve, 500));
//return;
2020-08-23 15:12:08 +03:00
//console.time('download sticker' + doc.id);
2020-05-26 18:04:06 +03:00
2020-08-23 15:12:08 +03:00
//appDocsManager.downloadDocNew(doc.id).promise.then(res => res.json()).then(async(json) => {
2020-08-25 12:39:39 +03:00
//fetch(doc.url).then(res => res.json()).then(async(json) => {
2021-01-11 19:21:03 +04:00
/* return */ await appDocsManager . downloadDoc ( doc , /* undefined, */ lazyLoadQueue ? . queueId )
2020-08-28 14:25:43 +03:00
. then ( readBlobAsText )
2020-09-25 17:50:57 +03:00
//.then(JSON.parse)
2020-08-28 14:25:43 +03:00
. then ( async ( json ) = > {
2020-08-23 15:12:08 +03:00
//console.timeEnd('download sticker' + doc.id);
2020-09-20 01:38:00 +03:00
//console.log('loaded sticker:', doc, div/* , blob */);
2020-08-23 15:12:08 +03:00
if ( middleware && ! middleware ( ) ) return ;
2020-05-30 09:44:54 +03:00
2020-11-27 21:09:05 +02:00
let animation = await LottieLoader . loadAnimationWorker ( {
2020-02-11 22:35:57 +07:00
container : div ,
2020-06-13 11:19:39 +03:00
loop : loop && ! emoji ,
autoplay : play ,
2020-08-23 15:12:08 +03:00
animationData : json ,
2020-06-13 11:19:39 +03:00
width ,
height
2020-05-26 18:04:06 +03:00
} , group , toneIndex ) ;
2020-09-20 01:38:00 +03:00
//const deferred = deferredPromise<void>();
2020-08-28 14:25:43 +03:00
2020-06-13 11:19:39 +03:00
animation . addListener ( 'firstFrame' , ( ) = > {
2020-11-27 21:09:05 +02:00
const element = div . firstElementChild ;
const needFadeIn = ! element || element . tagName === 'svg' ;
const cb = ( ) = > {
2021-01-11 19:21:03 +04:00
if ( element && element !== animation . canvas ) {
2020-11-27 21:09:05 +02:00
element . remove ( ) ;
}
} ;
if ( ! needFadeIn ) {
cb ( ) ;
2020-06-13 11:19:39 +03:00
} else {
animation . canvas . classList . add ( 'fade-in' ) ;
2020-11-27 21:09:05 +02:00
if ( element ) {
2021-01-11 20:09:20 +04:00
element . classList . add ( 'fade-out' ) ;
2020-11-27 21:09:05 +02:00
}
2021-01-11 20:09:20 +04:00
setTimeout ( ( ) = > {
animation . canvas . classList . remove ( 'fade-in' ) ;
cb ( ) ;
} , 200 ) ;
2020-05-30 09:44:54 +03:00
}
2020-09-20 01:38:00 +03:00
2020-11-27 21:09:05 +02:00
appDocsManager . saveLottiePreview ( doc , animation . canvas , toneIndex ) ;
2020-09-20 01:38:00 +03:00
//deferred.resolve();
2020-06-13 11:19:39 +03:00
} , true ) ;
2020-08-28 14:25:43 +03:00
2020-06-13 11:19:39 +03:00
if ( emoji ) {
2020-12-12 18:30:01 +02:00
attachClickEvent ( div , ( e ) = > {
2020-11-21 15:13:23 +02:00
cancelEvent ( e ) ;
2020-06-13 11:19:39 +03:00
let animation = LottieLoader . getAnimation ( div ) ;
2020-08-28 14:25:43 +03:00
2020-06-13 11:19:39 +03:00
if ( animation . paused ) {
2020-11-18 22:07:31 +02:00
animation . autoplay = true ;
2020-06-13 11:19:39 +03:00
animation . restart ( ) ;
2020-02-11 22:35:57 +07:00
}
2020-06-13 11:19:39 +03:00
} ) ;
}
2020-09-20 01:38:00 +03:00
//return deferred;
2020-08-28 14:25:43 +03:00
//await new Promise((resolve) => setTimeout(resolve, 5e3));
2020-02-11 22:35:57 +07:00
} ) ;
2020-08-23 15:12:08 +03:00
//console.timeEnd('render sticker' + doc.id);
2021-01-11 19:21:03 +04:00
} else if ( stickerType === 1 ) {
const image = new Image ( ) ;
const thumbImage = div . firstElementChild && div . firstElementChild !== image ? div.firstElementChild : null ;
const needFadeIn = ! downloaded || thumbImage ;
2020-04-16 03:48:41 +03:00
2021-01-11 19:21:03 +04:00
image . classList . add ( 'media-sticker' ) ;
2020-11-19 01:51:39 +02:00
2021-01-11 19:21:03 +04:00
if ( needFadeIn ) {
image . classList . add ( 'fade-in' ) ;
2020-05-06 04:03:31 +03:00
}
2021-01-11 19:21:03 +04:00
return new Promise ( ( resolve , reject ) = > {
const r = ( ) = > {
if ( middleware && ! middleware ( ) ) return resolve ( ) ;
2020-08-28 14:25:43 +03:00
2021-01-11 19:21:03 +04:00
renderImageFromUrl ( image , doc . url , ( ) = > {
div . append ( image ) ;
2021-01-11 20:09:20 +04:00
if ( thumbImage ) {
thumbImage . classList . add ( 'fade-out' ) ;
}
2021-01-11 19:21:03 +04:00
window . requestAnimationFrame ( ( ) = > {
resolve ( ) ;
} ) ;
if ( needFadeIn ) {
setTimeout ( ( ) = > {
image . classList . remove ( 'fade-in' ) ;
if ( thumbImage ) {
thumbImage . remove ( ) ;
}
} , 200 ) ;
}
} ) ;
} ;
if ( doc . url ) r ( ) ;
else {
appDocsManager . downloadDoc ( doc , /* undefined, */ lazyLoadQueue ? . queueId ) . then ( r , resolve ) ;
}
} ) ;
}
} ;
2020-08-28 14:25:43 +03:00
2021-01-11 19:21:03 +04:00
const loadPromise : Promise < any > = lazyLoadQueue && ( ! doc . downloaded || stickerType == 2 ) ?
( lazyLoadQueue . push ( { div , load } ) , Promise . resolve ( ) ) :
load ( ) ;
if ( doc . downloaded && stickerType === 1 ) {
loadThumbPromise = loadPromise ;
if ( loadPromises ) {
loadPromises . push ( loadThumbPromise ) ;
2020-02-11 22:35:57 +07:00
}
2021-01-11 19:21:03 +04:00
}
return loadPromise ;
2020-02-11 22:35:57 +07:00
}
2020-02-16 01:08:26 +07:00
2020-10-11 22:12:17 +03:00
export function wrapReply ( title : string , subtitle : string , message? : any ) {
const replyContainer = new ReplyContainer ( 'reply' ) ;
replyContainer . fill ( title , subtitle , message ) ;
2020-02-17 19:18:06 +07:00
/////////console.log('wrapReply', title, subtitle, media);
2020-10-11 22:12:17 +03:00
return replyContainer . container ;
2020-02-16 01:08:26 +07:00
}
2020-05-02 00:28:40 +03:00
2020-11-12 00:43:09 +02:00
export function prepareAlbum ( options : {
container : HTMLElement ,
items : { w : number , h : number } [ ] ,
maxWidth : number ,
minWidth : number ,
spacing : number ,
maxHeight? : number ,
forMedia? : true
2020-05-02 00:28:40 +03:00
} ) {
2020-11-12 00:43:09 +02:00
const layouter = new Layouter ( options . items , options . maxWidth , options . minWidth , options . spacing , options . maxHeight ) ;
const layout = layouter . layout ( ) ;
2020-05-02 00:28:40 +03:00
2020-11-12 00:43:09 +02:00
const widthItem = layout . find ( item = > item . sides & RectPart . Right ) ;
const width = widthItem . geometry . width + widthItem . geometry . x ;
2020-05-02 00:28:40 +03:00
2020-11-12 00:43:09 +02:00
const heightItem = layout . find ( item = > item . sides & RectPart . Bottom ) ;
const height = heightItem . geometry . height + heightItem . geometry . y ;
2020-05-02 00:28:40 +03:00
2020-11-12 00:43:09 +02:00
const container = options . container ;
container . style . width = width + 'px' ;
container . style . height = height + 'px' ;
const children = container . children ;
2020-05-02 00:28:40 +03:00
2020-11-12 00:43:09 +02:00
layout . forEach ( ( { geometry , sides } , idx ) = > {
let div : HTMLElement ;
div = children [ idx ] as HTMLElement ;
if ( ! div ) {
div = document . createElement ( 'div' ) ;
container . append ( div ) ;
2020-05-09 15:02:07 +03:00
}
2020-12-08 21:48:44 +02:00
div . classList . add ( 'album-item' , 'grouped-item' ) ;
2020-05-02 00:28:40 +03:00
2020-11-12 00:43:09 +02:00
div . style . width = ( geometry . width / width * 100 ) + '%' ;
div . style . height = ( geometry . height / height * 100 ) + '%' ;
div . style . top = ( geometry . y / height * 100 ) + '%' ;
div . style . left = ( geometry . x / width * 100 ) + '%' ;
2020-05-02 00:28:40 +03:00
if ( sides & RectPart . Left && sides & RectPart . Top ) {
div . style . borderTopLeftRadius = 'inherit' ;
}
if ( sides & RectPart . Left && sides & RectPart . Bottom ) {
div . style . borderBottomLeftRadius = 'inherit' ;
}
if ( sides & RectPart . Right && sides & RectPart . Top ) {
div . style . borderTopRightRadius = 'inherit' ;
}
if ( sides & RectPart . Right && sides & RectPart . Bottom ) {
div . style . borderBottomRightRadius = 'inherit' ;
}
2020-11-12 00:43:09 +02:00
if ( options . forMedia ) {
const mediaDiv = document . createElement ( 'div' ) ;
mediaDiv . classList . add ( 'album-item-media' ) ;
div . append ( mediaDiv ) ;
}
// @ts-ignore
//div.style.backgroundColor = '#' + Math.floor(Math.random() * (2 ** 24 - 1)).toString(16).padStart(6, '0');
} ) ;
/ * i f ( o p t i o n s . f o r M e d i a ) {
layout . forEach ( ( _ , i ) = > {
const mediaDiv = document . createElement ( 'div' ) ;
mediaDiv . classList . add ( 'album-item-media' ) ;
options . container . children [ i ] . append ( mediaDiv ) ;
} ) ;
} * /
}
2021-01-10 20:10:02 +04:00
export function wrapAlbum ( { groupId , attachmentDiv , middleware , uploading , lazyLoadQueue , isOut , chat , loadPromises } : {
2020-12-11 04:06:16 +02:00
groupId : string ,
2020-11-12 00:43:09 +02:00
attachmentDiv : HTMLElement ,
middleware ? : ( ) = > boolean ,
lazyLoadQueue? : LazyLoadQueue ,
uploading? : boolean ,
2020-12-16 05:22:58 +02:00
isOut : boolean ,
2021-01-10 20:10:02 +04:00
chat : Chat ,
loadPromises? : Promise < any > [ ]
2020-11-12 00:43:09 +02:00
} ) {
const items : { size : PhotoSize.photoSize , media : any , message : any } [ ] = [ ] ;
2020-11-09 22:57:06 +03:00
2020-12-10 01:58:20 +02:00
// !lowest msgID will be the FIRST in album
2020-12-11 04:06:16 +02:00
const storage = appMessagesManager . getMidsByAlbum ( groupId ) ;
2020-11-12 00:43:09 +02:00
for ( const mid of storage ) {
2020-12-16 05:22:58 +02:00
const m = chat . getMessage ( mid ) ;
2020-11-12 00:43:09 +02:00
const media = m . media . photo || m . media . document ;
const size : any = media . _ == 'photo' ? appPhotosManager . choosePhotoSize ( media , 480 , 480 ) : { w : media.w , h : media.h } ;
items . push ( { size , media , message : m } ) ;
}
2020-12-19 03:07:24 +02:00
/* / / * pending
2020-12-10 01:58:20 +02:00
if ( storage [ 0 ] < 0 ) {
items . reverse ( ) ;
2020-12-19 03:07:24 +02:00
} * /
2020-12-10 01:58:20 +02:00
2020-11-12 00:43:09 +02:00
prepareAlbum ( {
container : attachmentDiv ,
items : items.map ( i = > ( { w : i.size.w , h : i.size.h } ) ) ,
maxWidth : mediaSizes.active.album.width ,
minWidth : 100 ,
spacing : 2 ,
forMedia : true
} ) ;
items . forEach ( ( item , idx ) = > {
const { size , media , message } = item ;
const div = attachmentDiv . children [ idx ] as HTMLElement ;
div . dataset . mid = '' + message . mid ;
const mediaDiv = div . firstElementChild as HTMLElement ;
2020-05-02 00:28:40 +03:00
if ( media . _ == 'photo' ) {
2020-12-11 04:06:16 +02:00
wrapPhoto ( {
photo : media ,
2020-05-02 00:28:40 +03:00
message ,
2020-12-11 04:06:16 +02:00
container : mediaDiv ,
boxWidth : 0 ,
boxHeight : 0 ,
2020-05-02 00:28:40 +03:00
isOut ,
lazyLoadQueue ,
middleware ,
2021-01-10 20:10:02 +04:00
size ,
loadPromises
2020-12-11 04:06:16 +02:00
} ) ;
2020-05-02 00:28:40 +03:00
} else {
wrapVideo ( {
doc : message.media.document ,
2020-11-09 22:57:06 +03:00
container : mediaDiv ,
2020-05-02 00:28:40 +03:00
message ,
boxWidth : 0 ,
boxHeight : 0 ,
withTail : false ,
isOut ,
lazyLoadQueue ,
2021-01-10 20:10:02 +04:00
middleware ,
loadPromises
2020-05-02 00:28:40 +03:00
} ) ;
}
2020-11-12 00:43:09 +02:00
} ) ;
2020-05-02 00:28:40 +03:00
}
2020-05-09 15:02:07 +03:00
2021-01-10 20:10:02 +04:00
export function wrapGroupedDocuments ( { albumMustBeRenderedFull , message , bubble , messageDiv , chat , loadPromises } : {
2020-12-10 01:58:20 +02:00
albumMustBeRenderedFull : boolean ,
message : any ,
messageDiv : HTMLElement ,
bubble : HTMLElement ,
2020-12-16 05:22:58 +02:00
uploading? : boolean ,
2021-01-10 20:10:02 +04:00
chat : Chat ,
loadPromises? : Promise < any > [ ]
2020-12-10 01:58:20 +02:00
} ) {
let nameContainer : HTMLDivElement ;
2020-12-16 05:22:58 +02:00
const mids = albumMustBeRenderedFull ? chat . getMidsByMid ( message . mid ) : [ message . mid ] ;
2020-12-19 03:07:24 +02:00
/ * i f ( i s P e n d i n g ) {
2020-12-10 01:58:20 +02:00
mids . reverse ( ) ;
2020-12-19 03:07:24 +02:00
} * /
2020-12-10 01:58:20 +02:00
mids . forEach ( ( mid , idx ) = > {
2020-12-16 05:22:58 +02:00
const message = chat . getMessage ( mid ) ;
2020-12-19 03:07:24 +02:00
const div = wrapDocument ( {
2021-01-10 20:10:02 +04:00
message ,
loadPromises
2020-12-19 03:07:24 +02:00
} ) ;
2020-12-10 01:58:20 +02:00
const container = document . createElement ( 'div' ) ;
container . classList . add ( 'document-container' ) ;
container . dataset . mid = '' + mid ;
const wrapper = document . createElement ( 'div' ) ;
wrapper . classList . add ( 'document-wrapper' ) ;
if ( message . message ) {
const messageDiv = document . createElement ( 'div' ) ;
messageDiv . classList . add ( 'document-message' ) ;
const richText = RichTextProcessor . wrapRichText ( message . message , {
entities : message.totalEntities
} ) ;
messageDiv . innerHTML = richText ;
wrapper . append ( messageDiv ) ;
}
if ( mids . length > 1 ) {
const selection = document . createElement ( 'div' ) ;
selection . classList . add ( 'document-selection' ) ;
container . append ( selection ) ;
container . classList . add ( 'grouped-item' ) ;
if ( idx === 0 ) {
nameContainer = wrapper ;
}
}
wrapper . append ( div ) ;
container . append ( wrapper ) ;
messageDiv . append ( container ) ;
} ) ;
if ( mids . length > 1 ) {
bubble . classList . add ( 'is-multiple-documents' , 'is-grouped' ) ;
}
return nameContainer ;
}
2020-12-18 05:07:32 +02:00
export function wrapPoll ( message : any ) {
2020-06-13 11:19:39 +03:00
const elem = new PollElement ( ) ;
2020-12-18 05:07:32 +02:00
elem . message = message ;
elem . setAttribute ( 'peer-id' , '' + message . peerId ) ;
elem . setAttribute ( 'poll-id' , message . media . poll . id ) ;
elem . setAttribute ( 'message-id' , '' + message . mid ) ;
2020-12-24 10:19:56 +02:00
//elem.render();
2020-05-09 15:02:07 +03:00
return elem ;
}