diff --git a/src/components/chat/topbar.ts b/src/components/chat/topbar.ts
index 60a2a0c6..2623c7c2 100644
--- a/src/components/chat/topbar.ts
+++ b/src/components/chat/topbar.ts
@@ -218,7 +218,7 @@ export default class ChatTopbar {
this.pinnedMessage = new ChatPinnedMessage(this, this.chat, this.appMessagesManager, this.appPeersManager);
- this.btnJoin = Button('btn-primary chat-join hide');
+ this.btnJoin = Button('btn-primary btn-color-primary chat-join hide');
this.btnJoin.append('SUBSCRIBE');
this.btnPinned = ButtonIcon('pinlist');
diff --git a/src/components/horizontalMenu.ts b/src/components/horizontalMenu.ts
index 77334720..766e32b8 100644
--- a/src/components/horizontalMenu.ts
+++ b/src/components/horizontalMenu.ts
@@ -32,7 +32,8 @@ export function horizontalMenu(tabs: HTMLElement, content: HTMLElement, onClick?
animate = false;
}
- if(target.classList.contains('active') || id === selectTab.prevId) {
+ const prevId = selectTab.prevId();
+ if(target.classList.contains('active') || id === prevId) {
return false;
}
@@ -42,7 +43,6 @@ export function horizontalMenu(tabs: HTMLElement, content: HTMLElement, onClick?
prev && prev.classList.remove('active');
});
- const prevId = selectTab.prevId;
// stripe from ZINCHUK
if(useStripe && prevId !== -1 && animate) {
fastRaf(() => {
diff --git a/src/components/popups/avatar.ts b/src/components/popups/avatar.ts
index fd66c827..227b1ea7 100644
--- a/src/components/popups/avatar.ts
+++ b/src/components/popups/avatar.ts
@@ -66,7 +66,7 @@ export default class PopupAvatar extends PopupElement {
}, false);
this.btnSubmit = document.createElement('button');
- this.btnSubmit.className = 'btn-primary btn-circle btn-crop btn-icon tgico-check z-depth-1';
+ this.btnSubmit.className = 'btn-primary btn-color-primary btn-circle btn-crop btn-icon tgico-check z-depth-1';
ripple(this.btnSubmit);
this.btnSubmit.addEventListener('click', () => {
this.cropper.crop();
diff --git a/src/components/popups/index.ts b/src/components/popups/index.ts
index d34d3952..b13331b8 100644
--- a/src/components/popups/index.ts
+++ b/src/components/popups/index.ts
@@ -64,7 +64,7 @@ export default class PopupElement {
if(options.withConfirm) {
this.btnConfirm = document.createElement('button');
- this.btnConfirm.classList.add('btn-primary');
+ this.btnConfirm.classList.add('btn-primary', 'btn-color-primary');
this.btnConfirm.innerText = options.withConfirm;
this.header.append(this.btnConfirm);
ripple(this.btnConfirm);
diff --git a/src/components/popups/stickers.ts b/src/components/popups/stickers.ts
index 46ac7211..3b32bb2d 100644
--- a/src/components/popups/stickers.ts
+++ b/src/components/popups/stickers.ts
@@ -97,7 +97,7 @@ export default class PopupStickers extends PopupElement {
this.h6.innerHTML = RichTextProcessor.wrapEmojiText(set.set.title);
!set.set.installed_date ? this.stickersFooter.classList.add('add') : this.stickersFooter.classList.remove('add');
- this.stickersFooter.innerHTML = set.set.hasOwnProperty('installed_date') ? '
Remove stickers
' : ``;
+ this.stickersFooter.innerHTML = set.set.hasOwnProperty('installed_date') ? 'Remove stickers
' : ``;
this.stickersFooter.addEventListener('click', this.onFooterClick);
diff --git a/src/components/sidebarLeft/index.ts b/src/components/sidebarLeft/index.ts
index 10ec260b..ef4d9fe7 100644
--- a/src/components/sidebarLeft/index.ts
+++ b/src/components/sidebarLeft/index.ts
@@ -13,33 +13,18 @@ import Scrollable, { ScrollableX } from "../scrollable";
import InputSearch from "../inputSearch";
import SidebarSlider from "../slider";
import { TransitionSlider } 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";
import appMessagesManager from "../../lib/appManagers/appMessagesManager";
-import apiManagerProxy from "../../lib/mtproto/mtprotoworker";
import AppSearchSuper from "../appSearchSuper.";
import { DateData, fillTipDates } from "../../helpers/date";
-import AppGeneralSettingsTab from "./tabs/generalSettings";
-import AppPrivacyAndSecurityTab from "./tabs/privacyAndSecurity";
import { MOUNT_CLASS_TO } from "../../config/debug";
-
-const contactsTab = new AppContactsTab();
-const archivedTab = new AppArchivedTab();
+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";
export class AppSidebarLeft extends SidebarSlider {
- public static SLIDERITEMSIDS = {
- archived: 1,
- contacts: 2
- };
-
private toolsBtn: HTMLButtonElement;
private backBtn: HTMLButtonElement;
//private searchInput = document.getElementById('global-search') as HTMLInputElement;
@@ -63,19 +48,6 @@ export class AppSidebarLeft extends SidebarSlider {
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;
- public generalSettingsTab: AppGeneralSettingsTab;
- public privacyAndSecurityTab: AppPrivacyAndSecurityTab;
-
//private log = logger('SL');
private searchGroups: {[k in 'contacts' | 'globalContacts' | 'messages' | 'people' | 'recent']: SearchGroup} = {} as any;
@@ -87,11 +59,6 @@ export class AppSidebarLeft extends SidebarSlider {
navigationType: 'left'
});
- Object.assign(this.tabs, {
- [AppSidebarLeft.SLIDERITEMSIDS.archived]: archivedTab,
- [AppSidebarLeft.SLIDERITEMSIDS.contacts]: contactsTab
- });
-
//this._selectTab(0); // make first tab as default
this.inputSearch = new InputSearch('Telegram Search');
@@ -101,19 +68,6 @@ export class AppSidebarLeft extends SidebarSlider {
this.toolsBtn = this.sidebarEl.querySelector('.sidebar-tools-button') as HTMLButtonElement;
this.backBtn = this.sidebarEl.querySelector('.sidebar-back-button') as HTMLButtonElement;
- this.archivedTab = archivedTab;
- this.newChannelTab = new AppNewChannelTab(this);
- this.contactsTab = contactsTab;
- this.newGroupTab = new AppNewGroupTab(this);
- this.settingsTab = new AppSettingsTab(this);
- this.chatFoldersTab = new AppChatFoldersTab(appMessagesManager, appPeersManager, this, apiManagerProxy, rootScope);
- this.editFolderTab = new AppEditFolderTab(this);
- this.includedChatsTab = new AppIncludedChatsTab(this);
- this.editProfileTab = new AppEditProfileTab(this);
- this.generalSettingsTab = new AppGeneralSettingsTab(this);
- this.privacyAndSecurityTab = new AppPrivacyAndSecurityTab(this);
- this.addMembersTab = new AppAddMembersTab(this);
-
this.menuEl = this.toolsBtn.querySelector('.btn-menu');
this.newBtnMenu = this.sidebarEl.querySelector('#new-menu');
@@ -132,29 +86,29 @@ export class AppSidebarLeft extends SidebarSlider {
});
attachClickEvent(this.buttons.archived, (e) => {
- this.selectTab(AppSidebarLeft.SLIDERITEMSIDS.archived);
+ new AppArchivedTab(this).open();
});
attachClickEvent(this.buttons.contacts, (e) => {
- this.contactsTab.openContacts();
+ new AppContactsTab(this).open();
});
attachClickEvent(this.buttons.settings, (e) => {
- this.settingsTab.open();
+ new AppSettingsTab(this).open();
});
attachClickEvent(this.newButtons.channel, (e) => {
- this.newChannelTab.open();
+ new AppNewChannelTab(this).open();
});
[this.newButtons.group, this.buttons.newGroup].forEach(btn => {
attachClickEvent(btn, (e) => {
- this.addMembersTab.open({
+ new AppAddMembersTab(this).open({
peerId: 0,
type: 'chat',
skippable: false,
takeOut: (peerIds) => {
- this.newGroupTab.open(peerIds);
+ new AppNewGroupTab(this).open(peerIds);
},
title: 'Add Members',
placeholder: 'Add People...'
diff --git a/src/components/sidebarLeft/tabs/2fa/email.ts b/src/components/sidebarLeft/tabs/2fa/email.ts
index e10348c9..5a6d3137 100644
--- a/src/components/sidebarLeft/tabs/2fa/email.ts
+++ b/src/components/sidebarLeft/tabs/2fa/email.ts
@@ -9,6 +9,7 @@ import { attachClickEvent } from "../../../../helpers/dom";
import PopupConfirmAction from "../../../popups/confirmAction";
import { putPreloader } from "../../../misc";
import passwordManager from "../../../../lib/mtproto/passwordManager";
+import AppTwoStepVerificationSetTab from "./passwordSet";
export default class AppTwoStepVerificationEmailTab extends SliderSuperTab {
public inputField: InputField;
@@ -22,7 +23,7 @@ export default class AppTwoStepVerificationEmailTab extends SliderSuperTab {
}
protected init() {
- this.container.classList.add('two-step-verification-email');
+ this.container.classList.add('two-step-verification', 'two-step-verification-email');
this.title.innerHTML = 'Recovery Email';
const section = new SettingSection({
@@ -34,17 +35,21 @@ export default class AppTwoStepVerificationEmailTab extends SliderSuperTab {
const doc = appStickersManager.getAnimatedEmojiSticker(emoji);
const stickerContainer = document.createElement('div');
- wrapSticker({
- doc,
- div: stickerContainer,
- loop: false,
- play: true,
- width: 168,
- height: 168,
- emoji
- }).then(() => {
- // this.animation = player;
- });
+ if(doc) {
+ wrapSticker({
+ doc,
+ div: stickerContainer,
+ loop: false,
+ play: true,
+ width: 160,
+ height: 160,
+ emoji
+ }).then(() => {
+ // this.animation = player;
+ });
+ } else {
+ stickerContainer.classList.add('media-sticker-wrapper');
+ }
section.content.append(stickerContainer);
@@ -58,9 +63,13 @@ export default class AppTwoStepVerificationEmailTab extends SliderSuperTab {
label: 'Recovery Email'
});
- const btnContinue = Button('btn-primary', {text: 'CONTINUE'});
+ const btnContinue = Button('btn-primary btn-color-primary', {text: 'CONTINUE'});
const btnSkip = Button('btn-primary btn-primary-transparent primary', {text: 'SKIP'});
+ const goNext = () => {
+ new AppTwoStepVerificationSetTab(this.slider).open();
+ };
+
attachClickEvent(btnSkip, (e) => {
const popup = new PopupConfirmAction('popup-skip-email', [{
text: 'CANCEL',
@@ -68,20 +77,25 @@ export default class AppTwoStepVerificationEmailTab extends SliderSuperTab {
}, {
text: 'SKIP',
callback: () => {
- inputContent.classList.add('sidebar-left-section-disabled');
+ //inputContent.classList.add('sidebar-left-section-disabled');
+ btnContinue.setAttribute('disabled', 'true');
+ btnSkip.setAttribute('disabled', 'true');
putPreloader(btnSkip);
passwordManager.updateSettings({
hint: this.hint,
currentPassword: this.plainPassword,
newPassword: this.newPassword
}).then(() => {
-
+ goNext();
+ }, (err) => {
+ btnContinue.removeAttribute('disabled');
+ btnSkip.removeAttribute('disabled');
});
},
isDanger: true,
}], {
title: 'Warning',
- text: 'No, seriously.
If you forget your password, you will
lose access to your Telegram account.
There will be no way to restore it.'
+ text: 'No, seriously.
If you forget your password, you will lose access to your Telegram account. There will be no way to restore it.'
});
popup.show();
diff --git a/src/components/sidebarLeft/tabs/2fa/enterPassword.ts b/src/components/sidebarLeft/tabs/2fa/enterPassword.ts
index c2b816c1..e8dca6ea 100644
--- a/src/components/sidebarLeft/tabs/2fa/enterPassword.ts
+++ b/src/components/sidebarLeft/tabs/2fa/enterPassword.ts
@@ -3,6 +3,7 @@ import { SettingSection } from "../..";
import { attachClickEvent, cancelEvent } from "../../../../helpers/dom";
import { AccountPassword } from "../../../../layer";
import passwordManager from "../../../../lib/mtproto/passwordManager";
+import RichTextProcessor from "../../../../lib/richtextprocessor";
import Button from "../../../button";
import { putPreloader } from "../../../misc";
import PasswordMonkey from "../../../monkeys/password";
@@ -22,7 +23,7 @@ export default class AppTwoStepVerificationEnterPasswordTab extends SliderSuperT
protected init() {
const isNew = !this.state.pFlags.has_password || this.plainPassword;
- this.container.classList.add('two-step-verification-enter-password');
+ this.container.classList.add('two-step-verification', 'two-step-verification-enter-password');
this.title.innerHTML = isNew ? 'Enter a Password' : 'Enter your Password';
const section = new SettingSection({
@@ -40,7 +41,7 @@ export default class AppTwoStepVerificationEnterPasswordTab extends SliderSuperT
const monkey = new PasswordMonkey(passwordInputField, 157);
monkey.load();
- const btnContinue = Button('btn-primary', {text: 'CONTINUE'});
+ const btnContinue = Button('btn-primary btn-color-primary', {text: 'CONTINUE'});
inputWrapper.append(passwordInputField.container, btnContinue);
section.content.append(monkey.container, inputWrapper);
@@ -80,7 +81,7 @@ export default class AppTwoStepVerificationEnterPasswordTab extends SliderSuperT
return passwordManager.getState().then(_state => {
this.state = _state;
- passwordInputField.label.innerText = this.state.hint ?? 'Password';
+ passwordInputField.label.innerHTML = this.state.hint ? RichTextProcessor.wrapEmojiText(this.state.hint) : 'Password';
});
};
@@ -105,6 +106,7 @@ export default class AppTwoStepVerificationEnterPasswordTab extends SliderSuperT
tab.state = this.state;
tab.plainPassword = plainPassword;
tab.open();
+ this.slider.removeTabFromHistory(this);
}
}, (err) => {
btnContinue.removeAttribute('disabled');
diff --git a/src/components/sidebarLeft/tabs/2fa/hint.ts b/src/components/sidebarLeft/tabs/2fa/hint.ts
index 44b3813b..5a9e9bba 100644
--- a/src/components/sidebarLeft/tabs/2fa/hint.ts
+++ b/src/components/sidebarLeft/tabs/2fa/hint.ts
@@ -19,7 +19,7 @@ export default class AppTwoStepVerificationHintTab extends SliderSuperTab {
}
protected init() {
- this.container.classList.add('two-step-verification-hint');
+ this.container.classList.add('two-step-verification', 'two-step-verification-hint');
this.title.innerHTML = 'Password Hint';
const section = new SettingSection({
@@ -31,17 +31,21 @@ export default class AppTwoStepVerificationHintTab extends SliderSuperTab {
const doc = appStickersManager.getAnimatedEmojiSticker(emoji);
const stickerContainer = document.createElement('div');
- wrapSticker({
- doc,
- div: stickerContainer,
- loop: false,
- play: true,
- width: 168,
- height: 168,
- emoji
- }).then(() => {
- // this.animation = player;
- });
+ if(doc) {
+ wrapSticker({
+ doc,
+ div: stickerContainer,
+ loop: false,
+ play: true,
+ width: 160,
+ height: 160,
+ emoji
+ }).then(() => {
+ // this.animation = player;
+ });
+ } else {
+ stickerContainer.classList.add('media-sticker-wrapper');
+ }
section.content.append(stickerContainer);
@@ -72,7 +76,7 @@ export default class AppTwoStepVerificationHintTab extends SliderSuperTab {
tab.open();
};
- const btnContinue = Button('btn-primary', {text: 'CONTINUE'});
+ const btnContinue = Button('btn-primary btn-color-primary', {text: 'CONTINUE'});
const btnSkip = Button('btn-primary btn-primary-transparent primary', {text: 'SKIP'});
attachClickEvent(btnContinue, (e) => goNext(e, true));
diff --git a/src/components/sidebarLeft/tabs/2fa/index.ts b/src/components/sidebarLeft/tabs/2fa/index.ts
index e68d179f..32890e0c 100644
--- a/src/components/sidebarLeft/tabs/2fa/index.ts
+++ b/src/components/sidebarLeft/tabs/2fa/index.ts
@@ -30,23 +30,27 @@ export default class AppTwoStepVerificationTab extends SliderSuperTab {
const doc = appStickersManager.getAnimatedEmojiSticker(emoji);
const stickerContainer = document.createElement('div');
- wrapSticker({
- doc,
- div: stickerContainer,
- loop: false,
- play: true,
- width: 168,
- height: 168,
- emoji
- }).then(() => {
- // this.animation = player;
- });
+ if(doc) {
+ wrapSticker({
+ doc,
+ div: stickerContainer,
+ loop: false,
+ play: true,
+ width: 168,
+ height: 168,
+ emoji
+ }).then(() => {
+ // this.animation = player;
+ });
+ } else {
+ stickerContainer.classList.add('media-sticker-wrapper');
+ }
section.content.append(stickerContainer);
const c = section.generateContentElement();
if(this.state.pFlags.has_password) {
- section.caption.innerHTML = 'You have enabled Two-Step verification.
You\'ll need the password you set up here to log in to your Telegram account';
+ section.caption.innerHTML = 'You have enabled Two-Step verification.
You\'ll need the password you set up here to log in to your Telegram account.';
const btnChangePassword = Button('btn-primary btn-transparent', {icon: 'edit', text: 'Change Password'});
const btnDisablePassword = Button('btn-primary btn-transparent', {icon: 'passwordoff', text: 'Turn Password Off'});
@@ -78,8 +82,13 @@ export default class AppTwoStepVerificationTab extends SliderSuperTab {
} else {
section.caption.innerHTML = 'You can set a password that will be required when you log in on a new device in addition to the code you get in the SMS.';
- const btnSetPassword = Button('btn-primary', {text: 'SET PASSWORD'});
- c.append(btnSetPassword);
+ const inputWrapper = document.createElement('div');
+ inputWrapper.classList.add('input-wrapper');
+
+ const btnSetPassword = Button('btn-primary btn-color-primary', {text: 'SET PASSWORD'});
+
+ inputWrapper.append(btnSetPassword);
+ c.append(inputWrapper);
attachClickEvent(btnSetPassword, (e) => {
const tab = new AppTwoStepVerificationEnterPasswordTab(this.slider);
diff --git a/src/components/sidebarLeft/tabs/2fa/passwordSet.ts b/src/components/sidebarLeft/tabs/2fa/passwordSet.ts
new file mode 100644
index 00000000..5f9357bf
--- /dev/null
+++ b/src/components/sidebarLeft/tabs/2fa/passwordSet.ts
@@ -0,0 +1,61 @@
+import { SettingSection } from "../..";
+import { attachClickEvent } from "../../../../helpers/dom";
+import appStickersManager from "../../../../lib/appManagers/appStickersManager";
+import Button from "../../../button";
+import SidebarSlider, { SliderSuperTab } from "../../../slider";
+import { wrapSticker } from "../../../wrappers";
+
+export default class AppTwoStepVerificationSetTab extends SliderSuperTab {
+ constructor(slider: SidebarSlider) {
+ super(slider, true);
+ }
+
+ protected init() {
+ this.container.classList.add('two-step-verification', 'two-step-verification-set');
+ this.title.innerHTML = 'Password Set!';
+
+ const section = new SettingSection({
+ caption: 'This password will be required when you log in on a new device in addition to the code you get via SMS.',
+ noDelimiter: true
+ });
+
+ const emoji = '🥳';
+ const doc = appStickersManager.getAnimatedEmojiSticker(emoji);
+ const stickerContainer = document.createElement('div');
+
+ if(doc) {
+ wrapSticker({
+ doc,
+ div: stickerContainer,
+ loop: false,
+ play: true,
+ width: 160,
+ height: 160,
+ emoji
+ }).then(() => {
+ // this.animation = player;
+ });
+ } else {
+ stickerContainer.classList.add('media-sticker-wrapper');
+ }
+
+ section.content.append(stickerContainer);
+
+ const inputContent = section.generateContentElement();
+
+ const inputWrapper = document.createElement('div');
+ inputWrapper.classList.add('input-wrapper');
+
+ const btnReturn = Button('btn-primary btn-color-primary', {text: 'RETURN TO SETTINGS'});
+
+ attachClickEvent(btnReturn, (e) => {
+
+ });
+
+ inputWrapper.append(btnReturn);
+
+ inputContent.append(inputWrapper);
+
+ this.scrollable.container.append(section.container);
+ }
+}
diff --git a/src/components/sidebarLeft/tabs/2fa/reEnterPassword.ts b/src/components/sidebarLeft/tabs/2fa/reEnterPassword.ts
index decdff00..100802d9 100644
--- a/src/components/sidebarLeft/tabs/2fa/reEnterPassword.ts
+++ b/src/components/sidebarLeft/tabs/2fa/reEnterPassword.ts
@@ -19,7 +19,7 @@ export default class AppTwoStepVerificationReEnterPasswordTab extends SliderSupe
}
protected init() {
- this.container.classList.add('two-step-verification-enter-password', 'two-step-verification-re-enter-password');
+ this.container.classList.add('two-step-verification', 'two-step-verification-enter-password', 'two-step-verification-re-enter-password');
this.title.innerHTML = 'Re-Enter your Password';
const section = new SettingSection({
@@ -37,7 +37,7 @@ export default class AppTwoStepVerificationReEnterPasswordTab extends SliderSupe
const monkey = new TrackingMonkey(passwordInputField, 157);
monkey.load();
- const btnContinue = Button('btn-primary', {text: 'CONTINUE'});
+ const btnContinue = Button('btn-primary btn-color-primary', {text: 'CONTINUE'});
inputWrapper.append(passwordInputField.container, btnContinue);
section.content.append(monkey.container, inputWrapper);
diff --git a/src/components/sidebarLeft/tabs/addMembers.ts b/src/components/sidebarLeft/tabs/addMembers.ts
index 61e9b0d2..f86d7f89 100644
--- a/src/components/sidebarLeft/tabs/addMembers.ts
+++ b/src/components/sidebarLeft/tabs/addMembers.ts
@@ -12,7 +12,7 @@ export default class AppAddMembersTab extends SliderSuperTab {
private skippable: boolean;
constructor(slider: SidebarSlider) {
- super(slider);
+ super(slider, true);
}
protected init() {
@@ -44,13 +44,6 @@ export default class AppAddMembersTab extends SliderSuperTab {
});
}
- public onCloseAfterTimeout() {
- if(this.selector) {
- this.selector.container.remove();
- this.selector = null;
- }
- }
-
public open(options: {
title: string,
placeholder: string,
@@ -67,7 +60,6 @@ export default class AppAddMembersTab extends SliderSuperTab {
this.takeOut = options.takeOut;
this.skippable = options.skippable;
- this.onCloseAfterTimeout();
this.selector = new AppSelectPeers({
appendTo: this.content,
onChange: this.skippable ? null : (length) => {
diff --git a/src/components/sidebarLeft/tabs/archivedTab.ts b/src/components/sidebarLeft/tabs/archivedTab.ts
index fd025317..b201f44d 100644
--- a/src/components/sidebarLeft/tabs/archivedTab.ts
+++ b/src/components/sidebarLeft/tabs/archivedTab.ts
@@ -1,23 +1,27 @@
import appDialogsManager from "../../../lib/appManagers/appDialogsManager";
-import Scrollable from "../../scrollable";
-import { SliderTab } from "../../slider";
+import SidebarSlider, { SliderSuperTab } from "../../slider";
-export default class AppArchivedTab implements SliderTab {
- public container = document.getElementById('chats-archived-container') as HTMLDivElement;
- public chatList = document.getElementById('dialogs-archived') as HTMLUListElement;
- public scroll: Scrollable = null;
+export default class AppArchivedTab extends SliderSuperTab {
public loadedAll: boolean;
public loadDialogsPromise: Promise;
public wasFilterId: number;
+ constructor(slider: SidebarSlider) {
+ super(slider, true);
+ }
+
init() {
- this.scroll = new Scrollable(this.container, 'CLA', 500);
- this.scroll.container.addEventListener('scroll', appDialogsManager.onChatsRegularScroll);
- this.scroll.setVirtualContainer(this.chatList);
- this.scroll.onScrolledBottom = appDialogsManager.onChatsScroll;
+ this.container.id = 'chats-archived-container';
+ this.title.innerHTML = 'Archived Chats';
+
+ //this.scrollable = new Scrollable(this.container, 'CLA', 500);
+ this.scrollable.append(appDialogsManager.chatListArchived);
+ this.scrollable.container.addEventListener('scroll', appDialogsManager.onChatsRegularScroll);
+ this.scrollable.setVirtualContainer(appDialogsManager.chatListArchived);
+ this.scrollable.onScrolledBottom = appDialogsManager.onChatsScroll;
///this.scroll.attachSentinels();
- appDialogsManager.setListClickListener(this.chatList, null, true);
+ appDialogsManager.setListClickListener(appDialogsManager.chatListArchived, null, true);
window.addEventListener('resize', () => {
setTimeout(appDialogsManager.scroll.checkForTriggers, 0);
@@ -31,9 +35,11 @@ export default class AppArchivedTab implements SliderTab {
}
this.wasFilterId = appDialogsManager.filterId;
- appDialogsManager.scroll = this.scroll;
+ appDialogsManager.scroll = this.scrollable;
appDialogsManager.filterId = 1;
appDialogsManager.onTabChange();
+
+ return super.onOpen();
}
// вообще, так делать нельзя, но нет времени чтобы переделать главный чатлист на слайд...
@@ -48,6 +54,7 @@ export default class AppArchivedTab implements SliderTab {
}
onCloseAfterTimeout() {
- this.chatList.innerHTML = '';
+ appDialogsManager.chatListArchived.innerHTML = '';
+ return super.onCloseAfterTimeout();
}
}
diff --git a/src/components/sidebarLeft/tabs/chatFolders.ts b/src/components/sidebarLeft/tabs/chatFolders.ts
index 2dfebca4..5c61fbb4 100644
--- a/src/components/sidebarLeft/tabs/chatFolders.ts
+++ b/src/components/sidebarLeft/tabs/chatFolders.ts
@@ -1,17 +1,18 @@
-import { SliderTab, SliderSuperTab } from "../../slider";
+import SidebarSlider, { SliderSuperTab } from "../../slider";
import lottieLoader, { RLottiePlayer } from "../../../lib/lottieLoader";
import { RichTextProcessor } from "../../../lib/richtextprocessor";
import { cancelEvent, positionElementByIndex } from "../../../helpers/dom";
import { ripple } from "../../ripple";
import { toast } from "../../toast";
-import type { ApiManagerProxy } from "../../../lib/mtproto/mtprotoworker";
-import type { AppMessagesManager } from "../../../lib/appManagers/appMessagesManager";
import type { MyDialogFilter } from "../../../lib/storages/filters";
-import type { AppPeersManager } from "../../../lib/appManagers/appPeersManager";
-import type { AppSidebarLeft } from "..";
import type { DialogFilterSuggested, DialogFilter } from "../../../layer";
import type _rootScope from "../../../lib/rootScope";
import Button from "../../button";
+import appMessagesManager from "../../../lib/appManagers/appMessagesManager";
+import appPeersManager from "../../../lib/appManagers/appPeersManager";
+import apiManager from "../../../lib/mtproto/mtprotoworker";
+import rootScope from "../../../lib/rootScope";
+import AppEditFolderTab from "./editFolder";
export default class AppChatFoldersTab extends SliderSuperTab {
public createFolderBtn: HTMLElement;
@@ -22,8 +23,8 @@ export default class AppChatFoldersTab extends SliderSuperTab {
private filtersRendered: {[filterId: number]: HTMLElement} = {};
- constructor(private appMessagesManager: AppMessagesManager, private appPeersManager: AppPeersManager, private appSidebarLeft: AppSidebarLeft, private apiManager: ApiManagerProxy, private rootScope: typeof _rootScope) {
- super(appSidebarLeft);
+ constructor(slider: SidebarSlider) {
+ super(slider, true);
}
private renderFolder(dialogFilter: DialogFilterSuggested | DialogFilter | MyDialogFilter, container?: HTMLElement, div: HTMLElement = document.createElement('div')) {
@@ -40,7 +41,7 @@ export default class AppChatFoldersTab extends SliderSuperTab {
const filterId = filter.id;
if(!this.filtersRendered.hasOwnProperty(filter.id)) {
div.addEventListener('click', () => {
- this.appSidebarLeft.editFolderTab.open(this.appMessagesManager.filtersStorage.filters[filterId]);
+ new AppEditFolderTab(this.slider).open(appMessagesManager.filtersStorage.filters[filterId]);
});
}
@@ -65,11 +66,11 @@ export default class AppChatFoldersTab extends SliderSuperTab {
else if(pFlags.exclude_archived) description += 'Unarchived';
d.push(description);
} else {
- const folder = this.appMessagesManager.dialogsStorage.getFolder(filter.id);
+ const folder = appMessagesManager.dialogsStorage.getFolder(filter.id);
let chats = 0, channels = 0, groups = 0;
for(const dialog of folder) {
- if(this.appPeersManager.isAnyGroup(dialog.peerId)) groups++;
- else if(this.appPeersManager.isBroadcast(dialog.peerId)) channels++;
+ if(appPeersManager.isAnyGroup(dialog.peerId)) groups++;
+ else if(appPeersManager.isBroadcast(dialog.peerId)) channels++;
else chats++;
}
@@ -109,7 +110,7 @@ export default class AppChatFoldersTab extends SliderSuperTab {
caption.classList.add('caption');
caption.innerHTML = `Create folders for different groups of chats
and quickly switch between them.`;
- this.createFolderBtn = Button('btn-primary btn-create-folder', {
+ this.createFolderBtn = Button('btn-primary btn-color-primary btn-create-folder', {
text: 'Create Folder',
icon: 'add'
});
@@ -139,7 +140,7 @@ export default class AppChatFoldersTab extends SliderSuperTab {
if(Object.keys(this.filtersRendered).length >= 10) {
toast('Sorry, you can\'t create more folders.');
} else {
- this.appSidebarLeft.editFolderTab.open();
+ new AppEditFolderTab(this.slider).open();
}
});
@@ -153,13 +154,13 @@ export default class AppChatFoldersTab extends SliderSuperTab {
this.animation = player;
});
- this.appMessagesManager.filtersStorage.getDialogFilters().then(filters => {
+ appMessagesManager.filtersStorage.getDialogFilters().then(filters => {
for(const filter of filters) {
this.renderFolder(filter, this.foldersContainer);
}
});
- this.rootScope.on('filter_update', (e) => {
+ rootScope.on('filter_update', (e) => {
const filter = e;
if(this.filtersRendered.hasOwnProperty(filter.id)) {
this.renderFolder(filter, null, this.filtersRendered[filter.id]);
@@ -170,7 +171,7 @@ export default class AppChatFoldersTab extends SliderSuperTab {
this.getSuggestedFilters();
});
- this.rootScope.on('filter_delete', (e) => {
+ rootScope.on('filter_delete', (e) => {
const filter = e;
if(this.filtersRendered.hasOwnProperty(filter.id)) {
/* for(const suggested of this.suggestedFilters) {
@@ -185,7 +186,7 @@ export default class AppChatFoldersTab extends SliderSuperTab {
}
});
- this.rootScope.on('filter_order', (e) => {
+ rootScope.on('filter_order', (e) => {
const order = e;
order.forEach((filterId, idx) => {
const div = this.filtersRendered[filterId];
@@ -197,14 +198,14 @@ export default class AppChatFoldersTab extends SliderSuperTab {
}
private getSuggestedFilters() {
- this.apiManager.invokeApi('messages.getSuggestedDialogFilters').then(suggestedFilters => {
+ apiManager.invokeApi('messages.getSuggestedDialogFilters').then(suggestedFilters => {
this.suggestedContainer.style.display = suggestedFilters.length ? '' : 'none';
Array.from(this.suggestedContainer.children).slice(1).forEach(el => el.remove());
suggestedFilters.forEach(filter => {
const div = this.renderFolder(filter);
const button = document.createElement('button');
- button.classList.add('btn-primary');
+ button.classList.add('btn-primary', 'btn-color-primary');
button.innerText = 'Add';
div.append(button);
this.suggestedContainer.append(div);
@@ -219,7 +220,7 @@ export default class AppChatFoldersTab extends SliderSuperTab {
button.setAttribute('disabled', 'true');
- this.appMessagesManager.filtersStorage.createDialogFilter(filter.filter as any).then(bool => {
+ appMessagesManager.filtersStorage.createDialogFilter(filter.filter as any).then(bool => {
if(bool) {
div.remove();
}
diff --git a/src/components/sidebarLeft/tabs/contacts.ts b/src/components/sidebarLeft/tabs/contacts.ts
index e347b0ba..fce289e9 100644
--- a/src/components/sidebarLeft/tabs/contacts.ts
+++ b/src/components/sidebarLeft/tabs/contacts.ts
@@ -1,52 +1,52 @@
-import { SliderTab } from "../../slider";
-import Scrollable from "../../scrollable";
+import SidebarSlider, { SliderSuperTab } from "../../slider";
import appDialogsManager from "../../../lib/appManagers/appDialogsManager";
import appUsersManager from "../../../lib/appManagers/appUsersManager";
import appPhotosManager from "../../../lib/appManagers/appPhotosManager";
-import appSidebarLeft, { AppSidebarLeft } from "..";
import rootScope from "../../../lib/rootScope";
import InputSearch from "../../inputSearch";
// TODO: поиск по людям глобальный, если не нашло в контактах никого
-export default class AppContactsTab implements SliderTab {
- private container: HTMLElement;
+export default class AppContactsTab extends SliderSuperTab {
private list: HTMLUListElement;
- private scrollable: Scrollable;
private promise: Promise;
private inputSearch: InputSearch;
+ private alive = true;
+
+ constructor(slider: SidebarSlider) {
+ super(slider, true);
+ }
init() {
- this.container = document.getElementById('contacts-container');
- this.list = this.container.querySelector('#contacts');
+ this.container.id = 'contacts-container';
+
+ this.list = document.createElement('ul');
+ this.list.id = 'contacts';
+ this.list.classList.add('contacts-container');
appDialogsManager.setListClickListener(this.list, () => {
(this.container.querySelector('.sidebar-close-button') as HTMLElement).click();
}, undefined, true);
- this.scrollable = new Scrollable(this.list.parentElement);
-
this.inputSearch = new InputSearch('Search', (value) => {
this.list.innerHTML = '';
this.openContacts(value);
});
- this.container.firstElementChild.append(this.inputSearch.container);
+ this.title.replaceWith(this.inputSearch.container);
+
+ this.scrollable.append(this.list);
// preload contacts
// appUsersManager.getContacts();
}
- // need to clear, and left 1 page for smooth slide
- public onClose() {
+ onClose() {
+ this.alive = false;
+ /* // need to clear, and left 1 page for smooth slide
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 = '';
- this.inputSearch.value = '';
+ (Array.from(this.list.children) as HTMLElement[]).slice(pageCount).forEach(el => el.remove()); */
}
public openContacts(query?: string) {
@@ -55,18 +55,14 @@ export default class AppContactsTab implements SliderTab {
this.init = null;
}
- if(appSidebarLeft.historyTabIds.indexOf(AppSidebarLeft.SLIDERITEMSIDS.contacts) === -1) {
- appSidebarLeft.selectTab(AppSidebarLeft.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] !== AppSidebarLeft.SLIDERITEMSIDS.contacts) {
- console.warn('user closed contacts before it\'s loaded');
+ if(!this.alive) {
+ //console.warn('user closed contacts before it\'s loaded');
return;
}
@@ -118,4 +114,9 @@ export default class AppContactsTab implements SliderTab {
};
});
}
+
+ public open() {
+ this.openContacts();
+ return super.open();
+ }
}
\ No newline at end of file
diff --git a/src/components/sidebarLeft/tabs/editFolder.ts b/src/components/sidebarLeft/tabs/editFolder.ts
index aee48fbd..e693ea46 100644
--- a/src/components/sidebarLeft/tabs/editFolder.ts
+++ b/src/components/sidebarLeft/tabs/editFolder.ts
@@ -1,20 +1,18 @@
-import appSidebarLeft, { AppSidebarLeft } from "..";
import { deepEqual, copy } from "../../../helpers/object";
import appDialogsManager from "../../../lib/appManagers/appDialogsManager";
import { MyDialogFilter as DialogFilter } from "../../../lib/storages/filters";
import lottieLoader, { RLottiePlayer } from "../../../lib/lottieLoader";
-import { parseMenuButtonsTo } from "../../misc";
import { ripple } from "../../ripple";
-import { SliderTab, SliderSuperTab } from "../../slider";
+import SidebarSlider, { SliderSuperTab } from "../../slider";
import { toast } from "../../toast";
import appMessagesManager from "../../../lib/appManagers/appMessagesManager";
-import { attachClickEvent } from "../../../helpers/dom";
import InputField from "../../inputField";
import RichTextProcessor from "../../../lib/richtextprocessor";
import ButtonIcon from "../../buttonIcon";
import ButtonMenuToggle from "../../buttonMenuToggle";
import { ButtonMenuItemOptions } from "../../buttonMenu";
import Button from "../../button";
+import AppIncludedChatsTab from "./includedChats";
const MAX_FOLDER_NAME_LENGTH = 12;
@@ -36,8 +34,8 @@ export default class AppEditFolderTab extends SliderSuperTab {
private type: 'edit' | 'create';
- constructor(appSidebarLeft: AppSidebarLeft) {
- super(appSidebarLeft);
+ constructor(slider: SidebarSlider) {
+ super(slider, true);
}
protected init() {
@@ -159,11 +157,11 @@ export default class AppEditFolderTab extends SliderSuperTab {
const excludedFlagsContainer = this.exclude_peers.querySelector('.folder-categories');
includedFlagsContainer.firstElementChild.addEventListener('click', () => {
- appSidebarLeft.includedChatsTab.open(this.filter, 'included');
+ new AppIncludedChatsTab(this.slider).open(this.filter, 'included', this);
});
excludedFlagsContainer.firstElementChild.addEventListener('click', () => {
- appSidebarLeft.includedChatsTab.open(this.filter, 'excluded');
+ new AppIncludedChatsTab(this.slider).open(this.filter, 'excluded', this);
});
lottieLoader.loadAnimationFromURL({
@@ -228,10 +226,8 @@ export default class AppEditFolderTab extends SliderSuperTab {
if(this.animation) {
this.animation.restart();
}
- }
- onCloseAfterTimeout() {
- Array.from(this.container.querySelectorAll('ul, .show-more')).forEach(el => el.remove());
+ return super.onOpen();
}
private onCreateOpen() {
@@ -318,7 +314,7 @@ export default class AppEditFolderTab extends SliderSuperTab {
setFilter(filter: DialogFilter, firstTime: boolean) {
// cleanup
- this.onCloseAfterTimeout();
+ Array.from(this.container.querySelectorAll('ul, .show-more')).forEach(el => el.remove());
if(firstTime) {
this.originalFilter = filter;
diff --git a/src/components/sidebarLeft/tabs/editProfile.ts b/src/components/sidebarLeft/tabs/editProfile.ts
index 8f222150..524982cf 100644
--- a/src/components/sidebarLeft/tabs/editProfile.ts
+++ b/src/components/sidebarLeft/tabs/editProfile.ts
@@ -40,7 +40,7 @@ export default class AppEditProfileTab extends SliderSuperTab {
};
constructor(slider: SidebarSlider) {
- super(slider);
+ super(slider, true);
}
protected init() {
@@ -282,7 +282,6 @@ export default class AppEditProfileTab extends SliderSuperTab {
};
onCloseAfterTimeout() {
- this.nextBtn.classList.remove('is-visible');
- this.firstNameInputField.value = this.lastNameInputField.value = this.bioInputField.value = '';
+ super.onCloseAfterTimeout();
}
}
\ No newline at end of file
diff --git a/src/components/sidebarLeft/tabs/generalSettings.ts b/src/components/sidebarLeft/tabs/generalSettings.ts
index fb4d1a67..ac865c0b 100644
--- a/src/components/sidebarLeft/tabs/generalSettings.ts
+++ b/src/components/sidebarLeft/tabs/generalSettings.ts
@@ -55,7 +55,7 @@ export class RangeSettingSelector {
export default class AppGeneralSettingsTab extends SliderSuperTab {
constructor(appSidebarLeft: AppSidebarLeft) {
- super(appSidebarLeft);
+ super(appSidebarLeft, true);
}
init() {
diff --git a/src/components/sidebarLeft/tabs/includedChats.ts b/src/components/sidebarLeft/tabs/includedChats.ts
index bc2509a8..de85c3a4 100644
--- a/src/components/sidebarLeft/tabs/includedChats.ts
+++ b/src/components/sidebarLeft/tabs/includedChats.ts
@@ -1,6 +1,5 @@
-import { SliderTab, SliderSuperTab } from "../../slider";
+import SidebarSlider, { SliderSuperTab } from "../../slider";
import AppSelectPeers from "../../appSelectPeers";
-import appSidebarLeft, { AppSidebarLeft } from "..";
import appDialogsManager from "../../../lib/appManagers/appDialogsManager";
import appPeersManager from "../../../lib/appManagers/appPeersManager";
import appUsersManager from "../../../lib/appManagers/appUsersManager";
@@ -11,8 +10,10 @@ import ButtonIcon from "../../buttonIcon";
import { fastRaf } from "../../../helpers/schedulers";
import CheckboxField from "../../checkbox";
import Button from "../../button";
+import AppEditFolderTab from "./editFolder";
export default class AppIncludedChatsTab extends SliderSuperTab {
+ private editFolderTab: AppEditFolderTab;
private confirmBtn: HTMLElement;
private selector: AppSelectPeers;
@@ -20,8 +21,8 @@ export default class AppIncludedChatsTab extends SliderSuperTab {
private filter: DialogFilter;
private originalFilter: DialogFilter;
- constructor(appSidebarLeft: AppSidebarLeft) {
- super(appSidebarLeft);
+ constructor(slider: SidebarSlider) {
+ super(slider, true);
}
init() {
@@ -92,7 +93,7 @@ export default class AppIncludedChatsTab extends SliderSuperTab {
this.filter[this.type === 'included' ? 'include_peers' : 'exclude_peers'] = peers;
//this.filter.pinned_peers = this.filter.pinned_peers.filter(peerId => this.filter.include_peers.includes(peerId));
- appSidebarLeft.editFolderTab.setFilter(this.filter, false);
+ this.editFolderTab.setFilter(this.filter, false);
this.close();
});
}
@@ -233,6 +234,8 @@ export default class AppIncludedChatsTab extends SliderSuperTab {
(categories.querySelector(`[data-peer-id="${flag}"]`) as HTMLElement).click();
}
}
+
+ return super.onOpen();
}
onSelectChange = (length: number) => {
@@ -247,15 +250,18 @@ export default class AppIncludedChatsTab extends SliderSuperTab {
this.selector.container.remove();
this.selector = null;
}
+
+ return super.onCloseAfterTimeout();
}
/**
* Do not ignore arguments!
*/
- public open(filter?: DialogFilter, type?: 'included' | 'excluded') {
+ public open(filter?: DialogFilter, type?: 'included' | 'excluded', editFolderTab?: AppIncludedChatsTab['editFolderTab']) {
this.originalFilter = filter;
this.filter = copy(this.originalFilter);
this.type = type;
+ this.editFolderTab = editFolderTab;
return super.open();
}
diff --git a/src/components/sidebarLeft/tabs/newChannel.ts b/src/components/sidebarLeft/tabs/newChannel.ts
index 125483bc..9295c342 100644
--- a/src/components/sidebarLeft/tabs/newChannel.ts
+++ b/src/components/sidebarLeft/tabs/newChannel.ts
@@ -5,6 +5,7 @@ import Button from "../../button";
import InputField from "../../inputField";
import { SliderSuperTab } from "../../slider";
import AvatarEdit from "../../avatarEdit";
+import AppAddMembersTab from "./addMembers";
export default class AppNewChannelTab extends SliderSuperTab {
private uploadAvatar: () => Promise = null;
@@ -15,7 +16,7 @@ export default class AppNewChannelTab extends SliderSuperTab {
private avatarEdit: AvatarEdit;
constructor(appSidebarLeft: AppSidebarLeft) {
- super(appSidebarLeft);
+ super(appSidebarLeft, true);
}
protected init() {
@@ -68,8 +69,8 @@ export default class AppNewChannelTab extends SliderSuperTab {
});
}
- appSidebarLeft.removeTabFromHistory(this.id);
- appSidebarLeft.addMembersTab.open({
+ appSidebarLeft.removeTabFromHistory(this);
+ new AppAddMembersTab(this.slider).open({
peerId: channelId,
type: 'channel',
skippable: true,
@@ -92,5 +93,6 @@ export default class AppNewChannelTab extends SliderSuperTab {
this.channelNameInputField.value = '';
this.channelDescriptionInputField.value = '';
this.nextBtn.disabled = false;
+ return super.onCloseAfterTimeout();
}
-}
\ No newline at end of file
+}
diff --git a/src/components/sidebarLeft/tabs/newGroup.ts b/src/components/sidebarLeft/tabs/newGroup.ts
index bd2d9fe9..762f2745 100644
--- a/src/components/sidebarLeft/tabs/newGroup.ts
+++ b/src/components/sidebarLeft/tabs/newGroup.ts
@@ -18,7 +18,7 @@ export default class AppNewGroupTab extends SliderSuperTab {
private groupNameInputField: InputField;
constructor(appSidebarLeft: AppSidebarLeft) {
- super(appSidebarLeft);
+ super(appSidebarLeft, true);
}
protected init() {
@@ -57,7 +57,7 @@ export default class AppNewGroupTab extends SliderSuperTab {
});
}
- appSidebarLeft.removeTabFromHistory(this.id);
+ appSidebarLeft.removeTabFromHistory(this);
appSidebarLeft.selectTab(0);
});
});
diff --git a/src/components/sidebarLeft/tabs/privacyAndSecurity.ts b/src/components/sidebarLeft/tabs/privacyAndSecurity.ts
index 68dffe83..c88dc26a 100644
--- a/src/components/sidebarLeft/tabs/privacyAndSecurity.ts
+++ b/src/components/sidebarLeft/tabs/privacyAndSecurity.ts
@@ -10,7 +10,7 @@ import AppTwoStepVerificationEnterPasswordTab from "./2fa/enterPassword";
export default class AppPrivacyAndSecurityTab extends SliderSuperTab {
constructor(slider: SidebarSlider) {
- super(slider);
+ super(slider, true);
}
protected init() {
@@ -79,7 +79,9 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab {
const numberVisibilityRow = rowsByKeys['inputPrivacyKeyPhoneNumber'] = new Row({
title: 'Who can see my phone number?',
subtitle: 'My Contacts',
- navigationTab: new AppPrivacyPhoneNumberTab(this.slider)
+ clickable: () => {
+ new AppPrivacyPhoneNumberTab(this.slider).open()
+ }
});
const lastSeenTimeRow = rowsByKeys['inputPrivacyKeyStatusTimestamp'] = new Row({
@@ -121,4 +123,4 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab {
container.append(numberVisibilityRow.container, lastSeenTimeRow.container, photoVisibilityRow.container, linkAccountRow.container, groupChatsAddRow.container);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/components/sidebarLeft/tabs/settings.ts b/src/components/sidebarLeft/tabs/settings.ts
index 6d5cadcb..4c403e23 100644
--- a/src/components/sidebarLeft/tabs/settings.ts
+++ b/src/components/sidebarLeft/tabs/settings.ts
@@ -1,10 +1,13 @@
import SidebarSlider, { SliderSuperTab } from "../../slider";
import AvatarElement from "../../avatar";
import apiManager from "../../../lib/mtproto/mtprotoworker";
-import appSidebarLeft, { AppSidebarLeft } from "..";
import appUsersManager from "../../../lib/appManagers/appUsersManager";
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 AppMediaViewer from "../../appMediaViewerNew";
export default class AppSettingsTab extends SliderSuperTab {
@@ -22,7 +25,7 @@ export default class AppSettingsTab extends SliderSuperTab {
} = {} as any;
constructor(slider: SidebarSlider) {
- super(slider);
+ super(slider, true);
}
init() {
@@ -110,20 +113,21 @@ export default class AppSettingsTab extends SliderSuperTab {
}); */
this.buttons.edit.addEventListener('click', () => {
- appSidebarLeft.editProfileTab.fillElements();
- appSidebarLeft.editProfileTab.open();
+ const tab = new AppEditProfileTab(this.slider);
+ tab.fillElements();
+ tab.open();
});
this.buttons.folders.addEventListener('click', () => {
- appSidebarLeft.chatFoldersTab.open();
+ new AppChatFoldersTab(this.slider).open();
});
this.buttons.general.addEventListener('click', () => {
- appSidebarLeft.generalSettingsTab.open();
+ new AppGeneralSettingsTab(this.slider as any).open();
});
this.buttons.privacy.addEventListener('click', () => {
- appSidebarLeft.privacyAndSecurityTab.open();
+ new AppPrivacyAndSecurityTab(this.slider).open();
});
}
@@ -142,9 +146,6 @@ export default class AppSettingsTab extends SliderSuperTab {
}
this.fillElements();
+ return super.onOpen();
}
-
- onClose() {
-
- }
-}
\ No newline at end of file
+}
diff --git a/src/components/sidebarRight/index.ts b/src/components/sidebarRight/index.ts
index 58cc223e..eee758dc 100644
--- a/src/components/sidebarRight/index.ts
+++ b/src/components/sidebarRight/index.ts
@@ -34,13 +34,13 @@ export class AppSidebarRight extends SidebarSlider {
constructor() {
super({
sidebarEl: document.getElementById('column-right') as HTMLElement,
- tabs: {
- [AppSidebarRight.SLIDERITEMSIDS.sharedMedia]: sharedMediaTab,
- [AppSidebarRight.SLIDERITEMSIDS.search]: searchTab,
- [AppSidebarRight.SLIDERITEMSIDS.stickers]: stickersTab,
- [AppSidebarRight.SLIDERITEMSIDS.pollResults]: pollResultsTab,
- [AppSidebarRight.SLIDERITEMSIDS.gifs]: gifsTab
- },
+ tabs: new Map([
+ [AppSidebarRight.SLIDERITEMSIDS.sharedMedia, sharedMediaTab],
+ [AppSidebarRight.SLIDERITEMSIDS.search, searchTab],
+ [AppSidebarRight.SLIDERITEMSIDS.stickers, stickersTab],
+ [AppSidebarRight.SLIDERITEMSIDS.pollResults, pollResultsTab],
+ [AppSidebarRight.SLIDERITEMSIDS.gifs, gifsTab]
+ ] as any[]),
canHideFirst: true,
navigationType: 'right'
});
diff --git a/src/components/sidebarRight/tabs/stickers.ts b/src/components/sidebarRight/tabs/stickers.ts
index c4d9eec1..e39449b2 100644
--- a/src/components/sidebarRight/tabs/stickers.ts
+++ b/src/components/sidebarRight/tabs/stickers.ts
@@ -95,7 +95,7 @@ export default class AppStickersTab implements SliderTab {
`;
const button = document.createElement('button');
- button.classList.add('btn-primary', 'sticker-set-button');
+ button.classList.add('btn-primary', 'btn-color-primary', 'sticker-set-button');
button.innerText = set.installed_date ? 'Added' : 'Add';
// button.style.width = set.installed_date ? '68px' : '52px';
diff --git a/src/components/slider.ts b/src/components/slider.ts
index 03cfa23b..d0030e95 100644
--- a/src/components/slider.ts
+++ b/src/components/slider.ts
@@ -1,93 +1,20 @@
import { attachClickEvent } from "../helpers/dom";
import { horizontalMenu } from "./horizontalMenu";
-import ButtonIcon from "./buttonIcon";
-import Scrollable from "./scrollable";
import { TransitionSlider } from "./transition";
import appNavigationController, { NavigationItem } from "./appNavigationController";
-import { isSafari } from "../helpers/userAgent";
-
-export interface SliderTab {
- onOpen?: () => void,
- onOpenAfterTimeout?: () => void,
- onClose?: () => void,
- onCloseAfterTimeout?: () => void
-}
-
-export class SliderSuperTab implements SliderTab {
- public container: HTMLElement;
-
- public header: HTMLElement;
- public closeBtn: HTMLElement;
- public title: HTMLElement;
-
- public content: HTMLElement;
- public scrollable: Scrollable;
-
- public id: number;
-
- constructor(protected slider: SidebarSlider, protected destroyable = false) {
- this.container = document.createElement('div');
- this.container.classList.add('sidebar-slider-item');
-
- // * Header
- this.header = document.createElement('div');
- this.header.classList.add('sidebar-header');
-
- this.closeBtn = ButtonIcon('arrow_back sidebar-close-button', {noRipple: true});
- this.title = document.createElement('div');
- this.title.classList.add('sidebar-header__title');
- this.header.append(this.closeBtn, this.title);
-
- // * Content
- this.content = document.createElement('div');
- this.content.classList.add('sidebar-content');
-
- this.scrollable = new Scrollable(this.content, undefined, undefined, true);
-
- this.container.append(this.header, this.content);
-
- this.id = this.slider.addTab(this);
- }
-
- public close() {
- return this.slider.closeTab(this.id);
- }
-
- public async open(...args: any[]) {
- if(this.init) {
- const result = this.init();
- this.init = null;
- await (result instanceof Promise ? result : Promise.resolve());
- }
-
- return this.slider.selectTab(this);
- }
-
- protected init(): Promise | any {
-
- }
-
- // * fix incompability
- public onOpen() {
-
- }
-
- public onCloseAfterTimeout() {
- if(this.destroyable) { // ! WARNING, пока что это будет работать только с самой последней внутренней вкладкой !
- delete this.slider.tabs[this.id];
- this.container.remove();
- }
- }
-}
+import SliderSuperTab, { SliderTab } from "./sliderTab";
const TRANSITION_TIME = 250;
+export type {SliderTab};
+export {SliderSuperTab};
+
export default class SidebarSlider {
protected _selectTab: ReturnType;
- public historyTabIds: number[] = [];
+ public historyTabIds: (number | SliderSuperTab)[] = []; // * key is any, since right sidebar is ugly nowz
public tabsContainer: HTMLElement;
public sidebarEl: HTMLElement;
- public tabs: {[id: number]: SliderTab} = {};
+ public tabs: Map; // * key is any, since right sidebar is ugly now
private canHideFirst = false;
private navigationType: NavigationItem['type']
@@ -102,6 +29,10 @@ export default class SidebarSlider {
this[i] = options[i];
}
+ if(!this.tabs) {
+ this.tabs = new Map();
+ }
+
this.tabsContainer = this.sidebarEl.querySelector('.sidebar-slider');
this._selectTab = TransitionSlider(this.tabsContainer, 'navigation', TRANSITION_TIME);
if(!this.canHideFirst) {
@@ -118,28 +49,30 @@ export default class SidebarSlider {
// this.closeTab();
};
- public closeTab = (tabId?: number, animate?: boolean) => {
- if(tabId !== undefined && this.historyTabIds[this.historyTabIds.length - 1] !== tabId) {
+ public closeTab = (id?: number | SliderSuperTab, animate?: boolean) => {
+ if(id !== undefined && this.historyTabIds[this.historyTabIds.length - 1] !== id) {
return false;
}
//console.log('sidebar-close-button click:', this.historyTabIDs);
const closingId = this.historyTabIds.pop(); // pop current
this.onCloseTab(closingId, animate);
- this._selectTab(this.historyTabIds[this.historyTabIds.length - 1] ?? (this.canHideFirst ? -1 : 0), animate);
+
+ const tab = this.historyTabIds[this.historyTabIds.length - 1];
+ this._selectTab(tab !== undefined ? (tab instanceof SliderSuperTab ? tab.container : tab) : (this.canHideFirst ? -1 : 0), animate);
return true;
};
public selectTab(id: number | SliderSuperTab): boolean {
- if(id instanceof SliderSuperTab) {
+ /* if(id instanceof SliderSuperTab) {
id = id.id;
- }
+ } */
if(this.historyTabIds[this.historyTabIds.length - 1] === id) {
return false;
}
- const tab = this.tabs[id];
+ const tab: SliderTab = id instanceof SliderSuperTab ? id : this.tabs.get(id);
if(tab) {
if(tab.onOpen) {
tab.onOpen();
@@ -163,17 +96,17 @@ export default class SidebarSlider {
//}
this.historyTabIds.push(id);
- this._selectTab(id);
+ this._selectTab(id instanceof SliderSuperTab ? id.container : id);
return true;
}
- public removeTabFromHistory(id: number) {
+ public removeTabFromHistory(id: number | SliderSuperTab) {
this.historyTabIds.findAndSplice(i => i === id);
this.onCloseTab(id, undefined);
}
- public onCloseTab(id: number, animate: boolean) {
- let tab = this.tabs[id];
+ public onCloseTab(id: number | SliderSuperTab, animate: boolean) {
+ const tab: SliderTab = id instanceof SliderSuperTab ? id : this.tabs.get(id);
if(tab) {
if(tab.onClose) {
tab.onClose();
@@ -188,20 +121,12 @@ export default class SidebarSlider {
}
public addTab(tab: SliderSuperTab) {
- let id: number;
- if(tab.container.parentElement) {
- id = Array.from(this.tabsContainer.children).findIndex(el => el === tab.container);
- } else {
- id = this.tabsContainer.childElementCount;
+ if(!tab.container.parentElement) {
this.tabsContainer.append(tab.container);
if(tab.closeBtn) {
tab.closeBtn.addEventListener('click', this.onCloseBtnClick);
}
}
-
- this.tabs[id] = tab;
-
- return id;
}
}
diff --git a/src/components/sliderTab.ts b/src/components/sliderTab.ts
new file mode 100644
index 00000000..c50bcedf
--- /dev/null
+++ b/src/components/sliderTab.ts
@@ -0,0 +1,77 @@
+import ButtonIcon from "./buttonIcon";
+import Scrollable from "./scrollable";
+import SidebarSlider from "./slider";
+
+export interface SliderTab {
+ onOpen?: () => void,
+ onOpenAfterTimeout?: () => void,
+ onClose?: () => void,
+ onCloseAfterTimeout?: () => void
+}
+
+export default class SliderSuperTab implements SliderTab {
+ public container: HTMLElement;
+
+ public header: HTMLElement;
+ public closeBtn: HTMLElement;
+ public title: HTMLElement;
+
+ public content: HTMLElement;
+ public scrollable: Scrollable;
+
+ constructor(protected slider: SidebarSlider, protected destroyable = false) {
+ this.container = document.createElement('div');
+ this.container.classList.add('sidebar-slider-item');
+
+ // * Header
+ this.header = document.createElement('div');
+ this.header.classList.add('sidebar-header');
+
+ this.closeBtn = ButtonIcon('arrow_back sidebar-close-button', {noRipple: true});
+ this.title = document.createElement('div');
+ this.title.classList.add('sidebar-header__title');
+ this.header.append(this.closeBtn, this.title);
+
+ // * Content
+ this.content = document.createElement('div');
+ this.content.classList.add('sidebar-content');
+
+ this.scrollable = new Scrollable(this.content, undefined, undefined, true);
+
+ this.container.append(this.header, this.content);
+
+ this.slider.addTab(this);
+ }
+
+ public close() {
+ return this.slider.closeTab(this);
+ }
+
+ public async open(...args: any[]) {
+ if(this.init) {
+ const result = this.init();
+ this.init = null;
+ if(result instanceof Promise) {
+ await result;
+ }
+ }
+
+ return this.slider.selectTab(this);
+ }
+
+ protected init(): Promise | any {
+
+ }
+
+ // * fix incompability
+ public onOpen() {
+
+ }
+
+ public onCloseAfterTimeout() {
+ if(this.destroyable) { // ! WARNING, пока что это будет работать только с самой последней внутренней вкладкой !
+ this.slider.tabs.delete(this);
+ this.container.remove();
+ }
+ }
+}
diff --git a/src/components/transition.ts b/src/components/transition.ts
index d23cb62a..32892d9c 100644
--- a/src/components/transition.ts
+++ b/src/components/transition.ts
@@ -96,7 +96,7 @@ const Transition = (content: HTMLElement, animationFunction: TransitionFunction,
}
if(onTransitionEnd) {
- onTransitionEnd(selectTab.prevId);
+ onTransitionEnd(selectTab.prevId());
}
content.classList.remove('animating', 'backwards', 'disable-hover');
@@ -109,14 +109,15 @@ const Transition = (content: HTMLElement, animationFunction: TransitionFunction,
id = whichChild(id);
}
- if(id === self.prevId) return false;
+ const prevId = self.prevId();
+ if(id === prevId) return false;
//console.log('selectTab id:', id);
const _from = from;
const to = content.children[id] as HTMLElement;
- if(!rootScope.settings.animationsEnabled || self.prevId === -1) {
+ if(!rootScope.settings.animationsEnabled || prevId === -1) {
animate = false;
}
@@ -129,10 +130,9 @@ const Transition = (content: HTMLElement, animationFunction: TransitionFunction,
content.classList.remove('animating', 'backwards', 'disable-hover');
- self.prevId = id;
from = to;
- if(onTransitionEnd) onTransitionEnd(self.prevId);
+ if(onTransitionEnd) onTransitionEnd(id);
return;
}
@@ -142,7 +142,7 @@ const Transition = (content: HTMLElement, animationFunction: TransitionFunction,
}
content.classList.add('animating', 'disable-hover');
- const toRight = self.prevId < id;
+ const toRight = prevId < id;
content.classList.toggle('backwards', !toRight);
let onTransitionEndCallback: ReturnType;
@@ -196,11 +196,11 @@ const Transition = (content: HTMLElement, animationFunction: TransitionFunction,
}
}
- self.prevId = id;
from = to;
}
- selectTab.prevId = -1;
+ //selectTab.prevId = -1;
+ selectTab.prevId = () => from ? whichChild(from) : -1;
return selectTab;
};
diff --git a/src/helpers/bytes.ts b/src/helpers/bytes.ts
index 21926158..d0c636eb 100644
--- a/src/helpers/bytes.ts
+++ b/src/helpers/bytes.ts
@@ -1,24 +1,23 @@
export function bytesToHex(bytes: ArrayLike) {
bytes = bytes || [];
- var arr = [];
- for(var i = 0; i < bytes.length; i++) {
+ let arr: string[] = [];
+ for(let i = 0; i < bytes.length; ++i) {
arr.push((bytes[i] < 16 ? '0' : '') + (bytes[i] || 0).toString(16));
}
return arr.join('');
}
export function bytesFromHex(hexString: string) {
- var len = hexString.length,
- i;
- var start = 0;
- var bytes = [];
+ const len = hexString.length;
+ let start = 0;
+ let bytes: number[] = [];
- if(hexString.length % 2) {
+ if(len % 2) { // read 0x581 as 0x0581
bytes.push(parseInt(hexString.charAt(0), 16));
- start++;
+ ++start;
}
- for(i = start; i < len; i += 2) {
+ for(let i = start; i < len; i += 2) {
bytes.push(parseInt(hexString.substr(i, 2), 16));
}
@@ -26,24 +25,24 @@ export function bytesFromHex(hexString: string) {
}
export function bytesToBase64(bytes: number[] | Uint8Array) {
- var mod3
- var result = ''
+ let mod3: number;
+ let result = '';
- for (var nLen = bytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) {
- mod3 = nIdx % 3
- nUint24 |= bytes[nIdx] << (16 >>> mod3 & 24)
- if (mod3 === 2 || nLen - nIdx === 1) {
+ for(let nLen = bytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; ++nIdx) {
+ mod3 = nIdx % 3;
+ nUint24 |= bytes[nIdx] << (16 >>> mod3 & 24);
+ if(mod3 === 2 || nLen - nIdx === 1) {
result += String.fromCharCode(
uint6ToBase64(nUint24 >>> 18 & 63),
uint6ToBase64(nUint24 >>> 12 & 63),
uint6ToBase64(nUint24 >>> 6 & 63),
uint6ToBase64(nUint24 & 63)
- )
- nUint24 = 0
+ );
+ nUint24 = 0;
}
}
- return result.replace(/A(?=A$|$)/g, '=')
+ return result.replace(/A(?=A$|$)/g, '=');
}
export function uint6ToBase64(nUint6: number) {
@@ -61,12 +60,12 @@ export function uint6ToBase64(nUint6: number) {
}
export function bytesCmp(bytes1: number[] | Uint8Array, bytes2: number[] | Uint8Array) {
- var len = bytes1.length;
+ const len = bytes1.length;
if(len !== bytes2.length) {
return false;
}
- for(var i = 0; i < len; i++) {
+ for(let i = 0; i < len; ++i) {
if(bytes1[i] !== bytes2[i]) {
return false;
}
@@ -76,10 +75,10 @@ export function bytesCmp(bytes1: number[] | Uint8Array, bytes2: number[] | Uint8
}
export function bytesXor(bytes1: number[] | Uint8Array, bytes2: number[] | Uint8Array) {
- var len = bytes1.length;
- var bytes = [];
+ const len = bytes1.length;
+ const bytes: number[] = [];
- for (var i = 0; i < len; ++i) {
+ for(let i = 0; i < len; ++i) {
bytes[i] = bytes1[i] ^ bytes2[i];
}
@@ -111,11 +110,11 @@ export function convertToUint8Array(bytes: Uint8Array | number[]): Uint8Array {
}
export function bytesFromArrayBuffer(buffer: ArrayBuffer) {
- var len = buffer.byteLength;
- var byteView = new Uint8Array(buffer);
- var bytes = [];
+ const len = buffer.byteLength;
+ const byteView = new Uint8Array(buffer);
+ const bytes: number[] = [];
- for(var i = 0; i < len; ++i) {
+ for(let i = 0; i < len; ++i) {
bytes[i] = byteView[i];
}
@@ -123,9 +122,9 @@ export function bytesFromArrayBuffer(buffer: ArrayBuffer) {
}
export function bufferConcat(buffer1: any, buffer2: any) {
- var l1 = buffer1.byteLength || buffer1.length;
- var l2 = buffer2.byteLength || buffer2.length;
- var tmp = new Uint8Array(l1 + l2);
+ const l1 = buffer1.byteLength || buffer1.length;
+ const l2 = buffer2.byteLength || buffer2.length;
+ const tmp = new Uint8Array(l1 + l2);
tmp.set(buffer1 instanceof ArrayBuffer ? new Uint8Array(buffer1) : buffer1, 0);
tmp.set(buffer2 instanceof ArrayBuffer ? new Uint8Array(buffer2) : buffer2, l1);
@@ -136,7 +135,7 @@ export function bufferConcats(...args: any[]) {
let length = 0;
args.forEach(b => length += b.byteLength || b.length);
- var tmp = new Uint8Array(length);
+ const tmp = new Uint8Array(length);
let lastLength = 0;
args.forEach(b => {
@@ -148,8 +147,8 @@ export function bufferConcats(...args: any[]) {
}
export function bytesFromWordss(input: Uint32Array) {
- var o = [];
- for(var i = 0; i < input.length * 4; i++) {
+ const o: number[] = [];
+ for(let i = 0, length = input.length * 4; i < length; ++i) {
o.push((input[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff);
}
@@ -161,12 +160,17 @@ export function bytesToWordss(input: ArrayBuffer | Uint8Array) {
if(input instanceof ArrayBuffer) bytes = new Uint8Array(input);
else bytes = input;
- var len = bytes.length;
- var words: number[] = [];
- var i;
- for(i = 0; i < len; i++) {
+ const words: number[] = [];
+ for(let i = 0, len = bytes.length; i < len; ++i) {
words[i >>> 2] |= bytes[i] << (24 - (i % 4) * 8);
}
return new Uint32Array(words);
-}
\ No newline at end of file
+}
+
+// * https://stackoverflow.com/a/52827031
+/* export const isBigEndian = (() => {
+ const array = new Uint8Array(4);
+ const view = new Uint32Array(array.buffer);
+ return !((view[0] = 1) & array[0]);
+})(); */
diff --git a/src/helpers/random.ts b/src/helpers/random.ts
index a52cdd00..51b601ee 100644
--- a/src/helpers/random.ts
+++ b/src/helpers/random.ts
@@ -5,4 +5,4 @@ export function nextRandomInt(maxValue: number) {
export function randomLong() {
return '' + nextRandomInt(0xFFFFFFFF) + nextRandomInt(0xFFFFFF);
//return '' + parseInt(nextRandomInt(0xFFFFFFFF).toString(16) + nextRandomInt(0xFFFFFFFF).toString(16), 16);
-}
\ No newline at end of file
+}
diff --git a/src/index.hbs b/src/index.hbs
index e4c655e1..98a84300 100644
--- a/src/index.hbs
+++ b/src/index.hbs
@@ -135,36 +135,6 @@
-
-
-
@@ -190,7 +160,6 @@
-
Bio
diff --git a/src/lib/appManagers/appDialogsManager.ts b/src/lib/appManagers/appDialogsManager.ts
index 5f6e51d4..9a7a162c 100644
--- a/src/lib/appManagers/appDialogsManager.ts
+++ b/src/lib/appManagers/appDialogsManager.ts
@@ -176,6 +176,7 @@ class ConnectionStatusComponent {
export class AppDialogsManager {
public _chatList = document.getElementById('dialogs') as HTMLUListElement;
public chatList = this._chatList;
+ public chatListArchived: HTMLUListElement;
public doms: {[peerId: number]: DialogDom} = {};
@@ -191,10 +192,7 @@ export class AppDialogsManager {
public contextMenu = new DialogsContextMenu();
- public chatLists: {[filterId: number]: HTMLUListElement} = {
- 0: this.chatList,
- 1: appSidebarLeft.archivedTab.chatList
- };
+ public chatLists: {[filterId: number]: HTMLUListElement};
public filterId = 0;
private folders: {[k in 'menu' | 'container' | 'menuScrollContainer']: HTMLElement} = {
menu: document.getElementById('folders-tabs'),
@@ -222,6 +220,14 @@ export class AppDialogsManager {
private lastActiveElements: Set
= new Set();
constructor() {
+ this.chatListArchived = document.createElement('ul');
+ this.chatListArchived.id = 'dialogs-archived';
+
+ this.chatLists = {
+ 0: this.chatList,
+ 1: this.chatListArchived
+ };
+
this.chatsPreloader = putPreloader(null, true);
this.allUnreadCount = this.folders.menu.querySelector('.badge');
@@ -434,10 +440,10 @@ export class AppDialogsManager {
positionElementByIndex(renderedFilter.container, this.folders.container, filter.orderIndex);
});
- if(this.filterId) {
+ /* if(this.filterId) {
const tabIndex = order.indexOf(this.filterId) + 1;
selectTab.prevId = tabIndex;
- }
+ } */
});
rootScope.on('peer_typings', (e) => {
diff --git a/src/lib/crypto/crypto_utils.ts b/src/lib/crypto/crypto_utils.ts
index 0195cf3f..8759a488 100644
--- a/src/lib/crypto/crypto_utils.ts
+++ b/src/lib/crypto/crypto_utils.ts
@@ -183,13 +183,13 @@ export function pqPrimeLeemon(what: any) {
var x = new Array(minLen);
var y = new Array(minLen);
- for(i = 0; i < 3; i++) {
+ for(i = 0; i < 3; ++i) {
q = (nextRandomInt(128) & 15) + 17;
copyInt_(x, nextRandomInt(1000000000) + 1);
copy_(y, x);
lim = 1 << (i + 18);
- for (j = 1; j < lim; j++) {
+ for (j = 1; j < lim; ++j) {
++it;
copy_(a, x);
copy_(b, x);
diff --git a/src/lib/crypto/srp.ts b/src/lib/crypto/srp.ts
index 5c92c442..27ea3dba 100644
--- a/src/lib/crypto/srp.ts
+++ b/src/lib/crypto/srp.ts
@@ -5,9 +5,12 @@ import {str2bigInt, isZero,
import {logger, LogLevels} from '../logger';
import { AccountPassword, PasswordKdfAlgo } from "../../layer";
import { bufferConcats, bytesToHex, bytesFromHex, bufferConcat, bytesXor } from "../../helpers/bytes";
+//import { MOUNT_CLASS_TO } from "../../config/debug";
const log = logger('SRP', LogLevels.error);
+//MOUNT_CLASS_TO && Object.assign(MOUNT_CLASS_TO, {str2bigInt, bigInt2str, int2bigInt});
+
export async function makePasswordHash(password: string, client_salt: Uint8Array, server_salt: Uint8Array): Promise {
let clientSaltString = '';
for(let i = 0; i < client_salt.length; i++) clientSaltString += String.fromCharCode(client_salt[i]);
@@ -32,13 +35,12 @@ export async function makePasswordHash(password: string, client_salt: Uint8Array
}
export async function computeSRP(password: string, state: AccountPassword, isNew: boolean) {
- console.log('computeSRP:', password, state, isNew);
-
- let algo = (state.current_algo || state.new_algo) as PasswordKdfAlgo.passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow;
+ const algo = (isNew ? state.new_algo : state.current_algo) as PasswordKdfAlgo.passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow;
+ //console.log('computeSRP:', password, state, isNew, algo);
- let p = str2bigInt(bytesToHex(algo.p), 16);
- let B = str2bigInt(bytesToHex(state.srp_B), 16);
- let g = int2bigInt(algo.g, 32, 256);
+ const p = str2bigInt(bytesToHex(algo.p), 16);
+ const B = str2bigInt(bytesToHex(state.srp_B), 16);
+ const g = int2bigInt(algo.g, 32, 256);
//log('p', bigInt2str(p, 16));
//log('B', bigInt2str(B, 16));
@@ -63,28 +65,41 @@ export async function computeSRP(password: string, state: AccountPassword, isNew
//check_prime_and_good(algo.p, g);
- let pw_hash = await makePasswordHash(password, new Uint8Array(algo.salt1), new Uint8Array(algo.salt2));
- let x = str2bigInt(bytesToHex(new Uint8Array(pw_hash)), 16);
+ const pw_hash = await makePasswordHash(password, new Uint8Array(algo.salt1), new Uint8Array(algo.salt2));
+ const x = str2bigInt(bytesToHex(new Uint8Array(pw_hash)), 16);
//log('computed pw_hash:', pw_hash, x, bytesToHex(new Uint8Array(pw_hash)));
- var padArray = function(arr: any[], len: number, fill = 0) {
+ const padArray = function(arr: any[], len: number, fill = 0) {
return Array(len).fill(fill).concat(arr).slice(-len);
};
- let pForHash = padArray(bytesFromHex(bigInt2str(p, 16)), 256);
- let gForHash = padArray(bytesFromHex(bigInt2str(g, 16)), 256); // like uint8array
- let b_for_hash = padArray(bytesFromHex(bigInt2str(B, 16)), 256);
+ const pForHash = padArray(bytesFromHex(bigInt2str(p, 16)), 256);
+ const gForHash = padArray(bytesFromHex(bigInt2str(g, 16)), 256); // like uint8array
+ const b_for_hash = padArray(bytesFromHex(bigInt2str(B, 16)), 256);
/* log(bytesToHex(pForHash));
log(bytesToHex(gForHash));
log(bytesToHex(b_for_hash)); */
- let g_x = powMod(g, x, p);
+ const v = powMod(g, x, p);
+
+ const flipper = (arr: Uint8Array | number[]) => {
+ const out = new Uint8Array(arr.length);
+ for(let i = 0; i < arr.length; i += 4) {
+ out[i] = arr[i + 3];
+ out[i + 1] = arr[i + 2];
+ out[i + 2] = arr[i + 1];
+ out[i + 3] = arr[i];
+ }
+
+ return out;
+ };
// * https://core.telegram.org/api/srp#setting-a-new-2fa-password
if(isNew) {
- return padArray(bytesFromHex(bigInt2str(g_x, 16)), 256);
+ const bytes = bytesFromHex(bigInt2str(v, 16));
+ return padArray(/* (isBigEndian ? bytes.reverse() : bytes) */bytes, 256);
}
//log('g_x', bigInt2str(g_x, 16));
@@ -95,16 +110,16 @@ export async function computeSRP(password: string, state: AccountPassword, isNew
//log('k', bigInt2str(k, 16));
// kg_x = (k * g_x) % p
- let kg_x = mod(mult(k, g_x), p);
+ const k_v = mod(mult(k, v), p);
// good
//log('kg_x', bigInt2str(kg_x, 16));
- let is_good_mod_exp_first = (modexp: any, prime: any) => {
- let diff = sub(prime, modexp);
- let min_diff_bits_count = 2048 - 64;
- let max_mod_exp_size = 256;
+ const is_good_mod_exp_first = (modexp: any, prime: any) => {
+ const diff = sub(prime, modexp);
+ const min_diff_bits_count = 2048 - 64;
+ const max_mod_exp_size = 256;
if(negative(diff) ||
bitSize(diff) < min_diff_bits_count ||
bitSize(modexp) < min_diff_bits_count ||
@@ -113,19 +128,7 @@ export async function computeSRP(password: string, state: AccountPassword, isNew
return true;
};
- var flipper = (arr: Uint8Array | number[]) => {
- let out = new Uint8Array(arr.length);
- for(let i = 0; i < arr.length; i += 4) {
- out[i] = arr[i + 3];
- out[i + 1] = arr[i + 2];
- out[i + 2] = arr[i + 1];
- out[i + 3] = arr[i];
- }
-
- return out;
- };
-
- let generate_and_check_random = async() => {
+ const generate_and_check_random = async() => {
while(true) {
const a = str2bigInt(bytesToHex(flipper(state.secure_random)), 16);
//const a = str2bigInt('9153faef8f2bb6da91f6e5bc96bc00860a530a572a0f45aac0842b4602d711f8bda8d59fb53705e4ae3e31a3c4f0681955425f224297b8e9efd898fec22046debb7ba8a0bcf2be1ada7b100424ea318fdcef6ccfe6d7ab7d978c0eb76a807d4ab200eb767a22de0d828bc53f42c5a35c2df6e6ceeef9a3487aae8e9ef2271f2f6742e83b8211161fb1a0e037491ab2c2c73ad63c8bd1d739de1b523fe8d461270cedcf240de8da75f31be4933576532955041dc5770c18d3e75d0b357df9da4a5c8726d4fced87d15752400883dc57fa1937ac17608c5446c4774dcd123676d683ce3a1ab9f7e020ca52faafc99969822717c8e07ea383d5fb1a007ba0d170cb', 16);
@@ -161,11 +164,11 @@ export async function computeSRP(password: string, state: AccountPassword, isNew
log('B - kg_x', bigInt2str(sub(B, kg_x), 16)); */
let g_b;
- if(!greater(B, kg_x)) {
+ if(!greater(B, k_v)) {
//log('negative');
g_b = add(B, p);
} else g_b = B;
- g_b = mod(sub(g_b, kg_x), p);
+ g_b = mod(sub(g_b, k_v), p);
/* let g_b = sub(B, kg_x);
if(negative(g_b)) g_b = add(g_b, p); */
@@ -209,4 +212,4 @@ export async function computeSRP(password: string, state: AccountPassword, isNew
return out;
/* console.log(gForHash, pForHash, bForHash); */
-}
\ No newline at end of file
+}
diff --git a/src/pages/pagePassword.ts b/src/pages/pagePassword.ts
index 5a2749de..1a01fe48 100644
--- a/src/pages/pagePassword.ts
+++ b/src/pages/pagePassword.ts
@@ -2,7 +2,6 @@ import { putPreloader } from '../components/misc';
import mediaSizes from '../helpers/mediaSizes';
import { AccountPassword } from '../layer';
import appStateManager from '../lib/appManagers/appStateManager';
-import apiManager from '../lib/mtproto/mtprotoworker';
import passwordManager from '../lib/mtproto/passwordManager';
import Page from './page';
import pageIm from './pageIm';
@@ -10,12 +9,13 @@ import Button from '../components/button';
import PasswordInputField from '../components/passwordInputField';
import PasswordMonkey from '../components/monkeys/password';
import { ripple } from '../components/ripple';
+import RichTextProcessor from '../lib/richtextprocessor';
const TEST = false;
let passwordInput: HTMLInputElement;
let onFirstMount = (): Promise => {
- const btnNext = Button('btn-primary', {text: 'NEXT'});
+ const btnNext = Button('btn-primary btn-color-primary', {text: 'NEXT'});
const passwordInputField = new PasswordInputField({
label: 'Password',
@@ -37,7 +37,7 @@ let onFirstMount = (): Promise => {
return !TEST && passwordManager.getState().then(_state => {
state = _state;
- passwordInputField.label.innerText = state.hint ?? 'Password';
+ passwordInputField.label.innerHTML = state.hint ? RichTextProcessor.wrapEmojiText(state.hint) : 'Password';
});
};
diff --git a/src/pages/pageSignIn.ts b/src/pages/pageSignIn.ts
index 72aaaa96..cb36b456 100644
--- a/src/pages/pageSignIn.ts
+++ b/src/pages/pageSignIn.ts
@@ -297,7 +297,7 @@ let onFirstMount = () => {
});
signedCheckboxField.input.checked = true;
- btnNext = Button('btn-primary', {text: 'NEXT'});
+ btnNext = Button('btn-primary btn-color-primary', {text: 'NEXT'});
btnNext.style.visibility = 'hidden';
btnNext.addEventListener('click', function(this: HTMLElement, e) {
diff --git a/src/pages/pageSignUp.ts b/src/pages/pageSignUp.ts
index 11c117eb..e3823529 100644
--- a/src/pages/pageSignUp.ts
+++ b/src/pages/pageSignUp.ts
@@ -64,7 +64,7 @@ const onFirstMount = () => import('../lib/appManagers/appProfileManager').then(i
maxLength: 64
});
- const btnSignUp = Button('btn-primary');
+ const btnSignUp = Button('btn-primary btn-color-primary');
btnSignUp.append('START MESSAGING');
inputWrapper.append(nameInputField.container, lastNameInputField.container, btnSignUp);
diff --git a/src/scss/partials/_button.scss b/src/scss/partials/_button.scss
index f70deec8..f40a351d 100644
--- a/src/scss/partials/_button.scss
+++ b/src/scss/partials/_button.scss
@@ -206,8 +206,6 @@
}
.btn-primary {
- background-color: $color-blue;
- color: #fff;
border-radius: $border-radius-medium;
width: 100%;
text-align: center;
@@ -227,6 +225,7 @@
&-transparent {
background-color: transparent;
+
@include hover() {
background: hover-color($color-blue);
}
@@ -345,3 +344,12 @@
@include btn-hoverable();
}
+
+.btn-color-primary {
+ background: $color-blue;
+ color: #fff;
+
+ /* .c-ripple__circle {
+ background-color: var(--color-blue-hover);
+ } */
+}
diff --git a/src/scss/partials/_leftSidebar.scss b/src/scss/partials/_leftSidebar.scss
index a90e8311..cdca1a3d 100644
--- a/src/scss/partials/_leftSidebar.scss
+++ b/src/scss/partials/_leftSidebar.scss
@@ -903,29 +903,69 @@
}
.two-step-verification {
+ .sidebar-left-section-caption { // * main tab verified with mockup
+ text-align: center;
+ max-width: 342px;
+ margin-left: auto;
+ margin-right: auto;
+ font-size: 1rem;
+ line-height: 1.3125;
+ margin-bottom: 1.125rem;
+ }
+
+ .btn-primary + .btn-primary {
+ margin-top: .125rem !important;
+ }
+
.media-sticker-wrapper {
width: 168px;
height: 168px;
+ margin: .625rem auto 1.1875rem;
+ }
+
+ .input-wrapper .btn-primary:first-child:last-child {
+ margin-top: .25rem;
}
&-enter-password {
.media-sticker-wrapper {
+ margin: 1.125rem auto 1.8125rem;
width: 157px;
height: 157px;
}
}
+ &-hint, &-email {
+ .btn-primary + .btn-primary {
+ margin-top: .5rem !important;
+ }
+ }
+
&-hint {
.media-sticker-wrapper {
- width: 120px;
- height: 120px;
+ width: 160px;
+ height: 160px;
+ margin: .5rem auto 2.25rem;
}
}
&-email {
.media-sticker-wrapper {
- width: 120px;
- height: 120px;
+ width: 160px;
+ height: 160px;
+ margin: .5625rem auto 2.1875rem;
+ }
+ }
+
+ &-set {
+ .media-sticker-wrapper {
+ width: 160px;
+ height: 160px;
+ margin: 1rem auto 1.3125rem;
+
+ .rlottie, .rlottie-vector {
+ left: .625rem;
+ }
}
}
}
diff --git a/src/scss/style.scss b/src/scss/style.scss
index 2de3bccc..c575615f 100644
--- a/src/scss/style.scss
+++ b/src/scss/style.scss
@@ -754,6 +754,12 @@ img.emoji {
}
}
+.popup-disable-password, .popup-skip-email {
+ .popup-description {
+ max-width: 284px;
+ }
+}
+
.grid {
width: 100%;
display: grid;
diff --git a/src/tests/srp.test.ts b/src/tests/srp.test.ts
index 8c4870cf..c5021211 100644
--- a/src/tests/srp.test.ts
+++ b/src/tests/srp.test.ts
@@ -22,7 +22,7 @@ test('2FA whole (with negative)', async() => {
new_algo: null,
new_secure_algo: null
- }).then(res => {
+ }, false).then(res => {
expect(res.srp_id).toEqual(srp_id);
expect(res.A).toEqual(A);
expect(res.M1).toEqual(M1);