Eduard Kuzmenko
5 years ago
11 changed files with 581 additions and 53 deletions
@ -0,0 +1,330 @@
@@ -0,0 +1,330 @@
|
||||
//import { MTDocument, ProgressivePreloader, wrapVideo } from "../../components/misc";
|
||||
import appPeersManager from "./appPeersManager"; |
||||
import appDialogsManager from "./appDialogsManager"; |
||||
import appPhotosManager from "./appPhotosManager"; |
||||
import appSidebarRight from "./appSidebarRight"; |
||||
import { $rootScope } from "../utils"; |
||||
import appMessagesManager from "./appMessagesManager"; |
||||
//import { CancellablePromise } from "../mtproto/apiFileManager";
|
||||
import { RichTextProcessor } from "../richtextprocessor"; |
||||
import { logger } from "../polyfill"; |
||||
import ProgressivePreloader from "../../components/preloader"; |
||||
import { wrapVideo } from "../../components/wrappers"; |
||||
|
||||
export class AppMediaViewer { |
||||
private overlaysDiv = document.querySelector('.overlays') as HTMLDivElement; |
||||
private author = { |
||||
avatarEl: this.overlaysDiv.querySelector('.user-avatar') as HTMLDivElement, |
||||
nameEl: this.overlaysDiv.querySelector('.media-viewer-name') as HTMLDivElement, |
||||
date: this.overlaysDiv.querySelector('.media-viewer-date') as HTMLDivElement |
||||
}; |
||||
private buttons = { |
||||
delete: this.overlaysDiv.querySelector('.media-viewer-delete-button') as HTMLDivElement, |
||||
forward: this.overlaysDiv.querySelector('.media-viewer-forward-button') as HTMLDivElement, |
||||
download: this.overlaysDiv.querySelector('.media-viewer-download-button') as HTMLDivElement, |
||||
close: this.overlaysDiv.querySelector('.media-viewer-close-button') as HTMLDivElement, |
||||
prev: this.overlaysDiv.querySelector('.media-viewer-switcher-left') as HTMLDivElement, |
||||
next: this.overlaysDiv.querySelector('.media-viewer-switcher-right') as HTMLDivElement, |
||||
}; |
||||
private content = { |
||||
container: this.overlaysDiv.querySelector('.media-viewer-media') as HTMLDivElement, |
||||
caption: this.overlaysDiv.querySelector('.media-viewer-caption') as HTMLDivElement, |
||||
mover: this.overlaysDiv.querySelector('.media-viewer-mover') as HTMLDivElement |
||||
}; |
||||
|
||||
private reverse = false; |
||||
public currentMessageID = 0; |
||||
private higherMsgID: number | undefined = 0; |
||||
private lowerMsgID: number | undefined = 0; |
||||
private preloader: ProgressivePreloader = null; |
||||
private lastTarget: HTMLElement = null; |
||||
|
||||
public log: ReturnType<typeof logger>; |
||||
|
||||
constructor() { |
||||
this.log = logger('AMV'); |
||||
this.preloader = new ProgressivePreloader(); |
||||
|
||||
this.buttons.close.addEventListener('click', () => { |
||||
//this.overlaysDiv.classList.remove('active');
|
||||
this.content.container.innerHTML = ''; |
||||
this.currentMessageID = 0; |
||||
|
||||
this.setMoverToTarget(this.lastTarget, true); |
||||
}); |
||||
|
||||
this.buttons.prev.addEventListener('click', () => { |
||||
let id = this.reverse ? this.lowerMsgID : this.higherMsgID; |
||||
if(id) { |
||||
this.openMedia(appMessagesManager.getMessage(id), this.reverse); |
||||
} else { |
||||
this.buttons.prev.style.display = 'none'; |
||||
} |
||||
}); |
||||
|
||||
this.buttons.next.addEventListener('click', () => { |
||||
let id = this.reverse ? this.higherMsgID : this.lowerMsgID; |
||||
if(id) { |
||||
this.openMedia(appMessagesManager.getMessage(id), this.reverse); |
||||
} else { |
||||
this.buttons.next.style.display = 'none'; |
||||
} |
||||
}); |
||||
|
||||
this.buttons.download.addEventListener('click', () => { |
||||
let message = appMessagesManager.getMessage(this.currentMessageID); |
||||
appPhotosManager.downloadPhoto(message.media.photo.id); |
||||
}); |
||||
/* this.buttons.prev.onclick = (e) => { |
||||
let history = appSidebarRight.historiesStorage[$rootScope.selectedPeerID]['inputMessagesFilterPhotoVideo'].slice(); |
||||
|
||||
let message: any; |
||||
|
||||
if(!this.reverse) { |
||||
for(let mid of history) { |
||||
if(mid > this.currentMessageID) { |
||||
let _message = appMessagesManager.getMessage(mid); |
||||
if(_message.media && _message.media.photo) { |
||||
message = _message; |
||||
} |
||||
} else break; |
||||
} |
||||
} else { |
||||
for(let mid of history) { |
||||
if(mid < this.currentMessageID) { |
||||
let _message = appMessagesManager.getMessage(mid); |
||||
if(_message.media && _message.media.photo) { |
||||
message = _message; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
if(message) { |
||||
this.openMedia(message.media.photo, message.mid, this.reverse); |
||||
} else { |
||||
this.buttons.prev.style.display = 'none'; |
||||
} |
||||
}; |
||||
|
||||
this.buttons.next.onclick = (e) => { |
||||
let history = appSidebarRight.historiesStorage[$rootScope.selectedPeerID]['inputMessagesFilterPhotoVideo'].slice(); |
||||
|
||||
let message: any; |
||||
|
||||
if(this.reverse) { |
||||
for(let mid of history) { |
||||
if(mid > this.currentMessageID) { |
||||
let _message = appMessagesManager.getMessage(mid); |
||||
if(_message.media && _message.media.photo) { |
||||
message = _message; |
||||
} |
||||
} else break; |
||||
} |
||||
} else { |
||||
for(let mid of history) { |
||||
if(mid < this.currentMessageID) { |
||||
let _message = appMessagesManager.getMessage(mid); |
||||
if(_message.media && _message.media.photo) { |
||||
message = _message; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
if(message) { |
||||
this.openMedia(message.media.photo, message.mid, this.reverse); |
||||
} else { |
||||
this.buttons.next.style.display = 'none'; |
||||
} |
||||
}; */ |
||||
} |
||||
|
||||
public setMoverToTarget(target: HTMLElement, closing = false) { |
||||
let mover = this.content.mover; |
||||
|
||||
if(!closing) { |
||||
mover.innerHTML = ''; |
||||
} |
||||
|
||||
let rect = target.getBoundingClientRect(); |
||||
mover.style.transform = `translate(${rect.left}px, ${rect.top}px)`; |
||||
mover.style.width = rect.width + 'px'; |
||||
mover.style.height = rect.height + 'px'; |
||||
|
||||
if(!closing) { |
||||
let img: HTMLImageElement; |
||||
let video: HTMLVideoElement; |
||||
|
||||
if(target.tagName == 'DIV') { // means backgrounded with cover
|
||||
//img.style.objectFit = 'cover';
|
||||
img = new Image(); |
||||
img.src = target.style.backgroundImage.slice(5, -2); |
||||
} else if(target.tagName == 'IMG') { |
||||
img = new Image(); |
||||
img.src = (target as HTMLImageElement).src; |
||||
img.style.objectFit = 'contain'; |
||||
}/* else if(target.tagName == 'VIDEO') { |
||||
let video = document.createElement('video'); |
||||
let source = document.createElement('source'); |
||||
source.src = target.querySelector('source').src; |
||||
video.append(source); |
||||
} */ |
||||
|
||||
if(img) { |
||||
mover.appendChild(img); |
||||
} else if(video) { |
||||
mover.appendChild(video); |
||||
} |
||||
|
||||
mover.style.display = ''; |
||||
mover.classList.add('active'); |
||||
} else { |
||||
setTimeout(() => { |
||||
this.overlaysDiv.classList.remove('active'); |
||||
mover.classList.remove('active'); |
||||
mover.style.display = 'none'; |
||||
}, 250); |
||||
} |
||||
} |
||||
|
||||
public openMedia(message: any, reverse = false, target?: HTMLElement) { |
||||
this.log('openMedia doc:', message); |
||||
let media = message.media.photo || message.media.document || message.media.webpage.document || message.media.webpage.photo; |
||||
|
||||
let isVideo = media.mime_type == 'video/mp4'; |
||||
|
||||
this.currentMessageID = message.mid; |
||||
this.reverse = reverse; |
||||
|
||||
let container = this.content.container; |
||||
|
||||
if(container.firstElementChild) { |
||||
container.innerHTML = ''; |
||||
} |
||||
|
||||
let date = new Date(media.date * 1000); |
||||
let months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; |
||||
|
||||
let dateStr = months[date.getMonth()] + ' ' + date.getDate() + ' at '+ date.getHours() + ':' + ('0' + date.getMinutes()).slice(-2); |
||||
this.author.date.innerText = dateStr; |
||||
|
||||
let name = appPeersManager.getPeerTitle(message.fromID); |
||||
this.author.nameEl.innerHTML = name; |
||||
|
||||
if(message.message) { |
||||
this.content.caption.innerHTML = RichTextProcessor.wrapRichText(message.message, { |
||||
entities: message.totalEntities |
||||
}); |
||||
} else { |
||||
this.content.caption.innerHTML = ''; |
||||
} |
||||
|
||||
appDialogsManager.loadDialogPhoto(this.author.avatarEl, message.fromID); |
||||
|
||||
this.overlaysDiv.classList.add('active'); |
||||
|
||||
container.classList.add('loading'); |
||||
|
||||
// ok set
|
||||
let mover = this.content.mover; |
||||
|
||||
let rect = target.getBoundingClientRect(); |
||||
|
||||
this.lastTarget = target; |
||||
this.setMoverToTarget(target); |
||||
let maxWidth = appPhotosManager.windowW - 16; |
||||
let maxHeight = appPhotosManager.windowH - 100; |
||||
if(isVideo) { |
||||
//this.preloader.attach(container);
|
||||
//this.preloader.setProgress(75);
|
||||
|
||||
this.log('will wrap video'); |
||||
|
||||
let size = appPhotosManager.setAttachmentSize(media, container, maxWidth, maxHeight); |
||||
let containerRect = container.getBoundingClientRect(); |
||||
let scaleX = containerRect.width / rect.width; |
||||
let scaleY = containerRect.height / rect.height; |
||||
mover.style.transform = `translate(${containerRect.left}px, ${containerRect.top}px) scale(${scaleX}, ${scaleY})`; |
||||
wrapVideo.call(this, media, mover, message, false, this.preloader).then(() => { |
||||
if(this.currentMessageID != message.mid) { |
||||
this.log.warn('media viewer changed video'); |
||||
return; |
||||
} |
||||
}); |
||||
|
||||
|
||||
/* appPhotosManager.setAttachmentSize(media, container, appPhotosManager.windowW, appPhotosManager.windowH); |
||||
wrapVideo.call(this, media, container, message, false, this.preloader).then(() => { |
||||
if(this.currentMessageID != message.mid) { |
||||
this.log.warn('media viewer changed video'); |
||||
return; |
||||
} |
||||
|
||||
container.classList.remove('loading'); |
||||
container.style.width = ''; |
||||
container.style.height = ''; |
||||
}); */ |
||||
} else { |
||||
let size = appPhotosManager.setAttachmentSize(media.id, container, maxWidth, maxHeight); |
||||
|
||||
let containerRect = container.getBoundingClientRect(); |
||||
let scaleX = containerRect.width / rect.width; |
||||
let scaleY = containerRect.height / rect.height; |
||||
mover.style.transform = `translate(${containerRect.left}px, ${containerRect.top}px) scale(${scaleX}, ${scaleY})`; |
||||
|
||||
this.preloader.attach(mover); |
||||
//this.preloader.setProgress(75);
|
||||
|
||||
let cancellablePromise = appPhotosManager.preloadPhoto(media.id, size); |
||||
cancellablePromise.then((blob) => { |
||||
if(this.currentMessageID != message.mid) { |
||||
this.log.warn('media viewer changed photo'); |
||||
return; |
||||
} |
||||
|
||||
this.log('indochina', blob); |
||||
|
||||
let image = mover.firstElementChild as HTMLImageElement || new Image(); |
||||
image.src = URL.createObjectURL(blob); |
||||
mover.append(image); |
||||
|
||||
/* container.classList.remove('loading'); |
||||
|
||||
container.style.width = ''; |
||||
container.style.height = ''; */ |
||||
|
||||
this.preloader.detach(); |
||||
}).catch(err => { |
||||
this.log.error(err); |
||||
}); |
||||
} |
||||
|
||||
let history = appSidebarRight.historiesStorage[$rootScope.selectedPeerID]['inputMessagesFilterPhotoVideo'].slice(); |
||||
let index = history.findIndex(m => m == message.mid); |
||||
let comparer = (mid: number) => { |
||||
let _message = appMessagesManager.getMessage(mid); |
||||
let media = _message.media; |
||||
|
||||
if(media && (media.photo || (media.document && ['video', 'gif'].indexOf(media.document.type) !== -1))) return true; |
||||
return false; |
||||
}; |
||||
|
||||
this.higherMsgID = history.slice(0, index).reverse().find(comparer); |
||||
this.lowerMsgID = history.slice(index + 1).find(comparer); |
||||
|
||||
if(this.reverse) { |
||||
this.buttons.prev.style.display = this.lowerMsgID !== undefined ? '' : 'none'; |
||||
this.buttons.next.style.display = this.higherMsgID !== undefined ? '' : 'none'; |
||||
} else { |
||||
this.buttons.prev.style.display = this.higherMsgID !== undefined ? '' : 'none'; |
||||
this.buttons.next.style.display = this.lowerMsgID !== undefined ? '' : 'none'; |
||||
} |
||||
|
||||
//console.log('prev and next', prevMsgID, nextMsgID);
|
||||
} |
||||
} |
||||
|
||||
export default new AppMediaViewer(); |
Loading…
Reference in new issue