Browse Source

test new virtual method

master
Eduard Kuzmenko 5 years ago
parent
commit
107ab79c92
  1. 2
      src/components/pageIm.ts
  2. 420
      src/components/scrollable copy.ts
  3. 206
      src/components/scrollable.ts
  4. 26
      src/lib/appManagers/appDialogsManager.ts
  5. 37
      src/lib/appManagers/appImManager.ts
  6. 19
      src/lib/appManagers/appSidebarLeft.ts
  7. 326
      src/scss/partials/_chat.scss
  8. 4
      src/scss/partials/_chatlist.scss
  9. 213
      src/scss/partials/_emojiDropdown.scss
  10. 1
      src/scss/style.scss

2
src/components/pageIm.ts

@ -187,7 +187,7 @@ export default () => import('../lib/services').then(services => { @@ -187,7 +187,7 @@ export default () => import('../lib/services').then(services => {
});
appSidebarLeft.loadDialogs().then(result => {
appSidebarLeft.onChatsScroll();
//appSidebarLeft.onChatsScroll();
appSidebarLeft.loadDialogs(true);
});
});

420
src/components/scrollable copy.ts

@ -0,0 +1,420 @@ @@ -0,0 +1,420 @@
import { isElementInViewport, isScrolledIntoView, cancelEvent } from "../lib/utils";
export default class Scrollable {
public container: HTMLDivElement;
public thumb: HTMLDivElement;
public type: string;
public side: string;
public scrollType: string;
public scrollSide: string;
public clientAxis: string;
public scrollSize = -1;
public size = 0;
public thumbSize = 0;
public hiddenElements: {
up: {element: Element, height: number}[],
down: {element: Element, height: number}[]
} = {
up: [],
down: []
};
public paddings = {up: 0, down: 0};
public paddingTopDiv: HTMLDivElement;
public paddingBottomDiv: HTMLDivElement;
public splitUp: HTMLElement;
public splitOffset = 0;
public onAddedBottom: () => void = null;
public topObserver: IntersectionObserver;
public isTopIntersecting: boolean;
public bottomObserver: IntersectionObserver;
public isBottomIntersecting: boolean;
public splitObserver: IntersectionObserver;
constructor(public el: HTMLDivElement, x = false, y = true) {
this.container = document.createElement('div');
this.container.classList.add('scrollable');
let arr = [];
for(let i = 0.001; i < 1; i += 0.001) arr.push(i);
this.topObserver = new IntersectionObserver(entries => {
let entry = entries[0];
console.log('top intersection:', entries, this.isTopIntersecting, entry.isIntersecting, entry.intersectionRatio > 0);
if(this.isTopIntersecting = entry.isIntersecting) {
this.onTopIntersection(entry);
}
console.log('top intersection end');
}, {threshold: arr});
this.bottomObserver = new IntersectionObserver(entries => {
let entry = entries[0];
console.log('bottom intersection:', entries, this.isBottomIntersecting, entry.isIntersecting, entry.intersectionRatio > 0);
if(this.isBottomIntersecting = entry.isIntersecting) {
this.onBottomIntersection(entry);
if(this.onScrolledBottom) this.onScrolledBottom();
}
}, {threshold: arr});
this.splitObserver = new IntersectionObserver(entries => {
//console.log('splitObserver', entries);
for(let entry of entries) {
if(!entry.isIntersecting/* && entry.target.parentElement */) {
let child = entry.target;
console.log('onscroll entry', entry.boundingClientRect, child, entry);
let isTop = (entry.boundingClientRect.top + this.splitOffset) <= 0;
let isBottom = entry.rootBounds.height <= entry.boundingClientRect.top;
let height = child.scrollHeight;
let toPush = {element: child, height};
if(isTop) {
this.paddings.up += height;
this.hiddenElements.up.push(toPush);
child.parentElement.removeChild(child);
console.log('onscroll sliced up', child);
this.paddingTopDiv.style.height = this.paddings.up + 'px';
} else if(isBottom) {
this.paddings.down += height;
this.hiddenElements.down.unshift(toPush);
child.parentElement.removeChild(child);
console.log('onscroll sliced down', child);
this.paddingBottomDiv.style.height = this.paddings.down + 'px';
}
//console.log('splitObserver', entry, entry.target, isTop);
}
}
});
if(x) {
this.container.classList.add('scrollable-x');
this.type = 'width';
this.side = 'left';
this.scrollType = 'scrollWidth';
this.scrollSide = 'scrollLeft';
this.clientAxis = 'clientX';
let scrollHorizontally = (e: any) => {
e = window.event || e;
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
this.container.scrollLeft -= (delta * 20);
e.preventDefault();
};
if(this.container.addEventListener) {
// IE9, Chrome, Safari, Opera
this.container.addEventListener("mousewheel", scrollHorizontally, false);
// Firefox
this.container.addEventListener("DOMMouseScroll", scrollHorizontally, false);
} else {
// IE 6/7/8
// @ts-ignore
this.container.attachEvent("onmousewheel", scrollHorizontally);
}
} else if(y) {
this.container.classList.add('scrollable-y');
this.type = 'height';
this.side = 'top';
this.scrollType = 'scrollHeight';
this.scrollSide = 'scrollTop';
this.clientAxis = 'clientY';
} else {
throw new Error('no side for scroll');
}
this.thumb = document.createElement('div');
this.thumb.className = 'scrollbar-thumb';
// @ts-ignore
this.thumb.style[this.type] = '30px';
let onMouseMove = (e: MouseEvent) => {
let rect = this.thumb.getBoundingClientRect();
let diff: number;
// @ts-ignore
diff = e[this.clientAxis] - rect[this.side];
// @ts-ignore
this.container[this.scrollSide] += diff * 0.5;
console.log('onMouseMove', e, diff);
cancelEvent(e);
};
this.thumb.addEventListener('mousedown', () => {
window.addEventListener('mousemove', onMouseMove);
window.addEventListener('mouseup', () => {
window.removeEventListener('mousemove', onMouseMove);
}, {once: true});
});
//this.container.addEventListener('mouseover', this.resize.bind(this)); // omg
window.addEventListener('resize', this.resize.bind(this));
this.paddingTopDiv = document.createElement('div');
this.paddingTopDiv.classList.add('scroll-padding');
this.paddingBottomDiv = document.createElement('div');
this.paddingBottomDiv.classList.add('scroll-padding');
this.topObserver.observe(this.paddingTopDiv);
this.bottomObserver.observe(this.paddingBottomDiv);
this.container.addEventListener('scroll', this.onScroll.bind(this));
//this.container.append(this.paddingTopDiv);
Array.from(el.children).forEach(c => this.container.append(c));
//this.container.append(this.paddingBottomDiv);
el.append(this.container);//container.append(el);
this.container.parentElement.append(this.thumb);
this.resize();
}
public resize() {
console.time('scroll resize');
// @ts-ignore
this.scrollSize = this.container[this.scrollType];
let rect = this.container.getBoundingClientRect();
// @ts-ignore
this.size = rect[this.type];
if(!this.size || this.size == this.scrollSize) {
this.thumbSize = 0;
// @ts-ignore
this.thumb.style[this.type] = this.thumbSize + 'px';
console.timeEnd('scroll resize');
return;
}
//if(!height) return;
let divider = this.scrollSize / this.size / 0.5;
this.thumbSize = this.size / divider;
if(this.thumbSize < 20) this.thumbSize = 20;
// @ts-ignore
this.thumb.style[this.type] = this.thumbSize + 'px';
console.timeEnd('scroll resize');
// @ts-ignore
//console.log('onresize', thumb.style[type], thumbHeight, height);
}
public setVirtualContainer(el?: HTMLElement) {
this.splitUp = el;
this.hiddenElements.up.length = this.hiddenElements.down.length = 0;
this.paddings.up = this.paddings.down = 0;
if(this.paddingTopDiv.parentElement) {
this.paddingTopDiv.style.height = '';
this.paddingBottomDiv.style.height = '';
}
/* this.topObserver.unobserve(this.paddingTopDiv);
this.bottomObserver.unobserve(this.paddingBottomDiv);
this.topObserver.observe(this.paddingTopDiv);
this.bottomObserver.observe(this.paddingBottomDiv); */
if(el) {
el.parentElement.insertBefore(this.paddingTopDiv, el);
el.parentNode.insertBefore(this.paddingBottomDiv, el.nextSibling);
}
}
public onScroll() {
// @ts-ignore
//let st = container[scrollSide];
//console.time('scroll onScroll');
// @ts-ignore
if(this.container[this.scrollType] != this.scrollSize || this.thumbSize == 0) {
this.resize();
}
// @ts-ignore
let value = this.container[this.scrollSide] / (this.scrollSize - this.size) * 100;
let maxValue = 100 - (this.thumbSize / this.size * 100);
//console.log('onscroll', container.scrollHeight, thumbHeight, height, value, maxValue);
// @ts-ignore
this.thumb.style[this.side] = (value >= maxValue ? maxValue : value) + '%';
//console.timeEnd('scroll onScroll');
}
public async onTopIntersection2(entry: IntersectionObserverEntry) {
console.log('onTopIntersection');
if(this.hiddenElements.up.length && this.paddings.up) {
//while(this.isTopIntersecting && this.paddings.up) {
let child = this.hiddenElements.up.pop();
console.log('top returning from hidden', child);
if(!child) {
this.paddings.up = 0;
this.paddingTopDiv.style.height = '0px';
return;
}
/* await new Promise((resolve, reject) => {
window.requestAnimationFrame(resolve);
}); */
this.splitUp.prepend(child.element);
this.paddings.up -= child.height;
this.paddingTopDiv.style.height = this.paddings.up + 'px';
//}
} else {
this.paddingTopDiv.style.height = '0px';
}
}
public async onTopIntersection(entry: IntersectionObserverEntry) {
console.log('onTopIntersection');
if(this.hiddenElements.up.length && this.paddings.up) {
let needHeight = entry.intersectionRect.height + this.splitOffset;
while(needHeight > 0 && this.paddings.up) {
let child = this.hiddenElements.up.pop();
console.log('top returning from hidden', child);
if(!child) {
this.paddings.up = 0;
this.paddingTopDiv.style.height = '0px';
break;
}
/* await new Promise((resolve, reject) => {
window.requestAnimationFrame(resolve);
}); */
this.splitUp.prepend(child.element);
let height = child.height || child.element.scrollHeight;
needHeight -= height;
this.paddings.up -= height;
this.paddingTopDiv.style.height = this.paddings.up + 'px';
}
} else {
this.paddingTopDiv.style.height = '0px';
}
}
public onBottomIntersection2() {
console.log('onBottomIntersection');
if(this.hiddenElements.down.length && this.paddings.down) {
//while(this.isBottomIntersecting && this.paddings.down) {
let child = this.hiddenElements.down.shift();
if(!child) {
this.paddings.down = 0;
this.paddingBottomDiv.style.height = '0px';
return;//break;
}
this.splitUp.append(child.element);
this.paddings.down -= child.height;
this.paddingBottomDiv.style.height = this.paddings.down + 'px';
//}
if(this.onAddedBottom) this.onAddedBottom();
} else {
this.paddingBottomDiv.style.height = '0px';
}
}
public onBottomIntersection(entry: IntersectionObserverEntry) {
console.log('onBottomIntersection');
if(this.hiddenElements.down.length && this.paddings.down) {
let needHeight = entry.intersectionRect.height + this.splitOffset;
while(needHeight > 0 && this.paddings.down) {
let child = this.hiddenElements.down.shift();
if(!child) {
this.paddings.down = 0;
this.paddingBottomDiv.style.height = '0px';
break;
}
this.splitUp.append(child.element);
let height = child.height || child.element.scrollHeight;
needHeight -= height;
this.paddings.down -= height;
this.paddingBottomDiv.style.height = this.paddings.down + 'px';
}
if(this.onAddedBottom) this.onAddedBottom();
} else {
this.paddingBottomDiv.style.height = '0px';
}
}
public onScrolledBottom() {
}
public splitAppend(...smth: (string | Node)[]) {
this.splitUp.append(...smth);
for(let node of smth) {
if(typeof(node) !== 'string') {
this.splitObserver.observe(node as Element);
}
}
}
set scrollTop(y: number) {
this.container.scrollTop = y;
}
get scrollTop() {
return this.container.scrollTop;
}
get scrollHeight() {
return this.container.scrollHeight;
}
get parentElement() {
return this.container.parentElement;
}
get offsetHeight() {
return this.container.offsetHeight;
}
}

