Search messages pagination
This commit is contained in:
parent
971135ff8b
commit
70324b96ad
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@ node_modules
|
||||
coverage
|
||||
__pycache__
|
||||
dist
|
||||
.DS_Store
|
||||
|
@ -5,6 +5,8 @@ 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';
|
||||
|
||||
export type MTDocument = {
|
||||
_: 'document',
|
||||
@ -39,50 +41,50 @@ export type MTPhotoSize = {
|
||||
|
||||
let onRippleClick = function(this: HTMLElement, e: MouseEvent) {
|
||||
var $circle = this.firstElementChild as HTMLSpanElement;//this.querySelector('.c-ripple__circle') as HTMLSpanElement;
|
||||
|
||||
|
||||
var rect = this.parentElement.getBoundingClientRect();
|
||||
var x = e.clientX - rect.left; //x position within the element.
|
||||
var y = e.clientY - rect.top;
|
||||
|
||||
|
||||
/* var x = e.pageX - this.parentElement.offsetLeft;
|
||||
var y = e.pageY - this.parentElement.offsetTop - this.parentElement.scrollHeight; */
|
||||
|
||||
|
||||
$circle.style.top = y + 'px';
|
||||
$circle.style.left = x + 'px';
|
||||
|
||||
|
||||
this.classList.add('active');
|
||||
|
||||
|
||||
//console.log('onrippleclick', e/* e.pageY, this.parentElement.offsetTop */);
|
||||
};
|
||||
|
||||
export function ripple(elem: Element) {
|
||||
/* elem.addEventListener('click', function(e) {
|
||||
var $circle = elem.querySelector('.c-ripple__circle') as HTMLSpanElement;
|
||||
|
||||
|
||||
var x = e.pageX - elem.offsetLeft;
|
||||
var y = e.pageY - elem.offsetTop;
|
||||
|
||||
|
||||
$circle.style.top = y + 'px';
|
||||
$circle.style.left = x + 'px';
|
||||
|
||||
|
||||
elem.classList.add('active');
|
||||
}); */
|
||||
|
||||
|
||||
let r = document.createElement('div');
|
||||
r.classList.add('c-ripple');
|
||||
|
||||
|
||||
let span = document.createElement('span');
|
||||
span.classList.add('c-ripple__circle');
|
||||
|
||||
|
||||
r.append(span);
|
||||
elem.append(r);
|
||||
|
||||
|
||||
r.addEventListener('click', onRippleClick);
|
||||
|
||||
|
||||
let onEnd = () => {
|
||||
r.classList.remove('active');
|
||||
};
|
||||
|
||||
|
||||
for(let type of ['animationend', 'webkitAnimationEnd', 'oanimationend', 'MSAnimationEnd']) {
|
||||
r.addEventListener(type, onEnd);
|
||||
}
|
||||
@ -213,9 +215,20 @@ export class LazyLoadQueue {
|
||||
}
|
||||
}
|
||||
|
||||
export function wrapVideo(doc: MTDocument, container: HTMLDivElement, middleware: () => boolean, messageID: number, justLoader = true, preloader?: ProgressivePreloader) {
|
||||
if(!container.firstElementChild || container.firstElementChild.tagName != 'IMG') {
|
||||
export function wrapVideo(this: any, doc: MTDocument, container: HTMLDivElement, message: any, justLoader = true, preloader?: ProgressivePreloader) {
|
||||
//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();
|
||||
@ -227,17 +240,18 @@ export function wrapVideo(doc: MTDocument, container: HTMLDivElement, middleware
|
||||
let loadVideo = () => {
|
||||
let promise = appDocsManager.downloadDoc(doc);
|
||||
|
||||
promise.notify = (details: {done: number, total: number}) => {
|
||||
/* promise.notify = (details: {done: number, total: number}) => {
|
||||
console.log('doc download', promise, details);
|
||||
preloader.setProgress(details.done);
|
||||
};
|
||||
}; */
|
||||
|
||||
return promise.then(blob => {
|
||||
if(!middleware()) {
|
||||
if((this.peerID ? this.peerID : this.currentMessageID) != peerID) {
|
||||
this.log.warn('peer changed');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('loaded doc:', doc, blob, container.firstElementChild);
|
||||
console.log('loaded doc:', doc, blob, container);
|
||||
|
||||
let video = document.createElement('video');
|
||||
video.loop = true;
|
||||
@ -245,52 +259,50 @@ export function wrapVideo(doc: MTDocument, container: HTMLDivElement, middleware
|
||||
|
||||
if(!justLoader) {
|
||||
video.controls = true;
|
||||
} else {
|
||||
video.volume = 0;
|
||||
}
|
||||
|
||||
video.setAttribute('message-id', '' + messageID);
|
||||
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);
|
||||
|
||||
if(container.firstElementChild) {
|
||||
container.firstElementChild.remove();
|
||||
}
|
||||
|
||||
preloader.detach();
|
||||
});
|
||||
};
|
||||
|
||||
if(doc.type == 'gif') {
|
||||
return loadVideo();
|
||||
return this.peerID ? this.loadMediaQueuePush(loadVideo) : loadVideo();
|
||||
} else { // if video
|
||||
return appPhotosManager.preloadPhoto(doc).then((blob) => {
|
||||
if(!middleware()) {
|
||||
let load = () => appPhotosManager.preloadPhoto(doc).then((blob) => {
|
||||
if((this.peerID ? this.peerID : this.currentMessageID) != peerID) {
|
||||
this.log.warn('peer changed');
|
||||
return;
|
||||
}
|
||||
|
||||
if(container.firstElementChild) {
|
||||
container.firstElementChild.remove();
|
||||
}
|
||||
|
||||
let image = new Image();
|
||||
image.src = URL.createObjectURL(blob);
|
||||
|
||||
img.src = URL.createObjectURL(blob);
|
||||
|
||||
/* image.style.height = doc.h + 'px';
|
||||
image.style.width = doc.w + 'px'; */
|
||||
|
||||
image.setAttribute('message-id', '' + messageID);
|
||||
|
||||
container.append(image);
|
||||
|
||||
if(!justLoader) {
|
||||
return loadVideo();
|
||||
} else {
|
||||
preloader.detach();
|
||||
}
|
||||
});
|
||||
|
||||
return this.peerID ? this.loadMediaQueuePush(load) : load();
|
||||
}
|
||||
}
|
||||
|
||||
@ -335,10 +347,10 @@ export function scrollable(el: HTMLDivElement, x = false, y = true) {
|
||||
container.classList.add('scrollable');
|
||||
if(x) container.classList.add('scrollable-x');
|
||||
if(y) container.classList.add('scrollable-y');
|
||||
|
||||
|
||||
container.addEventListener('mouseover', () => {
|
||||
container.classList.add('active');
|
||||
|
||||
|
||||
container.addEventListener('mouseout', () => {
|
||||
container.classList.remove('active');
|
||||
}, {once: true});
|
||||
@ -350,6 +362,37 @@ export function scrollable(el: HTMLDivElement, x = false, y = true) {
|
||||
return container;
|
||||
}
|
||||
|
||||
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();
|
||||
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();
|
||||
});
|
||||
|
||||
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) {
|
||||
let stickerType = doc.mime_type == "application/x-tgsticker" ? 2 : (doc.mime_type == "image/webp" ? 1 : 0);
|
||||
|
||||
@ -399,24 +442,24 @@ export function wrapSticker(doc: MTDocument, div: HTMLDivElement, middleware?: (
|
||||
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;
|
||||
@ -451,11 +494,11 @@ export function horizontalMenu(tabs: HTMLUListElement, content: HTMLDivElement,
|
||||
|
||||
tabs.addEventListener('click', function(e) {
|
||||
let target = e.target as HTMLLIElement;
|
||||
|
||||
|
||||
if(target.tagName != 'LI') {
|
||||
target = findUpTag(target, 'LI');
|
||||
}
|
||||
|
||||
|
||||
console.log('tabs click:', target);
|
||||
|
||||
if(target.classList.contains('active')) return false;
|
||||
|
@ -2,13 +2,23 @@ import { MTProto } from "../mtproto/mtproto";
|
||||
import { $rootScope, findUpTag } from "../utils";
|
||||
import appImManager from "./appImManager";
|
||||
import appPeersManager from './appPeersManager';
|
||||
import { DialogDom } from "../services";
|
||||
import appMessagesManager from "./appMessagesManager";
|
||||
import appUsersManager from "./appUsersManager";
|
||||
import appSidebarRight from "./appSidebarRight";
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
import { ripple } from "../../components/misc";
|
||||
|
||||
type DialogDom = {
|
||||
avatarDiv: HTMLDivElement,
|
||||
captionDiv: HTMLDivElement,
|
||||
titleSpan: HTMLSpanElement,
|
||||
statusSpan: HTMLSpanElement,
|
||||
lastTimeSpan: HTMLSpanElement,
|
||||
unreadMessagesSpan: HTMLSpanElement,
|
||||
lastMessageSpan: HTMLSpanElement,
|
||||
listEl: HTMLLIElement
|
||||
};
|
||||
|
||||
export class AppDialogsManager {
|
||||
public pinnedChatList = document.getElementById('dialogs-pinned') as HTMLUListElement;
|
||||
public chatList = document.getElementById('dialogs') as HTMLUListElement;
|
||||
@ -190,13 +200,13 @@ export class AppDialogsManager {
|
||||
}
|
||||
|
||||
if(document.type == 'video') {
|
||||
lastMessageText += '<i>Video</i>';
|
||||
lastMessageText = '<i>Video' + (lastMessage.message ? ', ' : '') + '</i>';
|
||||
found = true;
|
||||
} else if(document.type == 'voice') {
|
||||
lastMessageText += '<i>Voice message</i>';
|
||||
lastMessageText = '<i>Voice message</i>';
|
||||
found = true;
|
||||
} else if(document.type == 'gif') {
|
||||
lastMessageText += '<i>GIF</i>';
|
||||
lastMessageText = '<i>GIF' + (lastMessage.message ? ', ' : '') + '</i>';
|
||||
found = true;
|
||||
}
|
||||
|
||||
|
@ -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 } from "../../components/misc";
|
||||
import { ProgressivePreloader, wrapDocument, wrapSticker, wrapVideo, wrapPhoto } from "../../components/misc";
|
||||
import appDialogsManager from "./appDialogsManager";
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
import appPhotosManager from "./appPhotosManager";
|
||||
@ -121,7 +121,7 @@ export class AppImManager {
|
||||
public scroll: HTMLDivElement = null;
|
||||
public scrollPosition: ScrollPosition = null;
|
||||
|
||||
private log: ReturnType<typeof logger>;
|
||||
public log: ReturnType<typeof logger>;
|
||||
|
||||
private preloader: ProgressivePreloader = null;
|
||||
|
||||
@ -763,28 +763,9 @@ export class AppImManager {
|
||||
let photo = message.media.photo;
|
||||
this.log('messageMediaPhoto', photo);
|
||||
|
||||
bubble.classList.add('photo');
|
||||
bubble.classList.add('hide-name', 'photo');
|
||||
|
||||
let size = appPhotosManager.setAttachmentSize(photo.id, attachmentDiv);
|
||||
let load = () => appPhotosManager.preloadPhoto(photo.id, size).then((blob) => {
|
||||
if(this.peerID != peerID) {
|
||||
this.log.warn('peer changed');
|
||||
return;
|
||||
}
|
||||
|
||||
if(attachmentDiv.firstElementChild) {
|
||||
attachmentDiv.firstElementChild.remove();
|
||||
}
|
||||
|
||||
let image = new Image();
|
||||
image.src = URL.createObjectURL(blob);
|
||||
image.setAttribute('message-id', message.mid);
|
||||
attachmentDiv.append(image);
|
||||
});
|
||||
|
||||
bubble.classList.add('hide-name');
|
||||
|
||||
this.loadMediaQueuePush(load);
|
||||
wrapPhoto.call(this, photo, message, attachmentDiv);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -827,58 +808,18 @@ export class AppImManager {
|
||||
doc = webpage.document;
|
||||
|
||||
if(doc.type == 'gif' || doc.type == 'video') {
|
||||
appPhotosManager.setAttachmentSize(doc, preview);
|
||||
|
||||
bubble.classList.add('video');
|
||||
|
||||
let load = () => wrapVideo(doc, preview, () => {
|
||||
if(this.peerID != peerID) {
|
||||
this.log.warn('peer changed');
|
||||
return false;
|
||||
}
|
||||
|
||||
loadedVideo = true;
|
||||
|
||||
return true;
|
||||
}, message.mid);
|
||||
|
||||
this.loadMediaQueuePush(load);
|
||||
wrapVideo.call(this, doc, preview, message);
|
||||
} else {
|
||||
doc = null;
|
||||
}
|
||||
}
|
||||
|
||||
if(webpage.photo && !doc) {
|
||||
bubble.classList.add('photo');
|
||||
appPhotosManager.savePhoto(webpage.photo); // hot-fix because no webpage manager
|
||||
|
||||
bubble.classList.add('photo');
|
||||
|
||||
let size = appPhotosManager.setAttachmentSize(webpage.photo.id, preview);
|
||||
let load = () => appPhotosManager.preloadPhoto(webpage.photo.id, size).then((blob) => {
|
||||
if(this.peerID != peerID) {
|
||||
this.log.warn('peer changed');
|
||||
return;
|
||||
}
|
||||
|
||||
if(loadedVideo) {
|
||||
return;
|
||||
}
|
||||
|
||||
let img = preview.firstElementChild as HTMLImageElement || new Image();
|
||||
this.log('night running 1', bubble, bubble.scrollHeight, img.src);
|
||||
|
||||
//setTimeout(() => {
|
||||
img.src = URL.createObjectURL(blob);
|
||||
///}, 5e3);
|
||||
|
||||
if(!preview.contains(img)) {
|
||||
preview.append(img);
|
||||
}
|
||||
|
||||
this.log('night running 2', bubble, bubble.scrollHeight);
|
||||
});
|
||||
|
||||
this.loadMediaQueuePush(load);
|
||||
wrapPhoto.call(this, webpage.photo, message, preview);
|
||||
}
|
||||
|
||||
if(preview) {
|
||||
@ -943,18 +884,7 @@ export class AppImManager {
|
||||
this.log('never get free 2', doc);
|
||||
|
||||
bubble.classList.add('video');
|
||||
|
||||
appPhotosManager.setAttachmentSize(doc, attachmentDiv);
|
||||
let load = () => wrapVideo(doc, attachmentDiv, () => {
|
||||
if(this.peerID != peerID) {
|
||||
this.log.warn('peer changed');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}, message.mid);
|
||||
|
||||
this.loadMediaQueuePush(load);
|
||||
wrapVideo.call(this, doc, attachmentDiv, message);
|
||||
|
||||
break;
|
||||
} else {
|
||||
@ -1055,19 +985,21 @@ export class AppImManager {
|
||||
//}
|
||||
}
|
||||
|
||||
let avatarDiv = document.createElement('div');
|
||||
avatarDiv.classList.add('user-avatar');
|
||||
if(!our && this.peerID < 0) {
|
||||
let avatarDiv = document.createElement('div');
|
||||
avatarDiv.classList.add('user-avatar');
|
||||
|
||||
this.log('exec loadDialogPhoto', message);
|
||||
if(message.fromID) { // if no - user hidden
|
||||
appDialogsManager.loadDialogPhoto(avatarDiv, message.fromID);
|
||||
} else if(!title && message.fwd_from && message.fwd_from.from_name) {
|
||||
title = message.fwd_from.from_name;
|
||||
|
||||
this.log('exec loadDialogPhoto', message);
|
||||
if(message.fromID) { // if no - user hidden
|
||||
appDialogsManager.loadDialogPhoto(avatarDiv, message.fromID);
|
||||
} else if(!title && message.fwd_from && message.fwd_from.from_name) {
|
||||
title = message.fwd_from.from_name;
|
||||
|
||||
appDialogsManager.loadDialogPhoto(avatarDiv, title);
|
||||
appDialogsManager.loadDialogPhoto(avatarDiv, title);
|
||||
}
|
||||
|
||||
bubble.append(avatarDiv);
|
||||
}
|
||||
|
||||
bubble.append(avatarDiv);
|
||||
}
|
||||
|
||||
let type = our ? 'out' : 'in';
|
||||
|
@ -7,8 +7,9 @@ import { $rootScope } from "../utils";
|
||||
import appMessagesManager from "./appMessagesManager";
|
||||
import { CancellablePromise } from "../mtproto/apiFileManager";
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
import { logger } from "../polyfill";
|
||||
|
||||
class AppMediaViewer {
|
||||
export class AppMediaViewer {
|
||||
private overlaysDiv = document.querySelector('.overlays') as HTMLDivElement;
|
||||
private author = {
|
||||
avatarEl: this.overlaysDiv.querySelector('.user-avatar') as HTMLDivElement,
|
||||
@ -29,17 +30,21 @@ class AppMediaViewer {
|
||||
};
|
||||
|
||||
private reverse = false;
|
||||
private currentMessageID = 0;
|
||||
public currentMessageID = 0;
|
||||
private higherMsgID: number | undefined = 0;
|
||||
private lowerMsgID: number | undefined = 0;
|
||||
private preloader: ProgressivePreloader = null;
|
||||
|
||||
public log: ReturnType<typeof logger>;
|
||||
|
||||
constructor() {
|
||||
this.log = logger('AMV');
|
||||
this.preloader = new ProgressivePreloader();
|
||||
|
||||
this.buttons.close.addEventListener('click', () => {
|
||||
this.overlaysDiv.classList.remove('active');
|
||||
this.content.container.innerHTML = '';
|
||||
this.currentMessageID = 0;
|
||||
});
|
||||
|
||||
this.buttons.prev.addEventListener('click', () => {
|
||||
@ -127,7 +132,7 @@ class AppMediaViewer {
|
||||
}
|
||||
|
||||
public openMedia(message: any, reverse = false) {
|
||||
console.log('openMedia doc:', message);
|
||||
this.log('openMedia doc:', message);
|
||||
let media = message.media.photo || message.media.document || message.media.webpage.document;
|
||||
|
||||
let isVideo = media.mime_type == 'video/mp4';
|
||||
@ -138,7 +143,7 @@ class AppMediaViewer {
|
||||
let container = this.content.container;
|
||||
|
||||
if(container.firstElementChild) {
|
||||
container.firstElementChild.remove();
|
||||
container.innerHTML = '';
|
||||
}
|
||||
|
||||
let date = new Date(media.date * 1000);
|
||||
@ -163,21 +168,12 @@ class AppMediaViewer {
|
||||
this.overlaysDiv.classList.add('active');
|
||||
|
||||
if(isVideo) {
|
||||
appPhotosManager.setAttachmentSize(media, container);
|
||||
|
||||
this.preloader.attach(container);
|
||||
//this.preloader.attach(container);
|
||||
//this.preloader.setProgress(75);
|
||||
|
||||
console.log('will wrap video');
|
||||
this.log('will wrap video');
|
||||
|
||||
wrapVideo(media, container, () => {
|
||||
if(this.currentMessageID != message.mid) {
|
||||
console.warn('media viewer changed photo');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}, message.mid, false, this.preloader);
|
||||
wrapVideo.call(this, media, container, message, false, this.preloader);
|
||||
} else {
|
||||
let size = appPhotosManager.setAttachmentSize(media.id, container, appPhotosManager.windowW, appPhotosManager.windowH);
|
||||
|
||||
@ -187,11 +183,11 @@ class AppMediaViewer {
|
||||
let cancellablePromise = appPhotosManager.preloadPhoto(media.id, size);
|
||||
cancellablePromise.then((blob) => {
|
||||
if(this.currentMessageID != message.mid) {
|
||||
console.warn('media viewer changed photo');
|
||||
this.log.warn('media viewer changed photo');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('indochina', blob);
|
||||
this.log('indochina', blob);
|
||||
if(container.firstElementChild) {
|
||||
container.firstElementChild.remove();
|
||||
}
|
||||
|
@ -1639,7 +1639,11 @@ export class AppMessagesManager {
|
||||
|
||||
public getSearch(peerID = 0, query: string = '', inputFilter: {
|
||||
_?: string
|
||||
} = {_: 'inputMessagesFilterEmpty'}, maxID: number, limit: number) {
|
||||
} = {_: 'inputMessagesFilterEmpty'}, maxID: number, limit: number, offsetRate = 0): Promise<{
|
||||
count: number,
|
||||
next_rate: number,
|
||||
history: number[]
|
||||
}> {
|
||||
//peerID = peerID ? parseInt(peerID) : 0;
|
||||
var foundMsgs: number[] = [];
|
||||
var useSearchCache = !query;
|
||||
@ -1713,6 +1717,7 @@ export class AppMessagesManager {
|
||||
default:
|
||||
return Promise.resolve({
|
||||
count: 0,
|
||||
next_rate: 0,
|
||||
history: [] as number[]
|
||||
});
|
||||
}
|
||||
@ -1756,6 +1761,7 @@ export class AppMessagesManager {
|
||||
|
||||
return Promise.resolve({
|
||||
count: 0,
|
||||
next_rate: 0,
|
||||
history: foundMsgs
|
||||
});
|
||||
}
|
||||
@ -1793,7 +1799,7 @@ export class AppMessagesManager {
|
||||
|
||||
apiPromise = MTProto.apiManager.invokeApi('messages.searchGlobal', {
|
||||
q: query,
|
||||
offset_date: offsetDate,
|
||||
offset_rate: offsetRate,
|
||||
offset_peer: AppPeersManager.getInputPeerByID(offsetPeerID),
|
||||
offset_id: appMessagesIDsManager.getMessageLocalID(offsetID),
|
||||
limit: limit || 20
|
||||
@ -1808,6 +1814,8 @@ export class AppMessagesManager {
|
||||
appChatsManager.saveApiChats(searchResult.chats);
|
||||
this.saveMessages(searchResult.messages);
|
||||
|
||||
console.log('messages.search result:', searchResult);
|
||||
|
||||
var foundCount: number = searchResult.count || searchResult.messages.length;
|
||||
|
||||
foundMsgs = [];
|
||||
@ -1830,12 +1838,14 @@ export class AppMessagesManager {
|
||||
|
||||
return {
|
||||
count: foundCount,
|
||||
next_rate: searchResult.next_rate,
|
||||
history: foundMsgs
|
||||
}
|
||||
};
|
||||
}, (error) => {
|
||||
if(error.code == 400) {
|
||||
error.handled = true;
|
||||
}
|
||||
|
||||
return Promise.reject(error);
|
||||
});
|
||||
}
|
||||
|
@ -151,13 +151,13 @@ export class AppPhotosManager {
|
||||
let image = new Image();
|
||||
image.src = URL.createObjectURL(blob);
|
||||
|
||||
image.style.width = '100%';
|
||||
image.style.height = '100%';
|
||||
// image.style.width = '100%';
|
||||
// image.style.height = '100%';
|
||||
div.append(image);
|
||||
}
|
||||
}
|
||||
|
||||
public setAttachmentSize(photoID: any, div: HTMLDivElement, w = 380, h = 0) {
|
||||
public setAttachmentSize(photoID: any, div: HTMLDivElement, w = 380, h = 0/* 380 */) {
|
||||
let photo: /* MTDocument | MTPhoto */any = null;
|
||||
|
||||
if(typeof(photoID) === 'string') {
|
||||
@ -170,11 +170,9 @@ export class AppPhotosManager {
|
||||
let photoSize = this.choosePhotoSize(photo, w, h);
|
||||
//console.log('setAttachmentSize', photo, photo.sizes[0].bytes, div);
|
||||
|
||||
let thumb: any;
|
||||
let sizes = photo.sizes || photo.thumbs;
|
||||
if(sizes && (sizes[0]._ == 'photoStrippedSize' || sizes[0]._ == 'photoCachedSize' && sizes[0].bytes)) {
|
||||
thumb = sizes[0];
|
||||
this.setAttachmentPreview(thumb.bytes, div);
|
||||
if(sizes && sizes[0].bytes) {
|
||||
this.setAttachmentPreview(sizes[0].bytes, div);
|
||||
}
|
||||
|
||||
if(photo._ == 'document' /* && photo.type != 'video' */ && photo.type != 'gif') {
|
||||
|
@ -2,91 +2,88 @@ import { logger } from "../polyfill";
|
||||
import { scrollable } from "../../components/misc";
|
||||
import appMessagesManager from "./appMessagesManager";
|
||||
import appDialogsManager from "./appDialogsManager";
|
||||
import { isElementInViewport } from "../utils";
|
||||
import appMessagesIDsManager from "./appMessagesIDsManager";
|
||||
|
||||
class AppSidebarLeft {
|
||||
private sidebarEl = document.querySelector('.page-chats .chats-container') as HTMLDivElement;
|
||||
private searchInput = document.getElementById('global-search') as HTMLInputElement;
|
||||
private toolsBtn = this.sidebarEl.querySelector('.sidebar-tools-button') as HTMLButtonElement;
|
||||
private searchContainer = this.sidebarEl.querySelector('#search-container') as HTMLDivElement;
|
||||
|
||||
|
||||
private listsContainer: HTMLDivElement = null;
|
||||
private searchMessagesList: HTMLUListElement = null;
|
||||
|
||||
|
||||
private log = logger('SL');
|
||||
|
||||
|
||||
private peerID = 0;
|
||||
|
||||
private minMsgID = 0;
|
||||
private loadedCount = 0;
|
||||
private foundCount = 0;
|
||||
private offsetRate = 0;
|
||||
|
||||
private searchPromise: Promise<void> = null;
|
||||
private searchTimeout: number = 0;
|
||||
|
||||
private query = '';
|
||||
|
||||
constructor() {
|
||||
this.listsContainer = scrollable(this.searchContainer);
|
||||
this.searchMessagesList = document.createElement('ul');
|
||||
|
||||
|
||||
this.listsContainer.onscroll = this.onSidebarScroll.bind(this);
|
||||
|
||||
this.searchContainer.append(this.listsContainer);
|
||||
|
||||
|
||||
appDialogsManager.setListClickListener(this.searchMessagesList);
|
||||
|
||||
|
||||
this.searchInput.addEventListener('focus', (e) => {
|
||||
this.toolsBtn.classList.remove('tgico-menu');
|
||||
this.toolsBtn.classList.add('tgico-back');
|
||||
this.searchContainer.classList.add('active');
|
||||
|
||||
|
||||
if(!this.searchInput.value) {
|
||||
this.searchMessagesList.innerHTML = '';
|
||||
}
|
||||
|
||||
|
||||
this.searchInput.addEventListener('blur', (e) => {
|
||||
if(!this.searchInput.value) {
|
||||
this.toolsBtn.classList.add('tgico-menu');
|
||||
this.toolsBtn.classList.remove('tgico-back');
|
||||
this.searchContainer.classList.remove('active');
|
||||
}
|
||||
|
||||
this.peerID = 0;
|
||||
|
||||
/* this.peerID = 0;
|
||||
this.loadedCount = 0;
|
||||
this.minMsgID = 0; */
|
||||
}, {once: true});
|
||||
});
|
||||
|
||||
|
||||
this.searchInput.addEventListener('input', (e) => {
|
||||
//console.log('messageInput input', this.innerText, serializeNodes(Array.from(messageInput.childNodes)));
|
||||
let value = this.searchInput.value;
|
||||
this.log('input', value);
|
||||
|
||||
|
||||
if(this.listsContainer.contains(this.searchMessagesList)) {
|
||||
this.listsContainer.removeChild(this.searchMessagesList)
|
||||
}
|
||||
|
||||
|
||||
if(!value.trim()) {
|
||||
return;
|
||||
}
|
||||
|
||||
appMessagesManager.getSearch(this.peerID, value, null, 0, 20).then(res => {
|
||||
if(this.searchInput.value != value) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.log('input search result:', res);
|
||||
|
||||
let {count, history} = res;
|
||||
|
||||
this.searchMessagesList.innerHTML = '';
|
||||
|
||||
history.forEach((msgID: number) => {
|
||||
let message = appMessagesManager.getMessage(msgID);
|
||||
let originalDialog = appMessagesManager.getDialogByPeerID(message.peerID)[0];
|
||||
|
||||
if(!originalDialog) {
|
||||
this.log.warn('no original dialog by message:', msgID);
|
||||
return;
|
||||
}
|
||||
|
||||
let {dialog, dom} = appDialogsManager.addDialog(originalDialog, this.searchMessagesList, false);
|
||||
appDialogsManager.setLastMessage(dialog, message, dom);
|
||||
});
|
||||
|
||||
this.query = value;
|
||||
this.minMsgID = 0;
|
||||
this.loadedCount = 0;
|
||||
this.foundCount = 0;
|
||||
this.offsetRate = 0;
|
||||
this.searchMessagesList.innerHTML = '';
|
||||
this.searchPromise = null;
|
||||
this.searchMore().then(() => {
|
||||
this.listsContainer.append(this.searchMessagesList);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
this.toolsBtn.addEventListener('click', () => {
|
||||
if(this.toolsBtn.classList.contains('tgico-back')) {
|
||||
this.searchInput.value = '';
|
||||
@ -95,15 +92,89 @@ class AppSidebarLeft {
|
||||
this.searchContainer.classList.remove('active');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
setTimeout(() => this.onSidebarScroll(), 0);
|
||||
});
|
||||
}
|
||||
|
||||
public onSidebarScroll() {
|
||||
let elements = Array.from(this.searchMessagesList.childNodes).slice(-5);
|
||||
for(let li of elements) {
|
||||
if(isElementInViewport(li)) {
|
||||
this.log('Will load more search');
|
||||
|
||||
if(!this.searchTimeout) {
|
||||
this.searchTimeout = setTimeout(() => {
|
||||
this.searchMore();
|
||||
this.searchTimeout = 0;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public beginSearch(peerID?: number) {
|
||||
if(peerID) {
|
||||
this.peerID = peerID;
|
||||
}
|
||||
|
||||
|
||||
this.searchInput.focus();
|
||||
}
|
||||
|
||||
private searchMore() {
|
||||
if(this.searchPromise) return this.searchPromise;
|
||||
|
||||
let query = this.query;
|
||||
|
||||
if(this.loadedCount != 0 && this.loadedCount >= this.foundCount) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
let maxID = 0;//appMessagesIDsManager.getMessageIDInfo(this.minMsgID)[0] - 1;
|
||||
|
||||
return this.searchPromise = appMessagesManager.getSearch(this.peerID, query, null, maxID, 20, this.offsetRate).then(res => {
|
||||
this.searchPromise = null;
|
||||
|
||||
if(this.searchInput.value != query) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.log('input search result:', this.peerID, query, null, maxID, 20, res);
|
||||
|
||||
let {count, history, next_rate} = res;
|
||||
|
||||
if(history[0] == this.minMsgID) {
|
||||
history.shift();
|
||||
}
|
||||
|
||||
history.forEach((msgID: number) => {
|
||||
let message = appMessagesManager.getMessage(msgID);
|
||||
let originalDialog = appMessagesManager.getDialogByPeerID(message.peerID)[0];
|
||||
|
||||
if(!originalDialog) {
|
||||
this.log.warn('no original dialog by message:', msgID);
|
||||
return;
|
||||
}
|
||||
|
||||
let {dialog, dom} = appDialogsManager.addDialog(originalDialog, this.searchMessagesList, false);
|
||||
appDialogsManager.setLastMessage(dialog, message, dom);
|
||||
});
|
||||
|
||||
this.minMsgID = history[history.length - 1];
|
||||
this.offsetRate = next_rate;
|
||||
this.loadedCount += history.length;
|
||||
|
||||
if(!this.foundCount) {
|
||||
this.foundCount = count;
|
||||
}
|
||||
}).catch(err => {
|
||||
this.log.error('search error', err);
|
||||
this.searchPromise = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new AppSidebarLeft();
|
||||
|
@ -9,7 +9,6 @@ import { RichTextProcessor } from "../richtextprocessor";
|
||||
import { logger } from "../polyfill";
|
||||
import appImManager from "./appImManager";
|
||||
import appMediaViewer from "./appMediaViewer";
|
||||
import appDocsManager from "./appDocsManager";
|
||||
|
||||
class AppSidebarRight {
|
||||
public sidebarEl = document.querySelector('.profile-container') as HTMLDivElement;
|
||||
|
@ -30,18 +30,6 @@ export const appStickersManager = AppStickersManager;
|
||||
export const appSidebarRight = AppSidebarRight;
|
||||
export const appSidebarLeft = AppSidebarLeft;
|
||||
|
||||
|
||||
export type DialogDom = {
|
||||
avatarDiv: HTMLDivElement,
|
||||
captionDiv: HTMLDivElement,
|
||||
titleSpan: HTMLSpanElement,
|
||||
statusSpan: HTMLSpanElement,
|
||||
lastTimeSpan: HTMLSpanElement,
|
||||
unreadMessagesSpan: HTMLSpanElement,
|
||||
lastMessageSpan: HTMLSpanElement,
|
||||
listEl: HTMLLIElement
|
||||
};
|
||||
|
||||
(window as any).Services = {
|
||||
appUsersManager,
|
||||
appChatsManager,
|
||||
|
@ -237,7 +237,8 @@
|
||||
|
||||
.box.web {
|
||||
width: min-content;
|
||||
max-width: min-content;
|
||||
/* max-width: min-content; */
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@ -248,7 +249,8 @@
|
||||
}
|
||||
|
||||
img, video {
|
||||
object-fit: contain;
|
||||
/* object-fit: contain; */
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.emoji {
|
||||
@ -361,14 +363,17 @@
|
||||
&:not(.sticker) {
|
||||
.attachment {
|
||||
max-width: 380px;
|
||||
max-height: 380px;
|
||||
}
|
||||
}
|
||||
|
||||
&.video {
|
||||
.attachment {
|
||||
//max-height: fit-content;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/* height: 100%; */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ $time-size: 12px;
|
||||
@import "partials/chat";
|
||||
@import "partials/sidebar";
|
||||
@import "partials/leftSidebar";
|
||||
@import "partials/mediaViewer";
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
@ -1077,136 +1078,7 @@ $width: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
.media-viewer {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, .9);
|
||||
/* color: $darkgrey; */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.media-viewer-author {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 60px;
|
||||
padding: 8px 8px 8px 80px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
color: #8b8b8b;
|
||||
|
||||
.user-avatar {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
left: 20px;
|
||||
}
|
||||
|
||||
.media-viewer-name {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.media-viewer-date {
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.media-viewer-buttons {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
padding: 8px;
|
||||
|
||||
.btn-icon {
|
||||
margin: 0 .25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.media-viewer-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
|
||||
.media-viewer-stub {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.media-viewer-container {
|
||||
align-self: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.media-viewer-media {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
> img, > video {
|
||||
max-height: calc(100vh - 100px);
|
||||
max-width: calc(100vw - 16px);
|
||||
}
|
||||
}
|
||||
|
||||
.media-viewer-switcher-left, .media-viewer-switcher-right {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 10rem;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
> span {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.media-viewer-switcher-right {
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.media-viewer-prev-button, .media-viewer-next-button {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
color: #fff;
|
||||
font-size: 3rem;
|
||||
left: 2rem;
|
||||
top: 50%;
|
||||
transform: translateY(-50%) rotate(90deg);
|
||||
opacity: 0;
|
||||
transition: .2s opacity;
|
||||
z-index: 3;
|
||||
/* box-shadow: 0 1px 2px 0 rgba(16, 35, 47, 0.07); */
|
||||
}
|
||||
|
||||
.media-viewer-next-button {
|
||||
left: auto;
|
||||
right: 2rem;
|
||||
transform: translateY(-50%) rotate(-90deg);
|
||||
}
|
||||
|
||||
.media-viewer-caption {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: $darkgrey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div.scrollable-y::-webkit-scrollbar {
|
||||
/* width: 4px; */
|
||||
|
9665
stats.json
9665
stats.json
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user