2021-01-06 13:16:53 +04:00

289 lines
10 KiB
TypeScript

import type { InputFile } from "../../../layer";
import appProfileManager from "../../../lib/appManagers/appProfileManager";
import appUsersManager from "../../../lib/appManagers/appUsersManager";
import apiManager from "../../../lib/mtproto/mtprotoworker";
import RichTextProcessor from "../../../lib/richtextprocessor";
import rootScope from "../../../lib/rootScope";
import AvatarElement from "../../avatar";
import InputField from "../../inputField";
import Scrollable from "../../scrollable";
import SidebarSlider, { SliderSuperTab } from "../../slider";
import AvatarEdit from "../../avatarEdit";
import ButtonIcon from "../../buttonIcon";
// TODO: аватарка не поменяется в этой вкладке после изменения почему-то (если поставить в другом клиенте, и потом тут проверить, для этого ещё вышел в чатлист)
export default class AppEditProfileTab extends SliderSuperTab {
//private scrollWrapper: HTMLElement;
private nextBtn: HTMLButtonElement;
private firstNameInputField: InputField;
private lastNameInputField: InputField;
private bioInputField: InputField;
private userNameInputField: InputField;
private firstNameInput: HTMLElement;
private lastNameInput: HTMLElement;
private bioInput: HTMLElement;
private userNameInput: HTMLElement;
private uploadAvatar: () => Promise<InputFile> = null;
private avatarEdit: AvatarEdit;
private avatarElem: AvatarElement;
private profileUrlContainer: HTMLDivElement;
private profileUrlAnchor: HTMLAnchorElement;
private originalValues = {
firstName: '',
lastName: '',
userName: '',
bio: ''
};
constructor(slider: SidebarSlider) {
super(slider);
}
protected init() {
this.container.classList.add('edit-profile-container');
this.title.innerText = 'Edit Profile';
//this.scrollWrapper = this.container.querySelector('.scroll-wrapper');
this.nextBtn = ButtonIcon('check btn-circle btn-corner');
this.content.append(this.nextBtn);
this.avatarElem = document.createElement('avatar-element') as AvatarElement;
this.avatarElem.classList.add('avatar-placeholder');
this.avatarEdit = new AvatarEdit((_upload) => {
this.uploadAvatar = _upload;
this.handleChange();
this.avatarElem.remove();
});
this.scrollable.append(this.avatarEdit.container);
{
const inputWrapper = document.createElement('div');
inputWrapper.classList.add('input-wrapper');
this.firstNameInputField = new InputField({
label: 'Name',
name: 'first-name',
maxLength: 70
});
this.lastNameInputField = new InputField({
label: 'Last Name',
name: 'last-name',
maxLength: 64
});
this.bioInputField = new InputField({
label: 'Bio (optional)',
name: 'bio',
maxLength: 70
});
this.firstNameInput = this.firstNameInputField.input;
this.lastNameInput = this.lastNameInputField.input;
this.bioInput = this.bioInputField.input;
inputWrapper.append(this.firstNameInputField.container, this.lastNameInputField.container, this.bioInputField.container);
const caption = document.createElement('div');
caption.classList.add('caption');
caption.innerHTML = 'Any details such as age, occupation or city. Example:<br>23 y.o. designer from San Francisco.';
this.scrollable.append(inputWrapper, caption);
}
this.scrollable.append(document.createElement('hr'));
{
const h2 = document.createElement('div');
h2.classList.add('sidebar-left-h2');
h2.innerText = 'Username';
const inputWrapper = document.createElement('div');
inputWrapper.classList.add('input-wrapper');
this.userNameInputField = new InputField({
label: 'Username (optional)',
name: 'username',
plainText: true
});
this.userNameInput = this.userNameInputField.input;
inputWrapper.append(this.userNameInputField.container);
const caption = document.createElement('div');
caption.classList.add('caption');
caption.innerHTML = `You can choose a username on Telegram. If you do, other people will be able to find you by this username and contact you without knowing your phone number.<br><br>You can use a-z, 0-9 and underscores. Minimum length is 5 characters.<br><br><div class="profile-url-container">This link opens a chat with you:
<br><a class="profile-url" href="#" target="_blank"></a></div>`;
this.profileUrlContainer = caption.querySelector('.profile-url-container');
this.profileUrlAnchor = this.profileUrlContainer.lastElementChild as HTMLAnchorElement;
this.scrollable.append(h2, inputWrapper, caption);
}
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', () => {
let value = this.userNameInputField.value;
//console.log('userNameInput:', value);
if(value == this.originalValues.userName || !value.length) {
this.userNameInput.classList.remove('valid', 'error');
userNameLabel.innerText = 'Username (optional)';
this.setProfileUrl();
this.handleChange();
return;
} else if(!this.isUsernameValid(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('valid', 'error');
}
if(this.userNameInput.classList.contains('error')) {
this.setProfileUrl();
this.handleChange();
return;
}
apiManager.invokeApi('account.checkUsername', {
username: value
}).then(available => {
if(this.userNameInputField.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.userNameInputField.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;
}
}
}).then(() => {
this.handleChange();
this.setProfileUrl();
});
});
this.nextBtn.addEventListener('click', () => {
this.nextBtn.disabled = true;
let promises: Promise<any>[] = [];
promises.push(appProfileManager.updateProfile(this.firstNameInputField.value, this.lastNameInputField.value, this.bioInputField.value).then(() => {
this.slider.selectTab(0);
}, (err) => {
console.error('updateProfile error:', err);
}));
if(this.uploadAvatar) {
promises.push(this.uploadAvatar().then(inputFile => {
appProfileManager.uploadProfilePhoto(inputFile);
}));
}
if(this.userNameInputField.value != this.originalValues.userName && this.userNameInput.classList.contains('valid')) {
promises.push(appProfileManager.updateUsername(this.userNameInputField.value));
}
Promise.race(promises).finally(() => {
this.nextBtn.removeAttribute('disabled');
});
});
}
public fillElements() {
if(this.init) {
this.init();
this.init = null;
}
const user = appUsersManager.getSelf();
Object.assign(this.originalValues, {
firstName: user.first_name,
lastName: user.last_name,
userName: user.username,
bio: ''
});
this.firstNameInputField.value = RichTextProcessor.wrapDraftText(user.first_name);
this.lastNameInputField.value = RichTextProcessor.wrapDraftText(user.last_name);
this.bioInputField.value = '';
this.userNameInputField.value = this.originalValues.userName = user.username ?? '';
this.userNameInput.classList.remove('valid', 'error');
this.userNameInput.nextElementSibling.innerHTML = 'Username (optional)';
appProfileManager.getProfile(user.id, true).then(userFull => {
if(userFull.about) {
this.originalValues.bio = userFull.about;
this.bioInputField.value = RichTextProcessor.wrapDraftText(userFull.about);
this.handleChange();
}
});
this.avatarElem.setAttribute('peer', '' + rootScope.myId);
if(!this.avatarElem.parentElement) {
this.avatarEdit.container.append(this.avatarElem);
}
this.uploadAvatar = null;
this.setProfileUrl();
this.handleChange();
}
public isUsernameValid(username: string) {
return ((username.length >= 5 && username.length <= 32) || !username.length) && /^[a-zA-Z0-9_]*$/.test(username);
}
private isChanged() {
return !!this.uploadAvatar
|| (!this.firstNameInput.classList.contains('error') && this.firstNameInputField.value != this.originalValues.firstName)
|| (!this.lastNameInput.classList.contains('error') && this.lastNameInputField.value != this.originalValues.lastName)
|| (!this.bioInput.classList.contains('error') && this.bioInputField.value != this.originalValues.bio)
|| (this.userNameInputField.value != this.originalValues.userName && !this.userNameInput.classList.contains('error'));
}
private setProfileUrl() {
if(this.userNameInput.classList.contains('error') || !this.userNameInputField.value.length) {
this.profileUrlContainer.style.display = 'none';
} else {
this.profileUrlContainer.style.display = '';
let url = 'https://t.me/' + this.userNameInputField.value;
this.profileUrlAnchor.innerText = url;
this.profileUrlAnchor.href = url;
}
}
private handleChange = () => {
this.nextBtn.classList.toggle('is-visible', this.isChanged());
};
onCloseAfterTimeout() {
this.nextBtn.classList.remove('is-visible');
this.firstNameInputField.value = this.lastNameInputField.value = this.bioInputField.value = '';
}
}