Browse Source

Search messages pagination

master
Eduard Kuzmenko 5 years ago
parent
commit
70324b96ad
  1. BIN
      .DS_Store
  2. 1
      .gitignore
  3. 139
      src/components/misc.ts
  4. 18
      src/lib/appManagers/appDialogsManager.ts
  5. 110
      src/lib/appManagers/appImManager.ts
  6. 32
      src/lib/appManagers/appMediaViewer.ts
  7. 16
      src/lib/appManagers/appMessagesManager.ts
  8. 12
      src/lib/appManagers/appPhotosManager.ts
  9. 153
      src/lib/appManagers/appSidebarLeft.ts
  10. 1
      src/lib/appManagers/appSidebarRight.ts
  11. 12
      src/lib/services.ts
  12. 11
      src/scss/partials/_chat.scss
  13. 130
      src/scss/style.scss
  14. 9665
      stats.json

BIN
.DS_Store vendored

Binary file not shown.

1
.gitignore vendored

@ -2,3 +2,4 @@ node_modules @@ -2,3 +2,4 @@ node_modules
coverage
__pycache__
dist
.DS_Store

139
src/components/misc.ts

@ -5,6 +5,8 @@ import CryptoWorker from '../lib/crypto/cryptoworker'; @@ -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 = { @@ -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 { @@ -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 @@ -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 @@ -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) { @@ -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) { @@ -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?: ( @@ -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, @@ -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;

18
src/lib/appManagers/appDialogsManager.ts

@ -2,13 +2,23 @@ import { MTProto } from "../mtproto/mtproto"; @@ -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 { @@ -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;
}

110
src/lib/appManagers/appImManager.ts

@ -4,7 +4,7 @@ import appUsersManager from "./appUsersManager"; @@ -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 { @@ -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 { @@ -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 { @@ -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) {
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);
});
appPhotosManager.savePhoto(webpage.photo); // hot-fix because no webpage manager
this.loadMediaQueuePush(load);
wrapPhoto.call(this, webpage.photo, message, preview);
}
if(preview) {
@ -943,18 +884,7 @@ export class AppImManager { @@ -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 { @@ -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';

32
src/lib/appManagers/appMediaViewer.ts

@ -7,8 +7,9 @@ import { $rootScope } from "../utils"; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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();
}

16
src/lib/appManagers/appMessagesManager.ts

@ -1639,7 +1639,11 @@ export class AppMessagesManager { @@ -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 { @@ -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 { @@ -1756,6 +1761,7 @@ export class AppMessagesManager {
return Promise.resolve({
count: 0,
next_rate: 0,
history: foundMsgs
});
}
@ -1793,7 +1799,7 @@ export class AppMessagesManager { @@ -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 { @@ -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 { @@ -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);
});
}

12
src/lib/appManagers/appPhotosManager.ts

@ -151,13 +151,13 @@ export class AppPhotosManager { @@ -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 { @@ -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') {

153
src/lib/appManagers/appSidebarLeft.ts

@ -2,91 +2,88 @@ import { logger } from "../polyfill"; @@ -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 { @@ -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();

1
src/lib/appManagers/appSidebarRight.ts

@ -9,7 +9,6 @@ import { RichTextProcessor } from "../richtextprocessor"; @@ -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;

12
src/lib/services.ts

@ -30,18 +30,6 @@ export const appStickersManager = AppStickersManager; @@ -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,

11
src/scss/partials/_chat.scss

@ -237,7 +237,8 @@ @@ -237,7 +237,8 @@
.box.web {
width: min-content;
max-width: min-content;
/* max-width: min-content; */
max-width: 100%;
}
}
@ -248,7 +249,8 @@ @@ -248,7 +249,8 @@
}
img, video {
object-fit: contain;
/* object-fit: contain; */
object-fit: cover;
}
.emoji {
@ -361,14 +363,17 @@ @@ -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%; */
}
}
}

130
src/scss/style.scss

@ -32,6 +32,7 @@ $time-size: 12px; @@ -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; @@ -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

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save