send message status & added global search contacts & set any peer
This commit is contained in:
parent
04123d0ba6
commit
55833f2489
@ -1,6 +1,6 @@
|
||||
import { AppImManager } from "../lib/appManagers/appImManager";
|
||||
import { AppMessagesManager } from "../lib/appManagers/appMessagesManager";
|
||||
import { LazyLoadQueue, horizontalMenu, MTDocument, wrapSticker } from "./misc";
|
||||
import { horizontalMenu } from "./misc";
|
||||
import lottieLoader from "../lib/lottieLoader";
|
||||
import Scrollable from "./scrollable";
|
||||
import { findUpTag, whichChild } from "../lib/utils";
|
||||
@ -8,6 +8,8 @@ import { RichTextProcessor } from "../lib/richtextprocessor";
|
||||
import appStickersManager, { MTStickerSet } from "../lib/appManagers/appStickersManager";
|
||||
import apiManager from '../lib/mtproto/apiManager';
|
||||
import CryptoWorker from '../lib/crypto/cryptoworker';
|
||||
import LazyLoadQueue from "./lazyLoadQueue";
|
||||
import { MTDocument, wrapSticker } from "./wrappers";
|
||||
|
||||
export const EMOTICONSSTICKERGROUP = 'emoticons-dropdown';
|
||||
|
||||
|
44
src/components/lazyLoadQueue.ts
Normal file
44
src/components/lazyLoadQueue.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { isElementInViewport } from "../lib/utils";
|
||||
|
||||
export default class LazyLoadQueue {
|
||||
private lazyLoadMedia: Array<{div: HTMLDivElement, load: () => Promise<void>}> = [];
|
||||
|
||||
public check(id?: number) {
|
||||
/* let length = this.lazyLoadMedia.length;
|
||||
for(let i = length - 1; i >= 0; --i) {
|
||||
let {div, load} = this.lazyLoadMedia[i];
|
||||
|
||||
if(isElementInViewport(div)) {
|
||||
console.log('will load div:', div);
|
||||
load();
|
||||
this.lazyLoadMedia.splice(i, 1);
|
||||
}
|
||||
} */
|
||||
if(id !== undefined) {
|
||||
let {div, load} = this.lazyLoadMedia[id];
|
||||
if(isElementInViewport(div)) {
|
||||
//console.log('will load div by id:', div, div.getBoundingClientRect());
|
||||
load();
|
||||
this.lazyLoadMedia.splice(id, 1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.lazyLoadMedia = this.lazyLoadMedia.filter(({div, load}) => {
|
||||
if(isElementInViewport(div)) {
|
||||
//console.log('will load div:', div, div.getBoundingClientRect());
|
||||
load();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public push(el: {div: HTMLDivElement, load: () => Promise<void>}) {
|
||||
let id = this.lazyLoadMedia.push(el) - 1;
|
||||
|
||||
this.check(id);
|
||||
}
|
||||
}
|
@ -1,47 +1,5 @@
|
||||
import { MTProto } from "../lib/mtproto/mtproto";
|
||||
import { formatBytes, whichChild, isElementInViewport, isInDOM, findUpTag } from "../lib/utils";
|
||||
import appPhotosManager from '../lib/appManagers/appPhotosManager';
|
||||
import CryptoWorker from '../lib/crypto/cryptoworker';
|
||||
import LottieLoader from '../lib/lottieLoader';
|
||||
import appStickersManager from "../lib/appManagers/appStickersManager";
|
||||
import appDocsManager from "../lib/appManagers/appDocsManager";
|
||||
import {AppImManager} from "../lib/appManagers/appImManager";
|
||||
import {AppMediaViewer} from '../lib/appManagers/appMediaViewer';
|
||||
import { RichTextProcessor } from "../lib/richtextprocessor";
|
||||
import lottieLoader from "../lib/lottieLoader";
|
||||
|
||||
export type MTDocument = {
|
||||
_: 'document',
|
||||
pFlags: any,
|
||||
flags: number,
|
||||
id: string,
|
||||
access_hash: string,
|
||||
file_reference: Uint8Array | number[],
|
||||
date: number,
|
||||
mime_type: string,
|
||||
size: number,
|
||||
thumbs: MTPhotoSize[],
|
||||
dc_id: number,
|
||||
attributes: any[],
|
||||
|
||||
type?: string,
|
||||
h?: number,
|
||||
w?: number,
|
||||
file_name?: string,
|
||||
file?: File
|
||||
};
|
||||
|
||||
export type MTPhotoSize = {
|
||||
_: string,
|
||||
w?: number,
|
||||
h?: number,
|
||||
size?: number,
|
||||
type?: string, // i, m, x, y, w by asc
|
||||
location?: any,
|
||||
bytes?: Uint8Array, // if type == 'i'
|
||||
|
||||
preloaded?: boolean // custom added
|
||||
};
|
||||
import apiManager from "../lib/mtproto/apiManager";
|
||||
import { whichChild, isElementInViewport, isInDOM, findUpTag } from "../lib/utils";
|
||||
|
||||
let onRippleClick = function(this: HTMLElement, e: MouseEvent) {
|
||||
var $circle = this.firstElementChild as HTMLSpanElement;//this.querySelector('.c-ripple__circle') as HTMLSpanElement;
|
||||
@ -103,580 +61,6 @@ export function putPreloader(elem: Element) {
|
||||
elem.innerHTML += html;
|
||||
}
|
||||
|
||||
export class ProgressivePreloader {
|
||||
public preloader: HTMLDivElement = null;
|
||||
private circle: SVGCircleElement = null;
|
||||
private progress = 0;
|
||||
constructor(elem?: Element, private cancelable = true) {
|
||||
this.preloader = document.createElement('div');
|
||||
this.preloader.classList.add('preloader-container');
|
||||
|
||||
this.preloader.innerHTML = `
|
||||
<div class="you-spin-me-round">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="preloader-circular" viewBox="25 25 50 50">
|
||||
<circle class="preloader-path-new" cx="50" cy="50" r="23" fill="none" stroke-miterlimit="10"/>
|
||||
</svg>
|
||||
</div>`;
|
||||
|
||||
if(cancelable) {
|
||||
this.preloader.innerHTML += `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="preloader-close" viewBox="0 0 20 20">
|
||||
<line x1="0" y1="20" x2="20" y2="0" stroke-width="2" stroke-linecap="round"></line>
|
||||
<line x1="0" y1="0" x2="20" y2="20" stroke-width="2" stroke-linecap="round"></line>
|
||||
</svg>`;
|
||||
} else {
|
||||
this.preloader.classList.add('preloader-swing');
|
||||
}
|
||||
|
||||
this.circle = this.preloader.firstElementChild.firstElementChild.firstElementChild as SVGCircleElement;
|
||||
|
||||
if(elem) {
|
||||
this.attach(elem);
|
||||
}
|
||||
}
|
||||
|
||||
public attach(elem: Element, reset = true) {
|
||||
if(this.cancelable && reset) {
|
||||
this.setProgress(0);
|
||||
}
|
||||
|
||||
elem.append(this.preloader);
|
||||
/* let isIn = isInDOM(this.preloader);
|
||||
|
||||
if(isIn && this.progress != this.defaultProgress) {
|
||||
this.setProgress(this.defaultProgress);
|
||||
}
|
||||
|
||||
elem.append(this.preloader);
|
||||
|
||||
if(!isIn && this.progress != this.defaultProgress) {
|
||||
this.setProgress(this.defaultProgress);
|
||||
} */
|
||||
}
|
||||
|
||||
public detach() {
|
||||
if(this.preloader.parentElement) {
|
||||
this.preloader.parentElement.removeChild(this.preloader);
|
||||
}
|
||||
}
|
||||
|
||||
public setProgress(percents: number) {
|
||||
this.progress = percents;
|
||||
|
||||
if(!isInDOM(this.circle)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(percents == 0) {
|
||||
this.circle.style.strokeDasharray = '';
|
||||
return;
|
||||
}
|
||||
|
||||
let totalLength = this.circle.getTotalLength();
|
||||
console.log('setProgress', (percents / 100 * totalLength));
|
||||
this.circle.style.strokeDasharray = '' + Math.max(5, percents / 100 * totalLength) + ', 200';
|
||||
}
|
||||
}
|
||||
|
||||
export class LazyLoadQueue {
|
||||
private lazyLoadMedia: Array<{div: HTMLDivElement, load: () => Promise<void>}> = [];
|
||||
|
||||
public check(id?: number) {
|
||||
/* let length = this.lazyLoadMedia.length;
|
||||
for(let i = length - 1; i >= 0; --i) {
|
||||
let {div, load} = this.lazyLoadMedia[i];
|
||||
|
||||
if(isElementInViewport(div)) {
|
||||
console.log('will load div:', div);
|
||||
load();
|
||||
this.lazyLoadMedia.splice(i, 1);
|
||||
}
|
||||
} */
|
||||
if(id !== undefined) {
|
||||
let {div, load} = this.lazyLoadMedia[id];
|
||||
if(isElementInViewport(div)) {
|
||||
//console.log('will load div by id:', div, div.getBoundingClientRect());
|
||||
load();
|
||||
this.lazyLoadMedia.splice(id, 1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.lazyLoadMedia = this.lazyLoadMedia.filter(({div, load}) => {
|
||||
if(isElementInViewport(div)) {
|
||||
//console.log('will load div:', div, div.getBoundingClientRect());
|
||||
load();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public push(el: {div: HTMLDivElement, load: () => Promise<void>}) {
|
||||
let id = this.lazyLoadMedia.push(el) - 1;
|
||||
|
||||
this.check(id);
|
||||
}
|
||||
}
|
||||
|
||||
export function wrapVideo(this: any, doc: MTDocument, container: HTMLDivElement, message: any, justLoader = true, preloader?: ProgressivePreloader, controls = true) {
|
||||
if(!container.firstElementChild || container.firstElementChild.tagName != 'IMG') {
|
||||
let size = appPhotosManager.setAttachmentSize(doc, container);
|
||||
}
|
||||
|
||||
let peerID = this.peerID ? this.peerID : this.currentMessageID;
|
||||
|
||||
//container.classList.add('video');
|
||||
|
||||
let img = container.firstElementChild as HTMLImageElement || new Image();
|
||||
img.setAttribute('message-id', '' + message.id);
|
||||
|
||||
if(!container.contains(img)) {
|
||||
container.append(img);
|
||||
}
|
||||
|
||||
//return Promise.resolve();
|
||||
|
||||
if(!preloader) {
|
||||
preloader = new ProgressivePreloader(container, false);
|
||||
}
|
||||
|
||||
let loadVideo = () => {
|
||||
let promise = appDocsManager.downloadDoc(doc);
|
||||
|
||||
/* promise.notify = (details: {done: number, total: number}) => {
|
||||
console.log('doc download', promise, details);
|
||||
preloader.setProgress(details.done);
|
||||
}; */
|
||||
|
||||
return promise.then(blob => {
|
||||
if((this.peerID ? this.peerID : this.currentMessageID) != peerID) {
|
||||
this.log.warn('peer changed');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('loaded doc:', doc, blob, container);
|
||||
|
||||
let video = document.createElement('video');
|
||||
video.loop = controls;
|
||||
video.autoplay = controls;
|
||||
|
||||
if(!justLoader) {
|
||||
video.controls = controls;
|
||||
} else {
|
||||
video.volume = 0;
|
||||
}
|
||||
|
||||
video.setAttribute('message-id', '' + message.id);
|
||||
|
||||
let source = document.createElement('source');
|
||||
//source.src = doc.url;
|
||||
source.src = URL.createObjectURL(blob);
|
||||
source.type = doc.mime_type;
|
||||
|
||||
if(img && container.contains(img)) {
|
||||
container.removeChild(img);
|
||||
}
|
||||
|
||||
video.append(source);
|
||||
container.append(video);
|
||||
|
||||
//container.style.width = '';
|
||||
//container.style.height = '';
|
||||
|
||||
preloader.detach();
|
||||
});
|
||||
};
|
||||
|
||||
if(doc.type == 'gif' || true) { // extra fix
|
||||
return this.peerID ? this.loadMediaQueuePush(loadVideo) : loadVideo();
|
||||
} else { // if video
|
||||
let load = () => appPhotosManager.preloadPhoto(doc).then((blob) => {
|
||||
if((this.peerID ? this.peerID : this.currentMessageID) != peerID) {
|
||||
this.log.warn('peer changed');
|
||||
return;
|
||||
}
|
||||
|
||||
img.src = URL.createObjectURL(blob);
|
||||
|
||||
/* image.style.height = doc.h + 'px';
|
||||
image.style.width = doc.w + 'px'; */
|
||||
|
||||
/* if(justLoader) { // extra fix
|
||||
justLoader = false;
|
||||
controls = false;
|
||||
} */
|
||||
|
||||
if(!justLoader) {
|
||||
return loadVideo();
|
||||
} else {
|
||||
container.style.width = '';
|
||||
container.style.height = '';
|
||||
preloader.detach();
|
||||
}
|
||||
});
|
||||
|
||||
return this.peerID ? this.loadMediaQueuePush(load) : load();
|
||||
}
|
||||
}
|
||||
|
||||
export function wrapDocument(doc: MTDocument, withTime = false): HTMLDivElement {
|
||||
let docDiv = document.createElement('div');
|
||||
docDiv.classList.add('document');
|
||||
|
||||
let iconDiv = document.createElement('div');
|
||||
iconDiv.classList.add('tgico-document');
|
||||
|
||||
let extSplitted = doc.file_name ? doc.file_name.split('.') : '';
|
||||
let ext = '';
|
||||
ext = extSplitted.length > 1 && Array.isArray(extSplitted) ? extSplitted.pop().toLowerCase() : 'file';
|
||||
|
||||
let ext2 = ext;
|
||||
if(doc.type == 'photo') {
|
||||
docDiv.classList.add('photo');
|
||||
ext2 = `<img src="${URL.createObjectURL(doc.file)}">`;
|
||||
}
|
||||
|
||||
let fileName = doc.file_name || 'Unknown.file';
|
||||
let size = formatBytes(doc.size);
|
||||
|
||||
if(withTime) {
|
||||
let months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
||||
let date = new Date(doc.date * 1000);
|
||||
|
||||
size += ' · ' + months[date.getMonth()] + ' ' + date.getDate() + ', ' + date.getFullYear()
|
||||
+ ' at ' + date.getHours() + ':' + ('0' + date.getMinutes()).slice(-2);
|
||||
}
|
||||
|
||||
docDiv.innerHTML = `
|
||||
<div class="document-ico ext-${ext}">${ext2}</div>
|
||||
<div class="document-name">${fileName}</div>
|
||||
<div class="document-size">${size}</div>
|
||||
`;
|
||||
|
||||
return docDiv;
|
||||
}
|
||||
|
||||
export function scrollable(el: HTMLDivElement, x = false, y = true) {
|
||||
let container = document.createElement('div');
|
||||
container.classList.add('scrollable');
|
||||
if(x) container.classList.add('scrollable-x');
|
||||
if(y) container.classList.add('scrollable-y');
|
||||
|
||||
let type = x ? 'width' : 'height';
|
||||
let side = x ? 'left' : 'top';
|
||||
let scrollType = x ? 'scrollWidth' : 'scrollHeight';
|
||||
let scrollSide = x ? 'scrollLeft' : 'scrollTop';
|
||||
|
||||
container.addEventListener('mouseover', () => {
|
||||
resize();
|
||||
/* container.classList.add('active');
|
||||
|
||||
container.addEventListener('mouseout', () => {
|
||||
container.classList.remove('active');
|
||||
}, {once: true}); */
|
||||
});
|
||||
|
||||
let thumb = document.createElement('div');
|
||||
thumb.className = 'scrollbar-thumb';
|
||||
|
||||
// @ts-ignore
|
||||
thumb.style[type] = '30px';
|
||||
|
||||
let resize = () => {
|
||||
// @ts-ignore
|
||||
scrollSize = container[scrollType];
|
||||
|
||||
let rect = container.getBoundingClientRect();
|
||||
|
||||
// @ts-ignore
|
||||
size = rect[type];
|
||||
|
||||
if(!size || size == scrollSize) {
|
||||
thumbSize = 0;
|
||||
|
||||
// @ts-ignore
|
||||
thumb.style[type] = thumbSize + 'px';
|
||||
return;
|
||||
}
|
||||
//if(!height) return;
|
||||
|
||||
let divider = scrollSize / size / 0.5;
|
||||
thumbSize = size / divider;
|
||||
|
||||
if(thumbSize < 20) thumbSize = 20;
|
||||
|
||||
// @ts-ignore
|
||||
thumb.style[type] = thumbSize + 'px';
|
||||
|
||||
// @ts-ignore
|
||||
//console.log('onresize', thumb.style[type], thumbHeight, height);
|
||||
};
|
||||
|
||||
let scrollSize = -1;
|
||||
let size = 0;
|
||||
let thumbSize = 0;
|
||||
window.addEventListener('resize', resize);
|
||||
//container.addEventListener('DOMNodeInserted', resize);
|
||||
|
||||
let hiddenElements: {
|
||||
up: Element[],
|
||||
down: Element[]
|
||||
} = {
|
||||
up: [],
|
||||
down: []
|
||||
};
|
||||
|
||||
let paddings = {up: 0, down: 0};
|
||||
|
||||
let paddingTopDiv = document.createElement('div');
|
||||
paddingTopDiv.classList.add('scroll-padding');
|
||||
let paddingBottomDiv = document.createElement('div');
|
||||
paddingBottomDiv.classList.add('scroll-padding');
|
||||
|
||||
let onScroll = (e: Event) => {
|
||||
// @ts-ignore
|
||||
//let st = container[scrollSide];
|
||||
|
||||
// @ts-ignore
|
||||
if(container[scrollType] != scrollSize || thumbSize == 0) {
|
||||
resize();
|
||||
}
|
||||
|
||||
//let splitUp = container.querySelector('ul');
|
||||
let splitUp = container.children[1];
|
||||
let children = Array.from(splitUp.children) as HTMLElement[];
|
||||
let firstVisible = -1, lastVisible = -1;
|
||||
let length = children.length;
|
||||
for(let i = 0; i < length; ++i) {
|
||||
let child = children[i];
|
||||
if(isElementInViewport(child)) {
|
||||
if(firstVisible < 0) firstVisible = i;
|
||||
lastVisible = i;
|
||||
}
|
||||
}
|
||||
|
||||
if(firstVisible > 0) {
|
||||
let sliced = children.slice(0, firstVisible);
|
||||
|
||||
for(let child of sliced) {
|
||||
paddings.up += child.scrollHeight;
|
||||
hiddenElements.up.push(child);
|
||||
child.parentElement.removeChild(child);
|
||||
}
|
||||
|
||||
//console.log('sliced up', sliced.length);
|
||||
|
||||
//sliced.forEach(child => child.style.display = 'none');
|
||||
paddingTopDiv.style.height = paddings.up + 'px';
|
||||
//console.log('onscroll need to add padding: ', paddings.up);
|
||||
} else if(hiddenElements.up.length) {
|
||||
while(isElementInViewport(paddingTopDiv) && paddings.up) {
|
||||
let child = hiddenElements.up.pop();
|
||||
|
||||
splitUp.prepend(child);
|
||||
|
||||
paddings.up -= child.scrollHeight;
|
||||
paddingTopDiv.style.height = paddings.up + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
if(lastVisible < (length - 1)) {
|
||||
let sliced = children.slice(lastVisible + 1).reverse();
|
||||
|
||||
for(let child of sliced) {
|
||||
paddings.down += child.scrollHeight;
|
||||
hiddenElements.down.unshift(child);
|
||||
child.parentElement.removeChild(child);
|
||||
}
|
||||
|
||||
//console.log('onscroll sliced down', sliced.length);
|
||||
|
||||
//sliced.forEach(child => child.style.display = 'none');
|
||||
paddingBottomDiv.style.height = paddings.down + 'px';
|
||||
//console.log('onscroll need to add padding: ', paddings.up);
|
||||
} else if(hiddenElements.down.length) {
|
||||
while(isElementInViewport(paddingBottomDiv) && paddings.down) {
|
||||
let child = hiddenElements.down.shift();
|
||||
|
||||
splitUp.append(child);
|
||||
|
||||
paddings.down -= child.scrollHeight;
|
||||
paddingBottomDiv.style.height = paddings.down + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
//console.log('onscroll', container, firstVisible, lastVisible, hiddenElements);
|
||||
|
||||
// @ts-ignore
|
||||
let value = container[scrollSide] / (scrollSize - size) * 100;
|
||||
let maxValue = 100 - (thumbSize / size * 100);
|
||||
|
||||
//console.log('onscroll', container.scrollHeight, thumbHeight, height, value, maxValue);
|
||||
|
||||
// @ts-ignore
|
||||
thumb.style[side] = (value >= maxValue ? maxValue : value) + '%';
|
||||
|
||||
//lastScrollPos = st;
|
||||
};
|
||||
|
||||
let lastScrollPos = 0;
|
||||
container.addEventListener('scroll', onScroll);
|
||||
|
||||
container.append(paddingTopDiv);
|
||||
Array.from(el.children).forEach(c => container.append(c));
|
||||
container.append(paddingBottomDiv);
|
||||
|
||||
el.append(container);//container.append(el);
|
||||
container.parentElement.append(thumb);
|
||||
resize();
|
||||
return {container, hiddenElements, onScroll};
|
||||
}
|
||||
|
||||
export function wrapPhoto(this: AppImManager, photo: any, message: any, container: HTMLDivElement) {
|
||||
//container.classList.add('photo');
|
||||
|
||||
let peerID = this.peerID;
|
||||
|
||||
let size = appPhotosManager.setAttachmentSize(photo.id, container);
|
||||
let image = container.firstElementChild as HTMLImageElement || new Image();
|
||||
//let size = appPhotosManager.setAttachmentSize(photo.id, image);
|
||||
image.setAttribute('message-id', message.mid);
|
||||
|
||||
if(!container.contains(image)) {
|
||||
container.append(image);
|
||||
}
|
||||
|
||||
let preloader = new ProgressivePreloader(container, false);
|
||||
|
||||
let load = () => appPhotosManager.preloadPhoto(photo.id, size).then((blob) => {
|
||||
if(this.peerID != peerID) {
|
||||
this.log.warn('peer changed');
|
||||
return;
|
||||
}
|
||||
|
||||
image.src = URL.createObjectURL(blob);
|
||||
|
||||
preloader.detach();
|
||||
|
||||
//image.style.width = '';
|
||||
//image.style.height = '';
|
||||
//container.style.width = '';
|
||||
//container.style.height = '';
|
||||
});
|
||||
|
||||
console.log('wrapPhoto', load, container, image);
|
||||
|
||||
return this.loadMediaQueue ? this.loadMediaQueuePush(load) : load();
|
||||
}
|
||||
|
||||
export function wrapSticker(doc: MTDocument, div: HTMLDivElement, middleware?: () => boolean, lazyLoadQueue?: LazyLoadQueue, group?: string, canvas?: boolean, play = false) {
|
||||
let stickerType = doc.mime_type == "application/x-tgsticker" ? 2 : (doc.mime_type == "image/webp" ? 1 : 0);
|
||||
|
||||
if(!stickerType) {
|
||||
console.error('wrong doc for wrapSticker!', doc, div);
|
||||
}
|
||||
|
||||
//console.log('wrap sticker', doc);
|
||||
|
||||
if(doc.thumbs && !div.firstElementChild) {
|
||||
let thumb = doc.thumbs[0];
|
||||
|
||||
if(thumb.bytes) {
|
||||
MTProto.apiFileManager.saveSmallFile(thumb.location, thumb.bytes);
|
||||
|
||||
appPhotosManager.setAttachmentPreview(thumb.bytes, div, true);
|
||||
}
|
||||
}
|
||||
|
||||
let load = () => MTProto.apiFileManager.downloadSmallFile({
|
||||
_: 'inputDocumentFileLocation',
|
||||
access_hash: doc.access_hash,
|
||||
file_reference: doc.file_reference,
|
||||
thumb_size: ''/* document.thumbs[0].type */,
|
||||
id: doc.id,
|
||||
stickerType: stickerType
|
||||
}, {mimeType: doc.mime_type, dcID: doc.dc_id}).then(blob => {
|
||||
//console.log('loaded sticker:', blob, div);
|
||||
if(middleware && !middleware()) return;
|
||||
|
||||
if(div.firstElementChild) {
|
||||
div.firstElementChild.remove();
|
||||
}
|
||||
|
||||
if(stickerType == 2) {
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.addEventListener('loadend', async(e) => {
|
||||
// @ts-ignore
|
||||
const text = e.srcElement.result;
|
||||
let json = await CryptoWorker.gzipUncompress<string>(text, true);
|
||||
|
||||
let animation = await LottieLoader.loadAnimation({
|
||||
container: div,
|
||||
loop: false,
|
||||
autoplay: false,
|
||||
animationData: JSON.parse(json),
|
||||
renderer: canvas ? 'canvas' : 'svg'
|
||||
}, group);
|
||||
|
||||
if(!canvas) {
|
||||
div.addEventListener('mouseover', (e) => {
|
||||
let animation = LottieLoader.getAnimation(div, group);
|
||||
|
||||
if(animation) {
|
||||
//console.log('sticker hover', animation, div);
|
||||
|
||||
// @ts-ignore
|
||||
animation.loop = true;
|
||||
|
||||
// @ts-ignore
|
||||
if(animation.currentFrame == animation.totalFrames - 1) {
|
||||
animation.goToAndPlay(0, true);
|
||||
} else {
|
||||
animation.play();
|
||||
}
|
||||
|
||||
div.addEventListener('mouseout', () => {
|
||||
// @ts-ignore
|
||||
animation.loop = false;
|
||||
}, {once: true});
|
||||
}
|
||||
});
|
||||
} /* else {
|
||||
let canvas = div.firstElementChild as HTMLCanvasElement;
|
||||
if(!canvas.width && !canvas.height) {
|
||||
console.log('Need lottie resize');
|
||||
|
||||
// @ts-ignore
|
||||
animation.resize();
|
||||
}
|
||||
} */
|
||||
|
||||
if(play) {
|
||||
animation.play();
|
||||
}
|
||||
});
|
||||
|
||||
reader.readAsArrayBuffer(blob);
|
||||
} else if(stickerType == 1) {
|
||||
let img = new Image();
|
||||
img.src = URL.createObjectURL(blob);
|
||||
|
||||
/* div.style.height = doc.h + 'px';
|
||||
div.style.width = doc.w + 'px'; */
|
||||
div.append(img);
|
||||
}
|
||||
|
||||
div.setAttribute('file-id', doc.id);
|
||||
appStickersManager.saveSticker(doc);
|
||||
});
|
||||
|
||||
return lazyLoadQueue ? (lazyLoadQueue.push({div, load}), Promise.resolve()) : load();
|
||||
}
|
||||
|
||||
export function horizontalMenu(tabs: HTMLUListElement, content: HTMLDivElement, onClick?: (id: number, tabContent: HTMLDivElement) => void, onTransitionEnd?: () => void) {
|
||||
let hideTimeout: number = 0;
|
||||
let prevTabContent: HTMLDivElement = null;
|
||||
@ -761,10 +145,10 @@ export function horizontalMenu(tabs: HTMLUListElement, content: HTMLDivElement,
|
||||
}
|
||||
|
||||
export function getNearestDc() {
|
||||
return MTProto.apiManager.invokeApi('help.getNearestDc').then((nearestDcResult: any) => {
|
||||
return apiManager.invokeApi('help.getNearestDc').then((nearestDcResult: any) => {
|
||||
if(nearestDcResult.nearest_dc != nearestDcResult.this_dc) {
|
||||
//MTProto.apiManager.baseDcID = nearestDcResult.nearest_dc;
|
||||
MTProto.apiManager.getNetworker(nearestDcResult.nearest_dc);
|
||||
apiManager.getNetworker(nearestDcResult.nearest_dc);
|
||||
}
|
||||
|
||||
return nearestDcResult;
|
||||
|
@ -1,5 +1,5 @@
|
||||
//import { appImManager, appMessagesManager, appDialogsManager, apiUpdatesManager, appUsersManager } from "../lib/services";
|
||||
import { LazyLoadQueue, openBtnMenu } from "./misc";
|
||||
import { openBtnMenu } from "./misc";
|
||||
import Scrollable from './scrollable';
|
||||
|
||||
import {stackBlurImage} from '../lib/StackBlur';
|
||||
@ -49,13 +49,6 @@ export default () => import('../lib/services').then(services => {
|
||||
}
|
||||
});
|
||||
|
||||
// @ts-ignore
|
||||
document.addEventListener('history_multiappend', (e: CustomEvent) => {
|
||||
//let msgIDsByPeer = e.detail;
|
||||
|
||||
appDialogsManager.sortDom();
|
||||
});
|
||||
|
||||
// @ts-ignore
|
||||
document.addEventListener('dialog_top', (e: CustomEvent) => {
|
||||
let dialog: any = e.detail;
|
||||
@ -64,16 +57,6 @@ export default () => import('../lib/services').then(services => {
|
||||
appDialogsManager.sortDom();
|
||||
});
|
||||
|
||||
// @ts-ignore
|
||||
document.addEventListener('history_delete', (e: CustomEvent) => {
|
||||
let detail: {
|
||||
peerID: string,
|
||||
msgs: {[x: number]: boolean}
|
||||
} = e.detail;
|
||||
|
||||
appImManager.deleteMessagesByIDs(Object.keys(detail.msgs).map(s => +s));
|
||||
});
|
||||
|
||||
// @ts-ignore
|
||||
document.addEventListener('dialogs_multiupdate', (e: CustomEvent) => {
|
||||
let dialogs = e.detail;
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { MTProto } from "../lib/mtproto/mtproto";
|
||||
import { putPreloader, getNearestDc, formatPhoneNumber } from "./misc";
|
||||
import Scrollable from './scrollable';
|
||||
import {RichTextProcessor} from '../lib/richtextprocessor';
|
||||
@ -6,6 +5,7 @@ import * as Config from '../lib/config';
|
||||
|
||||
import { findUpTag } from "../lib/utils";
|
||||
import pageAuthCode from "./pageAuthCode";
|
||||
import apiManager from "../lib/mtproto/apiManager";
|
||||
|
||||
let installed = false;
|
||||
|
||||
@ -193,8 +193,8 @@ export default () => {
|
||||
this.removeAttribute('readonly'); // fix autocomplete
|
||||
});*/
|
||||
|
||||
/* MTProto.authorizer.auth(2);
|
||||
MTProto.networkerFactory.startAll(); */
|
||||
/* authorizer.auth(2);
|
||||
networkerFactory.startAll(); */
|
||||
|
||||
btnNext.addEventListener('click', function(this: HTMLElement, e) {
|
||||
this.setAttribute('disabled', 'true');
|
||||
@ -204,7 +204,7 @@ export default () => {
|
||||
//this.innerHTML = 'PLEASE WAIT...';
|
||||
|
||||
let phone_number = telEl.value;
|
||||
MTProto.apiManager.invokeApi('auth.sendCode', {
|
||||
apiManager.invokeApi('auth.sendCode', {
|
||||
/* flags: 0, */
|
||||
phone_number: phone_number,
|
||||
api_id: Config.App.id,
|
||||
|
76
src/components/preloader.ts
Normal file
76
src/components/preloader.ts
Normal file
@ -0,0 +1,76 @@
|
||||
import { isInDOM } from "../lib/utils";
|
||||
|
||||
export default class ProgressivePreloader {
|
||||
public preloader: HTMLDivElement = null;
|
||||
private circle: SVGCircleElement = null;
|
||||
private progress = 0;
|
||||
constructor(elem?: Element, private cancelable = true) {
|
||||
this.preloader = document.createElement('div');
|
||||
this.preloader.classList.add('preloader-container');
|
||||
|
||||
this.preloader.innerHTML = `
|
||||
<div class="you-spin-me-round">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="preloader-circular" viewBox="25 25 50 50">
|
||||
<circle class="preloader-path-new" cx="50" cy="50" r="23" fill="none" stroke-miterlimit="10"/>
|
||||
</svg>
|
||||
</div>`;
|
||||
|
||||
if(cancelable) {
|
||||
this.preloader.innerHTML += `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="preloader-close" viewBox="0 0 20 20">
|
||||
<line x1="0" y1="20" x2="20" y2="0" stroke-width="2" stroke-linecap="round"></line>
|
||||
<line x1="0" y1="0" x2="20" y2="20" stroke-width="2" stroke-linecap="round"></line>
|
||||
</svg>`;
|
||||
} else {
|
||||
this.preloader.classList.add('preloader-swing');
|
||||
}
|
||||
|
||||
this.circle = this.preloader.firstElementChild.firstElementChild.firstElementChild as SVGCircleElement;
|
||||
|
||||
if(elem) {
|
||||
this.attach(elem);
|
||||
}
|
||||
}
|
||||
|
||||
public attach(elem: Element, reset = true) {
|
||||
if(this.cancelable && reset) {
|
||||
this.setProgress(0);
|
||||
}
|
||||
|
||||
elem.append(this.preloader);
|
||||
/* let isIn = isInDOM(this.preloader);
|
||||
|
||||
if(isIn && this.progress != this.defaultProgress) {
|
||||
this.setProgress(this.defaultProgress);
|
||||
}
|
||||
|
||||
elem.append(this.preloader);
|
||||
|
||||
if(!isIn && this.progress != this.defaultProgress) {
|
||||
this.setProgress(this.defaultProgress);
|
||||
} */
|
||||
}
|
||||
|
||||
public detach() {
|
||||
if(this.preloader.parentElement) {
|
||||
this.preloader.parentElement.removeChild(this.preloader);
|
||||
}
|
||||
}
|
||||
|
||||
public setProgress(percents: number) {
|
||||
this.progress = percents;
|
||||
|
||||
if(!isInDOM(this.circle)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(percents == 0) {
|
||||
this.circle.style.strokeDasharray = '';
|
||||
return;
|
||||
}
|
||||
|
||||
let totalLength = this.circle.getTotalLength();
|
||||
console.log('setProgress', (percents / 100 * totalLength));
|
||||
this.circle.style.strokeDasharray = '' + Math.max(5, percents / 100 * totalLength) + ', 200';
|
||||
}
|
||||
}
|
323
src/components/wrappers.ts
Normal file
323
src/components/wrappers.ts
Normal file
@ -0,0 +1,323 @@
|
||||
import appPhotosManager from '../lib/appManagers/appPhotosManager';
|
||||
import CryptoWorker from '../lib/crypto/cryptoworker';
|
||||
import LottieLoader from '../lib/lottieLoader';
|
||||
import appStickersManager from "../lib/appManagers/appStickersManager";
|
||||
import appDocsManager from "../lib/appManagers/appDocsManager";
|
||||
import {AppImManager} from "../lib/appManagers/appImManager";
|
||||
import { formatBytes } from "../lib/utils";
|
||||
import ProgressivePreloader from './preloader';
|
||||
import LazyLoadQueue from './lazyLoadQueue';
|
||||
import apiFileManager from '../lib/mtproto/apiFileManager';
|
||||
|
||||
export type MTDocument = {
|
||||
_: 'document',
|
||||
pFlags: any,
|
||||
flags: number,
|
||||
id: string,
|
||||
access_hash: string,
|
||||
file_reference: Uint8Array | number[],
|
||||
date: number,
|
||||
mime_type: string,
|
||||
size: number,
|
||||
thumbs: MTPhotoSize[],
|
||||
dc_id: number,
|
||||
attributes: any[],
|
||||
|
||||
type?: string,
|
||||
h?: number,
|
||||
w?: number,
|
||||
file_name?: string,
|
||||
file?: File
|
||||
};
|
||||
|
||||
export type MTPhotoSize = {
|
||||
_: string,
|
||||
w?: number,
|
||||
h?: number,
|
||||
size?: number,
|
||||
type?: string, // i, m, x, y, w by asc
|
||||
location?: any,
|
||||
bytes?: Uint8Array, // if type == 'i'
|
||||
|
||||
preloaded?: boolean // custom added
|
||||
};
|
||||
|
||||
export function wrapVideo(this: any, doc: MTDocument, container: HTMLDivElement, message: any, justLoader = true, preloader?: ProgressivePreloader, controls = true) {
|
||||
if(!container.firstElementChild || container.firstElementChild.tagName != 'IMG') {
|
||||
let size = appPhotosManager.setAttachmentSize(doc, container);
|
||||
}
|
||||
|
||||
let peerID = this.peerID ? this.peerID : this.currentMessageID;
|
||||
|
||||
//container.classList.add('video');
|
||||
|
||||
let img = container.firstElementChild as HTMLImageElement || new Image();
|
||||
img.setAttribute('message-id', '' + message.id);
|
||||
|
||||
if(!container.contains(img)) {
|
||||
container.append(img);
|
||||
}
|
||||
|
||||
//return Promise.resolve();
|
||||
|
||||
if(!preloader) {
|
||||
preloader = new ProgressivePreloader(container, false);
|
||||
}
|
||||
|
||||
let loadVideo = () => {
|
||||
let promise = appDocsManager.downloadDoc(doc);
|
||||
|
||||
/* promise.notify = (details: {done: number, total: number}) => {
|
||||
console.log('doc download', promise, details);
|
||||
preloader.setProgress(details.done);
|
||||
}; */
|
||||
|
||||
return promise.then(blob => {
|
||||
if((this.peerID ? this.peerID : this.currentMessageID) != peerID) {
|
||||
this.log.warn('peer changed');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('loaded doc:', doc, blob, container);
|
||||
|
||||
let video = document.createElement('video');
|
||||
video.loop = controls;
|
||||
video.autoplay = controls;
|
||||
|
||||
if(!justLoader) {
|
||||
video.controls = controls;
|
||||
} else {
|
||||
video.volume = 0;
|
||||
}
|
||||
|
||||
video.setAttribute('message-id', '' + message.id);
|
||||
|
||||
let source = document.createElement('source');
|
||||
//source.src = doc.url;
|
||||
source.src = URL.createObjectURL(blob);
|
||||
source.type = doc.mime_type;
|
||||
|
||||
if(img && container.contains(img)) {
|
||||
container.removeChild(img);
|
||||
}
|
||||
|
||||
video.append(source);
|
||||
container.append(video);
|
||||
|
||||
//container.style.width = '';
|
||||
//container.style.height = '';
|
||||
|
||||
preloader.detach();
|
||||
});
|
||||
};
|
||||
|
||||
if(doc.type == 'gif' || true) { // extra fix
|
||||
return this.peerID ? this.loadMediaQueuePush(loadVideo) : loadVideo();
|
||||
} else { // if video
|
||||
let load = () => appPhotosManager.preloadPhoto(doc).then((blob) => {
|
||||
if((this.peerID ? this.peerID : this.currentMessageID) != peerID) {
|
||||
this.log.warn('peer changed');
|
||||
return;
|
||||
}
|
||||
|
||||
img.src = URL.createObjectURL(blob);
|
||||
|
||||
/* image.style.height = doc.h + 'px';
|
||||
image.style.width = doc.w + 'px'; */
|
||||
|
||||
/* if(justLoader) { // extra fix
|
||||
justLoader = false;
|
||||
controls = false;
|
||||
} */
|
||||
|
||||
if(!justLoader) {
|
||||
return loadVideo();
|
||||
} else {
|
||||
container.style.width = '';
|
||||
container.style.height = '';
|
||||
preloader.detach();
|
||||
}
|
||||
});
|
||||
|
||||
return this.peerID ? this.loadMediaQueuePush(load) : load();
|
||||
}
|
||||
}
|
||||
|
||||
export function wrapDocument(doc: MTDocument, withTime = false): HTMLDivElement {
|
||||
let docDiv = document.createElement('div');
|
||||
docDiv.classList.add('document');
|
||||
|
||||
let iconDiv = document.createElement('div');
|
||||
iconDiv.classList.add('tgico-document');
|
||||
|
||||
let extSplitted = doc.file_name ? doc.file_name.split('.') : '';
|
||||
let ext = '';
|
||||
ext = extSplitted.length > 1 && Array.isArray(extSplitted) ? extSplitted.pop().toLowerCase() : 'file';
|
||||
|
||||
let ext2 = ext;
|
||||
if(doc.type == 'photo') {
|
||||
docDiv.classList.add('photo');
|
||||
ext2 = `<img src="${URL.createObjectURL(doc.file)}">`;
|
||||
}
|
||||
|
||||
let fileName = doc.file_name || 'Unknown.file';
|
||||
let size = formatBytes(doc.size);
|
||||
|
||||
if(withTime) {
|
||||
let months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
||||
let date = new Date(doc.date * 1000);
|
||||
|
||||
size += ' · ' + months[date.getMonth()] + ' ' + date.getDate() + ', ' + date.getFullYear()
|
||||
+ ' at ' + date.getHours() + ':' + ('0' + date.getMinutes()).slice(-2);
|
||||
}
|
||||
|
||||
docDiv.innerHTML = `
|
||||
<div class="document-ico ext-${ext}">${ext2}</div>
|
||||
<div class="document-name">${fileName}</div>
|
||||
<div class="document-size">${size}</div>
|
||||
`;
|
||||
|
||||
return docDiv;
|
||||
}
|
||||
|
||||
export function wrapPhoto(this: AppImManager, photo: any, message: any, container: HTMLDivElement) {
|
||||
//container.classList.add('photo');
|
||||
|
||||
let peerID = this.peerID;
|
||||
|
||||
let size = appPhotosManager.setAttachmentSize(photo.id, container);
|
||||
let image = container.firstElementChild as HTMLImageElement || new Image();
|
||||
//let size = appPhotosManager.setAttachmentSize(photo.id, image);
|
||||
image.setAttribute('message-id', message.mid);
|
||||
|
||||
if(!container.contains(image)) {
|
||||
container.append(image);
|
||||
}
|
||||
|
||||
let preloader = new ProgressivePreloader(container, false);
|
||||
|
||||
let load = () => appPhotosManager.preloadPhoto(photo.id, size).then((blob) => {
|
||||
if(this.peerID != peerID) {
|
||||
this.log.warn('peer changed');
|
||||
return;
|
||||
}
|
||||
|
||||
image.src = URL.createObjectURL(blob);
|
||||
|
||||
preloader.detach();
|
||||
|
||||
//image.style.width = '';
|
||||
//image.style.height = '';
|
||||
//container.style.width = '';
|
||||
//container.style.height = '';
|
||||
});
|
||||
|
||||
console.log('wrapPhoto', load, container, image);
|
||||
|
||||
return this.loadMediaQueue ? this.loadMediaQueuePush(load) : load();
|
||||
}
|
||||
|
||||
export function wrapSticker(doc: MTDocument, div: HTMLDivElement, middleware?: () => boolean, lazyLoadQueue?: LazyLoadQueue, group?: string, canvas?: boolean, play = false) {
|
||||
let stickerType = doc.mime_type == "application/x-tgsticker" ? 2 : (doc.mime_type == "image/webp" ? 1 : 0);
|
||||
|
||||
if(!stickerType) {
|
||||
console.error('wrong doc for wrapSticker!', doc, div);
|
||||
}
|
||||
|
||||
//console.log('wrap sticker', doc);
|
||||
|
||||
if(doc.thumbs && !div.firstElementChild) {
|
||||
let thumb = doc.thumbs[0];
|
||||
|
||||
if(thumb.bytes) {
|
||||
apiFileManager.saveSmallFile(thumb.location, thumb.bytes);
|
||||
|
||||
appPhotosManager.setAttachmentPreview(thumb.bytes, div, true);
|
||||
}
|
||||
}
|
||||
|
||||
let load = () => apiFileManager.downloadSmallFile({
|
||||
_: 'inputDocumentFileLocation',
|
||||
access_hash: doc.access_hash,
|
||||
file_reference: doc.file_reference,
|
||||
thumb_size: ''/* document.thumbs[0].type */,
|
||||
id: doc.id,
|
||||
stickerType: stickerType
|
||||
}, {mimeType: doc.mime_type, dcID: doc.dc_id}).then(blob => {
|
||||
//console.log('loaded sticker:', blob, div);
|
||||
if(middleware && !middleware()) return;
|
||||
|
||||
if(div.firstElementChild) {
|
||||
div.firstElementChild.remove();
|
||||
}
|
||||
|
||||
if(stickerType == 2) {
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.addEventListener('loadend', async(e) => {
|
||||
// @ts-ignore
|
||||
const text = e.srcElement.result;
|
||||
let json = await CryptoWorker.gzipUncompress<string>(text, true);
|
||||
|
||||
let animation = await LottieLoader.loadAnimation({
|
||||
container: div,
|
||||
loop: false,
|
||||
autoplay: false,
|
||||
animationData: JSON.parse(json),
|
||||
renderer: canvas ? 'canvas' : 'svg'
|
||||
}, group);
|
||||
|
||||
if(!canvas) {
|
||||
div.addEventListener('mouseover', (e) => {
|
||||
let animation = LottieLoader.getAnimation(div, group);
|
||||
|
||||
if(animation) {
|
||||
//console.log('sticker hover', animation, div);
|
||||
|
||||
// @ts-ignore
|
||||
animation.loop = true;
|
||||
|
||||
// @ts-ignore
|
||||
if(animation.currentFrame == animation.totalFrames - 1) {
|
||||
animation.goToAndPlay(0, true);
|
||||
} else {
|
||||
animation.play();
|
||||
}
|
||||
|
||||
div.addEventListener('mouseout', () => {
|
||||
// @ts-ignore
|
||||
animation.loop = false;
|
||||
}, {once: true});
|
||||
}
|
||||
});
|
||||
} /* else {
|
||||
let canvas = div.firstElementChild as HTMLCanvasElement;
|
||||
if(!canvas.width && !canvas.height) {
|
||||
console.log('Need lottie resize');
|
||||
|
||||
// @ts-ignore
|
||||
animation.resize();
|
||||
}
|
||||
} */
|
||||
|
||||
if(play) {
|
||||
animation.play();
|
||||
}
|
||||
});
|
||||
|
||||
reader.readAsArrayBuffer(blob);
|
||||
} else if(stickerType == 1) {
|
||||
let img = new Image();
|
||||
img.src = URL.createObjectURL(blob);
|
||||
|
||||
/* div.style.height = doc.h + 'px';
|
||||
div.style.width = doc.w + 'px'; */
|
||||
div.append(img);
|
||||
}
|
||||
|
||||
div.setAttribute('file-id', doc.id);
|
||||
appStickersManager.saveSticker(doc);
|
||||
});
|
||||
|
||||
return lazyLoadQueue ? (lazyLoadQueue.push({div, load}), Promise.resolve()) : load();
|
||||
}
|
@ -23,7 +23,7 @@ export class AppChatsManager {
|
||||
}
|
||||
|
||||
public saveApiChats(apiChats: any[]) {
|
||||
apiChats.forEach(this.saveApiChat.bind(this));
|
||||
apiChats.forEach(chat => this.saveApiChat(chat));
|
||||
}
|
||||
|
||||
public saveApiChat(apiChat: any) {
|
||||
@ -254,27 +254,6 @@ export class AppChatsManager {
|
||||
}
|
||||
return participants;
|
||||
}
|
||||
|
||||
/* public openChat(chatID: number, accessHash: string) {
|
||||
var scope = $rootScope.$new()
|
||||
scope.chatID = chatID
|
||||
|
||||
if(this.isChannel(chatID)) {
|
||||
var modalInstance = $modal.open({
|
||||
templateUrl: templateUrl('channel_modal'),
|
||||
controller: 'ChannelModalController',
|
||||
scope: scope,
|
||||
windowClass: 'chat_modal_window channel_modal_window mobile_modal'
|
||||
})
|
||||
} else {
|
||||
var modalInstance = $modal.open({
|
||||
templateUrl: templateUrl('chat_modal'),
|
||||
controller: 'ChatModalController',
|
||||
scope: scope,
|
||||
windowClass: 'chat_modal_window mobile_modal'
|
||||
})
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
export default new AppChatsManager();
|
||||
|
@ -22,11 +22,14 @@ type DialogDom = {
|
||||
|
||||
export class AppDialogsManager {
|
||||
public chatList = document.getElementById('dialogs') as HTMLUListElement;
|
||||
public chatListArchived = document.getElementById('dialogs-archived') as HTMLUListElement;
|
||||
public pinnedDelimiter: HTMLDivElement;
|
||||
public chatsHidden: any;
|
||||
|
||||
public myID = 0;
|
||||
public doms: {[x: number]: any} = {};
|
||||
public doms: {[peerID: number]: DialogDom} = {};
|
||||
public domsArchived: {[peerID: number]: DialogDom} = {};
|
||||
public lastActiveListElement: HTMLElement = null;
|
||||
|
||||
constructor() {
|
||||
this.pinnedDelimiter = document.createElement('div');
|
||||
@ -56,6 +59,10 @@ export class AppDialogsManager {
|
||||
return;
|
||||
}
|
||||
|
||||
if(this.lastActiveListElement) {
|
||||
this.lastActiveListElement.classList.remove('active');
|
||||
}
|
||||
|
||||
if(elem) {
|
||||
/* if(chatClosedDiv) {
|
||||
chatClosedDiv.style.display = 'none';
|
||||
@ -66,6 +73,8 @@ export class AppDialogsManager {
|
||||
let peerID = +elem.getAttribute('data-peerID');
|
||||
let lastMsgID = +elem.getAttribute('data-mid');
|
||||
appImManager.setPeer(peerID, lastMsgID);
|
||||
elem.classList.add('active');
|
||||
this.lastActiveListElement = elem;
|
||||
} else /* if(chatClosedDiv) */ {
|
||||
appImManager.setPeer(0);
|
||||
//chatClosedDiv.style.display = '';
|
||||
@ -140,7 +149,7 @@ export class AppDialogsManager {
|
||||
return true;
|
||||
}
|
||||
|
||||
public sortDom() {
|
||||
public sortDom(archived = false) {
|
||||
//return;
|
||||
|
||||
let dialogs = appMessagesManager.dialogsStorage.dialogs;
|
||||
@ -153,11 +162,17 @@ export class AppDialogsManager {
|
||||
let dialog = dialogs[i];
|
||||
if(!dialog.pFlags.pinned) break;
|
||||
pinnedDialogs.push(dialog);
|
||||
}
|
||||
|
||||
let dom = this.getDialogDom(dialog.peerID);
|
||||
if(pinnedDialogs.length) {
|
||||
let dom = this.getDialogDom(pinnedDialogs[pinnedDialogs.length - 1].peerID);
|
||||
if(dom) {
|
||||
dom.listEl.append(this.pinnedDelimiter);
|
||||
}
|
||||
} else {
|
||||
if(this.pinnedDelimiter.parentElement) {
|
||||
this.pinnedDelimiter.parentElement.removeChild(this.pinnedDelimiter);
|
||||
}
|
||||
}
|
||||
|
||||
let sorted = dialogs
|
||||
@ -372,13 +387,14 @@ export class AppDialogsManager {
|
||||
}
|
||||
|
||||
public getDialogDom(peerID: number) {
|
||||
return this.doms[peerID] as DialogDom;
|
||||
return this.doms[peerID] || this.domsArchived[peerID];
|
||||
}
|
||||
|
||||
public addDialog(dialog: {
|
||||
peerID: number,
|
||||
pFlags: any,
|
||||
peer: any
|
||||
peer: any,
|
||||
folder_id?: number
|
||||
}, container?: HTMLUListElement, drawStatus = true) {
|
||||
let peerID: number = dialog.peerID;
|
||||
|
||||
@ -481,7 +497,14 @@ export class AppDialogsManager {
|
||||
};
|
||||
|
||||
if(!container) {
|
||||
if(dialog.folder_id) {
|
||||
this.chatListArchived.append(li);
|
||||
this.domsArchived[dialog.peerID] = dom;
|
||||
} else {
|
||||
this.chatList.append(li);
|
||||
this.doms[dialog.peerID] = dom;
|
||||
}
|
||||
|
||||
//this.appendTo.push(li);
|
||||
|
||||
if(dialog.pFlags.pinned) {
|
||||
@ -490,7 +513,6 @@ export class AppDialogsManager {
|
||||
dom.listEl.append(this.pinnedDelimiter);
|
||||
}
|
||||
|
||||
this.doms[dialog.peerID] = dom;
|
||||
this.setLastMessage(dialog);
|
||||
} else {
|
||||
container.append(li);
|
||||
|
@ -4,7 +4,7 @@ import appUsersManager from "./appUsersManager";
|
||||
import appMessagesManager from "./appMessagesManager";
|
||||
import appPeersManager from "./appPeersManager";
|
||||
import appProfileManager from "./appProfileManager";
|
||||
import { ProgressivePreloader, wrapDocument, wrapSticker, wrapVideo, wrapPhoto, openBtnMenu, LazyLoadQueue } from "../../components/misc";
|
||||
//import { ProgressivePreloader, wrapDocument, wrapSticker, wrapVideo, wrapPhoto, openBtnMenu, LazyLoadQueue } from "../../components/misc";
|
||||
import appDialogsManager from "./appDialogsManager";
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
import appPhotosManager from "./appPhotosManager";
|
||||
@ -19,6 +19,10 @@ import appChatsManager from "./appChatsManager";
|
||||
import appMessagesIDsManager from "./appMessagesIDsManager";
|
||||
import apiUpdatesManager from './apiUpdatesManager';
|
||||
import initEmoticonsDropdown, { EMOTICONSSTICKERGROUP } from '../../components/emoticonsDropdown';
|
||||
import LazyLoadQueue from '../../components/lazyLoadQueue';
|
||||
import { wrapDocument, wrapPhoto, wrapVideo, wrapSticker } from '../../components/wrappers';
|
||||
import ProgressivePreloader from '../../components/preloader';
|
||||
import { openBtnMenu } from '../../components/misc';
|
||||
|
||||
console.log('appImManager included!');
|
||||
|
||||
@ -213,7 +217,7 @@ class ChatInput {
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
/* this.messageInput.addEventListener('paste', (e) => {
|
||||
this.messageInput.addEventListener('paste', (e) => {
|
||||
e.preventDefault();
|
||||
// @ts-ignore
|
||||
let text = (e.originalEvent || e).clipboardData.getData('text/plain');
|
||||
@ -229,7 +233,7 @@ class ChatInput {
|
||||
// @ts-ignore
|
||||
//console.log('paste text', text, );
|
||||
window.document.execCommand('insertHTML', false, text);
|
||||
}); */
|
||||
});
|
||||
|
||||
let attachFile = (file: File) => {
|
||||
console.log('selected file:', file, typeof(file));
|
||||
@ -240,6 +244,8 @@ class ChatInput {
|
||||
|
||||
this.attachMediaPopUp.captionInput.value = '';
|
||||
this.attachMediaPopUp.mediaContainer.innerHTML = '';
|
||||
this.attachMediaPopUp.mediaContainer.style.width = '';
|
||||
this.attachMediaPopUp.mediaContainer.style.height = '';
|
||||
|
||||
switch(willAttach) {
|
||||
case 'media': {
|
||||
@ -248,11 +254,14 @@ class ChatInput {
|
||||
img.onload = () => {
|
||||
willAttachWidth = img.naturalWidth;
|
||||
willAttachHeight = img.naturalHeight;
|
||||
|
||||
let {w, h} = calcImageInBox(willAttachWidth, willAttachHeight, 378, 256);
|
||||
this.attachMediaPopUp.mediaContainer.style.width = w + 'px';
|
||||
this.attachMediaPopUp.mediaContainer.style.height = h + 'px';
|
||||
this.attachMediaPopUp.mediaContainer.append(img);
|
||||
};
|
||||
|
||||
this.attachMediaPopUp.titleEl.innerText = 'Send Photo';
|
||||
|
||||
this.attachMediaPopUp.mediaContainer.append(img);
|
||||
this.attachMediaPopUp.container.classList.add('active');
|
||||
|
||||
break;
|
||||
@ -308,7 +317,7 @@ class ChatInput {
|
||||
|
||||
// @ts-ignore
|
||||
var items = (event.clipboardData || event.originalEvent.clipboardData).items;
|
||||
//console.log(items); // will give you the mime types
|
||||
//console.log('item', event.clipboardData.getData());
|
||||
for(let i = 0; i < items.length; ++i) {
|
||||
if(items[i].kind == 'file') {
|
||||
event.cancelBubble = true;
|
||||
@ -526,15 +535,42 @@ export class AppImManager {
|
||||
let msgIDs = msgIDsByPeer[this.peerID];
|
||||
|
||||
this.renderMessagesByIDs(msgIDs);
|
||||
|
||||
appDialogsManager.sortDom();
|
||||
});
|
||||
|
||||
$rootScope.$on('history_delete', (e: CustomEvent) => {
|
||||
let detail: {
|
||||
peerID: string,
|
||||
msgs: {[x: number]: boolean}
|
||||
} = e.detail;
|
||||
|
||||
this.deleteMessagesByIDs(Object.keys(detail.msgs).map(s => +s));
|
||||
});
|
||||
|
||||
// Calls when message successfully sent and we have an ID
|
||||
$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);
|
||||
|
||||
let media = bubble.querySelector('img, video');
|
||||
if(media) {
|
||||
media.setAttribute('message-id', mid);
|
||||
}
|
||||
|
||||
bubble.classList.remove('is-sending');
|
||||
bubble.classList.add('is-sent');
|
||||
|
||||
delete this.bubbles[tempID];
|
||||
} else {
|
||||
this.log.warn('message_sent there is no bubble', e.detail);
|
||||
}
|
||||
|
||||
let length = this.unreadOut.length;
|
||||
@ -964,10 +1000,12 @@ export class AppImManager {
|
||||
let length = history.length; */
|
||||
|
||||
// filter negative ids
|
||||
let lastBadIndex = 0;
|
||||
for(let i = 0; i < history.length; ++i) {
|
||||
if(history[i] <= 0) history.splice(i, 1);
|
||||
if(history[i] <= 0) lastBadIndex = i;
|
||||
else break;
|
||||
}
|
||||
history = history.slice(lastBadIndex + 1);
|
||||
|
||||
this.getHistoryTimeout = 0;
|
||||
|
||||
@ -978,6 +1016,11 @@ export class AppImManager {
|
||||
|
||||
let bubble = this.bubbles[msgID];
|
||||
|
||||
if(!bubble) {
|
||||
this.log.error('no bubble by msgID:', msgID);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(isElementInViewport(bubble)) {
|
||||
willLoad = true;
|
||||
|
||||
@ -994,6 +1037,9 @@ export class AppImManager {
|
||||
}
|
||||
|
||||
let dialog = appMessagesManager.getDialogByPeerID(this.peerID)[0];
|
||||
if(!dialog) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if scroll down after search
|
||||
if(!willLoad && history.indexOf(/* this.lastDialog */dialog.top_message) === -1) {
|
||||
@ -1162,7 +1208,7 @@ export class AppImManager {
|
||||
}
|
||||
|
||||
if(this.bubbles[lastMsgID]) {
|
||||
if(lastMsgID == this.lastDialog.top_message) {
|
||||
if(this.lastDialog && lastMsgID == this.lastDialog.top_message) {
|
||||
this.scroll.scrollTop = this.scroll.scrollHeight;
|
||||
} else {
|
||||
this.bubbles[lastMsgID].scrollIntoView();
|
||||
@ -1179,45 +1225,47 @@ export class AppImManager {
|
||||
this.peerID = $rootScope.selectedPeerID = peerID;
|
||||
|
||||
// no dialog
|
||||
if(!appMessagesManager.getDialogByPeerID(this.peerID).length) {
|
||||
/* if(!appMessagesManager.getDialogByPeerID(this.peerID).length) {
|
||||
this.log.error('No dialog by peerID:', this.peerID);
|
||||
return Promise.reject();
|
||||
}
|
||||
} */
|
||||
|
||||
this.pinnedMessageContainer.style.display = 'none';
|
||||
|
||||
this.preloader.attach(this.chatInner);
|
||||
|
||||
if(this.lastDialog) {
|
||||
let lastDom = appDialogsManager.getDialogDom(this.lastDialog.peerID);
|
||||
lastDom.listEl.classList.remove('active');
|
||||
}
|
||||
|
||||
let dialog = this.lastDialog = appMessagesManager.getDialogByPeerID(this.peerID)[0];
|
||||
let dialog = this.lastDialog = appMessagesManager.getDialogByPeerID(this.peerID)[0] || null;
|
||||
this.log('setPeer peerID:', this.peerID, dialog);
|
||||
appDialogsManager.loadDialogPhoto(this.avatarEl, dialog.peerID);
|
||||
appDialogsManager.loadDialogPhoto(appSidebarRight.profileElements.avatar, dialog.peerID);
|
||||
appDialogsManager.loadDialogPhoto(this.avatarEl, this.peerID);
|
||||
appDialogsManager.loadDialogPhoto(appSidebarRight.profileElements.avatar, this.peerID);
|
||||
|
||||
this.firstTopMsgID = dialog.top_message || 0;
|
||||
this.firstTopMsgID = dialog ? dialog.top_message : 0;
|
||||
|
||||
let dom = appDialogsManager.getDialogDom(this.peerID);
|
||||
/* let dom = appDialogsManager.getDialogDom(this.peerID);
|
||||
if(!dom) {
|
||||
this.log.warn('No rendered dialog by peerID:', this.peerID);
|
||||
appDialogsManager.addDialog(dialog);
|
||||
dom = appDialogsManager.getDialogDom(this.peerID);
|
||||
}
|
||||
// warning need check
|
||||
dom.listEl.classList.add('active');
|
||||
dom.listEl.classList.add('active'); */
|
||||
|
||||
this.setPeerStatus();
|
||||
|
||||
this.titleEl.innerHTML = appSidebarRight.profileElements.name.innerHTML = dom.titleSpan.innerHTML;
|
||||
//this.titleEl.innerHTML = appSidebarRight.profileElements.name.innerHTML = dom.titleSpan.innerHTML;
|
||||
this.titleEl.innerHTML = appSidebarRight.profileElements.name.innerHTML = appPeersManager.getPeerTitle(this.peerID);
|
||||
|
||||
this.topbar.style.display = '';
|
||||
appSidebarRight.toggleSidebar(true);
|
||||
|
||||
this.chatInput.style.display = appPeersManager.isChannel(peerID) && !appPeersManager.isMegagroup(peerID) ? 'none' : '';
|
||||
|
||||
if(appPeersManager.isAnyGroup(peerID)) {
|
||||
this.chatInner.classList.add('is-chat');
|
||||
} else {
|
||||
this.chatInner.classList.remove('is-chat');
|
||||
}
|
||||
|
||||
return Promise.all([
|
||||
this.getHistory(lastMsgID).then(() => {
|
||||
this.log('setPeer removing preloader');
|
||||
@ -1230,7 +1278,7 @@ export class AppImManager {
|
||||
} else {
|
||||
this.scroll.scrollTop = this.scroll.scrollHeight;
|
||||
}
|
||||
} else if(dialog.top_message) { // add last message, bc in getHistory will load < max_id
|
||||
} else if(dialog && dialog.top_message) { // add last message, bc in getHistory will load < max_id
|
||||
this.renderMessage(appMessagesManager.getMessage(dialog.top_message));
|
||||
}
|
||||
|
||||
@ -1240,10 +1288,10 @@ export class AppImManager {
|
||||
|
||||
this.preloader.detach();
|
||||
|
||||
setTimeout(() => {
|
||||
//setTimeout(() => {
|
||||
//appSidebarRight.fillProfileElements();
|
||||
appSidebarRight.loadSidebarMedia();
|
||||
}, 0);
|
||||
//}, 500);
|
||||
|
||||
return true;
|
||||
})/* .catch(err => {
|
||||
@ -1271,15 +1319,17 @@ export class AppImManager {
|
||||
}
|
||||
|
||||
public updateUnreadByDialog(dialog: any) {
|
||||
let maxID = dialog.read_outbox_max_id;
|
||||
let maxID = this.peerID == this.myID ? dialog.read_inbox_max_id : dialog.read_outbox_max_id;
|
||||
|
||||
this.log('updateUnreadByDialog', maxID, dialog, this.unreadOut);
|
||||
|
||||
let length = this.unreadOut.length;
|
||||
for(let i = length - 1; i >= 0; --i) {
|
||||
let msgID = this.unreadOut[i];
|
||||
if(msgID <= maxID) {
|
||||
if(msgID > 0 && msgID <= maxID) {
|
||||
let bubble = this.bubbles[msgID];
|
||||
bubble.classList.remove('sent');
|
||||
bubble.classList.add('read');
|
||||
bubble.classList.remove('is-sent');
|
||||
bubble.classList.add('is-read');
|
||||
this.unreadOut.splice(i, 1);
|
||||
}
|
||||
}
|
||||
@ -1391,8 +1441,10 @@ export class AppImManager {
|
||||
//bubble.prepend(timeSpan, messageDiv); // that's bad
|
||||
|
||||
if(our) {
|
||||
if(message.pFlags.unread) this.unreadOut.push(message.mid);
|
||||
let status = message.pFlags.unread ? 'sent' : 'read';
|
||||
if(message.pFlags.unread || message.mid < 0) this.unreadOut.push(message.mid); // message.mid < 0 added 11.02.2020
|
||||
let status = '';
|
||||
if(message.mid < 0) status = 'is-sending';
|
||||
else status = message.pFlags.unread ? 'is-sent' : 'is-read';
|
||||
bubble.classList.add(status);
|
||||
} else {
|
||||
//this.log('not our message', message, message.pFlags.unread);
|
||||
@ -1416,7 +1468,7 @@ export class AppImManager {
|
||||
|
||||
switch(pending.type) {
|
||||
case 'photo': {
|
||||
if(pending.size < 1e6) {
|
||||
if(pending.size < 5e6) {
|
||||
let img = new Image();
|
||||
img.src = URL.createObjectURL(pending.file);
|
||||
|
||||
@ -1487,8 +1539,6 @@ export class AppImManager {
|
||||
let textDiv = document.createElement('div');
|
||||
textDiv.classList.add('text');
|
||||
|
||||
let loadedVideo = false;
|
||||
|
||||
let preview: HTMLDivElement = null;
|
||||
if(webpage.photo || webpage.document) {
|
||||
preview = document.createElement('div');
|
||||
@ -1631,7 +1681,7 @@ export class AppImManager {
|
||||
let nameDiv = document.createElement('div');
|
||||
nameDiv.classList.add('name');
|
||||
nameDiv.innerHTML = 'Forwarded from ' + title;
|
||||
nameDiv.style.color = appPeersManager.getPeerColorByID(message.fromID, false);
|
||||
//nameDiv.style.color = appPeersManager.getPeerColorByID(message.fromID, false);
|
||||
bubble.append(nameDiv);
|
||||
}
|
||||
} else {
|
||||
@ -1768,9 +1818,9 @@ export class AppImManager {
|
||||
this.chatInner.append(containerDiv);
|
||||
}
|
||||
|
||||
if(bubble.classList.contains('webpage')) {
|
||||
/* if(bubble.classList.contains('webpage')) {
|
||||
this.log('night running', bubble, bubble.scrollHeight);
|
||||
}
|
||||
} */
|
||||
|
||||
//return //this.scrollPosition.restore();
|
||||
|
||||
@ -1825,7 +1875,7 @@ export class AppImManager {
|
||||
public getHistory(maxID = 0, reverse = false, isBackLimit = false) {
|
||||
let peerID = this.peerID;
|
||||
|
||||
if(!maxID && this.lastDialog.top_message) {
|
||||
if(!maxID && this.lastDialog && this.lastDialog.top_message) {
|
||||
maxID = this.lastDialog.top_message/* + 1 */;
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,15 @@
|
||||
import { MTDocument, ProgressivePreloader, wrapVideo } from "../../components/misc";
|
||||
//import { MTDocument, ProgressivePreloader, wrapVideo } from "../../components/misc";
|
||||
import appPeersManager from "./appPeersManager";
|
||||
import appDialogsManager from "./appDialogsManager";
|
||||
import appPhotosManager from "./appPhotosManager";
|
||||
import appSidebarRight from "./appSidebarRight";
|
||||
import { $rootScope } from "../utils";
|
||||
import appMessagesManager from "./appMessagesManager";
|
||||
import { CancellablePromise } from "../mtproto/apiFileManager";
|
||||
//import { CancellablePromise } from "../mtproto/apiFileManager";
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
import { logger } from "../polyfill";
|
||||
import ProgressivePreloader from "../../components/preloader";
|
||||
import { wrapVideo } from "../../components/wrappers";
|
||||
|
||||
export class AppMediaViewer {
|
||||
private overlaysDiv = document.querySelector('.overlays') as HTMLDivElement;
|
||||
|
@ -4,7 +4,7 @@ import appChatsManager from "./appChatsManager";
|
||||
import appUsersManager from "./appUsersManager";
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
import { nextRandomInt, bigint } from "../bin_utils";
|
||||
import { MTProto, telegramMeWebService } from "../mtproto/mtproto";
|
||||
import { telegramMeWebService } from "../mtproto/mtproto";
|
||||
import apiUpdatesManager from "./apiUpdatesManager";
|
||||
import appPhotosManager from "./appPhotosManager";
|
||||
|
||||
@ -12,9 +12,12 @@ import AppStorage from '../storage';
|
||||
import AppPeersManager from "./appPeersManager";
|
||||
import ServerTimeManager from "../mtproto/serverTimeManager";
|
||||
import apiFileManager, { CancellablePromise } from "../mtproto/apiFileManager";
|
||||
import { MTDocument, ProgressivePreloader } from "../../components/misc";
|
||||
import appDocsManager from "./appDocsManager";
|
||||
import appImManager from "./appImManager";
|
||||
import { MTDocument } from "../../components/wrappers";
|
||||
import ProgressivePreloader from "../../components/preloader";
|
||||
import serverTimeManager from "../mtproto/serverTimeManager";
|
||||
import apiManager from "../mtproto/apiManager";
|
||||
|
||||
type HistoryStorage = {
|
||||
count: number | null,
|
||||
@ -221,7 +224,7 @@ export class AppMessagesManager {
|
||||
to_id: AppPeersManager.getOutputPeer(peerID),
|
||||
flags: flags,
|
||||
pFlags: pFlags,
|
||||
date: tsNow(true) + MTProto.serverTimeManager.serverTimeOffset,
|
||||
date: tsNow(true) + serverTimeManager.serverTimeOffset,
|
||||
message: text,
|
||||
random_id: randomIDS,
|
||||
reply_to_msg_id: replyToMsgID,
|
||||
@ -274,7 +277,7 @@ export class AppMessagesManager {
|
||||
|
||||
var apiPromise: any;
|
||||
if(options.viaBotID) {
|
||||
apiPromise = MTProto.apiManager.invokeApi('messages.sendInlineBotResult', {
|
||||
apiPromise = apiManager.invokeApi('messages.sendInlineBotResult', {
|
||||
flags: flags,
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
random_id: randomID,
|
||||
@ -287,7 +290,7 @@ export class AppMessagesManager {
|
||||
flags |= 8;
|
||||
}
|
||||
|
||||
apiPromise = MTProto.apiManager.invokeApi('messages.sendMessage', {
|
||||
apiPromise = apiManager.invokeApi('messages.sendMessage', {
|
||||
flags: flags,
|
||||
no_webpage: noWebPage,
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
@ -523,7 +526,7 @@ export class AppMessagesManager {
|
||||
let invoke = (flags: number, inputMedia: any) => {
|
||||
appImManager.setTyping('sendMessageCancelAction');
|
||||
|
||||
return MTProto.apiManager.invokeApi('messages.sendMedia', {
|
||||
return apiManager.invokeApi('messages.sendMedia', {
|
||||
flags: flags,
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
media: inputMedia,
|
||||
@ -767,7 +770,7 @@ export class AppMessagesManager {
|
||||
var flags = 0;
|
||||
|
||||
if(this.dialogsOffsetDate) {
|
||||
offsetDate = this.dialogsOffsetDate + MTProto.serverTimeManager.serverTimeOffset;
|
||||
offsetDate = this.dialogsOffsetDate + serverTimeManager.serverTimeOffset;
|
||||
offsetIndex = this.dialogsOffsetDate * 0x10000;
|
||||
flags |= 1;
|
||||
}
|
||||
@ -776,7 +779,7 @@ export class AppMessagesManager {
|
||||
/* let id = 296814355;
|
||||
hash = (((hash * 0x4F25) & 0x7FFFFFFF) + id) & 0x7FFFFFFF; */
|
||||
|
||||
return MTProto.apiManager.invokeApi('messages.getDialogs', {
|
||||
return apiManager.invokeApi('messages.getDialogs', {
|
||||
flags: flags,
|
||||
offset_date: offsetDate,
|
||||
offset_id: appMessagesIDsManager.getMessageLocalID(offsetID),
|
||||
@ -851,7 +854,7 @@ export class AppMessagesManager {
|
||||
|
||||
public generateDialogIndex(date?: any) {
|
||||
if(date === undefined) {
|
||||
date = tsNow(true) + MTProto.serverTimeManager.serverTimeOffset;
|
||||
date = tsNow(true) + serverTimeManager.serverTimeOffset;
|
||||
}
|
||||
return (date * 0x10000) + ((++this.dialogsNum) & 0xFFFF);
|
||||
}
|
||||
@ -925,7 +928,7 @@ export class AppMessagesManager {
|
||||
|
||||
console.log('will reloadConversation', peerID);
|
||||
|
||||
return MTProto.apiManager.invokeApi('messages.getPeerDialogs', {
|
||||
return apiManager.invokeApi('messages.getPeerDialogs', {
|
||||
peers: peers
|
||||
}).then(this.applyConversations.bind(this));
|
||||
}
|
||||
@ -972,7 +975,7 @@ export class AppMessagesManager {
|
||||
apiMessage.reply_to_mid = appMessagesIDsManager.getFullMessageID(apiMessage.reply_to_msg_id, channelID);
|
||||
}
|
||||
|
||||
apiMessage.date -= MTProto.serverTimeManager.serverTimeOffset;
|
||||
apiMessage.date -= serverTimeManager.serverTimeOffset;
|
||||
|
||||
apiMessage.peerID = peerID;
|
||||
apiMessage.fromID = apiMessage.pFlags.post ? peerID : apiMessage.from_id;
|
||||
@ -993,7 +996,7 @@ export class AppMessagesManager {
|
||||
apiMessage.fwdPostID = fwdHeader.channel_post;
|
||||
}
|
||||
|
||||
fwdHeader.date -= MTProto.serverTimeManager.serverTimeOffset;
|
||||
fwdHeader.date -= serverTimeManager.serverTimeOffset;
|
||||
}
|
||||
|
||||
if(apiMessage.via_bot_id > 0) {
|
||||
@ -1579,7 +1582,7 @@ export class AppMessagesManager {
|
||||
notification.silent = message.pFlags.silent || false
|
||||
|
||||
if(notificationPhoto.location && !notificationPhoto.location.empty) {
|
||||
MTProto.apiFileManager.downloadSmallFile(notificationPhoto.location/* , notificationPhoto.size */)
|
||||
apiFileManager.downloadSmallFile(notificationPhoto.location/* , notificationPhoto.size */)
|
||||
.then((blob) => {
|
||||
if(message.pFlags.unread) {
|
||||
notification.image = blob
|
||||
@ -1798,7 +1801,7 @@ export class AppMessagesManager {
|
||||
var apiPromise
|
||||
|
||||
if(peerID || !query) {
|
||||
apiPromise = MTProto.apiManager.invokeApi('messages.search', {
|
||||
apiPromise = apiManager.invokeApi('messages.search', {
|
||||
flags: 0,
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
q: query || '',
|
||||
@ -1826,7 +1829,7 @@ export class AppMessagesManager {
|
||||
offsetPeerID = this.getMessagePeer(offsetMessage);
|
||||
}
|
||||
|
||||
apiPromise = MTProto.apiManager.invokeApi('messages.searchGlobal', {
|
||||
apiPromise = apiManager.invokeApi('messages.searchGlobal', {
|
||||
q: query,
|
||||
offset_rate: offsetRate,
|
||||
offset_peer: AppPeersManager.getInputPeerByID(offsetPeerID),
|
||||
@ -1950,12 +1953,12 @@ export class AppMessagesManager {
|
||||
|
||||
var apiPromise: any;
|
||||
if(isChannel) {
|
||||
apiPromise = MTProto.apiManager.invokeApi('channels.readHistory', {
|
||||
apiPromise = apiManager.invokeApi('channels.readHistory', {
|
||||
channel: appChatsManager.getChannelInput(-peerID),
|
||||
max_id: maxID
|
||||
});
|
||||
} else {
|
||||
apiPromise = MTProto.apiManager.invokeApi('messages.readHistory', {
|
||||
apiPromise = apiManager.invokeApi('messages.readHistory', {
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
max_id: maxID
|
||||
}).then((affectedMessages: any) => {
|
||||
@ -2041,7 +2044,7 @@ export class AppMessagesManager {
|
||||
let msgIDs = splitted.msgIDs[channelID];
|
||||
|
||||
if(channelID > 0) {
|
||||
MTProto.apiManager.invokeApi('channels.readMessageContents', {
|
||||
apiManager.invokeApi('channels.readMessageContents', {
|
||||
channel: appChatsManager.getChannelInput(channelID),
|
||||
id: msgIDs
|
||||
}).then(() => {
|
||||
@ -2055,7 +2058,7 @@ export class AppMessagesManager {
|
||||
});
|
||||
});
|
||||
} else {
|
||||
MTProto.apiManager.invokeApi('messages.readMessageContents', {
|
||||
apiManager.invokeApi('messages.readMessageContents', {
|
||||
id: msgIDs
|
||||
}).then((affectedMessages: any) => {
|
||||
apiUpdatesManager.processUpdateMessage({
|
||||
@ -2096,7 +2099,7 @@ export class AppMessagesManager {
|
||||
var msgs: any = {}
|
||||
msgs[tempID] = true;
|
||||
|
||||
$rootScope.$broadcast('history_delete', {peerID: peerID, msgs: msgs});
|
||||
//$rootScope.$broadcast('history_delete', {peerID: peerID, msgs: msgs}); // commented 11.02.2020
|
||||
|
||||
this.finalizePendingMessageCallbacks(tempID, mid);
|
||||
} else {
|
||||
@ -2255,7 +2258,7 @@ export class AppMessagesManager {
|
||||
case 'updatePinnedDialogs': {
|
||||
var newPinned: any = {};
|
||||
if(!update.order) {
|
||||
MTProto.apiManager.invokeApi('messages.getPinnedDialogs', {}).then((dialogsResult: any) => {
|
||||
apiManager.invokeApi('messages.getPinnedDialogs', {}).then((dialogsResult: any) => {
|
||||
dialogsResult.dialogs.reverse();
|
||||
this.applyConversations(dialogsResult);
|
||||
|
||||
@ -2343,7 +2346,7 @@ export class AppMessagesManager {
|
||||
} else {
|
||||
var msgs: any = {};
|
||||
msgs[mid] = true;
|
||||
$rootScope.$broadcast('history_delete', {peerID: peerID, msgs: msgs});
|
||||
/////////$rootScope.$broadcast('history_delete', {peerID: peerID, msgs: msgs}); // commented 11.02.2020
|
||||
}
|
||||
} else {
|
||||
$rootScope.$broadcast('message_edit', {
|
||||
@ -2654,7 +2657,7 @@ export class AppMessagesManager {
|
||||
to_id: AppPeersManager.getOutputPeer(peerID),
|
||||
flags: 0,
|
||||
pFlags: {unread: true},
|
||||
date: (update.inbox_date || tsNow(true)) + MTProto.serverTimeManager.serverTimeOffset,
|
||||
date: (update.inbox_date || tsNow(true)) + serverTimeManager.serverTimeOffset,
|
||||
message: update.message,
|
||||
media: update.media,
|
||||
entities: update.entities
|
||||
@ -2845,7 +2848,7 @@ export class AppMessagesManager {
|
||||
max_seen_msg: maxID
|
||||
});
|
||||
|
||||
MTProto.apiManager.invokeApi('messages.receivedMessages', {
|
||||
apiManager.invokeApi('messages.receivedMessages', {
|
||||
max_id: maxID
|
||||
});
|
||||
}
|
||||
@ -3079,7 +3082,7 @@ export class AppMessagesManager {
|
||||
|
||||
//console.trace('requestHistory', peerID, maxID, limit, offset);
|
||||
|
||||
return MTProto.apiManager.invokeApi('messages.getHistory', {
|
||||
return apiManager.invokeApi('messages.getHistory', {
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
offset_id: maxID ? appMessagesIDsManager.getMessageLocalID(maxID) : 0,
|
||||
offset_date: 0,
|
||||
@ -3124,7 +3127,7 @@ export class AppMessagesManager {
|
||||
to_id: AppPeersManager.getOutputPeer(peerID),
|
||||
flags: 0,
|
||||
pFlags: {},
|
||||
date: tsNow(true) + MTProto.serverTimeManager.serverTimeOffset,
|
||||
date: tsNow(true) + serverTimeManager.serverTimeOffset,
|
||||
action: {
|
||||
_: 'messageActionBotIntro',
|
||||
description: description
|
||||
@ -3233,12 +3236,12 @@ export class AppMessagesManager {
|
||||
var promise;
|
||||
channelID = +channelID;
|
||||
if(channelID > 0) {
|
||||
promise = MTProto.apiManager.invokeApi('channels.getMessages', {
|
||||
promise = apiManager.invokeApi('channels.getMessages', {
|
||||
channel: appChatsManager.getChannelInput(channelID),
|
||||
id: msgIDs
|
||||
});
|
||||
} else {
|
||||
promise = MTProto.apiManager.invokeApi('messages.getMessages', {
|
||||
promise = apiManager.invokeApi('messages.getMessages', {
|
||||
id: msgIDs
|
||||
});
|
||||
}
|
||||
|
@ -105,6 +105,22 @@ const AppPeersManager = {
|
||||
return (peerID < 0) && appChatsManager.isChannel(-peerID);
|
||||
},
|
||||
|
||||
isMegagroup: (peerID: number) => {
|
||||
return (peerID < 0) && appChatsManager.isMegagroup(-peerID);
|
||||
},
|
||||
|
||||
isAnyGroup: (peerID: number): boolean => {
|
||||
return (peerID < 0) && !appChatsManager.isBroadcast(-peerID);
|
||||
},
|
||||
|
||||
isBroadcast: (id: number): boolean => {
|
||||
return AppPeersManager.isChannel(id) && !AppPeersManager.isMegagroup(id);
|
||||
},
|
||||
|
||||
isBot: (peerID: number): boolean => {
|
||||
return (peerID > 0) && appUsersManager.isBot(peerID);
|
||||
},
|
||||
|
||||
getInputPeerByID: (peerID: number) => {
|
||||
if (!peerID) {
|
||||
return {_: 'inputPeerEmpty'}
|
||||
@ -137,10 +153,6 @@ const AppPeersManager = {
|
||||
return color;
|
||||
},
|
||||
|
||||
isMegagroup: (peerID: number) => {
|
||||
return (peerID < 0) && appChatsManager.isMegagroup(-peerID);
|
||||
},
|
||||
|
||||
getPeerSearchText: (peerID: number) => {
|
||||
var text
|
||||
if(peerID > 0) {
|
||||
|
@ -1,9 +1,11 @@
|
||||
import { MTProto } from "../mtproto/mtproto";
|
||||
import appUsersManager from "./appUsersManager";
|
||||
import { copy, calcImageInBox } from "../utils";
|
||||
import fileManager from '../filemanager';
|
||||
import { bytesFromHex } from "../bin_utils";
|
||||
import { MTPhotoSize } from "../../components/misc";
|
||||
import { MTPhotoSize } from "../../components/wrappers";
|
||||
import apiFileManager from "../mtproto/apiFileManager";
|
||||
import apiManager from "../mtproto/apiManager";
|
||||
//import { MTPhotoSize } from "../../components/misc";
|
||||
|
||||
type MTPhoto = {
|
||||
_: 'photo',
|
||||
@ -53,7 +55,7 @@ export class AppPhotosManager {
|
||||
|
||||
apiPhoto.sizes.forEach((photoSize: any) => {
|
||||
if(photoSize._ == 'photoCachedSize') {
|
||||
MTProto.apiFileManager.saveSmallFile(photoSize.location, photoSize.bytes);
|
||||
apiFileManager.saveSmallFile(photoSize.location, photoSize.bytes);
|
||||
|
||||
console.log('clearing photo cached size', apiPhoto);
|
||||
|
||||
@ -109,7 +111,7 @@ export class AppPhotosManager {
|
||||
|
||||
public getUserPhotos(userID: number, maxID: number, limit: number) {
|
||||
var inputUser = appUsersManager.getUserInput(userID);
|
||||
return MTProto.apiManager.invokeApi('photos.getUserPhotos', {
|
||||
return apiManager.invokeApi('photos.getUserPhotos', {
|
||||
user_id: inputUser,
|
||||
offset: 0,
|
||||
limit: limit || 20,
|
||||
@ -221,26 +223,26 @@ export class AppPhotosManager {
|
||||
} : photoSize.location;
|
||||
|
||||
/* if(overwrite) {
|
||||
await MTProto.apiFileManager.deleteFile(location);
|
||||
await apiFileManager.deleteFile(location);
|
||||
console.log('Photos deleted file!');
|
||||
} */
|
||||
|
||||
if(isPhoto/* && photoSize.size >= 1e6 */) {
|
||||
console.log('Photos downloadFile exec', photo);
|
||||
/* let promise = MTProto.apiFileManager.downloadFile(photo.dc_id, location, photoSize.size);
|
||||
/* let promise = apiFileManager.downloadFile(photo.dc_id, location, photoSize.size);
|
||||
|
||||
let blob = await promise;
|
||||
if(blob.size < photoSize.size && overwrite) {
|
||||
await MTProto.apiFileManager.deleteFile(location);
|
||||
await apiFileManager.deleteFile(location);
|
||||
console.log('Photos deleted file!');
|
||||
return MTProto.apiFileManager.downloadFile(photo.dc_id, location, photoSize.size);
|
||||
return apiFileManager.downloadFile(photo.dc_id, location, photoSize.size);
|
||||
}
|
||||
|
||||
return blob; */
|
||||
return MTProto.apiFileManager.downloadFile(photo.dc_id, location, photoSize.size);
|
||||
return apiFileManager.downloadFile(photo.dc_id, location, photoSize.size);
|
||||
} else {
|
||||
console.log('Photos downloadSmallFile exec', photo, location);
|
||||
return MTProto.apiFileManager.downloadSmallFile(location);
|
||||
return apiFileManager.downloadSmallFile(location);
|
||||
}
|
||||
} else return Promise.reject('no photoSize');
|
||||
}
|
||||
@ -359,7 +361,7 @@ export class AppPhotosManager {
|
||||
|
||||
fileManager.chooseSaveFile(fileName, ext, mimeType).then((writableFileEntry) => {
|
||||
if(writableFileEntry) {
|
||||
MTProto.apiFileManager.downloadFile(photo.dc_id, inputFileLocation, fullPhotoSize.size, {
|
||||
apiFileManager.downloadFile(photo.dc_id, inputFileLocation, fullPhotoSize.size, {
|
||||
mimeType: mimeType,
|
||||
toFileEntry: writableFileEntry
|
||||
}).then(() => {
|
||||
@ -369,12 +371,12 @@ export class AppPhotosManager {
|
||||
});
|
||||
}
|
||||
}, () => {
|
||||
var cachedBlob = MTProto.apiFileManager.getCachedFile(inputFileLocation)
|
||||
var cachedBlob = apiFileManager.getCachedFile(inputFileLocation)
|
||||
if (cachedBlob) {
|
||||
return fileManager.download(cachedBlob, mimeType, fileName);
|
||||
}
|
||||
|
||||
MTProto.apiFileManager.downloadFile(photo.dc_id, inputFileLocation, fullPhotoSize.size, {mimeType: mimeType})
|
||||
apiFileManager.downloadFile(photo.dc_id, inputFileLocation, fullPhotoSize.size, {mimeType: mimeType})
|
||||
.then((blob: Blob) => {
|
||||
fileManager.download(blob, mimeType, fileName);
|
||||
}, (e: any) => {
|
||||
|
@ -1,11 +1,42 @@
|
||||
import { logger } from "../polyfill";
|
||||
import { putPreloader } from "../../components/misc";
|
||||
import { putPreloader, formatPhoneNumber } from "../../components/misc";
|
||||
import Scrollable from '../../components/scrollable';
|
||||
import appMessagesManager from "./appMessagesManager";
|
||||
import appDialogsManager from "./appDialogsManager";
|
||||
import { isElementInViewport } from "../utils";
|
||||
import { isElementInViewport, numberWithCommas } from "../utils";
|
||||
import appMessagesIDsManager from "./appMessagesIDsManager";
|
||||
import appImManager from "./appImManager";
|
||||
import appUsersManager from "./appUsersManager";
|
||||
import { appPeersManager } from "../services";
|
||||
|
||||
class SearchGroup {
|
||||
container: HTMLDivElement;
|
||||
nameEl: HTMLDivElement;
|
||||
list: HTMLUListElement;
|
||||
|
||||
constructor(public name: string, public type: string) {
|
||||
this.list = document.createElement('ul');
|
||||
this.container = document.createElement('div');
|
||||
this.nameEl = document.createElement('div');
|
||||
this.nameEl.classList.add('search-group__name');
|
||||
this.nameEl.innerText = name;
|
||||
|
||||
this.container.classList.add('search-group');
|
||||
this.container.append(this.nameEl, this.list);
|
||||
this.container.style.display = 'none';
|
||||
|
||||
appDialogsManager.setListClickListener(this.list);
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.container.style.display = 'none';
|
||||
this.list.innerHTML = '';
|
||||
}
|
||||
|
||||
setActive() {
|
||||
this.container.style.display = '';
|
||||
}
|
||||
}
|
||||
|
||||
class AppSidebarLeft {
|
||||
private sidebarEl = document.querySelector('.page-chats .chats-container') as HTMLDivElement;
|
||||
@ -15,10 +46,11 @@ class AppSidebarLeft {
|
||||
|
||||
private menuEl = this.toolsBtn.querySelector('.btn-menu');
|
||||
private savedBtn = this.menuEl.querySelector('.menu-saved');
|
||||
private archivedBtn = this.menuEl.querySelector('.menu-archive');
|
||||
|
||||
private listsContainer: HTMLDivElement = null;
|
||||
private searchMessagesList: HTMLUListElement = null;
|
||||
|
||||
private chatsArchivedContainer = document.getElementById('chats-archived-container') as HTMLDivElement;
|
||||
private chatsContainer = document.getElementById('chats-container') as HTMLDivElement;
|
||||
private chatsOffsetIndex = 0;
|
||||
private chatsPreloader: HTMLDivElement;
|
||||
@ -40,6 +72,13 @@ class AppSidebarLeft {
|
||||
|
||||
public scroll: Scrollable = null;
|
||||
|
||||
public searchGroups: {[group: string]: SearchGroup} = {
|
||||
contacts: new SearchGroup('Contacts and Chats', 'contacts'),
|
||||
globalContacts: new SearchGroup('Global Search', 'contacts'),
|
||||
globalMessages: new SearchGroup('Global Search', 'messages'),
|
||||
privateMessages: new SearchGroup('Private Search', 'messages')
|
||||
};
|
||||
|
||||
constructor() {
|
||||
this.chatsPreloader = document.createElement('div');
|
||||
this.chatsPreloader.classList.add('preloader');
|
||||
@ -55,7 +94,10 @@ class AppSidebarLeft {
|
||||
this.scroll.container.addEventListener('scroll', this.onChatsScroll.bind(this));
|
||||
|
||||
this.listsContainer = new Scrollable(this.searchContainer).container;
|
||||
this.searchMessagesList = document.createElement('ul');
|
||||
|
||||
for(let i in this.searchGroups) {
|
||||
this.listsContainer.append(this.searchGroups[i].container);
|
||||
}
|
||||
|
||||
this.savedBtn.addEventListener('click', (e) => {
|
||||
this.log('savedbtn click');
|
||||
@ -64,6 +106,12 @@ class AppSidebarLeft {
|
||||
}, 0);
|
||||
});
|
||||
|
||||
this.archivedBtn.addEventListener('click', (e) => {
|
||||
this.chatsArchivedContainer.classList.add('active');
|
||||
this.toolsBtn.classList.remove('tgico-menu', 'btn-menu-toggle');
|
||||
this.toolsBtn.classList.add('tgico-back');
|
||||
});
|
||||
|
||||
/* this.listsContainer.insertBefore(this.searchMessagesList, this.listsContainer.lastElementChild);
|
||||
for(let i = 0; i < 25; ++i) {
|
||||
let li = document.createElement('li');
|
||||
@ -75,8 +123,6 @@ class AppSidebarLeft {
|
||||
|
||||
//this.searchContainer.append(this.listsContainer);
|
||||
|
||||
appDialogsManager.setListClickListener(this.searchMessagesList);
|
||||
|
||||
let clickTimeout = 0;
|
||||
this.searchInput.addEventListener('focus', (e) => {
|
||||
this.toolsBtn.classList.remove('tgico-menu', 'btn-menu-toggle');
|
||||
@ -84,7 +130,9 @@ class AppSidebarLeft {
|
||||
this.searchContainer.classList.add('active');
|
||||
|
||||
if(!this.searchInput.value) {
|
||||
this.searchMessagesList.innerHTML = '';
|
||||
for(let i in this.searchGroups) {
|
||||
this.searchGroups[i].clear();
|
||||
}
|
||||
}
|
||||
|
||||
this.searchInput.addEventListener('blur', (e) => {
|
||||
@ -111,10 +159,6 @@ class AppSidebarLeft {
|
||||
let value = this.searchInput.value;
|
||||
this.log('input', value);
|
||||
|
||||
if(this.listsContainer.contains(this.searchMessagesList)) {
|
||||
this.listsContainer.removeChild(this.searchMessagesList);
|
||||
}
|
||||
|
||||
if(!value.trim()) {
|
||||
return;
|
||||
}
|
||||
@ -124,11 +168,13 @@ class AppSidebarLeft {
|
||||
this.loadedCount = 0;
|
||||
this.foundCount = 0;
|
||||
this.offsetRate = 0;
|
||||
this.searchMessagesList.innerHTML = '';
|
||||
|
||||
for(let i in this.searchGroups) {
|
||||
this.searchGroups[i].clear();
|
||||
}
|
||||
|
||||
this.searchPromise = null;
|
||||
this.searchMore().then(() => {
|
||||
this.listsContainer.append(this.searchMessagesList);
|
||||
});
|
||||
this.searchMore();
|
||||
});
|
||||
|
||||
this.toolsBtn.addEventListener('click', (e) => {
|
||||
@ -138,6 +184,7 @@ class AppSidebarLeft {
|
||||
this.toolsBtn.classList.add('tgico-menu', 'btn-menu-toggle');
|
||||
this.toolsBtn.classList.remove('tgico-back');
|
||||
this.searchContainer.classList.remove('active');
|
||||
this.chatsArchivedContainer.classList.remove('active');
|
||||
this.peerID = 0;
|
||||
e.stopPropagation();
|
||||
e.cancelBubble = true;
|
||||
@ -156,6 +203,10 @@ class AppSidebarLeft {
|
||||
this.onChatsScroll();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
/* appUsersManager.getTopPeers().then(categories => {
|
||||
this.log('got top categories:', categories);
|
||||
}); */
|
||||
}
|
||||
|
||||
public async loadDialogs() {
|
||||
@ -207,7 +258,7 @@ class AppSidebarLeft {
|
||||
public onSidebarScroll() {
|
||||
if(!this.query.trim()) return;
|
||||
|
||||
let elements = Array.from(this.searchMessagesList.childNodes).slice(-5);
|
||||
let elements = Array.from(this.searchGroups[this.peerID ? 'privateMessages' : 'globalMessages'].list.childNodes).slice(-5);
|
||||
for(let li of elements) {
|
||||
if(isElementInViewport(li)) {
|
||||
this.log('Will load more search');
|
||||
@ -245,6 +296,64 @@ class AppSidebarLeft {
|
||||
|
||||
let maxID = appMessagesIDsManager.getMessageIDInfo(this.minMsgID)[0];
|
||||
|
||||
if(!this.peerID && !maxID) {
|
||||
appUsersManager.searchContacts(query, 20).then((contacts: any) => {
|
||||
if(this.searchInput.value != query) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.log('input search contacts result:', contacts);
|
||||
|
||||
let setResults = (results: any, group: SearchGroup, showMembersCount = false) => {
|
||||
results.forEach((inputPeer: any) => {
|
||||
let peerID = appPeersManager.getPeerID(inputPeer);
|
||||
let peer = appPeersManager.getPeer(peerID);
|
||||
let originalDialog = appMessagesManager.getDialogByPeerID(peerID)[0];
|
||||
|
||||
this.log('contacts peer', peer);
|
||||
|
||||
if(!originalDialog) {
|
||||
this.log('no original dialog by peerID:', peerID);
|
||||
|
||||
originalDialog = {
|
||||
peerID: peerID,
|
||||
pFlags: {},
|
||||
peer: peer
|
||||
};
|
||||
}
|
||||
|
||||
let {dialog, dom} = appDialogsManager.addDialog(originalDialog, group.list, false);
|
||||
|
||||
if(showMembersCount && (peer.participants_count || peer.participants)) {
|
||||
let isChannel = appPeersManager.isChannel(peerID) && !appPeersManager.isMegagroup(peerID);
|
||||
let participants_count = peer.participants_count || peer.participants.participants.length;
|
||||
let subtitle = numberWithCommas(participants_count) + ' ' + (isChannel ? 'subscribers' : 'members');
|
||||
dom.lastMessageSpan.innerText = subtitle;
|
||||
} else {
|
||||
let username = appPeersManager.getPeerUsername(peerID);
|
||||
if(!username) {
|
||||
let user = appUsersManager.getUser(peerID);
|
||||
if(user && user.phone) {
|
||||
username = '+' + formatPhoneNumber(user.phone).formatted;
|
||||
}
|
||||
} else {
|
||||
username = '@' + username;
|
||||
}
|
||||
|
||||
dom.lastMessageSpan.innerText = username;
|
||||
}
|
||||
});
|
||||
|
||||
if(results.length) {
|
||||
group.setActive();
|
||||
}
|
||||
};
|
||||
|
||||
setResults(contacts.my_results, this.searchGroups.contacts, true);
|
||||
setResults(contacts.results, this.searchGroups.globalContacts);
|
||||
});
|
||||
}
|
||||
|
||||
return this.searchPromise = appMessagesManager.getSearch(this.peerID, query, null, maxID, 20, this.offsetRate).then(res => {
|
||||
this.searchPromise = null;
|
||||
|
||||
@ -260,6 +369,9 @@ class AppSidebarLeft {
|
||||
history.shift();
|
||||
}
|
||||
|
||||
let searchGroup = this.searchGroups[this.peerID ? 'privateMessages' : 'globalMessages'];
|
||||
searchGroup.setActive();
|
||||
|
||||
history.forEach((msgID: number) => {
|
||||
let message = appMessagesManager.getMessage(msgID);
|
||||
let originalDialog = appMessagesManager.getDialogByPeerID(message.peerID)[0];
|
||||
@ -274,7 +386,7 @@ class AppSidebarLeft {
|
||||
};
|
||||
}
|
||||
|
||||
let {dialog, dom} = appDialogsManager.addDialog(originalDialog, this.searchMessagesList, false);
|
||||
let {dialog, dom} = appDialogsManager.addDialog(originalDialog, searchGroup.list, false);
|
||||
appDialogsManager.setLastMessage(dialog, message, dom);
|
||||
});
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { LazyLoadQueue, horizontalMenu, wrapDocument, formatPhoneNumber } from "../../components/misc";
|
||||
import { horizontalMenu, formatPhoneNumber } from "../../components/misc";
|
||||
import Scrollable from '../../components/scrollable';
|
||||
import { isElementInViewport, $rootScope } from "../utils";
|
||||
import appMessagesManager from "./appMessagesManager";
|
||||
@ -10,6 +10,8 @@ import { RichTextProcessor } from "../richtextprocessor";
|
||||
import { logger } from "../polyfill";
|
||||
import appImManager from "./appImManager";
|
||||
import appMediaViewer from "./appMediaViewer";
|
||||
import LazyLoadQueue from "../../components/lazyLoadQueue";
|
||||
import { wrapDocument } from "../../components/wrappers";
|
||||
|
||||
class AppSidebarRight {
|
||||
public sidebarEl = document.querySelector('.profile-container') as HTMLDivElement;
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { MTDocument } from "../../components/misc";
|
||||
import AppStorage from '../storage';
|
||||
import { MTProto } from "../mtproto/mtproto";
|
||||
import { MTDocument } from '../../components/wrappers';
|
||||
import apiManager from '../mtproto/apiManager';
|
||||
import apiFileManager from '../mtproto/apiFileManager';
|
||||
|
||||
export type MTStickerSet = {
|
||||
_: 'stickerSet',
|
||||
@ -78,7 +79,7 @@ class appStickersManager {
|
||||
}) {
|
||||
if(this.stickerSets[set.id]) return this.stickerSets[set.id];
|
||||
|
||||
let promise = MTProto.apiManager.invokeApi('messages.getStickerSet', {
|
||||
let promise = apiManager.invokeApi('messages.getStickerSet', {
|
||||
stickerset: {
|
||||
_: 'inputStickerSetID',
|
||||
id: set.id,
|
||||
@ -132,7 +133,7 @@ class appStickersManager {
|
||||
let thumb = stickerSet.thumb;
|
||||
let dcID = stickerSet.thumb_dc_id;
|
||||
|
||||
let promise = MTProto.apiFileManager.downloadSmallFile({
|
||||
let promise = apiFileManager.downloadSmallFile({
|
||||
_: 'inputStickerSetThumb',
|
||||
stickerset: {
|
||||
_: 'inputStickerSetID',
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { SearchIndexManager, safeReplaceObject, isObject, tsNow, copy, $rootScope } from "../utils";
|
||||
import { MTProto } from "../mtproto/mtproto";
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
import appChatsManager from "./appChatsManager";
|
||||
import apiManager from "../mtproto/apiManager";
|
||||
import serverTimeManager from "../mtproto/serverTimeManager";
|
||||
|
||||
export class AppUsersManager {
|
||||
public users: any = {};
|
||||
@ -13,7 +15,7 @@ export class AppUsersManager {
|
||||
public myID: number;
|
||||
|
||||
constructor() {
|
||||
MTProto.apiManager.getUserID().then((id) => {
|
||||
apiManager.getUserID().then((id) => {
|
||||
this.myID = id;
|
||||
});
|
||||
|
||||
@ -37,11 +39,11 @@ export class AppUsersManager {
|
||||
user.status = update.status;
|
||||
if(user.status) {
|
||||
if(user.status.expires) {
|
||||
user.status.expires -= MTProto.serverTimeManager.serverTimeOffset;
|
||||
user.status.expires -= serverTimeManager.serverTimeOffset;
|
||||
}
|
||||
|
||||
if(user.status.was_online) {
|
||||
user.status.was_online -= MTProto.serverTimeManager.serverTimeOffset;
|
||||
user.status.was_online -= serverTimeManager.serverTimeOffset;
|
||||
}
|
||||
}
|
||||
|
||||
@ -149,8 +151,7 @@ export class AppUsersManager {
|
||||
}
|
||||
|
||||
public saveApiUsers(apiUsers: any[]) {
|
||||
// @ts-ignore
|
||||
apiUsers.forEach(this.saveApiUser.bind(this));
|
||||
apiUsers.forEach((user) => this.saveApiUser(user));
|
||||
}
|
||||
|
||||
public saveApiUser(apiUser: any, noReplace?: boolean) {
|
||||
@ -200,11 +201,11 @@ export class AppUsersManager {
|
||||
|
||||
if(apiUser.status) {
|
||||
if(apiUser.status.expires) {
|
||||
apiUser.status.expires -= MTProto.serverTimeManager.serverTimeOffset
|
||||
apiUser.status.expires -= serverTimeManager.serverTimeOffset
|
||||
}
|
||||
|
||||
if(apiUser.status.was_online) {
|
||||
apiUser.status.was_online -= MTProto.serverTimeManager.serverTimeOffset
|
||||
apiUser.status.was_online -= serverTimeManager.serverTimeOffset
|
||||
}
|
||||
}
|
||||
|
||||
@ -349,20 +350,6 @@ export class AppUsersManager {
|
||||
return user;
|
||||
}
|
||||
|
||||
/* public openUser(userID: number, override) {
|
||||
var scope = $rootScope.$new()
|
||||
scope.userID = userID
|
||||
scope.override = override || {}
|
||||
|
||||
var modalInstance = $modal.open({
|
||||
templateUrl: templateUrl('user_modal'),
|
||||
controller: 'UserModalController',
|
||||
scope: scope,
|
||||
windowClass: 'user_modal_window mobile_modal',
|
||||
backdrop: 'single'
|
||||
})
|
||||
} */
|
||||
|
||||
/* function importContact (phone, firstName, lastName) {
|
||||
return MtpApiManager.invokeApi('contacts.importContacts', {
|
||||
contacts: [{
|
||||
@ -424,7 +411,7 @@ export class AppUsersManager {
|
||||
ids.push(this.getUserInput(userID));
|
||||
})
|
||||
|
||||
return MTProto.apiManager.invokeApi('contacts.deleteContacts', {
|
||||
return apiManager.invokeApi('contacts.deleteContacts', {
|
||||
id: ids
|
||||
}).then(() => {
|
||||
userIDs.forEach((userID) => {
|
||||
@ -433,6 +420,35 @@ export class AppUsersManager {
|
||||
});
|
||||
}
|
||||
|
||||
public getTopPeers() {
|
||||
return apiManager.invokeApi('contacts.getTopPeers', {
|
||||
flags: 1,
|
||||
correspondents: true,
|
||||
offset: 0,
|
||||
limit: 5,
|
||||
hash: 0,
|
||||
}).then((peers: any) => {
|
||||
//console.log(peers);
|
||||
this.saveApiUsers(peers.users);
|
||||
appChatsManager.saveApiChats(peers.chats);
|
||||
|
||||
return peers.categories;
|
||||
});
|
||||
}
|
||||
|
||||
public searchContacts(query: string, limit = 20) {
|
||||
return apiManager.invokeApi('contacts.search', {
|
||||
q: query,
|
||||
limit
|
||||
}).then((peers: any) => {
|
||||
//console.log(peers);
|
||||
this.saveApiUsers(peers.users);
|
||||
appChatsManager.saveApiChats(peers.chats);
|
||||
|
||||
return peers;
|
||||
});
|
||||
}
|
||||
|
||||
public onContactUpdated(userID: number, isContact: boolean) {
|
||||
userID = parseInt('' + userID);
|
||||
|
||||
@ -453,19 +469,6 @@ export class AppUsersManager {
|
||||
}
|
||||
}
|
||||
|
||||
/* function openImportContact () {
|
||||
return $modal.open({
|
||||
templateUrl: templateUrl('import_contact_modal'),
|
||||
controller: 'ImportContactModalController',
|
||||
windowClass: 'md_simple_modal_window mobile_modal'
|
||||
}).result.then(function (foundUserID) {
|
||||
if (!foundUserID) {
|
||||
return $q.reject()
|
||||
}
|
||||
return foundUserID
|
||||
})
|
||||
} */
|
||||
|
||||
public setUserStatus(userID: number, offline: boolean) {
|
||||
if(this.isBot(userID)) {
|
||||
return;
|
||||
|
@ -8,7 +8,7 @@ var EmojiHelper = {
|
||||
|
||||
var emojiData = Config.Emoji;
|
||||
var emojiIconSize = emojiData.img_size;
|
||||
var emojiSupported = navigator.userAgent.search(/OS X|iPhone|iPad|iOS|Android/i) != -1 && false,
|
||||
var emojiSupported = navigator.userAgent.search(/OS X|iPhone|iPad|iOS|Android/i) != -1/* && false */,
|
||||
emojiCode;
|
||||
//var emojiRegExp = '\\u0023\\u20E3|\\u00a9|\\u00ae|\\u203c|\\u2049|\\u2139|[\\u2194-\\u2199]|\\u21a9|\\u21aa|\\u231a|\\u231b|\\u23e9|[\\u23ea-\\u23ec]|\\u23f0|\\u24c2|\\u25aa|\\u25ab|\\u25b6|\\u2611|\\u2614|\\u26fd|\\u2705|\\u2709|[\\u2795-\\u2797]|\\u27a1|\\u27b0|\\u27bf|\\u2934|\\u2935|[\\u2b05-\\u2b07]|\\u2b1b|\\u2b1c|\\u2b50|\\u2b55|\\u3030|\\u303d|\\u3297|\\u3299|[\\uE000-\\uF8FF\\u270A-\\u2764\\u2122\\u25C0\\u25FB-\\u25FE\\u2615\\u263a\\u2648-\\u2653\\u2660-\\u2668\\u267B\\u267F\\u2693\\u261d\\u26A0-\\u26FA\\u2708\\u2702\\u2601\\u260E]|[\\u2600\\u26C4\\u26BE\\u23F3\\u2764]|\\uD83D[\\uDC00-\\uDFFF]|\\uD83C[\\uDDE8-\\uDDFA\uDDEC]\\uD83C[\\uDDEA-\\uDDFA\uDDE7]|[0-9]\\u20e3|\\uD83C[\\uDC00-\\uDFFF]';
|
||||
//var emojiRegExp = '\\u00a9|\\u00ae|[\\u2000-\\u3300]|\\ud83c[\\ud000-\\udfff]|\\ud83d[\\ud000-\\udfff]|\\ud83e[\\ud000-\\udfff]';
|
||||
|
@ -137,6 +137,12 @@
|
||||
box-sizing: border-box;
|
||||
min-height: 100%;
|
||||
justify-content: flex-end;
|
||||
|
||||
&.is-chat {
|
||||
.in {
|
||||
padding-left: 36px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.service {
|
||||
@ -474,12 +480,12 @@
|
||||
|
||||
.user-avatar {
|
||||
position: absolute;
|
||||
left: -2.5rem;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
left: -3rem;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
bottom: 0;
|
||||
font-size: .85rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
&:not(.forwarded).hide-name, &.emoji-big {
|
||||
@ -657,18 +663,28 @@
|
||||
}
|
||||
}
|
||||
|
||||
.bubble.read {
|
||||
.bubble.is-read {
|
||||
.time .tgico:after {
|
||||
content: $tgico-checks;
|
||||
}
|
||||
}
|
||||
|
||||
.bubble.sent {
|
||||
.bubble.is-sent {
|
||||
.time .tgico:after {
|
||||
content: $tgico-check;
|
||||
}
|
||||
}
|
||||
|
||||
.bubble.is-sending {
|
||||
.time .tgico:after {
|
||||
content: $tgico-sending;
|
||||
}
|
||||
}
|
||||
|
||||
.bubble.is-reply .name {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.bubble {
|
||||
background-color: #eeffde;
|
||||
border-radius: 12px 6px 6px 12px;
|
||||
|
@ -46,6 +46,7 @@
|
||||
display: grid;
|
||||
grid-auto-columns: 1fr;
|
||||
/* grid-gap: 4px; */
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
li {
|
||||
@ -133,11 +134,19 @@
|
||||
.user-title {
|
||||
max-width: 80%;
|
||||
|
||||
.emoji {
|
||||
img.emoji {
|
||||
vertical-align: top;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
span.emoji {
|
||||
overflow: visible;
|
||||
margin: 0;
|
||||
width: auto;
|
||||
font-size: 14px;
|
||||
vertical-align: unset;
|
||||
}
|
||||
}
|
||||
|
||||
.user-last-message {
|
||||
@ -148,11 +157,15 @@
|
||||
color: $darkblue;
|
||||
}
|
||||
|
||||
.emoji {
|
||||
font-size: 1.2rem;
|
||||
img.emoji {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
span.emoji {
|
||||
font-size: 1.2rem;
|
||||
margin: 0 .125rem;
|
||||
overflow: visible;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@
|
||||
content: "\e918";
|
||||
}
|
||||
.tgico-sending:before {
|
||||
content: "\e919";
|
||||
content: $tgico-sending;
|
||||
}
|
||||
.tgico-sendingerror:before {
|
||||
content: "\e91a";
|
||||
|
@ -3,3 +3,4 @@ $tgico-font-path: "../../assets/fonts" !default;
|
||||
|
||||
$tgico-check: "\e900";
|
||||
$tgico-checks: "\e95a";
|
||||
$tgico-sending: "\e919";
|
||||
|
@ -21,7 +21,7 @@
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#search-container {
|
||||
#search-container, #chats-archived-container {
|
||||
display: none;
|
||||
width: 100%;
|
||||
max-height: 100%;
|
||||
@ -37,4 +37,17 @@
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.search-group {
|
||||
width: 100%;
|
||||
border-bottom: 1px solid #DADCE0;
|
||||
padding: 1rem 0 .5rem;
|
||||
margin-bottom: .5rem;
|
||||
|
||||
&__name {
|
||||
color: $color-gray;
|
||||
padding: 0 1.85rem;
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -314,7 +314,10 @@ input {
|
||||
}
|
||||
.c-ripple.active .c-ripple__circle {
|
||||
//-webkit-animation: a-ripple 750ms ease-in;
|
||||
animation: a-ripple 750ms ease-in-out;
|
||||
//animation: a-ripple 750ms ease-in-out;
|
||||
will-change: padding-bottom, width, opacity;
|
||||
-webkit-animation: a-ripple 625ms ease-in-out;
|
||||
animation: a-ripple 625ms ease-in-out;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -324,6 +327,7 @@ input {
|
||||
@-webkit-keyframes a-ripple {
|
||||
0% {
|
||||
opacity: 0;
|
||||
//opacity: 1;
|
||||
}
|
||||
25% {
|
||||
opacity: 1;
|
||||
@ -337,6 +341,7 @@ input {
|
||||
@keyframes a-ripple {
|
||||
0% {
|
||||
opacity: 0;
|
||||
//opacity: 1;
|
||||
}
|
||||
25% {
|
||||
opacity: 1;
|
||||
@ -397,6 +402,12 @@ input {
|
||||
}
|
||||
}
|
||||
|
||||
&.photo {
|
||||
.document-ico {
|
||||
border-radius: $border-radius;
|
||||
}
|
||||
}
|
||||
|
||||
.document-name {
|
||||
white-space: nowrap;
|
||||
font-weight: 500;
|
||||
@ -488,7 +499,7 @@ input {
|
||||
transform: translateY(-50%);
|
||||
background-color: #fff;
|
||||
font-size: 0.85rem;
|
||||
transition: .2s all;
|
||||
transition: .2s all, .1s opacity;
|
||||
display: inline-block;
|
||||
cursor: text;
|
||||
}
|
||||
@ -542,6 +553,8 @@ input {
|
||||
transform: none;
|
||||
padding: 0 5px;
|
||||
left: 7.5px;
|
||||
font-size: 0.85rem!important;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -930,8 +943,6 @@ $width: 100px;
|
||||
display: inline-block;
|
||||
/* width: 100%;
|
||||
height: 100%; */
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
vertical-align: middle;
|
||||
@ -940,7 +951,11 @@ $width: 100px;
|
||||
font-size: 1em;
|
||||
|
||||
font-family: apple color emoji,segoe ui emoji,noto color emoji,android emoji,emojisymbols,emojione mozilla,twemoji mozilla,segoe ui symbol;
|
||||
}
|
||||
|
||||
img.emoji {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.popup {
|
||||
@ -1309,6 +1324,7 @@ div.scrollable::-webkit-scrollbar-thumb {
|
||||
|
||||
.popup-send-photo {
|
||||
.popup-container {
|
||||
width: 420px;
|
||||
max-width: 420px;
|
||||
max-height: 425px;
|
||||
overflow: hidden;
|
||||
@ -1352,6 +1368,7 @@ div.scrollable::-webkit-scrollbar-thumb {
|
||||
justify-content: center;
|
||||
width: fit-content;
|
||||
border-radius: $border-radius-medium;
|
||||
margin: 0 auto;
|
||||
/* align-items: center; */
|
||||
|
||||
.document {
|
||||
@ -1366,6 +1383,12 @@ div.scrollable::-webkit-scrollbar-thumb {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* &.photo {
|
||||
.document-ico {
|
||||
border-radius: $border-radius;
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
img {
|
||||
@ -1381,6 +1404,15 @@ div.scrollable::-webkit-scrollbar-thumb {
|
||||
font-size: 1.15rem;
|
||||
padding: 0 15px;
|
||||
border-radius: $border-radius-medium;
|
||||
|
||||
&:focus {
|
||||
padding: 0 14.5px;
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: inherit;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user