virtual chatlist scroll (care)
This commit is contained in:
parent
2f9396be3f
commit
be4205e5cc
@ -376,62 +376,151 @@ export function scrollable(el: HTMLDivElement, x = false, y = true) {
|
||||
|
||||
let resize = () => {
|
||||
// @ts-ignore
|
||||
scrollHeight = container[scrollType];
|
||||
scrollSize = container[scrollType];
|
||||
|
||||
let rect = container.getBoundingClientRect();
|
||||
|
||||
// @ts-ignore
|
||||
height = rect[type];
|
||||
size = rect[type];
|
||||
|
||||
if(!height || height == scrollHeight) {
|
||||
thumbHeight = 0;
|
||||
if(!size || size == scrollSize) {
|
||||
thumbSize = 0;
|
||||
|
||||
// @ts-ignore
|
||||
thumb.style[type] = thumbHeight + 'px';
|
||||
thumb.style[type] = thumbSize + 'px';
|
||||
return;
|
||||
}
|
||||
//if(!height) return;
|
||||
|
||||
let divider = scrollHeight / height / 0.5;
|
||||
thumbHeight = height / divider;
|
||||
let divider = scrollSize / size / 0.5;
|
||||
thumbSize = size / divider;
|
||||
|
||||
if(thumbHeight < 20) thumbHeight = 20;
|
||||
if(thumbSize < 20) thumbSize = 20;
|
||||
|
||||
// @ts-ignore
|
||||
thumb.style[type] = thumbHeight + 'px';
|
||||
thumb.style[type] = thumbSize + 'px';
|
||||
|
||||
// @ts-ignore
|
||||
//console.log('onresize', thumb.style[type], thumbHeight, height);
|
||||
};
|
||||
|
||||
let scrollHeight = -1;
|
||||
let height = 0;
|
||||
let thumbHeight = 0;
|
||||
let scrollSize = -1;
|
||||
let size = 0;
|
||||
let thumbSize = 0;
|
||||
window.addEventListener('resize', resize);
|
||||
//container.addEventListener('DOMNodeInserted', resize);
|
||||
|
||||
container.addEventListener('scroll', (e) => {
|
||||
|
||||
let hiddenElements: {
|
||||
up: Element[],
|
||||
down: Element[]
|
||||
} = {
|
||||
up: [],
|
||||
down: []
|
||||
};
|
||||
|
||||
let paddings = {up: 0, down: 0};
|
||||
|
||||
let paddingTopDiv = document.createElement('div');
|
||||
paddingTopDiv.classList.add('scroll-padding');
|
||||
let paddingBottomDiv = document.createElement('div');
|
||||
paddingBottomDiv.classList.add('scroll-padding');
|
||||
|
||||
let onScroll = (e: Event) => {
|
||||
// @ts-ignore
|
||||
if(container[scrollType] != scrollHeight || thumbHeight == 0) {
|
||||
//let st = container[scrollSide];
|
||||
|
||||
// @ts-ignore
|
||||
if(container[scrollType] != scrollSize || thumbSize == 0) {
|
||||
resize();
|
||||
}
|
||||
|
||||
let splitUp = container.querySelector('ul');
|
||||
let children = Array.from(splitUp.children) as HTMLElement[];
|
||||
let firstVisible = -1, lastVisible = -1;
|
||||
let length = children.length;
|
||||
for(let i = 0; i < length; ++i) {
|
||||
let child = children[i];
|
||||
if(isElementInViewport(child)) {
|
||||
if(firstVisible < 0) firstVisible = i;
|
||||
lastVisible = i;
|
||||
}
|
||||
}
|
||||
|
||||
if(firstVisible > 0) {
|
||||
let sliced = children.slice(0, firstVisible);
|
||||
|
||||
for(let child of sliced) {
|
||||
paddings.up += child.scrollHeight;
|
||||
hiddenElements.up.push(child);
|
||||
child.parentElement.removeChild(child);
|
||||
}
|
||||
|
||||
//console.log('sliced up', sliced.length);
|
||||
|
||||
//sliced.forEach(child => child.style.display = 'none');
|
||||
paddingTopDiv.style.height = paddings.up + 'px';
|
||||
//console.log('onscroll need to add padding: ', paddings.up);
|
||||
} else if(hiddenElements.up.length) {
|
||||
while(isElementInViewport(paddingTopDiv) && paddings.up) {
|
||||
let child = hiddenElements.up.pop();
|
||||
|
||||
splitUp.prepend(child);
|
||||
|
||||
paddings.up -= child.scrollHeight;
|
||||
paddingTopDiv.style.height = paddings.up + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
if(lastVisible < (length - 1)) {
|
||||
let sliced = children.slice(lastVisible + 1).reverse();
|
||||
|
||||
for(let child of sliced) {
|
||||
paddings.down += child.scrollHeight;
|
||||
hiddenElements.down.unshift(child);
|
||||
child.parentElement.removeChild(child);
|
||||
}
|
||||
|
||||
//console.log('onscroll sliced down', sliced.length);
|
||||
|
||||
//sliced.forEach(child => child.style.display = 'none');
|
||||
paddingBottomDiv.style.height = paddings.down + 'px';
|
||||
//console.log('onscroll need to add padding: ', paddings.up);
|
||||
} else if(hiddenElements.down.length) {
|
||||
while(isElementInViewport(paddingBottomDiv) && paddings.down) {
|
||||
let child = hiddenElements.down.shift();
|
||||
|
||||
splitUp.append(child);
|
||||
|
||||
paddings.down -= child.scrollHeight;
|
||||
paddingBottomDiv.style.height = paddings.down + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
//console.log('onscroll', container, firstVisible, lastVisible, hiddenElements);
|
||||
|
||||
// @ts-ignore
|
||||
let value = container[scrollSide] / (scrollHeight - height) * 100;
|
||||
let maxValue = 100 - (thumbHeight / height * 100);
|
||||
let value = container[scrollSide] / (scrollSize - size) * 100;
|
||||
let maxValue = 100 - (thumbSize / size * 100);
|
||||
|
||||
//console.log('onscroll', container.scrollHeight, thumbHeight, height, value, maxValue);
|
||||
|
||||
// @ts-ignore
|
||||
thumb.style[side] = (value >= maxValue ? maxValue : value) + '%';
|
||||
});
|
||||
|
||||
//lastScrollPos = st;
|
||||
};
|
||||
|
||||
let lastScrollPos = 0;
|
||||
container.addEventListener('scroll', onScroll);
|
||||
|
||||
container.append(paddingTopDiv);
|
||||
Array.from(el.children).forEach(c => container.append(c));
|
||||
container.append(paddingBottomDiv);
|
||||
|
||||
el.append(container);//container.append(el);
|
||||
container.parentElement.append(thumb);
|
||||
resize();
|
||||
return container;
|
||||
return {container, hiddenElements, onScroll};
|
||||
}
|
||||
|
||||
export function wrapPhoto(this: AppImManager, photo: any, message: any, container: HTMLDivElement) {
|
||||
|
@ -13,6 +13,7 @@ import appStickersManager, { MTStickerSet } from "../lib/appManagers/appStickers
|
||||
import { AppImManager } from "../lib/appManagers/appImManager";
|
||||
import { AppMessagesManager } from "../lib/appManagers/appMessagesManager";
|
||||
import appSidebarRight from "../lib/appManagers/appSidebarRight";
|
||||
import appSidebarLeft from "../lib/appManagers/appSidebarLeft";
|
||||
|
||||
const EMOTICONSSTICKERGROUP = 'emoticons-dropdown';
|
||||
|
||||
@ -175,7 +176,7 @@ let initEmoticonsDropdown = (pageEl: HTMLDivElement,
|
||||
|
||||
let prevCategoryIndex = 1;
|
||||
let menu = contentEmojiDiv.nextElementSibling as HTMLUListElement;
|
||||
let emojiScroll = scrollable(contentEmojiDiv);
|
||||
let emojiScroll = scrollable(contentEmojiDiv).container;
|
||||
emojiScroll.addEventListener('scroll', (e) => {
|
||||
prevCategoryIndex = emoticonsContentOnScroll(menu, heights, prevCategoryIndex, emojiScroll);
|
||||
});
|
||||
@ -341,7 +342,7 @@ let initEmoticonsDropdown = (pageEl: HTMLDivElement,
|
||||
});
|
||||
|
||||
let prevCategoryIndex = 0;
|
||||
let stickersScroll = scrollable(contentStickersDiv);
|
||||
let stickersScroll = scrollable(contentStickersDiv).container;
|
||||
stickersScroll.addEventListener('scroll', (e) => {
|
||||
lazyLoadQueue.check();
|
||||
lottieLoader.checkAnimations();
|
||||
@ -362,72 +363,15 @@ export default () => import('../lib/services').then(services => {
|
||||
|
||||
let {appImManager, appMessagesManager, appDialogsManager, apiUpdatesManager, appUsersManager} = services;
|
||||
//export default () => {
|
||||
let chatsContainer = document.getElementById('chats-container') as HTMLDivElement;
|
||||
let d = document.createElement('div');
|
||||
d.classList.add('preloader');
|
||||
putPreloader(d);
|
||||
chatsContainer.append(d);
|
||||
|
||||
let pageEl = document.body.getElementsByClassName('page-chats')[0] as HTMLDivElement;
|
||||
pageEl.style.display = '';
|
||||
|
||||
const loadCount = Math.round(document.body.scrollHeight / 70 * 1.5);
|
||||
|
||||
let chatsScroll = scrollable(chatsContainer as HTMLDivElement);
|
||||
let sidebarScroll = scrollable(document.body.querySelector('.profile-container'));
|
||||
let chatScroll = scrollable(document.getElementById('bubbles') as HTMLDivElement);
|
||||
let sidebarScroll = scrollable(document.body.querySelector('.profile-container')).container;
|
||||
let chatScroll = scrollable(document.getElementById('bubbles') as HTMLDivElement).container;
|
||||
|
||||
apiUpdatesManager.attach();
|
||||
|
||||
let offsetIndex = 0;
|
||||
let loadDialogsPromise: Promise<any>;
|
||||
let loadDialogs = async() => {
|
||||
if(loadDialogsPromise) return loadDialogsPromise;
|
||||
|
||||
chatsContainer.append(d);
|
||||
|
||||
//let offset = appMessagesManager.generateDialogIndex();/* appMessagesManager.dialogsNum */;
|
||||
|
||||
try {
|
||||
loadDialogsPromise = appMessagesManager.getConversations('', offsetIndex, loadCount);
|
||||
|
||||
let result = await loadDialogsPromise;
|
||||
|
||||
console.log('loaded ' + loadCount + ' dialogs by offset:', offsetIndex, result);
|
||||
|
||||
if(result && result.dialogs && result.dialogs.length) {
|
||||
offsetIndex = result.dialogs[result.dialogs.length - 1].index;
|
||||
result.dialogs.forEach((dialog: any) => {
|
||||
appDialogsManager.addDialog(dialog);
|
||||
});
|
||||
}
|
||||
} catch(err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
d.remove();
|
||||
loadDialogsPromise = undefined;
|
||||
};
|
||||
|
||||
let onScroll = () => {
|
||||
if(!loadDialogsPromise) {
|
||||
let d = Array.from(appDialogsManager.chatList.childNodes).slice(-5);
|
||||
for(let node of d) {
|
||||
if(isElementInViewport(node)) {
|
||||
loadDialogs();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//console.log('last 5 dialogs:', d);
|
||||
}
|
||||
};
|
||||
|
||||
chatsScroll.addEventListener('scroll', onScroll);
|
||||
window.addEventListener('resize', () => {
|
||||
setTimeout(onScroll, 0);
|
||||
});
|
||||
|
||||
// @ts-ignore
|
||||
document.addEventListener('user_update', (e: CustomEvent) => {
|
||||
let userID = e.detail;
|
||||
@ -797,9 +741,8 @@ export default () => import('../lib/services').then(services => {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
loadDialogs().then(result => {
|
||||
onScroll();
|
||||
appSidebarLeft.loadDialogs().then(result => {
|
||||
appSidebarLeft.onChatsScroll();
|
||||
appImManager.setScroll(chatScroll);
|
||||
appSidebarRight.setScroll(sidebarScroll);
|
||||
});
|
||||
|
@ -51,7 +51,7 @@ export default () => {
|
||||
wrapper.appendChild(list);
|
||||
|
||||
//let wrapperScroll = OverlayScrollbars(wrapper, (window as any).scrollbarOptions);
|
||||
let wrapperScroll = scrollable(wrapper);
|
||||
scrollable(wrapper);
|
||||
|
||||
let initedSelect = false;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import apiManager from "../mtproto/apiManager";
|
||||
import apiFileManager from '../mtproto/apiFileManager';
|
||||
import { $rootScope, findUpTag } from "../utils";
|
||||
import { $rootScope, findUpTag, isElementInViewport } from "../utils";
|
||||
import appImManager from "./appImManager";
|
||||
import appPeersManager from './appPeersManager';
|
||||
import appMessagesManager from "./appMessagesManager";
|
||||
@ -20,11 +20,9 @@ type DialogDom = {
|
||||
};
|
||||
|
||||
export class AppDialogsManager {
|
||||
public pinnedChatList = document.getElementById('dialogs-pinned') as HTMLUListElement;
|
||||
public chatList = document.getElementById('dialogs') as HTMLUListElement;
|
||||
public chatsHidden: any;
|
||||
|
||||
|
||||
|
||||
public myID = 0;
|
||||
public doms: {[x: number]: any} = {};
|
||||
|
||||
@ -40,7 +38,6 @@ export class AppDialogsManager {
|
||||
|
||||
//let chatClosedDiv = document.getElementById('chat-closed');
|
||||
|
||||
this.setListClickListener(this.pinnedChatList);
|
||||
this.setListClickListener(this.chatList);
|
||||
}
|
||||
|
||||
@ -131,20 +128,54 @@ export class AppDialogsManager {
|
||||
}
|
||||
|
||||
public sortDom() {
|
||||
/* let sorted = */appMessagesManager.dialogsStorage.dialogs
|
||||
console.log('sortDom');
|
||||
//return;
|
||||
|
||||
let dialogs = appMessagesManager.dialogsStorage.dialogs;
|
||||
|
||||
let inUpper: HTMLLIElement[] = [];
|
||||
let inBottom: HTMLLIElement[] = [];
|
||||
|
||||
let lastPinnedIndex = -1;
|
||||
for(let i = 0; i < dialogs.length; ++i) {
|
||||
let dialog = dialogs[i];
|
||||
if(!dialog.pFlags.pinned) break;
|
||||
lastPinnedIndex = i;
|
||||
}
|
||||
|
||||
let sorted = dialogs
|
||||
.filter((d: any) => !d.pFlags.pinned)
|
||||
.sort((a: any, b: any) => {
|
||||
let timeA = appMessagesManager.getMessage(a.top_message).date;
|
||||
let timeB = appMessagesManager.getMessage(b.top_message).date;
|
||||
|
||||
return timeB - timeA;
|
||||
})
|
||||
.forEach((d: any) => {
|
||||
});
|
||||
|
||||
if(lastPinnedIndex != -1) {
|
||||
sorted = dialogs.slice(0, lastPinnedIndex + 1).concat(sorted);
|
||||
}
|
||||
|
||||
let inViewportIndex = -1;
|
||||
sorted.forEach((d: any) => {
|
||||
let dom = this.getDialogDom(d.peerID);
|
||||
if(!dom) return;
|
||||
|
||||
this.chatList.append(dom.listEl);
|
||||
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('found no dom!', dom);
|
||||
}
|
||||
|
||||
//this.chatList.append(dom.listEl);
|
||||
});
|
||||
|
||||
this.chatsHidden.up = inUpper;
|
||||
this.chatsHidden.down = inBottom;
|
||||
}
|
||||
|
||||
public setLastMessage(dialog: any, lastMessage?: any, dom?: DialogDom) {
|
||||
@ -405,7 +436,13 @@ export class AppDialogsManager {
|
||||
};
|
||||
|
||||
if(!container) {
|
||||
(dialog.pFlags.pinned ? this.pinnedChatList : this.chatList).append(li);
|
||||
this.chatList.append(li);
|
||||
//this.appendTo.push(li);
|
||||
|
||||
if(dialog.pFlags.pinned) {
|
||||
li.classList.add('dialog-pinned');
|
||||
}
|
||||
|
||||
this.doms[dialog.peerID] = dom;
|
||||
this.setLastMessage(dialog);
|
||||
} else {
|
||||
|
@ -132,6 +132,7 @@ export class AppImManager {
|
||||
|
||||
private topbar: HTMLDivElement = null;
|
||||
private chatInput: HTMLDivElement = null;
|
||||
scrolledAll: boolean;
|
||||
|
||||
constructor() {
|
||||
this.log = logger('IM');
|
||||
@ -380,30 +381,39 @@ export class AppImManager {
|
||||
|
||||
// load more history
|
||||
if(!this.getHistoryPromise && !this.getHistoryTimeout /* && false */) {
|
||||
let history = Object.keys(this.bubbles).map(id => +id).sort();
|
||||
/* let history = appMessagesManager.historiesStorage[this.peerID].history;
|
||||
let length = history.length; */
|
||||
this.getHistoryTimeout = setTimeout(() => { // must be
|
||||
let history = Object.keys(this.bubbles).map(id => +id).sort();
|
||||
|
||||
/* let history = appMessagesManager.historiesStorage[this.peerID].history;
|
||||
let length = history.length; */
|
||||
|
||||
// filter negative ids
|
||||
for(let i = 0; i < history.length; ++i) {
|
||||
if(history[i] <= 0) history.splice(i, 1);
|
||||
else break;
|
||||
}
|
||||
|
||||
this.getHistoryTimeout = 0;
|
||||
|
||||
let willLoad = false;
|
||||
for(let i = 0; i < 10; ++i) {
|
||||
let msgID = history[i];
|
||||
if(!(msgID in this.bubbles) || msgID <= 0) continue;
|
||||
if(!this.scrolledAll) {
|
||||
for(let i = 0; i < 10; ++i) {
|
||||
let msgID = history[i];
|
||||
|
||||
let bubble = this.bubbles[msgID];
|
||||
|
||||
if(isElementInViewport(bubble)) {
|
||||
willLoad = true;
|
||||
|
||||
let bubble = this.bubbles[msgID];
|
||||
|
||||
if(isElementInViewport(bubble)) {
|
||||
willLoad = true;
|
||||
|
||||
this.log('Will load more (up) history by id:', history[0], 'maxID:', history[history.length - 1], history, bubble);
|
||||
/* false && */!testScroll && this.getHistory(history[0], true).then(() => { // uncomment
|
||||
this.onScroll();
|
||||
}).catch(err => {
|
||||
this.log.warn('Could not load more history, err:', err);
|
||||
});
|
||||
|
||||
break;
|
||||
this.log('Will load more (up) history by id:', history[0], 'maxID:', history[history.length - 1], history, bubble);
|
||||
/* false && */!testScroll && this.getHistory(history[0], true).then(() => { // uncomment
|
||||
this.onScroll();
|
||||
}).catch(err => {
|
||||
this.log.warn('Could not load more history, err:', err);
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -413,8 +423,6 @@ export class AppImManager {
|
||||
if(!willLoad && history.indexOf(/* this.lastDialog */dialog.top_message) === -1) {
|
||||
let lastMsgIDs = history.slice(-10);
|
||||
for(let msgID of lastMsgIDs) {
|
||||
if(!(msgID in this.bubbles) || msgID <= 0) continue;
|
||||
|
||||
let bubble = this.bubbles[msgID];
|
||||
|
||||
if(isElementInViewport(bubble)) {
|
||||
@ -520,6 +528,7 @@ export class AppImManager {
|
||||
|
||||
public cleanup() {
|
||||
this.peerID = $rootScope.selectedPeerID = 0;
|
||||
this.scrolledAll = false;
|
||||
|
||||
if(this.lastContainerDiv) this.lastContainerDiv.remove();
|
||||
if(this.firstContainerDiv) this.firstContainerDiv.remove();
|
||||
@ -645,7 +654,7 @@ export class AppImManager {
|
||||
|
||||
appSidebarRight.fillProfileElements()
|
||||
]).catch(err => {
|
||||
this.log.error(err);
|
||||
this.log.error('setPeer promises error:', err);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1189,7 +1198,12 @@ export class AppImManager {
|
||||
if(!result || !result.history) {
|
||||
console.timeEnd('render history total');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// commented bot getProfile in getHistory!
|
||||
if(!result.history/* .filter((id: number) => id > 0) */.length && !isBackLimit) {
|
||||
this.scrolledAll = true;
|
||||
}
|
||||
|
||||
//this.chatInner.innerHTML = '';
|
||||
|
||||
|
@ -30,7 +30,7 @@ export class AppMessagesIDsManager {
|
||||
}
|
||||
|
||||
public getMessageLocalID(fullMsgID: number) {
|
||||
if (!fullMsgID) {
|
||||
if(!fullMsgID) {
|
||||
return 0;
|
||||
}
|
||||
return fullMsgID % this.fullMsgIDModulus;
|
||||
|
@ -2418,7 +2418,7 @@ export class AppMessagesManager {
|
||||
|
||||
// need be commented for read out messages
|
||||
//if(newUnreadCount != 0 || !isOut) { // fix 16.11.2019 (maybe not)
|
||||
console.warn(dT(), 'cnt', peerID, newUnreadCount);
|
||||
console.warn(dT(), 'cnt', peerID, newUnreadCount, isOut, foundDialog, update, foundAffected);
|
||||
$rootScope.$broadcast('dialog_unread', {peerID: peerID, count: newUnreadCount});
|
||||
//}
|
||||
|
||||
@ -3068,7 +3068,7 @@ export class AppMessagesManager {
|
||||
public requestHistory(peerID: number, maxID: number, limit: number, offset = 0) {
|
||||
var isChannel = AppPeersManager.isChannel(peerID);
|
||||
|
||||
console.trace('requestHistory', peerID, maxID, limit, offset);
|
||||
//console.trace('requestHistory', peerID, maxID, limit, offset);
|
||||
|
||||
return MTProto.apiManager.invokeApi('messages.getHistory', {
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
@ -3079,16 +3079,7 @@ export class AppMessagesManager {
|
||||
max_id: 0,
|
||||
min_id: 0,
|
||||
hash: 0
|
||||
}/* {
|
||||
peer: AppPeersManager.getInputPeerByID(peerID),
|
||||
offset_id: offset,
|
||||
offset_date: 0,
|
||||
add_offset: offset || 0,
|
||||
limit: limit || 0,
|
||||
max_id: maxID,
|
||||
min_id: 0,
|
||||
hash: 0
|
||||
} */, {
|
||||
}, {
|
||||
timeout: 300,
|
||||
noErrorBox: true
|
||||
}).then((historyResult: any) => {
|
||||
@ -3101,22 +3092,19 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
var length = historyResult.messages.length;
|
||||
if(length &&
|
||||
historyResult.messages[length - 1].deleted) {
|
||||
if(length && historyResult.messages[length - 1].deleted) {
|
||||
historyResult.messages.splice(length - 1, 1);
|
||||
length--;
|
||||
historyResult.count--;
|
||||
}
|
||||
|
||||
if(
|
||||
peerID < 0 ||
|
||||
!appUsersManager.isBot(peerID) ||
|
||||
(length == limit && limit < historyResult.count)
|
||||
) {
|
||||
// don't need the intro now
|
||||
/* if(peerID < 0 || !appUsersManager.isBot(peerID) || (length == limit && limit < historyResult.count)) {
|
||||
return historyResult;
|
||||
}
|
||||
} */
|
||||
return historyResult;
|
||||
|
||||
return appProfileManager.getProfile(peerID).then((userFull: any) => {
|
||||
/* return appProfileManager.getProfile(peerID).then((userFull: any) => {
|
||||
var description = userFull.bot_info && userFull.bot_info.description;
|
||||
if(description) {
|
||||
var messageID = this.tempID--;
|
||||
@ -3142,7 +3130,7 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
return historyResult;
|
||||
});
|
||||
}); */
|
||||
}, (error) => {
|
||||
switch (error.type) {
|
||||
case 'CHANNEL_PRIVATE':
|
||||
|
@ -1,10 +1,9 @@
|
||||
import { logger } from "../polyfill";
|
||||
import { scrollable } from "../../components/misc";
|
||||
import { scrollable, putPreloader } from "../../components/misc";
|
||||
import appMessagesManager from "./appMessagesManager";
|
||||
import appDialogsManager from "./appDialogsManager";
|
||||
import { isElementInViewport, $rootScope } from "../utils";
|
||||
import { isElementInViewport } from "../utils";
|
||||
import appMessagesIDsManager from "./appMessagesIDsManager";
|
||||
import apiManager from '../mtproto/apiManager';
|
||||
import appImManager from "./appImManager";
|
||||
|
||||
class AppSidebarLeft {
|
||||
@ -12,13 +11,22 @@ class AppSidebarLeft {
|
||||
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 menuEl = this.toolsBtn.querySelector('.btn-menu');
|
||||
private savedBtn = this.menuEl.querySelector('.menu-saved');
|
||||
|
||||
private listsContainer: HTMLDivElement = null;
|
||||
private searchMessagesList: HTMLUListElement = null;
|
||||
|
||||
private chatsContainer = document.getElementById('chats-container') as HTMLDivElement;
|
||||
private chatsOffsetIndex = 0;
|
||||
private chatsScroll: HTMLDivElement;
|
||||
private chatsHidden: any;
|
||||
private chatsPreloader: HTMLDivElement;
|
||||
private chatsLoadCount = 0;
|
||||
private loadDialogsPromise: Promise<any>;
|
||||
private hiddenScroll: any;
|
||||
|
||||
private log = logger('SL');
|
||||
|
||||
private peerID = 0;
|
||||
@ -29,31 +37,43 @@ class AppSidebarLeft {
|
||||
|
||||
private searchPromise: Promise<void> = null;
|
||||
private searchTimeout: number = 0;
|
||||
|
||||
|
||||
private query = '';
|
||||
|
||||
public myID = 0;
|
||||
|
||||
constructor() {
|
||||
this.listsContainer = scrollable(this.searchContainer);
|
||||
this.chatsPreloader = document.createElement('div');
|
||||
this.chatsPreloader.classList.add('preloader');
|
||||
putPreloader(this.chatsPreloader);
|
||||
this.chatsContainer.append(this.chatsPreloader);
|
||||
|
||||
this.chatsLoadCount = Math.round(document.body.scrollHeight / 70 * 1.5);
|
||||
|
||||
let {container: chatsScroll, hiddenElements: chatsHidden, onScroll: hiddenScroll} = scrollable(this.chatsContainer as HTMLDivElement);
|
||||
this.chatsScroll = chatsScroll;
|
||||
this.chatsHidden = chatsHidden;
|
||||
this.hiddenScroll = hiddenScroll;
|
||||
|
||||
appDialogsManager.chatsHidden = this.chatsHidden;
|
||||
|
||||
chatsScroll.addEventListener('scroll', this.onChatsScroll.bind(this));
|
||||
|
||||
this.listsContainer = scrollable(this.searchContainer).container;
|
||||
this.searchMessagesList = document.createElement('ul');
|
||||
|
||||
apiManager.getUserID().then((id) => {
|
||||
this.myID = id;
|
||||
});
|
||||
|
||||
$rootScope.$on('user_auth', (e: CustomEvent) => {
|
||||
let userAuth = e.detail;
|
||||
this.myID = userAuth ? userAuth.id : 0;
|
||||
});
|
||||
|
||||
|
||||
this.savedBtn.addEventListener('click', () => {
|
||||
appImManager.setPeer(this.myID);
|
||||
appImManager.setPeer(appImManager.myID);
|
||||
});
|
||||
|
||||
/* this.listsContainer.insertBefore(this.searchMessagesList, this.listsContainer.lastElementChild);
|
||||
for(let i = 0; i < 25; ++i) {
|
||||
let li = document.createElement('li');
|
||||
li.innerHTML = `<div class="user-avatar is-online" style="font-size: 0px;"><img src="assets/img/camomile.jpg"></div><div class="user-caption"><p><span class="user-title">Влад</span><span><span class="message-status"></span><span class="message-time">14:41</span></span></p><p><span class="user-last-message">это важно</span><span class="tgico-pinnedchat"></span></p></div><div class="c-ripple"><span class="c-ripple__circle" style="top: 65px; left: 338.5px;"></span></div>`;
|
||||
this.searchMessagesList.append(li);
|
||||
} */
|
||||
|
||||
this.listsContainer.addEventListener('scroll', this.onSidebarScroll.bind(this));
|
||||
|
||||
this.searchContainer.append(this.listsContainer);
|
||||
//this.searchContainer.append(this.listsContainer);
|
||||
|
||||
appDialogsManager.setListClickListener(this.searchMessagesList);
|
||||
|
||||
@ -85,13 +105,13 @@ class AppSidebarLeft {
|
||||
this.log('input', value);
|
||||
|
||||
if(this.listsContainer.contains(this.searchMessagesList)) {
|
||||
this.listsContainer.removeChild(this.searchMessagesList)
|
||||
this.listsContainer.removeChild(this.searchMessagesList);
|
||||
}
|
||||
|
||||
if(!value.trim()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
this.query = value;
|
||||
this.minMsgID = 0;
|
||||
this.loadedCount = 0;
|
||||
@ -113,18 +133,70 @@ class AppSidebarLeft {
|
||||
this.peerID = 0;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
setTimeout(() => this.onSidebarScroll(), 0);
|
||||
this.chatsLoadCount = Math.round(document.body.scrollHeight / 70 * 1.5);
|
||||
|
||||
setTimeout(() => {
|
||||
this.onSidebarScroll();
|
||||
this.onChatsScroll();
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
|
||||
public async loadDialogs() {
|
||||
if(this.loadDialogsPromise/* || 1 == 1 */) return this.loadDialogsPromise;
|
||||
|
||||
this.chatsContainer.append(this.chatsPreloader);
|
||||
|
||||
//let offset = appMessagesManager.generateDialogIndex();/* appMessagesManager.dialogsNum */;
|
||||
|
||||
try {
|
||||
this.loadDialogsPromise = appMessagesManager.getConversations('', this.chatsOffsetIndex, this.chatsLoadCount);
|
||||
|
||||
let result = await this.loadDialogsPromise;
|
||||
|
||||
if(result && result.dialogs && result.dialogs.length) {
|
||||
this.chatsOffsetIndex = result.dialogs[result.dialogs.length - 1].index;
|
||||
result.dialogs.forEach((dialog: any) => {
|
||||
appDialogsManager.addDialog(dialog);
|
||||
});
|
||||
}
|
||||
|
||||
this.log('loaded ' + this.chatsLoadCount + ' dialogs by offset:', this.chatsOffsetIndex, result, this.chatsHidden);
|
||||
this.hiddenScroll();
|
||||
} catch(err) {
|
||||
this.log.error(err);
|
||||
}
|
||||
|
||||
this.chatsPreloader.remove();
|
||||
this.loadDialogsPromise = undefined;
|
||||
}
|
||||
|
||||
public onChatsScroll() {
|
||||
if(this.chatsHidden.down.length > 0/* || 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 onSidebarScroll() {
|
||||
if(!this.query.trim()) return;
|
||||
|
||||
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();
|
||||
@ -144,21 +216,23 @@ class AppSidebarLeft {
|
||||
|
||||
this.searchInput.focus();
|
||||
}
|
||||
|
||||
|
||||
private searchMore() {
|
||||
if(this.searchPromise) return this.searchPromise;
|
||||
|
||||
|
||||
let query = this.query;
|
||||
|
||||
|
||||
if(!query.trim()) return;
|
||||
|
||||
if(this.loadedCount != 0 && this.loadedCount >= this.foundCount) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
let maxID = appMessagesIDsManager.getMessageIDInfo(this.minMsgID)[0];
|
||||
|
||||
|
||||
return this.searchPromise = appMessagesManager.getSearch(this.peerID, query, null, maxID, 20, this.offsetRate).then(res => {
|
||||
this.searchPromise = null;
|
||||
|
||||
|
||||
if(this.searchInput.value != query) {
|
||||
return;
|
||||
}
|
||||
@ -166,7 +240,7 @@ class AppSidebarLeft {
|
||||
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();
|
||||
}
|
||||
@ -177,7 +251,7 @@ class AppSidebarLeft {
|
||||
|
||||
if(!originalDialog) {
|
||||
this.log('no original dialog by message:', message);
|
||||
|
||||
|
||||
originalDialog = {
|
||||
peerID: message.peerID,
|
||||
pFlags: {},
|
||||
@ -188,11 +262,11 @@ class AppSidebarLeft {
|
||||
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;
|
||||
}
|
||||
|
@ -65,6 +65,8 @@ class AppSidebarRight {
|
||||
|
||||
private log = logger('SR');
|
||||
|
||||
private peerID = 0;
|
||||
|
||||
constructor() {
|
||||
let container = this.profileContentEl.querySelector('.profile-tabs-content') as HTMLDivElement;
|
||||
let tabs = this.profileContentEl.querySelector('.profile-tabs') as HTMLUListElement;
|
||||
@ -143,7 +145,7 @@ class AppSidebarRight {
|
||||
}
|
||||
|
||||
public loadSidebarMedia(single = false) {
|
||||
let peerID = $rootScope.selectedPeerID;
|
||||
let peerID = this.peerID;
|
||||
|
||||
let typesToLoad = single ? [this.sharedMediaType] : this.sharedMediaTypes;
|
||||
|
||||
@ -164,14 +166,14 @@ class AppSidebarRight {
|
||||
? appMessagesManager.historiesStorage[peerID].history.slice() : [];
|
||||
|
||||
maxID = !maxID && ids.length ? ids[ids.length - 1] : maxID;
|
||||
this.log('search house of glass pre', type, ids, maxID);
|
||||
//this.log('search house of glass pre', type, ids, maxID);
|
||||
|
||||
return this.loadSidebarMediaPromises[type] = appMessagesManager.getSearch(peerID, '', {_: type}, maxID, 50)
|
||||
.then(value => {
|
||||
ids = ids.concat(value.history);
|
||||
history.push(...ids);
|
||||
|
||||
this.log('search house of glass', type, value, ids, this.cleared);
|
||||
//this.log('search house of glass', type, value, ids, this.cleared);
|
||||
|
||||
if($rootScope.selectedPeerID != peerID) {
|
||||
this.log.warn('peer changed');
|
||||
@ -188,11 +190,11 @@ class AppSidebarRight {
|
||||
let message = appMessagesManager.getMessage(mid);
|
||||
if(!message.media) return;
|
||||
|
||||
/* 'inputMessagesFilterContacts',
|
||||
'inputMessagesFilterPhotoVideo',
|
||||
'inputMessagesFilterDocument',
|
||||
'inputMessagesFilterUrl',
|
||||
'inputMessagesFilterVoice'*/
|
||||
/*'inputMessagesFilterContacts',
|
||||
'inputMessagesFilterPhotoVideo',
|
||||
'inputMessagesFilterDocument',
|
||||
'inputMessagesFilterUrl',
|
||||
'inputMessagesFilterVoice'*/
|
||||
switch(type) {
|
||||
case 'inputMessagesFilterPhotoVideo': {
|
||||
/* if(!(message.media.photo || message.media.document || message.media.webpage.document)) {
|
||||
@ -281,7 +283,8 @@ class AppSidebarRight {
|
||||
}
|
||||
|
||||
public fillProfileElements() {
|
||||
let peerID = $rootScope.selectedPeerID;
|
||||
let peerID = this.peerID = $rootScope.selectedPeerID;
|
||||
this.loadSidebarMediaPromises = {};
|
||||
|
||||
this.profileContentEl.parentElement.scrollTop = 0;
|
||||
this.profileElements.bio.style.display = 'none';
|
||||
@ -311,19 +314,19 @@ class AppSidebarRight {
|
||||
};
|
||||
|
||||
// username
|
||||
let username = appPeersManager.getPeerUsername($rootScope.selectedPeerID);
|
||||
let username = appPeersManager.getPeerUsername(peerID);
|
||||
if(username) {
|
||||
setText(appPeersManager.getPeerUsername($rootScope.selectedPeerID), this.profileElements.username);
|
||||
setText(appPeersManager.getPeerUsername(peerID), this.profileElements.username);
|
||||
}
|
||||
|
||||
if($rootScope.selectedPeerID > 0) {
|
||||
let user = appUsersManager.getUser($rootScope.selectedPeerID);
|
||||
if(peerID > 0) {
|
||||
let user = appUsersManager.getUser(peerID);
|
||||
if(user.phone) {
|
||||
setText('+' + formatPhoneNumber(user.phone).formatted, this.profileElements.phone);
|
||||
}
|
||||
|
||||
appProfileManager.getProfile($rootScope.selectedPeerID, true).then(userFull => {
|
||||
if($rootScope.selectedPeerID != peerID) {
|
||||
appProfileManager.getProfile(peerID, true).then(userFull => {
|
||||
if(this.peerID != peerID) {
|
||||
this.log.warn('peer changed');
|
||||
return;
|
||||
}
|
||||
@ -340,10 +343,10 @@ class AppSidebarRight {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
let chat = appPeersManager.getPeer($rootScope.selectedPeerID);
|
||||
let chat = appPeersManager.getPeer(peerID);
|
||||
|
||||
appProfileManager.getChatFull(chat.id).then((chatFull: any) => {
|
||||
if($rootScope.selectedPeerID != peerID) {
|
||||
if(this.peerID != peerID) {
|
||||
this.log.warn('peer changed');
|
||||
return;
|
||||
}
|
||||
@ -356,7 +359,7 @@ class AppSidebarRight {
|
||||
});
|
||||
}
|
||||
|
||||
let dialog: any = appMessagesManager.getDialogByPeerID($rootScope.selectedPeerID);
|
||||
let dialog: any = appMessagesManager.getDialogByPeerID(peerID);
|
||||
if(dialog.length) {
|
||||
dialog = dialog[0];
|
||||
let muted = false;
|
||||
@ -368,8 +371,8 @@ class AppSidebarRight {
|
||||
}
|
||||
}
|
||||
|
||||
if($rootScope.selectedPeerID < 0) { // not human
|
||||
let isChannel = appPeersManager.isChannel($rootScope.selectedPeerID) && !appPeersManager.isMegagroup($rootScope.selectedPeerID);
|
||||
if(peerID < 0) { // not human
|
||||
let isChannel = appPeersManager.isChannel(peerID) && !appPeersManager.isMegagroup(peerID);
|
||||
if(isChannel) {
|
||||
appImManager.btnMute.classList.remove('tgico-mute', 'tgico-unmute');
|
||||
appImManager.btnMute.classList.add(muted ? 'tgico-unmute' : 'tgico-mute');
|
||||
|
41
src/scss/materialize.scss
vendored
41
src/scss/materialize.scss
vendored
@ -1,41 +0,0 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
// Color
|
||||
@import "components/color-variables";
|
||||
@import "components/color-classes";
|
||||
|
||||
// Variables;
|
||||
@import "components/variables";
|
||||
|
||||
// Reset
|
||||
@import "components/normalize";
|
||||
|
||||
// components
|
||||
@import "components/global";
|
||||
@import "components/badges";
|
||||
@import "components/icons-material-design";
|
||||
@import "components/grid";
|
||||
@import "components/navbar";
|
||||
@import "components/typography";
|
||||
@import "components/transitions";
|
||||
@import "components/cards";
|
||||
@import "components/toast";
|
||||
@import "components/tabs";
|
||||
@import "components/tooltip";
|
||||
@import "components/buttons";
|
||||
@import "components/dropdown";
|
||||
@import "components/waves";
|
||||
@import "components/modal";
|
||||
@import "components/collapsible";
|
||||
@import "components/chips";
|
||||
@import "components/materialbox";
|
||||
@import "components/forms/forms";
|
||||
@import "components/table_of_contents";
|
||||
@import "components/sidenav";
|
||||
@import "components/preloader";
|
||||
@import "components/slider";
|
||||
@import "components/carousel";
|
||||
@import "components/tapTarget";
|
||||
@import "components/pulse";
|
||||
@import "components/datepicker";
|
||||
@import "components/timepicker";
|
@ -5,9 +5,14 @@
|
||||
.sidebar-content {
|
||||
width: 100%;
|
||||
max-height: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
display: flex; /* idk why but need */
|
||||
position: relative;
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
#chats-container {
|
||||
@ -29,7 +34,7 @@
|
||||
background: #fff;
|
||||
|
||||
&.active {
|
||||
display: block;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user