206
src/components/scrollable.ts

@ -15,8 +15,8 @@ export default class Scrollable { @@ -15,8 +15,8 @@ export default class Scrollable {
public thumbSize = 0;
public hiddenElements: {
up: Element[],
down: Element[]
up: {element: Element, height: number}[],
down: {element: Element, height: number}[]
} = {
up: [],
down: []
@ -27,37 +27,96 @@ export default class Scrollable { @@ -27,37 +27,96 @@ export default class Scrollable {
public paddingBottomDiv: HTMLDivElement;
public splitUp: HTMLElement;
public splitOffset = 0;
public onAddedBottom: () => void = null;
/* public topObserver: IntersectionObserver;
public topObserver: IntersectionObserver;
public isTopIntersecting: boolean;
public bottomObserver: IntersectionObserver;
public isBottomIntersecting: boolean; */
public isBottomIntersecting: boolean;
public splitObserver: IntersectionObserver;
constructor(public el: HTMLDivElement, x = false, y = true) {
this.container = document.createElement('div');
this.container.classList.add('scrollable');
/* this.bottomObserver = new IntersectionObserver(entries => {
let arr = [];
for(let i = 0.001; i < 1; i += 0.001) arr.push(i);
this.topObserver = new IntersectionObserver(entries => {
let entry = entries[0];
this.isBottomIntersecting = entry.intersectionRatio > 0;
// console.log('top intersection:', entries, this.isTopIntersecting, entry.isIntersecting, entry.intersectionRatio > 0);
if(this.isTopIntersecting = entry.isIntersecting) {
this.onTopIntersection(entry);
}
// console.log('top intersection end');
}, {threshold: arr});
// @ts-ignore
//console.log('bottom instersection:', entry, entry.isVisible, entry.intersectionRatio, entry.isIntersecting);
console.log('bottom intersection:', this.isBottomIntersecting);
this.bottomObserver = new IntersectionObserver(entries => {
let entry = entries[0];
// console.log('bottom intersection:', entries, this.isBottomIntersecting, entry.isIntersecting, entry.intersectionRatio > 0);
if(this.isBottomIntersecting = entry.isIntersecting) {
this.onBottomIntersection(entry);
if(this.onScrolledBottom) this.onScrolledBottom();
}
}, {threshold: arr});
this.splitObserver = new IntersectionObserver(entries => {
//console.log('splitObserver', entries);
for(let entry of entries) {
//console.log('onscroll entry', entry.target, entry.isIntersecting, entry);
if(!entry.isIntersecting && entry.target.parentElement) {
let child = entry.target;
//console.log('onscroll entry', entry.boundingClientRect, child, entry);
let isTop = (entry.boundingClientRect.top + this.splitOffset) <= 0;
let isBottom = entry.rootBounds.height <= entry.boundingClientRect.top;
if(isTop) {
let sliced: Element[] = [child];
while(child.previousElementSibling) {
sliced.push(child = child.previousElementSibling);
}
sliced.reverse();
sliced.forEach(child => {
let height = child.scrollHeight;
this.paddings.up += height;
this.hiddenElements.up.push({element: child, height});
child.parentElement.removeChild(child);
this.paddingTopDiv.style.height = this.paddings.up + 'px';
});
this.topObserver = new IntersectionObserver(entries => {
let entry = entries[0];
//console.log('onscroll sliced up', sliced);
} else if(isBottom) {
let sliced: Element[] = [child];
this.isTopIntersecting = entry.intersectionRatio > 0;
while(child.nextElementSibling) {
sliced.push(child = child.nextElementSibling);
}
// @ts-ignore
//console.log('top instersection:', entry, entry.isVisible, entry.intersectionRatio, entry.isIntersecting);
console.log('top intersection:', this.isTopIntersecting);
}); */
sliced.reverse();
sliced.forEach(child => {
let height = child.scrollHeight;
this.paddings.down += height;
this.hiddenElements.down.unshift({element: child, height});
child.parentElement.removeChild(child);
this.paddingBottomDiv.style.height = this.paddings.down + 'px';
});
//console.log('onscroll sliced down', sliced);
}
//console.log('splitObserver', entry, entry.target, isTop);
}
}
});
if(x) {
this.container.classList.add('scrollable-x');
@ -109,7 +168,7 @@ export default class Scrollable { @@ -109,7 +168,7 @@ export default class Scrollable {
// @ts-ignore
this.container[this.scrollSide] += diff * 0.5;
console.log('onMouseMove', e, diff);
// console.log('onMouseMove', e, diff);
cancelEvent(e);
};
@ -122,7 +181,7 @@ export default class Scrollable { @@ -122,7 +181,7 @@ export default class Scrollable {
}, {once: true});
});
this.container.addEventListener('mouseover', this.resize.bind(this));
//this.container.addEventListener('mouseover', this.resize.bind(this)); // omg
window.addEventListener('resize', this.resize.bind(this));
this.paddingTopDiv = document.createElement('div');
@ -130,6 +189,9 @@ export default class Scrollable { @@ -130,6 +189,9 @@ export default class Scrollable {
this.paddingBottomDiv = document.createElement('div');
this.paddingBottomDiv.classList.add('scroll-padding');
this.topObserver.observe(this.paddingTopDiv);
this.bottomObserver.observe(this.paddingBottomDiv);
this.container.addEventListener('scroll', this.onScroll.bind(this));
//this.container.append(this.paddingTopDiv);
@ -142,6 +204,7 @@ export default class Scrollable { @@ -142,6 +204,7 @@ export default class Scrollable {
}
public resize() {
console.time('scroll resize');
// @ts-ignore
this.scrollSize = this.container[this.scrollType];
@ -155,6 +218,7 @@ export default class Scrollable { @@ -155,6 +218,7 @@ export default class Scrollable {
// @ts-ignore
this.thumb.style[this.type] = this.thumbSize + 'px';
console.timeEnd('scroll resize');
return;
}
//if(!height) return;
@ -167,6 +231,8 @@ export default class Scrollable { @@ -167,6 +231,8 @@ export default class Scrollable {
// @ts-ignore
this.thumb.style[this.type] = this.thumbSize + 'px';
console.timeEnd('scroll resize');
// @ts-ignore
//console.log('onresize', thumb.style[type], thumbHeight, height);
}
@ -182,8 +248,11 @@ export default class Scrollable { @@ -182,8 +248,11 @@ export default class Scrollable {
this.paddingBottomDiv.style.height = '';
}
//this.topObserver.observe(this.paddingTopDiv);
//this.bottomObserver.observe(this.paddingBottomDiv);
/* this.topObserver.unobserve(this.paddingTopDiv);
this.bottomObserver.unobserve(this.paddingBottomDiv);
this.topObserver.observe(this.paddingTopDiv);
this.bottomObserver.observe(this.paddingBottomDiv); */
if(el) {
el.parentElement.insertBefore(this.paddingTopDiv, el);
@ -195,6 +264,9 @@ export default class Scrollable { @@ -195,6 +264,9 @@ export default class Scrollable {
// @ts-ignore
//let st = container[scrollSide];
console.time('scroll onScroll');
// @ts-ignore
if(this.container[this.scrollType] != this.scrollSize || this.thumbSize == 0) {
this.resize();
}
@ -208,67 +280,50 @@ export default class Scrollable { @@ -208,67 +280,50 @@ export default class Scrollable {
// @ts-ignore
this.thumb.style[this.side] = (value >= maxValue ? maxValue : value) + '%';
if(!this.splitUp) {
return;
console.timeEnd('scroll onScroll');
}
let splitUp = this.splitUp;
let children = Array.from(splitUp.children) as HTMLElement[];
let firstVisible = -1, lastVisible = -1;
let length = children.length;
for(let i = 0; i < length; ++i) {
let child = children[i];
if(isElementInViewport(child) || isScrolledIntoView(child)) {
if(firstVisible < 0) firstVisible = i;
lastVisible = i;
}
}
public onTopIntersection(entry: IntersectionObserverEntry) {
// console.log('onTopIntersection');
if(this.hiddenElements.up.length && this.paddings.up) {
let needHeight = entry.intersectionRect.height + this.splitOffset;
//console.log('onscroll', firstVisible, lastVisible);
while(needHeight > 0 && this.paddings.up) {
let child = this.hiddenElements.up.pop();
if(firstVisible > 0) {
let sliced = children.slice(0, firstVisible);
// console.log('top returning from hidden', child);
for(let child of sliced) {
this.paddings.up += child.scrollHeight;
this.hiddenElements.up.push(child);
child.parentElement.removeChild(child);
if(!child) {
this.paddings.up = 0;
this.paddingTopDiv.style.height = '0px';
break;
}
//console.log('onscroll sliced up', sliced.length);
/* await new Promise((resolve, reject) => {
window.requestAnimationFrame(resolve);
}); */
//sliced.forEach(child => child.style.display = 'none');
this.paddingTopDiv.style.height = this.paddings.up + 'px';
//console.log('onscroll need to add padding: ', paddings.up);
} else if(this.hiddenElements.up.length) {
//console.log('onscroll up', isElementInViewport(this.paddingTopDiv), isScrolledIntoView(this.paddingTopDiv), this.paddings.up);
while((isElementInViewport(this.paddingTopDiv) || isScrolledIntoView(this.paddingTopDiv)) && this.paddings.up) {
let child = this.hiddenElements.up.pop();
this.splitUp.prepend(child.element);
let height = child.height || child.element.scrollHeight;
splitUp.prepend(child);
needHeight -= height;
this.paddings.up -= height;
this.paddings.up -= child.scrollHeight;
this.paddingTopDiv.style.height = this.paddings.up + 'px';
}
} else {
this.paddingTopDiv.style.height = '0px';
}
if(lastVisible < (length - 1)) {
let sliced = children.slice(lastVisible + 1).reverse();
for(let child of sliced) {
this.paddings.down += child.scrollHeight;
this.hiddenElements.down.unshift(child);
child.parentElement.removeChild(child);
}
//console.log('onscroll sliced down', splitUp, sliced.length, this.paddings.down + 'px');
public onBottomIntersection(entry: IntersectionObserverEntry) {
// console.log('onBottomIntersection');
this.paddingBottomDiv.style.height = this.paddings.down + 'px';
//console.log('onscroll need to add padding: ', paddings.up);
} else if(this.hiddenElements.down.length) {
//console.log('onscroll down', isElementInViewport(this.paddingBottomDiv),
//isScrolledIntoView(this.paddingBottomDiv), this.paddings.down, this.hiddenElements);
while((isElementInViewport(this.paddingBottomDiv) || isScrolledIntoView(this.paddingBottomDiv)) && this.paddings.down) {
if(this.hiddenElements.down.length && this.paddings.down) {
let needHeight = entry.intersectionRect.height + this.splitOffset;
while(needHeight > 0 && this.paddings.down) {
let child = this.hiddenElements.down.shift();
if(!child) {
@ -277,9 +332,12 @@ export default class Scrollable { @@ -277,9 +332,12 @@ export default class Scrollable {
break;
}
splitUp.append(child);
this.splitUp.append(child.element);
let height = child.height || child.element.scrollHeight;
needHeight -= height;
this.paddings.down -= height;
this.paddings.down -= child.scrollHeight;
this.paddingBottomDiv.style.height = this.paddings.down + 'px';
}
@ -287,10 +345,20 @@ export default class Scrollable { @@ -287,10 +345,20 @@ export default class Scrollable {
} else {
this.paddingBottomDiv.style.height = '0px';
}
}
//console.log('onscroll', container, firstVisible, lastVisible, hiddenElements);
public onScrolledBottom() {
}
//lastScrollPos = st;
public splitAppend(...smth: (string | Node)[]) {
this.splitUp.append(...smth);
for(let node of smth) {
if(typeof(node) !== 'string') {
this.splitObserver.observe(node as Element);
}
}
}
set scrollTop(y: number) {

26
src/lib/appManagers/appDialogsManager.ts

@ -153,12 +153,12 @@ export class AppDialogsManager { @@ -153,12 +153,12 @@ export class AppDialogsManager {
}
public sortDom(archived = false) {
//return;
return;
let dialogs = appMessagesManager.dialogsStorage.dialogs.slice();
let inUpper: HTMLLIElement[] = [];
let inBottom: HTMLLIElement[] = [];
let inUpper: {element: HTMLLIElement, height: number}[] = [];
let inBottom: {element: HTMLLIElement, height: number}[] = [];
let pinnedDialogs = [];
@ -214,26 +214,13 @@ export class AppDialogsManager { @@ -214,26 +214,13 @@ export class AppDialogsManager {
if(!dom) return;
if(inUpper.length < hiddenLength) {
inUpper.push(dom.listEl);
inUpper.push({element: dom.listEl, height: 0});
} else if(inViewportIndex <= inViewportLength - 1) {
chatList.append(dom.listEl);
++inViewportIndex;
//this.chatList.insertBefore(dom.listEl, this.chatList.children[inViewportIndex++]);
} else {
inBottom.push(dom.listEl);
inBottom.push({element: dom.listEl, height: 0});
}
/* if(this.chatsHidden.up.find((d: HTMLLIElement) => d === dom.listEl)) {
inUpper.push(dom.listEl);
} else if(isElementInViewport(dom.listEl)) {
this.chatList.insertBefore(dom.listEl, this.chatList.children[++inViewportIndex]);
} else if(this.chatsHidden.down.find((d: HTMLLIElement) => d === dom.listEl)) {
inBottom.push(dom.listEl);
} else {
//console.warn('sortDom found no dom!', dom, d);
} */
//this.chatList.append(dom.listEl);
});
//////console.log('sortDom', sorted.length, inUpper.length, chatList.childElementCount, inBottom.length);
@ -536,7 +523,8 @@ export class AppDialogsManager { @@ -536,7 +523,8 @@ export class AppDialogsManager {
this.chatListArchived.append(li);
this.domsArchived[dialog.peerID] = dom;
} else {
this.chatList.append(li);
//this.chatList.append(li);
appSidebarLeft.scroll.splitAppend(li);
this.doms[dialog.peerID] = dom;
}

37
src/lib/appManagers/appImManager.ts

@ -1634,37 +1634,11 @@ export class AppImManager { @@ -1634,37 +1634,11 @@ export class AppImManager {
}
if(updatePosition) {
let type = our ? 'out' : 'in';
let containerDiv = reverse ? this.firstContainerDiv : this.lastContainerDiv;
if(!containerDiv || !containerDiv.classList.contains(type)) {
/* if(containerDiv) {
if(reverse) this.chatInner.prepend(containerDiv);
else this.chatInner.append(containerDiv);
} */
containerDiv = document.createElement('div');
containerDiv.classList.add(type);
if(!this.firstContainerDiv) this.firstContainerDiv = containerDiv;
if(reverse) this.firstContainerDiv = containerDiv;
else this.lastContainerDiv = containerDiv;
}
bubble.classList.add(our ? 'is-out' : 'is-in');
if(reverse) {
/* if(!multipleRender) {
this.scrollPosition.prepareFor('up'); // лагает из-за этого
} */
containerDiv.prepend(bubble);
this.chatInner.prepend(containerDiv);
this.chatInner.prepend(bubble);
} else {
/* if(!multipleRender) {
this.scrollPosition.prepareFor('down'); // лагает из-за этого
} */
containerDiv.append(bubble);
this.chatInner.append(containerDiv);
this.chatInner.append(bubble);
}
let justDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
@ -1698,12 +1672,13 @@ export class AppImManager { @@ -1698,12 +1672,13 @@ export class AppImManager {
};
//this.chatInner.insertBefore(div, containerDiv);
containerDiv.insertBefore(div, bubble);
//containerDiv.insertBefore(div, bubble);
this.chatInner.insertBefore(div, bubble);
} else {
let dateMessage = this.dateMessages[dateTimestamp];
if(dateMessage.firstTimestamp > date.getTime()) {
//this.chatInner.insertBefore(dateMessage.div, containerDiv);
containerDiv.insertBefore(dateMessage.div, bubble);
this.chatInner.insertBefore(dateMessage.div, bubble);
}
}
}

19
src/lib/appManagers/appSidebarLeft.ts

@ -94,13 +94,14 @@ class AppSidebarLeft { @@ -94,13 +94,14 @@ class AppSidebarLeft {
this.scroll = new Scrollable(this.chatsContainer as HTMLDivElement);
this.scroll.setVirtualContainer(appDialogsManager.chatList);
this.scroll.onScrolledBottom = this.onChatsScroll.bind(this);
appDialogsManager.chatsHidden = this.scroll.hiddenElements;
this.scroll.container.addEventListener('scroll', this.onChatsScroll.bind(this));
//this.scroll.container.addEventListener('scroll', this.onChatsScroll.bind(this));
this.scrollArchived = new Scrollable(this.chatsArchivedContainer as HTMLDivElement);
this.scrollArchived.setVirtualContainer(appDialogsManager.chatListArchived);
appDialogsManager.chatsArchivedHidden = this.scrollArchived.hiddenElements;
this.scroll.container.addEventListener('scroll', this.onChatsArchivedScroll.bind(this));
//this.scrollArchived.container.addEventListener('scroll', this.onChatsArchivedScroll.bind(this));
this.listsContainer = new Scrollable(this.searchContainer).container;
for(let i in this.searchGroups) {
@ -211,7 +212,7 @@ class AppSidebarLeft { @@ -211,7 +212,7 @@ class AppSidebarLeft {
setTimeout(() => {
this.onSidebarScroll();
this.scroll.onScroll();
this.onChatsScroll();
//this.onChatsScroll();
this.onChatsArchivedScroll();
}, 0);
});
@ -265,19 +266,9 @@ class AppSidebarLeft { @@ -265,19 +266,9 @@ class AppSidebarLeft {
public onChatsScroll() {
//this.log(this.scroll.hiddenElements.down.length, this.loadDialogsPromise, appDialogsManager.chatList.childNodes);
if(this.scroll.hiddenElements.down.length > 0/* || 1 == 1 */) return;
if(this.scroll.hiddenElements.down.length > 0 || this.loadDialogsPromise/* || 1 == 1 */) return;
if(!this.loadDialogsPromise) {
let d = Array.from(appDialogsManager.chatList.childNodes).slice(-5);
for(let node of d) {
if(isElementInViewport(node)) {
this.loadDialogs();
break;
}
}
//console.log('last 5 dialogs:', d);
}
}
public onChatsArchivedScroll() {

326
src/scss/partials/_chat.scss

@ -148,8 +148,8 @@ @@ -148,8 +148,8 @@
justify-content: flex-end;
&.is-chat {
.in {
padding-left: 45px;
.is-in {
margin-left: 45px;
}
}
}
@ -731,8 +731,37 @@ @@ -731,8 +731,37 @@
padding: 5px 0;
}
.in {
align-items: flex-start;
.is-in {
align-self: flex-start;
background-color: #ffffff;
border-radius: 6px 12px 12px 6px;
&:first-child {
border-radius: 12px 12px 12px 6px;
}
&:last-child {
border-radius: 6px 12px 12px 0px;
//border-radius: 12px 12px 12px 0px;
&:after {
left: -8.4px;
background-image: url('../../assets/img/msg-tail-left.svg');
}
}
&:first-child:last-child {
border-radius: 12px 12px 12px 0px;
}
&.forwarded .attachment,
&.is-reply .attachment,
&:not(.hide-name) .message-empty + .attachment/* ,
&:not(.hide-name):not(.sticker) .attachment */ {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
a {
color: $darkblue;
@ -742,7 +771,7 @@ @@ -742,7 +771,7 @@
background-color: $light;
}
.bubble.is-reply {
&.is-reply {
&.emoji-big, &.sticker {
.box, .reply {
left: calc(100% + 10px);
@ -773,47 +802,42 @@ @@ -773,47 +802,42 @@
margin-bottom: 4px;
}
}
}
.bubble {
background-color: #ffffff;
border-radius: 6px 12px 12px 6px;
.is-out {
align-self: flex-end;
background-color: #eeffde;
border-radius: 12px 6px 6px 12px;
&:first-child {
border-radius: 12px 12px 12px 6px;
border-radius: 12px 12px 6px 12px;
}
&:last-child {
border-radius: 6px 12px 12px 0px;
//border-radius: 12px 12px 12px 0px;
border-radius: 12px 6px 0px 12px;
&:after {
left: -8.4px;
background-image: url('../../assets/img/msg-tail-left.svg');
right: -8.4px;
background-image: url('../../assets/img/msg-tail-right.svg');
}
}
&:first-child:last-child {
border-radius: 12px 12px 12px 0px;
border-radius: 12px 12px 0px 12px;
}
&.forwarded .attachment,
&.is-reply .attachment,
&:not(.hide-name) .message-empty + .attachment/* ,
&:not(.hide-name):not(.sticker) .attachment */ {
&.is-reply .attachment {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
}
}
.out {
align-items: flex-end;
.quote:hover, .reply:hover {
background-color: rgba($green, 0.12);
}
.bubble.is-reply {
&.is-reply {
&.emoji-big, &.sticker {
.box, .reply {
background-color: #eeffde;
@ -844,76 +868,46 @@ @@ -844,76 +868,46 @@
padding: 0 4px 0 4px;
bottom: 1px;
}
}
.bubble {
.time .tgico:after {
.tgico:after {
font-size: 19px;
vertical-align: middle;
margin-left: 1px;
}
}
.bubble.forwarded {
&.forwarded {
.name {
color: $darkgreen;
}
}
.bubble.is-read {
&.is-read {
.time .tgico:after {
content: $tgico-checks;
}
}
.bubble.is-sent {
&.is-sent {
.time .tgico:after {
content: $tgico-check;
}
}
.bubble.is-sending {
&.is-sending {
.time .tgico:after {
content: $tgico-sending;
}
}
.bubble.is-reply .name {
&.is-reply .name {
display: none;
}
.bubble.is-edited .time {
&.is-edited .time {
width: 85px;
}
.bubble {
background-color: #eeffde;
border-radius: 12px 6px 6px 12px;
&:first-child {
border-radius: 12px 12px 6px 12px;
}
&:last-child {
border-radius: 12px 6px 0px 12px;
&:after {
right: -8.4px;
background-image: url('../../assets/img/msg-tail-right.svg');
}
}
&:first-child:last-child {
border-radius: 12px 12px 0px 12px;
}
&.forwarded .attachment,
&.is-reply .attachment {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
}
.user-avatar {
left: auto;
right: -2.5rem;
@ -1255,219 +1249,7 @@ @@ -1255,219 +1249,7 @@
bottom: auto;
}
.emoji-dropdown {
position: absolute;
left: 0;
top: calc(-420px + -0.75rem);
display: flex;
flex-direction: column;
width: 420px;
height: 420px;
background: #fff;
box-shadow: 0px 5px 10px 5px rgba(16, 35, 47, 0.14);
border-radius: 12px;
z-index: 2;
/* display: none; */
display: flex;
overflow: hidden;
transition: all 0.2s ease-out;
transform: scale(0);
transform-origin: 0 100%;
&.active {
/* display: flex; */
transition: all 0.2s ease-in;
transform: scale(1);
}
> .menu-horizontal {
padding: 0 3rem;
}
.emoji-container {
width: 100%;
max-width: 100%;
overflow: hidden;
height: 100%;
}
.tabs-container {
/* width: 300%; */
height: 100%;
.emoji-category {
font-size: 2.25rem;
line-height: 2.25rem;
margin-top: 1px;
> * {
margin: 0;
padding: 5px 5px;
line-height: inherit;
border-radius: 8px;
cursor: pointer;
user-select: none;
-webkit-user-select: none;
width: 44px;
height: 44px;
.emoji {
width: 100%;
height: 100%;
}
&:hover {
background-color: rgba(112, 117, 121, 0.08);
}
}
/* &::after {
content: "";
flex: auto;
} */
}
.emoji-category, .sticker-category {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
&::after {
content: "";
flex: auto;
}
}
.sticker-category {
/* &.not-full::after {
content: "";
flex: auto;
} */
> div {
width: 80px;
height: 80px;
display: flex;
align-items: center;
/* overflow: hidden; */
cursor: pointer;
user-select: none;
-webkit-user-select: none;
/* margin: 3.5px 0;
margin-right: 6.25px; */
padding: 1px 2.5px;
justify-content: center;
border-radius: 12px;
&:hover {
background-color: rgba(112, 117, 121, 0.08);
}
/* &:nth-child(5n+5) {
margin-right: 0;
} */
> * {
max-width: 100%;
max-height: 100%;
}
}
}
> div {
min-height: 100%;
/* display: flex; */
flex-direction: column;
height: 100%;
> div:first-of-type {
flex: 1;
padding: 0;
padding-top: 10px;
}
}
.scrollable {
padding: 0 10px;
}
}
.emoji-padding {
.menu-horizontal {
border-top: 1px solid $lightgrey;
}
}
.emoji-padding, .stickers-padding {
.menu-horizontal {
height: 50px;
border-bottom: none;
padding: 0;
width: 100%;
li {
padding: 0;
width: 50px;
height: 50px;
line-height: 50px;
display: flex;
align-items: center;
&.active {
&:after {
display: none;
}
}
}
}
}
/* #content-stickers {
padding: 0;
} */
.emoji-padding {
.menu-horizontal > li {
font-size: 1.65rem;
}
}
.stickers-padding {
.menu-wrapper {
padding: 0;
height: 50px;
max-width: 100%;
border-top: 1px solid $lightgrey;
.menu-horizontal {
width: 100%;
height: 100%;
}
}
li {
/* width: calc(100% / 7); */
flex: 0 0 auto;
&.active {
&:not(.tgico-recent) {
background-color: rgba(112, 117, 121, 0.08);
}
}
> * {
padding: .75rem;
max-width: 100%;
max-height: 100%;
width: 100%;
height: 100%;
}
}
}
}
.popup {
&.popup-delete-message {

4
src/scss/partials/_chatlist.scss

@ -70,9 +70,9 @@ @@ -70,9 +70,9 @@
margin: 0 8.5px 0 8px;
overflow: hidden;
&:hover {
/* &:hover {
background: rgba(112, 117, 121, .08);
}
} */
}
li.active > .rp {

213
src/scss/partials/_emojiDropdown.scss

@ -0,0 +1,213 @@ @@ -0,0 +1,213 @@
.emoji-dropdown {
position: absolute;
left: 0;
top: calc(-420px + -0.75rem);
display: flex;
flex-direction: column;
width: 420px;
height: 420px;
background: #fff;
box-shadow: 0px 5px 10px 5px rgba(16, 35, 47, 0.14);
border-radius: 12px;
z-index: 2;
/* display: none; */
display: flex;
overflow: hidden;
transition: all 0.2s ease-out;
transform: scale(0);
transform-origin: 0 100%;
&.active {
/* display: flex; */
transition: all 0.2s ease-in;
transform: scale(1);
}
> .menu-horizontal {
padding: 0 3rem;
}
.emoji-container {
width: 100%;
max-width: 100%;
overflow: hidden;
height: 100%;
}
.tabs-container {
/* width: 300%; */
height: 100%;
.emoji-category {
font-size: 2.25rem;
line-height: 2.25rem;
margin-top: 1px;
> * {
margin: 0;
padding: 5px 5px;
line-height: inherit;
border-radius: 8px;
cursor: pointer;
user-select: none;
-webkit-user-select: none;
width: 44px;
height: 44px;
.emoji {
width: 100%;
height: 100%;
}
&:hover {
background-color: rgba(112, 117, 121, 0.08);
}
}
/* &::after {
content: "";
flex: auto;
} */
}
.emoji-category, .sticker-category {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
&::after {
content: "";
flex: auto;
}
}
.sticker-category {
/* &.not-full::after {
content: "";
flex: auto;
} */
> div {
width: 80px;
height: 80px;
display: flex;
align-items: center;
/* overflow: hidden; */
cursor: pointer;
user-select: none;
-webkit-user-select: none;
/* margin: 3.5px 0;
margin-right: 6.25px; */
padding: 1px 2.5px;
justify-content: center;
border-radius: 12px;
&:hover {
background-color: rgba(112, 117, 121, 0.08);
}
/* &:nth-child(5n+5) {
margin-right: 0;
} */
> * {
max-width: 100%;
max-height: 100%;
}
}
}
> div {
min-height: 100%;
/* display: flex; */
flex-direction: column;
height: 100%;
> div:first-of-type {
flex: 1;
padding: 0;
padding-top: 10px;
}
}
.scrollable {
padding: 0 10px;
}
}
.emoji-padding {
.menu-horizontal {
border-top: 1px solid $lightgrey;
}
}
.emoji-padding, .stickers-padding {
.menu-horizontal {
height: 50px;
border-bottom: none;
padding: 0;
width: 100%;
li {
padding: 0;
width: 50px;
height: 50px;
line-height: 50px;
display: flex;
align-items: center;
&.active {
&:after {
display: none;
}
}
}
}
}
/* #content-stickers {
padding: 0;
} */
.emoji-padding {
.menu-horizontal > li {
font-size: 1.65rem;
}
}
.stickers-padding {
.menu-wrapper {
padding: 0;
height: 50px;
max-width: 100%;
border-top: 1px solid $lightgrey;
.menu-horizontal {
width: 100%;
height: 100%;
}
}
li {
/* width: calc(100% / 7); */
flex: 0 0 auto;
&.active {
&:not(.tgico-recent) {
background-color: rgba(112, 117, 121, 0.08);
}
}
> * {
padding: .75rem;
max-width: 100%;
max-height: 100%;
width: 100%;
height: 100%;
}
}
}
}

1
src/scss/style.scss

@ -36,6 +36,7 @@ $time-size: 12px; @@ -36,6 +36,7 @@ $time-size: 12px;
@import "partials/leftSidebar";
@import "partials/mediaViewer";
@import "partials/ckin";
@import "partials/emojiDropdown";
html, body {
height: 100%;

Loading…
Cancel
Save