Albums send & render after send
This commit is contained in:
parent
ae8e8f0008
commit
d15abda503
@ -5,11 +5,12 @@ import { RichTextProcessor } from "../lib/richtextprocessor";
|
||||
import apiManager from "../lib/mtproto/mtprotoworker";
|
||||
import appWebPagesManager from "../lib/appManagers/appWebPagesManager";
|
||||
import appImManager from "../lib/appManagers/appImManager";
|
||||
import { calcImageInBox, getRichValue } from "../lib/utils";
|
||||
import { getRichValue, calcImageInBox } from "../lib/utils";
|
||||
import { wrapDocument, wrapReply } from "./wrappers";
|
||||
import appMessagesManager from "../lib/appManagers/appMessagesManager";
|
||||
import initEmoticonsDropdown, { EMOTICONSSTICKERGROUP } from "./emoticonsDropdown";
|
||||
import lottieLoader from "../lib/lottieLoader";
|
||||
import { Layouter, RectPart } from "./groupedLayout";
|
||||
|
||||
export class ChatInput {
|
||||
public pageEl = document.querySelector('.page-chats') as HTMLDivElement;
|
||||
@ -187,67 +188,44 @@ export class ChatInput {
|
||||
});
|
||||
|
||||
let attachFile = (file: File) => {
|
||||
willAttach.file = file;
|
||||
delete willAttach.objectURL;
|
||||
delete willAttach.duration;
|
||||
delete willAttach.width;
|
||||
delete willAttach.height;
|
||||
|
||||
this.fileInput.value = '';
|
||||
|
||||
this.attachMediaPopUp.captionInput.value = '';
|
||||
this.attachMediaPopUp.mediaContainer.innerHTML = '';
|
||||
this.attachMediaPopUp.mediaContainer.style.width = '';
|
||||
this.attachMediaPopUp.mediaContainer.style.height = '';
|
||||
this.attachMediaPopUp.mediaContainer.classList.remove('is-document');
|
||||
|
||||
if(willAttach.type == 'media' && !['image/', 'video/'].find(s => file.type.indexOf(s) === 0)) {
|
||||
willAttach.type = 'document';
|
||||
}
|
||||
|
||||
return new Promise<HTMLDivElement>((resolve, reject) => {
|
||||
let params: SendFileParams = {};
|
||||
params.file = file;
|
||||
console.log('selected file:', file, typeof(file), willAttach);
|
||||
|
||||
let itemDiv = document.createElement('div');
|
||||
switch(willAttach.type) {
|
||||
case 'media': {
|
||||
let isVideo = file.type.indexOf('video/') === 0;
|
||||
|
||||
itemDiv.classList.add('popup-item-media');
|
||||
|
||||
if(isVideo) {
|
||||
let video = document.createElement('video');
|
||||
let source = document.createElement('source');
|
||||
source.src = willAttach.objectURL = URL.createObjectURL(file);
|
||||
source.src = params.objectURL = URL.createObjectURL(file);
|
||||
video.autoplay = false;
|
||||
video.controls = false;
|
||||
|
||||
video.onloadeddata = () => {
|
||||
willAttach.width = video.videoWidth;
|
||||
willAttach.height = video.videoHeight;
|
||||
willAttach.duration = Math.floor(video.duration);
|
||||
params.width = video.videoWidth;
|
||||
params.height = video.videoHeight;
|
||||
params.duration = Math.floor(video.duration);
|
||||
|
||||
let {w, h} = calcImageInBox(willAttach.width, willAttach.height, 378, 256);
|
||||
this.attachMediaPopUp.mediaContainer.style.width = w + 'px';
|
||||
this.attachMediaPopUp.mediaContainer.style.height = h + 'px';
|
||||
this.attachMediaPopUp.mediaContainer.append(video);
|
||||
this.attachMediaPopUp.container.classList.add('active');
|
||||
itemDiv.append(video);
|
||||
resolve(itemDiv);
|
||||
};
|
||||
|
||||
video.append(source);
|
||||
|
||||
this.attachMediaPopUp.titleEl.innerText = 'Send Video';
|
||||
} else {
|
||||
let img = new Image();
|
||||
img.src = willAttach.objectURL = URL.createObjectURL(file);
|
||||
img.src = params.objectURL = URL.createObjectURL(file);
|
||||
img.onload = () => {
|
||||
willAttach.width = img.naturalWidth;
|
||||
willAttach.height = img.naturalHeight;
|
||||
params.width = img.naturalWidth;
|
||||
params.height = img.naturalHeight;
|
||||
|
||||
let {w, h} = calcImageInBox(willAttach.width, willAttach.height, 378, 256);
|
||||
this.attachMediaPopUp.mediaContainer.style.width = w + 'px';
|
||||
this.attachMediaPopUp.mediaContainer.style.height = h + 'px';
|
||||
this.attachMediaPopUp.mediaContainer.append(img);
|
||||
this.attachMediaPopUp.container.classList.add('active');
|
||||
itemDiv.append(img);
|
||||
resolve(itemDiv);
|
||||
};
|
||||
|
||||
this.attachMediaPopUp.titleEl.innerText = 'Send Photo';
|
||||
}
|
||||
|
||||
break;
|
||||
@ -261,34 +239,127 @@ export class ChatInput {
|
||||
type: file.type.indexOf('image/') !== -1 ? 'photo' : 'doc'
|
||||
} as any, false, true);
|
||||
|
||||
this.attachMediaPopUp.titleEl.innerText = 'Send File';
|
||||
|
||||
this.attachMediaPopUp.mediaContainer.append(docDiv);
|
||||
this.attachMediaPopUp.mediaContainer.classList.add('is-document');
|
||||
this.attachMediaPopUp.container.classList.add('active');
|
||||
itemDiv.append(docDiv);
|
||||
resolve(itemDiv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
willAttach.sendFileDetails.push(params);
|
||||
});
|
||||
};
|
||||
|
||||
let willAttach: Partial<{
|
||||
type: 'media' | 'document',
|
||||
isMedia: boolean,
|
||||
let attachFiles = (files: File[]) => {
|
||||
this.fileInput.value = '';
|
||||
|
||||
let container = this.attachMediaPopUp.container.firstElementChild as HTMLElement;
|
||||
container.classList.remove('is-media', 'is-document', 'is-album');
|
||||
|
||||
this.attachMediaPopUp.captionInput.value = '';
|
||||
this.attachMediaPopUp.mediaContainer.innerHTML = '';
|
||||
this.attachMediaPopUp.mediaContainer.style.width = this.attachMediaPopUp.mediaContainer.style.height = '';
|
||||
//willAttach.sendFileDetails.length = 0;
|
||||
willAttach.sendFileDetails = []; // need new array
|
||||
|
||||
files = files.filter(file => {
|
||||
if(willAttach.type == 'media') {
|
||||
return ['image/', 'video/'].find(s => file.type.indexOf(s) === 0);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
if(files.length) {
|
||||
if(willAttach.type == 'document') {
|
||||
this.attachMediaPopUp.titleEl.innerText = 'Send ' + (files.length > 1 ? files.length + ' Files' : 'File');
|
||||
container.classList.add('is-document');
|
||||
} else {
|
||||
container.classList.add('is-media');
|
||||
|
||||
let foundPhotos = 0;
|
||||
let foundVideos = 0;
|
||||
files.forEach(file => {
|
||||
if(file.type.indexOf('image/') === 0) ++foundPhotos;
|
||||
else if(file.type.indexOf('video/') === 0) ++foundVideos;
|
||||
});
|
||||
|
||||
if(foundPhotos && foundVideos) {
|
||||
this.attachMediaPopUp.titleEl.innerText = 'Send Album';
|
||||
} else if(foundPhotos) {
|
||||
this.attachMediaPopUp.titleEl.innerText = 'Send ' + (foundPhotos > 1 ? foundPhotos + ' Photos' : 'Photo');
|
||||
} else if(foundVideos) {
|
||||
this.attachMediaPopUp.titleEl.innerText = 'Send ' + (foundVideos > 1 ? foundVideos + ' Videos' : 'Video');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Promise.all(files.map(attachFile)).then(results => {
|
||||
if(willAttach.type == 'media') {
|
||||
if(willAttach.sendFileDetails.length > 1) {
|
||||
container.classList.add('is-album');
|
||||
|
||||
let layouter = new Layouter(willAttach.sendFileDetails.map(o => ({w: o.width, h: o.height})), 380, 100, 4);
|
||||
let layout = layouter.layout();
|
||||
|
||||
for(let {geometry, sides} of layout) {
|
||||
let div = results.shift();
|
||||
|
||||
div.style.width = geometry.width + 'px';
|
||||
div.style.height = geometry.height + 'px';
|
||||
div.style.top = geometry.y + 'px';
|
||||
div.style.left = geometry.x + 'px';
|
||||
|
||||
if(sides & RectPart.Right) {
|
||||
this.attachMediaPopUp.mediaContainer.style.width = geometry.width + geometry.x + 'px';
|
||||
}
|
||||
|
||||
if(sides & RectPart.Bottom) {
|
||||
this.attachMediaPopUp.mediaContainer.style.height = geometry.height + geometry.y + 'px';
|
||||
}
|
||||
|
||||
this.attachMediaPopUp.mediaContainer.append(div);
|
||||
}
|
||||
|
||||
console.log('chatInput album layout:', layout);
|
||||
} else {
|
||||
let params = willAttach.sendFileDetails[0];
|
||||
let div = results[0];
|
||||
let {w, h} = calcImageInBox(params.width, params.height, 380, 320);
|
||||
div.style.width = w + 'px';
|
||||
div.style.height = h + 'px';
|
||||
this.attachMediaPopUp.mediaContainer.append(div);
|
||||
}
|
||||
} else {
|
||||
this.attachMediaPopUp.mediaContainer.append(...results);
|
||||
}
|
||||
|
||||
this.attachMediaPopUp.container.classList.add('active');
|
||||
});
|
||||
};
|
||||
|
||||
type SendFileParams = Partial<{
|
||||
file: File,
|
||||
caption: string,
|
||||
objectURL: string,
|
||||
width: number,
|
||||
height: number,
|
||||
duration: number
|
||||
}> = {};
|
||||
}>;
|
||||
|
||||
let willAttach: Partial<{
|
||||
type: 'media' | 'document',
|
||||
isMedia: boolean,
|
||||
sendFileDetails: SendFileParams[]
|
||||
}> = {
|
||||
sendFileDetails: []
|
||||
};
|
||||
|
||||
this.fileInput.addEventListener('change', (e) => {
|
||||
var file = (e.target as HTMLInputElement & EventTarget).files[0];
|
||||
if(!file) {
|
||||
let files = (e.target as HTMLInputElement & EventTarget).files;
|
||||
if(!files.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
attachFile(file);
|
||||
attachFiles(Array.from(files));
|
||||
}, false);
|
||||
|
||||
this.attachMenu.media.addEventListener('click', () => {
|
||||
@ -329,10 +400,43 @@ export class ChatInput {
|
||||
|
||||
this.attachMediaPopUp.sendBtn.addEventListener('click', () => {
|
||||
this.attachMediaPopUp.container.classList.remove('active');
|
||||
willAttach.caption = this.attachMediaPopUp.captionInput.value;
|
||||
let caption = this.attachMediaPopUp.captionInput.value;
|
||||
willAttach.isMedia = willAttach.type == 'media';
|
||||
|
||||
appMessagesManager.sendFile(appImManager.peerID, willAttach.file, willAttach);
|
||||
console.log('will send files with options:', willAttach);
|
||||
|
||||
let peerID = appImManager.peerID;
|
||||
|
||||
if(willAttach.sendFileDetails.length > 1 && willAttach.isMedia) {
|
||||
appMessagesManager.sendAlbum(peerID, willAttach.sendFileDetails.map(d => d.file), Object.assign({
|
||||
caption,
|
||||
replyToMsgID: this.replyToMsgID
|
||||
}, willAttach));
|
||||
} else {
|
||||
if(caption) {
|
||||
if(willAttach.sendFileDetails.length > 1) {
|
||||
appMessagesManager.sendText(peerID, caption, {replyToMsgID: this.replyToMsgID});
|
||||
caption = '';
|
||||
this.replyToMsgID = 0;
|
||||
}
|
||||
}
|
||||
|
||||
let promises = willAttach.sendFileDetails.map(params => {
|
||||
let promise = appMessagesManager.sendFile(peerID, params.file, Object.assign({
|
||||
isMedia: willAttach.isMedia,
|
||||
caption,
|
||||
replyToMsgID: this.replyToMsgID
|
||||
}, params));
|
||||
|
||||
caption = '';
|
||||
this.replyToMsgID = 0;
|
||||
return promise;
|
||||
});
|
||||
}
|
||||
|
||||
//Promise.all(promises);
|
||||
|
||||
//appMessagesManager.sendFile(appImManager.peerID, willAttach.file, willAttach);
|
||||
|
||||
this.onMessageSent();
|
||||
});
|
||||
|
@ -4,7 +4,6 @@ import { CancellablePromise } from "../lib/polyfill";
|
||||
export default class ProgressivePreloader {
|
||||
public preloader: HTMLDivElement = null;
|
||||
private circle: SVGCircleElement = null;
|
||||
private progress = 0;
|
||||
private promise: CancellablePromise<any> = null;
|
||||
private tempID = 0;
|
||||
private detached = true;
|
||||
@ -103,8 +102,6 @@ export default class ProgressivePreloader {
|
||||
}
|
||||
|
||||
public setProgress(percents: number) {
|
||||
this.progress = percents;
|
||||
|
||||
if(!isInDOM(this.circle)) {
|
||||
return;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import appPhotosManager from '../lib/appManagers/appPhotosManager';
|
||||
import appPhotosManager, { MTPhoto } from '../lib/appManagers/appPhotosManager';
|
||||
//import CryptoWorker from '../lib/crypto/cryptoworker';
|
||||
import apiManager from '../lib/mtproto/mtprotoworker';
|
||||
import LottieLoader from '../lib/lottieLoader';
|
||||
@ -13,6 +13,8 @@ import VideoPlayer, { MediaProgressLine } from '../lib/mediaPlayer';
|
||||
import { RichTextProcessor } from '../lib/richtextprocessor';
|
||||
import { CancellablePromise } from '../lib/polyfill';
|
||||
import { renderImageFromUrl } from './misc';
|
||||
import appMessagesManager from '../lib/appManagers/appMessagesManager';
|
||||
import { Layouter, RectPart } from './groupedLayout';
|
||||
|
||||
export type MTDocument = {
|
||||
_: 'document' | 'documentEmpty',
|
||||
@ -75,6 +77,17 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
||||
|
||||
if(withTail) {
|
||||
img = wrapMediaWithTail(doc, message, container, boxWidth, boxHeight, isOut);
|
||||
} else if(!boxWidth && !boxHeight) { // album
|
||||
let sizes = doc.thumbs;
|
||||
if(!doc.downloaded && sizes && sizes[0].bytes) {
|
||||
appPhotosManager.setAttachmentPreview(sizes[0].bytes, container, false);
|
||||
}
|
||||
|
||||
img = container.firstElementChild as HTMLImageElement || new Image();
|
||||
|
||||
if(!container.contains(img)) {
|
||||
container.append(img);
|
||||
}
|
||||
} else {
|
||||
if(!container.firstElementChild || (container.firstElementChild.tagName != 'IMG' && container.firstElementChild.tagName != 'VIDEO')) {
|
||||
let size = appPhotosManager.setAttachmentSize(doc, container, boxWidth, boxHeight);
|
||||
@ -106,7 +119,9 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
||||
let loadVideo = () => {
|
||||
let promise = appDocsManager.downloadDoc(doc);
|
||||
|
||||
if(!doc.downloaded) {
|
||||
if(message.media.preloader) { // means upload
|
||||
message.media.preloader.attach(container);
|
||||
} else if(!doc.downloaded) {
|
||||
let preloader = new ProgressivePreloader(container, true);
|
||||
preloader.attach(container, true, promise);
|
||||
}
|
||||
@ -600,14 +615,24 @@ function wrapMediaWithTail(photo: any, message: {mid: number, message: string},
|
||||
return image;
|
||||
}
|
||||
|
||||
export 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, size: MTPhotoSize = null) {
|
||||
let photo = appPhotosManager.getPhoto(photoID);
|
||||
|
||||
let size: MTPhotoSize;
|
||||
let image: SVGImageElement | HTMLImageElement;
|
||||
if(withTail) {
|
||||
image = wrapMediaWithTail(photo, message, container, boxWidth, boxHeight, isOut);
|
||||
} else { // means webpage's preview
|
||||
} else if(size) { // album
|
||||
let sizes = photo.sizes;
|
||||
if(!photo.downloaded && sizes && sizes[0].bytes) {
|
||||
appPhotosManager.setAttachmentPreview(sizes[0].bytes, container, false);
|
||||
}
|
||||
|
||||
image = container.firstElementChild as HTMLImageElement || new Image();
|
||||
|
||||
if(!container.contains(image)) {
|
||||
container.appendChild(image);
|
||||
}
|
||||
} else if(boxWidth && boxHeight) { // means webpage's preview
|
||||
size = appPhotosManager.setAttachmentSize(photoID, container, boxWidth, boxHeight, false);
|
||||
|
||||
image = container.firstElementChild as HTMLImageElement || new Image();
|
||||
@ -626,7 +651,12 @@ export function wrapPhoto(photoID: string, message: any, container: HTMLDivEleme
|
||||
} */
|
||||
|
||||
let preloader: ProgressivePreloader;
|
||||
if(!photo.downloaded) preloader = new ProgressivePreloader(container, false);
|
||||
if(message.media.preloader) { // means upload
|
||||
message.media.preloader.attach(container);
|
||||
} else if(!photo.downloaded) {
|
||||
preloader = new ProgressivePreloader(container, false);
|
||||
}
|
||||
|
||||
let load = () => {
|
||||
let promise = appPhotosManager.preloadPhoto(photoID, size);
|
||||
|
||||
@ -637,7 +667,7 @@ export function wrapPhoto(photoID: string, message: any, container: HTMLDivEleme
|
||||
return promise.then(() => {
|
||||
if(middleware && !middleware()) return;
|
||||
|
||||
renderImageFromUrl(image, photo.url);
|
||||
renderImageFromUrl(image || container, photo.url);
|
||||
});
|
||||
};
|
||||
|
||||
@ -854,3 +884,128 @@ export function wrapReply(title: string, subtitle: string, media?: any) {
|
||||
|
||||
return div;
|
||||
}
|
||||
|
||||
export function wrapAlbum({groupID, attachmentDiv, middleware, uploading, lazyLoadQueue, isOut}: {
|
||||
groupID: string,
|
||||
attachmentDiv: HTMLElement,
|
||||
middleware?: () => boolean,
|
||||
lazyLoadQueue?: LazyLoadQueue,
|
||||
uploading?: boolean,
|
||||
isOut: boolean
|
||||
}) {
|
||||
let items: {size: MTPhotoSize, media: any, message: any}[] = [];
|
||||
|
||||
// higher msgID will be the last in album
|
||||
let storage = appMessagesManager.groupedMessagesStorage[groupID];
|
||||
for(let mid in storage) {
|
||||
let m = appMessagesManager.getMessage(+mid);
|
||||
let media = m.media.photo || m.media.document;
|
||||
|
||||
let size: any = media._ == 'photo' ? appPhotosManager.choosePhotoSize(media, 380, 380) : {w: media.w, h: media.h};
|
||||
items.push({size, media, message: m});
|
||||
}
|
||||
|
||||
let spacing = 2;
|
||||
let layouter = new Layouter(items.map(i => ({w: i.size.w, h: i.size.h})), 451, 100, spacing);
|
||||
let layout = layouter.layout();
|
||||
console.log('layout:', layout, items.map(i => ({w: i.size.w, h: i.size.h})));
|
||||
|
||||
/* let borderRadius = window.getComputedStyle(realParent).getPropertyValue('border-radius');
|
||||
let brSplitted = fillPropertyValue(borderRadius); */
|
||||
|
||||
for(let {geometry, sides} of layout) {
|
||||
let {size, media, message} = items.shift();
|
||||
let div = document.createElement('div');
|
||||
div.classList.add('album-item');
|
||||
div.dataset.mid = message.mid;
|
||||
|
||||
div.style.width = geometry.width + 'px';
|
||||
div.style.height = geometry.height + 'px';
|
||||
div.style.top = geometry.y + 'px';
|
||||
div.style.left = geometry.x + 'px';
|
||||
|
||||
if(sides & RectPart.Right) {
|
||||
attachmentDiv.style.width = geometry.width + geometry.x + 'px';
|
||||
}
|
||||
|
||||
if(sides & RectPart.Bottom) {
|
||||
attachmentDiv.style.height = geometry.height + geometry.y + 'px';
|
||||
}
|
||||
|
||||
if(sides & RectPart.Left && sides & RectPart.Top) {
|
||||
div.style.borderTopLeftRadius = 'inherit';
|
||||
}
|
||||
|
||||
if(sides & RectPart.Left && sides & RectPart.Bottom) {
|
||||
div.style.borderBottomLeftRadius = 'inherit';
|
||||
}
|
||||
|
||||
if(sides & RectPart.Right && sides & RectPart.Top) {
|
||||
div.style.borderTopRightRadius = 'inherit';
|
||||
}
|
||||
|
||||
if(sides & RectPart.Right && sides & RectPart.Bottom) {
|
||||
div.style.borderBottomRightRadius = 'inherit';
|
||||
}
|
||||
|
||||
if(media._ == 'photo') {
|
||||
wrapPhoto(
|
||||
media.id,
|
||||
message,
|
||||
div,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
isOut,
|
||||
lazyLoadQueue,
|
||||
middleware,
|
||||
size
|
||||
);
|
||||
} else {
|
||||
wrapVideo({
|
||||
doc: message.media.document,
|
||||
container: div,
|
||||
message,
|
||||
boxWidth: 0,
|
||||
boxHeight: 0,
|
||||
withTail: false,
|
||||
isOut,
|
||||
lazyLoadQueue,
|
||||
middleware
|
||||
});
|
||||
}
|
||||
|
||||
/* let load = () => appPhotosManager.preloadPhoto(media._ == 'photo' ? media.id : media, size)
|
||||
.then((blob) => {
|
||||
if(middleware && !middleware()) {
|
||||
console.warn('peer changed');
|
||||
return;
|
||||
}
|
||||
|
||||
if(!uploading) {
|
||||
preloader.detach();
|
||||
}
|
||||
|
||||
if(media && media.url) {
|
||||
renderImageFromUrl(div, media.url);
|
||||
} else {
|
||||
let url = URL.createObjectURL(blob);
|
||||
|
||||
let img = new Image();
|
||||
img.src = url;
|
||||
img.onload = () => {
|
||||
div.style.backgroundImage = 'url(' + url + ')';
|
||||
};
|
||||
}
|
||||
|
||||
//div.style.backgroundImage = 'url(' + url + ')';
|
||||
});
|
||||
|
||||
load(); */
|
||||
|
||||
// @ts-ignore
|
||||
//div.style.backgroundColor = '#' + Math.floor(Math.random() * (2 ** 24 - 1)).toString(16).padStart(6, '0');
|
||||
|
||||
attachmentDiv.append(div);
|
||||
}
|
||||
}
|
||||
|
@ -145,6 +145,21 @@ class AppDocsManager {
|
||||
return isObject(docID) ? docID : this.docs[docID];
|
||||
}
|
||||
|
||||
public getInputByID(docID: any) {
|
||||
let doc = this.getDoc(docID);
|
||||
return {
|
||||
_: 'inputMediaDocument',
|
||||
flags: 0,
|
||||
id: {
|
||||
_: 'inputDocument',
|
||||
id: doc.id,
|
||||
access_hash: doc.access_hash,
|
||||
file_reference: doc.file_reference
|
||||
},
|
||||
ttl_seconds: 0
|
||||
};
|
||||
}
|
||||
|
||||
public getFileName(doc: MTDocument) {
|
||||
if(doc.file_name) {
|
||||
return doc.file_name;
|
||||
|
@ -17,15 +17,14 @@ import appSidebarLeft from "./appSidebarLeft";
|
||||
import appChatsManager from "./appChatsManager";
|
||||
import appMessagesIDsManager from "./appMessagesIDsManager";
|
||||
import apiUpdatesManager from './apiUpdatesManager';
|
||||
import { wrapDocument, wrapPhoto, wrapVideo, wrapSticker, wrapReply, MTPhotoSize } from '../../components/wrappers';
|
||||
import { wrapDocument, wrapPhoto, wrapVideo, wrapSticker, wrapReply, wrapAlbum } from '../../components/wrappers';
|
||||
import ProgressivePreloader from '../../components/preloader';
|
||||
import { openBtnMenu, renderImageFromUrl, formatPhoneNumber } from '../../components/misc';
|
||||
import { openBtnMenu, formatPhoneNumber } from '../../components/misc';
|
||||
import { ChatInput } from '../../components/chatInput';
|
||||
import Scrollable from '../../components/scrollable';
|
||||
import BubbleGroups from '../../components/bubbleGroups';
|
||||
import LazyLoadQueue from '../../components/lazyLoadQueue';
|
||||
import appDocsManager from './appDocsManager';
|
||||
import { Layouter, RectPart } from '../../components/groupedLayout';
|
||||
|
||||
console.log('appImManager included!');
|
||||
|
||||
@ -192,13 +191,7 @@ export class AppImManager {
|
||||
$rootScope.$on('message_sent', (e: CustomEvent) => {
|
||||
let {tempID, mid} = e.detail;
|
||||
|
||||
////this.log('message_sent', e.detail);
|
||||
|
||||
let bubble = this.bubbles[tempID];
|
||||
if(bubble) {
|
||||
this.bubbles[mid] = bubble;
|
||||
|
||||
/////this.log('message_sent', bubble);
|
||||
this.log('message_sent', e.detail);
|
||||
|
||||
// set cached url to media
|
||||
let message = appMessagesManager.getMessage(mid);
|
||||
@ -220,6 +213,21 @@ export class AppImManager {
|
||||
}
|
||||
}
|
||||
|
||||
let bubble = this.bubbles[tempID];
|
||||
if(bubble) {
|
||||
this.bubbles[mid] = bubble;
|
||||
|
||||
/////this.log('message_sent', bubble);
|
||||
|
||||
// set new mids to album items for mediaViewer
|
||||
if(message.grouped_id) {
|
||||
let items = bubble.querySelectorAll('.album-item');
|
||||
let groupIDs = Object.keys(appMessagesManager.groupedMessagesStorage[message.grouped_id]).map(i => +i).sort((a, b) => a - b);
|
||||
(Array.from(items) as HTMLElement[]).forEach((item, idx) => {
|
||||
item.dataset.mid = '' + groupIDs[idx];
|
||||
});
|
||||
}
|
||||
|
||||
bubble.classList.remove('is-sending');
|
||||
bubble.classList.add('is-sent');
|
||||
bubble.dataset.mid = mid;
|
||||
@ -243,11 +251,16 @@ export class AppImManager {
|
||||
let {peerID, mid, id, justMedia} = e.detail;
|
||||
|
||||
if(peerID != this.peerID) return;
|
||||
let message = appMessagesManager.getMessage(mid);
|
||||
|
||||
let bubble = this.bubbles[mid];
|
||||
if(!bubble && message.grouped_id) {
|
||||
let a = this.getAlbumBubble(message.grouped_id);
|
||||
bubble = a.bubble;
|
||||
message = a.message;
|
||||
}
|
||||
if(!bubble) return;
|
||||
|
||||
let message = appMessagesManager.getMessage(mid);
|
||||
this.renderMessage(message, true, false, bubble, false);
|
||||
});
|
||||
|
||||
@ -320,7 +333,50 @@ export class AppImManager {
|
||||
|
||||
if(!bubble) return;
|
||||
|
||||
if(['IMG', 'VIDEO', 'SVG', 'DIV', 'image'].indexOf(target.tagName) === -1) target = findUpTag(target, 'DIV');
|
||||
if((target.tagName == 'IMG' && !target.classList.contains('emoji') && !target.parentElement.classList.contains('user-avatar'))
|
||||
|| target.tagName == 'image'
|
||||
|| target.classList.contains('album-item')
|
||||
|| (target.tagName == 'VIDEO' && !bubble.classList.contains('round'))) {
|
||||
let messageID = +findUpClassName(target, 'album-item')?.dataset.mid || +bubble.dataset.mid;
|
||||
let message = appMessagesManager.getMessage(messageID);
|
||||
if(!message) {
|
||||
this.log.warn('no message by messageID:', messageID);
|
||||
return;
|
||||
}
|
||||
|
||||
let targets: {element: HTMLElement, mid: number}[] = [];
|
||||
let ids = Object.keys(this.bubbles).map(k => +k).filter(id => {
|
||||
//if(!this.scrollable.visibleElements.find(e => e.element == this.bubbles[id])) return false;
|
||||
|
||||
let message = appMessagesManager.getMessage(id);
|
||||
|
||||
return message.media && (message.media.photo || (message.media.document && (message.media.document.type == 'video' || message.media.document.type == 'gif')) || (message.media.webpage && (message.media.webpage.document || message.media.webpage.photo)));
|
||||
}).sort((a, b) => a - b);
|
||||
|
||||
ids.forEach(id => {
|
||||
let bubble = this.bubbles[id];
|
||||
|
||||
let elements = this.bubbles[id].querySelectorAll('.attachment img, .preview img, video, .bubble__media-container') as NodeListOf<HTMLElement>;
|
||||
Array.from(elements).forEach((element: HTMLElement) => {
|
||||
let albumItem = findUpClassName(element, 'album-item');
|
||||
targets.push({
|
||||
element,
|
||||
mid: +albumItem?.dataset.mid || id
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
let idx = targets.findIndex(t => t.mid == messageID);
|
||||
|
||||
this.log('open mediaViewer single with ids:', ids, idx, targets);
|
||||
|
||||
appMediaViewer.openMedia(message, targets[idx].element, true,
|
||||
this.scroll.parentElement, targets.slice(0, idx), targets.slice(idx + 1)/* , !message.grouped_id */);
|
||||
|
||||
//appMediaViewer.openMedia(message, target as HTMLImageElement);
|
||||
}
|
||||
|
||||
if(['IMG', 'DIV'].indexOf(target.tagName) === -1) target = findUpTag(target, 'DIV');
|
||||
|
||||
if(target.tagName == 'DIV') {
|
||||
if(target.classList.contains('forward')) {
|
||||
@ -351,49 +407,12 @@ export class AppImManager {
|
||||
let originalMessageID = +bubble.getAttribute('data-original-mid');
|
||||
this.setPeer(this.peerID, originalMessageID);
|
||||
}
|
||||
} else if(bubble.classList.contains('round')) {
|
||||
|
||||
} else if(target.tagName == 'IMG' && target.parentElement.classList.contains('user-avatar')) {
|
||||
let peerID = +target.parentElement.dataset.peerID;
|
||||
|
||||
if(!isNaN(peerID)) {
|
||||
this.setPeer(peerID);
|
||||
}
|
||||
} else if((target.tagName == 'IMG' && !target.classList.contains('emoji')) || target.tagName == 'image' || target.tagName == 'VIDEO') {
|
||||
let messageID = 0;
|
||||
for(let mid in this.bubbles) {
|
||||
if(this.bubbles[mid] == bubble) {
|
||||
messageID = +mid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
let message = appMessagesManager.getMessage(messageID);
|
||||
if(!message) {
|
||||
this.log.warn('no message by messageID:', messageID);
|
||||
return;
|
||||
}
|
||||
|
||||
let ids = Object.keys(this.bubbles).map(k => +k).filter(id => {
|
||||
//if(!this.scrollable.visibleElements.find(e => e.element == this.bubbles[id])) return false;
|
||||
|
||||
let message = appMessagesManager.getMessage(id);
|
||||
|
||||
return message.media && (message.media.photo || (message.media.document && (message.media.document.type == 'video' || message.media.document.type == 'gif')) || (message.media.webpage && (message.media.webpage.document || message.media.webpage.photo)));
|
||||
}).sort((a, b) => a - b);
|
||||
let idx = ids.findIndex(i => i == messageID);
|
||||
|
||||
let targets = ids.map(id => ({
|
||||
//element: (this.bubbles[id].querySelector('img, video') || this.bubbles[id].querySelector('image')) as HTMLElement,
|
||||
element: this.bubbles[id].querySelector('.attachment img, .preview img, video, .bubble__media-container, .album-item') as HTMLElement,
|
||||
mid: id
|
||||
}));
|
||||
|
||||
this.log('open mediaViewer with ids:', ids, idx, targets);
|
||||
|
||||
appMediaViewer.openMedia(message, targets[idx].element, true,
|
||||
this.scroll.parentElement, targets.slice(0, idx), targets.slice(idx + 1));
|
||||
|
||||
//appMediaViewer.openMedia(message, target as HTMLImageElement);
|
||||
}
|
||||
|
||||
//console.log('chatInner click', e);
|
||||
@ -656,6 +675,19 @@ export class AppImManager {
|
||||
return apiManager.invokeApi('account.updateStatus', {offline: this.offline});
|
||||
}
|
||||
|
||||
public getAlbumBubble(groupID: string) {
|
||||
let group = appMessagesManager.groupedMessagesStorage[groupID];
|
||||
for(let i in group) {
|
||||
let mid = +i;
|
||||
if(this.bubbles[mid]) return {
|
||||
bubble: this.bubbles[mid],
|
||||
message: appMessagesManager.getMessage(mid)
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public loadMoreHistory(top: boolean) {
|
||||
this.log('loadMoreHistory', top);
|
||||
if(!this.peerID || testScroll || this.setPeerPromise || (top && this.getHistoryTopPromise) || (!top && this.getHistoryBottomPromise)) return;
|
||||
@ -1295,13 +1327,37 @@ export class AppImManager {
|
||||
timeInner.classList.add('inner', 'tgico');
|
||||
timeInner.innerHTML = time;
|
||||
|
||||
let richText = RichTextProcessor.wrapRichText(message.message, {
|
||||
entities: message.totalEntities
|
||||
let messageMessage: string, totalEntities: any[];
|
||||
if(message.grouped_id) {
|
||||
let group = appMessagesManager.groupedMessagesStorage[message.grouped_id];
|
||||
let foundMessages = 0;
|
||||
for(let i in group) {
|
||||
let m = group[i];
|
||||
if(m.message) {
|
||||
if(++foundMessages > 1) break;
|
||||
messageMessage = m.message;
|
||||
totalEntities = m.totalEntities;
|
||||
}
|
||||
}
|
||||
|
||||
if(foundMessages > 1) {
|
||||
messageMessage = undefined;
|
||||
totalEntities = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
if(!messageMessage && !totalEntities) {
|
||||
messageMessage = message.message;
|
||||
totalEntities = message.totalEntities;
|
||||
}
|
||||
|
||||
let richText = RichTextProcessor.wrapRichText(messageMessage, {
|
||||
entities: totalEntities
|
||||
});
|
||||
|
||||
if(message.totalEntities) {
|
||||
let emojiEntities = message.totalEntities.filter((e: any) => e._ == 'messageEntityEmoji');
|
||||
let strLength = message.message.length;
|
||||
if(totalEntities) {
|
||||
let emojiEntities = totalEntities.filter((e: any) => e._ == 'messageEntityEmoji');
|
||||
let strLength = messageMessage.length;
|
||||
let emojiStrLength = emojiEntities.reduce((acc: number, curr: any) => acc + curr.length, 0);
|
||||
|
||||
if(emojiStrLength == strLength && emojiEntities.length <= 3) {
|
||||
@ -1348,23 +1404,37 @@ export class AppImManager {
|
||||
let attachmentDiv = document.createElement('div');
|
||||
attachmentDiv.classList.add('attachment');
|
||||
|
||||
if(!message.message) {
|
||||
if(!messageMessage) {
|
||||
bubble.classList.add('is-message-empty');
|
||||
}
|
||||
|
||||
let processingWebPage = false;
|
||||
|
||||
switch(message.media._) {
|
||||
case 'messageMediaPending': {
|
||||
let pending = message.media;
|
||||
let preloader = pending.preloader as ProgressivePreloader;
|
||||
|
||||
switch(pending.type) {
|
||||
case 'album': {
|
||||
this.log('will wrap pending album');
|
||||
|
||||
bubble.classList.add('hide-name', 'photo', 'is-album');
|
||||
wrapAlbum({
|
||||
groupID: '' + message.id,
|
||||
attachmentDiv,
|
||||
uploading: true,
|
||||
isOut: true
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'photo': {
|
||||
//if(pending.size < 5e6) {
|
||||
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');
|
||||
//}
|
||||
|
||||
@ -1401,6 +1471,7 @@ export class AppImManager {
|
||||
preloader.attach(icoDiv, false);
|
||||
|
||||
bubble.classList.remove('is-message-empty');
|
||||
messageDiv.classList.add((pending.type || 'document') + '-message');
|
||||
messageDiv.append(docDiv);
|
||||
processingWebPage = true;
|
||||
break;
|
||||
@ -1416,105 +1487,18 @@ export class AppImManager {
|
||||
////////this.log('messageMediaPhoto', photo);
|
||||
|
||||
bubble.classList.add('hide-name', 'photo');
|
||||
|
||||
if(message.grouped_id) {
|
||||
bubble.classList.add('is-album');
|
||||
|
||||
let items: {size: MTPhotoSize, media: any}[] = [];
|
||||
|
||||
// higher msgID will be the last in album
|
||||
let storage = appMessagesManager.groupedMessagesStorage[message.grouped_id];
|
||||
for(let mid in storage) {
|
||||
let m = appMessagesManager.getMessage(+mid);
|
||||
let media = m.media.photo || m.media.document;
|
||||
|
||||
let size = appPhotosManager.choosePhotoSize(media, 380, 380);
|
||||
items.push({size, media});
|
||||
}
|
||||
|
||||
let spacing = 2;
|
||||
let layouter = new Layouter(items.map(i => ({w: i.size.w, h: i.size.h})), 451, 100, spacing);
|
||||
let layout = layouter.layout();
|
||||
this.log('layout:', layout);
|
||||
|
||||
/* let borderRadius = window.getComputedStyle(realParent).getPropertyValue('border-radius');
|
||||
let brSplitted = fillPropertyValue(borderRadius); */
|
||||
|
||||
for(let {geometry, sides} of layout) {
|
||||
let {size, media} = items.shift();
|
||||
let div = document.createElement('div');
|
||||
div.classList.add('album-item');
|
||||
|
||||
div.style.width = geometry.width + 'px';
|
||||
div.style.height = geometry.height + 'px';
|
||||
div.style.top = geometry.y + 'px';
|
||||
div.style.left = geometry.x + 'px';
|
||||
|
||||
if(sides & RectPart.Right) {
|
||||
attachmentDiv.style.width = geometry.width + geometry.x + 'px';
|
||||
}
|
||||
|
||||
if(sides & RectPart.Bottom) {
|
||||
attachmentDiv.style.height = geometry.height + geometry.y + 'px';
|
||||
}
|
||||
|
||||
if(sides & RectPart.Left && sides & RectPart.Top) {
|
||||
div.style.borderTopLeftRadius = 'inherit';
|
||||
}
|
||||
|
||||
if(sides & RectPart.Left && sides & RectPart.Bottom) {
|
||||
div.style.borderBottomLeftRadius = 'inherit';
|
||||
}
|
||||
|
||||
if(sides & RectPart.Right && sides & RectPart.Top) {
|
||||
div.style.borderTopRightRadius = 'inherit';
|
||||
}
|
||||
|
||||
if(sides & RectPart.Right && sides & RectPart.Bottom) {
|
||||
div.style.borderBottomRightRadius = 'inherit';
|
||||
}
|
||||
|
||||
/* if(geometry.y != 0) {
|
||||
div.style.marginTop = spacing + 'px';
|
||||
}
|
||||
|
||||
if(geometry.x != 0) {
|
||||
div.style.marginLeft = spacing + 'px';
|
||||
} */
|
||||
|
||||
let preloader = new ProgressivePreloader(div);
|
||||
|
||||
let load = () => appPhotosManager.preloadPhoto(media._ == 'photo' ? media.id : media, size)
|
||||
.then((blob) => {
|
||||
if(this.peerID != peerID) {
|
||||
this.log.warn('peer changed');
|
||||
return;
|
||||
}
|
||||
|
||||
preloader.detach();
|
||||
if(media && media.url) {
|
||||
renderImageFromUrl(div, media.url);
|
||||
}/* else {
|
||||
let url = URL.createObjectURL(blob);
|
||||
this.urlsToRevoke.push(url);
|
||||
|
||||
let img = new Image();
|
||||
img.src = url;
|
||||
img.onload = () => {
|
||||
div.style.backgroundImage = 'url(' + url + ')';
|
||||
};
|
||||
} */
|
||||
|
||||
//div.style.backgroundImage = 'url(' + url + ')';
|
||||
wrapAlbum({
|
||||
groupID: message.grouped_id,
|
||||
attachmentDiv,
|
||||
middleware: () => {
|
||||
return this.peerID == peerID;
|
||||
},
|
||||
isOut: our,
|
||||
lazyLoadQueue: this.lazyLoadQueue
|
||||
});
|
||||
|
||||
load();
|
||||
|
||||
// @ts-ignore
|
||||
//div.style.backgroundColor = '#' + Math.floor(Math.random() * (2 ** 24 - 1)).toString(16).padStart(6, '0');
|
||||
|
||||
attachmentDiv.append(div);
|
||||
}
|
||||
} else {
|
||||
wrapPhoto(photo.id, message, attachmentDiv, undefined, undefined, true, our, this.lazyLoadQueue, () => {
|
||||
return this.peerID == peerID;
|
||||
@ -1650,6 +1634,19 @@ export class AppImManager {
|
||||
}
|
||||
|
||||
bubble.classList.add('hide-name', 'video');
|
||||
if(message.grouped_id) {
|
||||
bubble.classList.add('is-album');
|
||||
|
||||
wrapAlbum({
|
||||
groupID: message.grouped_id,
|
||||
attachmentDiv,
|
||||
middleware: () => {
|
||||
return this.peerID == peerID;
|
||||
},
|
||||
isOut: our,
|
||||
lazyLoadQueue: this.lazyLoadQueue
|
||||
});
|
||||
} else {
|
||||
wrapVideo({
|
||||
doc,
|
||||
container: attachmentDiv,
|
||||
@ -1663,6 +1660,7 @@ export class AppImManager {
|
||||
return this.peerID == peerID;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
} else if(doc.mime_type == 'audio/ogg') {
|
||||
|
@ -56,6 +56,7 @@ export class AppMediaViewer {
|
||||
private loadedAllMediaDown = false;
|
||||
|
||||
private reverse = false; // reverse means next = higher msgid
|
||||
private needLoadMore = true;
|
||||
|
||||
constructor() {
|
||||
this.log = logger('AMV');
|
||||
@ -517,7 +518,7 @@ export class AppMediaViewer {
|
||||
}
|
||||
|
||||
public openMedia(message: any, target?: HTMLElement, reverse = false, targetContainer?: HTMLElement,
|
||||
prevTargets: AppMediaViewer['prevTargets'] = [], nextTargets: AppMediaViewer['prevTargets'] = [], loadMore: () => void = null) {
|
||||
prevTargets: AppMediaViewer['prevTargets'] = [], nextTargets: AppMediaViewer['prevTargets'] = [], needLoadMore = true) {
|
||||
////////this.log('openMedia doc:', message, prevTarget, nextTarget);
|
||||
let media = message.media.photo || message.media.document || message.media.webpage.document || message.media.webpage.photo;
|
||||
|
||||
@ -530,6 +531,7 @@ export class AppMediaViewer {
|
||||
this.prevTargets = prevTargets;
|
||||
this.nextTargets = nextTargets;
|
||||
this.reverse = reverse;
|
||||
this.needLoadMore = needLoadMore;
|
||||
//this.loadMore = loadMore;
|
||||
}
|
||||
|
||||
@ -557,6 +559,7 @@ export class AppMediaViewer {
|
||||
this.currentMessageID = message.mid;
|
||||
this.lastTarget = target;
|
||||
|
||||
if(this.needLoadMore) {
|
||||
if(this.nextTargets.length < 20) {
|
||||
this.loadMoreMedia(!this.reverse);
|
||||
}
|
||||
@ -564,6 +567,7 @@ export class AppMediaViewer {
|
||||
if(this.prevTargets.length < 20) {
|
||||
this.loadMoreMedia(this.reverse);
|
||||
}
|
||||
}
|
||||
|
||||
if(container.firstElementChild) {
|
||||
container.innerHTML = '';
|
||||
|
@ -47,7 +47,7 @@ export class AppMessagesManager {
|
||||
count: any,
|
||||
dialogs: any[]
|
||||
} = {count: null, dialogs: []};
|
||||
public pendingByRandomID: any = {};
|
||||
public pendingByRandomID: {[randomID: string]: [number, number]} = {};
|
||||
public pendingByMessageID: any = {};
|
||||
public pendingAfterMsgs: any = {};
|
||||
public pendingTopMsgs: any = {};
|
||||
@ -449,17 +449,18 @@ export class AppMessagesManager {
|
||||
this.pendingByRandomID[randomIDS] = [peerID, messageID];
|
||||
}
|
||||
|
||||
public sendFile(peerID: number, file: File | Blob | MTDocument, options: {
|
||||
isMedia?: boolean,
|
||||
replyToMsgID?: number,
|
||||
caption?: string,
|
||||
entities?: any[],
|
||||
width?: number,
|
||||
height?: number,
|
||||
objectURL?: string,
|
||||
isRoundMessage?: boolean,
|
||||
duration?: number
|
||||
} = {}) {
|
||||
public sendFile(peerID: number, file: File | Blob | MTDocument, options: Partial<{
|
||||
isMedia: boolean,
|
||||
replyToMsgID: number,
|
||||
caption: string,
|
||||
entities: any[],
|
||||
width: number,
|
||||
height: number,
|
||||
objectURL: string,
|
||||
isRoundMessage: boolean,
|
||||
duration: number,
|
||||
background: boolean
|
||||
}> = {}) {
|
||||
peerID = AppPeersManager.getPeerMigratedTo(peerID) || peerID;
|
||||
var messageID = this.tempID--;
|
||||
var randomID = [nextRandomInt(0xFFFFFFFF), nextRandomInt(0xFFFFFFFF)];
|
||||
@ -656,6 +657,8 @@ export class AppMessagesManager {
|
||||
|
||||
return apiManager.invokeApi('messages.sendMedia', {
|
||||
flags: flags,
|
||||
background: options.background,
|
||||
clear_draft: true,
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
media: inputMedia,
|
||||
message: caption,
|
||||
@ -683,9 +686,10 @@ export class AppMessagesManager {
|
||||
if(replyToMsgID) {
|
||||
flags |= 1;
|
||||
}
|
||||
if(asChannel) {
|
||||
flags |= 16;
|
||||
if(options.background) {
|
||||
flags |= 64;
|
||||
}
|
||||
flags |= 128; // clear_draft
|
||||
|
||||
if(isDocument) {
|
||||
let {id, access_hash, file_reference} = file as MTDocument;
|
||||
@ -777,6 +781,293 @@ export class AppMessagesManager {
|
||||
this.pendingByRandomID[randomIDS] = [peerID, messageID];
|
||||
}
|
||||
|
||||
public async sendAlbum(peerID: number, files: File[], options: Partial<{
|
||||
entities: any[],
|
||||
replyToMsgID: number,
|
||||
caption: string,
|
||||
sendFileDetails: Partial<{
|
||||
duration: number,
|
||||
width: number,
|
||||
height: number,
|
||||
objectURL: string,
|
||||
}>[]
|
||||
}> = {}) {
|
||||
peerID = AppPeersManager.getPeerMigratedTo(peerID) || peerID;
|
||||
let groupID: number;
|
||||
let historyStorage = this.historiesStorage[peerID] ?? (this.historiesStorage[peerID] = {count: null, history: [], pending: []});
|
||||
let flags = 0;
|
||||
let pFlags: any = {};
|
||||
let replyToMsgID = options.replyToMsgID;
|
||||
let isChannel = AppPeersManager.isChannel(peerID);
|
||||
let isMegagroup = isChannel && AppPeersManager.isMegagroup(peerID);
|
||||
let asChannel = isChannel && !isMegagroup ? true : false;
|
||||
|
||||
let caption = options.caption || '';
|
||||
|
||||
let date = tsNow(true) + ServerTimeManager.serverTimeOffset;
|
||||
|
||||
if(caption) {
|
||||
let entities = options.entities || [];
|
||||
caption = RichTextProcessor.parseMarkdown(caption, entities);
|
||||
}
|
||||
|
||||
console.log('AMM: sendAlbum', files, options);
|
||||
|
||||
let fromID = appUsersManager.getSelf().id;
|
||||
if(peerID != fromID) {
|
||||
pFlags.out = true;
|
||||
|
||||
if(!isChannel && !appUsersManager.isBot(peerID)) {
|
||||
pFlags.unread = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(replyToMsgID) {
|
||||
flags |= 1;
|
||||
}
|
||||
|
||||
if(asChannel) {
|
||||
fromID = 0;
|
||||
pFlags.post = true;
|
||||
} else {
|
||||
flags |= 128; // clear_draft
|
||||
}
|
||||
|
||||
let ids = files.map(() => this.tempID--).reverse();
|
||||
groupID = ids[ids.length - 1];
|
||||
let messages = files.map((file, idx) => {
|
||||
//let messageID = this.tempID--;
|
||||
//if(!groupID) groupID = messageID;
|
||||
let messageID = ids[idx];
|
||||
let randomID = [nextRandomInt(0xFFFFFFFF), nextRandomInt(0xFFFFFFFF)];
|
||||
let randomIDS = bigint(randomID[0]).shiftLeft(32).add(bigint(randomID[1])).toString();
|
||||
let preloader = new ProgressivePreloader(null, true);
|
||||
|
||||
let details = options.sendFileDetails[idx];
|
||||
|
||||
let media = {
|
||||
_: 'messageMediaPending',
|
||||
type: 'album',
|
||||
preloader: preloader,
|
||||
progress: {
|
||||
percent: 1,
|
||||
total: file.size,
|
||||
done: 0,
|
||||
cancel: () => {}
|
||||
},
|
||||
document: undefined as any,
|
||||
photo: undefined as any
|
||||
};
|
||||
|
||||
if(file.type.indexOf('video/') === 0) {
|
||||
let flags = 1;
|
||||
let videoAttribute = {
|
||||
_: 'documentAttributeVideo',
|
||||
flags: flags,
|
||||
pFlags: { // that's only for client, not going to telegram
|
||||
supports_streaming: true,
|
||||
round_message: false
|
||||
},
|
||||
round_message: false,
|
||||
supports_streaming: true,
|
||||
duration: details.duration,
|
||||
w: details.width,
|
||||
h: details.height
|
||||
};
|
||||
|
||||
let doc: any = {
|
||||
_: 'document',
|
||||
id: '' + messageID,
|
||||
attributes: [videoAttribute],
|
||||
downloaded: file.size,
|
||||
thumbs: [],
|
||||
mime_type: file.type,
|
||||
url: details.objectURL || '',
|
||||
size: file.size
|
||||
};
|
||||
|
||||
appDocsManager.saveDoc(doc);
|
||||
media.document = doc;
|
||||
} else {
|
||||
let photo: any = {
|
||||
_: 'photo',
|
||||
id: '' + messageID,
|
||||
sizes: [{
|
||||
_: 'photoSize',
|
||||
w: details.width,
|
||||
h: details.height,
|
||||
type: 'm',
|
||||
size: file.size
|
||||
} as MTPhotoSize],
|
||||
w: details.width,
|
||||
h: details.height,
|
||||
downloaded: file.size,
|
||||
url: details.objectURL || ''
|
||||
};
|
||||
|
||||
appPhotosManager.savePhoto(photo);
|
||||
media.photo = photo;
|
||||
}
|
||||
|
||||
preloader.preloader.onclick = () => {
|
||||
console.log('cancelling upload', media);
|
||||
appImManager.setTyping('sendMessageCancelAction');
|
||||
media.progress.cancel();
|
||||
};
|
||||
|
||||
let message = {
|
||||
_: 'message',
|
||||
id: messageID,
|
||||
from_id: fromID,
|
||||
grouped_id: groupID,
|
||||
to_id: AppPeersManager.getOutputPeer(peerID),
|
||||
flags: flags,
|
||||
pFlags: pFlags,
|
||||
date: date,
|
||||
message: caption,
|
||||
media: media,
|
||||
random_id: randomIDS,
|
||||
randomID: randomID,
|
||||
reply_to_msg_id: replyToMsgID,
|
||||
views: asChannel && 1,
|
||||
pending: true,
|
||||
error: false
|
||||
};
|
||||
|
||||
this.saveMessages([message]);
|
||||
historyStorage.pending.unshift(messageID);
|
||||
//$rootScope.$broadcast('history_append', {peerID: peerID, messageID: messageID, my: true});
|
||||
|
||||
this.pendingByRandomID[randomIDS] = [peerID, messageID];
|
||||
|
||||
return message;
|
||||
});
|
||||
|
||||
$rootScope.$broadcast('history_append', {peerID: peerID, messageID: messages[messages.length - 1].id, my: true});
|
||||
|
||||
let toggleError = (message: any, on: boolean) => {
|
||||
if(on) {
|
||||
message.error = true;
|
||||
} else {
|
||||
delete message.error;
|
||||
}
|
||||
|
||||
$rootScope.$broadcast('messages_pending');
|
||||
};
|
||||
|
||||
let uploaded = false,
|
||||
uploadPromise: ReturnType<typeof apiFileManager.uploadFile> = null;
|
||||
|
||||
let inputPeer = AppPeersManager.getInputPeerByID(peerID);
|
||||
let invoke = (multiMedia: any[]) => {
|
||||
appImManager.setTyping('sendMessageCancelAction');
|
||||
|
||||
return apiManager.invokeApi('messages.sendMultiMedia', {
|
||||
flags: flags,
|
||||
peer: inputPeer,
|
||||
multi_media: multiMedia,
|
||||
reply_to_msg_id: appMessagesIDsManager.getMessageLocalID(replyToMsgID)
|
||||
}).then((updates) => {
|
||||
apiUpdatesManager.processUpdateMessage(updates);
|
||||
}, (error) => {
|
||||
messages.forEach(message => toggleError(message, true));
|
||||
});
|
||||
};
|
||||
|
||||
let inputs: any[] = [];
|
||||
for(let i = 0, length = files.length; i < length; ++i) {
|
||||
let file = files[i];
|
||||
let message = messages[i];
|
||||
let media = message.media;
|
||||
let preloader = media.preloader;
|
||||
let actionName = file.type.indexOf('video/') === 0 ? 'sendMessageUploadVideoAction' : 'sendMessageUploadPhotoAction';
|
||||
let deferred = deferredPromise<void>();
|
||||
|
||||
await this.sendFilePromise;
|
||||
this.sendFilePromise = deferred;
|
||||
|
||||
if(!uploaded || message.error) {
|
||||
uploaded = false;
|
||||
uploadPromise = apiFileManager.uploadFile(file);
|
||||
}
|
||||
|
||||
uploadPromise.notify = (progress: {done: number, total: number}) => {
|
||||
console.log('upload progress', progress);
|
||||
media.progress.percent = Math.max(1, Math.floor(100 * progress.done / progress.total));
|
||||
appImManager.setTyping({_: actionName, progress: media.progress.percent | 0});
|
||||
preloader.setProgress(media.progress.percent); // lol, nice
|
||||
$rootScope.$broadcast('history_update', {peerID: peerID});
|
||||
};
|
||||
|
||||
await uploadPromise.then((inputFile) => {
|
||||
console.log('appMessagesManager: sendAlbum file uploaded:', inputFile);
|
||||
|
||||
let inputMedia: any;
|
||||
let details = options.sendFileDetails[i];
|
||||
if(details.duration) {
|
||||
inputMedia = {
|
||||
_: 'inputMediaUploadedDocument',
|
||||
flags: 0,
|
||||
file: inputFile,
|
||||
mime_type: file.type,
|
||||
attributes: [{
|
||||
_: 'documentAttributeVideo',
|
||||
flags: 2,
|
||||
supports_streaming: true,
|
||||
duration: details.duration,
|
||||
w: details.width,
|
||||
h: details.height
|
||||
}]
|
||||
};
|
||||
} else {
|
||||
inputMedia = {
|
||||
_: 'inputMediaUploadedPhoto',
|
||||
flags: 0,
|
||||
file: inputFile
|
||||
};
|
||||
}
|
||||
|
||||
return apiManager.invokeApi('messages.uploadMedia', {
|
||||
peer: inputPeer,
|
||||
media: inputMedia
|
||||
}).then(messageMedia => {
|
||||
let inputMedia: any;
|
||||
if(messageMedia.photo) {
|
||||
let photo = messageMedia.photo;
|
||||
appPhotosManager.savePhoto(photo);
|
||||
inputMedia = appPhotosManager.getInputByID(photo.id);
|
||||
} else {
|
||||
let doc = messageMedia.document;
|
||||
appDocsManager.saveDoc(doc);
|
||||
inputMedia = appDocsManager.getInputByID(doc.id);
|
||||
}
|
||||
|
||||
inputs.push({
|
||||
_: 'inputSingleMedia',
|
||||
flags: 0,
|
||||
media: inputMedia,
|
||||
random_id: message.randomID,
|
||||
message: caption,
|
||||
entities: []
|
||||
});
|
||||
|
||||
caption = ''; // only 1 caption for all inputs
|
||||
}, () => {
|
||||
toggleError(message, true);
|
||||
});
|
||||
}, () => {
|
||||
toggleError(message, true);
|
||||
});
|
||||
|
||||
console.log('appMessagesManager: sendAlbum uploadPromise.finally!');
|
||||
deferred.resolve();
|
||||
preloader.detach();
|
||||
}
|
||||
|
||||
uploaded = true;
|
||||
invoke(inputs);
|
||||
}
|
||||
|
||||
public cancelPendingMessage(randomID: string) {
|
||||
var pendingData = this.pendingByRandomID[randomID];
|
||||
|
||||
@ -2273,6 +2564,7 @@ export class AppMessagesManager {
|
||||
case 'updateMessageID': {
|
||||
var randomID = update.random_id;
|
||||
var pendingData = this.pendingByRandomID[randomID];
|
||||
console.log('AMM updateMessageID:', update, pendingData);
|
||||
if(pendingData) {
|
||||
var peerID: number = pendingData[0];
|
||||
var tempID = pendingData[1];
|
||||
|
@ -315,6 +315,21 @@ export class AppPhotosManager {
|
||||
return isObject(photoID) ? photoID : this.photos[photoID];
|
||||
}
|
||||
|
||||
public getInputByID(photoID: any) {
|
||||
let photo = this.getPhoto(photoID);
|
||||
return {
|
||||
_: 'inputMediaPhoto',
|
||||
flags: 0,
|
||||
id: {
|
||||
_: 'inputPhoto',
|
||||
id: photo.id,
|
||||
access_hash: photo.access_hash,
|
||||
file_reference: photo.file_reference
|
||||
},
|
||||
ttl_seconds: 0
|
||||
};
|
||||
}
|
||||
|
||||
public downloadPhoto(photoID: string) {
|
||||
var photo = this.photos[photoID];
|
||||
var ext = 'jpg';
|
||||
|
@ -171,7 +171,7 @@ class AppSidebarRight {
|
||||
|
||||
let targets = ids.map(id => ({element: this.mediaDivsByIDs[id], mid: id}));
|
||||
|
||||
appMediaViewer.openMedia(message, target, false, this.sidebarEl, targets.slice(idx + 1).reverse(), targets.slice(0, idx).reverse(), () => this.loadSidebarMedia(true));
|
||||
appMediaViewer.openMedia(message, target, false, this.sidebarEl, targets.slice(idx + 1).reverse(), targets.slice(0, idx).reverse(), true);
|
||||
});
|
||||
|
||||
this.profileElements.notificationsCheckbox.addEventListener('change', () => {
|
||||
|
@ -121,6 +121,7 @@ class ApiManagerProxy extends CryptoWorkerMethods {
|
||||
stopTime?: number,
|
||||
rawError?: any
|
||||
} = {}): Promise<any> {
|
||||
console.log('will invokeApi:', method, params, options);
|
||||
return this.performTaskWorker('invokeApi', method, params, options);
|
||||
}
|
||||
|
||||
|
@ -589,6 +589,10 @@ $chat-max-width: 696px;
|
||||
max-width: 100%;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
|
||||
img, video {
|
||||
border-radius: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1132,8 +1136,8 @@ $chat-max-width: 696px;
|
||||
}
|
||||
}
|
||||
|
||||
.audio-subtitle, .contact-number {
|
||||
color: #707579;
|
||||
.audio-subtitle, .contact-number, .audio-time {
|
||||
color: #707579 !important;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1376,6 +1380,16 @@ $chat-max-width: 696px;
|
||||
&.menu-open {
|
||||
color: $blue;
|
||||
}
|
||||
|
||||
.btn-menu {
|
||||
padding: 8px 0;
|
||||
right: -8px;
|
||||
bottom: calc(100% + 16px);
|
||||
|
||||
> div {
|
||||
padding: 0 38px 0 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> div {
|
||||
|
@ -1,7 +1,7 @@
|
||||
.emoji-dropdown {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: calc(-420px + -0.75rem);
|
||||
top: calc(-420px + -4px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 420px;
|
||||
|
@ -4,7 +4,7 @@
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, .9);
|
||||
background: rgba(0, 0, 0, .88);
|
||||
/* color: $darkgrey; */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
52
src/scss/partials/popups/_editAvatar.scss
Normal file
52
src/scss/partials/popups/_editAvatar.scss
Normal file
@ -0,0 +1,52 @@
|
||||
.popup-avatar {
|
||||
$parent: ".popup";
|
||||
|
||||
#{$parent} {
|
||||
&-container {
|
||||
max-width: 600px;
|
||||
//max-height: 600px;
|
||||
padding: 15px 16px 16px 24px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
> button {
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
&-close {
|
||||
font-size: 1.5rem;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
&-header {
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1.25rem;
|
||||
text-align: left;
|
||||
margin: 0;
|
||||
margin-left: 2rem;
|
||||
}
|
||||
|
||||
.crop {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
padding: 24px 54px 46px 46px;
|
||||
border-radius: $border-radius;
|
||||
|
||||
> img {
|
||||
display: none;
|
||||
}
|
||||
|
||||
img {
|
||||
//height: 100%;
|
||||
border-radius: $border-radius;
|
||||
}
|
||||
}
|
||||
}
|
150
src/scss/partials/popups/_mediaAttacher.scss
Normal file
150
src/scss/partials/popups/_mediaAttacher.scss
Normal file
@ -0,0 +1,150 @@
|
||||
.popup-send-photo {
|
||||
$parent: ".popup";
|
||||
|
||||
#{$parent} {
|
||||
&-container {
|
||||
width: 420px;
|
||||
max-width: 420px;
|
||||
overflow: hidden;
|
||||
/* padding: 12px 20px 50px; */
|
||||
padding: 12px 20px 32.5px;
|
||||
|
||||
&.is-media:not(.is-album) {
|
||||
/* max-height: 425px; */
|
||||
|
||||
#{$parent}-photo {
|
||||
max-height: 320px;
|
||||
margin: 0 auto;
|
||||
padding-bottom: 8px;
|
||||
|
||||
img {
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
> div {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.is-album {
|
||||
#{$parent}-photo {
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
|
||||
> div {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.is-document, &.is-album {
|
||||
#{$parent}-photo {
|
||||
img, video {
|
||||
object-fit: cover;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-header {
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 9px;
|
||||
|
||||
.btn-primary {
|
||||
width: 79px;
|
||||
height: 36px;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
padding: 0;
|
||||
padding-top: 2px;
|
||||
margin-top: -3px;
|
||||
border-radius: $border-radius-medium;
|
||||
}
|
||||
}
|
||||
|
||||
&-close {
|
||||
font-size: 1.5rem;
|
||||
margin: -1px 0 0 -4px;
|
||||
}
|
||||
|
||||
&-title {
|
||||
flex: 1;
|
||||
padding: 0 2rem 0 1.5rem;
|
||||
margin: 0;
|
||||
margin-top: -3px;
|
||||
font-size: 1.25rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
&-photo {
|
||||
max-width: 380px;
|
||||
//display: flex;
|
||||
overflow: hidden;
|
||||
//justify-content: center;
|
||||
width: fit-content;
|
||||
border-radius: $border-radius-medium;
|
||||
/* align-items: center; */
|
||||
|
||||
.document {
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
cursor: default;
|
||||
padding-left: 3.75rem;
|
||||
height: 4.5rem;
|
||||
|
||||
&-name {
|
||||
font-weight: normal;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
&-ico {
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
font-size: 16px;
|
||||
font-weight: normal;
|
||||
line-height: 11px;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
/* &.photo {
|
||||
.document-ico {
|
||||
border-radius: $border-radius;
|
||||
}
|
||||
} */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input-field {
|
||||
margin-top: 1rem;
|
||||
|
||||
&::placeholder {
|
||||
color: #a2acb4;
|
||||
}
|
||||
|
||||
input {
|
||||
height: 54px;
|
||||
font-size: 1rem;
|
||||
padding: 0 15px;
|
||||
border-radius: $border-radius-medium;
|
||||
|
||||
&:focus {
|
||||
padding: 0 14.5px;
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: inherit;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
80
src/scss/partials/popups/_popup.scss
Normal file
80
src/scss/partials/popups/_popup.scss
Normal file
@ -0,0 +1,80 @@
|
||||
.popup {
|
||||
position: fixed!important;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
max-width: none;
|
||||
width: 100%;
|
||||
z-index: 3;
|
||||
background-color: rgba(0, 0, 0, .3);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-shadow: none;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
-webkit-transition: opacity 0.3s 0s, visibility 0s 0.3s;
|
||||
-moz-transition: opacity 0.3s 0s, visibility 0s 0.3s;
|
||||
transition: opacity 0.3s 0s, visibility 0s 0.3s;
|
||||
overflow: auto;
|
||||
/* text-align: center; */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
&.active {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
-webkit-transition: opacity 0.3s 0s, visibility 0s 0s;
|
||||
-moz-transition: opacity 0.3s 0s, visibility 0s 0s;
|
||||
transition: opacity 0.3s 0s, visibility 0s 0s;
|
||||
|
||||
.popup-container {
|
||||
-webkit-transform: translateY(0);
|
||||
-moz-transform: translateY(0);
|
||||
-ms-transform: translateY(0);
|
||||
-o-transform: translateY(0);
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
&-container {
|
||||
position: relative;
|
||||
/* max-width: 400px; */
|
||||
border-radius: $border-radius-medium;
|
||||
background-color: #fff;
|
||||
padding: 1rem;
|
||||
-webkit-transform: translateY(-40px);
|
||||
-moz-transform: translateY(-40px);
|
||||
-ms-transform: translateY(-40px);
|
||||
-o-transform: translateY(-40px);
|
||||
transform: translateY(-40px);
|
||||
backface-visibility: hidden;
|
||||
-webkit-backface-visibility: hidden;
|
||||
-webkit-transition-property: -webkit-transform;
|
||||
-moz-transition-property: -moz-transform;
|
||||
transition-property: transform;
|
||||
-webkit-transition-duration: 0.3s;
|
||||
-moz-transition-duration: 0.3s;
|
||||
transition-duration: 0.3s;
|
||||
}
|
||||
|
||||
&-close {
|
||||
cursor: pointer;
|
||||
color: $color-gray;
|
||||
z-index: 3;
|
||||
text-align: center;
|
||||
justify-self: center;
|
||||
line-height: 1;
|
||||
transition: .2s;
|
||||
|
||||
&:hover {
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
&-header {
|
||||
display: flex;
|
||||
margin-bottom: 2rem;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
@ -43,6 +43,10 @@ $large-screen: 1680px;
|
||||
@import "partials/emojiDropdown";
|
||||
@import "partials/scrollable";
|
||||
|
||||
@import "partials/popups/popup";
|
||||
@import "partials/popups/editAvatar";
|
||||
@import "partials/popups/mediaAttacher";
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
@ -1156,81 +1160,6 @@ img.emoji {
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.popup {
|
||||
position: fixed!important;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
max-width: none;
|
||||
width: 100%;
|
||||
z-index: 3;
|
||||
background-color: rgba(0, 0, 0, .35);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-shadow: none;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
-webkit-transition: opacity 0.3s 0s, visibility 0s 0.3s;
|
||||
-moz-transition: opacity 0.3s 0s, visibility 0s 0.3s;
|
||||
transition: opacity 0.3s 0s, visibility 0s 0.3s;
|
||||
overflow: auto;
|
||||
/* text-align: center; */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.popup.active {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
-webkit-transition: opacity 0.3s 0s, visibility 0s 0s;
|
||||
-moz-transition: opacity 0.3s 0s, visibility 0s 0s;
|
||||
transition: opacity 0.3s 0s, visibility 0s 0s;
|
||||
}
|
||||
|
||||
.popup-container {
|
||||
position: relative;
|
||||
/* max-width: 400px; */
|
||||
border-radius: $border-radius;
|
||||
background-color: #fff;
|
||||
padding: 1rem;
|
||||
-webkit-transform: translateY(-40px);
|
||||
-moz-transform: translateY(-40px);
|
||||
-ms-transform: translateY(-40px);
|
||||
-o-transform: translateY(-40px);
|
||||
transform: translateY(-40px);
|
||||
backface-visibility: hidden;
|
||||
-webkit-backface-visibility: hidden;
|
||||
-webkit-transition-property: -webkit-transform;
|
||||
-moz-transition-property: -moz-transform;
|
||||
transition-property: transform;
|
||||
-webkit-transition-duration: 0.3s;
|
||||
-moz-transition-duration: 0.3s;
|
||||
transition-duration: 0.3s;
|
||||
}
|
||||
|
||||
span.popup-close {
|
||||
cursor: pointer;
|
||||
color: $color-gray;
|
||||
z-index: 3;
|
||||
text-align: center;
|
||||
justify-self: center;
|
||||
line-height: 1;
|
||||
transition: .2s;
|
||||
|
||||
&:hover {
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
.popup.active .popup-container {
|
||||
-webkit-transform: translateY(0);
|
||||
-moz-transform: translateY(0);
|
||||
-ms-transform: translateY(0);
|
||||
-o-transform: translateY(0);
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.btn-circle {
|
||||
border-radius: 50%;
|
||||
height: 54px;
|
||||
@ -1241,66 +1170,6 @@ span.popup-close {
|
||||
}
|
||||
}
|
||||
|
||||
.popup-header {
|
||||
/* display: grid;
|
||||
align-items: center;
|
||||
grid-template-columns: 9.5% 86.5%;
|
||||
justify-content: space-between; */
|
||||
display: flex;
|
||||
margin-bottom: 2rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.popup-avatar {
|
||||
.popup-container {
|
||||
max-width: 600px;
|
||||
//max-height: 600px;
|
||||
border-radius: $border-radius-medium;
|
||||
padding: 15px 16px 16px 24px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
> button {
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-close {
|
||||
font-size: 1.5rem;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.popup-header {
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1.25rem;
|
||||
text-align: left;
|
||||
margin: 0;
|
||||
margin-left: 2rem;
|
||||
}
|
||||
|
||||
.crop {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
padding: 24px 54px 46px 46px;
|
||||
border-radius: $border-radius;
|
||||
|
||||
> img {
|
||||
display: none;
|
||||
}
|
||||
|
||||
img {
|
||||
//height: 100%;
|
||||
border-radius: $border-radius;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.overlay::selection {
|
||||
background: transparent;
|
||||
}
|
||||
@ -1487,105 +1356,6 @@ span.popup-close {
|
||||
justify-content: flex-start!important;
|
||||
}
|
||||
|
||||
.popup-send-photo {
|
||||
.popup-container {
|
||||
width: 420px;
|
||||
max-width: 420px;
|
||||
max-height: 425px;
|
||||
overflow: hidden;
|
||||
/* padding: 12px 20px 50px; */
|
||||
padding: 12px 20px 32.5px;
|
||||
border-radius: $border-radius-medium;
|
||||
}
|
||||
|
||||
.popup-header {
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12.5px;
|
||||
|
||||
.popup-close {
|
||||
font-size: 1.5rem;
|
||||
margin-left: .5rem;
|
||||
}
|
||||
|
||||
.popup-title {
|
||||
flex: 1;
|
||||
padding: 0 2rem;
|
||||
margin: 0;
|
||||
font-size: 1.35rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
width: 80px;
|
||||
height: 35px;
|
||||
font-size: 1rem;
|
||||
padding: 0;
|
||||
border-radius: $border-radius-medium;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-photo {
|
||||
max-width: 378px;
|
||||
max-height: 256px;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
justify-content: center;
|
||||
width: fit-content;
|
||||
border-radius: $border-radius-medium;
|
||||
margin: 0 auto;
|
||||
/* align-items: center; */
|
||||
|
||||
&.is-document {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.document {
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
cursor: default;
|
||||
|
||||
.document-name {
|
||||
font-weight: normal;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* &.photo {
|
||||
.document-ico {
|
||||
border-radius: $border-radius;
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
img {
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
.input-field {
|
||||
margin-top: 25px;
|
||||
|
||||
input {
|
||||
height: 55px;
|
||||
font-size: 1.15rem;
|
||||
padding: 0 15px;
|
||||
border-radius: $border-radius-medium;
|
||||
|
||||
&:focus {
|
||||
padding: 0 14.5px;
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: inherit;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.page-chats {
|
||||
/* display: grid; */
|
||||
/* grid-template-columns: 25% 50%; */
|
||||
|
Loading…
Reference in New Issue
Block a user