tweb/src/components/sidebarLeft/tabs/settings.ts

315 lines
10 KiB
TypeScript

/*
* https://github.com/morethanwords/tweb
* Copyright (C) 2019-2021 Eduard Kuzmenko
* https://github.com/morethanwords/tweb/blob/master/LICENSE
*/
import {SliderSuperTab} from '../../slider';
import ButtonMenuToggle from '../../buttonMenuToggle';
import Button from '../../button';
import AppPrivacyAndSecurityTab from './privacyAndSecurity';
import AppGeneralSettingsTab from './generalSettings';
import AppEditProfileTab from './editProfile';
import AppChatFoldersTab from './chatFolders';
import AppNotificationsTab from './notifications';
import AppLanguageTab from './language';
import lottieLoader from '../../../lib/rlottie/lottieLoader';
import PopupPeer from '../../popups/peer';
import AppDataAndStorageTab from './dataAndStorage';
import ButtonIcon from '../../buttonIcon';
import PeerProfile from '../../peerProfile';
import rootScope from '../../../lib/rootScope';
import Row from '../../row';
import AppActiveSessionsTab from './activeSessions';
import {i18n, LangPackKey} from '../../../lib/langPack';
import {SliderSuperTabConstructable, SliderSuperTabEventable} from '../../sliderTab';
import PopupAvatar from '../../popups/avatar';
import {AccountAuthorizations, Authorization} from '../../../layer';
import PopupElement from '../../popups';
import {attachClickEvent} from '../../../helpers/dom/clickEvent';
import SettingSection from '../../settingSection';
import AppStickersAndEmojiTab from './stickersAndEmoji';
export default class AppSettingsTab extends SliderSuperTab {
private buttons: {
edit: HTMLButtonElement,
folders: HTMLButtonElement,
general: HTMLButtonElement,
notifications: HTMLButtonElement,
storage: HTMLButtonElement,
privacy: HTMLButtonElement,
} = {} as any;
private profile: PeerProfile;
private languageRow: Row;
private devicesRow: Row;
private authorizations: Authorization.authorization[];
private getAuthorizationsPromise: Promise<AccountAuthorizations.accountAuthorizations>;
public async init() {
this.container.classList.add('settings-container');
this.setTitle('Settings');
const btnMenu = ButtonMenuToggle({
listenerSetter: this.listenerSetter,
direction: 'bottom-left',
buttons: [{
icon: 'logout',
text: 'EditAccount.Logout',
onClick: () => {
new PopupPeer('logout', {
titleLangKey: 'LogOut',
descriptionLangKey: 'LogOut.Description',
buttons: [{
langKey: 'LogOut',
callback: () => {
this.managers.apiManager.logOut();
},
isDanger: true
}]
}).show();
}
}]
});
this.buttons.edit = ButtonIcon('edit');
this.header.append(this.buttons.edit, btnMenu);
this.profile = new PeerProfile(this.managers, this.scrollable, this.listenerSetter, false);
this.profile.init();
this.profile.setPeer(rootScope.myId);
const fillPromise = this.profile.fillProfileElements();
const changeAvatarBtn = Button('btn-circle btn-corner z-depth-1 profile-change-avatar', {icon: 'cameraadd'});
attachClickEvent(changeAvatarBtn, () => {
const canvas = document.createElement('canvas');
PopupElement.createPopup(PopupAvatar).open(canvas, (upload) => {
upload().then((inputFile) => {
return this.managers.appProfileManager.uploadProfilePhoto(inputFile);
});
});
}, {listenerSetter: this.listenerSetter});
this.profile.element.lastElementChild.firstElementChild.append(changeAvatarBtn);
const updateChangeAvatarBtn = async() => {
const user = await this.managers.appUsersManager.getSelf();
changeAvatarBtn.classList.toggle('hide', user.photo?._ !== 'userProfilePhoto');
};
updateChangeAvatarBtn();
this.listenerSetter.add(rootScope)('avatar_update', ({peerId}) => {
if(rootScope.myId === peerId) {
updateChangeAvatarBtn();
}
});
/* const div = document.createElement('div');
//div.style.cssText = 'border-radius: 8px; overflow: hidden; width: 396px; height: 264px; flex: 0 0 auto; position: relative; margin: 10rem 0 10rem auto;';
//div.style.width = '135px';
//div.style.height = '100px';
div.style.cssText = 'border-radius: 8px; overflow: hidden; width: 396px; height: 264px; flex: 0 0 auto; position: relative; margin: 10rem auto 10rem 0;';
div.style.width = '135px';
div.style.height = '100px';
const img = document.createElement('img');
img.src = 'assets/img/pepe.jpg';
img.classList.add('media-photo');
img.style.cssText = 'max-width: 100%;max-height: 100%;';
div.append(img);
div.addEventListener('click', () => {
new AppMediaViewer().setSearchContext({peerId: 61004386, inputFilter: 'inputMessagesFilterPhotos'}).openMedia({
_: 'message',
mid: 1,
peerId: 61004386,
fromId: 61004386,
message: '',
media: {
_: 'messageMediaPhoto',
photo: {
_: 'photo',
url: img.src,
downloaded: 111,
sizes: [{
_: 'photoSize',
type: 'x',
w: 618,
h: 412
}]
}
},
date: Date.now() / 1000 | 0
}, img);
});
this.scrollable.append(div); */
const buttonsDiv = document.createElement('div');
buttonsDiv.classList.add('profile-buttons');
type ConstructorP<T> = T extends {
new (...args: any[]): infer U;
} ? U : never;
const m = <T extends SliderSuperTabConstructable>(
icon: string,
text: LangPackKey,
c: T,
getInitArgs?: () => Promise<Parameters<ConstructorP<T>['init']>>
): {
icon: string,
text: LangPackKey,
tabConstructor: T,
getInitArgs?: typeof getInitArgs,
// args?: ReturnType<typeof getInitArgs>
args?: any
} => {
if(!getInitArgs) {
const g = (c as any as typeof SliderSuperTab).getInitArgs;
if(g) {
// @ts-ignore
getInitArgs = () => [g(this)];
}
}
return {
icon,
text,
tabConstructor: c,
getInitArgs,
args: getInitArgs?.()
};
};
// const k = <T extends SliderSuperTabConstructable>(c: T): () => [ReturnType<ConstructorP<T>['getInitArgs']>] => {
// return () => (c as any).getInitArgs(this);
// };
const b = [
m('unmute', 'AccountSettings.Notifications', AppNotificationsTab),
m('data', 'DataSettings', AppDataAndStorageTab),
m('lock', 'AccountSettings.PrivacyAndSecurity', AppPrivacyAndSecurityTab),
m('settings', 'Telegram.GeneralSettingsViewController', AppGeneralSettingsTab),
m('folder', 'AccountSettings.Filters', AppChatFoldersTab),
m('stickers_face', 'StickersName', AppStickersAndEmojiTab)
];
const rows = b.map((item) => {
const {icon, text: langPackKey, tabConstructor, getInitArgs} = item;
return new Row({
titleLangKey: langPackKey,
icon,
clickable: async() => {
const args = item.args ? await item.args : [];
const tab = this.slider.createTab(tabConstructor as any);
tab.open(...args);
if(tab instanceof SliderSuperTabEventable && getInitArgs) {
tab.eventListener.addEventListener('destroyAfter', (promise) => {
item.args = promise.then(() => getInitArgs() as any);
});
}
},
listenerSetter: this.listenerSetter
});
});
const languageArgs = AppLanguageTab.getInitArgs();
rows.push(
this.devicesRow = new Row({
titleLangKey: 'Devices',
titleRightSecondary: ' ',
icon: 'activesessions',
clickable: async() => {
if(!this.authorizations) {
await this.updateActiveSessions();
}
const tab = this.slider.createTab(AppActiveSessionsTab);
tab.authorizations = this.authorizations;
tab.eventListener.addEventListener('destroy', () => {
this.authorizations = undefined;
this.updateActiveSessions(true);
}, {once: true});
tab.open();
},
listenerSetter: this.listenerSetter
}),
this.languageRow = new Row({
titleLangKey: 'AccountSettings.Language',
titleRightSecondary: i18n('LanguageName'),
icon: 'language',
clickable: () => {
this.slider.createTab(AppLanguageTab).open(languageArgs);
},
listenerSetter: this.listenerSetter
})
);
buttonsDiv.append(...rows.map((row) => row.container));
// const profileSection = new SettingSection({fullWidth: true, noPaddingTop: true});
// profileSection.content.append(this.profile.element);
const buttonsSection = new SettingSection();
buttonsSection.content.append(buttonsDiv);
this.scrollable.append(this.profile.element/* profileSection.container */, buttonsSection.container);
const getEditProfileArgs = () => {
editProfileArgs = AppEditProfileTab.getInitArgs();
};
let editProfileArgs: ReturnType<typeof AppEditProfileTab['getInitArgs']>;
attachClickEvent(this.buttons.edit, () => {
const tab = this.slider.createTab(AppEditProfileTab);
tab.open(editProfileArgs);
}, {listenerSetter: this.listenerSetter});
getEditProfileArgs();
// this.listenerSetter.add(rootScope)('user_full_update', (userId) => {
// if(rootScope.myId.toUserId() === userId) {
// getEditProfileArgs();
// }
// });
this.listenerSetter.add(rootScope)('user_update', (userId) => {
if(rootScope.myId.toUserId() === userId) {
getEditProfileArgs();
}
});
lottieLoader.loadLottieWorkers();
this.updateActiveSessions();
(await fillPromise)();
}
private getAuthorizations(overwrite?: boolean) {
if(this.getAuthorizationsPromise && !overwrite) return this.getAuthorizationsPromise;
const promise = this.getAuthorizationsPromise = this.managers.apiManager.invokeApi('account.getAuthorizations')
.finally(() => {
if(this.getAuthorizationsPromise === promise) {
this.getAuthorizationsPromise = undefined;
}
});
return promise;
}
public updateActiveSessions(overwrite?: boolean) {
return this.getAuthorizations(overwrite).then((auths) => {
this.authorizations = auths.authorizations;
this.devicesRow.titleRight.textContent = '' + this.authorizations.length;
});
}
public onCloseAfterTimeout() {
this.profile.destroy();
return super.onCloseAfterTimeout();
}
}