Images .onload & several fixes
This commit is contained in:
parent
da6a4d2d2e
commit
67aca5c877
@ -92,14 +92,26 @@ export function ripple(elem: HTMLElement, callback: (id: number) => Promise<bool
|
||||
});
|
||||
}
|
||||
|
||||
export function renderImageFromUrl(elem: HTMLElement | HTMLImageElement | SVGImageElement, url: string) {
|
||||
let img = new Image();
|
||||
img.src = url;
|
||||
img.onload = () => {
|
||||
if(elem instanceof HTMLImageElement) elem.src = url;
|
||||
else if(elem instanceof SVGImageElement) elem.setAttributeNS(null, 'href', url);
|
||||
else elem.style.backgroundImage = 'url(' + url + ')';
|
||||
};
|
||||
let loadedURLs: {[url: string]: boolean} = {};
|
||||
let set = (elem: HTMLElement | HTMLImageElement | SVGImageElement | HTMLSourceElement, url: string) => {
|
||||
if(elem instanceof HTMLImageElement || elem instanceof HTMLSourceElement) elem.src = url;
|
||||
else if(elem instanceof SVGImageElement) elem.setAttributeNS(null, 'href', url);
|
||||
else elem.style.backgroundImage = 'url(' + url + ')';
|
||||
};
|
||||
|
||||
export function renderImageFromUrl(elem: HTMLElement | HTMLImageElement | SVGImageElement | HTMLSourceElement, url: string) {
|
||||
if(loadedURLs[url]) return set(elem, url);
|
||||
|
||||
if(elem instanceof HTMLSourceElement) {
|
||||
return elem.src = url;
|
||||
} else {
|
||||
let loader = new Image();
|
||||
loader.src = url;
|
||||
loader.onload = () => {
|
||||
set(elem, url);
|
||||
loadedURLs[url] = true;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function putPreloader(elem: Element, returnDiv = false) {
|
||||
|
@ -875,9 +875,8 @@ export default class Scrollable {
|
||||
|
||||
public removeElement(element: Element) {
|
||||
if(!this.splitUp) {
|
||||
if(this.container.contains(element)) {
|
||||
//fastdom.mutate(() => this.container.removeChild(element));
|
||||
this.container.removeChild(element);
|
||||
if(element.parentElement) {
|
||||
element.remove();
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -36,6 +36,7 @@ export type MTDocument = {
|
||||
file?: File,
|
||||
duration?: number,
|
||||
downloaded?: boolean,
|
||||
url?: string,
|
||||
version?: any,
|
||||
|
||||
audioTitle?: string,
|
||||
@ -110,11 +111,10 @@ export function wrapVideo(this: AppImManager, doc: MTDocument, container: HTMLDi
|
||||
|
||||
//return;
|
||||
|
||||
///////console.log('loaded doc:', doc, blob, container);
|
||||
console.log('loaded doc:', doc, doc.url, blob, container);
|
||||
|
||||
//source.src = doc.url;
|
||||
renderImageFromUrl(source, doc.url);
|
||||
source.type = doc.mime_type;
|
||||
source.src = URL.createObjectURL(blob);
|
||||
video.append(source);
|
||||
|
||||
if(!withTail) {
|
||||
@ -141,7 +141,7 @@ export function wrapVideo(this: AppImManager, doc: MTDocument, container: HTMLDi
|
||||
};
|
||||
|
||||
if(doc.type == 'gif' || true) { // extra fix
|
||||
return this.lazyLoadQueue.push({div: container, load: loadVideo, wasSeen: true});
|
||||
return doc.downloaded ? loadVideo() : this.lazyLoadQueue.push({div: container, load: loadVideo, wasSeen: true});
|
||||
} /* else { // if video
|
||||
let load = () => appPhotosManager.preloadPhoto(doc).then((blob) => {
|
||||
if((this.peerID ? this.peerID : this.currentMessageID) != peerID) {
|
||||
@ -446,7 +446,7 @@ function wrapMediaWithTail(photo: any, message: {mid: number, message: string},
|
||||
let image = document.createElementNS("http://www.w3.org/2000/svg", "image");
|
||||
svg.append(image);
|
||||
|
||||
let size = appPhotosManager.setAttachmentSize(photo.type ? photo : photo.id, svg, boxWidth, boxHeight, false);
|
||||
let size = appPhotosManager.setAttachmentSize(photo._ == 'document' ? photo : photo.id, svg, boxWidth, boxHeight);
|
||||
|
||||
let width = +svg.getAttributeNS(null, 'width');
|
||||
let height = +svg.getAttributeNS(null, 'height');
|
||||
@ -540,7 +540,7 @@ export function wrapSticker(doc: MTDocument, div: HTMLDivElement, middleware?: (
|
||||
|
||||
console.log('wrap sticker', doc, div, onlyThumb);
|
||||
|
||||
if(doc.thumbs && !div.firstElementChild) {
|
||||
if(doc.thumbs && !div.firstElementChild && (!doc.downloaded || stickerType == 2)) {
|
||||
let thumb = doc.thumbs[0];
|
||||
|
||||
console.log('wrap sticker', thumb, div);
|
||||
@ -652,17 +652,19 @@ export function wrapSticker(doc: MTDocument, div: HTMLDivElement, middleware?: (
|
||||
reader.readAsArrayBuffer(blob);
|
||||
} else if(stickerType == 1) {
|
||||
let img = new Image();
|
||||
|
||||
appWebpManager.polyfillImage(img, blob).then(() => {
|
||||
if(div.firstElementChild && div.firstElementChild != img) {
|
||||
div.firstElementChild.remove();
|
||||
}
|
||||
});
|
||||
|
||||
//img.src = URL.createObjectURL(blob);
|
||||
|
||||
/* div.style.height = doc.h + 'px';
|
||||
div.style.width = doc.w + 'px'; */
|
||||
|
||||
if(!doc.url) {
|
||||
appWebpManager.polyfillImage(img, blob).then((url) => {
|
||||
doc.url = url;
|
||||
|
||||
if(div.firstElementChild && div.firstElementChild != img) {
|
||||
div.firstElementChild.remove();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
img.src = doc.url;
|
||||
}
|
||||
|
||||
div.append(img);
|
||||
}
|
||||
|
||||
|
@ -218,8 +218,7 @@ export class AppDialogsManager {
|
||||
}
|
||||
|
||||
let img = new Image();
|
||||
img.src = this.savedAvatarURLs[peerID];
|
||||
//renderImageFromUrl(img, this.savedAvatarURLs[peerID]);
|
||||
renderImageFromUrl(img, this.savedAvatarURLs[peerID]);
|
||||
div.innerHTML = '';
|
||||
//div.style.fontSize = '0'; // need
|
||||
//div.style.backgroundColor = '';
|
||||
|
@ -37,10 +37,10 @@ class AppDocsManager {
|
||||
break;
|
||||
|
||||
case 'documentAttributeAudio':
|
||||
apiDoc.duration = attribute.duration
|
||||
apiDoc.audioTitle = attribute.title
|
||||
apiDoc.audioPerformer = attribute.performer
|
||||
apiDoc.type = attribute.pFlags.voice ? 'voice' : 'audio'
|
||||
apiDoc.duration = attribute.duration;
|
||||
apiDoc.audioTitle = attribute.title;
|
||||
apiDoc.audioPerformer = attribute.performer;
|
||||
apiDoc.type = attribute.pFlags.voice ? 'voice' : 'audio';
|
||||
break;
|
||||
|
||||
case 'documentAttributeVideo':
|
||||
@ -49,7 +49,7 @@ class AppDocsManager {
|
||||
apiDoc.h = attribute.h;
|
||||
if(apiDoc.thumbs && attribute.pFlags.round_message) {
|
||||
apiDoc.type = 'round';
|
||||
} else if(apiDoc.thumbs) {
|
||||
} else /* if(apiDoc.thumbs) */ {
|
||||
apiDoc.type = 'video';
|
||||
}
|
||||
break;
|
||||
@ -64,14 +64,14 @@ class AppDocsManager {
|
||||
|
||||
if(attribute.stickerset) {
|
||||
if(attribute.stickerset._ == 'inputStickerSetEmpty') {
|
||||
delete attribute.stickerset
|
||||
delete attribute.stickerset;
|
||||
} else if(attribute.stickerset._ == 'inputStickerSetID') {
|
||||
apiDoc.stickerSetInput = attribute.stickerset
|
||||
apiDoc.stickerSetInput = attribute.stickerset;
|
||||
}
|
||||
}
|
||||
|
||||
if(apiDoc.thumbs && apiDoc.mime_type == 'image/webp') {
|
||||
apiDoc.type = 'sticker'
|
||||
apiDoc.type = 'sticker';
|
||||
} else if(apiDoc.mime_type == 'application/x-tgsticker') {
|
||||
apiDoc.type = 'sticker';
|
||||
apiDoc.animated = true;
|
||||
@ -103,22 +103,22 @@ class AppDocsManager {
|
||||
apiDoc.mime_type = 'video/mp4';
|
||||
break;
|
||||
case 'sticker':
|
||||
apiDoc.mime_type = 'image/webp'
|
||||
break
|
||||
apiDoc.mime_type = 'image/webp';
|
||||
break;
|
||||
case 'audio':
|
||||
apiDoc.mime_type = 'audio/mpeg'
|
||||
break
|
||||
apiDoc.mime_type = 'audio/mpeg';
|
||||
break;
|
||||
case 'voice':
|
||||
apiDoc.mime_type = 'audio/ogg'
|
||||
break
|
||||
apiDoc.mime_type = 'audio/ogg';
|
||||
break;
|
||||
default:
|
||||
apiDoc.mime_type = 'application/octet-stream'
|
||||
break
|
||||
apiDoc.mime_type = 'application/octet-stream';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!apiDoc.file_name) {
|
||||
apiDoc.file_name = ''
|
||||
apiDoc.file_name = '';
|
||||
}
|
||||
|
||||
if(apiDoc._ == 'documentEmpty') {
|
||||
@ -132,10 +132,6 @@ class AppDocsManager {
|
||||
return this.docs[docID] || {_: 'documentEmpty'};
|
||||
}
|
||||
|
||||
public hasDoc(docID: string) {
|
||||
return this.docs[docID] !== undefined;
|
||||
}
|
||||
|
||||
public getFileName(doc: MTDocument) {
|
||||
if(doc.file_name) {
|
||||
return doc.file_name;
|
||||
@ -209,9 +205,9 @@ class AppDocsManager {
|
||||
if(blob) {
|
||||
doc.downloaded = true;
|
||||
|
||||
/* FileManager.getFileCorrectUrl(blob, doc.mime_type).then((url) => {
|
||||
doc.url = url;
|
||||
}); */
|
||||
if(/* !doc.animated || */doc.type != 'sticker') {
|
||||
doc.url = FileManager.getFileCorrectUrl(blob, doc.mime_type);
|
||||
}
|
||||
}
|
||||
|
||||
/* doc.progress.percent = 100;
|
||||
|
@ -28,76 +28,6 @@ console.log('appImManager included!');
|
||||
|
||||
let testScroll = false;
|
||||
|
||||
class ScrollPosition {
|
||||
previousScrollHeightMinusTop = 0;
|
||||
readyFor = 'up';
|
||||
container: HTMLElement;
|
||||
rAF: number;
|
||||
debug = true;
|
||||
prepared = false;
|
||||
|
||||
constructor(node: HTMLElement) {
|
||||
this.container = node.parentElement;
|
||||
}
|
||||
|
||||
restore(callback?: () => void) {
|
||||
return;
|
||||
|
||||
let setScrollTop = this.container.scrollHeight - this.previousScrollHeightMinusTop;
|
||||
if(this.debug) appImManager.log('scrollPosition restore', this.readyFor, this.container.scrollHeight,
|
||||
setScrollTop, this.container, this.container.parentElement.classList.contains('scrolled-down'));
|
||||
|
||||
if(this.readyFor === 'up' || this.container.parentElement.classList.contains('scrolled-down')) {
|
||||
if(this.debug) appImManager.log('scrollPosition restore 2', this.readyFor, this.container.scrollHeight,
|
||||
setScrollTop, this.container);
|
||||
|
||||
if(this.rAF) window.cancelAnimationFrame(this.rAF);
|
||||
this.rAF = window.requestAnimationFrame(() => {
|
||||
this.container.scrollTop = this.container.scrollHeight - this.previousScrollHeightMinusTop;
|
||||
this.rAF = 0;
|
||||
this.prepared = false;
|
||||
|
||||
callback && callback();
|
||||
});
|
||||
}/* else if(this.container.parentElement.classList.contains('scrolled-down')) {
|
||||
if(this.debug) appImManager.log('scrollPosition restore 2', this.readyFor, this.container.scrollHeight,
|
||||
setScrollTop, this.container);
|
||||
|
||||
this.container.scrollTop = setScrollTop;
|
||||
this.prepared = false;
|
||||
} */
|
||||
|
||||
// 'down' doesn't need to be special cased unless the
|
||||
// content was flowing upwards, which would only happen
|
||||
// if the container is position: absolute, bottom: 0 for
|
||||
// a Facebook messages effect
|
||||
}
|
||||
|
||||
prepareFor(direction = 'up') {
|
||||
return;
|
||||
//if(this.prepared) return;
|
||||
|
||||
if(this.rAF) {
|
||||
window.cancelAnimationFrame(this.rAF);
|
||||
this.rAF = 0;
|
||||
}
|
||||
|
||||
this.readyFor = direction;
|
||||
|
||||
if(direction == 'down') {
|
||||
let scrollTop = this.container.scrollTop;
|
||||
this.previousScrollHeightMinusTop = scrollTop > 0 ? this.container.scrollHeight - scrollTop : 0;
|
||||
} else {
|
||||
this.previousScrollHeightMinusTop = this.container.scrollHeight - this.container.scrollTop;
|
||||
}
|
||||
//let scrollTop = this.container.scrollTop;
|
||||
//this.previousScrollHeightMinusTop = scrollTop > 0 || this.readyFor == 'up' ? this.container.scrollHeight - this.container.scrollTop : 0;
|
||||
|
||||
if(this.debug) appImManager.log.warn('scrollPosition prepareFor', direction, this.container.scrollHeight,
|
||||
this.container.scrollTop, this.previousScrollHeightMinusTop);
|
||||
}
|
||||
}
|
||||
|
||||
export class AppImManager {
|
||||
public pageEl = document.querySelector('.page-chats') as HTMLDivElement;
|
||||
public btnMute = this.pageEl.querySelector('.tool-mute') as HTMLButtonElement;
|
||||
@ -142,8 +72,7 @@ export class AppImManager {
|
||||
|
||||
public scroll: HTMLDivElement = null;
|
||||
public scrollable: Scrollable = null;
|
||||
public scrollPosition: ScrollPosition = null;
|
||||
|
||||
|
||||
public log: ReturnType<typeof logger>;
|
||||
|
||||
private preloader: ProgressivePreloader = null;
|
||||
@ -171,6 +100,8 @@ export class AppImManager {
|
||||
private setPeerPromise: Promise<boolean> = null;
|
||||
|
||||
public bubbleGroups = new BubbleGroups();
|
||||
|
||||
private scrolledDown = true;
|
||||
|
||||
constructor() {
|
||||
/* if(!lottieLoader.loaded) {
|
||||
@ -204,7 +135,7 @@ export class AppImManager {
|
||||
$rootScope.$on('history_append', (e: CustomEvent) => {
|
||||
let details = e.detail;
|
||||
|
||||
this.renderMessagesByIDs([details.messageID]);
|
||||
this.renderNewMessagesByIDs([details.messageID]);
|
||||
});
|
||||
|
||||
// will call when sent for update pos
|
||||
@ -221,8 +152,6 @@ export class AppImManager {
|
||||
//this.log('history_update', this.bubbles[mid], mid, message);
|
||||
|
||||
this.renderMessage(message, false, false, bubble);
|
||||
|
||||
this.deleteEmptySideDivs();
|
||||
}
|
||||
});
|
||||
|
||||
@ -232,9 +161,7 @@ export class AppImManager {
|
||||
|
||||
let msgIDs = msgIDsByPeer[this.peerID];
|
||||
|
||||
this.renderMessagesByIDs(msgIDs);
|
||||
|
||||
//appDialogsManager.sortDom();
|
||||
this.renderNewMessagesByIDs(msgIDs);
|
||||
});
|
||||
|
||||
$rootScope.$on('history_delete', (e: CustomEvent) => {
|
||||
@ -244,10 +171,6 @@ export class AppImManager {
|
||||
} = e.detail;
|
||||
|
||||
this.deleteMessagesByIDs(Object.keys(detail.msgs).map(s => +s));
|
||||
|
||||
setTimeout(() => {
|
||||
this.deleteEmptySideDivs();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
// Calls when message successfully sent and we have an ID
|
||||
@ -667,37 +590,6 @@ export class AppImManager {
|
||||
});
|
||||
}
|
||||
|
||||
public deleteEmptySideDivs() {
|
||||
return;
|
||||
|
||||
let nodes = Array.from(this.chatInner.childNodes) as HTMLDivElement[];
|
||||
nodes.filter((node) => {
|
||||
let childElementCount = node.childElementCount;
|
||||
|
||||
if(!childElementCount) {
|
||||
node.remove();
|
||||
return false;
|
||||
} else if(childElementCount == 1) {
|
||||
let child = node.firstElementChild;
|
||||
if(child.classList.contains('service')) {
|
||||
node.remove();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}).forEach(node => {
|
||||
let nextNode = node.nextElementSibling;
|
||||
if(nextNode && node.className == nextNode.className) {
|
||||
(Array.from(node.childNodes) as HTMLDivElement[]).reverse().forEach(div => {
|
||||
nextNode.prepend(div);
|
||||
});
|
||||
|
||||
node.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public updateStatus() {
|
||||
if(!this.myID) return Promise.resolve();
|
||||
|
||||
@ -779,8 +671,10 @@ export class AppImManager {
|
||||
|
||||
if(this.scroll.scrollHeight - (this.scroll.scrollTop + this.scroll.offsetHeight) == 0/* <= 5 */) {
|
||||
this.scroll.parentElement.classList.add('scrolled-down');
|
||||
this.scrolledDown = true;
|
||||
} else if(this.scroll.parentElement.classList.contains('scrolled-down')) {
|
||||
this.scroll.parentElement.classList.remove('scrolled-down');
|
||||
this.scrolledDown = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -793,8 +687,7 @@ export class AppImManager {
|
||||
//this.scrollable.setVirtualContainer(this.chatInner);
|
||||
this.scrollable.onScrolledTop = () => this.loadMoreHistory(true);
|
||||
this.scrollable.onScrolledBottom = () => this.loadMoreHistory(false);
|
||||
|
||||
this.scrollPosition = new ScrollPosition(this.chatInner);
|
||||
|
||||
this.scroll.addEventListener('scroll', this.onScroll.bind(this));
|
||||
this.scroll.parentElement.classList.add('scrolled-down');
|
||||
}
|
||||
@ -931,6 +824,7 @@ export class AppImManager {
|
||||
this.getHistoryTopPromise = this.getHistoryBottomPromise = undefined;
|
||||
|
||||
//this.scrollable.setVirtualContainer(this.chatInner);
|
||||
this.scrollable.setVirtualContainer(null);
|
||||
|
||||
////console.timeEnd('appImManager cleanup');
|
||||
}
|
||||
@ -996,6 +890,8 @@ export class AppImManager {
|
||||
this.chatInner.style.visibility = 'hidden';
|
||||
this.chatInput.style.display = appPeersManager.isChannel(peerID) && !appPeersManager.isMegagroup(peerID) ? 'none' : '';
|
||||
this.topbar.style.display = '';
|
||||
if(appPeersManager.isAnyGroup(peerID)) this.chatInner.classList.add('is-chat');
|
||||
else this.chatInner.classList.remove('is-chat');
|
||||
window.requestAnimationFrame(() => {
|
||||
//this.chatInner.style.visibility = 'hidden';
|
||||
|
||||
@ -1010,8 +906,8 @@ export class AppImManager {
|
||||
//this.chatInput.style.display = appPeersManager.isChannel(peerID) && !appPeersManager.isMegagroup(peerID) ? 'none' : '';
|
||||
//appSidebarRight.toggleSidebar(true);
|
||||
|
||||
if(appPeersManager.isAnyGroup(peerID)) this.chatInner.classList.add('is-chat');
|
||||
else this.chatInner.classList.remove('is-chat');
|
||||
//if(appPeersManager.isAnyGroup(peerID)) this.chatInner.classList.add('is-chat');
|
||||
//else this.chatInner.classList.remove('is-chat');
|
||||
|
||||
if(!fromClick) {
|
||||
if(!samePeer && appDialogsManager.lastActiveListElement) {
|
||||
@ -1141,12 +1037,13 @@ export class AppImManager {
|
||||
lottieLoader.checkAnimations();
|
||||
}
|
||||
|
||||
public renderMessagesByIDs(msgIDs: number[]) {
|
||||
public renderNewMessagesByIDs(msgIDs: number[]) {
|
||||
if(!this.bubbles[this.firstTopMsgID] && Object.keys(this.bubbles).length) { // seems search active
|
||||
//////this.log('seems search is active, skipping render:', msgIDs);
|
||||
return;
|
||||
}
|
||||
|
||||
let scrolledDown = this.scrolledDown;
|
||||
msgIDs.forEach((msgID: number) => {
|
||||
let message = appMessagesManager.getMessage(msgID);
|
||||
|
||||
@ -1155,10 +1052,11 @@ export class AppImManager {
|
||||
//this.unreaded.push(msgID);
|
||||
this.renderMessage(message);
|
||||
});
|
||||
if(scrolledDown) this.scrollable.scrollTop = this.scrollable.scrollHeight;
|
||||
}
|
||||
|
||||
// reverse means top, will save scrollPosition if bubble will be higher
|
||||
public renderMessage(message: any, reverse = false, multipleRender?: boolean, bubble: HTMLDivElement = null, updatePosition = true) {
|
||||
// reverse means top
|
||||
public renderMessage(message: any, reverse = false, multipleRender = false, bubble: HTMLDivElement = null, updatePosition = true) {
|
||||
/////this.log('message to render:', message);
|
||||
if(message.deleted) return;
|
||||
|
||||
@ -1169,11 +1067,7 @@ export class AppImManager {
|
||||
messageDiv.classList.add('message');
|
||||
|
||||
//messageDiv.innerText = message.message;
|
||||
|
||||
if(!multipleRender) {
|
||||
this.scrollPosition.prepareFor(reverse ? 'up' : 'down'); // лагает из-за этого
|
||||
}
|
||||
|
||||
|
||||
let bubbleContainer: HTMLDivElement;
|
||||
|
||||
// bubble
|
||||
@ -1406,8 +1300,7 @@ export class AppImManager {
|
||||
|
||||
if(webpage.photo && !doc) {
|
||||
bubble.classList.add('photo');
|
||||
//appPhotosManager.savePhoto(webpage.photo); // hot-fix because no webpage manager
|
||||
|
||||
|
||||
wrapPhoto.call(this, webpage.photo.id, message, preview, 380, 300, false);
|
||||
}
|
||||
|
||||
@ -1440,10 +1333,7 @@ export class AppImManager {
|
||||
|
||||
case 'messageMediaDocument': {
|
||||
let doc = message.media.document;
|
||||
/* if(document.size > 1e6) { // 1mb
|
||||
break;
|
||||
} */
|
||||
|
||||
|
||||
this.log('messageMediaDocument', doc, bubble);
|
||||
|
||||
if(doc.sticker && doc.size <= 1e6) {
|
||||
@ -1468,7 +1358,7 @@ export class AppImManager {
|
||||
}, this.lazyLoadQueue, 'chat', false, !!message.pending || !multipleRender);
|
||||
|
||||
break;
|
||||
} else if(doc.mime_type == 'video/mp4' && doc.size <= 20e6) {
|
||||
} else if((doc.type == 'video' || doc.type == 'gif') && doc.size <= 20e6) {
|
||||
this.log('never get free 2', doc);
|
||||
|
||||
if(doc.type == 'round') {
|
||||
@ -1614,16 +1504,13 @@ export class AppImManager {
|
||||
} else {
|
||||
this.scrollable.appendByBatch(bubble);
|
||||
} */
|
||||
/* if(reverse) {
|
||||
this.scrollable.prepend(bubble);
|
||||
|
||||
if(!this.scrollable.scrollTop) {
|
||||
let height = bubble.scrollHeight;
|
||||
this.scrollable.scrollTop += height;
|
||||
if(!multipleRender) {
|
||||
if(reverse) {
|
||||
this.scrollable.prepend(bubble);
|
||||
} else {
|
||||
this.scrollable.append(bubble);
|
||||
}
|
||||
} else {
|
||||
this.scrollable.append(bubble);
|
||||
} */
|
||||
}
|
||||
//});
|
||||
|
||||
let justDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
||||
@ -1681,12 +1568,6 @@ export class AppImManager {
|
||||
/* if(bubble.classList.contains('webpage')) {
|
||||
this.log('night running', bubble, bubble.scrollHeight);
|
||||
} */
|
||||
|
||||
//return //this.scrollPosition.restore();
|
||||
|
||||
if(!multipleRender) {
|
||||
this.scrollPosition.restore(); // лагает из-за этого
|
||||
}
|
||||
|
||||
return bubble;
|
||||
}
|
||||
@ -1714,10 +1595,6 @@ export class AppImManager {
|
||||
//console.time('appImManager render history');
|
||||
|
||||
this.log('getHistory method', method);
|
||||
|
||||
if(!isBackLimit) {
|
||||
this.scrollPosition.prepareFor(reverse ? 'up' : 'down');
|
||||
}
|
||||
|
||||
let firstLoad = !!this.setPeerPromise && false;
|
||||
|
||||
@ -1731,7 +1608,7 @@ export class AppImManager {
|
||||
bubbles.push(bubble);
|
||||
}); */
|
||||
|
||||
//let innerHeight = this.scrollable.innerHeight;
|
||||
let leftHeightToScroll = this.scrollable.innerHeight;
|
||||
|
||||
//console.timeEnd('appImManager: pre render start');
|
||||
|
||||
@ -1789,7 +1666,12 @@ export class AppImManager {
|
||||
//let height = Math.ceil(bubble.getBoundingClientRect().height);
|
||||
this.scrollable.scrollTop += height;
|
||||
//innerHeight -= height;
|
||||
} else {
|
||||
}
|
||||
/* if(leftHeightToScroll >= 0) {
|
||||
let height = bubble.scrollHeight;
|
||||
leftHeightToScroll -= height;
|
||||
this.scrollable.scrollTop += height;
|
||||
} */ else {
|
||||
renderedFirstScreen = true;
|
||||
resolve();
|
||||
resolved = true;
|
||||
@ -1906,7 +1788,8 @@ export class AppImManager {
|
||||
return (reverse ? this.getHistoryTopPromise = promise : this.getHistoryBottomPromise = promise);
|
||||
} else {
|
||||
let promise = this.performHistoryResult(result.history || [], reverse, isBackLimit, additionMsgID, true);
|
||||
return (reverse ? this.getHistoryTopPromise = promise : this.getHistoryBottomPromise = promise);
|
||||
//return (reverse ? this.getHistoryTopPromise = promise : this.getHistoryBottomPromise = promise);
|
||||
return promise;
|
||||
//return this.performHistoryResult(result.history || [], reverse, isBackLimit, additionMsgID, true);
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import ProgressivePreloader from "../../components/preloader";
|
||||
import { findUpClassName, $rootScope, generatePathData } from "../utils";
|
||||
import appDocsManager from "./appDocsManager";
|
||||
import { wrapPlayer } from "../ckin";
|
||||
import { renderImageFromUrl } from "../../components/misc";
|
||||
|
||||
export class AppMediaViewer {
|
||||
private overlaysDiv = document.querySelector('.overlays') as HTMLDivElement;
|
||||
@ -514,9 +515,8 @@ export class AppMediaViewer {
|
||||
|
||||
public updateMediaSource(target: HTMLElement, url: string, tagName: 'source' | 'image') {
|
||||
//if(target instanceof SVGSVGElement) {
|
||||
let el = target.querySelector(tagName);
|
||||
if(tagName == 'source') (el as HTMLSourceElement).src = url;
|
||||
else el.setAttributeNS(null, 'href', url);
|
||||
let el = target.querySelector(tagName) as HTMLElement;
|
||||
renderImageFromUrl(el, url);
|
||||
/* } else {
|
||||
|
||||
} */
|
||||
@ -644,7 +644,7 @@ export class AppMediaViewer {
|
||||
return;
|
||||
}
|
||||
|
||||
let url = URL.createObjectURL(blob);
|
||||
let url = media.url;
|
||||
if(target instanceof SVGSVGElement) {
|
||||
this.updateMediaSource(mover, url, 'source');
|
||||
this.updateMediaSource(target, url, 'source');
|
||||
@ -655,8 +655,7 @@ export class AppMediaViewer {
|
||||
}
|
||||
|
||||
source = document.createElement('source');
|
||||
//source.src = doc.url;
|
||||
source.src = url;
|
||||
renderImageFromUrl(source, url);
|
||||
source.type = media.mime_type;
|
||||
|
||||
mover.prepend(video);
|
||||
@ -703,13 +702,14 @@ export class AppMediaViewer {
|
||||
|
||||
///////this.log('indochina', blob);
|
||||
|
||||
let url = URL.createObjectURL(blob);
|
||||
let url = media.url;
|
||||
if(target instanceof SVGSVGElement) {
|
||||
this.updateMediaSource(target, url, 'image');
|
||||
this.updateMediaSource(mover, url, 'image');
|
||||
} else {
|
||||
let image = mover.firstElementChild as HTMLImageElement || new Image();
|
||||
image.src = url;
|
||||
//image.src = url;
|
||||
renderImageFromUrl(image, url);
|
||||
mover.prepend(image);
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ import appUsersManager from "./appUsersManager";
|
||||
import { copy, calcImageInBox } from "../utils";
|
||||
import fileManager from '../filemanager';
|
||||
import { bytesFromHex } from "../bin_utils";
|
||||
import { MTPhotoSize } from "../../components/wrappers";
|
||||
import { MTPhotoSize, MTDocument } from "../../components/wrappers";
|
||||
import apiFileManager from "../mtproto/apiFileManager";
|
||||
import apiManager from "../mtproto/apiManager";
|
||||
|
||||
@ -207,7 +207,7 @@ export class AppPhotosManager {
|
||||
//console.log('setAttachmentSize', photo, photo.sizes[0].bytes, div);
|
||||
|
||||
let sizes = photo.sizes || photo.thumbs;
|
||||
if((!photo.downloaded || isSticker) && sizes && sizes[0].bytes) {
|
||||
if((!photo.downloaded || (isSticker && photo.animated)) && sizes && sizes[0].bytes) {
|
||||
this.setAttachmentPreview(sizes[0].bytes, element, isSticker);
|
||||
}
|
||||
|
||||
@ -225,6 +225,8 @@ export class AppPhotosManager {
|
||||
if(element instanceof SVGSVGElement) {
|
||||
element.setAttributeNS(null, 'width', '' + w);
|
||||
element.setAttributeNS(null, 'height', '' + h);
|
||||
|
||||
console.log('set dimensions to svg element:', element, w, h);
|
||||
|
||||
if(element.firstElementChild) {
|
||||
let imageSvg = element.firstElementChild as SVGImageElement;
|
||||
|
@ -129,7 +129,7 @@ class appStickersManager {
|
||||
}); */
|
||||
}
|
||||
|
||||
public async getStickerSetThumb(stickerSet: MTStickerSet) {
|
||||
public getStickerSetThumb(stickerSet: MTStickerSet) {
|
||||
let thumb = stickerSet.thumb;
|
||||
let dcID = stickerSet.thumb_dc_id;
|
||||
|
||||
@ -144,7 +144,7 @@ class appStickersManager {
|
||||
local_id: thumb.location.local_id
|
||||
}, {dcID: dcID});
|
||||
|
||||
return await promise;
|
||||
return promise;
|
||||
}
|
||||
|
||||
public async cleanup() { // if logout
|
||||
|
@ -5,7 +5,7 @@ class AppWebpManager {
|
||||
public webpMachine: any = null;
|
||||
public loaded: Promise<void>;
|
||||
public busyPromise: Promise<string>;
|
||||
public queue: {bytes: Uint8Array, img: HTMLImageElement, callback: () => void}[] = [];
|
||||
public queue: {bytes: Uint8Array, img: HTMLImageElement, callback: (url: string) => void}[] = [];
|
||||
//public worker: any;
|
||||
public webpSupport: Promise<boolean> = null;
|
||||
|
||||
@ -65,12 +65,13 @@ class AppWebpManager {
|
||||
await this.loaded;
|
||||
|
||||
this.busyPromise = this.convert(bytes);
|
||||
let url = await this.busyPromise;
|
||||
let imgTemp = new Image();
|
||||
imgTemp.src = await this.busyPromise;
|
||||
imgTemp.src = url;
|
||||
imgTemp.onload = () => {
|
||||
img.src = imgTemp.src;
|
||||
};
|
||||
callback();
|
||||
callback(url);
|
||||
|
||||
this.busyPromise = null;
|
||||
|
||||
@ -98,11 +99,12 @@ class AppWebpManager {
|
||||
|
||||
//if(await this.webpMachine.webpSupport) {
|
||||
if(await this.webpSupport) {
|
||||
img.src = URL.createObjectURL(blob);
|
||||
return;
|
||||
let url = URL.createObjectURL(blob);
|
||||
img.src = url;
|
||||
return url;
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.addEventListener('loadend', (e) => {
|
||||
// @ts-ignore
|
||||
|
@ -8,11 +8,6 @@ if(window.location.href.indexOf('localhost') === -1) {
|
||||
}
|
||||
|
||||
class FileManager {
|
||||
public isSafari = 'safari' in window;
|
||||
public safariVersion = parseFloat(this.isSafari && (navigator.userAgent.match(/Version\/(\d+\.\d+).* Safari/) || [])[1]);
|
||||
public safariWithDownload = this.isSafari && this.safariVersion >= 11.0;
|
||||
public buggyUnknownBlob = this.isSafari && !this.safariWithDownload;
|
||||
|
||||
public blobSupported = true;
|
||||
|
||||
constructor() {
|
||||
@ -93,12 +88,12 @@ class FileManager {
|
||||
let fileReader = new FileReader();
|
||||
fileReader.onload = function(event) {
|
||||
let arrayBuffer = event.target.result as ArrayBuffer;
|
||||
|
||||
|
||||
let arr = new Uint8Array(arrayBuffer);
|
||||
|
||||
|
||||
fileWriter.write(arr).then(resolve, reject);
|
||||
};
|
||||
|
||||
|
||||
fileReader.readAsArrayBuffer(bytes);
|
||||
});
|
||||
} else {
|
||||
@ -117,7 +112,7 @@ class FileManager {
|
||||
let writer = fileStream.getWriter();
|
||||
return writer;
|
||||
}
|
||||
|
||||
|
||||
public getFakeFileWriter(mimeType: string, saveFileCallback: any) {
|
||||
var blobParts: Array<Blob> = [];
|
||||
var fakeFileWriter = {
|
||||
@ -143,76 +138,16 @@ class FileManager {
|
||||
|
||||
return fakeFileWriter;
|
||||
}
|
||||
|
||||
public getUrl(fileData: any, mimeType: string) {
|
||||
|
||||
public getFileCorrectUrl(fileData: Blob | number[], mimeType: string): string {
|
||||
var safeMimeType = blobSafeMimeType(mimeType);
|
||||
// console.log(dT(), 'get url', fileData, mimeType, fileData.toURL !== undefined, fileData instanceof Blob)
|
||||
if(fileData.toURL !== undefined) {
|
||||
return fileData.toURL(safeMimeType);
|
||||
}
|
||||
if(fileData instanceof Blob) {
|
||||
return URL.createObjectURL(fileData);
|
||||
}
|
||||
return 'data:' + safeMimeType + ';base64,' + bytesToBase64(fileData);
|
||||
}
|
||||
|
||||
public getByteArray(fileData: any) {
|
||||
if(fileData instanceof Blob) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
var reader = new FileReader();
|
||||
reader.onloadend = (e) => {
|
||||
// @ts-ignore
|
||||
resolve(new Uint8Array(e.target.result));
|
||||
};
|
||||
reader.onerror = (e) => {
|
||||
reject(e);
|
||||
};
|
||||
reader.readAsArrayBuffer(fileData);
|
||||
} catch(e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
} else if(fileData.file) {
|
||||
return new Promise((resolve, reject) => {
|
||||
fileData.file((blob: any) => {
|
||||
this.getByteArray(blob).then(resolve, reject);
|
||||
}, reject);
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.resolve(fileData);
|
||||
//return $q.when(fileData);
|
||||
}
|
||||
|
||||
public getDataUrl(blob: any) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
var reader = new FileReader();
|
||||
reader.onloadend = () => {
|
||||
resolve(reader.result);
|
||||
};
|
||||
reader.readAsDataURL(blob);
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public getFileCorrectUrl(blob: any, mimeType: string) {
|
||||
if(this.buggyUnknownBlob && blob instanceof Blob) {
|
||||
// @ts-ignore
|
||||
mimeType = blob.type || blob.mimeType || mimeType || ''
|
||||
if(!mimeType.match(/image\/(jpeg|gif|png|bmp)|video\/quicktime/)) {
|
||||
return this.getDataUrl(blob);
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.resolve(this.getUrl(blob, mimeType));
|
||||
}
|
||||
|
||||
// downloadFile
|
||||
public download(blob: any, mimeType: string, fileName: string) {
|
||||
public download(blob: Blob, mimeType: string, fileName: string) {
|
||||
if(window.navigator && navigator.msSaveBlob !== undefined) {
|
||||
window.navigator.msSaveBlob(blob, fileName);
|
||||
return false;
|
||||
@ -244,57 +179,37 @@ class FileManager {
|
||||
return;
|
||||
}
|
||||
|
||||
var popup: Window;
|
||||
if(this.isSafari && !this.safariWithDownload) {
|
||||
popup = window.open();
|
||||
let url = this.getFileCorrectUrl(blob, mimeType);
|
||||
var anchor = document.createElementNS('http://www.w3.org/1999/xhtml', 'a') as HTMLAnchorElement;
|
||||
anchor.href = url as string;
|
||||
anchor.download = fileName;
|
||||
if(anchor.dataset) {
|
||||
anchor.dataset.downloadurl = ['video/quicktime', fileName, url].join(':');
|
||||
}
|
||||
|
||||
this.getFileCorrectUrl(blob, mimeType).then((url) => {
|
||||
if(popup) {
|
||||
try {
|
||||
// @ts-ignore
|
||||
popup.location.href = url;
|
||||
return;
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
var anchor = document.createElementNS('http://www.w3.org/1999/xhtml', 'a') as HTMLAnchorElement;
|
||||
anchor.href = url as string;
|
||||
if(!this.safariWithDownload) {
|
||||
anchor.target = '_blank';
|
||||
}
|
||||
anchor.download = fileName;
|
||||
if(anchor.dataset) {
|
||||
anchor.dataset.downloadurl = ['video/quicktime', fileName, url].join(':');
|
||||
}
|
||||
|
||||
anchor.style.position = 'absolute';
|
||||
anchor.style.top = '1px';
|
||||
anchor.style.left = '1px';
|
||||
|
||||
document.body.append(anchor);
|
||||
|
||||
anchor.style.position = 'absolute';
|
||||
anchor.style.top = '1px';
|
||||
anchor.style.left = '1px';
|
||||
|
||||
document.body.append(anchor);
|
||||
|
||||
try {
|
||||
var clickEvent = document.createEvent('MouseEvents');
|
||||
clickEvent.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
|
||||
anchor.dispatchEvent(clickEvent);
|
||||
} catch (e) {
|
||||
console.error('Download click error', e);
|
||||
try {
|
||||
var clickEvent = document.createEvent('MouseEvents');
|
||||
clickEvent.initMouseEvent(
|
||||
'click', true, false, window, 0, 0, 0, 0, 0
|
||||
, false, false, false, false, 0, null
|
||||
)
|
||||
anchor.dispatchEvent(clickEvent);
|
||||
} catch (e) {
|
||||
console.error('Download click error', e);
|
||||
try {
|
||||
anchor.click();
|
||||
} catch (e) {
|
||||
window.open(url as string, '_blank');
|
||||
}
|
||||
}
|
||||
setTimeout(() => {
|
||||
anchor.remove();
|
||||
}, 100);
|
||||
})
|
||||
anchor.click();
|
||||
} catch (e) {
|
||||
window.open(url as string, '_blank');
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
anchor.remove();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
export default new FileManager();
|
||||
|
||||
}
|
||||
|
||||
export default new FileManager();
|
||||
|
@ -121,7 +121,10 @@
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
display: flex; // for end
|
||||
//display: flex; // for end
|
||||
//flex-direction: unset;
|
||||
display: block;
|
||||
|
||||
|
||||
/* display: flex;
|
||||
flex-direction: column;
|
||||
@ -156,9 +159,9 @@
|
||||
//padding-top: 9px;
|
||||
margin: 0 auto;
|
||||
box-sizing: border-box;
|
||||
/* min-height: 100%; */
|
||||
min-height: 100%;
|
||||
justify-content: flex-end;
|
||||
flex: 1;
|
||||
//flex: 1;
|
||||
|
||||
&.is-chat {
|
||||
.is-in .bubble__container {
|
||||
|
Loading…
x
Reference in New Issue
Block a user