Telegram Web K with changes to work inside I2P
https://web.telegram.i2p/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
766 lines
25 KiB
766 lines
25 KiB
/* |
|
* https://github.com/morethanwords/tweb |
|
* Copyright (C) 2019-2021 Eduard Kuzmenko |
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE |
|
*/ |
|
|
|
import appImManager from '../../lib/appManagers/appImManager'; |
|
import rootScope from '../../lib/rootScope'; |
|
import {SearchGroup} from '../appSearch'; |
|
import '../avatar'; |
|
import Scrollable, {ScrollableX} from '../scrollable'; |
|
import InputSearch from '../inputSearch'; |
|
import SidebarSlider from '../slider'; |
|
import {TransitionSlider} from '../transition'; |
|
import AppNewGroupTab from './tabs/newGroup'; |
|
import AppSearchSuper from '../appSearchSuper.'; |
|
import {DateData, fillTipDates} from '../../helpers/date'; |
|
import {MOUNT_CLASS_TO} from '../../config/debug'; |
|
import AppSettingsTab from './tabs/settings'; |
|
import AppNewChannelTab from './tabs/newChannel'; |
|
import AppContactsTab from './tabs/contacts'; |
|
import AppArchivedTab from './tabs/archivedTab'; |
|
import AppAddMembersTab from './tabs/addMembers'; |
|
import I18n, {FormatterArguments, i18n, i18n_, LangPackKey} from '../../lib/langPack'; |
|
import AppPeopleNearbyTab from './tabs/peopleNearby'; |
|
import {ButtonMenuItemOptions} from '../buttonMenu'; |
|
import CheckboxField from '../checkboxField'; |
|
import {IS_MOBILE_SAFARI} from '../../environment/userAgent'; |
|
import appNavigationController, {NavigationItem} from '../appNavigationController'; |
|
import findUpClassName from '../../helpers/dom/findUpClassName'; |
|
import findUpTag from '../../helpers/dom/findUpTag'; |
|
import PeerTitle from '../peerTitle'; |
|
import App from '../../config/app'; |
|
import ButtonMenuToggle from '../buttonMenuToggle'; |
|
import replaceContent from '../../helpers/dom/replaceContent'; |
|
import sessionStorage from '../../lib/sessionStorage'; |
|
import {attachClickEvent, CLICK_EVENT_NAME, simulateClickEvent} from '../../helpers/dom/clickEvent'; |
|
import ButtonIcon from '../buttonIcon'; |
|
import confirmationPopup from '../confirmationPopup'; |
|
import IS_GEOLOCATION_SUPPORTED from '../../environment/geolocationSupport'; |
|
import type SortedUserList from '../sortedUserList'; |
|
import Button, {ButtonOptions} from '../button'; |
|
import noop from '../../helpers/noop'; |
|
import ripple from '../ripple'; |
|
import indexOfAndSplice from '../../helpers/array/indexOfAndSplice'; |
|
import formatNumber from '../../helpers/number/formatNumber'; |
|
import AvatarElement from '../avatar'; |
|
import {AppManagers} from '../../lib/appManagers/managers'; |
|
import themeController from '../../helpers/themeController'; |
|
import contextMenuController from '../../helpers/contextMenuController'; |
|
import {DIALOG_LIST_ELEMENT_TAG} from '../../lib/appManagers/appDialogsManager'; |
|
import apiManagerProxy from '../../lib/mtproto/mtprotoworker'; |
|
|
|
export const LEFT_COLUMN_ACTIVE_CLASSNAME = 'is-left-column-shown'; |
|
|
|
export class AppSidebarLeft extends SidebarSlider { |
|
private toolsBtn: HTMLElement; |
|
private backBtn: HTMLButtonElement; |
|
// private searchInput = document.getElementById('global-search') as HTMLInputElement; |
|
private inputSearch: InputSearch; |
|
|
|
public archivedCount: HTMLSpanElement; |
|
|
|
private newBtnMenu: HTMLElement; |
|
|
|
// private log = logger('SL'); |
|
|
|
private searchGroups: {[k in 'contacts' | 'globalContacts' | 'messages' | 'people' | 'recent']: SearchGroup} = {} as any; |
|
private searchSuper: AppSearchSuper; |
|
|
|
private updateBtn: HTMLElement; |
|
private hasUpdate: boolean; |
|
|
|
constructor() { |
|
super({ |
|
sidebarEl: document.getElementById('column-left') as HTMLDivElement, |
|
navigationType: 'left' |
|
}); |
|
} |
|
|
|
construct(managers: AppManagers) { |
|
this.managers = managers; |
|
// this._selectTab(0); // make first tab as default |
|
|
|
this.inputSearch = new InputSearch('Search'); |
|
const sidebarHeader = this.sidebarEl.querySelector('.item-main .sidebar-header'); |
|
sidebarHeader.append(this.inputSearch.container); |
|
|
|
const onNewGroupClick = () => { |
|
this.createTab(AppAddMembersTab).open({ |
|
type: 'chat', |
|
skippable: false, |
|
takeOut: (peerIds) => { |
|
this.createTab(AppNewGroupTab).open(peerIds); |
|
}, |
|
title: 'GroupAddMembers', |
|
placeholder: 'SendMessageTo' |
|
}); |
|
}; |
|
|
|
const onContactsClick = () => { |
|
this.createTab(AppContactsTab).open(); |
|
}; |
|
|
|
// this.toolsBtn = this.sidebarEl.querySelector('.sidebar-tools-button') as HTMLButtonElement; |
|
this.backBtn = this.sidebarEl.querySelector('.sidebar-back-button') as HTMLButtonElement; |
|
|
|
const btnArchive: typeof menuButtons[0] = { |
|
icon: 'archive', |
|
text: 'ArchivedChats', |
|
onClick: () => { |
|
this.createTab(AppArchivedTab).open(); |
|
}, |
|
verify: async() => { |
|
const folder = await this.managers.dialogsStorage.getFolderDialogs(1, false); |
|
return !!folder.length || !(await this.managers.dialogsStorage.isDialogsLoaded(1)); |
|
} |
|
}; |
|
|
|
const themeCheckboxField = new CheckboxField({ |
|
toggle: true, |
|
checked: themeController.getTheme().name === 'night' |
|
}); |
|
themeCheckboxField.input.addEventListener('change', async() => { |
|
await this.managers.appStateManager.setByKey('settings.theme', themeCheckboxField.input.checked ? 'night' : 'day'); |
|
rootScope.dispatchEvent('theme_change'); |
|
}); |
|
|
|
rootScope.addEventListener('theme_change', () => { |
|
themeCheckboxField.setValueSilently(themeController.getTheme().name === 'night'); |
|
}); |
|
|
|
const menuButtons: (ButtonMenuItemOptions & {verify?: () => boolean | Promise<boolean>})[] = [{ |
|
icon: 'saved', |
|
text: 'SavedMessages', |
|
onClick: () => { |
|
setTimeout(() => { // menu doesn't close if no timeout (lol) |
|
appImManager.setPeer({ |
|
peerId: appImManager.myId |
|
}); |
|
}, 0); |
|
} |
|
}, btnArchive, { |
|
icon: 'user', |
|
text: 'Contacts', |
|
onClick: onContactsClick |
|
}, IS_GEOLOCATION_SUPPORTED ? { |
|
icon: 'group', |
|
text: 'PeopleNearby', |
|
onClick: () => { |
|
this.createTab(AppPeopleNearbyTab).open(); |
|
} |
|
} : undefined, { |
|
icon: 'settings', |
|
text: 'Settings', |
|
onClick: () => { |
|
this.createTab(AppSettingsTab).open(); |
|
} |
|
}, { |
|
icon: 'darkmode', |
|
text: 'DarkMode', |
|
onClick: () => { |
|
|
|
}, |
|
checkboxField: themeCheckboxField |
|
}, { |
|
icon: 'animations', |
|
text: 'Animations', |
|
onClick: () => { |
|
|
|
}, |
|
checkboxField: new CheckboxField({ |
|
toggle: true, |
|
checked: true, |
|
stateKey: 'settings.animationsEnabled' |
|
}) |
|
}, { |
|
icon: 'help', |
|
text: 'TelegramFeatures', |
|
onClick: () => { |
|
const url = I18n.format('TelegramFeaturesUrl', true); |
|
appImManager.openUrl(url); |
|
} |
|
}, { |
|
icon: 'bug', |
|
text: 'ReportBug', |
|
onClick: () => { |
|
const a = document.createElement('a'); |
|
a.target = '_blank'; |
|
a.href = 'https://bugs.telegram.org/?tag_ids=40&sort=time'; |
|
document.body.append(a); |
|
a.click(); |
|
setTimeout(() => { |
|
a.remove(); |
|
}, 0); |
|
} |
|
}]; |
|
|
|
const filteredButtons = menuButtons.filter(Boolean); |
|
|
|
this.toolsBtn = ButtonMenuToggle({}, 'bottom-right', filteredButtons, async(e) => { |
|
await Promise.all(filteredButtons.map(async(button) => { |
|
if(button.verify) { |
|
button.element.classList.toggle('hide', !(await button.verify())); |
|
} |
|
})); |
|
}); |
|
this.toolsBtn.classList.remove('tgico-more'); |
|
this.toolsBtn.classList.add('sidebar-tools-button', 'is-visible'); |
|
|
|
this.backBtn.parentElement.insertBefore(this.toolsBtn, this.backBtn); |
|
|
|
const btnMenu = this.toolsBtn.querySelector('.btn-menu') as HTMLElement; |
|
|
|
const btnMenuFooter = document.createElement('a'); |
|
btnMenuFooter.href = 'https://github.com/morethanwords/tweb/blob/master/CHANGELOG.md'; |
|
btnMenuFooter.target = '_blank'; |
|
btnMenuFooter.rel = 'noopener noreferrer'; |
|
btnMenuFooter.classList.add('btn-menu-footer'); |
|
btnMenuFooter.addEventListener(CLICK_EVENT_NAME, (e) => { |
|
e.stopPropagation(); |
|
contextMenuController.close(); |
|
}); |
|
const t = document.createElement('span'); |
|
t.classList.add('btn-menu-footer-text'); |
|
t.innerHTML = 'Telegram Web' + App.suffix + ' '/* ' alpha ' */ + App.versionFull; |
|
btnMenuFooter.append(t); |
|
btnMenu.classList.add('has-footer'); |
|
btnMenu.append(btnMenuFooter); |
|
|
|
this.newBtnMenu = ButtonMenuToggle({}, 'top-left', [{ |
|
icon: 'newchannel', |
|
text: 'NewChannel', |
|
onClick: () => { |
|
this.createTab(AppNewChannelTab).open(); |
|
} |
|
}, { |
|
icon: 'newgroup', |
|
text: 'NewGroup', |
|
onClick: onNewGroupClick |
|
}, { |
|
icon: 'newprivate', |
|
text: 'NewPrivateChat', |
|
onClick: onContactsClick |
|
}]); |
|
this.newBtnMenu.className = 'btn-circle rp btn-corner z-depth-1 btn-menu-toggle animated-button-icon'; |
|
this.newBtnMenu.insertAdjacentHTML('afterbegin', ` |
|
<span class="tgico tgico-newchat_filled"></span> |
|
<span class="tgico tgico-close"></span> |
|
`); |
|
this.newBtnMenu.id = 'new-menu'; |
|
sidebarHeader.nextElementSibling.append(this.newBtnMenu); |
|
|
|
this.updateBtn = document.createElement('div'); |
|
// this.updateBtn.classList.add('btn-update'); |
|
this.updateBtn.className = 'btn-circle rp btn-corner z-depth-1 btn-update is-hidden'; |
|
ripple(this.updateBtn); |
|
this.updateBtn.append(i18n('Update')); |
|
// const weave = new TopbarWeave(); |
|
// const weaveContainer = weave.render('btn-update-weave'); |
|
// this.updateBtn.prepend(weaveContainer); |
|
|
|
attachClickEvent(this.updateBtn, () => { |
|
if(this.updateBtn.classList.contains('is-hidden')) { |
|
return; |
|
} |
|
|
|
location.reload(); |
|
}); |
|
|
|
sidebarHeader.nextElementSibling.append(this.updateBtn); |
|
|
|
// setTimeout(() => { |
|
// weave.componentDidMount(); |
|
// weave.setCurrentState(GROUP_CALL_STATE.MUTED, true); |
|
// weave.setAmplitude(0); |
|
// weave.handleBlur(); |
|
// }, 1e3); |
|
|
|
this.inputSearch.input.addEventListener('focus', () => this.initSearch(), {once: true}); |
|
|
|
// parseMenuButtonsTo(this.newButtons, this.newBtnMenu.firstElementChild.children); |
|
|
|
this.archivedCount = document.createElement('span'); |
|
this.archivedCount.className = 'archived-count badge badge-24 badge-gray'; |
|
|
|
btnArchive.element.append(this.archivedCount); |
|
|
|
rootScope.addEventListener('folder_unread', (folder) => { |
|
if(folder.id === 1) { |
|
// const count = folder.unreadMessagesCount; |
|
const count = folder.unreadPeerIds.size; |
|
this.archivedCount.innerText = '' + formatNumber(count, 1); |
|
this.archivedCount.classList.toggle('hide', !count); |
|
} |
|
}); |
|
|
|
this.managers.appUsersManager.getTopPeers('correspondents'); |
|
|
|
// Focus search input by pressing Escape |
|
const navigationItem: NavigationItem = { |
|
type: 'global-search-focus', |
|
onPop: () => { |
|
setTimeout(() => { |
|
this.inputSearch.input.focus(); |
|
}, 0); |
|
|
|
return false; |
|
}, |
|
noHistory: true |
|
}; |
|
appNavigationController.pushItem(navigationItem); |
|
|
|
apiManagerProxy.getState().then((state) => { |
|
const CHECK_UPDATE_INTERVAL = 1800e3; |
|
const checkUpdateInterval = setInterval(() => { |
|
fetch('version', {cache: 'no-cache'}) |
|
.then((res) => (res.status === 200 && res.ok && res.text()) || Promise.reject()) |
|
.then((text) => { |
|
if(text !== App.versionFull) { |
|
this.hasUpdate = true; |
|
clearInterval(checkUpdateInterval); |
|
|
|
if(!this.newBtnMenu.classList.contains('is-hidden')) { |
|
this.updateBtn.classList.remove('is-hidden'); |
|
} |
|
} |
|
}) |
|
.catch(noop); |
|
}, CHECK_UPDATE_INTERVAL); |
|
}); |
|
} |
|
|
|
private initSearch() { |
|
const searchContainer = this.sidebarEl.querySelector('#search-container') as HTMLDivElement; |
|
|
|
const scrollable = new Scrollable(searchContainer); |
|
|
|
const close = () => { |
|
// setTimeout(() => { |
|
simulateClickEvent(this.backBtn); |
|
// }, 0); |
|
}; |
|
|
|
this.searchGroups = { |
|
contacts: new SearchGroup('SearchAllChatsShort', 'contacts', undefined, undefined, undefined, undefined, close), |
|
globalContacts: new SearchGroup('GlobalSearch', 'contacts', undefined, undefined, undefined, undefined, close), |
|
messages: new SearchGroup('SearchMessages', 'messages'), |
|
people: new SearchGroup(false, 'contacts', true, 'search-group-people', true, false, close, true), |
|
recent: new SearchGroup('Recent', 'contacts', true, 'search-group-recent', true, true, close) |
|
}; |
|
|
|
const searchSuper = this.searchSuper = new AppSearchSuper({ |
|
mediaTabs: [{ |
|
inputFilter: 'inputMessagesFilterEmpty', |
|
name: 'FilterChats', |
|
type: 'chats' |
|
}, { |
|
inputFilter: 'inputMessagesFilterPhotoVideo', |
|
name: 'SharedMediaTab2', |
|
type: 'media' |
|
}, { |
|
inputFilter: 'inputMessagesFilterUrl', |
|
name: 'SharedLinksTab2', |
|
type: 'links' |
|
}, { |
|
inputFilter: 'inputMessagesFilterDocument', |
|
name: 'SharedFilesTab2', |
|
type: 'files' |
|
}, { |
|
inputFilter: 'inputMessagesFilterMusic', |
|
name: 'SharedMusicTab2', |
|
type: 'music' |
|
}, { |
|
inputFilter: 'inputMessagesFilterRoundVoice', |
|
name: 'SharedVoiceTab2', |
|
type: 'voice' |
|
}], |
|
scrollable, |
|
searchGroups: this.searchGroups, |
|
asChatList: true, |
|
hideEmptyTabs: false, |
|
showSender: true, |
|
managers: this.managers |
|
}); |
|
|
|
searchContainer.prepend(searchSuper.nav.parentElement.parentElement); |
|
scrollable.container.append(searchSuper.container); |
|
|
|
const resetSearch = () => { |
|
searchSuper.setQuery({ |
|
peerId: ''.toPeerId(), |
|
folderId: 0 |
|
}); |
|
searchSuper.selectTab(0); |
|
searchSuper.load(true); |
|
}; |
|
|
|
resetSearch(); |
|
|
|
const pickedElements: HTMLElement[] = []; |
|
let selectedPeerId: PeerId = ''.toPeerId(); |
|
let selectedMinDate = 0; |
|
let selectedMaxDate = 0; |
|
const updatePicked = () => { |
|
// (this.inputSearch.input as HTMLInputElement).placeholder = pickedElements.length ? 'Search' : 'Telegram Search'; |
|
this.inputSearch.container.classList.toggle('is-picked-twice', pickedElements.length === 2); |
|
this.inputSearch.container.classList.toggle('is-picked', !!pickedElements.length); |
|
|
|
if(pickedElements.length) { |
|
this.inputSearch.input.style.setProperty('--paddingLeft', (pickedElements[pickedElements.length - 1].getBoundingClientRect().right - this.inputSearch.input.getBoundingClientRect().left) + 'px'); |
|
} else { |
|
this.inputSearch.input.style.removeProperty('--paddingLeft'); |
|
} |
|
}; |
|
|
|
const helper = document.createElement('div'); |
|
helper.classList.add('search-helper'); |
|
helper.addEventListener('click', (e) => { |
|
const target = findUpClassName(e.target, 'selector-user'); |
|
if(!target) { |
|
return; |
|
} |
|
|
|
const key = target.dataset.key; |
|
if(key.indexOf('date_') === 0) { |
|
const [_, minDate, maxDate] = key.split('_'); |
|
selectedMinDate = +minDate; |
|
selectedMaxDate = +maxDate; |
|
} else { |
|
selectedPeerId = key.toPeerId(); |
|
} |
|
|
|
target.addEventListener('click', () => { |
|
unselectEntity(target); |
|
}); |
|
|
|
this.inputSearch.container.append(target); |
|
this.inputSearch.onChange(this.inputSearch.value = ''); |
|
pickedElements.push(target); |
|
updatePicked(); |
|
}); |
|
|
|
searchSuper.nav.parentElement.append(helper); |
|
|
|
const renderEntity = (key: PeerId | string, title?: string | HTMLElement) => { |
|
const div = document.createElement('div'); |
|
div.classList.add('selector-user'/* , 'scale-in' */); |
|
|
|
const avatarEl = new AvatarElement(); |
|
avatarEl.classList.add('selector-user-avatar', 'tgico', 'avatar-30'); |
|
avatarEl.isDialog = true; |
|
|
|
div.dataset.key = '' + key; |
|
if(key.isPeerId()) { |
|
if(title === undefined) { |
|
title = new PeerTitle({peerId: key.toPeerId()}).element; |
|
} |
|
|
|
avatarEl.updateWithOptions({peerId: key as PeerId}); |
|
} else { |
|
avatarEl.classList.add('tgico-calendarfilter'); |
|
} |
|
|
|
if(title) { |
|
if(typeof(title) === 'string') { |
|
div.innerHTML = title; |
|
} else { |
|
replaceContent(div, title); |
|
div.append(title); |
|
} |
|
} |
|
|
|
div.insertAdjacentElement('afterbegin', avatarEl); |
|
|
|
return div; |
|
}; |
|
|
|
const unselectEntity = (target: HTMLElement) => { |
|
const key = target.dataset.key; |
|
if(key.indexOf('date_') === 0) { |
|
selectedMinDate = selectedMaxDate = 0; |
|
} else { |
|
selectedPeerId = ''.toPeerId(); |
|
} |
|
|
|
target.remove(); |
|
indexOfAndSplice(pickedElements, target); |
|
|
|
setTimeout(() => { |
|
updatePicked(); |
|
this.inputSearch.onChange(this.inputSearch.value); |
|
}, 0); |
|
}; |
|
|
|
this.inputSearch.onClear = () => { |
|
pickedElements.forEach((el) => { |
|
unselectEntity(el); |
|
}); |
|
}; |
|
|
|
this.inputSearch.onChange = (value) => { |
|
searchSuper.cleanupHTML(); |
|
searchSuper.setQuery({ |
|
peerId: selectedPeerId, |
|
folderId: selectedPeerId ? undefined : 0, |
|
query: value, |
|
minDate: selectedMinDate, |
|
maxDate: selectedMaxDate |
|
}); |
|
searchSuper.load(true); |
|
|
|
helper.innerHTML = ''; |
|
searchSuper.nav.classList.remove('hide'); |
|
if(!value) { |
|
} |
|
|
|
if(!selectedPeerId && value.trim()) { |
|
const middleware = searchSuper.middleware.get(); |
|
Promise.all([ |
|
// appMessagesManager.getConversationsAll(value).then((dialogs) => dialogs.map((d) => d.peerId)), |
|
this.managers.appMessagesManager.getConversations(value).then(({dialogs}) => dialogs.map((d) => d.peerId)), |
|
this.managers.appUsersManager.getContactsPeerIds(value, true) |
|
]).then((results) => { |
|
if(!middleware()) return; |
|
const peerIds = new Set(results[0].concat(results[1])); |
|
|
|
peerIds.forEach((peerId) => { |
|
helper.append(renderEntity(peerId)); |
|
}); |
|
|
|
searchSuper.nav.classList.toggle('hide', !!helper.innerHTML); |
|
// console.log('got peerIds by value:', value, [...peerIds]); |
|
}); |
|
} |
|
|
|
if(!selectedMinDate && value.trim()) { |
|
const dates: DateData[] = []; |
|
fillTipDates(value, dates); |
|
dates.forEach((dateData) => { |
|
helper.append(renderEntity('date_' + dateData.minDate + '_' + dateData.maxDate, dateData.title)); |
|
}); |
|
|
|
searchSuper.nav.classList.toggle('hide', !!helper.innerHTML); |
|
} |
|
}; |
|
|
|
searchSuper.tabs.inputMessagesFilterEmpty.addEventListener('mousedown', (e) => { |
|
const target = findUpTag(e.target, DIALOG_LIST_ELEMENT_TAG) 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-peer-id').toPeerId(); |
|
this.managers.appUsersManager.pushRecentSearch(peerId); |
|
}, {capture: true}); |
|
|
|
const peopleContainer = document.createElement('div'); |
|
peopleContainer.classList.add('search-group-scrollable'); |
|
peopleContainer.append(this.searchGroups.people.list); |
|
this.searchGroups.people.container.append(peopleContainer); |
|
const peopleScrollable = new ScrollableX(peopleContainer); |
|
|
|
let first = true; |
|
let hideNewBtnMenuTimeout: number; |
|
// const transition = Transition.bind(null, searchContainer.parentElement, 150); |
|
const transition = TransitionSlider(searchContainer.parentElement, 'zoom-fade', 150, (id) => { |
|
if(hideNewBtnMenuTimeout) clearTimeout(hideNewBtnMenuTimeout); |
|
|
|
if(id === 0 && !first) { |
|
searchSuper.selectTab(0, false); |
|
this.inputSearch.onClearClick(); |
|
hideNewBtnMenuTimeout = window.setTimeout(() => { |
|
hideNewBtnMenuTimeout = 0; |
|
this.newBtnMenu.classList.remove('is-hidden'); |
|
this.hasUpdate && this.updateBtn.classList.remove('is-hidden'); |
|
}, 150); |
|
} |
|
|
|
first = false; |
|
}); |
|
|
|
transition(0); |
|
|
|
const activeClassName = 'is-visible'; |
|
const onFocus = () => { |
|
this.toolsBtn.classList.remove(activeClassName); |
|
this.backBtn.classList.add(activeClassName); |
|
this.newBtnMenu.classList.add('is-hidden'); |
|
this.updateBtn.classList.add('is-hidden'); |
|
this.toolsBtn.parentElement.firstElementChild.classList.toggle('state-back', true); |
|
|
|
const navigationType: NavigationItem['type'] = 'global-search'; |
|
if(!IS_MOBILE_SAFARI && !appNavigationController.findItemByType(navigationType)) { |
|
appNavigationController.pushItem({ |
|
onPop: () => { |
|
close(); |
|
}, |
|
type: navigationType |
|
}); |
|
} |
|
|
|
transition(1); |
|
}; |
|
|
|
this.inputSearch.input.addEventListener('focus', onFocus); |
|
onFocus(); |
|
|
|
attachClickEvent(this.backBtn, (e) => { |
|
this.toolsBtn.classList.add(activeClassName); |
|
this.backBtn.classList.remove(activeClassName); |
|
this.toolsBtn.parentElement.firstElementChild.classList.toggle('state-back', false); |
|
|
|
appNavigationController.removeByType('global-search'); |
|
|
|
transition(0); |
|
}); |
|
|
|
const clearRecentSearchBtn = ButtonIcon('close'); |
|
this.searchGroups.recent.nameEl.append(clearRecentSearchBtn); |
|
clearRecentSearchBtn.addEventListener('click', () => { |
|
confirmationPopup({ |
|
descriptionLangKey: 'Search.Confirm.ClearHistory', |
|
button: { |
|
langKey: 'ClearButton', |
|
isDanger: true |
|
} |
|
}).then(() => { |
|
return this.managers.appUsersManager.clearRecentSearch().then(() => { |
|
this.searchGroups.recent.clear(); |
|
}); |
|
}); |
|
}); |
|
} |
|
} |
|
|
|
export type SettingSectionOptions = { |
|
name?: LangPackKey, |
|
nameArgs?: FormatterArguments, |
|
caption?: LangPackKey | true, |
|
captionArgs?: FormatterArguments, |
|
captionOld?: SettingSectionOptions['caption'], |
|
noDelimiter?: boolean, |
|
fakeGradientDelimiter?: boolean, |
|
noShadow?: boolean, |
|
// fullWidth?: boolean, |
|
// noPaddingTop?: boolean |
|
}; |
|
|
|
const className = 'sidebar-left-section'; |
|
export class SettingSection { |
|
public container: HTMLElement; |
|
public innerContainer: HTMLElement; |
|
public content: HTMLElement; |
|
public title: HTMLElement; |
|
public caption: HTMLElement; |
|
|
|
private fullWidth: boolean; |
|
|
|
constructor(options: SettingSectionOptions = {}) { |
|
const container = this.container = document.createElement('div'); |
|
container.classList.add(className + '-container'); |
|
|
|
const innerContainer = this.innerContainer = document.createElement('div'); |
|
innerContainer.classList.add(className); |
|
|
|
if(options.noShadow) { |
|
innerContainer.classList.add('no-shadow'); |
|
} |
|
|
|
if(options.fakeGradientDelimiter) { |
|
innerContainer.append(generateDelimiter()); |
|
innerContainer.classList.add('with-fake-delimiter'); |
|
} else if(!options.noDelimiter) { |
|
const hr = document.createElement('hr'); |
|
innerContainer.append(hr); |
|
} else { |
|
innerContainer.classList.add('no-delimiter'); |
|
} |
|
|
|
// if(options.fullWidth) { |
|
// this.fullWidth = true; |
|
// } |
|
|
|
// if(options.noPaddingTop) { |
|
// innerContainer.classList.add('no-padding-top'); |
|
// } |
|
|
|
const content = this.content = this.generateContentElement(); |
|
|
|
if(options.name) { |
|
const title = this.title = document.createElement('div'); |
|
title.classList.add('sidebar-left-h2', className + '-name'); |
|
i18n_({element: title, key: options.name, args: options.nameArgs}); |
|
content.append(title); |
|
} |
|
|
|
container.append(innerContainer); |
|
|
|
const caption = options.caption ?? options.captionOld; |
|
if(caption) { |
|
const el = this.caption = this.generateContentElement(); |
|
el.classList.add(className + '-caption'); |
|
|
|
if(!options.captionOld) { |
|
container.append(el); |
|
} |
|
|
|
if(caption !== true) { |
|
i18n_({element: el, key: caption, args: options.captionArgs}); |
|
} |
|
} |
|
} |
|
|
|
public generateContentElement() { |
|
const content = document.createElement('div'); |
|
content.classList.add(className + '-content'); |
|
|
|
// if(this.fullWidth) { |
|
// content.classList.add('full-width'); |
|
// } |
|
|
|
this.innerContainer.append(content); |
|
return content; |
|
} |
|
} |
|
|
|
export const generateSection = (appendTo: Scrollable, name?: LangPackKey, caption?: LangPackKey) => { |
|
const section = new SettingSection({name, caption}); |
|
appendTo.append(section.container); |
|
return section.content; |
|
}; |
|
|
|
export const generateDelimiter = () => { |
|
const delimiter = document.createElement('div'); |
|
delimiter.classList.add('gradient-delimiter'); |
|
return delimiter; |
|
}; |
|
|
|
export class SettingChatListSection extends SettingSection { |
|
public sortedList: SortedUserList; |
|
|
|
constructor(options: SettingSectionOptions & {sortedList: SortedUserList}) { |
|
super(options); |
|
|
|
this.sortedList = options.sortedList; |
|
|
|
this.content.append(this.sortedList.list); |
|
} |
|
|
|
public makeButton(options: ButtonOptions) { |
|
const button = Button('folder-category-button btn btn-primary btn-transparent', options); |
|
if(this.title) this.content.insertBefore(button, this.title.nextSibling); |
|
else this.content.prepend(button); |
|
return button; |
|
} |
|
} |
|
|
|
const appSidebarLeft = new AppSidebarLeft(); |
|
MOUNT_CLASS_TO.appSidebarLeft = appSidebarLeft; |
|
export default appSidebarLeft;
|
|
|