From 44beca2458d239919829dfef8b41940beb35b01f Mon Sep 17 00:00:00 2001 From: Eduard Kuzmenko Date: Thu, 24 Dec 2020 05:09:33 +0200 Subject: [PATCH] Handle peer change for chat list elements Handle contextmenu event for ripple --- src/components/appSearch.ts | 7 +- src/components/ripple.ts | 5 + src/components/sidebarLeft/index.ts | 10 +- src/components/sidebarLeft/tabs/contacts.ts | 3 +- .../sidebarRight/tabs/pollResults.ts | 2 +- src/lib/appManagers/appDialogsManager.ts | 112 +++++++----------- 6 files changed, 59 insertions(+), 80 deletions(-) diff --git a/src/components/appSearch.ts b/src/components/appSearch.ts index 17b1a574..321457a4 100644 --- a/src/components/appSearch.ts +++ b/src/components/appSearch.ts @@ -15,7 +15,7 @@ export class SearchGroup { nameEl: HTMLDivElement; list: HTMLUListElement; - constructor(public name: string, public type: string, private clearable = true, className?: string, clickable = true) { + constructor(public name: string, public type: string, private clearable = true, className?: string, clickable = true, public autonomous = true) { this.list = document.createElement('ul'); this.container = document.createElement('div'); if(className) this.container.className = className; @@ -32,7 +32,7 @@ export class SearchGroup { this.container.style.display = 'none'; if(clickable) { - appDialogsManager.setListClickListener(this.list); + appDialogsManager.setListClickListener(this.list, undefined, undefined, autonomous); } } @@ -183,7 +183,8 @@ export default class AppSearch { dialog: peerId, container: group.list, drawStatus: false, - avatarSize: 48 + avatarSize: 48, + autonomous: group.autonomous }); if(showMembersCount && (peer.participants_count || peer.participants)) { diff --git a/src/components/ripple.ts b/src/components/ripple.ts index 47de65f9..e414c33d 100644 --- a/src/components/ripple.ts +++ b/src/components/ripple.ts @@ -55,6 +55,10 @@ export function ripple(elem: HTMLElement, callback: (id: number) => Promise Promise { @@ -222,7 +222,8 @@ export class AppSidebarLeft extends SidebarSlider { container: this.searchGroups.people.list, drawStatus: false, onlyFirstName: true, - avatarSize: 54 + avatarSize: 54, + autonomous: false }); }); } @@ -358,7 +359,8 @@ export class AppSidebarLeft extends SidebarSlider { container: this.searchGroups.recent.list, drawStatus: false, meAsSaved: true, - avatarSize: 48 + avatarSize: 48, + autonomous: false }); dom.lastMessageSpan.innerText = peerId > 0 ? appUsersManager.getUserStatusString(peerId) : appChatsManager.getChatMembersString(peerId); diff --git a/src/components/sidebarLeft/tabs/contacts.ts b/src/components/sidebarLeft/tabs/contacts.ts index 2f79c37f..1ee9901e 100644 --- a/src/components/sidebarLeft/tabs/contacts.ts +++ b/src/components/sidebarLeft/tabs/contacts.ts @@ -94,7 +94,8 @@ export default class AppContactsTab implements SliderTab { dialog: user.id, container: this.list, drawStatus: false, - avatarSize: 48 + avatarSize: 48, + autonomous: false }); let status = appUsersManager.getUserStatusString(user.id); diff --git a/src/components/sidebarRight/tabs/pollResults.ts b/src/components/sidebarRight/tabs/pollResults.ts index 204d1371..67eed4c8 100644 --- a/src/components/sidebarRight/tabs/pollResults.ts +++ b/src/components/sidebarRight/tabs/pollResults.ts @@ -72,7 +72,7 @@ export default class AppPollResultsTab implements SliderTab { appDialogsManager.setListClickListener(list, () => { this.closeBtn.click(); - }); + }, undefined, true); list.style.minHeight = Math.min(result.voters, 4) * 50 + 'px'; diff --git a/src/lib/appManagers/appDialogsManager.ts b/src/lib/appManagers/appDialogsManager.ts index 23c63672..15dfdfd1 100644 --- a/src/lib/appManagers/appDialogsManager.ts +++ b/src/lib/appManagers/appDialogsManager.ts @@ -4,16 +4,16 @@ import { horizontalMenu } from "../../components/horizontalMenu"; import { attachContextMenuListener, putPreloader } from "../../components/misc"; import { ripple } from "../../components/ripple"; //import Scrollable from "../../components/scrollable"; -import Scrollable, { ScrollableX, SliceSides, SliceSidesContainer } from "../../components/scrollable"; +import Scrollable, { ScrollableX, SliceSides } from "../../components/scrollable"; import appSidebarLeft from "../../components/sidebarLeft"; import { formatDateAccordingToToday } from "../../helpers/date"; import { escapeRegExp } from "../../helpers/string"; -import { isApple, isSafari } from "../../helpers/userAgent"; +import { isApple } from "../../helpers/userAgent"; import { logger, LogLevels } from "../logger"; import { RichTextProcessor } from "../richtextprocessor"; import rootScope from "../rootScope"; import { findUpClassName, findUpTag, positionElementByIndex } from "../../helpers/dom"; -import appImManager, { AppImManager } from "./appImManager"; +import appImManager from "./appImManager"; import appMessagesManager, { Dialog } from "./appMessagesManager"; import {MyDialogFilter as DialogFilter} from "../storages/filters"; import appPeersManager from './appPeersManager'; @@ -157,7 +157,6 @@ export class AppDialogsManager { public chatList = this._chatList; public doms: {[peerId: number]: DialogDom} = {}; - public lastActiveListElement: HTMLElement = null; public chatsContainer = document.getElementById('chatlist-container') as HTMLDivElement; private chatsPreloader: HTMLDivElement; @@ -199,6 +198,8 @@ export class AppDialogsManager { private sliceTimeout: number; private reorderDialogsTimeout: number; + private lastActiveElements: Set = new Set(); + constructor() { this.chatsPreloader = putPreloader(null, true); @@ -335,21 +336,22 @@ export class AppDialogsManager { }); rootScope.on('peer_changed', (e) => { - let peerId = e.detail; + const peerId = e.detail; - let lastPeerId = this.lastActiveListElement && +this.lastActiveListElement.getAttribute('data-peerId'); - if(this.lastActiveListElement && lastPeerId != peerId) { - this.lastActiveListElement.classList.remove('active'); - this.lastActiveListElement = null; - } - - if(lastPeerId != peerId) { - let dom = this.getDialogDom(peerId); - if(dom) { - this.lastActiveListElement = dom.listEl; - dom.listEl.classList.add('active'); + //const perf = performance.now(); + for(const element of this.lastActiveElements) { + if(+element.getAttribute('data-peerid') !== peerId) { + element.classList.remove('active'); + this.lastActiveElements.delete(element); } } + + const elements = Array.from(document.querySelectorAll(`[data-autonomous="0"] li[data-peerid="${peerId}"]`)) as HTMLElement[]; + elements.forEach(element => { + element.classList.add('active'); + this.lastActiveElements.add(element); + }); + //this.log('peer_changed total time:', performance.now() - perf); }); rootScope.on('filter_update', (e) => { @@ -519,7 +521,6 @@ export class AppDialogsManager { this.doms = {}; this.scroll.loadedAll.top = true; this.scroll.loadedAll.bottom = false; - this.lastActiveListElement = null; this.loadDialogsPromise = undefined; this.chatList = this.chatLists[this.filterId]; this.loadDialogs(); @@ -561,10 +562,6 @@ export class AppDialogsManager { const listEl = this.doms[peerId].listEl; listEl.remove(); delete this.doms[peerId]; - - if(this.lastActiveListElement == listEl) { - this.lastActiveListElement = null; - } } } } @@ -687,50 +684,17 @@ export class AppDialogsManager { if(result.dialogs.length) { const dialogs = side == 'top' ? result.dialogs.slice().reverse() : result.dialogs; - /* let previousScrollHeightMinusTop: number; - //if(isApple || true) { - if(isApple && side == 'top') { - const {scrollTop, scrollHeight} = this.scroll; - - previousScrollHeightMinusTop = side == 'top' ? scrollHeight - scrollTop : scrollTop; - //this.scroll.scrollLocked = 1; - } */ - dialogs.forEach((dialog) => { this.addDialogNew({ dialog, append: side == 'bottom' }); }); - - /* if(previousScrollHeightMinusTop !== undefined) { - const newScrollTop = side == 'top' ? this.scroll.scrollHeight - previousScrollHeightMinusTop : previousScrollHeightMinusTop; - - // touchSupport for safari iOS - isTouchSupported && isApple && (this.scroll.container.style.overflow = 'hidden'); - this.scroll.scrollTop = newScrollTop; - isTouchSupported && isApple && (this.scroll.container.style.overflow = ''); - } */ - - //this.scroll.scrollLocked = 0; - - //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); - //} } 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) { @@ -839,7 +803,10 @@ export class AppDialogsManager { this.loadDialogs(side); }; - public setListClickListener(list: HTMLUListElement, onFound?: () => void, withContext = false) { + public setListClickListener(list: HTMLUListElement, onFound?: () => void, withContext = false, autonomous = false) { + let lastActiveListElement: HTMLElement; + + list.dataset.autonomous = '' + +autonomous; list.addEventListener('mousedown', (e) => { if(e.button != 0) return; //cancelEvent(e); @@ -854,10 +821,17 @@ export class AppDialogsManager { elem = elem.parentElement; - let samePeer = this.lastActiveListElement == elem; + if(autonomous) { + let sameElement = lastActiveListElement === elem; + if(lastActiveListElement && !sameElement) { + lastActiveListElement.classList.remove('active'); + } - if(this.lastActiveListElement && !samePeer) { - this.lastActiveListElement.classList.remove('active'); + if(elem) { + elem.classList.add('active'); + lastActiveListElement = elem; + this.lastActiveElements.add(elem); + } } if(elem) { @@ -866,11 +840,6 @@ export class AppDialogsManager { let peerId = +elem.getAttribute('data-peerId'); let lastMsgId = +elem.dataset.mid || undefined; - if(!samePeer) { - elem.classList.add('active'); - this.lastActiveListElement = elem; - } - appImManager.setPeer(peerId, lastMsgId); } else { appImManager.setPeer(0); @@ -1120,12 +1089,13 @@ export class AppDialogsManager { onlyFirstName?: boolean, meAsSaved?: boolean, append?: boolean, - avatarSize?: number + avatarSize?: number, + autonomous?: boolean }) { - return this.addDialog(options.dialog, options.container, options.drawStatus, options.rippleEnabled, options.onlyFirstName, options.meAsSaved, options.append, options.avatarSize); + return this.addDialog(options.dialog, options.container, options.drawStatus, options.rippleEnabled, options.onlyFirstName, options.meAsSaved, options.append, options.avatarSize, options.autonomous); } - public addDialog(_dialog: Dialog | number, container?: HTMLUListElement | Scrollable, drawStatus = true, rippleEnabled = true, onlyFirstName = false, meAsSaved = true, append = true, avatarSize = 54) { + public addDialog(_dialog: Dialog | number, container?: HTMLUListElement | Scrollable, drawStatus = true, rippleEnabled = true, onlyFirstName = false, meAsSaved = true, append = true, avatarSize = 54, autonomous = !!container) { let dialog: Dialog; if(typeof(_dialog) === 'number') { @@ -1276,11 +1246,6 @@ export class AppDialogsManager { this.doms[dialog.peerId] = dom; - if(appImManager.chat?.peerId == peerId) { - li.classList.add('active'); - this.lastActiveListElement = li; - } - /* if(container) { container.append(li); } */ @@ -1289,6 +1254,11 @@ export class AppDialogsManager { } else { container[method](li); } + + if(!autonomous && appImManager.chat?.peerId === peerId) { + li.classList.add('active'); + this.lastActiveElements.add(li); + } return {dom, dialog}; }