diff --git a/src/components/misc.ts b/src/components/misc.ts index de32d463..800e5aaf 100644 --- a/src/components/misc.ts +++ b/src/components/misc.ts @@ -92,14 +92,26 @@ export function ripple(elem: HTMLElement, callback: (id: number) => Promise { - 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) { diff --git a/src/components/scrollable.ts b/src/components/scrollable.ts index 48e935c5..d84e9061 100644 --- a/src/components/scrollable.ts +++ b/src/components/scrollable.ts @@ -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; diff --git a/src/components/wrappers.ts b/src/components/wrappers.ts index 8f859a7c..e90c1752 100644 --- a/src/components/wrappers.ts +++ b/src/components/wrappers.ts @@ -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); } diff --git a/src/lib/appManagers/appDialogsManager.ts b/src/lib/appManagers/appDialogsManager.ts index b04c696b..cab86a2b 100644 --- a/src/lib/appManagers/appDialogsManager.ts +++ b/src/lib/appManagers/appDialogsManager.ts @@ -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 = ''; diff --git a/src/lib/appManagers/appDocsManager.ts b/src/lib/appManagers/appDocsManager.ts index 5016155e..17c916ec 100644 --- a/src/lib/appManagers/appDocsManager.ts +++ b/src/lib/appManagers/appDocsManager.ts @@ -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; diff --git a/src/lib/appManagers/appImManager.ts b/src/lib/appManagers/appImManager.ts index d7898ff7..4018c687 100644 --- a/src/lib/appManagers/appImManager.ts +++ b/src/lib/appManagers/appImManager.ts @@ -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; private preloader: ProgressivePreloader = null; @@ -171,6 +100,8 @@ export class AppImManager { private setPeerPromise: Promise = 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); } } diff --git a/src/lib/appManagers/appMediaViewer.ts b/src/lib/appManagers/appMediaViewer.ts index dda61041..b2715d08 100644 --- a/src/lib/appManagers/appMediaViewer.ts +++ b/src/lib/appManagers/appMediaViewer.ts @@ -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); } diff --git a/src/lib/appManagers/appPhotosManager.ts b/src/lib/appManagers/appPhotosManager.ts index 286431d1..f21b168c 100644 --- a/src/lib/appManagers/appPhotosManager.ts +++ b/src/lib/appManagers/appPhotosManager.ts @@ -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; diff --git a/src/lib/appManagers/appStickersManager.ts b/src/lib/appManagers/appStickersManager.ts index f4559c34..57114285 100644 --- a/src/lib/appManagers/appStickersManager.ts +++ b/src/lib/appManagers/appStickersManager.ts @@ -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 diff --git a/src/lib/appManagers/appWebpManager.ts b/src/lib/appManagers/appWebpManager.ts index 119195ae..b9c3c587 100644 --- a/src/lib/appManagers/appWebpManager.ts +++ b/src/lib/appManagers/appWebpManager.ts @@ -5,7 +5,7 @@ class AppWebpManager { public webpMachine: any = null; public loaded: Promise; public busyPromise: Promise; - public queue: {bytes: Uint8Array, img: HTMLImageElement, callback: () => void}[] = []; + public queue: {bytes: Uint8Array, img: HTMLImageElement, callback: (url: string) => void}[] = []; //public worker: any; public webpSupport: Promise = 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((resolve, reject) => { const reader = new FileReader(); reader.addEventListener('loadend', (e) => { // @ts-ignore diff --git a/src/lib/filemanager.ts b/src/lib/filemanager.ts index 4d5de899..e8a28d23 100644 --- a/src/lib/filemanager.ts +++ b/src/lib/filemanager.ts @@ -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 = []; 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(); - \ No newline at end of file +} + +export default new FileManager(); diff --git a/src/scss/partials/_chat.scss b/src/scss/partials/_chat.scss index 0cdb7c9f..b0582e8e 100644 --- a/src/scss/partials/_chat.scss +++ b/src/scss/partials/_chat.scss @@ -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 {