Removed scrollable virtualization
Chatlist slicing (need test)
This commit is contained in:
parent
6c36941b41
commit
9ec40ea9e9
@ -81,7 +81,7 @@ export default class EmojiTab implements EmoticonsTab {
|
||||
//console.timeEnd('emojiParse');
|
||||
|
||||
const menu = this.content.previousElementSibling as HTMLElement;
|
||||
const emojiScroll = this.scroll = new Scrollable(this.content, 'EMOJI', null);
|
||||
const emojiScroll = this.scroll = new Scrollable(this.content, 'EMOJI');
|
||||
|
||||
//emojiScroll.setVirtualContainer(emojiScroll.container);
|
||||
|
||||
@ -111,7 +111,7 @@ export default class EmojiTab implements EmoticonsTab {
|
||||
console.error('no div by category:', category);
|
||||
}
|
||||
|
||||
emojiScroll.append(div);
|
||||
emojiScroll.container.append(div);
|
||||
this.stickyIntersector.observeStickyHeaderChanges(div);
|
||||
return div;
|
||||
});
|
||||
|
@ -13,7 +13,7 @@ export default class GifsTab implements EmoticonsTab {
|
||||
const gifsContainer = this.content.firstElementChild as HTMLDivElement;
|
||||
gifsContainer.addEventListener('click', EmoticonsDropdown.onMediaClick);
|
||||
|
||||
const scroll = new Scrollable(this.content, 'GIFS', null);
|
||||
const scroll = new Scrollable(this.content, 'GIFS');
|
||||
const masonry = new GifsMasonry(gifsContainer, EMOTICONSSTICKERGROUP, scroll);
|
||||
const preloader = putPreloader(this.content, true);
|
||||
|
||||
|
@ -18,6 +18,7 @@ import { wrapSticker } from "../../wrappers";
|
||||
|
||||
export default class StickersTab implements EmoticonsTab {
|
||||
public content: HTMLElement;
|
||||
private stickersDiv: HTMLElement;
|
||||
|
||||
private stickerSets: {[id: string]: {
|
||||
stickers: HTMLElement,
|
||||
@ -66,12 +67,12 @@ export default class StickersTab implements EmoticonsTab {
|
||||
this.queueCategoryPush.forEach(({element, prepend}) => {
|
||||
if(prepend) {
|
||||
if(this.recentDiv.parentElement) {
|
||||
this.scroll.prepend(element);
|
||||
this.scroll.prepend(this.recentDiv);
|
||||
this.stickersDiv.prepend(element);
|
||||
this.stickersDiv.prepend(this.recentDiv);
|
||||
} else {
|
||||
this.scroll.prepend(element);
|
||||
this.stickersDiv.prepend(element);
|
||||
}
|
||||
} else this.scroll.append(element);
|
||||
} else this.stickersDiv.append(element);
|
||||
});
|
||||
|
||||
this.queueCategoryPush.length = 0;
|
||||
@ -234,9 +235,9 @@ export default class StickersTab implements EmoticonsTab {
|
||||
|
||||
let menuScroll = new ScrollableX(menuWrapper);
|
||||
|
||||
let stickersDiv = document.createElement('div');
|
||||
stickersDiv.classList.add('stickers-categories');
|
||||
this.content.append(stickersDiv);
|
||||
this.stickersDiv = document.createElement('div');
|
||||
this.stickersDiv.classList.add('stickers-categories');
|
||||
this.content.append(this.stickersDiv);
|
||||
|
||||
/* stickersDiv.addEventListener('mouseover', (e) => {
|
||||
let target = e.target as HTMLElement;
|
||||
@ -274,10 +275,10 @@ export default class StickersTab implements EmoticonsTab {
|
||||
}
|
||||
});
|
||||
|
||||
stickersDiv.addEventListener('click', EmoticonsDropdown.onMediaClick);
|
||||
this.stickersDiv.addEventListener('click', EmoticonsDropdown.onMediaClick);
|
||||
|
||||
this.scroll = new Scrollable(this.content, 'STICKERS', undefined, undefined, 2);
|
||||
this.scroll.setVirtualContainer(stickersDiv);
|
||||
this.scroll = new Scrollable(this.content, 'STICKERS');
|
||||
this.scroll.setVirtualContainer(this.stickersDiv);
|
||||
|
||||
this.stickyIntersector = EmoticonsDropdown.menuOnClick(this.menu, this.scroll, menuScroll);
|
||||
|
||||
|
@ -2,8 +2,6 @@ import { CancellablePromise, deferredPromise } from "../helpers/cancellablePromi
|
||||
import { isTouchSupported } from "../helpers/touchSupport";
|
||||
import { logger, LogLevels } from "../lib/logger";
|
||||
import smoothscroll, { SCROLL_TIME, SmoothScrollToOptions } from '../vendor/smoothscroll';
|
||||
//import { CancellablePromise, deferredPromise } from "../lib/polyfill";
|
||||
//import { isInDOM } from "../lib/utils";
|
||||
(window as any).__forceSmoothScrollPolyfill__ = true;
|
||||
smoothscroll();
|
||||
/*
|
||||
@ -58,13 +56,9 @@ export class ScrollableBase {
|
||||
public scrollLocked = 0;
|
||||
public scrollLockedPromise: CancellablePromise<void> = Promise.resolve();
|
||||
|
||||
constructor(public el: HTMLElement, logPrefix = '', public appendTo = el, public container: HTMLElement = document.createElement('div')) {
|
||||
constructor(public el: HTMLElement, logPrefix = '', public container: HTMLElement = document.createElement('div')) {
|
||||
this.container.classList.add('scrollable');
|
||||
|
||||
if(!appendTo) {
|
||||
this.appendTo = this.container;
|
||||
}
|
||||
|
||||
this.log = logger('SCROLL' + (logPrefix ? '-' + logPrefix : ''), LogLevels.error);
|
||||
|
||||
if(el) {
|
||||
@ -80,20 +74,8 @@ export class ScrollableBase {
|
||||
this.container.addEventListener('scroll', this.onScroll, {passive: true, capture: true});
|
||||
}
|
||||
|
||||
public prepend(element: HTMLElement) {
|
||||
this.appendTo.prepend(element);
|
||||
}
|
||||
|
||||
public append(element: HTMLElement) {
|
||||
this.appendTo.append(element);
|
||||
}
|
||||
|
||||
public contains(element: Element) {
|
||||
return !!element.parentElement;
|
||||
}
|
||||
|
||||
public removeElement(element: Element) {
|
||||
element.remove();
|
||||
this.container.append(element);
|
||||
}
|
||||
|
||||
public scrollTo(value: number, side: 'top' | 'left', smooth = true, important = false, scrollTime = SCROLL_TIME) {
|
||||
@ -134,12 +116,11 @@ export class ScrollableBase {
|
||||
this.container.dispatchEvent(new CustomEvent('scroll'));
|
||||
}
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this.appendTo.childElementCount;
|
||||
}
|
||||
}
|
||||
|
||||
export type SliceSides = 'top' | 'bottom';
|
||||
export type SliceSidesContainer = {[k in SliceSides]: boolean};
|
||||
|
||||
export default class Scrollable extends ScrollableBase {
|
||||
public splitUp: HTMLElement;
|
||||
|
||||
@ -149,231 +130,31 @@ export default class Scrollable extends ScrollableBase {
|
||||
public onScrollMeasure: number = null;
|
||||
|
||||
public lastScrollTop: number = 0;
|
||||
|
||||
private disableHoverTimeout: number = 0;
|
||||
|
||||
/* private sentinelsObserver: IntersectionObserver;
|
||||
private topSentinel: HTMLDivElement;
|
||||
private bottomSentinel: HTMLDivElement; */
|
||||
|
||||
private observer: IntersectionObserver;
|
||||
private visible: Set<HTMLElement>;
|
||||
private virtualTempIDTop = 0;
|
||||
private virtualTempIDBottom = 0;
|
||||
private lastTopID = 0;
|
||||
private lastBottomID = 0;
|
||||
private lastScrollDirection = 0; // true = bottom
|
||||
public loadedAll: SliceSidesContainer = {top: true, bottom: false};
|
||||
|
||||
/* private onScrolledTopFired = false;
|
||||
private onScrolledBottomFired = false; */
|
||||
|
||||
public isVisible = false;
|
||||
|
||||
private reorderTimeout: number;
|
||||
|
||||
private setVisible(element: HTMLElement) {
|
||||
if(this.visible.has(element)) return;
|
||||
|
||||
this.log.debug('setVisible id:', element.dataset.virtual);
|
||||
(element.firstElementChild as HTMLElement).style.display = '';
|
||||
this.visible.add(element);
|
||||
}
|
||||
|
||||
private setHidden(element: HTMLElement) {
|
||||
if(!this.visible.has(element)) return;
|
||||
|
||||
this.log.debug('setHidden id:', element.dataset.virtual);
|
||||
(element.firstElementChild as HTMLElement).style.display = 'none';
|
||||
this.visible.delete(element);
|
||||
}
|
||||
|
||||
constructor(el: HTMLElement, logPrefix = '', appendTo = el, public onScrollOffset = 300, public splitCount = 15, container: HTMLElement = document.createElement('div')) {
|
||||
super(el, logPrefix, appendTo, container);
|
||||
|
||||
this.visible = new Set();
|
||||
this.observer = new IntersectionObserver(entries => {
|
||||
const filtered = entries.filter(entry => entry.isIntersecting);
|
||||
|
||||
//return;
|
||||
|
||||
//this.log('entries:', entries);
|
||||
|
||||
entries.forEach(entry => {
|
||||
const target = entry.target as HTMLElement;
|
||||
|
||||
if(entry.isIntersecting) {
|
||||
this.setVisible(target);
|
||||
|
||||
this.log.debug('intersection entry:', entry, this.lastTopID, this.lastBottomID);
|
||||
} else {
|
||||
const id = +target.dataset.virtual;
|
||||
const isTop = entry.boundingClientRect.top < 0;
|
||||
|
||||
if(isTop) {
|
||||
this.lastTopID = id + 1;
|
||||
} else {
|
||||
this.lastBottomID = id - 1;
|
||||
}
|
||||
|
||||
//this.setHidden(target);
|
||||
//this.log('intersection entry setHidden:', entry);
|
||||
}
|
||||
|
||||
//this.debug && this.log('intersection entry:', entry, isTop, isBottom, this.lastTopID, this.lastBottomID);
|
||||
});
|
||||
|
||||
if(!filtered.length || this.lastScrollDirection === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(this.lastScrollDirection === 1) { // bottom
|
||||
let target = filtered[filtered.length - 1].target as HTMLElement;
|
||||
this.lastBottomID = +target.dataset.virtual;
|
||||
|
||||
for(let i = 0; i < this.splitCount; ++i) {
|
||||
target = target.nextElementSibling as HTMLElement;
|
||||
if(!target) break;
|
||||
this.setVisible(target);
|
||||
}
|
||||
} else {
|
||||
let target = filtered[0].target as HTMLElement;
|
||||
this.lastTopID = +target.dataset.virtual;
|
||||
|
||||
for(let i = 0; i < this.splitCount; ++i) {
|
||||
target = target.previousElementSibling as HTMLElement;
|
||||
if(!target) break;
|
||||
this.setVisible(target);
|
||||
}
|
||||
}
|
||||
|
||||
this.log.debug('entries:', entries, filtered, this.lastScrollDirection, this.lastTopID, this.lastBottomID);
|
||||
|
||||
const minVisibleID = this.lastTopID - this.splitCount;
|
||||
const maxVisibleID = this.lastBottomID + this.splitCount;
|
||||
for(const target of this.visible) {
|
||||
const id = +target.dataset.virtual;
|
||||
if(id < minVisibleID || id > maxVisibleID) {
|
||||
this.setHidden(target);
|
||||
}
|
||||
}
|
||||
});
|
||||
constructor(el: HTMLElement, logPrefix = '', public onScrollOffset = 300) {
|
||||
super(el, logPrefix);
|
||||
|
||||
this.container.classList.add('scrollable-y');
|
||||
|
||||
//this.onScroll();
|
||||
|
||||
this.setListeners();
|
||||
}
|
||||
|
||||
// public attachSentinels(container = this.container, offset = this.onScrollOffset) {
|
||||
// if(!this.sentinelsObserver) {
|
||||
// this.topSentinel = document.createElement('div');
|
||||
// this.topSentinel.classList.add('scrollable-sentinel');
|
||||
// this.topSentinel.style.top = offset + 'px';
|
||||
// this.bottomSentinel = document.createElement('div');
|
||||
// this.bottomSentinel.classList.add('scrollable-sentinel');
|
||||
// this.bottomSentinel.style.bottom = offset + 'px';
|
||||
|
||||
// this.container.append(this.topSentinel, this.bottomSentinel);
|
||||
|
||||
// //let fire: () => void;
|
||||
|
||||
// this.sentinelsObserver = new IntersectionObserver(entries => {
|
||||
// for(let entry of entries) {
|
||||
// let top = entry.target == this.topSentinel;
|
||||
// if(top) {
|
||||
// this.onScrolledTopFired = entry.isIntersecting;
|
||||
// } else {
|
||||
// this.onScrolledBottomFired = entry.isIntersecting;
|
||||
// }
|
||||
// }
|
||||
|
||||
// /* this.debug && */this.log('Set onScrolledFires:', this.onScrolledTopFired, this.onScrolledBottomFired);
|
||||
|
||||
// /* if((this.onScrolledTopFired || this.onScrolledBottomFired) && !fire) {
|
||||
// fire = () => window.requestAnimationFrame(() => {
|
||||
// if(!this.scrollLocked) {
|
||||
// if(this.onScrolledTopFired && this.onScrolledTop) this.onScrolledTop();
|
||||
// if(this.onScrolledBottomFired && this.onScrolledBottom) this.onScrolledBottom();
|
||||
// }
|
||||
|
||||
// if(!this.onScrolledTopFired && !this.onScrolledBottomFired) {
|
||||
// fire = undefined;
|
||||
// } else {
|
||||
// fire();
|
||||
// }
|
||||
// });
|
||||
|
||||
// fire();
|
||||
// } */
|
||||
// });
|
||||
|
||||
// this.sentinelsObserver.observe(this.topSentinel);
|
||||
// this.sentinelsObserver.observe(this.bottomSentinel);
|
||||
// }
|
||||
|
||||
// container.prepend(this.topSentinel);
|
||||
// container.append(this.bottomSentinel);
|
||||
// }
|
||||
|
||||
public setVirtualContainer(el?: HTMLElement) {
|
||||
this.splitUp = el;
|
||||
this.lastScrollTop = 0;
|
||||
this.log('setVirtualContainer:', el, this);
|
||||
}
|
||||
|
||||
public onScroll = () => {
|
||||
/* let scrollTop = this.scrollTop;
|
||||
this.lastScrollDirection = this.lastScrollTop < scrollTop;
|
||||
this.lastScrollTop = scrollTop;
|
||||
return; */
|
||||
|
||||
//if(!this.isVisible) return;
|
||||
|
||||
//if(this.debug) {
|
||||
//this.log('onScroll call', this.onScrollMeasure);
|
||||
//}
|
||||
|
||||
//let appendTo = this.splitUp || this.appendTo;
|
||||
|
||||
// this.log('onScroll:', this.container.scrollTop);
|
||||
// if(this.container.scrollTop <= 0) {
|
||||
// /* touchSupport && */(this.container.style.overflow = 'hidden');
|
||||
// this.scrollTop = 0;
|
||||
// /* touchSupport && */(this.container.style.overflow = '');
|
||||
// }
|
||||
|
||||
if(this.splitUp) {
|
||||
clearTimeout(this.disableHoverTimeout);
|
||||
|
||||
this.disableHoverTimeout = window.setTimeout(() => {
|
||||
//appendTo.classList.remove('disable-hover');
|
||||
this.lastScrollDirection = 0;
|
||||
}, 100);
|
||||
}
|
||||
|
||||
/* if(this.el != this.appendTo && this.appendTo != this.container) {
|
||||
if(!appendTo.classList.contains('disable-hover')) {
|
||||
appendTo.classList.add('disable-hover');
|
||||
}
|
||||
} */
|
||||
|
||||
if(this.onScrollMeasure || ((this.scrollLocked || (!this.onScrolledTop && !this.onScrolledBottom)) && !this.splitUp)) return;
|
||||
this.onScrollMeasure = window.requestAnimationFrame(() => {
|
||||
//if(!this.isVisible) return;
|
||||
|
||||
this.checkForTriggers();
|
||||
|
||||
this.onScrollMeasure = 0;
|
||||
if(!this.splitUp) return;
|
||||
|
||||
const scrollTop = this.scrollTop;
|
||||
if(this.lastScrollTop != scrollTop) {
|
||||
this.lastScrollDirection = this.lastScrollTop < scrollTop ? 1 : -1;
|
||||
this.lastScrollTop = scrollTop;
|
||||
} else {
|
||||
this.lastScrollDirection = 0;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@ -400,73 +181,12 @@ export default class Scrollable extends ScrollableBase {
|
||||
}
|
||||
}
|
||||
|
||||
public reorder() {
|
||||
if(!this.splitUp || this.reorderTimeout) return;
|
||||
|
||||
this.reorderTimeout = window.setTimeout(() => {
|
||||
this.reorderTimeout = 0;
|
||||
|
||||
(Array.from(this.splitUp.children) as HTMLElement[]).forEach((el, idx) => {
|
||||
el.dataset.virtual = '' + idx;
|
||||
});
|
||||
}, 0);
|
||||
public prepend(element: HTMLElement) {
|
||||
(this.splitUp || this.container).prepend(element);
|
||||
}
|
||||
|
||||
public updateElement(element: HTMLElement) {
|
||||
element.style.minHeight = '';
|
||||
window.requestAnimationFrame(() => {
|
||||
const height = element.scrollHeight;
|
||||
|
||||
window.requestAnimationFrame(() => {
|
||||
element.style.minHeight = height + 'px';
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public prepareElement(element: HTMLElement, append = true) {
|
||||
if(!this.splitUp) return;
|
||||
//return;
|
||||
element.dataset.virtual = '' + (append ? this.virtualTempIDBottom++ : this.virtualTempIDTop--);
|
||||
|
||||
this.log.debug('prepareElement: prepared');
|
||||
|
||||
window.requestAnimationFrame(() => {
|
||||
const {scrollHeight/* , scrollWidth */} = element;
|
||||
|
||||
this.log.debug('prepareElement: first rAF');
|
||||
|
||||
window.requestAnimationFrame(() => {
|
||||
//element.style.height = scrollHeight + 'px';
|
||||
element.style.minHeight = scrollHeight + 'px'; // height doesn't work for safari
|
||||
//element.style.width = scrollWidth + 'px';
|
||||
//(element.firstElementChild as HTMLElement).style.display = 'none';
|
||||
});
|
||||
|
||||
this.visible.add(element);
|
||||
this.observer.observe(element);
|
||||
});
|
||||
}
|
||||
|
||||
public prepend(element: HTMLElement, splitable = true) {
|
||||
if(splitable) this.prepareElement(element, false);
|
||||
|
||||
if(this.splitUp) this.splitUp.prepend(element);
|
||||
else this.appendTo.prepend(element);
|
||||
}
|
||||
|
||||
public append(element: HTMLElement, splitable = true) {
|
||||
if(splitable) this.prepareElement(element);
|
||||
|
||||
if(this.splitUp) this.splitUp.append(element);
|
||||
else this.appendTo.append(element);
|
||||
}
|
||||
|
||||
public contains(element: Element) {
|
||||
if(!this.splitUp) {
|
||||
return this.appendTo.contains(element);
|
||||
}
|
||||
|
||||
return !!element.parentElement;
|
||||
public append(element: HTMLElement) {
|
||||
(this.splitUp || this.container).append(element);
|
||||
}
|
||||
|
||||
public scrollIntoView(element: HTMLElement, smooth = true) {
|
||||
@ -491,14 +211,37 @@ export default class Scrollable extends ScrollableBase {
|
||||
}
|
||||
}
|
||||
|
||||
public removeElement(element: Element) {
|
||||
element.remove();
|
||||
}
|
||||
|
||||
public getScrollValue = () => {
|
||||
return this.scrollTop;
|
||||
};
|
||||
|
||||
public slice(side: SliceSides, safeCount: number/* sliceLength: number */) {
|
||||
//const isOtherSideLoaded = this.loadedAll[side == 'top' ? 'bottom' : 'top'];
|
||||
//const multiplier = 2 - +isOtherSideLoaded;
|
||||
const multiplier = 2;
|
||||
safeCount *= multiplier;
|
||||
|
||||
const length = this.splitUp.childElementCount;
|
||||
|
||||
if(length <= safeCount) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const children = Array.from(this.splitUp.children) as HTMLElement[];
|
||||
const sliced = side == 'top' ? children.slice(0, length - safeCount) : children.slice(safeCount);
|
||||
for(const el of sliced) {
|
||||
el.remove();
|
||||
}
|
||||
|
||||
this.log.error('slice', side, length, sliced.length, this.splitUp.childElementCount);
|
||||
|
||||
if(sliced.length) {
|
||||
this.loadedAll[side] = false;
|
||||
}
|
||||
|
||||
return sliced;
|
||||
}
|
||||
|
||||
get isScrolledDown() {
|
||||
return this.scrollHeight - Math.round(this.scrollTop + this.container.offsetHeight) <= 1;
|
||||
}
|
||||
@ -518,8 +261,8 @@ export default class Scrollable extends ScrollableBase {
|
||||
}
|
||||
|
||||
export class ScrollableX extends ScrollableBase {
|
||||
constructor(el: HTMLElement, logPrefix = '', public appendTo = el, public onScrollOffset = 300, public splitCount = 15, public container: HTMLElement = document.createElement('div')) {
|
||||
super(el, logPrefix, appendTo, container);
|
||||
constructor(el: HTMLElement, logPrefix = '', public onScrollOffset = 300, public splitCount = 15, public container: HTMLElement = document.createElement('div')) {
|
||||
super(el, logPrefix, container);
|
||||
|
||||
this.container.classList.add('scrollable-x');
|
||||
|
||||
|
@ -11,7 +11,7 @@ export default class AppArchivedTab implements SliderTab {
|
||||
public wasFilterID: number;
|
||||
|
||||
init() {
|
||||
this.scroll = new Scrollable(this.container, 'CLA', this.chatList, 500);
|
||||
this.scroll = new Scrollable(this.container, 'CLA', 500);
|
||||
this.scroll.setVirtualContainer(this.chatList);
|
||||
this.scroll.onScrolledBottom = appDialogsManager.onChatsScroll;
|
||||
///this.scroll.attachSentinels();
|
||||
|
@ -31,8 +31,7 @@ export default class AppGifsTab implements SliderTab {
|
||||
private searchPromise: ReturnType<AppInlineBotsManager['getInlineResults']>;
|
||||
|
||||
constructor() {
|
||||
this.scrollable = new Scrollable(this.contentDiv, ANIMATIONGROUP, undefined, undefined, 2);
|
||||
this.scrollable.setVirtualContainer(this.gifsDiv);
|
||||
this.scrollable = new Scrollable(this.contentDiv, ANIMATIONGROUP);
|
||||
|
||||
this.masonry = new GifsMasonry(this.gifsDiv, ANIMATIONGROUP, this.scrollable);
|
||||
|
||||
|
@ -18,7 +18,7 @@ export default class AppPollResultsTab implements SliderTab {
|
||||
private mid: number;
|
||||
|
||||
constructor() {
|
||||
this.scrollable = new Scrollable(this.contentDiv, 'POLL-RESULTS', undefined, undefined, 2);
|
||||
this.scrollable = new Scrollable(this.contentDiv, 'POLL-RESULTS');
|
||||
}
|
||||
|
||||
public cleanup() {
|
||||
|
@ -131,7 +131,7 @@ export default class AppSharedMediaTab implements SliderTab {
|
||||
let container = this.profileContentEl.querySelector('.content-container .tabs-container') as HTMLDivElement;
|
||||
this.profileTabs = this.profileContentEl.querySelector('.profile-tabs');
|
||||
|
||||
this.scroll = new Scrollable(this.container, 'SR', undefined, 400);
|
||||
this.scroll = new Scrollable(this.container, 'SR', 400);
|
||||
this.scroll.onScrolledBottom = () => {
|
||||
if(this.sharedMediaSelected && this.sharedMediaSelected.childElementCount/* && false */) {
|
||||
//this.log('onScrolledBottom will load media');
|
||||
|
@ -23,8 +23,7 @@ export default class AppStickersTab implements SliderTab {
|
||||
private lazyLoadQueue: LazyLoadQueue;
|
||||
|
||||
constructor() {
|
||||
this.scrollable = new Scrollable(this.contentDiv, 'STICKERS-SEARCH', undefined, undefined, 2);
|
||||
this.scrollable.setVirtualContainer(this.setsDiv);
|
||||
this.scrollable = new Scrollable(this.contentDiv, 'STICKERS-SEARCH');
|
||||
|
||||
this.lazyLoadQueue = new LazyLoadQueue();
|
||||
|
||||
@ -176,7 +175,7 @@ export default class AppStickersTab implements SliderTab {
|
||||
|
||||
div.append(header, stickersDiv);
|
||||
|
||||
this.scrollable.append(div);
|
||||
this.setsDiv.append(div);
|
||||
}
|
||||
|
||||
public init() {
|
||||
|
@ -21,7 +21,7 @@ export const formatDateAccordingToToday = (time: Date) => {
|
||||
if((now - timestamp) < ONE_DAY && date.getDate() == time.getDate()) { // if the same day
|
||||
timeStr = ('0' + time.getHours()).slice(-2) + ':' + ('0' + time.getMinutes()).slice(-2);
|
||||
} else if(date.getFullYear() != time.getFullYear()) { // different year
|
||||
timeStr = time.getDate() + '.' + (time.getMonth() + 1) + '.' + ('' + time.getFullYear()).slice(-2);
|
||||
timeStr = time.getDate() + '.' + ('0' + (time.getMonth() + 1)).slice(-2) + '.' + ('' + time.getFullYear()).slice(-2);
|
||||
} else if((now - timestamp) < (ONE_DAY * 7) && getWeekNumber(date) == getWeekNumber(time)) { // current week
|
||||
timeStr = days[time.getDay()].slice(0, 3);
|
||||
} else { // same year
|
||||
|
@ -1,6 +1,7 @@
|
||||
//import apiManager from '../mtproto/apiManager';
|
||||
import { logger, LogLevels } from '../logger';
|
||||
import apiManager from '../mtproto/mtprotoworker';
|
||||
import { MOUNT_CLASS_TO } from '../mtproto/mtproto_config';
|
||||
import $rootScope from '../rootScope';
|
||||
//import networkerFactory from '../mtproto/networkerFactory';
|
||||
import appChatsManager from "./appChatsManager";
|
||||
@ -555,4 +556,6 @@ export class ApiUpdatesManager {
|
||||
}
|
||||
}
|
||||
|
||||
export default new ApiUpdatesManager();
|
||||
const apiUpdatesManager = new ApiUpdatesManager();
|
||||
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.apiUpdatesManager = apiUpdatesManager);
|
||||
export default apiUpdatesManager
|
||||
|
@ -2,6 +2,7 @@ import { numberWithCommas } from "../../helpers/number";
|
||||
import { isObject, safeReplaceObject, copy } from "../../helpers/object";
|
||||
import { ChatAdminRights, ChatBannedRights, ChatFull, ChatParticipants, InputChannel, InputChatPhoto, InputFile, InputPeer, Updates } from "../../layer";
|
||||
import apiManager from '../mtproto/mtprotoworker';
|
||||
import { MOUNT_CLASS_TO } from "../mtproto/mtproto_config";
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
import $rootScope from "../rootScope";
|
||||
import apiUpdatesManager from "./apiUpdatesManager";
|
||||
@ -529,4 +530,6 @@ export class AppChatsManager {
|
||||
}
|
||||
}
|
||||
|
||||
export default new AppChatsManager();
|
||||
const appChatsManager = new AppChatsManager();
|
||||
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.appChatsManager = appChatsManager);
|
||||
export default appChatsManager;
|
||||
|
@ -4,7 +4,7 @@ import { horizontalMenu } from "../../components/horizontalMenu";
|
||||
import { attachContextMenuListener, putPreloader } from "../../components/misc";
|
||||
import { ripple } from "../../components/ripple";
|
||||
//import Scrollable from "../../components/scrollable";
|
||||
import Scrollable, { ScrollableX } from "../../components/scrollable";
|
||||
import Scrollable, { ScrollableX, SliceSides, SliceSidesContainer } from "../../components/scrollable";
|
||||
import appSidebarLeft from "../../components/sidebarLeft";
|
||||
import { formatDateAccordingToToday } from "../../helpers/date";
|
||||
import { escapeRegExp } from "../../helpers/string";
|
||||
@ -20,6 +20,7 @@ import {MyDialogFilter as DialogFilter} from "../storages/filters";
|
||||
import appPeersManager from './appPeersManager';
|
||||
import appStateManager from "./appStateManager";
|
||||
import appUsersManager, { User } from "./appUsersManager";
|
||||
import { MOUNT_CLASS_TO } from "../mtproto/mtproto_config";
|
||||
|
||||
type DialogDom = {
|
||||
avatarEl: AvatarElement,
|
||||
@ -36,6 +37,7 @@ type DialogDom = {
|
||||
};
|
||||
|
||||
const testScroll = false;
|
||||
let testTopSlice = 1;
|
||||
|
||||
export class AppDialogsManager {
|
||||
public _chatList = document.getElementById('dialogs') as HTMLUListElement;
|
||||
@ -52,7 +54,6 @@ export class AppDialogsManager {
|
||||
private chatsPreloader: HTMLDivElement;
|
||||
|
||||
public loadDialogsPromise: Promise<any>;
|
||||
public loadedAll = false;
|
||||
|
||||
public scroll: Scrollable = null;
|
||||
public _scroll: Scrollable = null;
|
||||
@ -84,6 +85,8 @@ export class AppDialogsManager {
|
||||
|
||||
private accumulateArchivedTimeout: number;
|
||||
|
||||
private topOffsetIndex = 0;
|
||||
|
||||
constructor() {
|
||||
this.chatsPreloader = putPreloader(null, true);
|
||||
|
||||
@ -91,7 +94,8 @@ export class AppDialogsManager {
|
||||
|
||||
this.folders.menuScrollContainer = this.folders.menu.parentElement;
|
||||
|
||||
this.scroll = this._scroll = new Scrollable(this.chatsContainer, 'CL', this.chatList, 500);
|
||||
this.scroll = this._scroll = new Scrollable(this.chatsContainer, 'CL', 500);
|
||||
this.scroll.onScrolledTop = this.onChatsScrollTop;
|
||||
this.scroll.onScrolledBottom = this.onChatsScroll;
|
||||
this.scroll.setVirtualContainer(this.chatList);
|
||||
//this.scroll.attachSentinels();
|
||||
@ -120,7 +124,7 @@ export class AppDialogsManager {
|
||||
|
||||
this.setListClickListener(this.chatList, null, true);
|
||||
|
||||
/* if(testScroll) {
|
||||
if(testScroll) {
|
||||
let i = 0;
|
||||
let add = () => {
|
||||
let li = document.createElement('li');
|
||||
@ -130,11 +134,11 @@ export class AppDialogsManager {
|
||||
i++;
|
||||
this.scroll.append(li);
|
||||
};
|
||||
for(let i = 0; i < 100; ++i) {
|
||||
for(let i = 0; i < 500; ++i) {
|
||||
add();
|
||||
}
|
||||
(window as any).addElement = add;
|
||||
} */
|
||||
}
|
||||
|
||||
$rootScope.$on('user_update', (e) => {
|
||||
const userID = e.detail;
|
||||
@ -156,14 +160,14 @@ export class AppDialogsManager {
|
||||
}
|
||||
});
|
||||
|
||||
$rootScope.$on('dialog_top', (e) => {
|
||||
/* $rootScope.$on('dialog_top', (e) => {
|
||||
const dialog = e.detail;
|
||||
|
||||
this.setLastMessage(dialog);
|
||||
this.setDialogPosition(dialog);
|
||||
|
||||
this.setFiltersUnreadCount();
|
||||
});
|
||||
}); */
|
||||
|
||||
$rootScope.$on('dialog_flush', (e) => {
|
||||
const peerID: number = e.detail.peerID;
|
||||
@ -188,22 +192,21 @@ export class AppDialogsManager {
|
||||
});
|
||||
|
||||
$rootScope.$on('dialog_drop', (e) => {
|
||||
let {peerID, dialog} = e.detail;
|
||||
const {peerID, dialog} = e.detail;
|
||||
|
||||
let dom = this.getDialogDom(peerID);
|
||||
const dom = this.getDialogDom(peerID);
|
||||
if(dom) {
|
||||
dom.listEl.remove();
|
||||
delete this.doms[peerID];
|
||||
this.scroll.reorder();
|
||||
}
|
||||
|
||||
this.setFiltersUnreadCount();
|
||||
});
|
||||
|
||||
$rootScope.$on('dialog_unread', (e) => {
|
||||
let info = e.detail;
|
||||
const info = e.detail;
|
||||
|
||||
let dialog = appMessagesManager.getDialogByPeerID(info.peerID)[0];
|
||||
const dialog = appMessagesManager.getDialogByPeerID(info.peerID)[0];
|
||||
if(dialog) {
|
||||
this.setUnreadMessages(dialog);
|
||||
|
||||
@ -327,7 +330,7 @@ export class AppDialogsManager {
|
||||
//selectTab(0);
|
||||
(this.folders.menu.firstElementChild.firstElementChild as HTMLElement).click();
|
||||
appStateManager.getState().then((state) => {
|
||||
const getFiltersPromise = !state.filters || Object.keys(state.filters).length ? appMessagesManager.filtersStorage.getDialogFilters() : Promise.resolve([]);
|
||||
const getFiltersPromise = appMessagesManager.filtersStorage.getDialogFilters();
|
||||
getFiltersPromise.then((filters) => {
|
||||
for(const filter of filters) {
|
||||
this.addFilter(filter);
|
||||
@ -340,6 +343,12 @@ export class AppDialogsManager {
|
||||
this.accumulateArchivedUnread();
|
||||
});
|
||||
});
|
||||
|
||||
/* const mutationObserver = new MutationObserver((mutationList, observer) => {
|
||||
|
||||
});
|
||||
|
||||
mutationObserver.observe */
|
||||
}
|
||||
|
||||
private updateDialog(dialog: Dialog) {
|
||||
@ -347,8 +356,18 @@ export class AppDialogsManager {
|
||||
return;
|
||||
}
|
||||
|
||||
if(this.topOffsetIndex && dialog.index > this.topOffsetIndex) {
|
||||
const dom = this.getDialogDom(dialog.peerID);
|
||||
if(dom) {
|
||||
dom.listEl.remove();
|
||||
delete this.doms[dialog.peerID];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(!this.doms.hasOwnProperty(dialog.peerID)) {
|
||||
this.addDialog(dialog);
|
||||
this.addDialogNew({dialog});
|
||||
}
|
||||
|
||||
if(this.getDialogDom(dialog.peerID)) {
|
||||
@ -359,14 +378,16 @@ export class AppDialogsManager {
|
||||
|
||||
onTabChange = () => {
|
||||
this.doms = {};
|
||||
this.loadedAll = false;
|
||||
this.topOffsetIndex = 0;
|
||||
this.scroll.loadedAll.top = true;
|
||||
this.scroll.loadedAll.bottom = false;
|
||||
this.lastActiveListElement = null;
|
||||
this.loadDialogsPromise = undefined;
|
||||
this.chatList = this.chatLists[this.filterID];
|
||||
this.loadDialogs();
|
||||
};
|
||||
|
||||
public setFilterUnreadCount(filterID: number, folder?: Dialog[]) {
|
||||
private setFilterUnreadCount(filterID: number, folder?: Dialog[]) {
|
||||
const unreadSpan = filterID == 0 ? this.allUnreadCount : this.filtersRendered[filterID]?.unread;
|
||||
if(!unreadSpan) {
|
||||
return;
|
||||
@ -378,7 +399,7 @@ export class AppDialogsManager {
|
||||
unreadSpan.innerText = sum ? '' + sum : '';
|
||||
}
|
||||
|
||||
public setFiltersUnreadCount() {
|
||||
private setFiltersUnreadCount() {
|
||||
for(const filterID in this.filtersRendered) {
|
||||
this.setFilterUnreadCount(+filterID);
|
||||
}
|
||||
@ -389,12 +410,11 @@ export class AppDialogsManager {
|
||||
/**
|
||||
* Удалит неподходящие чаты из списка, но не добавит их(!)
|
||||
*/
|
||||
public validateForFilter() {
|
||||
private validateForFilter() {
|
||||
// !WARNING, возможно это было зачем-то, но комментарий исправил архивирование
|
||||
//if(this.filterID == 0) return;
|
||||
|
||||
const folder = appMessagesManager.dialogsStorage.getFolder(this.filterID);
|
||||
let affected = false;
|
||||
for(const _peerID in this.doms) {
|
||||
const peerID = +_peerID;
|
||||
|
||||
@ -402,20 +422,16 @@ export class AppDialogsManager {
|
||||
if(folder.findIndex((dialog) => dialog.peerID == peerID) === -1) {
|
||||
const listEl = this.doms[peerID].listEl;
|
||||
listEl.remove();
|
||||
affected = true;
|
||||
delete this.doms[peerID];
|
||||
|
||||
if(this.lastActiveListElement == listEl) {
|
||||
this.lastActiveListElement = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(affected) {
|
||||
this.scroll.reorder();
|
||||
}
|
||||
}
|
||||
|
||||
public addFilter(filter: DialogFilter) {
|
||||
private addFilter(filter: DialogFilter) {
|
||||
if(this.filtersRendered[filter.id]) return;
|
||||
|
||||
const li = document.createElement('li');
|
||||
@ -459,7 +475,7 @@ export class AppDialogsManager {
|
||||
};
|
||||
}
|
||||
|
||||
public async loadDialogs() {
|
||||
private async loadDialogs(side: SliceSides = 'bottom') {
|
||||
if(testScroll) {
|
||||
return;
|
||||
}
|
||||
@ -474,24 +490,42 @@ export class AppDialogsManager {
|
||||
//return;
|
||||
|
||||
const filterID = this.filterID;
|
||||
let loadCount = 30/*this.chatsLoadCount */;
|
||||
|
||||
const storage = appMessagesManager.dialogsStorage.getFolder(filterID);
|
||||
let offsetIndex = 0;
|
||||
|
||||
for(let i = storage.length - 1; i >= 0; --i) {
|
||||
const dialog = storage[i];
|
||||
if(this.getDialogDom(dialog.peerID)) {
|
||||
offsetIndex = dialog.index;
|
||||
break;
|
||||
|
||||
if(side == 'top') {
|
||||
const element = this.chatList.firstElementChild;
|
||||
if(element) {
|
||||
const peerID = +element.getAttribute('data-peerID');
|
||||
const index = storage.findIndex(dialog => dialog.peerID == peerID);
|
||||
const needIndex = Math.max(0, index - loadCount);
|
||||
loadCount = index - needIndex;
|
||||
offsetIndex = storage[needIndex].index + 1;
|
||||
}
|
||||
} else {
|
||||
const element = this.chatList.lastElementChild;
|
||||
if(element) {
|
||||
const peerID = +element.getAttribute('data-peerID');
|
||||
const dialog = storage.find(dialog => dialog.peerID == peerID);
|
||||
offsetIndex = dialog.index;
|
||||
}
|
||||
/* for(let i = storage.length - 1; i >= 0; --i) {
|
||||
const dialog = storage[i];
|
||||
if(this.getDialogDom(dialog.peerID)) {
|
||||
offsetIndex = dialog.index;
|
||||
break;
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
|
||||
//let offset = storage[storage.length - 1]?.index || 0;
|
||||
|
||||
try {
|
||||
//console.time('getDialogs time');
|
||||
|
||||
const loadCount = 50/*this.chatsLoadCount */;
|
||||
|
||||
const getConversationPromise = (this.filterID > 1 ? appUsersManager.getContacts() as Promise<any> : Promise.resolve()).then(() => {
|
||||
return appMessagesManager.getConversations('', offsetIndex, loadCount, filterID);
|
||||
});
|
||||
@ -505,23 +539,59 @@ export class AppDialogsManager {
|
||||
}
|
||||
|
||||
//console.timeEnd('getDialogs time');
|
||||
|
||||
if(result && result.dialogs && result.dialogs.length) {
|
||||
result.dialogs.forEach((dialog) => {
|
||||
this.addDialog(dialog);
|
||||
});
|
||||
}
|
||||
|
||||
// * loaded all
|
||||
//if(!result.dialogs.length || this.chatList.childElementCount == result.count) {
|
||||
// !result.dialogs.length не подходит, так как при супердревном диалоге getConversations его не выдаст.
|
||||
if(this.chatList.childElementCount == result.count) {
|
||||
this.loadedAll = true;
|
||||
//if(this.chatList.childElementCount == result.count) {
|
||||
if(side == 'bottom') {
|
||||
if(result.isEnd) {
|
||||
this.scroll.loadedAll[side] = true;
|
||||
}
|
||||
} else {
|
||||
const storage = appMessagesManager.dialogsStorage.getFolder(filterID);
|
||||
if(!result.dialogs.length || (storage.length && storage[0].index < offsetIndex)) {
|
||||
this.scroll.loadedAll[side] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(result.dialogs.length) {
|
||||
const dialogs = side == 'top' ? result.dialogs.slice().reverse() : result.dialogs;
|
||||
dialogs.forEach((dialog) => {
|
||||
this.addDialogNew({
|
||||
dialog,
|
||||
append: side == 'bottom'
|
||||
});
|
||||
});
|
||||
|
||||
//if(side == 'bottom' || true || (testTopSlice-- > 0 && side == 'top')) {
|
||||
//setTimeout(() => {
|
||||
const sliced = this.scroll.slice(side == 'bottom' ? 'top' : 'bottom', 30/* result.dialogs.length */);
|
||||
sliced.forEach(el => {
|
||||
const peerID = +el.getAttribute('data-peerID');
|
||||
delete this.doms[peerID];
|
||||
});
|
||||
//}, 0);
|
||||
//}
|
||||
}
|
||||
|
||||
if(!this.scroll.loadedAll['top']) {
|
||||
const element = this.chatList.firstElementChild;
|
||||
if(element) {
|
||||
const peerID = +element.getAttribute('data-peerID');
|
||||
const dialog = appMessagesManager.getDialogByPeerID(peerID)[0];
|
||||
this.topOffsetIndex = dialog.index;
|
||||
}
|
||||
} else {
|
||||
this.topOffsetIndex = 0;
|
||||
}
|
||||
|
||||
this.log.debug('getDialogs ' + loadCount + ' dialogs by offset:', offsetIndex, result, this.chatList.childElementCount);
|
||||
|
||||
setTimeout(() => {
|
||||
/* setTimeout(() => {
|
||||
this.scroll.slice(true);
|
||||
}, 100); */
|
||||
this.scroll.onScroll();
|
||||
}, 0);
|
||||
} catch(err) {
|
||||
@ -531,12 +601,16 @@ export class AppDialogsManager {
|
||||
this.chatsPreloader.remove();
|
||||
this.loadDialogsPromise = undefined;
|
||||
}
|
||||
|
||||
public onChatsScrollTop = () => {
|
||||
this.onChatsScroll('top');
|
||||
};
|
||||
|
||||
onChatsScroll = () => {
|
||||
if(this.loadedAll || this.loadDialogsPromise) return;
|
||||
this.log('onChatsScroll');
|
||||
this.loadDialogs();
|
||||
}
|
||||
public onChatsScroll = (side: SliceSides = 'bottom') => {
|
||||
if(this.scroll.loadedAll[side] || this.loadDialogsPromise) return;
|
||||
this.log.error('onChatsScroll', side);
|
||||
this.loadDialogs(side);
|
||||
};
|
||||
|
||||
public setListClickListener(list: HTMLUListElement, onFound?: () => void, withContext = false) {
|
||||
list.addEventListener('mousedown', (e) => {
|
||||
@ -588,28 +662,28 @@ export class AppDialogsManager {
|
||||
}
|
||||
}
|
||||
|
||||
public setDialogPosition(dialog: Dialog, pos?: number) {
|
||||
private setDialogPosition(dialog: Dialog) {
|
||||
const dom = this.getDialogDom(dialog.peerID);
|
||||
if(!dom) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(pos === undefined) {
|
||||
pos = appMessagesManager.dialogsStorage.getDialog(dialog.peerID, this.filterID)[1];
|
||||
let pos = appMessagesManager.dialogsStorage.getDialog(dialog.peerID, this.filterID)[1];
|
||||
if(this.topOffsetIndex) {
|
||||
const element = this.chatList.firstElementChild;
|
||||
if(element) {
|
||||
const peerID = +element.getAttribute('data-peerID');
|
||||
const firstDialog = appMessagesManager.getDialogByPeerID(peerID);
|
||||
pos -= firstDialog[1];
|
||||
}
|
||||
}
|
||||
|
||||
if(positionElementByIndex(dom.listEl, this.chatList, pos)) {
|
||||
this.scroll.reorder();
|
||||
|
||||
this.log.debug('setDialogPosition:', dialog, dom, pos);
|
||||
}
|
||||
}
|
||||
|
||||
public setLastMessage(dialog: any, lastMessage?: any, dom?: DialogDom, highlightWord?: string) {
|
||||
if(!lastMessage) {
|
||||
lastMessage = appMessagesManager.getMessage(dialog.top_message);
|
||||
}
|
||||
|
||||
///////console.log('setlastMessage:', lastMessage);
|
||||
if(!dom) {
|
||||
dom = this.getDialogDom(dialog.peerID);
|
||||
@ -620,6 +694,10 @@ export class AppDialogsManager {
|
||||
}
|
||||
}
|
||||
|
||||
if(!lastMessage) {
|
||||
lastMessage = appMessagesManager.getMessage(dialog.top_message);
|
||||
}
|
||||
|
||||
if(lastMessage._ == 'messageEmpty' || (lastMessage._ == 'messageService' && !lastMessage.rReply)) {
|
||||
dom.lastMessageSpan.innerHTML = '';
|
||||
dom.lastTimeSpan.innerHTML = '';
|
||||
@ -700,7 +778,7 @@ export class AppDialogsManager {
|
||||
}
|
||||
}
|
||||
|
||||
public setUnreadMessages(dialog: Dialog) {
|
||||
private setUnreadMessages(dialog: Dialog) {
|
||||
const dom = this.getDialogDom(dialog.peerID);
|
||||
|
||||
if(dialog.folder_id == 1) {
|
||||
@ -765,7 +843,7 @@ export class AppDialogsManager {
|
||||
}
|
||||
}
|
||||
|
||||
public accumulateArchivedUnread() {
|
||||
private accumulateArchivedUnread() {
|
||||
if(this.accumulateArchivedTimeout) return;
|
||||
this.accumulateArchivedTimeout = window.setTimeout(() => {
|
||||
this.accumulateArchivedTimeout = 0;
|
||||
@ -775,11 +853,23 @@ export class AppDialogsManager {
|
||||
}, 0);
|
||||
}
|
||||
|
||||
public getDialogDom(peerID: number) {
|
||||
private getDialogDom(peerID: number) {
|
||||
return this.doms[peerID];
|
||||
}
|
||||
|
||||
public addDialog(_dialog: Dialog | number, container?: HTMLUListElement | Scrollable, drawStatus = true, rippleEnabled = true, onlyFirstName = false, meAsSaved = true) {
|
||||
public addDialogNew(options: {
|
||||
dialog: Dialog | number,
|
||||
container?: HTMLUListElement | Scrollable,
|
||||
drawStatus?: boolean,
|
||||
rippleEnabled?: boolean,
|
||||
onlyFirstName?: boolean,
|
||||
meAsSaved?: boolean,
|
||||
append?: boolean
|
||||
}) {
|
||||
return this.addDialog(options.dialog, options.container, options.drawStatus, options.rippleEnabled, options.onlyFirstName, options.meAsSaved, options.append);
|
||||
}
|
||||
|
||||
public addDialog(_dialog: Dialog | number, container?: HTMLUListElement | Scrollable, drawStatus = true, rippleEnabled = true, onlyFirstName = false, meAsSaved = true, append = true) {
|
||||
let dialog: Dialog;
|
||||
|
||||
if(typeof(_dialog) === 'number') {
|
||||
@ -939,8 +1029,9 @@ export class AppDialogsManager {
|
||||
good = true;
|
||||
}
|
||||
} */
|
||||
const method: 'append' | 'prepend' = append ? 'append' : 'prepend';
|
||||
if(!container/* || good */) {
|
||||
this.scroll.append(li);
|
||||
this.scroll[method](li);
|
||||
|
||||
this.doms[dialog.peerID] = dom;
|
||||
|
||||
@ -955,7 +1046,7 @@ export class AppDialogsManager {
|
||||
|
||||
this.setLastMessage(dialog);
|
||||
} else {
|
||||
container.append(li);
|
||||
container[method](li);
|
||||
}
|
||||
|
||||
return {dom, dialog};
|
||||
@ -995,4 +1086,5 @@ export class AppDialogsManager {
|
||||
}
|
||||
|
||||
const appDialogsManager = new AppDialogsManager();
|
||||
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.appDialogsManager = appDialogsManager);
|
||||
export default appDialogsManager;
|
||||
|
@ -960,7 +960,7 @@ export class AppImManager {
|
||||
}
|
||||
|
||||
public setScroll() {
|
||||
this.scrollable = new Scrollable(this.bubblesContainer/* .firstElementChild */ as HTMLElement, 'IM', this.chatInner, 300);
|
||||
this.scrollable = new Scrollable(this.bubblesContainer/* .firstElementChild */ as HTMLElement, 'IM', 300);
|
||||
|
||||
/* const getScrollOffset = () => {
|
||||
//return Math.round(Math.max(300, appPhotosManager.windowH / 1.5));
|
||||
@ -1236,7 +1236,6 @@ export class AppImManager {
|
||||
this.cleanup();
|
||||
this.chatInner = document.createElement('div');
|
||||
this.chatInner.id = 'bubbles-inner';
|
||||
this.scrollable.appendTo = this.chatInner;
|
||||
this.chatInner.className = oldChatInner.className;
|
||||
this.chatInner.classList.add('disable-hover', 'is-scrolling');
|
||||
|
||||
@ -1473,7 +1472,7 @@ export class AppImManager {
|
||||
this.bubbleGroups.removeBubble(bubble, mid);
|
||||
this.unreadedObserver.unobserve(bubble);
|
||||
//this.unreaded.findAndSplice(mid => mid == id);
|
||||
this.scrollable.removeElement(bubble);
|
||||
bubble.remove();
|
||||
//bubble.remove();
|
||||
});
|
||||
|
||||
@ -1567,9 +1566,9 @@ export class AppImManager {
|
||||
container.append(div);
|
||||
|
||||
if(reverse) {
|
||||
this.scrollable.prepend(container, false);
|
||||
this.chatInner.prepend(container);
|
||||
} else {
|
||||
this.scrollable.append(container, false);
|
||||
this.chatInner.append(container);
|
||||
}
|
||||
|
||||
this.stickyIntersector.observeStickyHeaderChanges(container);
|
||||
@ -1715,7 +1714,7 @@ export class AppImManager {
|
||||
const classNames = ['bubble'].concat(save.filter(c => wasClassNames.includes(c)));
|
||||
bubble.className = classNames.join(' ');
|
||||
|
||||
bubbleContainer = bubble.firstElementChild as HTMLDivElement;
|
||||
bubbleContainer = bubble.lastElementChild as HTMLDivElement;
|
||||
bubbleContainer.innerHTML = '';
|
||||
//bubbleContainer.style.marginBottom = '';
|
||||
bubbleContainer.style.cssText = '';
|
||||
@ -2441,7 +2440,7 @@ export class AppImManager {
|
||||
const method = (reverse ? history.shift : history.pop).bind(history);
|
||||
|
||||
//const padding = 99999;
|
||||
const realLength = this.scrollable.length;
|
||||
const realLength = this.scrollable.container.childElementCount;
|
||||
let previousScrollHeightMinusTop: number/* , previousScrollHeight: number */;
|
||||
if(realLength > 0 && (reverse || isSafari)) { // for safari need set when scrolling bottom too
|
||||
this.messagesQueueOnRender = () => {
|
||||
|
@ -12,6 +12,7 @@ import { logger, LogLevels } from "../logger";
|
||||
import type { ApiFileManager } from '../mtproto/apiFileManager';
|
||||
//import apiManager from '../mtproto/apiManager';
|
||||
import apiManager from '../mtproto/mtprotoworker';
|
||||
import { MOUNT_CLASS_TO } from "../mtproto/mtproto_config";
|
||||
import referenceDatabase, { ReferenceContext } from "../mtproto/referenceDatabase";
|
||||
import serverTimeManager from "../mtproto/serverTimeManager";
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
@ -1506,7 +1507,8 @@ export class AppMessagesManager {
|
||||
if(query || this.dialogsStorage.allDialogsLoaded[realFolderID] || curDialogStorage.length >= offset + limit) {
|
||||
return Promise.resolve({
|
||||
dialogs: curDialogStorage.slice(offset, offset + limit),
|
||||
count: this.dialogsStorage.allDialogsLoaded[realFolderID] ? curDialogStorage.length : null
|
||||
count: this.dialogsStorage.allDialogsLoaded[realFolderID] ? curDialogStorage.length : null,
|
||||
isEnd: this.dialogsStorage.allDialogsLoaded[realFolderID] && (offset + limit) >= curDialogStorage.length
|
||||
});
|
||||
}
|
||||
|
||||
@ -1526,7 +1528,8 @@ export class AppMessagesManager {
|
||||
|
||||
return {
|
||||
dialogs: curDialogStorage.slice(offset, offset + limit),
|
||||
count: totalCount
|
||||
count: totalCount,
|
||||
isEnd: this.dialogsStorage.allDialogsLoaded[realFolderID] && (offset + limit) >= curDialogStorage.length
|
||||
};
|
||||
});
|
||||
}
|
||||
@ -1906,7 +1909,7 @@ export class AppMessagesManager {
|
||||
|
||||
message.peerID = peerID;
|
||||
if(message.peerID == myID/* && !message.from_id && !message.fwd_from */) {
|
||||
message.fromID = message.fwd_from?.from_id ? appPeersManager.getPeerID(message.fwd_from.from_id) : myID;
|
||||
message.fromID = message.fwd_from ? (message.fwd_from.from_id ? appPeersManager.getPeerID(message.fwd_from.from_id) : 0) : myID;
|
||||
} else {
|
||||
message.fromID = message.pFlags.post || (!message.pFlags.out && !message.from_id) ? peerID : appPeersManager.getPeerID(message.from_id);
|
||||
}
|
||||
@ -2424,7 +2427,7 @@ export class AppMessagesManager {
|
||||
} */
|
||||
|
||||
if(topMessage) {
|
||||
const wasDialogBefore = this.getDialogByPeerID(peerID)[0];
|
||||
//const wasDialogBefore = this.getDialogByPeerID(peerID)[0];
|
||||
|
||||
// here need to just replace, not FULL replace dialog! WARNING
|
||||
/* if(wasDialogBefore?.pFlags?.pinned && !dialog?.pFlags?.pinned) {
|
||||
@ -2435,12 +2438,12 @@ export class AppMessagesManager {
|
||||
|
||||
this.saveConversation(dialog);
|
||||
|
||||
if(wasDialogBefore) {
|
||||
/* if(wasDialogBefore) {
|
||||
$rootScope.$broadcast('dialog_top', dialog);
|
||||
} else {
|
||||
} else { */
|
||||
updatedDialogs[peerID] = dialog;
|
||||
hasUpdated = true;
|
||||
}
|
||||
//}
|
||||
} else {
|
||||
const dropped = this.dialogsStorage.dropDialog(peerID);
|
||||
if(dropped.length) {
|
||||
@ -4220,4 +4223,5 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
const appMessagesManager = new AppMessagesManager();
|
||||
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.appMessagesManager = appMessagesManager);
|
||||
export default appMessagesManager;
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { isObject } from "../../helpers/object";
|
||||
import { DialogPeer, InputDialogPeer, InputPeer, Peer } from "../../layer";
|
||||
import { MOUNT_CLASS_TO } from "../mtproto/mtproto_config";
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
import $rootScope from "../rootScope";
|
||||
import appChatsManager from "./appChatsManager";
|
||||
@ -230,4 +231,5 @@ export class AppPeersManager {
|
||||
}
|
||||
|
||||
const appPeersManager = new AppPeersManager();
|
||||
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.appPeersManager = appPeersManager);
|
||||
export default appPeersManager;
|
||||
|
@ -11,6 +11,7 @@ import { calcImageInBox } from "../../helpers/dom";
|
||||
import { MyDocument } from "./appDocsManager";
|
||||
import appDownloadManager from "./appDownloadManager";
|
||||
import appUsersManager from "./appUsersManager";
|
||||
import { MOUNT_CLASS_TO } from "../mtproto/mtproto_config";
|
||||
|
||||
export type MyPhoto = Photo.photo;
|
||||
|
||||
@ -346,4 +347,6 @@ export class AppPhotosManager {
|
||||
}
|
||||
}
|
||||
|
||||
export default new AppPhotosManager();
|
||||
const appPhotosManager = new AppPhotosManager();
|
||||
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.appPhotosManager = appPhotosManager);
|
||||
export default appPhotosManager;
|
||||
|
@ -4,6 +4,7 @@ import { safeReplaceObject, isObject } from "../../helpers/object";
|
||||
import { InputUser, Update, User as MTUser, UserStatus } from "../../layer";
|
||||
//import apiManager from '../mtproto/apiManager';
|
||||
import apiManager from '../mtproto/mtprotoworker';
|
||||
import { MOUNT_CLASS_TO } from "../mtproto/mtproto_config";
|
||||
import serverTimeManager from "../mtproto/serverTimeManager";
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
import $rootScope from "../rootScope";
|
||||
@ -641,4 +642,6 @@ export class AppUsersManager {
|
||||
}
|
||||
}
|
||||
|
||||
export default new AppUsersManager();
|
||||
const appUsersManager = new AppUsersManager();
|
||||
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.appUsersManager = appUsersManager);
|
||||
export default appUsersManager
|
||||
|
@ -20,7 +20,7 @@ type BroadcastEvents = {
|
||||
'dialog_flush': {peerID: number},
|
||||
'dialog_drop': {peerID: number, dialog?: Dialog},
|
||||
'dialog_migrate': {migrateFrom: number, migrateTo: number},
|
||||
'dialog_top': Dialog,
|
||||
//'dialog_top': Dialog,
|
||||
'dialog_notify_settings': number,
|
||||
'dialogs_multiupdate': {[peerID: string]: Dialog},
|
||||
'dialogs_archived_unread': {count: number},
|
||||
|
@ -1,62 +0,0 @@
|
||||
console.log('Services included!');
|
||||
|
||||
import AppMediaViewer from '../components/appMediaViewer';
|
||||
import AppSidebarLeft from '../components/sidebarLeft';
|
||||
import AppSidebarRight from '../components/sidebarRight';
|
||||
import ApiUpdatesManager from './appManagers/apiUpdatesManager';
|
||||
import AppChatsManager from './appManagers/appChatsManager';
|
||||
import AppDialogsManager from './appManagers/appDialogsManager';
|
||||
import AppDocsManager from './appManagers/appDocsManager';
|
||||
import AppImManager from './appManagers/appImManager';
|
||||
import AppMessagesIDsManager from './appManagers/appMessagesIDsManager';
|
||||
import AppMessagesManager from './appManagers/appMessagesManager';
|
||||
import AppPeersManager from './appManagers/appPeersManager';
|
||||
import AppPhotosManager from './appManagers/appPhotosManager';
|
||||
import AppProfileManager from './appManagers/appProfileManager';
|
||||
import AppStickersManager from './appManagers/appStickersManager';
|
||||
import AppUsersManager from './appManagers/appUsersManager';
|
||||
//import AppSharedMediaManager from './appManagers/appSharedMediaManager';
|
||||
|
||||
const appUsersManager = AppUsersManager;
|
||||
const appChatsManager = AppChatsManager;
|
||||
const appMessagesIDsManager = AppMessagesIDsManager;
|
||||
const apiUpdatesManager = ApiUpdatesManager;
|
||||
const appPhotosManager = AppPhotosManager;
|
||||
const appMessagesManager = AppMessagesManager;
|
||||
const appProfileManager = AppProfileManager;
|
||||
const appImManager = AppImManager;
|
||||
const appPeersManager = AppPeersManager;
|
||||
const appStickersManager = AppStickersManager;
|
||||
const appDocsManager = AppDocsManager;
|
||||
//export const appSharedMediaManager = AppSharedMediaManager;
|
||||
const appSidebarRight = AppSidebarRight;
|
||||
const appSidebarLeft = AppSidebarLeft;
|
||||
const appMediaViewer = AppMediaViewer;
|
||||
const appDialogsManager = AppDialogsManager;
|
||||
|
||||
const Services = {
|
||||
appUsersManager,
|
||||
appChatsManager,
|
||||
apiUpdatesManager,
|
||||
appMessagesManager,
|
||||
appMessagesIDsManager,
|
||||
appPeersManager,
|
||||
appProfileManager,
|
||||
appPhotosManager,
|
||||
appDocsManager,
|
||||
|
||||
appDialogsManager,
|
||||
appImManager,
|
||||
appStickersManager,
|
||||
appSidebarRight,
|
||||
appSidebarLeft,
|
||||
appMediaViewer
|
||||
//appSharedMediaManager
|
||||
};
|
||||
|
||||
(window as any).Services = Services;
|
||||
|
||||
for(let i in Services) {
|
||||
// @ts-ignore
|
||||
(window as any)[i] = Services[i];
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
//import {stackBlurImage} from '../lib/StackBlur';
|
||||
//import appStateManager from "../lib/appManagers/appStateManager";
|
||||
import appStateManager from "../lib/appManagers/appStateManager";
|
||||
import { DEBUG } from "../lib/mtproto/mtproto_config";
|
||||
import Page from "./page";
|
||||
|
||||
let onFirstMount = () => {
|
||||
@ -24,11 +23,7 @@ let onFirstMount = () => {
|
||||
alert('navigator.mediaDevices:' + typeof(navigator.mediaDevices));
|
||||
alert('navigator.mediaDevices.getUserMedia:' + typeof(navigator.mediaDevices?.getUserMedia));
|
||||
alert('global.WebAssembly:' + typeof(WebAssembly)); */
|
||||
|
||||
if(DEBUG) {
|
||||
import('../lib/services');
|
||||
}
|
||||
|
||||
|
||||
//(Array.from(document.getElementsByClassName('rp')) as HTMLElement[]).forEach(el => ripple(el));
|
||||
|
||||
const misc = await import("../components/buttonMenuToggle");
|
||||
|
Loading…
x
Reference in New Issue
Block a user