From 2a5ad412f199f93395664491551d5bc96f8503a0 Mon Sep 17 00:00:00 2001 From: morethanwords Date: Sun, 26 Apr 2020 04:45:07 +0300 Subject: [PATCH] GIF sending & fix blink after message send --- src/components/chatInput.ts | 56 +++--- src/components/emoticonsDropdown.ts | 37 ++-- src/components/wrappers.ts | 16 +- src/lib/appManagers/appDocsManager.ts | 22 ++- src/lib/appManagers/appImManager.ts | 35 ++-- src/lib/appManagers/appMediaViewer.ts | 2 +- src/lib/appManagers/appMessagesManager.ts | 228 ++++------------------ src/lib/appManagers/appPhotosManager.ts | 129 +++++------- src/lib/appManagers/appSidebarRight.ts | 9 +- src/lib/appManagers/appStickersManager.ts | 2 +- src/lib/appManagers/appWebPagesManager.ts | 16 +- src/pages/pageIm.ts | 2 + src/scss/partials/_chat.scss | 4 + src/scss/partials/_emojiDropdown.scss | 2 +- tsconfig.json | 1 + 15 files changed, 203 insertions(+), 358 deletions(-) diff --git a/src/components/chatInput.ts b/src/components/chatInput.ts index 4a695ff4..71a2cab4 100644 --- a/src/components/chatInput.ts +++ b/src/components/chatInput.ts @@ -189,6 +189,7 @@ export class ChatInput { console.log('selected file:', file, typeof(file)); willAttachFile = file; + willAttachObjectURL = ''; this.fileInput.value = ''; @@ -207,7 +208,7 @@ export class ChatInput { switch(willAttach) { case 'media': { let img = new Image(); - img.src = URL.createObjectURL(file); + img.src = willAttachObjectURL = URL.createObjectURL(file); img.onload = () => { willAttachWidth = img.naturalWidth; willAttachHeight = img.naturalHeight; @@ -248,6 +249,7 @@ export class ChatInput { let willAttach = ''; let willAttachFile: File = null; + let willAttachObjectURL = ''; let willAttachWidth = 0, willAttachHeight = 0; this.fileInput.addEventListener('change', (e) => { var file = (e.target as HTMLInputElement & EventTarget).files[0]; @@ -302,14 +304,11 @@ export class ChatInput { isMedia: true, caption, width: willAttachWidth, - height: willAttachHeight + height: willAttachHeight, + objectURL: willAttachObjectURL }); - appImManager.scroll.scrollTop = appImManager.scroll.scrollHeight; - - let dialog = appMessagesManager.getDialogByPeerID(appImManager.peerID)[0]; - if(dialog && dialog.top_message) { - appMessagesManager.readHistory(appImManager.peerID, dialog.top_message); // lol - } + + this.onMessageSent(); }); this.btnSend.addEventListener('click', () => { @@ -384,6 +383,29 @@ export class ChatInput { }, ''); }; + public onMessageSent(scrollDown = true, clearInput = true) { + if(scrollDown) { + appImManager.scroll.scrollTop = appImManager.scroll.scrollHeight; + } + + let dialog = appMessagesManager.getDialogByPeerID(appImManager.peerID)[0]; + if(dialog && dialog.top_message) { + appMessagesManager.readHistory(appImManager.peerID, dialog.top_message); // lol + } + + if(clearInput) { + this.lastUrl = ''; + this.editMsgID = 0; + this.replyToMsgID = 0; + this.noWebPage = false; + this.replyElements.container.classList.remove('active'); + this.willSendWebPage = null; + this.messageInput.innerText = ''; + this.btnSend.classList.remove('tgico-send'); + this.btnSend.classList.add('tgico-microphone2'); + } + } + public sendMessage() { //let str = this.serializeNodes(Array.from(this.messageInput.childNodes)); let str = getRichValue(this.messageInput); @@ -391,7 +413,6 @@ export class ChatInput { //console.log('childnode str after:', str/* , getRichValue(this.messageInput) */); //return; - this.lastUrl = ''; if(this.editMsgID) { appMessagesManager.editMessage(this.editMsgID, str, { @@ -403,24 +424,9 @@ export class ChatInput { noWebPage: this.noWebPage, webPage: this.willSendWebPage }); - - appImManager.scroll.scrollTop = appImManager.scroll.scrollHeight; } - let dialog = appMessagesManager.getDialogByPeerID(appImManager.peerID)[0]; - if(dialog && dialog.top_message) { - appMessagesManager.readHistory(appImManager.peerID, dialog.top_message); // lol - } - - this.editMsgID = 0; - this.replyToMsgID = 0; - this.noWebPage = false; - this.replyElements.container.classList.remove('active'); - this.willSendWebPage = null; - this.messageInput.innerText = ''; - - this.btnSend.classList.remove('tgico-send'); - this.btnSend.classList.add('tgico-microphone2'); + this.onMessageSent(!this.editMsgID); }; public setTopInfo(title: string, subtitle: string, input?: string, media?: any) { diff --git a/src/components/emoticonsDropdown.ts b/src/components/emoticonsDropdown.ts index 50d8d827..09053a31 100644 --- a/src/components/emoticonsDropdown.ts +++ b/src/components/emoticonsDropdown.ts @@ -206,6 +206,22 @@ const initEmoticonsDropdown = (pageEl: HTMLDivElement, emoticonsMenuOnClick(menu, heights, emojiScroll); } + let onMediaClick = (e: MouseEvent) => { + let target = e.target as HTMLDivElement; + target = findUpTag(target, 'DIV'); + + let fileID = target.dataset.docID; + let document = appDocsManager.getDoc(fileID); + if(document._ != 'documentEmpty') { + appMessagesManager.sendFile(appImManager.peerID, document, {isMedia: true}); + appImManager.chatInputC.onMessageSent(true, false); + dropdown.classList.remove('active'); + toggleEl.classList.remove('active'); + } else { + console.warn('got no doc by id:', fileID); + } + }; + let stickersInit = () => { let contentStickersDiv = document.getElementById('content-stickers') as HTMLDivElement; //let stickersDiv = contentStickersDiv.querySelector('.os-content') as HTMLDivElement; @@ -236,22 +252,7 @@ const initEmoticonsDropdown = (pageEl: HTMLDivElement, } }); - stickersDiv.addEventListener('click', (e) => { - let target = e.target as HTMLDivElement; - target = findUpTag(target, 'DIV'); - - let fileID = target.getAttribute('file-id'); - let document = appStickersManager.getSticker(fileID); - - if(document) { - appMessagesManager.sendFile(appImManager.peerID, document, {isMedia: true}); - appImManager.scroll.scrollTop = appImManager.scroll.scrollHeight; - dropdown.classList.remove('active'); - toggleEl.classList.remove('active'); - } else { - console.warn('got no sticker by id:', fileID); - } - }); + stickersDiv.addEventListener('click', onMediaClick); let heights: number[] = []; @@ -403,6 +404,8 @@ const initEmoticonsDropdown = (pageEl: HTMLDivElement, let contentDiv = document.getElementById('content-gifs') as HTMLDivElement; let masonry = contentDiv.firstElementChild as HTMLDivElement; + masonry.addEventListener('click', onMediaClick); + let scroll = new Scrollable(contentDiv, 'y', 500, 'GIFS', null); scroll.container.addEventListener('scroll', (e) => { @@ -459,7 +462,7 @@ const initEmoticonsDropdown = (pageEl: HTMLDivElement, let div = document.createElement('div'); div.style.width = w + 'px'; //div.style.height = h + 'px'; - div.dataset.documentID = gif.id; + div.dataset.docID = gif.id; masonry.append(div); diff --git a/src/components/wrappers.ts b/src/components/wrappers.ts index 7183119f..258df723 100644 --- a/src/components/wrappers.ts +++ b/src/components/wrappers.ts @@ -596,7 +596,7 @@ function wrapMediaWithTail(photo: any, message: {mid: number, message: string}, return image; } -export async function wrapPhoto(photoID: string, message: any, container: HTMLDivElement, boxWidth = 380, boxHeight = 380, withTail = true, isOut = false, lazyLoadQueue: LazyLoadQueue, middleware: () => boolean) { +export function wrapPhoto(photoID: string, message: any, container: HTMLDivElement, boxWidth = 380, boxHeight = 380, withTail = true, isOut = false, lazyLoadQueue: LazyLoadQueue, middleware: () => boolean) { let photo = appPhotosManager.getPhoto(photoID); let size: MTPhotoSize; @@ -615,6 +615,12 @@ export async function wrapPhoto(photoID: string, message: any, container: HTMLDi console.log('wrapPhoto downloaded:', photo, photo.downloaded, container); + // так нельзя делать, потому что может быть загружен неправильный размер картинки + /* if(photo.downloaded && photo.url) { + renderImageFromUrl(image, photo.url); + return; + } */ + let preloader: ProgressivePreloader; if(!photo.downloaded) preloader = new ProgressivePreloader(container, false); let load = () => { @@ -625,7 +631,7 @@ export async function wrapPhoto(photoID: string, message: any, container: HTMLDi } return promise.then(() => { - if(!middleware()) return; + if(middleware && !middleware()) return; renderImageFromUrl(image, photo.url); }); @@ -680,7 +686,7 @@ export function wrapSticker(doc: MTDocument, div: HTMLDivElement, middleware?: ( div.append(img); - div.setAttribute('file-id', doc.id); + div.dataset.docID = doc.id; appStickersManager.saveSticker(doc); }); @@ -778,7 +784,7 @@ export function wrapSticker(doc: MTDocument, div: HTMLDivElement, middleware?: ( div.append(img); } - div.setAttribute('file-id', doc.id); + div.dataset.docID = doc.id; appStickersManager.saveSticker(doc); }); @@ -827,7 +833,7 @@ export function wrapReply(title: string, subtitle: string, media?: any) { appPhotosManager.preloadPhoto(photo, appPhotosManager.choosePhotoSize(photo, 32, 32)) .then(blob => { - renderImageFromUrl(replyMedia, photo.url || URL.createObjectURL(blob)); + renderImageFromUrl(replyMedia, photo._ == 'photo' ? photo.url : URL.createObjectURL(blob)); }); replyContent.append(replyMedia); diff --git a/src/lib/appManagers/appDocsManager.ts b/src/lib/appManagers/appDocsManager.ts index 17c916ec..b1c8a73c 100644 --- a/src/lib/appManagers/appDocsManager.ts +++ b/src/lib/appManagers/appDocsManager.ts @@ -5,19 +5,31 @@ import { CancellablePromise } from '../polyfill'; import { MTDocument } from '../../components/wrappers'; class AppDocsManager { - private docs: any = {}; + private docs: {[docID: string]: MTDocument} = {}; public saveDoc(apiDoc: MTDocument/* any */, context?: any) { console.log('saveDoc', apiDoc, this.docs[apiDoc.id]); - if(this.docs[apiDoc.id]) return this.docs[apiDoc.id]; + if(this.docs[apiDoc.id]) { + let d = this.docs[apiDoc.id]; - this.docs[apiDoc.id] = apiDoc; + if(apiDoc.thumbs) { + if(!d.thumbs) d.thumbs = apiDoc.thumbs; + else if(apiDoc.thumbs[0].bytes && !d.thumbs[0].bytes) { + d.thumbs.unshift(apiDoc.thumbs[0]); + } + } + + return context ? Object.assign(d, context) : d; + } - /* if(context) { + if(context) { Object.assign(apiDoc, context); - } */ + } + + this.docs[apiDoc.id] = apiDoc; if(apiDoc.thumb && apiDoc.thumb._ == 'photoCachedSize') { + console.warn('this will happen!!!'); apiFileManager.saveSmallFile(apiDoc.thumb.location, apiDoc.thumb.bytes); // Memory diff --git a/src/lib/appManagers/appImManager.ts b/src/lib/appManagers/appImManager.ts index 09c8acc7..2e766a3c 100644 --- a/src/lib/appManagers/appImManager.ts +++ b/src/lib/appManagers/appImManager.ts @@ -44,7 +44,7 @@ export class AppImManager { private getHistoryTopPromise: Promise; private getHistoryBottomPromise: Promise; - private chatInputC: ChatInput = null; + public chatInputC: ChatInput = null; public myID = 0; public peerID = 0; @@ -158,7 +158,12 @@ export class AppImManager { let message = appMessagesManager.getMessage(mid); //this.log('history_update', this.bubbles[mid], mid, message); - this.renderMessage(message, false, false, bubble); + let dateMessage = this.getDateContainerByMessage(message, false); + dateMessage.container.append(bubble); + + this.bubbleGroups.addBubble(bubble, message, false); + + //this.renderMessage(message, false, false, bubble); } }); @@ -191,9 +196,21 @@ export class AppImManager { this.bubbles[mid] = bubble; /////this.log('message_sent', bubble); + + // set cached url to media + let message = appMessagesManager.getMessage(mid); + if(message.media && message.media.photo) { + let photo = appPhotosManager.getPhoto(tempID); + if(photo) { + let newPhoto = message.media.photo; + newPhoto.downloaded = photo.downloaded; + newPhoto.url = photo.url; + } + } bubble.classList.remove('is-sending'); bubble.classList.add('is-sent'); + bubble.dataset.mid = mid; this.bubbleGroups.removeBubble(bubble, tempID); @@ -1163,7 +1180,7 @@ export class AppImManager { // reverse means top public renderMessage(message: any, reverse = false, multipleRender = false, bubble: HTMLDivElement = null, updatePosition = true) { - /////this.log('message to render:', message); + this.log('message to render:', message); if(message.deleted) return; let peerID = this.peerID; @@ -1323,15 +1340,9 @@ export class AppImManager { switch(pending.type) { case 'photo': { if(pending.size < 5e6) { - let img = new Image(); - img.src = URL.createObjectURL(pending.file); - - let {w, h} = calcImageInBox(pending.w, pending.h, 380, 380); - - attachmentDiv.style.width = w + 'px'; - attachmentDiv.style.height = h + 'px'; - - attachmentDiv.append(img); + this.log('will wrap pending photo:', pending, message, appPhotosManager.getPhoto(message.id)); + wrapPhoto(message.id, message, attachmentDiv, undefined, undefined, true, true, this.lazyLoadQueue, null); + preloader.attach(attachmentDiv, false); bubble.classList.add('hide-name', 'photo'); diff --git a/src/lib/appManagers/appMediaViewer.ts b/src/lib/appManagers/appMediaViewer.ts index 97487761..442eb4f0 100644 --- a/src/lib/appManagers/appMediaViewer.ts +++ b/src/lib/appManagers/appMediaViewer.ts @@ -693,7 +693,7 @@ export class AppMediaViewer { this.preloader.attach(mover); let cancellablePromise = appPhotosManager.preloadPhoto(media.id, size); - cancellablePromise.then((blob) => { + cancellablePromise.then(() => { if(this.currentMessageID != message.mid) { this.log.warn('media viewer changed photo'); return; diff --git a/src/lib/appManagers/appMessagesManager.ts b/src/lib/appManagers/appMessagesManager.ts index 1b2f33be..216c6189 100644 --- a/src/lib/appManagers/appMessagesManager.ts +++ b/src/lib/appManagers/appMessagesManager.ts @@ -14,7 +14,7 @@ import ServerTimeManager from "../mtproto/serverTimeManager"; import apiFileManager from "../mtproto/apiFileManager"; import appDocsManager from "./appDocsManager"; import appImManager from "./appImManager"; -import { MTDocument } from "../../components/wrappers"; +import { MTDocument, MTPhotoSize } from "../../components/wrappers"; import ProgressivePreloader from "../../components/preloader"; import serverTimeManager from "../mtproto/serverTimeManager"; import apiManager from "../mtproto/apiManager"; @@ -37,7 +37,6 @@ export type HistoryResult = { export class AppMessagesManager { public messagesStorage: any = {}; - public messagesForHistory: any = {}; public messagesForDialogs: any = {}; public historiesStorage: { [peerID: string]: HistoryStorage @@ -107,20 +106,14 @@ export class AppMessagesManager { $rootScope.$on('webpage_updated', (e: CustomEvent) => { let eventData = e.detail; eventData.msgs.forEach((msgID: number) => { - var historyMessage = this.messagesForHistory[msgID]; - if(historyMessage) { - historyMessage.media = { - _: 'messageMediaWebPage', - webpage: appWebPagesManager.wrapForHistory(eventData.id) - }; - - $rootScope.$broadcast('message_edit', { - peerID: this.getMessagePeer(historyMessage), - id: historyMessage.id, - mid: msgID, - justMedia: true - }); - } + let message = this.getMessage(msgID); + message.webpage = appWebPagesManager.getWebPage(eventData.id); // warning + $rootScope.$broadcast('message_edit', { + peerID: this.getMessagePeer(message), + id: message.id, + mid: msgID, + justMedia: true + }); }); }); @@ -327,17 +320,10 @@ export class AppMessagesManager { } var toggleError = (on: any) => { - var historyMessage = this.messagesForHistory[messageID]; if(on) { message.error = true; - if(historyMessage) { - historyMessage.error = true; - } } else { delete message.error; - if(historyMessage) { - delete historyMessage.error; - } } $rootScope.$broadcast('messages_pending'); } @@ -467,7 +453,8 @@ export class AppMessagesManager { caption?: string, entities?: any[], width?: number, - height?: number + height?: number, + objectURL?: string } = {}) { peerID = AppPeersManager.getPeerMigratedTo(peerID) || peerID; var messageID = this.tempID--; @@ -487,6 +474,8 @@ export class AppMessagesManager { let isDocument = !(file instanceof File) && !(file instanceof Blob); let caption = options.caption || ''; + let date = tsNow(true) + ServerTimeManager.serverTimeOffset; + if(caption) { let entities = options.entities || []; caption = RichTextProcessor.parseMarkdown(caption, entities); @@ -497,13 +486,31 @@ export class AppMessagesManager { attachType = 'document'; apiFileName = 'document.' + fileType.split('/')[1]; actionName = 'sendMessageUploadDocumentAction'; - } else if(isDocument) { // maybe it's a sticker + } else if(isDocument) { // maybe it's a sticker or gif attachType = 'document'; apiFileName = ''; } else if(['image/jpeg', 'image/png', 'image/bmp'].indexOf(fileType) >= 0) { attachType = 'photo'; apiFileName = 'photo.' + fileType.split('/')[1]; actionName = 'sendMessageUploadPhotoAction'; + + let photo: any = { + _: 'photo', + id: '' + messageID, + sizes: [{ + _: 'photoSize', + w: options.width, + h: options.height, + type: 'm', + size: file.size + } as MTPhotoSize], + w: options.width, + h: options.height, + downloaded: file.size, + url: options.objectURL || '' + }; + + appPhotosManager.savePhoto(photo); } else if(fileType.substr(0, 6) == 'audio/' || ['video/ogg'].indexOf(fileType) >= 0) { attachType = 'audio'; apiFileName = 'audio.' + (fileType.split('/')[1] == 'ogg' ? 'ogg' : 'mp3'); @@ -559,6 +566,7 @@ export class AppMessagesManager { preloader: preloader, w: options.width, h: options.height, + url: options.objectURL, progress: { percent: 1, total: file.size, @@ -580,7 +588,7 @@ export class AppMessagesManager { to_id: AppPeersManager.getOutputPeer(peerID), flags: flags, pFlags: pFlags, - date: tsNow(true) + ServerTimeManager.serverTimeOffset, + date: date, message: caption, media: isDocument ? { _: 'messageMediaDocument', @@ -595,19 +603,10 @@ export class AppMessagesManager { }; var toggleError = (on: boolean) => { - var historyMessage = this.messagesForHistory[messageID]; if(on) { message.error = true; - - if(historyMessage) { - historyMessage.error = true; - } } else { delete message.error; - - if(historyMessage) { - delete historyMessage.error; - } } $rootScope.$broadcast('messages_pending'); @@ -677,6 +676,8 @@ export class AppMessagesManager { } uploadPromise && uploadPromise.then((inputFile) => { + console.log('appMessagesManager: sendFile uploaded:', inputFile); + inputFile.name = apiFileName; uploaded = true; var inputMedia; @@ -767,7 +768,6 @@ export class AppMessagesManager { historyStorage.pending.splice(pos, 1); } - delete this.messagesForHistory[tempID]; delete this.messagesStorage[tempID]; return true; @@ -2177,10 +2177,6 @@ export class AppMessagesManager { if(message && !message.pFlags.out) { message.pFlags.unread = false; - if(this.messagesForHistory[messageID]) { - this.messagesForHistory[messageID].pFlags.unread = false; - } - if(this.messagesForDialogs[messageID]) { this.messagesForDialogs[messageID].pFlags.unread = false; } @@ -2235,7 +2231,7 @@ export class AppMessagesManager { } public handleUpdate(update: any) { - //console.log('AMM: handleUpdate:', update._); + console.log('AMM: handleUpdate:', update._); switch(update._) { case 'updateMessageID': { var randomID = update.random_id; @@ -2252,14 +2248,8 @@ export class AppMessagesManager { if(pos != -1) { historyStorage.pending.splice(pos, 1); } - delete this.messagesForHistory[tempID]; delete this.messagesStorage[tempID]; - var msgs: any = {} - msgs[tempID] = true; - - //$rootScope.$broadcast('history_delete', {peerID: peerID, msgs: msgs}); // commented 11.02.2020 - this.finalizePendingMessageCallbacks(tempID, mid); } else { this.pendingByMessageID[mid] = randomID; @@ -2489,23 +2479,11 @@ export class AppMessagesManager { this.saveMessages([message], {isEdited: true}); safeReplaceObject(this.messagesStorage[mid], message); - var wasForHistory = this.messagesForHistory[mid]; - if(wasForHistory !== undefined) { - delete this.messagesForHistory[mid]; - var newForHistory = this.wrapForHistory(mid); - safeReplaceObject(wasForHistory, newForHistory); - this.messagesForHistory[mid] = wasForHistory; - } - var dialog = this.getDialogByPeerID(peerID)[0]; var isTopMessage = dialog && dialog.top_message == mid; if(message.clear_history) { // that's will never happen if(isTopMessage) { $rootScope.$broadcast('dialog_flush', {peerID: peerID}); - } else { - var msgs: any = {}; - msgs[mid] = true; - /////////$rootScope.$broadcast('history_delete', {peerID: peerID, msgs: msgs}); // commented 11.02.2020 } } else { $rootScope.$broadcast('message_edit', { @@ -2562,11 +2540,8 @@ export class AppMessagesManager { // console.warn('read', messageID, message.pFlags.unread, message) if(message && message.pFlags.unread) { message.pFlags.unread = false - if(this.messagesForHistory[messageID]) { - this.messagesForHistory[messageID].pFlags.unread = false; - if(!foundAffected) { - foundAffected = true; - } + if(!foundAffected) { + foundAffected = true; } if(this.messagesForDialogs[messageID]) { this.messagesForDialogs[messageID].pFlags.unread = false; @@ -2614,15 +2589,11 @@ export class AppMessagesManager { var len = messages.length; var i; var messageID: number, message; - var historyMessage; for(i = 0; i < len; i++) { messageID = messages[i]; if(message = this.messagesStorage[messageID]) { delete message.pFlags.media_unread; } - if(historyMessage = this.messagesForHistory[messageID]) { - delete historyMessage.pFlags.media_unread; - } } break; } @@ -2668,10 +2639,6 @@ export class AppMessagesManager { history.count++; history.msgs[messageID] = true; - if(this.messagesForHistory[messageID]) { - this.messagesForHistory[messageID].deleted = true; - delete this.messagesForHistory[messageID]; - } if(this.messagesForDialogs[messageID]) { this.messagesForDialogs[messageID].deleted = true; delete this.messagesForDialogs[messageID]; @@ -2842,7 +2809,6 @@ export class AppMessagesManager { }); } if(update.pFlags.popup && update.message) { - var historyMessage = this.wrapForHistory(messageID); //ErrorService.show({error: {code: 400, type: 'UPDATE_SERVICE_NOTIFICATION'}, historyMessage: historyMessage}); // warning } break; @@ -2850,106 +2816,6 @@ export class AppMessagesManager { } } - public wrapForHistory(msgID: number) { - if(this.messagesForHistory[msgID] !== undefined) { - return this.messagesForHistory[msgID]; - } - - var message = copy(this.messagesStorage[msgID]) || {id: msgID}; - - if(message.media && message.media.progress !== undefined) { - message.media.progress = this.messagesStorage[msgID].media.progress; - } - - var fromUser = message.from_id && appUsersManager.getUser(message.from_id); - var fromBot = fromUser && fromUser.pFlags.bot && fromUser.username || false; - var withBot = (fromBot || - message.to_id && ( - message.to_id.chat_id || - message.to_id.user_id && appUsersManager.isBot(message.to_id.user_id) - ) - ) - - if(message.media) { - if(message.media.caption && - message.media.caption.length) { - message.media.rCaption = RichTextProcessor.wrapRichText(message.media.caption, { - noCommands: !withBot, - fromBot: fromBot - }) - } - - switch (message.media._) { - case 'messageMediaPhoto': - message.media.photo = appPhotosManager.wrapForHistory(message.media.photo.id) - break - - /* case 'messageMediaDocument': - message.media.document = appDocsManager.wrapForHistory(message.media.document.id) - break */ - - case 'messageMediaGeo': - var mapUrl = 'https://maps.google.com/?q=' + message.media.geo['lat'] + ',' + message.media.geo['long'] - message.media.mapUrl = mapUrl;//$sce.trustAsResourceUrl(mapUrl) // warning - break - - case 'messageMediaVenue': - var mapUrl: string; - if(message.media.provider == 'foursquare' && - message.media.venue_id) { - mapUrl = 'https://foursquare.com/v/' + encodeURIComponent(message.media.venue_id) - } else { - mapUrl = 'https://maps.google.com/?q=' + message.media.geo['lat'] + ',' + message.media.geo['long'] - } - message.media.mapUrl = mapUrl;//$sce.trustAsResourceUrl(mapUrl) // warning - break - - case 'messageMediaContact': - message.media.rFullName = RichTextProcessor.wrapRichText( - message.media.first_name + ' ' + (message.media.last_name || ''), - {noLinks: true, noLinebreaks: true} - ) - break - - case 'messageMediaWebPage': - if(!message.media.webpage || - message.media.webpage._ == 'webPageEmpty') { - delete message.media - break - } - message.media.webpage = appWebPagesManager.wrapForHistory(message.media.webpage.id) - break - - /*case 'messageMediaGame': - message.media.game = AppGamesManager.wrapForHistory(message.media.game.id) - break */ - } - } else if(message.action) { - switch (message.action._) { - case 'messageActionChatEditPhoto': - case 'messageActionChannelEditPhoto': - message.action.photo = appPhotosManager.wrapForHistory(message.action.photo.id); - break - - case 'messageActionChatCreate': - case 'messageActionChatEditTitle': - case 'messageActionChannelCreate': - case 'messageActionChannelEditTitle': - message.action.rTitle = RichTextProcessor.wrapRichText(message.action.title, {noLinebreaks: true}) || 'chat_title_deleted'; - break - - case 'messageActionBotIntro': - message.action.rDescription = RichTextProcessor.wrapRichText(message.action.description, { - noCommands: !withBot, - fromBot: fromBot - }); - break; - } - } - - return this.messagesForHistory[msgID] = message; - } - public finalizePendingMessage(randomID: number, finalMessage: any) { var pendingData = this.pendingByRandomID[randomID]; // console.log('pdata', randomID, pendingData) @@ -2958,8 +2824,7 @@ export class AppMessagesManager { var peerID = pendingData[0]; var tempID = pendingData[1]; var historyStorage = this.historiesStorage[peerID], - message, - historyMessage; + message; // console.log('pending', randomID, historyStorage.pending) var pos = historyStorage.pending.indexOf(tempID); @@ -2972,19 +2837,10 @@ export class AppMessagesManager { delete message.error; delete message.random_id; delete message.send; - } - - if(historyMessage = this.messagesForHistory[tempID]) { - this.messagesForHistory[finalMessage.mid] = Object.assign(historyMessage, this.wrapForHistory(finalMessage.mid)); - delete historyMessage.pending; - delete historyMessage.error; - delete historyMessage.random_id; - delete historyMessage.send; $rootScope.$broadcast('messages_pending'); } - delete this.messagesForHistory[tempID]; delete this.messagesStorage[tempID]; this.finalizePendingMessageCallbacks(tempID, finalMessage.mid); @@ -2995,10 +2851,6 @@ export class AppMessagesManager { return false } - /* public finalizePendingMessageCallbacks(tempID: number, mid: number) { - $rootScope.$broadcast('message_sent', {tempID, mid}); - } */ - public finalizePendingMessageCallbacks(tempID: number, mid: number) { var callbacks = this.tempFinalizeCallbacks[tempID]; console.warn(dT(), callbacks, tempID); diff --git a/src/lib/appManagers/appPhotosManager.ts b/src/lib/appManagers/appPhotosManager.ts index f21b168c..ee33b9fb 100644 --- a/src/lib/appManagers/appPhotosManager.ts +++ b/src/lib/appManagers/appPhotosManager.ts @@ -1,12 +1,12 @@ import appUsersManager from "./appUsersManager"; -import { copy, calcImageInBox } from "../utils"; +import { calcImageInBox, isObject } from "../utils"; import fileManager from '../filemanager'; import { bytesFromHex } from "../bin_utils"; -import { MTPhotoSize, MTDocument } from "../../components/wrappers"; +import { MTPhotoSize } from "../../components/wrappers"; import apiFileManager from "../mtproto/apiFileManager"; import apiManager from "../mtproto/apiManager"; -type MTPhoto = { +export type MTPhoto = { _: 'photo' | 'photoEmpty' | string, pFlags: any, flags: number, @@ -51,7 +51,7 @@ export class AppPhotosManager { if(!photo.id) { console.warn('no apiPhoto.id', photo); - } else this.photos[photo.id] = photo; + } else this.photos[photo.id] = photo as any; /* if(!('sizes' in photo)) return; @@ -241,98 +241,61 @@ export class AppPhotosManager { return photoSize; } - public preloadPhoto(photoID: any, photoSize?: MTPhotoSize): Promise { - let photo: MTPhoto = null; - - if(typeof(photoID) === 'string') { - photo = this.photos[photoID]; - if(!photo) return Promise.reject(); - } else { - photo = photoID; - } + public preloadPhoto(photoID: any, photoSize?: MTPhotoSize): Promise { + let photo = this.getPhoto(photoID); if(!photoSize) { - let fullWidth = this.windowW/* - (Config.Mobile ? 20 : 32) */; - let fullHeight = this.windowH/* - (Config.Mobile ? 150 : 116) */; + let fullWidth = this.windowW; + let fullHeight = this.windowH; photoSize = this.choosePhotoSize(photo, fullWidth, fullHeight); } - - if(photoSize && photoSize._ != 'photoSizeEmpty') { - // maybe it's a thumb - let isPhoto = photoSize.size && photo.access_hash && photo.file_reference; - let location = isPhoto ? { - _: photo._ == 'document' ? 'inputDocumentFileLocation' : 'inputPhotoFileLocation', - id: photo.id, - access_hash: photo.access_hash, - file_reference: photo.file_reference, - thumb_size: photoSize.type - } : photoSize.location; - let promise: Promise; + if(photo.downloaded >= photoSize.size && photo.url) { + return Promise.resolve(); + } - /* if(photo.downloaded == photoSize.size && photo.url) { - return Promise.resolve(photo.url); - } */ + if(!photoSize || photoSize._ == 'photoSizeEmpty') { + console.error('no photoSize by photo:', photo); + return Promise.reject('no photoSize'); + } + + // maybe it's a thumb + let isPhoto = photoSize.size && photo.access_hash && photo.file_reference; + let location = isPhoto ? { + _: photo._ == 'document' ? 'inputDocumentFileLocation' : 'inputPhotoFileLocation', + id: photo.id, + access_hash: photo.access_hash, + file_reference: photo.file_reference, + thumb_size: photoSize.type + } : photoSize.location; - if(isPhoto/* && photoSize.size >= 1e6 */) { - //console.log('Photos downloadFile exec', photo); - promise = apiFileManager.downloadFile(photo.dc_id, location, photoSize.size); - } else { - //console.log('Photos downloadSmallFile exec', photo, location); - promise = apiFileManager.downloadSmallFile(location); - } + let promise: Promise; + if(isPhoto/* && photoSize.size >= 1e6 */) { + //console.log('Photos downloadFile exec', photo); + promise = apiFileManager.downloadFile(photo.dc_id, location, photoSize.size); + } else { + //console.log('Photos downloadSmallFile exec', photo, location); + promise = apiFileManager.downloadSmallFile(location); + } - if(typeof(photoID) === 'string') { - let photo = this.photos[photoID]; - promise.then(blob => { - if(!photo.downloaded || photo.downloaded < blob.size) { - photo.downloaded = blob.size; - photo.url = URL.createObjectURL(blob); + if(typeof(photoID) === 'string') { + let photo = this.photos[photoID]; + promise.then(blob => { + if(!photo.downloaded || photo.downloaded < blob.size) { + photo.downloaded = blob.size; + photo.url = URL.createObjectURL(blob); - console.log('wrote photo:', photo, photoSize, blob); - } - }); - } + console.log('wrote photo:', photo, photoSize, blob); + } + }); + } - return promise; - } else return Promise.reject('no photoSize'); - } - - public getPhoto(photoID: string) { - return this.photos[photoID] || {_: 'photoEmpty'} as unknown as Partial; + return promise; } - public wrapForHistory(photoID: string, options: any = {}) { - var photo = copy(this.photos[photoID]) || {_: 'photoEmpty'}; - var width = options.website ? 64 : Math.min(this.windowW - 80, Config.Mobile ? 210 : 260); - var height = options.website ? 64 : Math.min(this.windowH - 100, Config.Mobile ? 210 : 260); - var thumbPhotoSize = this.choosePhotoSize(photo, width, height); - var thumb: any = { - width: width, - height: height - }; - - if(options.website && Config.Mobile) { - width = 50; - height = 50; - } - - // console.log('chosen photo size', photoID, thumbPhotoSize) - if(thumbPhotoSize && thumbPhotoSize._ != 'photoSizeEmpty') { - var dim = calcImageInBox(thumbPhotoSize.w, thumbPhotoSize.h, width, height); - thumb.width = dim.w; - thumb.height = dim.h; - thumb.location = thumbPhotoSize.location; - thumb.size = thumbPhotoSize.size; - } else { - thumb.width = 100; - thumb.height = 100; - } - - photo.thumb = thumb; - - return photo; + public getPhoto(photoID: any): MTPhoto { + return isObject(photoID) ? photoID : this.photos[photoID]; } public downloadPhoto(photoID: string) { diff --git a/src/lib/appManagers/appSidebarRight.ts b/src/lib/appManagers/appSidebarRight.ts index 9d938cc6..5c139b85 100644 --- a/src/lib/appManagers/appSidebarRight.ts +++ b/src/lib/appManagers/appSidebarRight.ts @@ -348,19 +348,14 @@ class AppSidebarRight { //this.log('wrapping webpage', webpage); if(webpage.photo) { - let load = () => appPhotosManager.preloadPhoto(webpage.photo.id, appPhotosManager.choosePhotoSize(webpage.photo, 380, 0)) - .then((blob) => { + let load = () => appPhotosManager.preloadPhoto(webpage.photo.id, appPhotosManager.choosePhotoSize(webpage.photo, 60, 60)) + .then(() => { if($rootScope.selectedPeerID != peerID) { this.log.warn('peer changed'); return; } renderImageFromUrl(previewDiv, webpage.photo.url); - - /* let url = URL.createObjectURL(blob); - this.urlsToRevoke.push(url); - - previewDiv.style.backgroundImage = 'url(' + url + ')'; */ }); this.lazyLoadQueueSidebar.push({div: previewDiv, load}); diff --git a/src/lib/appManagers/appStickersManager.ts b/src/lib/appManagers/appStickersManager.ts index 54e1f115..36dd53a1 100644 --- a/src/lib/appManagers/appStickersManager.ts +++ b/src/lib/appManagers/appStickersManager.ts @@ -81,7 +81,7 @@ class appStickersManager { doc.file_reference = Array.from(doc.file_reference); - appDocsManager.saveDoc(doc); + doc = appDocsManager.saveDoc(doc); this.documents[doc.id] = doc; return doc; diff --git a/src/lib/appManagers/appWebPagesManager.ts b/src/lib/appManagers/appWebPagesManager.ts index 37e5800b..986301f8 100644 --- a/src/lib/appManagers/appWebPagesManager.ts +++ b/src/lib/appManagers/appWebPagesManager.ts @@ -19,7 +19,7 @@ class AppWebPagesManager { }); } - saveWebPage(apiWebPage: any, messageID?: number, mediaContext?: any) { + public saveWebPage(apiWebPage: any, messageID?: number, mediaContext?: any) { if(apiWebPage.photo && apiWebPage.photo._ === 'photo') { //appPhotosManager.savePhoto(apiWebPage.photo, mediaContext); apiWebPage.photo = appPhotosManager.savePhoto(apiWebPage.photo, mediaContext); @@ -102,19 +102,9 @@ class AppWebPagesManager { }); } } - - wrapForHistory(webPageID: number) { - var webPage = copy(this.webpages[webPageID]) || {_: 'webPageEmpty'}; - - if(webPage.photo && webPage.photo.id) { - webPage.photo = appPhotosManager.wrapForHistory(webPage.photo.id, {website: webPage.type != 'photo' && webPage.type != 'video'}); - } - /* if (webPage.document && webPage.document.id) { - webPage.document = appDocsManager.wrapForHistory(webPage.document.id) - } */ // warning - - return webPage; + public getWebPage(id: string) { + return this.webpages[id]; } } diff --git a/src/pages/pageIm.ts b/src/pages/pageIm.ts index c73577b6..faee2687 100644 --- a/src/pages/pageIm.ts +++ b/src/pages/pageIm.ts @@ -42,6 +42,8 @@ let onFirstMount = () => import('../lib/appManagers/appImManager').then(() => {/ toggleEmoticons.classList.toggle('active'); }; */ + import('../lib/services'); + (Array.from(document.getElementsByClassName('rp')) as HTMLElement[]).forEach(el => ripple(el)); Array.from(document.getElementsByClassName('btn-menu-toggle')).forEach((el) => { diff --git a/src/scss/partials/_chat.scss b/src/scss/partials/_chat.scss index 7df60faf..57601370 100644 --- a/src/scss/partials/_chat.scss +++ b/src/scss/partials/_chat.scss @@ -476,6 +476,10 @@ $chat-max-width: 696px; .attachment { max-width: 200px; max-height: 200px; + + img { + border-radius: 50%; + } } } diff --git a/src/scss/partials/_emojiDropdown.scss b/src/scss/partials/_emojiDropdown.scss index ae558b97..7b8bf213 100644 --- a/src/scss/partials/_emojiDropdown.scss +++ b/src/scss/partials/_emojiDropdown.scss @@ -15,7 +15,7 @@ overflow: hidden; transition: all 0.2s ease-out; - //transform: scale(0); + transform: scale(0); transform-origin: 0 100%; &.active { diff --git a/tsconfig.json b/tsconfig.json index 97ea0fd7..835957f1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -66,6 +66,7 @@ "public", "coverage", "./src/lib/ckin.js", + "./src/lib/config.js", "./src/lib/StackBlur.js", "./src/lib/*.js", "./src/*.js",