2020-04-24 03:48:48 +03:00
|
|
|
//import { logger } from "../polyfill";
|
2020-02-06 22:43:07 +07:00
|
|
|
import appDialogsManager from "./appDialogsManager";
|
2020-04-24 03:48:48 +03:00
|
|
|
import { $rootScope } from "../utils";
|
2020-02-08 13:03:09 +07:00
|
|
|
import appImManager from "./appImManager";
|
2020-04-26 15:19:17 +03:00
|
|
|
//import apiManager from '../mtproto/apiManager';
|
|
|
|
import apiManager from '../mtproto/mtprotoworker';
|
2020-04-24 03:48:48 +03:00
|
|
|
import AppSearch, { SearchGroup } from "../../components/appSearch";
|
2020-05-09 15:02:07 +03:00
|
|
|
import { horizontalMenu, putPreloader } from "../../components/misc";
|
2020-05-06 04:03:31 +03:00
|
|
|
import appUsersManager from "./appUsersManager";
|
|
|
|
import Scrollable from "../../components/scrollable_new";
|
|
|
|
import appPhotosManager from "./appPhotosManager";
|
|
|
|
import { appPeersManager } from "../services";
|
2020-05-09 15:02:07 +03:00
|
|
|
import popupAvatar from "../../components/popupAvatar";
|
|
|
|
import appChatsManager from "./appChatsManager";
|
|
|
|
import { AppSelectPeers } from "../../components/appSelectPeers";
|
2020-05-13 18:26:40 +03:00
|
|
|
import AvatarElement from "../../components/avatar";
|
|
|
|
import appProfileManager from "./appProfileManager";
|
|
|
|
|
|
|
|
AvatarElement;
|
2020-05-06 04:03:31 +03:00
|
|
|
|
|
|
|
const SLIDERITEMSIDS = {
|
|
|
|
archived: 1,
|
2020-05-09 15:02:07 +03:00
|
|
|
contacts: 2,
|
|
|
|
newChannel: 3,
|
|
|
|
addMembers: 4,
|
|
|
|
newGroup: 5,
|
2020-05-13 18:26:40 +03:00
|
|
|
settings: 6,
|
|
|
|
editProfile: 7,
|
2020-05-06 04:03:31 +03:00
|
|
|
};
|
2020-02-06 22:43:07 +07:00
|
|
|
|
2020-05-09 15:02:07 +03:00
|
|
|
interface SliderTab {
|
|
|
|
onClose?: () => void,
|
|
|
|
onCloseAfterTimeout?: () => void
|
|
|
|
}
|
|
|
|
|
|
|
|
class AppAddMembersTab implements SliderTab {
|
|
|
|
private container = document.querySelector('.addmembers-container') as HTMLDivElement;
|
|
|
|
private contentDiv = this.container.querySelector('.sidebar-content') as HTMLDivElement;
|
|
|
|
private backBtn = this.container.querySelector('.sidebar-close-button') as HTMLButtonElement;
|
|
|
|
private nextBtn = this.contentDiv.querySelector('.btn-corner') as HTMLButtonElement;
|
|
|
|
private selector: AppSelectPeers;
|
|
|
|
private peerType: 'channel' | 'chat';
|
|
|
|
private peerID: number; // always positive
|
|
|
|
private takeOut: (peerIDs: number[]) => void
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
this.nextBtn.addEventListener('click', () => {
|
|
|
|
let peerIDs = this.selector.getSelected();
|
|
|
|
|
|
|
|
if(peerIDs.length) {
|
|
|
|
if(this.takeOut) {
|
|
|
|
this.takeOut(peerIDs);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.nextBtn.classList.remove('tgico-next');
|
|
|
|
this.nextBtn.disabled = true;
|
|
|
|
putPreloader(this.nextBtn);
|
|
|
|
this.selector.freezed = true;
|
|
|
|
|
|
|
|
appChatsManager.inviteToChannel(this.peerID, peerIDs).then(() => {
|
|
|
|
this.backBtn.click();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public onCloseAfterTimeout() {
|
|
|
|
if(this.selector) {
|
|
|
|
this.selector.container.remove();
|
|
|
|
this.selector = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public init(id: number, type: 'channel' | 'chat', skipable: boolean, takeOut?: AppAddMembersTab['takeOut']) {
|
|
|
|
this.peerID = Math.abs(id);
|
|
|
|
this.peerType = type;
|
|
|
|
this.takeOut = takeOut;
|
|
|
|
|
|
|
|
this.onCloseAfterTimeout();
|
|
|
|
this.selector = new AppSelectPeers(this.contentDiv, skipable ? null : (length) => {
|
|
|
|
if(length) {
|
|
|
|
this.nextBtn.classList.add('is-visible');
|
|
|
|
} else {
|
|
|
|
this.nextBtn.classList.remove('is-visible');
|
|
|
|
}
|
|
|
|
}, 'contacts');
|
|
|
|
|
|
|
|
this.nextBtn.innerHTML = '';
|
|
|
|
this.nextBtn.disabled = false;
|
|
|
|
this.nextBtn.classList.add('tgico-next');
|
|
|
|
if(skipable) {
|
|
|
|
this.nextBtn.classList.add('is-visible');
|
|
|
|
} else {
|
|
|
|
this.nextBtn.classList.remove('is-visible');
|
|
|
|
}
|
|
|
|
|
|
|
|
appSidebarLeft.selectTab(SLIDERITEMSIDS.addMembers);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class AppNewChannelTab implements SliderTab {
|
|
|
|
private container = document.querySelector('.new-channel-container') as HTMLDivElement;
|
|
|
|
private canvas = this.container.querySelector('.avatar-edit-canvas') as HTMLCanvasElement;
|
|
|
|
private channelNameInput = this.container.querySelector('.new-channel-name') as HTMLInputElement;
|
|
|
|
private channelDescriptionInput = this.container.querySelector('.new-channel-description') as HTMLInputElement;
|
|
|
|
private nextBtn = this.container.querySelector('.btn-corner') as HTMLButtonElement;
|
|
|
|
private backBtn = this.container.querySelector('.sidebar-close-button') as HTMLButtonElement;
|
|
|
|
private uploadAvatar: () => Promise<any> = null;
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
this.container.querySelector('.avatar-edit').addEventListener('click', () => {
|
|
|
|
popupAvatar.open(this.canvas, (_upload) => {
|
|
|
|
this.uploadAvatar = _upload;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
this.channelNameInput.addEventListener('input', () => {
|
|
|
|
let value = this.channelNameInput.value;
|
|
|
|
if(value.length) {
|
|
|
|
this.nextBtn.classList.add('is-visible');
|
|
|
|
} else {
|
|
|
|
this.nextBtn.classList.remove('is-visible');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
this.nextBtn.addEventListener('click', () => {
|
|
|
|
let title = this.channelNameInput.value;
|
|
|
|
let about = this.channelDescriptionInput.value;
|
|
|
|
|
|
|
|
this.nextBtn.disabled = true;
|
|
|
|
appChatsManager.createChannel(title, about).then((channelID) => {
|
|
|
|
if(this.uploadAvatar) {
|
|
|
|
this.uploadAvatar().then((inputFile: any) => {
|
|
|
|
appChatsManager.editPhoto(channelID, inputFile);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
appSidebarLeft.removeTabFromHistory(SLIDERITEMSIDS.newChannel);
|
|
|
|
appSidebarLeft.addMembersTab.init(channelID, 'channel', true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public onCloseAfterTimeout() {
|
|
|
|
let ctx = this.canvas.getContext('2d');
|
|
|
|
ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
|
|
|
|
|
|
this.uploadAvatar = null;
|
|
|
|
this.channelNameInput.value = '';
|
|
|
|
this.channelDescriptionInput.value = '';
|
|
|
|
this.nextBtn.disabled = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class AppNewGroupTab implements SliderTab {
|
|
|
|
private container = document.querySelector('.new-group-container') as HTMLDivElement;
|
|
|
|
private contentDiv = this.container.querySelector('.sidebar-content') as HTMLDivElement;
|
|
|
|
private canvas = this.container.querySelector('.avatar-edit-canvas') as HTMLCanvasElement;
|
|
|
|
private groupNameInput = this.container.querySelector('.new-group-name') as HTMLInputElement;
|
|
|
|
private nextBtn = this.container.querySelector('.btn-corner') as HTMLButtonElement;
|
|
|
|
private searchGroup = new SearchGroup('', 'contacts', true, 'new-group-members disable-hover', false);
|
|
|
|
private uploadAvatar: () => Promise<any> = null;
|
|
|
|
private userIDs: number[];
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
this.container.querySelector('.avatar-edit').addEventListener('click', () => {
|
|
|
|
popupAvatar.open(this.canvas, (_upload) => {
|
|
|
|
this.uploadAvatar = _upload;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
this.groupNameInput.addEventListener('input', () => {
|
|
|
|
let value = this.groupNameInput.value;
|
|
|
|
if(value.length) {
|
|
|
|
this.nextBtn.classList.add('is-visible');
|
|
|
|
} else {
|
|
|
|
this.nextBtn.classList.remove('is-visible');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
this.nextBtn.addEventListener('click', () => {
|
|
|
|
let title = this.groupNameInput.value;
|
|
|
|
|
|
|
|
this.nextBtn.disabled = true;
|
|
|
|
appChatsManager.createChat(title, this.userIDs).then((chatID) => {
|
|
|
|
if(this.uploadAvatar) {
|
|
|
|
this.uploadAvatar().then((inputFile: any) => {
|
|
|
|
appChatsManager.editPhoto(chatID, inputFile);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
appSidebarLeft.selectTab(0);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
let chatsContainer = document.createElement('div');
|
|
|
|
chatsContainer.classList.add('chats-container');
|
|
|
|
chatsContainer.append(this.searchGroup.container);
|
|
|
|
|
|
|
|
let scrollable = new Scrollable(chatsContainer);
|
|
|
|
|
|
|
|
this.contentDiv.append(chatsContainer);
|
|
|
|
}
|
|
|
|
|
|
|
|
public onClose() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public onCloseAfterTimeout() {
|
|
|
|
this.searchGroup.clear();
|
|
|
|
|
|
|
|
let ctx = this.canvas.getContext('2d');
|
|
|
|
ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
|
|
|
|
|
|
this.uploadAvatar = null;
|
|
|
|
this.groupNameInput.value = '';
|
|
|
|
this.nextBtn.disabled = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public init(userIDs: number[]) {
|
|
|
|
this.userIDs = userIDs;
|
|
|
|
|
|
|
|
appSidebarLeft.selectTab(SLIDERITEMSIDS.newGroup);
|
|
|
|
this.userIDs.forEach(userID => {
|
|
|
|
let {dom} = appDialogsManager.addDialog(userID, this.searchGroup.list, false, false);
|
|
|
|
|
|
|
|
let subtitle = '';
|
|
|
|
subtitle = appUsersManager.getUserStatusString(userID);
|
|
|
|
if(subtitle == 'online') {
|
|
|
|
subtitle = `<i>${subtitle}</i>`;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(subtitle) {
|
|
|
|
dom.lastMessageSpan.innerHTML = subtitle;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
this.searchGroup.nameEl.innerText = this.userIDs.length + ' members';
|
|
|
|
this.searchGroup.setActive();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class AppContactsTab implements SliderTab {
|
|
|
|
private container = document.getElementById('contacts-container');
|
|
|
|
private list = this.container.querySelector('#contacts') as HTMLUListElement;
|
|
|
|
private scrollable: Scrollable;
|
|
|
|
private promise: Promise<void>;
|
|
|
|
private input = this.container.querySelector('#contacts-search') as HTMLInputElement;
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
appDialogsManager.setListClickListener(this.list);
|
|
|
|
this.scrollable = new Scrollable(this.list.parentElement);
|
|
|
|
|
|
|
|
let prevValue = '';
|
|
|
|
this.input.addEventListener('input', () => {
|
|
|
|
let value = this.input.value;
|
|
|
|
if(prevValue != value) {
|
|
|
|
this.list.innerHTML = '';
|
|
|
|
this.openContacts(prevValue = value);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// preload contacts
|
|
|
|
appUsersManager.getContacts();
|
|
|
|
}
|
|
|
|
|
|
|
|
// need to clear, and left 1 page for smooth slide
|
|
|
|
public onClose() {
|
|
|
|
let pageCount = appPhotosManager.windowH / 72 * 1.25 | 0;
|
|
|
|
(Array.from(this.list.children) as HTMLElement[]).slice(pageCount).forEach(el => el.remove());
|
|
|
|
}
|
|
|
|
|
|
|
|
public onCloseAfterTimeout() {
|
|
|
|
this.list.innerHTML = '';
|
|
|
|
}
|
|
|
|
|
|
|
|
public openContacts(query?: string) {
|
|
|
|
appSidebarLeft.selectTab(SLIDERITEMSIDS.contacts);
|
|
|
|
if(this.promise) return this.promise;
|
|
|
|
this.scrollable.onScrolledBottom = null;
|
|
|
|
|
|
|
|
this.promise = appUsersManager.getContacts(query).then(contacts => {
|
|
|
|
this.promise = null;
|
|
|
|
|
|
|
|
if(appSidebarLeft.historyTabIDs[appSidebarLeft.historyTabIDs.length - 1] != SLIDERITEMSIDS.contacts) {
|
|
|
|
console.warn('user closed contacts before it\'s loaded');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let sorted = contacts
|
|
|
|
.map(userID => {
|
|
|
|
let user = appUsersManager.getUser(userID);
|
|
|
|
let status = appUsersManager.getUserStatusForSort(user.status);
|
|
|
|
|
|
|
|
return {user, status};
|
|
|
|
})
|
|
|
|
.sort((a, b) => b.status - a.status);
|
|
|
|
|
|
|
|
let renderPage = () => {
|
|
|
|
let pageCount = appPhotosManager.windowH / 72 * 1.25 | 0;
|
|
|
|
let arr = sorted.splice(0, pageCount); // надо splice!
|
|
|
|
|
|
|
|
arr.forEach(({user}) => {
|
|
|
|
let {dialog, dom} = appDialogsManager.addDialog(user.id, this.list, false);
|
|
|
|
|
|
|
|
let status = appUsersManager.getUserStatusString(user.id);
|
|
|
|
dom.lastMessageSpan.innerHTML = status == 'online' ? `<i>${status}</i>` : status;
|
|
|
|
});
|
|
|
|
|
|
|
|
if(!sorted.length) renderPage = undefined;
|
|
|
|
};
|
|
|
|
|
|
|
|
renderPage();
|
|
|
|
this.scrollable.onScrolledBottom = () => {
|
|
|
|
if(renderPage) {
|
|
|
|
renderPage();
|
|
|
|
} else {
|
|
|
|
this.scrollable.onScrolledBottom = null;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-13 18:26:40 +03:00
|
|
|
class AppSettingsTab implements SliderTab {
|
|
|
|
private container = document.querySelector('.settings-container') as HTMLDivElement;
|
|
|
|
private avatarElem = this.container.querySelector('.profile-avatar') as AvatarElement;
|
|
|
|
private nameDiv = this.container.querySelector('.profile-name') as HTMLDivElement;
|
|
|
|
private phoneDiv = this.container.querySelector('.profile-subtitle') as HTMLDivElement;
|
|
|
|
|
|
|
|
private logOutBtn = this.container.querySelector('.menu-logout') as HTMLButtonElement;
|
|
|
|
|
|
|
|
private buttons: {
|
|
|
|
edit: HTMLButtonElement,
|
|
|
|
general: HTMLButtonElement,
|
|
|
|
notifications: HTMLButtonElement,
|
|
|
|
privacy: HTMLButtonElement,
|
|
|
|
language: HTMLButtonElement
|
|
|
|
} = {} as any;
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
(Array.from(this.container.querySelector('.profile-buttons').children) as HTMLButtonElement[]).forEach(el => {
|
|
|
|
let name = el.className.match(/ menu-(.+?) /)[1];
|
|
|
|
// @ts-ignore
|
|
|
|
this.buttons[name] = el;
|
|
|
|
});
|
|
|
|
|
|
|
|
$rootScope.$on('user_auth', (e: CustomEvent) => {
|
|
|
|
this.fillElements();
|
|
|
|
});
|
|
|
|
|
|
|
|
this.logOutBtn.addEventListener('click', (e) => {
|
|
|
|
apiManager.logOut();
|
|
|
|
});
|
|
|
|
|
|
|
|
this.buttons.edit.addEventListener('click', () => {
|
|
|
|
appSidebarLeft.selectTab(SLIDERITEMSIDS.editProfile);
|
|
|
|
appSidebarLeft.editProfileTab.fillElements();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public fillElements() {
|
|
|
|
let user = appUsersManager.getSelf();
|
|
|
|
this.avatarElem.setAttribute('peer', '' + user.id);
|
|
|
|
|
|
|
|
this.nameDiv.innerHTML = user.rFullName || '';
|
|
|
|
this.phoneDiv.innerHTML = user.rPhone || '';
|
|
|
|
}
|
|
|
|
|
|
|
|
onClose() {
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class AppEditProfileTab implements SliderTab {
|
|
|
|
private container = document.querySelector('.edit-profile-container') as HTMLDivElement;
|
|
|
|
private scrollWrapper = this.container.querySelector('.scroll-wrapper') as HTMLDivElement;
|
|
|
|
private nextBtn = this.container.querySelector('.btn-corner') as HTMLButtonElement;
|
|
|
|
private canvas = this.container.querySelector('.avatar-edit-canvas') as HTMLCanvasElement;
|
|
|
|
private uploadAvatar: () => Promise<any> = null;
|
|
|
|
|
|
|
|
private firstNameInput = this.container.querySelector('.firstname') as HTMLInputElement;
|
|
|
|
private lastNameInput = this.container.querySelector('.lastname') as HTMLInputElement;
|
|
|
|
private bioInput = this.container.querySelector('.bio') as HTMLInputElement;
|
|
|
|
private userNameInput = this.container.querySelector('.username') as HTMLInputElement;
|
|
|
|
|
|
|
|
private avatarElem = document.createElement('avatar-element');
|
|
|
|
|
|
|
|
private originalValues = {
|
|
|
|
firstName: '',
|
|
|
|
lastName: '',
|
|
|
|
userName: '',
|
|
|
|
bio: ''
|
|
|
|
};
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
this.container.querySelector('.avatar-edit').addEventListener('click', () => {
|
|
|
|
popupAvatar.open(this.canvas, (_upload) => {
|
|
|
|
this.uploadAvatar = _upload;
|
|
|
|
this.handleChange();
|
|
|
|
this.avatarElem.remove();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
this.avatarElem.classList.add('avatar-placeholder');
|
|
|
|
|
|
|
|
let userNameLabel = this.userNameInput.nextElementSibling as HTMLLabelElement;
|
|
|
|
|
|
|
|
this.firstNameInput.addEventListener('input', () => this.handleChange());
|
|
|
|
this.lastNameInput.addEventListener('input', () => this.handleChange());
|
|
|
|
this.bioInput.addEventListener('input', () => this.handleChange());
|
|
|
|
this.userNameInput.addEventListener('input', () => {
|
|
|
|
this.handleChange();
|
|
|
|
let value = this.userNameInput.value;
|
|
|
|
|
|
|
|
console.log('userNameInput:', value);
|
|
|
|
if(value == this.originalValues.userName) {
|
|
|
|
this.userNameInput.classList.remove('valid', 'error');
|
|
|
|
userNameLabel.innerText = 'Username (optional)';
|
|
|
|
return;
|
|
|
|
} else if(value.length < 5 || value.length > 32 || !/^[a-zA-Z0-9_]+$/.test(value)) { // does not check the last underscore
|
|
|
|
this.userNameInput.classList.add('error');
|
|
|
|
this.userNameInput.classList.remove('valid');
|
|
|
|
userNameLabel.innerText = 'Username is invalid';
|
|
|
|
} else {
|
|
|
|
this.userNameInput.classList.remove('error');
|
|
|
|
/* */
|
|
|
|
}
|
|
|
|
|
|
|
|
apiManager.invokeApi('account.checkUsername', {
|
|
|
|
username: value
|
|
|
|
}).then(available => {
|
|
|
|
if(this.userNameInput.value != value) return;
|
|
|
|
|
|
|
|
if(available) {
|
|
|
|
this.userNameInput.classList.add('valid');
|
|
|
|
this.userNameInput.classList.remove('error');
|
|
|
|
userNameLabel.innerText = 'Username is available';
|
|
|
|
} else {
|
|
|
|
this.userNameInput.classList.add('error');
|
|
|
|
this.userNameInput.classList.remove('valid');
|
|
|
|
userNameLabel.innerText = 'Username is already taken';
|
|
|
|
}
|
|
|
|
}, (err) => {
|
|
|
|
if(this.userNameInput.value != value) return;
|
|
|
|
|
|
|
|
switch(err.type) {
|
|
|
|
case 'USERNAME_INVALID': {
|
|
|
|
this.userNameInput.classList.add('error');
|
|
|
|
this.userNameInput.classList.remove('valid');
|
|
|
|
userNameLabel.innerText = 'Username is invalid';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
this.nextBtn.addEventListener('click', () => {
|
|
|
|
this.nextBtn.disabled = true;
|
|
|
|
|
|
|
|
let promises: Promise<any>[] = [];
|
|
|
|
|
|
|
|
|
|
|
|
promises.push(appProfileManager.updateProfile(this.firstNameInput.value, this.lastNameInput.value, this.bioInput.value).then(() => {
|
|
|
|
appSidebarLeft.selectTab(0);
|
|
|
|
}, (err) => {
|
|
|
|
console.error('updateProfile error:', err);
|
|
|
|
}));
|
|
|
|
|
|
|
|
if(this.uploadAvatar) {
|
|
|
|
promises.push(this.uploadAvatar().then(inputFile => {
|
|
|
|
appProfileManager.uploadProfilePhoto(inputFile);
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
if(this.userNameInput.value != this.originalValues.userName && this.userNameInput.classList.contains('valid')) {
|
|
|
|
promises.push(appProfileManager.updateUsername(this.userNameInput.value));
|
|
|
|
}
|
|
|
|
|
|
|
|
Promise.race(promises).then(() => {
|
|
|
|
this.nextBtn.disabled = false;
|
|
|
|
}, () => {
|
|
|
|
this.nextBtn.disabled = false;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
let scrollable = new Scrollable(this.scrollWrapper as HTMLElement, 'y');
|
|
|
|
}
|
|
|
|
|
|
|
|
public fillElements() {
|
|
|
|
let user = appUsersManager.getSelf();
|
|
|
|
this.firstNameInput.value = this.originalValues.firstName = user.first_name ?? '';
|
|
|
|
this.lastNameInput.value = this.originalValues.lastName = user.last_name ?? '';
|
|
|
|
this.userNameInput.value = this.originalValues.userName = user.username ?? '';
|
|
|
|
|
|
|
|
this.userNameInput.classList.remove('valid', 'error');
|
|
|
|
this.userNameInput.nextElementSibling.innerHTML = 'Username (optional)';
|
|
|
|
|
|
|
|
appProfileManager.getProfile(user.id).then(userFull => {
|
|
|
|
if(userFull.rAbout) {
|
|
|
|
this.bioInput.value = this.originalValues.bio = userFull.rAbout;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
this.avatarElem.setAttribute('peer', '' + $rootScope.myID);
|
|
|
|
if(!this.avatarElem.parentElement) {
|
|
|
|
this.canvas.parentElement.append(this.avatarElem);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.uploadAvatar = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
private isChanged() {
|
|
|
|
return !!this.uploadAvatar
|
|
|
|
|| this.firstNameInput.value != this.originalValues.firstName
|
|
|
|
|| this.lastNameInput.value != this.originalValues.lastName
|
|
|
|
|| this.userNameInput.value != this.originalValues.userName
|
|
|
|
|| this.bioInput.value != this.originalValues.bio;
|
|
|
|
}
|
|
|
|
|
|
|
|
private handleChange() {
|
|
|
|
if(this.isChanged()) {
|
|
|
|
this.nextBtn.classList.add('is-visible');
|
|
|
|
} else {
|
|
|
|
this.nextBtn.classList.remove('is-visible');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
onCloseAfterTimeout() {
|
|
|
|
this.nextBtn.classList.remove('is-visible');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-06 22:43:07 +07:00
|
|
|
class AppSidebarLeft {
|
2020-04-24 03:48:48 +03:00
|
|
|
private sidebarEl = document.getElementById('column-left') as HTMLDivElement;
|
2020-02-06 22:43:07 +07:00
|
|
|
private toolsBtn = this.sidebarEl.querySelector('.sidebar-tools-button') as HTMLButtonElement;
|
2020-02-15 22:20:38 +07:00
|
|
|
private backBtn = this.sidebarEl.querySelector('.sidebar-back-button') as HTMLButtonElement;
|
2020-02-06 22:43:07 +07:00
|
|
|
private searchContainer = this.sidebarEl.querySelector('#search-container') as HTMLDivElement;
|
2020-04-24 03:48:48 +03:00
|
|
|
private searchInput = document.getElementById('global-search') as HTMLInputElement;
|
2020-02-08 18:58:22 +07:00
|
|
|
|
2020-02-08 13:03:09 +07:00
|
|
|
private menuEl = this.toolsBtn.querySelector('.btn-menu');
|
2020-05-09 15:02:07 +03:00
|
|
|
private newGroupBtn = this.menuEl.querySelector('.menu-new-group');
|
2020-05-06 04:03:31 +03:00
|
|
|
private contactsBtn = this.menuEl.querySelector('.menu-contacts');
|
2020-05-09 15:02:07 +03:00
|
|
|
private archivedBtn = this.menuEl.querySelector('.menu-archive');
|
|
|
|
private savedBtn = this.menuEl.querySelector('.menu-saved');
|
2020-05-13 18:26:40 +03:00
|
|
|
private settingsBtn = this.menuEl.querySelector('.menu-settings');
|
2020-02-15 22:20:38 +07:00
|
|
|
public archivedCount = this.archivedBtn.querySelector('.archived-count') as HTMLSpanElement;
|
2020-02-09 13:45:43 +07:00
|
|
|
|
2020-05-09 15:02:07 +03:00
|
|
|
private newBtnMenu = this.sidebarEl.querySelector('#new-menu');
|
|
|
|
private newButtons = {
|
|
|
|
channel: this.newBtnMenu.querySelector('.menu-channel'),
|
|
|
|
group: this.newBtnMenu.querySelector('.menu-group'),
|
|
|
|
privateChat: this.newBtnMenu.querySelector('.menu-private-chat'),
|
|
|
|
};
|
|
|
|
|
|
|
|
public newChannelTab = new AppNewChannelTab();
|
|
|
|
public addMembersTab = new AppAddMembersTab();
|
|
|
|
public contactsTab = new AppContactsTab();
|
|
|
|
public newGroupTab = new AppNewGroupTab();
|
2020-05-13 18:26:40 +03:00
|
|
|
public settingsTab = new AppSettingsTab();
|
|
|
|
public editProfileTab = new AppEditProfileTab();
|
2020-05-09 15:02:07 +03:00
|
|
|
|
|
|
|
private tabs: {[id: number]: SliderTab} = {
|
|
|
|
[SLIDERITEMSIDS.newChannel]: this.newChannelTab,
|
|
|
|
[SLIDERITEMSIDS.contacts]: this.contactsTab,
|
|
|
|
[SLIDERITEMSIDS.addMembers]: this.addMembersTab,
|
|
|
|
[SLIDERITEMSIDS.newGroup]: this.newGroupTab,
|
2020-05-13 18:26:40 +03:00
|
|
|
[SLIDERITEMSIDS.settings]: this.settingsTab,
|
|
|
|
[SLIDERITEMSIDS.editProfile]: this.editProfileTab,
|
2020-05-09 15:02:07 +03:00
|
|
|
};
|
|
|
|
|
2020-04-24 03:48:48 +03:00
|
|
|
//private log = logger('SL');
|
|
|
|
|
2020-05-06 04:03:31 +03:00
|
|
|
private searchGroups = {
|
2020-04-24 03:48:48 +03:00
|
|
|
contacts: new SearchGroup('Contacts and Chats', 'contacts'),
|
|
|
|
globalContacts: new SearchGroup('Global Search', 'contacts'),
|
2020-05-06 04:03:31 +03:00
|
|
|
messages: new SearchGroup('Global Search', 'messages'),
|
|
|
|
people: new SearchGroup('People', 'contacts', false, 'search-group-people'),
|
|
|
|
recent: new SearchGroup('Recent', 'contacts', false, 'search-group-recent')
|
|
|
|
};
|
|
|
|
private globalSearch = new AppSearch(this.searchContainer, this.searchInput, this.searchGroups);
|
|
|
|
|
|
|
|
private _selectTab: (id: number) => void;
|
2020-05-09 15:02:07 +03:00
|
|
|
public historyTabIDs: number[] = [];
|
2020-02-21 15:25:19 +07:00
|
|
|
|
2020-02-06 22:43:07 +07:00
|
|
|
constructor() {
|
2020-05-06 04:03:31 +03:00
|
|
|
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 Scrollable(peopleContainer, 'x');
|
|
|
|
|
2020-02-10 14:56:15 +07:00
|
|
|
this.savedBtn.addEventListener('click', (e) => {
|
2020-02-17 19:18:06 +07:00
|
|
|
///////this.log('savedbtn click');
|
2020-02-10 14:56:15 +07:00
|
|
|
setTimeout(() => { // menu doesn't close if no timeout (lol)
|
2020-02-13 22:42:39 +07:00
|
|
|
let dom = appDialogsManager.getDialogDom(appImManager.myID);
|
2020-04-08 18:46:43 +03:00
|
|
|
appImManager.setPeer(appImManager.myID);
|
2020-02-10 14:56:15 +07:00
|
|
|
}, 0);
|
2020-02-08 13:03:09 +07:00
|
|
|
});
|
2020-02-07 13:38:55 +07:00
|
|
|
|
2020-02-11 22:35:57 +07:00
|
|
|
this.archivedBtn.addEventListener('click', (e) => {
|
2020-05-06 04:03:31 +03:00
|
|
|
this.selectTab(SLIDERITEMSIDS.archived);
|
|
|
|
});
|
|
|
|
|
|
|
|
this.contactsBtn.addEventListener('click', (e) => {
|
2020-05-09 15:02:07 +03:00
|
|
|
this.contactsTab.openContacts();
|
2020-02-11 22:35:57 +07:00
|
|
|
});
|
2020-04-19 00:55:20 +03:00
|
|
|
|
2020-05-13 18:26:40 +03:00
|
|
|
this.settingsBtn.addEventListener('click', () => {
|
|
|
|
this.settingsTab.fillElements();
|
|
|
|
this.selectTab(SLIDERITEMSIDS.settings);
|
2020-04-19 00:55:20 +03:00
|
|
|
});
|
2020-02-22 18:20:43 +07:00
|
|
|
|
2020-02-06 22:43:07 +07:00
|
|
|
this.searchInput.addEventListener('focus', (e) => {
|
2020-02-15 22:20:38 +07:00
|
|
|
this.toolsBtn.classList.remove('active');
|
|
|
|
this.backBtn.classList.add('active');
|
2020-05-06 04:03:31 +03:00
|
|
|
this.searchContainer.classList.remove('hide');
|
|
|
|
void this.searchContainer.offsetWidth; // reflow
|
2020-02-06 22:43:07 +07:00
|
|
|
this.searchContainer.classList.add('active');
|
2020-02-09 17:30:24 +07:00
|
|
|
|
2020-05-13 18:26:40 +03:00
|
|
|
/* this.searchInput.addEventListener('blur', (e) => {
|
2020-02-06 22:43:07 +07:00
|
|
|
if(!this.searchInput.value) {
|
2020-02-15 22:20:38 +07:00
|
|
|
this.toolsBtn.classList.add('active');
|
|
|
|
this.backBtn.classList.remove('active');
|
2020-02-17 19:18:06 +07:00
|
|
|
this.backBtn.click();
|
2020-02-06 22:43:07 +07:00
|
|
|
}
|
2020-05-13 18:26:40 +03:00
|
|
|
}, {once: true}); */
|
2020-02-06 22:43:07 +07:00
|
|
|
});
|
2020-02-10 14:56:15 +07:00
|
|
|
|
2020-02-15 22:20:38 +07:00
|
|
|
this.backBtn.addEventListener('click', (e) => {
|
2020-04-20 00:40:00 +03:00
|
|
|
appDialogsManager.chatsArchivedContainer.classList.remove('active');
|
2020-02-15 22:20:38 +07:00
|
|
|
this.toolsBtn.classList.add('active');
|
|
|
|
this.backBtn.classList.remove('active');
|
2020-02-17 19:18:06 +07:00
|
|
|
this.searchContainer.classList.remove('active');
|
2020-05-06 04:03:31 +03:00
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
this.searchContainer.classList.add('hide');
|
|
|
|
this.globalSearch.reset();
|
|
|
|
|
|
|
|
this.searchGroups.people.setActive();
|
|
|
|
//this.searchGroups.recent.setActive();
|
|
|
|
}, 150);
|
2020-02-07 13:38:55 +07:00
|
|
|
});
|
2020-02-11 22:35:57 +07:00
|
|
|
|
2020-05-09 15:02:07 +03:00
|
|
|
this.newButtons.channel.addEventListener('click', (e) => {
|
|
|
|
this.selectTab(SLIDERITEMSIDS.newChannel);
|
|
|
|
});
|
|
|
|
|
|
|
|
[this.newButtons.group, this.newGroupBtn].forEach(btn => {
|
|
|
|
btn.addEventListener('click', (e) => {
|
|
|
|
this.addMembersTab.init(0, 'chat', false, (peerIDs) => {
|
|
|
|
this.newGroupTab.init(peerIDs);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-04-20 00:40:00 +03:00
|
|
|
$rootScope.$on('dialogs_archived_unread', (e: CustomEvent) => {
|
|
|
|
this.archivedCount.innerText = '' + e.detail.count;
|
|
|
|
});
|
|
|
|
|
2020-05-06 04:03:31 +03:00
|
|
|
this._selectTab = horizontalMenu(null, this.sidebarEl.querySelector('.sidebar-slider') as HTMLDivElement, null, null, 420);
|
|
|
|
this._selectTab(0);
|
|
|
|
|
2020-05-09 15:02:07 +03:00
|
|
|
let onCloseBtnClick = () => {
|
|
|
|
console.log('sidebar-close-button click:', this.historyTabIDs);
|
|
|
|
let closingID = this.historyTabIDs.pop(); // pop current
|
|
|
|
this.onCloseTab(closingID);
|
2020-05-13 18:26:40 +03:00
|
|
|
this._selectTab(this.historyTabIDs[this.historyTabIDs.length - 1] || 0);
|
2020-05-09 15:02:07 +03:00
|
|
|
};
|
2020-05-06 04:03:31 +03:00
|
|
|
Array.from(this.sidebarEl.querySelectorAll('.sidebar-close-button') as any as HTMLElement[]).forEach(el => {
|
2020-05-09 15:02:07 +03:00
|
|
|
el.addEventListener('click', onCloseBtnClick);
|
2020-05-06 04:03:31 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
appUsersManager.getTopPeers().then(categories => {
|
|
|
|
console.log('got top categories:', categories);
|
|
|
|
|
|
|
|
let category = categories[0];
|
|
|
|
if(!category || !category.peers) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
category.peers.forEach((topPeer: {
|
|
|
|
_: 'topPeer',
|
|
|
|
peer: any,
|
|
|
|
rating: number
|
|
|
|
}) => {
|
|
|
|
let peerID = appPeersManager.getPeerID(topPeer.peer);
|
|
|
|
let {dialog, dom} = appDialogsManager.addDialog(peerID, this.searchGroups.people.list, false, true, true);
|
|
|
|
|
|
|
|
this.searchGroups.people.setActive();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-05-09 15:02:07 +03:00
|
|
|
public selectTab(id: number) {
|
|
|
|
this.historyTabIDs.push(id);
|
|
|
|
this._selectTab(id);
|
|
|
|
}
|
2020-05-06 04:03:31 +03:00
|
|
|
|
2020-05-09 15:02:07 +03:00
|
|
|
public removeTabFromHistory(id: number) {
|
|
|
|
this.historyTabIDs.findAndSplice(i => i == id);
|
|
|
|
this.onCloseTab(id);
|
|
|
|
}
|
2020-05-06 04:03:31 +03:00
|
|
|
|
2020-05-09 15:02:07 +03:00
|
|
|
public onCloseTab(id: number) {
|
|
|
|
let tab = this.tabs[id];
|
|
|
|
if(tab) {
|
|
|
|
if('onClose' in tab) {
|
|
|
|
tab.onClose();
|
2020-05-06 04:03:31 +03:00
|
|
|
}
|
|
|
|
|
2020-05-09 15:02:07 +03:00
|
|
|
if('onCloseAfterTimeout' in tab) {
|
|
|
|
setTimeout(() => {
|
|
|
|
tab.onCloseAfterTimeout();
|
|
|
|
}, 420);
|
|
|
|
}
|
|
|
|
}
|
2020-02-07 13:38:55 +07:00
|
|
|
}
|
2020-02-06 22:43:07 +07:00
|
|
|
}
|
|
|
|
|
2020-04-08 18:46:43 +03:00
|
|
|
const appSidebarLeft = new AppSidebarLeft();
|
|
|
|
(window as any).appSidebarLeft = appSidebarLeft;
|
|
|
|
export default appSidebarLeft;
|