//import { logger } from "../polyfill"; import { formatNumber } from "../../helpers/number"; import appChatsManager from "../../lib/appManagers/appChatsManager"; import appDialogsManager from "../../lib/appManagers/appDialogsManager"; import appImManager from "../../lib/appManagers/appImManager"; import appPeersManager from "../../lib/appManagers/appPeersManager"; import appStateManager from "../../lib/appManagers/appStateManager"; import appUsersManager from "../../lib/appManagers/appUsersManager"; import { MOUNT_CLASS_TO } from "../../lib/mtproto/mtproto_config"; import $rootScope from "../../lib/rootScope"; import { findUpClassName, findUpTag } from "../../helpers/dom"; import AppSearch, { SearchGroup } from "../appSearch"; import AvatarElement from "../avatar"; import { parseMenuButtonsTo } from "../misc"; import { ScrollableX } from "../scrollable"; import SearchInput from "../searchInput"; import SidebarSlider from "../slider"; import Transition from "../transition"; import AppAddMembersTab from "./tabs/addMembers"; import AppArchivedTab from "./tabs/archivedTab"; import AppChatFoldersTab from "./tabs/chatFolders"; import AppContactsTab from "./tabs/contacts"; import AppEditFolderTab from "./tabs/editFolder"; import AppEditProfileTab from "./tabs/editProfile"; import AppIncludedChatsTab from "./tabs/includedChats"; import AppNewChannelTab from "./tabs/newChannel"; import AppNewGroupTab from "./tabs/newGroup"; import AppSettingsTab from "./tabs/settings"; AvatarElement; const newChannelTab = new AppNewChannelTab(); const addMembersTab = new AppAddMembersTab(); const contactsTab = new AppContactsTab(); const newGroupTab = new AppNewGroupTab(); const settingsTab = new AppSettingsTab(); const editProfileTab = new AppEditProfileTab(); const chatFoldersTab = new AppChatFoldersTab(); const editFolderTab = new AppEditFolderTab(); const includedChatsTab = new AppIncludedChatsTab(); const archivedTab = new AppArchivedTab(); /* const Transition = (container: HTMLElement, duration: number, from: HTMLElement, to: HTMLElement) => { if(to.classList.contains('active')) return Promise.resolve(); container.classList.add('animating'); const backwards = whichChild(to) < whichChild(from); if(backwards) { container.classList.add('backwards'); } from.classList.add('from'); to.classList.add('to'); return new Promise((resolve) => { setTimeout(() => { from.classList.remove('from', 'active'); container.classList.remove('animating', 'backwards'); to.classList.replace('to', 'active'); resolve(); }, duration); }); }; */ export class AppSidebarLeft extends SidebarSlider { public static SLIDERITEMSIDS = { archived: 1, contacts: 2, newChannel: 3, addMembers: 4, newGroup: 5, settings: 6, editProfile: 7, chatFolders: 8, editFolder: 9, includedChats: 10, }; private toolsBtn: HTMLButtonElement; private backBtn: HTMLButtonElement; private searchContainer: HTMLDivElement; //private searchInput = document.getElementById('global-search') as HTMLInputElement; private searchInput: SearchInput; private menuEl: HTMLElement; private buttons: { newGroup: HTMLButtonElement, contacts: HTMLButtonElement, archived: HTMLButtonElement, saved: HTMLButtonElement, settings: HTMLButtonElement, help: HTMLButtonElement } = {} as any; public archivedCount: HTMLSpanElement; private newBtnMenu: HTMLElement; private newButtons: { channel: HTMLButtonElement, group: HTMLButtonElement, privateChat: HTMLButtonElement, } = {} as any; public archivedTab: AppArchivedTab; public newChannelTab: AppNewChannelTab; public addMembersTab: AppAddMembersTab; public contactsTab: AppContactsTab; public newGroupTab: AppNewGroupTab; public settingsTab: AppSettingsTab; public editProfileTab: AppEditProfileTab; public chatFoldersTab: AppChatFoldersTab; public editFolderTab: AppEditFolderTab; public includedChatsTab: AppIncludedChatsTab; //private log = logger('SL'); private searchGroups: {[k in 'contacts' | 'globalContacts' | 'messages' | 'people' | 'recent']: SearchGroup} = {} as any; private globalSearch: AppSearch; // peerIDs private recentSearch: number[] = []; private recentSearchLoaded = false; private recentSearchClearBtn: HTMLElement; constructor() { super(document.getElementById('column-left') as HTMLDivElement, { [AppSidebarLeft.SLIDERITEMSIDS.archived]: archivedTab, [AppSidebarLeft.SLIDERITEMSIDS.newChannel]: newChannelTab, [AppSidebarLeft.SLIDERITEMSIDS.contacts]: contactsTab, [AppSidebarLeft.SLIDERITEMSIDS.addMembers]: addMembersTab, [AppSidebarLeft.SLIDERITEMSIDS.newGroup]: newGroupTab, [AppSidebarLeft.SLIDERITEMSIDS.settings]: settingsTab, [AppSidebarLeft.SLIDERITEMSIDS.editProfile]: editProfileTab, [AppSidebarLeft.SLIDERITEMSIDS.chatFolders]: chatFoldersTab, [AppSidebarLeft.SLIDERITEMSIDS.editFolder]: editFolderTab, [AppSidebarLeft.SLIDERITEMSIDS.includedChats]: includedChatsTab, }); //this._selectTab(0); // make first tab as default this.searchInput = new SearchInput('Telegram Search'); this.sidebarEl.querySelector('.item-main .sidebar-header').append(this.searchInput.container); this.toolsBtn = this.sidebarEl.querySelector('.sidebar-tools-button') as HTMLButtonElement; this.backBtn = this.sidebarEl.querySelector('.sidebar-back-button') as HTMLButtonElement; this.searchContainer = this.sidebarEl.querySelector('#search-container') as HTMLDivElement; this.archivedTab = archivedTab; this.newChannelTab = newChannelTab; this.addMembersTab = addMembersTab; this.contactsTab = contactsTab; this.newGroupTab = newGroupTab; this.settingsTab = settingsTab; this.editProfileTab = editProfileTab; this.chatFoldersTab = chatFoldersTab; this.editFolderTab = editFolderTab; this.includedChatsTab = includedChatsTab; this.menuEl = this.toolsBtn.querySelector('.btn-menu'); this.newBtnMenu = this.sidebarEl.querySelector('#new-menu'); this.searchInput.input.addEventListener('focus', () => { this.searchGroups = { //saved: new SearchGroup('', 'contacts'), contacts: new SearchGroup('Chats', 'contacts'), globalContacts: new SearchGroup('Global Search', 'contacts'), messages: new SearchGroup('Global Search', 'messages'), people: new SearchGroup('People', 'contacts', false, 'search-group-people'), recent: new SearchGroup('Recent', 'contacts', false, 'search-group-recent') }; this.globalSearch = new AppSearch(this.searchContainer, this.searchInput, this.searchGroups, (count) => { if(!count && !this.searchInput.value.trim()) { this.globalSearch.reset(); this.searchGroups.people.setActive(); this.renderRecentSearch(); } }); this.searchContainer.addEventListener('click', (e) => { const target = findUpTag(e.target, 'LI') as HTMLElement; if(!target) { return; } const searchGroup = findUpClassName(target, 'search-group'); if(!searchGroup || searchGroup.classList.contains('search-group-recent') || searchGroup.classList.contains('search-group-people')) { return; } const peerID = +target.getAttribute('data-peerID'); if(this.recentSearch[0] != peerID) { this.recentSearch.findAndSplice(p => p == peerID); this.recentSearch.unshift(peerID); if(this.recentSearch.length > 20) { this.recentSearch.length = 20; } this.renderRecentSearch(); appStateManager.pushToState('recentSearch', this.recentSearch); for(const peerID of this.recentSearch) { appStateManager.setPeer(peerID, appPeersManager.getPeer(peerID)); } clearRecentSearchBtn.style.display = ''; } }, {capture: true}); let peopleContainer = document.createElement('div'); peopleContainer.classList.add('search-group-scrollable'); peopleContainer.append(this.searchGroups.people.list); this.searchGroups.people.container.append(peopleContainer); let peopleScrollable = new ScrollableX(peopleContainer); appUsersManager.getTopPeers().then(peers => { //console.log('got top categories:', categories); peers.forEach((peerID) => { let {dialog, dom} = appDialogsManager.addDialog(peerID, this.searchGroups.people.list, false, true, true); this.searchGroups.people.setActive(); }); }); let hideNewBtnMenuTimeout: number; //const transition = Transition.bind(null, this.searchContainer.parentElement, 150); const transition = Transition(this.searchContainer.parentElement, 'zoom-fade', 150, (id) => { if(hideNewBtnMenuTimeout) clearTimeout(hideNewBtnMenuTimeout); if(id == 0) { this.globalSearch.reset(); hideNewBtnMenuTimeout = window.setTimeout(() => { hideNewBtnMenuTimeout = 0; this.newBtnMenu.classList.remove('is-hidden'); }, 150); } }); transition(0); const onFocus = () => { this.toolsBtn.classList.remove('active'); this.backBtn.classList.add('active'); this.newBtnMenu.classList.add('is-hidden'); transition(1); if(firstTime) { this.searchGroups.people.setActive(); this.renderRecentSearch(); firstTime = false; } /* this.searchInput.addEventListener('blur', (e) => { if(!this.searchInput.value) { this.toolsBtn.classList.add('active'); this.backBtn.classList.remove('active'); this.backBtn.click(); } }, {once: true}); */ }; let firstTime = true; this.searchInput.input.addEventListener('focus', onFocus); onFocus(); this.backBtn.addEventListener('click', (e) => { //appDialogsManager.chatsArchivedContainer.classList.remove('active'); this.toolsBtn.classList.add('active'); this.backBtn.classList.remove('active'); firstTime = true; transition(0); }); this.renderRecentSearch(); const clearRecentSearchBtn = this.recentSearchClearBtn = document.createElement('button'); clearRecentSearchBtn.classList.add('btn-icon', 'tgico-close'); this.searchGroups.recent.nameEl.append(clearRecentSearchBtn); clearRecentSearchBtn.addEventListener('click', () => { this.recentSearch = []; appStateManager.pushToState('recentSearch', this.recentSearch); this.renderRecentSearch(false); clearRecentSearchBtn.style.display = 'none'; }); }, {once: true}); parseMenuButtonsTo(this.buttons, this.menuEl.children); parseMenuButtonsTo(this.newButtons, this.newBtnMenu.firstElementChild.children); this.archivedCount = this.buttons.archived.querySelector('.archived-count') as HTMLSpanElement; this.buttons.saved.addEventListener('click', (e) => { ///////this.log('savedbtn click'); setTimeout(() => { // menu doesn't close if no timeout (lol) appImManager.setPeer(appImManager.myID); }, 0); }); this.buttons.archived.addEventListener('click', (e) => { this.selectTab(AppSidebarLeft.SLIDERITEMSIDS.archived); }); this.buttons.contacts.addEventListener('click', (e) => { this.contactsTab.openContacts(); }); this.buttons.settings.addEventListener('click', (e) => { this.settingsTab.fillElements(); this.selectTab(AppSidebarLeft.SLIDERITEMSIDS.settings); }); this.newButtons.channel.addEventListener('click', (e) => { this.selectTab(AppSidebarLeft.SLIDERITEMSIDS.newChannel); }); [this.newButtons.group, this.buttons.newGroup].forEach(btn => { btn.addEventListener('click', (e) => { this.addMembersTab.init(0, 'chat', false, (peerIDs) => { this.newGroupTab.init(peerIDs); }); }); }); $rootScope.$on('dialogs_archived_unread', (e) => { this.archivedCount.innerText = '' + formatNumber(e.detail.count, 1); this.archivedCount.classList.toggle('hide', !e.detail.count); }); appUsersManager.getTopPeers(); } public renderRecentSearch(setActive = true) { appStateManager.getState().then(state => { if(state && !this.recentSearchLoaded && Array.isArray(state.recentSearch)) { this.recentSearch = state.recentSearch; this.recentSearchLoaded = true; } if(this.searchInput.value.trim()) { return; } this.searchGroups.recent.list.innerHTML = ''; this.recentSearchClearBtn.style.display = this.recentSearch.length ? '' : 'none'; this.recentSearch.slice(0, 20).forEach(peerID => { let {dialog, dom} = appDialogsManager.addDialog(peerID, this.searchGroups.recent.list, false, true, false, true); dom.lastMessageSpan.innerText = peerID > 0 ? appUsersManager.getUserStatusString(peerID) : appChatsManager.getChatMembersString(peerID); }); if(setActive) { this.searchGroups.recent.setActive(); } }); } } const appSidebarLeft = new AppSidebarLeft(); MOUNT_CLASS_TO && (MOUNT_CLASS_TO.appSidebarLeft = appSidebarLeft); export default appSidebarLeft;