Browse Source

Fixed slider animation & added same animation to auth pages

master
morethanwords 4 years ago
parent
commit
43bc94b0c4
  1. 152
      src/components/misc.ts
  2. 194
      src/components/pageIm.ts
  3. 33
      src/components/wrappers.ts
  4. 337
      src/lib/appManagers/appDialogsManager.ts
  5. 54
      src/lib/appManagers/appImManager.ts
  6. 3
      src/lib/appManagers/appMediaViewer.ts
  7. 152
      src/lib/appManagers/appSidebarLeft.ts
  8. 2
      src/lib/services.ts
  9. 10
      src/lib/utils.js
  10. 28
      src/pages/page.ts
  11. 550
      src/pages/pageAuthCode.ts
  12. 111
      src/pages/pageIm.ts
  13. 267
      src/pages/pagePassword.ts
  14. 518
      src/pages/pageSignIn.ts
  15. 393
      src/pages/pageSignUp.ts
  16. 37
      src/pages/pagesManager.ts
  17. 2
      src/scss/partials/_leftSidebar.scss
  18. 35
      src/scss/style.scss

152
src/components/misc.ts

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
import { whichChild, findUpTag } from "../lib/utils";
import { whichChild, findUpTag, cancelEvent } from "../lib/utils";
let rippleClickID = 0;
export function ripple(elem: HTMLElement, callback: (id: number) => Promise<boolean | void> = () => Promise.resolve(), onEnd: (id: number) => void = null) {
@ -8,11 +8,17 @@ export function ripple(elem: HTMLElement, callback: (id: number) => Promise<bool @@ -8,11 +8,17 @@ export function ripple(elem: HTMLElement, callback: (id: number) => Promise<bool
elem.append(r);
elem.addEventListener('mousedown', (e) => {
if(elem.dataset.ripple == '0') {
return false;
}
let startTime = Date.now();
let span = document.createElement('span');
let clickID = rippleClickID++;
console.log('ripple mousedown');
let handler = () => {
let elapsedTime = Date.now() - startTime;
if(elapsedTime < 700) {
@ -135,87 +141,125 @@ export function putPreloader(elem: Element, returnDiv = false) { @@ -135,87 +141,125 @@ export function putPreloader(elem: Element, returnDiv = false) {
elem.innerHTML += html;
}
export function horizontalMenu(tabs: HTMLUListElement, content: HTMLDivElement, onClick?: (id: number, tabContent: HTMLDivElement) => void, onTransitionEnd?: () => void) {
export function horizontalMenu(tabs: HTMLUListElement, content: HTMLDivElement, onClick?: (id: number, tabContent: HTMLDivElement) => void, onTransitionEnd?: () => void, transitionTime = 300) {
let hideTimeout: number = 0;
let prevTabContent: HTMLDivElement = null;
let prevId = -1;
tabs.addEventListener('click', function(e) {
let target = e.target as HTMLLIElement;
if(target.tagName != 'LI') {
target = findUpTag(target, 'LI');
}
///////console.log('tabs click:', target);
if(!target) return false;
let children = Array.from(content.children);
let tabsChildren = tabs ? Array.from(tabs.children) : [];
let activeInSlide: Set<Element> = new Set();
let selectTab = (id: number) => {
if(id == prevId) return false;
let p = prevTabContent;
/* children.forEach(child => {
if(child != p) {
child.classList.remove('active');
}
}); */
let id = whichChild(target);
let tabContent = content.children[id] as HTMLDivElement;
if(onClick) onClick(id, tabContent);
if(target.classList.contains('active') || id == prevId) {
return false;
}
let prev = tabs.querySelector('li.active') as HTMLLIElement;
prev && prev.classList.remove('active');
target.classList.add('active');
tabContent.classList.add('active');
/////console.log('mambo rap', prevId, id);
if(!activeInSlide.has(tabContent)) {
activeInSlide.add(tabContent);
}
//content.style.marginLeft = id > 0 ? (-id * 100) + '%' : '';
let toRight = prevId < id;
if(prevId != -1) {
content.style.width = '200%';
content.style.cssText = `width: ${activeInSlide.size * 100}%; will-change: width, transform; transform: translateX(-${100 - 100 / activeInSlide.size}%);`;
//////console.log('mambo rap setting', toRight);
content.classList.remove('animated');
if(toRight) {
content.classList.add('animated');
content.style.marginLeft = '-100%';
} else {
content.style.marginLeft = '-100%';
setTimeout(() => {
window.requestAnimationFrame(() => {
content.classList.add('animated');
content.style.marginLeft = '';
}, 10);
content.style.transform = '';
});
}
}
prevId = id;
let p = prevTabContent;
clearTimeout(hideTimeout);
if(p) hideTimeout = setTimeout(() => {
if(toRight) {
p.classList.remove('active');
if(hideTimeout) clearTimeout(hideTimeout);
if(p/* && false */) {
//if(tabs) tabs.classList.add('disable-hover');
if(tabs) {
tabsChildren.forEach((c, idx) => {
if(idx != prevId && idx != id) {
(c as HTMLElement).dataset.ripple = '0';
}
});
}
hideTimeout = setTimeout(() => {
children.forEach(child => {
if(child != tabContent) {
child.classList.remove('active');
activeInSlide.delete(child);
}
});
if(tabs) {
tabsChildren.forEach(c => {
delete (c as HTMLElement).dataset.ripple;
});
}
content.classList.remove('animated');
content.style.width = '100%';
content.style.cssText = '';
hideTimeout = 0;
if(onTransitionEnd) onTransitionEnd();
//if(tabs) tabs.classList.remove('disable-hover');
}, transitionTime);
}
prevId = id;
prevTabContent = tabContent;
};
if(tabs) {
tabs.addEventListener('click', function(e) {
let target = e.target as HTMLLIElement;
if(target.tagName != 'LI') {
target = findUpTag(target, 'LI');
}
/* content.style.marginLeft = '0%';
content.style.width = '100%'; */
//console.log('tabs click:', target);
if(!toRight) {
p.classList.remove('active');
content.classList.remove('animated');
content.style.width = '100%';
if(!target) return false;
let id = whichChild(target);
let tabContent = content.children[id] as HTMLDivElement;
if(activeInSlide.size >= 2 && !activeInSlide.has(tabContent)) {
cancelEvent(e);
return false;
}
if(onClick) onClick(id, tabContent);
if(target.classList.contains('active') || id == prevId) {
return false;
}
content.style.marginLeft = '';
let prev = tabs.querySelector('li.active') as HTMLLIElement;
prev && prev.classList.remove('active');
if(onTransitionEnd) onTransitionEnd();
}, 200);
prevTabContent = tabContent;
});
target.classList.add('active');
selectTab(id);
});
}
return selectTab;
}
export function formatPhoneNumber(str: string) {

194
src/components/pageIm.ts

@ -1,194 +0,0 @@ @@ -1,194 +0,0 @@
//import { appImManager, appMessagesManager, appDialogsManager, apiUpdatesManager, appUsersManager } from "../lib/services";
import { openBtnMenu } from "./misc";
//import {stackBlurImage} from '../lib/StackBlur';
import appSidebarLeft from "../lib/appManagers/appSidebarLeft";
export default () => import('../lib/services').then(services => {
//console.log('included services', services);
let {appImManager, appMessagesManager, appDialogsManager, apiUpdatesManager, appUsersManager} = services;
//export default () => {
let pageEl = document.body.getElementsByClassName('page-chats')[0] as HTMLDivElement;
pageEl.style.display = '';
apiUpdatesManager.attach();
// @ts-ignore
document.addEventListener('user_update', (e: CustomEvent) => {
let userID = e.detail;
let user = appUsersManager.getUser(userID);
let dialog = appMessagesManager.getDialogByPeerID(user.id)[0];
//console.log('updating user:', user, dialog);
if(dialog && !appUsersManager.isBot(dialog.peerID) && dialog.peerID != appImManager.myID) {
let online = user.status && user.status._ == 'userStatusOnline';
let dom = appDialogsManager.getDialogDom(dialog.peerID);
if(dom) {
if(online) {
dom.avatarDiv.classList.add('is-online');
} else {
dom.avatarDiv.classList.remove('is-online');
}
}
}
if(appImManager.peerID == user.id) {
appImManager.setPeerStatus();
}
});
// @ts-ignore
document.addEventListener('dialog_top', (e: CustomEvent) => {
let dialog: any = e.detail;
appDialogsManager.setLastMessage(dialog);
appDialogsManager.sortDom();
});
// @ts-ignore
document.addEventListener('dialogs_multiupdate', (e: CustomEvent) => {
let dialogs = e.detail;
let performed = 0;
for(let id in dialogs) {
let dialog = dialogs[id];
/////console.log('updating dialog:', dialog);
++performed;
if(!(dialog.peerID in appDialogsManager.doms)) {
appDialogsManager.addDialog(dialog);
continue;
}
appDialogsManager.setLastMessage(dialog);
}
if(performed/* && false */) {
/////////console.log('will sortDom');
appDialogsManager.sortDom();
appDialogsManager.sortDom(true);
}
});
// @ts-ignore
document.addEventListener('dialog_unread', (e: CustomEvent) => {
let info: {
peerID: number,
count: number
} = e.detail;
let dialog = appMessagesManager.getDialogByPeerID(info.peerID)[0];
if(dialog) {
appDialogsManager.setUnreadMessages(dialog);
if(dialog.peerID == appImManager.peerID) {
appImManager.updateUnreadByDialog(dialog);
}
}
});
/*
loadDialogs().then(result => {
//appImManager.setScroll(chatScroll);
});
return;
*/
/* function placeCaretAfterNode(node: HTMLElement) {
if (typeof window.getSelection != "undefined") {
var range = document.createRange();
range.setStartAfter(node);
range.collapse(true);
var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
}
}
messageInput.onclick = (e) => {
let target = e.target as HTMLElement;
if(target.classList.contains('emoji-inner')) {
placeCaretAfterNode(target.parentElement);
} else if(target.classList.contains('emoji-sizer')) {
placeCaretAfterNode(target);
}
console.log('lol', target);
}; */
/* window.addEventListener('click', function(this, e) {
// @ts-ignore
let isInput = e.target.tagName == 'INPUT';
if(!isInput && !window.getSelection().toString()) {
console.log('click');
messageInput.focus();
}
}); */
/* fetch('assets/img/camomile.jpg')
.then(res => res.blob())
.then(blob => {
let img = new Image();
let url = URL.createObjectURL(blob);
img.src = url;
img.onload = () => {
let id = 'chat-background-canvas';
var canvas = document.getElementById(id) as HTMLCanvasElement;
//URL.revokeObjectURL(url);
let elements = ['.chat-container'].map(selector => {
return document.querySelector(selector) as HTMLDivElement;
});
stackBlurImage(img, id, 15, 0);
canvas.toBlob(blob => {
//let dataUrl = canvas.toDataURL('image/jpeg', 1);
let dataUrl = URL.createObjectURL(blob);
elements.forEach(el => {
el.style.backgroundImage = 'url(' + dataUrl + ')';
});
}, 'image/jpeg', 1);
};
}); */
/* toggleEmoticons.onclick = (e) => {
if(!emoticonsDropdown) {
emoticonsDropdown = initEmoticonsDropdown(pageEl, appImManager,
appMessagesManager, messageInput, toggleEmoticons);
} else {
emoticonsDropdown.classList.toggle('active');
}
toggleEmoticons.classList.toggle('active');
}; */
Array.from(document.getElementsByClassName('btn-menu-toggle')).forEach((el) => {
el.addEventListener('click', (e) => {
//console.log('click pageIm');
if(!el.classList.contains('btn-menu-toggle')) return false;
//window.removeEventListener('mousemove', onMouseMove);
let openedMenu = el.querySelector('.btn-menu') as HTMLDivElement;
e.cancelBubble = true;
if(el.classList.contains('menu-open')) {
el.classList.remove('menu-open');
openedMenu.classList.remove('active');
} else {
openBtnMenu(openedMenu);
}
});
});
appSidebarLeft.loadDialogs().then(result => {
//appSidebarLeft.onChatsScroll();
appSidebarLeft.loadDialogs(true);
});
});

33
src/components/wrappers.ts

@ -3,7 +3,6 @@ import CryptoWorker from '../lib/crypto/cryptoworker'; @@ -3,7 +3,6 @@ import CryptoWorker from '../lib/crypto/cryptoworker';
import LottieLoader from '../lib/lottieLoader';
import appStickersManager from "../lib/appManagers/appStickersManager";
import appDocsManager from "../lib/appManagers/appDocsManager";
import {AppImManager} from "../lib/appManagers/appImManager";
import { formatBytes } from "../lib/utils";
import ProgressivePreloader from './preloader';
import LazyLoadQueue from './lazyLoadQueue';
@ -60,9 +59,21 @@ export type MTPhotoSize = { @@ -60,9 +59,21 @@ export type MTPhotoSize = {
bytes?: Uint8Array // if type == 'i'
};
export function wrapVideo(this: AppImManager, doc: MTDocument, container: HTMLDivElement, message: any, justLoader = true, preloader?: ProgressivePreloader, controls = true, round = false, boxWidth = 380, boxHeight = 380, withTail = false, isOut = false) {
export function wrapVideo({doc, container, message, justLoader, preloader, round, boxWidth, boxHeight, withTail, isOut, middleware, lazyLoadQueue}: {
doc: MTDocument,
container: HTMLDivElement,
message: any,
justLoader: boolean,
preloader?: ProgressivePreloader,
round: boolean,
boxWidth: number,
boxHeight: number,
withTail?: boolean,
isOut?: boolean,
middleware: () => boolean,
lazyLoadQueue: LazyLoadQueue
}) {
let img: HTMLImageElement | SVGImageElement;
let peerID = this.peerID;
if(withTail) {
img = wrapMediaWithTail(doc, message, container, boxWidth, boxHeight, isOut);
@ -104,8 +115,7 @@ export function wrapVideo(this: AppImManager, doc: MTDocument, container: HTMLDi @@ -104,8 +115,7 @@ export function wrapVideo(this: AppImManager, doc: MTDocument, container: HTMLDi
preloader.attach(container, true, promise);
return promise.then(blob => {
if(this.peerID != peerID) {
this.log.warn('peer changed');
if(!middleware()) {
return;
}
@ -141,7 +151,7 @@ export function wrapVideo(this: AppImManager, doc: MTDocument, container: HTMLDi @@ -141,7 +151,7 @@ export function wrapVideo(this: AppImManager, doc: MTDocument, container: HTMLDi
};
if(doc.type == 'gif' || true) { // extra fix
return doc.downloaded ? loadVideo() : this.lazyLoadQueue.push({div: container, load: loadVideo, wasSeen: true});
return doc.downloaded ? loadVideo() : lazyLoadQueue.push({div: container, load: loadVideo, wasSeen: true});
} /* else { // if video
let load = () => appPhotosManager.preloadPhoto(doc).then((blob) => {
if((this.peerID ? this.peerID : this.currentMessageID) != peerID) {
@ -481,9 +491,7 @@ function wrapMediaWithTail(photo: any, message: {mid: number, message: string}, @@ -481,9 +491,7 @@ function wrapMediaWithTail(photo: any, message: {mid: number, message: string},
return image;
}
export async function wrapPhoto(this: AppImManager, photoID: string, message: any, container: HTMLDivElement, boxWidth = 380, boxHeight = 380, withTail = true, isOut = false) {
let peerID = this.peerID;
export async function wrapPhoto(photoID: string, message: any, container: HTMLDivElement, boxWidth = 380, boxHeight = 380, withTail = true, isOut = false, lazyLoadQueue: LazyLoadQueue, middleware: () => boolean) {
let photo = appPhotosManager.getPhoto(photoID);
let size: MTPhotoSize;
@ -512,10 +520,7 @@ export async function wrapPhoto(this: AppImManager, photoID: string, message: an @@ -512,10 +520,7 @@ export async function wrapPhoto(this: AppImManager, photoID: string, message: an
}
return promise.then(() => {
if(this.peerID != peerID) {
this.log.warn('peer changed');
return;
}
if(!middleware()) return;
renderImageFromUrl(image, photo.url);
});
@ -523,7 +528,7 @@ export async function wrapPhoto(this: AppImManager, photoID: string, message: an @@ -523,7 +528,7 @@ export async function wrapPhoto(this: AppImManager, photoID: string, message: an
/////////console.log('wrapPhoto', load, container, image);
return photo.downloaded ? load() : this.lazyLoadQueue.push({div: container, load: load, wasSeen: true});
return photo.downloaded ? load() : lazyLoadQueue.push({div: container, load: load, wasSeen: true});
}
export function wrapSticker(doc: MTDocument, div: HTMLDivElement, middleware?: () => boolean, lazyLoadQueue?: LazyLoadQueue, group?: string, canvas?: boolean, play = false, onlyThumb = false) {

337
src/lib/appManagers/appDialogsManager.ts

@ -1,14 +1,13 @@ @@ -1,14 +1,13 @@
import apiManager from "../mtproto/apiManager";
import apiFileManager from '../mtproto/apiFileManager';
import { $rootScope, langPack, findUpClassName } from "../utils";
import { langPack, findUpClassName, $rootScope } from "../utils";
import appImManager, { AppImManager } from "./appImManager";
import appPeersManager from './appPeersManager';
import appMessagesManager from "./appMessagesManager";
import appMessagesManager, { AppMessagesManager } from "./appMessagesManager";
import appUsersManager from "./appUsersManager";
import { RichTextProcessor } from "../richtextprocessor";
import { ripple, renderImageFromUrl } from "../../components/misc";
import appSidebarLeft from "./appSidebarLeft";
import { ripple, putPreloader } from "../../components/misc";
import Scrollable from "../../components/scrollable";
import appProfileManager from "./appProfileManager";
import { logger } from "../polyfill";
type DialogDom = {
avatarDiv: HTMLDivElement,
@ -22,6 +21,8 @@ type DialogDom = { @@ -22,6 +21,8 @@ type DialogDom = {
listEl: HTMLLIElement
};
let testScroll = false;
export class AppDialogsManager {
public chatList = document.getElementById('dialogs') as HTMLUListElement;
public chatListArchived = document.getElementById('dialogs-archived') as HTMLUListElement;
@ -31,42 +32,228 @@ export class AppDialogsManager { @@ -31,42 +32,228 @@ export class AppDialogsManager {
public chatsArchivedHidden: Scrollable["hiddenElements"];
public chatsArchivedVisible: Scrollable["visibleElements"];
public myID = 0;
public doms: {[peerID: number]: DialogDom} = {};
public domsArchived: {[peerID: number]: DialogDom} = {};
public lastActiveListElement: HTMLElement = null;
public savedAvatarURLs: {[peerID: number]: string} = {};
private rippleCallback: (value?: boolean | PromiseLike<boolean>) => void = null;
private lastClickID = 0;
private lastGoodClickID = 0;
public chatsArchivedContainer = document.getElementById('chats-archived-container') as HTMLDivElement;
public chatsContainer = document.getElementById('chats-container') as HTMLDivElement;
private chatsArchivedOffsetIndex = 0;
private chatsOffsetIndex = 0;
private chatsPreloader: HTMLDivElement;
//private chatsLoadCount = 0;
//private loadDialogsPromise: Promise<any>;
private loadDialogsPromise: ReturnType<AppMessagesManager["getConversations"]>;
private loadedAll = false;
private loadedArchivedAll = false;
public scroll: Scrollable = null;
public scrollArchived: Scrollable = null;
private log = logger('DIALOGS');
constructor() {
this.chatsPreloader = putPreloader(null, true);
//this.chatsContainer.append(this.chatsPreloader);
this.pinnedDelimiter = document.createElement('div');
this.pinnedDelimiter.classList.add('pinned-delimiter');
this.pinnedDelimiter.appendChild(document.createElement('span'));
apiManager.getUserID().then((id) => {
this.myID = id;
//this.chatsLoadCount = Math.round(document.body.scrollHeight / 70 * 1.5);
let splitOffset = 1110;
this.scroll = new Scrollable(this.chatsContainer, 'y', splitOffset, 'CL', this.chatList, 500);
this.scroll.setVirtualContainer(this.chatList);
this.scroll.onScrolledBottom = this.onChatsScroll.bind(this);
this.chatsHidden = this.scroll.hiddenElements;
this.chatsVisible = this.scroll.visibleElements;
this.scrollArchived = new Scrollable(this.chatsArchivedContainer, 'y', splitOffset, 'CLA', this.chatListArchived, 500);
this.scrollArchived.setVirtualContainer(this.chatListArchived);
this.scrollArchived.onScrolledBottom = this.onChatsArchivedScroll.bind(this);
this.chatsArchivedHidden = this.scrollArchived.hiddenElements;
this.chatsArchivedVisible = this.scrollArchived.visibleElements;
//this.scrollArchived.container.addEventListener('scroll', this.onChatsArchivedScroll.bind(this));
//let chatClosedDiv = document.getElementById('chat-closed');
this.setListClickListener(this.chatList);
this.setListClickListener(this.chatListArchived);
if(testScroll) {
for(let i = 0; i < 1000; ++i) {
let li = document.createElement('li');
li.dataset.id = '' + i;
li.innerHTML = `<div class="rp"><div class="user-avatar" style="background-color: rgb(166, 149, 231); font-size: 0px;"><img src="#"></div><div class="user-caption"><p><span class="user-title">${i}</span><span><span class="message-status"></span><span class="message-time">18:33</span></span></p><p><span class="user-last-message"><b>-_-_-_-: </b>qweasd</span><span></span></p></div></div>`;
this.scroll.append(li);
}
}
window.addEventListener('resize', () => {
//this.chatsLoadCount = Math.round(document.body.scrollHeight / 70 * 1.5);
setTimeout(() => {
this.onChatsArchivedScroll();
}, 0);
});
$rootScope.$on('user_auth', (e: CustomEvent) => {
let userAuth = e.detail;
this.myID = userAuth ? userAuth.id : 0;
$rootScope.$on('user_update', (e: CustomEvent) => {
let userID = e.detail;
let user = appUsersManager.getUser(userID);
let dialog = appMessagesManager.getDialogByPeerID(user.id)[0];
//console.log('updating user:', user, dialog);
if(dialog && !appUsersManager.isBot(dialog.peerID) && dialog.peerID != $rootScope.myID) {
let online = user.status && user.status._ == 'userStatusOnline';
let dom = this.getDialogDom(dialog.peerID);
if(dom) {
if(online) {
dom.avatarDiv.classList.add('is-online');
} else {
dom.avatarDiv.classList.remove('is-online');
}
}
}
if(appImManager.peerID == user.id) {
appImManager.setPeerStatus();
}
});
$rootScope.$on('history_request', () => { // will call at history request api or cache RENDERED!
if(this.rippleCallback) {
this.rippleCallback();
this.rippleCallback = null;
$rootScope.$on('dialog_top', (e: CustomEvent) => {
let dialog: any = e.detail;
this.setLastMessage(dialog);
this.sortDom();
});
$rootScope.$on('dialogs_multiupdate', (e: CustomEvent) => {
let dialogs = e.detail;
let performed = 0;
for(let id in dialogs) {
let dialog = dialogs[id];
/////console.log('updating dialog:', dialog);
++performed;
if(!(dialog.peerID in this.doms)) {
this.addDialog(dialog);
continue;
}
this.setLastMessage(dialog);
}
if(performed/* && false */) {
/////////console.log('will sortDom');
this.sortDom();
this.sortDom(true);
}
});
//let chatClosedDiv = document.getElementById('chat-closed');
$rootScope.$on('dialog_unread', (e: CustomEvent) => {
let info: {
peerID: number,
count: number
} = e.detail;
this.setListClickListener(this.chatList);
this.setListClickListener(this.chatListArchived);
let dialog = appMessagesManager.getDialogByPeerID(info.peerID)[0];
if(dialog) {
this.setUnreadMessages(dialog);
if(dialog.peerID == appImManager.peerID) {
appImManager.updateUnreadByDialog(dialog);
}
}
});
this.loadDialogs().then(result => {
//appSidebarLeft.onChatsScroll();
this.loadDialogs(true);
});
}
public async loadDialogs(archived = false) {
if(testScroll) {
return;
}
if(this.loadDialogsPromise/* || 1 == 1 */) return this.loadDialogsPromise;
(archived ? this.chatsArchivedContainer : this.chatsContainer).append(this.chatsPreloader);
//let offset = appMessagesManager.generateDialogIndex();/* appMessagesManager.dialogsNum */;
let offset = archived ? this.chatsArchivedOffsetIndex : this.chatsOffsetIndex;
//let offset = 0;
let scroll = archived ? this.scrollArchived : this.scroll;
scroll.lock();
try {
console.time('getDialogs time');
let loadCount = 50/*this.chatsLoadCount */;
this.loadDialogsPromise = appMessagesManager.getConversations('', offset, loadCount, +archived);
let result = await this.loadDialogsPromise;
console.timeEnd('getDialogs time');
if(result && result.dialogs && result.dialogs.length) {
let index = result.dialogs[result.dialogs.length - 1].index;
if(archived) this.chatsArchivedOffsetIndex = index;
else this.chatsOffsetIndex = index;
result.dialogs.forEach((dialog: any) => {
this.addDialog(dialog);
});
}
if(!result.dialogs.length || (archived ? this.scrollArchived.length == result.count : this.scroll.length == result.count)) { // loaded all
if(archived) this.loadedArchivedAll = true;
else this.loadedAll = true;
}
/* if(archived) {
let count = result.count;
this.archivedCount.innerText = '' + count;
} */
this.log('getDialogs ' + loadCount + ' dialogs by offset:', offset, result, this.scroll.length);
this.scroll.onScroll();
} catch(err) {
this.log.error(err);
}
this.chatsPreloader.remove();
this.loadDialogsPromise = undefined;
scroll.unlock();
}
public onChatsScroll() {
if(this.loadedAll || this.scroll.hiddenElements.down.length > 0 || this.loadDialogsPromise/* || 1 == 1 */) return;
this.loadDialogs();
}
public onChatsArchivedScroll() {
if(this.loadedArchivedAll || this.scrollArchived.hiddenElements.down.length > 0 || this.loadDialogsPromise/* || 1 == 1 */) return;
this.loadDialogs(true);
}
public setListClickListener(list: HTMLUListElement, onFound?: () => void) {
@ -142,94 +329,6 @@ export class AppDialogsManager { @@ -142,94 +329,6 @@ export class AppDialogsManager {
});
}
// peerID == peerID || title
public async loadDialogPhoto(div: HTMLDivElement, peerID: number, isDialog = false, title = ''): Promise<boolean> {
let inputPeer: any;
let location: any;
if(peerID) {
inputPeer = appPeersManager.getInputPeerByID(peerID);
location = appPeersManager.getPeerPhoto(peerID);
}
//console.log('loadDialogPhoto location:', location, inputPeer);
if(peerID == this.myID && (isDialog || $rootScope.selectedPeerID == this.myID)) {
if(div.firstChild) {
div.firstChild.remove();
}
div.style.backgroundColor = '';
div.classList.add('tgico-savedmessages');
div.classList.remove('tgico-avatar_deletedaccount');
return true;
}
if(peerID) {
let user = appUsersManager.getUser(peerID);
if(user && user.pFlags && user.pFlags.deleted) {
if(div.firstChild) {
div.firstChild.remove();
}
div.style.backgroundColor = '';
div.classList.add('tgico-avatar_deletedaccount');
return true;
}
}
//if(!location || location.empty || !location.photo_small) {
if(div.firstChild) {
div.firstChild.remove();
}
let color = '';
if(peerID && peerID != this.myID) {
color = appPeersManager.getPeerColorByID(peerID);
}
div.classList.remove('tgico-savedmessages', 'tgico-avatar_deletedaccount');
div.style.backgroundColor = color;
let abbrSplitted = (!title && peerID ? appPeersManager.getPeerTitle(peerID, true) : title).split(' ');
let abbr = (abbrSplitted.length == 2 ?
abbrSplitted[0][0] + abbrSplitted[1][0] :
abbrSplitted[0][0]).toUpperCase();
//div.innerText = peer.initials.toUpperCase();
div.innerText = abbr.toUpperCase();
//return Promise.resolve(true);
//}
if(!location || location.empty || !location.photo_small) {
return true;
}
if(!this.savedAvatarURLs[peerID]) {
let res = await apiFileManager.downloadSmallFile({
_: 'inputPeerPhotoFileLocation',
dc_id: location.dc_id,
flags: 0,
peer: inputPeer,
volume_id: location.photo_small.volume_id,
local_id: location.photo_small.local_id
});
this.savedAvatarURLs[peerID] = URL.createObjectURL(res);
}
let img = new Image();
renderImageFromUrl(img, this.savedAvatarURLs[peerID]);
div.innerHTML = '';
//div.style.fontSize = '0'; // need
//div.style.backgroundColor = '';
//window.requestAnimationFrame(() => {
div.append(img);
//});
return true;
}
public sortDom(archived = false) {
//return;
//if(archived) return;
@ -299,7 +398,7 @@ export class AppDialogsManager { @@ -299,7 +398,7 @@ export class AppDialogsManager {
let child = concated.find(obj => obj.element == dom.listEl);
if(!child) {
return console.error('no child by listEl:', dom.listEl, archived, concated);
return this.log.error('no child by listEl:', dom.listEl, archived, concated);
}
if(inUpper.length < hiddenLength) {
@ -412,7 +511,7 @@ export class AppDialogsManager { @@ -412,7 +511,7 @@ export class AppDialogsManager {
let senderBold = document.createElement('b');
let str = '';
if(sender.id == this.myID) {
if(sender.id == $rootScope.myID) {
str = 'You';
} else {
str = sender.first_name || sender.last_name || sender.username;
@ -459,7 +558,7 @@ export class AppDialogsManager { @@ -459,7 +558,7 @@ export class AppDialogsManager {
dom.statusSpan.innerHTML = '';
let lastMessage = appMessagesManager.getMessage(dialog.top_message);
if(lastMessage._ != 'messageEmpty' &&
lastMessage.from_id == this.myID && lastMessage.peerID != this.myID &&
lastMessage.from_id == $rootScope.myID && lastMessage.peerID != $rootScope.myID &&
dialog.read_outbox_max_id) { // maybe comment, 06.20.2020
let outgoing = (lastMessage.pFlags && lastMessage.pFlags.unread)
/* && dialog.read_outbox_max_id != 0 */; // maybe uncomment, 31.01.2020
@ -497,7 +596,7 @@ export class AppDialogsManager { @@ -497,7 +596,7 @@ export class AppDialogsManager {
return acc;
}, 0);
appSidebarLeft.archivedCount.innerText = '' + sum;
$rootScope.$broadcast('dialogs_archived_unread', {count: sum});
}
}
@ -520,7 +619,7 @@ export class AppDialogsManager { @@ -520,7 +619,7 @@ export class AppDialogsManager {
let avatarDiv = document.createElement('div');
avatarDiv.classList.add('user-avatar');
if(drawStatus && peerID != this.myID) {
if(drawStatus && peerID != $rootScope.myID) {
let peer = dialog.peer;
switch(peer._) {
@ -544,12 +643,12 @@ export class AppDialogsManager { @@ -544,12 +643,12 @@ export class AppDialogsManager {
let titleSpan = document.createElement('span');
titleSpan.classList.add('user-title');
if(peerID == this.myID) {
if(peerID == $rootScope.myID) {
title = 'Saved Messages';
}
//console.log('trying to load photo for:', title);
this.loadDialogPhoto(avatarDiv, dialog.peerID, true);
appProfileManager.putPhoto(avatarDiv, dialog.peerID, true);
titleSpan.innerHTML = title;
//p.classList.add('')
@ -565,7 +664,7 @@ export class AppDialogsManager { @@ -565,7 +664,7 @@ export class AppDialogsManager {
paddingDiv.append(avatarDiv, captionDiv);
ripple(paddingDiv, (id) => {
console.log('dialogs click element');
this.log('dialogs click element');
this.lastClickID = id;
return new Promise((resolve, reject) => {
@ -617,10 +716,10 @@ export class AppDialogsManager { @@ -617,10 +716,10 @@ export class AppDialogsManager {
if(!container) {
if(dialog.folder_id && dialog.folder_id == 1) {
appSidebarLeft.scrollArchived.append(li);
this.scrollArchived.append(li);
this.domsArchived[dialog.peerID] = dom;
} else {
appSidebarLeft.scroll.append(li);
this.scroll.append(li);
this.doms[dialog.peerID] = dom;
}

54
src/lib/appManagers/appImManager.ts

@ -120,7 +120,7 @@ export class AppImManager { @@ -120,7 +120,7 @@ export class AppImManager {
this.popupDeleteMessage.cancelBtn = this.popupDeleteMessage.popupEl.querySelector('.popup-close') as HTMLButtonElement;
apiManager.getUserID().then((id) => {
this.myID = id;
this.myID = $rootScope.myID = id;
});
this.topbar = document.getElementById('topbar') as HTMLDivElement;
@ -128,7 +128,7 @@ export class AppImManager { @@ -128,7 +128,7 @@ export class AppImManager {
$rootScope.$on('user_auth', (e: CustomEvent) => {
let userAuth = e.detail;
this.myID = userAuth ? userAuth.id : 0;
this.myID = $rootScope.myID = userAuth ? userAuth.id : 0;
});
// will call when message is sent (only 1)
@ -558,6 +558,7 @@ export class AppImManager { @@ -558,6 +558,7 @@ export class AppImManager {
setInterval(() => this.setPeerStatus(), 60e3);
this.setScroll();
apiUpdatesManager.attach();
}
public deleteMessages(revoke = false) {
@ -882,8 +883,8 @@ export class AppImManager { @@ -882,8 +883,8 @@ export class AppImManager {
let dialog = appMessagesManager.getDialogByPeerID(this.peerID)[0] || null;
//////this.log('setPeer peerID:', this.peerID, dialog, lastMsgID);
appDialogsManager.loadDialogPhoto(this.avatarEl, this.peerID);
appDialogsManager.loadDialogPhoto(appSidebarRight.profileElements.avatar, this.peerID);
appProfileManager.putPhoto(this.avatarEl, this.peerID);
appProfileManager.putPhoto(appSidebarRight.profileElements.avatar, this.peerID);
this.firstTopMsgID = dialog ? dialog.top_message : 0;
@ -1248,7 +1249,9 @@ export class AppImManager { @@ -1248,7 +1249,9 @@ export class AppImManager {
bubble.classList.add('hide-name', 'photo');
wrapPhoto.call(this, photo.id, message, attachmentDiv, undefined, undefined, true, our);
wrapPhoto(photo.id, message, attachmentDiv, undefined, undefined, true, our, this.lazyLoadQueue, () => {
return this.peerID == peerID;
});
break;
}
@ -1291,7 +1294,20 @@ export class AppImManager { @@ -1291,7 +1294,20 @@ export class AppImManager {
if(doc.type == 'gif' || doc.type == 'video') {
//if(doc.size <= 20e6) {
bubble.classList.add('video');
wrapVideo.call(this, doc, preview, message, true, null, false, false, 380, 300);
wrapVideo({
doc,
container: preview,
message,
justLoader: true,
preloader: null,
round: false,
boxWidth: 380,
boxHeight: 300,
lazyLoadQueue: this.lazyLoadQueue,
middleware: () => {
return this.peerID == peerID;
}
});
//}
} else {
doc = null;
@ -1301,7 +1317,9 @@ export class AppImManager { @@ -1301,7 +1317,9 @@ export class AppImManager {
if(webpage.photo && !doc) {
bubble.classList.add('photo');
wrapPhoto.call(this, webpage.photo.id, message, preview, 380, 300, false);
wrapPhoto(webpage.photo.id, message, preview, 380, 300, false, null, this.lazyLoadQueue, () => {
return this.peerID == peerID;
});
}
if(preview) {
@ -1366,7 +1384,23 @@ export class AppImManager { @@ -1366,7 +1384,23 @@ export class AppImManager {
}
bubble.classList.add('hide-name', 'video');
wrapVideo.call(this, doc, attachmentDiv, message, true, null, false, doc.type == 'round', 380, 380, doc.type != 'round', our);
//wrapVideo.call(this, doc, attachmentDiv, message, true, null, false, doc.type == 'round', 380, 380, doc.type != 'round', our);
wrapVideo({
doc,
container: attachmentDiv,
message,
justLoader: true,
preloader: null,
round: doc.type == 'round',
boxWidth: 380,
boxHeight: 380,
withTail: doc.type != 'round',
isOut: our,
lazyLoadQueue: this.lazyLoadQueue,
middleware: () => {
return this.peerID == peerID;
}
});
break;
} else if(doc.mime_type == 'audio/ogg') {
@ -1479,11 +1513,11 @@ export class AppImManager { @@ -1479,11 +1513,11 @@ export class AppImManager {
/////////this.log('exec loadDialogPhoto', message);
if(message.fromID) { // if no - user hidden
appDialogsManager.loadDialogPhoto(avatarDiv, message.fromID);
appProfileManager.putPhoto(avatarDiv, message.fromID);
} else if(!title && message.fwd_from && message.fwd_from.from_name) {
title = message.fwd_from.from_name;
appDialogsManager.loadDialogPhoto(avatarDiv, 0, false, title);
appProfileManager.putPhoto(avatarDiv, 0, false, title);
}
avatarDiv.dataset.peerID = message.fromID;

3
src/lib/appManagers/appMediaViewer.ts

@ -9,6 +9,7 @@ import { findUpClassName, $rootScope, generatePathData } from "../utils"; @@ -9,6 +9,7 @@ import { findUpClassName, $rootScope, generatePathData } from "../utils";
import appDocsManager from "./appDocsManager";
import { wrapPlayer } from "../ckin";
import { renderImageFromUrl } from "../../components/misc";
import appProfileManager from "./appProfileManager";
export class AppMediaViewer {
private overlaysDiv = document.querySelector('.overlays') as HTMLDivElement;
@ -592,7 +593,7 @@ export class AppMediaViewer { @@ -592,7 +593,7 @@ export class AppMediaViewer {
this.content.caption.innerHTML = '';
}
appDialogsManager.loadDialogPhoto(this.author.avatarEl, message.fromID);
appProfileManager.putPhoto(this.author.avatarEl, message.fromID);
// ok set

152
src/lib/appManagers/appSidebarLeft.ts

@ -1,16 +1,14 @@ @@ -1,16 +1,14 @@
import { logger } from "../polyfill";
import { putPreloader, formatPhoneNumber } from "../../components/misc";
import { formatPhoneNumber } from "../../components/misc";
import Scrollable from '../../components/scrollable';
import appMessagesManager, { AppMessagesManager } from "./appMessagesManager";
import appMessagesManager from "./appMessagesManager";
import appDialogsManager from "./appDialogsManager";
import { isElementInViewport, numberWithCommas } from "../utils";
import { isElementInViewport, numberWithCommas, $rootScope } from "../utils";
import appMessagesIDsManager from "./appMessagesIDsManager";
import appImManager from "./appImManager";
import appUsersManager from "./appUsersManager";
import { appPeersManager } from "../services";
import apiManager from "../mtproto/apiManager";
let testScroll = false;
import appPeersManager from './appPeersManager';
class SearchGroup {
container: HTMLDivElement;
@ -56,18 +54,6 @@ class AppSidebarLeft { @@ -56,18 +54,6 @@ class AppSidebarLeft {
private listsContainer: HTMLDivElement = null;
private chatsArchivedContainer = document.getElementById('chats-archived-container') as HTMLDivElement;
private chatsContainer = document.getElementById('chats-container') as HTMLDivElement;
private chatsArchivedOffsetIndex = 0;
private chatsOffsetIndex = 0;
private chatsPreloader: HTMLDivElement;
//private chatsLoadCount = 0;
//private loadDialogsPromise: Promise<any>;
private loadDialogsPromise: ReturnType<AppMessagesManager["getConversations"]>;
private loadedAll = false;
private loadedArchivedAll = false;
private log = logger('SL');
private peerID = 0;
@ -81,37 +67,16 @@ class AppSidebarLeft { @@ -81,37 +67,16 @@ class AppSidebarLeft {
private query = '';
public scroll: Scrollable = null;
public scrollArchived: Scrollable = null;
public searchGroups: {[group: string]: SearchGroup} = {
contacts: new SearchGroup('Contacts and Chats', 'contacts'),
globalContacts: new SearchGroup('Global Search', 'contacts'),
globalMessages: new SearchGroup('Global Search', 'messages'),
privateMessages: new SearchGroup('Private Search', 'messages')
};
public searchGroups: {[group: string]: SearchGroup} = {};
constructor() {
this.chatsPreloader = putPreloader(null, true);
//this.chatsContainer.append(this.chatsPreloader);
//this.chatsLoadCount = Math.round(document.body.scrollHeight / 70 * 1.5);
let splitOffset = 1110;
this.scroll = new Scrollable(this.chatsContainer, 'y', splitOffset, 'CL', appDialogsManager.chatList, 500);
this.scroll.setVirtualContainer(appDialogsManager.chatList);
this.scroll.onScrolledBottom = this.onChatsScroll.bind(this);
appDialogsManager.chatsHidden = this.scroll.hiddenElements;
appDialogsManager.chatsVisible = this.scroll.visibleElements;
this.scrollArchived = new Scrollable(this.chatsArchivedContainer, 'y', splitOffset, 'CLA', appDialogsManager.chatListArchived, 500);
this.scrollArchived.setVirtualContainer(appDialogsManager.chatListArchived);
this.scrollArchived.onScrolledBottom = this.onChatsArchivedScroll.bind(this);
appDialogsManager.chatsArchivedHidden = this.scrollArchived.hiddenElements;
appDialogsManager.chatsArchivedVisible = this.scrollArchived.visibleElements;
//this.scrollArchived.container.addEventListener('scroll', this.onChatsArchivedScroll.bind(this));
this.searchGroups = {
contacts: new SearchGroup('Contacts and Chats', 'contacts'),
globalContacts: new SearchGroup('Global Search', 'contacts'),
globalMessages: new SearchGroup('Global Search', 'messages'),
privateMessages: new SearchGroup('Private Search', 'messages')
};
this.listsContainer = new Scrollable(this.searchContainer).container;
for(let i in this.searchGroups) {
this.listsContainer.append(this.searchGroups[i].container);
@ -126,7 +91,7 @@ class AppSidebarLeft { @@ -126,7 +91,7 @@ class AppSidebarLeft {
});
this.archivedBtn.addEventListener('click', (e) => {
this.chatsArchivedContainer.classList.add('active');
appDialogsManager.chatsArchivedContainer.classList.add('active');
this.toolsBtn.classList.remove('active');
this.backBtn.classList.add('active');
//this.toolsBtn.classList.remove('tgico-menu', 'btn-menu-toggle');
@ -137,15 +102,6 @@ class AppSidebarLeft { @@ -137,15 +102,6 @@ class AppSidebarLeft {
apiManager.logOut();
});
if(testScroll) {
for(let i = 0; i < 1000; ++i) {
let li = document.createElement('li');
li.dataset.id = '' + i;
li.innerHTML = `<div class="rp"><div class="user-avatar" style="background-color: rgb(166, 149, 231); font-size: 0px;"><img src="#"></div><div class="user-caption"><p><span class="user-title">${i}</span><span><span class="message-status"></span><span class="message-time">18:33</span></span></p><p><span class="user-last-message"><b>-_-_-_-: </b>qweasd</span><span></span></p></div></div>`;
this.scroll.append(li);
}
}
this.listsContainer.addEventListener('scroll', this.onSidebarScroll.bind(this));
this.searchInput.addEventListener('focus', (e) => {
@ -198,101 +154,31 @@ class AppSidebarLeft { @@ -198,101 +154,31 @@ class AppSidebarLeft {
});
this.backBtn.addEventListener('click', (e) => {
this.chatsArchivedContainer.classList.remove('active');
appDialogsManager.chatsArchivedContainer.classList.remove('active');
this.toolsBtn.classList.add('active');
this.backBtn.classList.remove('active');
this.searchInput.value = '';
this.searchContainer.classList.remove('active');
this.peerID = 0;
});
window.addEventListener('resize', () => {
//this.chatsLoadCount = Math.round(document.body.scrollHeight / 70 * 1.5);
setTimeout(() => {
this.onSidebarScroll();
this.scroll.onScroll();
//this.onChatsScroll();
this.onChatsArchivedScroll();
}, 0);
});
$rootScope.$on('dialogs_archived_unread', (e: CustomEvent) => {
this.archivedCount.innerText = '' + e.detail.count;
});
/* appUsersManager.getTopPeers().then(categories => {
this.log('got top categories:', categories);
}); */
}
public async loadDialogs(archived = false) {
if(testScroll) {
return;
}
if(this.loadDialogsPromise/* || 1 == 1 */) return this.loadDialogsPromise;
(archived ? this.chatsArchivedContainer : this.chatsContainer).append(this.chatsPreloader);
//let offset = appMessagesManager.generateDialogIndex();/* appMessagesManager.dialogsNum */;
let offset = archived ? this.chatsArchivedOffsetIndex : this.chatsOffsetIndex;
//let offset = 0;
let scroll = archived ? this.scrollArchived : this.scroll;
scroll.lock();
try {
console.time('getDialogs time');
let loadCount = 50/*this.chatsLoadCount */;
this.loadDialogsPromise = appMessagesManager.getConversations('', offset, loadCount, +archived);
let result = await this.loadDialogsPromise;
console.timeEnd('getDialogs time');
if(result && result.dialogs && result.dialogs.length) {
let index = result.dialogs[result.dialogs.length - 1].index;
if(archived) this.chatsArchivedOffsetIndex = index;
else this.chatsOffsetIndex = index;
result.dialogs.forEach((dialog: any) => {
appDialogsManager.addDialog(dialog);
});
}
if(!result.dialogs.length || (archived ? this.scrollArchived.length == result.count : this.scroll.length == result.count)) { // loaded all
if(archived) this.loadedArchivedAll = true;
else this.loadedAll = true;
}
/* if(archived) {
let count = result.count;
this.archivedCount.innerText = '' + count;
} */
this.log('getDialogs ' + loadCount + ' dialogs by offset:', offset, result, this.scroll.length);
this.scroll.onScroll();
} catch(err) {
this.log.error(err);
}
this.chatsPreloader.remove();
this.loadDialogsPromise = undefined;
scroll.unlock();
}
public onChatsScroll() {
if(this.loadedAll || this.scroll.hiddenElements.down.length > 0 || this.loadDialogsPromise/* || 1 == 1 */) return;
this.loadDialogs();
}
public onChatsArchivedScroll() {
if(this.loadedArchivedAll || this.scrollArchived.hiddenElements.down.length > 0 || this.loadDialogsPromise/* || 1 == 1 */) return;
this.loadDialogs(true);
}
public onSidebarScroll() {
if(!this.query.trim()) return;

2
src/lib/services.ts

@ -22,7 +22,6 @@ export const appChatsManager = AppChatsManager; @@ -22,7 +22,6 @@ export const appChatsManager = AppChatsManager;
export const appMessagesIDsManager = AppMessagesIDsManager;
export const apiUpdatesManager = ApiUpdatesManager;
export const appPhotosManager = AppPhotosManager;
export const appDialogsManager = AppDialogsManager;
export const appMessagesManager = AppMessagesManager;
export const appProfileManager = AppProfileManager;
export const appImManager = AppImManager;
@ -33,6 +32,7 @@ export const appDocsManager = AppDocsManager; @@ -33,6 +32,7 @@ export const appDocsManager = AppDocsManager;
export const appSidebarRight = AppSidebarRight;
export const appSidebarLeft = AppSidebarLeft;
export const appMediaViewer = AppMediaViewer;
export const appDialogsManager = AppDialogsManager;
(window as any).Services = {
appUsersManager,

10
src/lib/utils.js

@ -61,15 +61,6 @@ export function cancelEvent (event) { @@ -61,15 +61,6 @@ export function cancelEvent (event) {
return false
}
export function onCtrlEnter (textarea, cb) {
$(textarea).on('keydown', function (e) {
if (e.keyCode == 13 && (e.ctrlKey || e.metaKey)) {
cb()
return cancelEvent(e)
}
})
}
export function setFieldSelection (field, from, to) {
field = $(field)[0]
try {
@ -307,6 +298,7 @@ export const $rootScope = { @@ -307,6 +298,7 @@ export const $rootScope = {
},
selectedPeerID: 0,
myID: 0,
idle: {
isIDLE: false
}

28
src/pages/page.ts

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
import pagesManager from "./pagesManager";
export default class Page {
public pageEl: HTMLDivElement;
private installed = false;
constructor(className: string, public isAuthPage: boolean, private onFirstMount?: (...args: any[]) => void, private onMount?: (...args: any[]) => void) {
this.pageEl = document.body.getElementsByClassName(className)[0] as HTMLDivElement;
}
public mount(...args: any[]) {
//this.pageEl.style.display = '';
if(this.onMount) {
this.onMount(...args);
}
if(!this.installed) {
if(this.onFirstMount) {
this.onFirstMount(...args);
}
this.installed = true;
}
pagesManager.setPage(this);
}
}

550
src/components/pageAuthCode.ts → src/pages/pageAuthCode.ts

@ -1,276 +1,274 @@ @@ -1,276 +1,274 @@
import pageSignIn from './pageSignIn';
import pageSignUp from './pageSignUp';
import pageIm from './pageIm';
import pagePassword from './pagePassword';
import CryptoWorker from '../lib/crypto/cryptoworker';
import LottieLoader from '../lib/lottieLoader';
import apiManager from '../lib/mtproto/apiManager';
let installed = false;
let authCode: {
_: string, // 'auth.sentCode'
pFlags: any, // {}
flags: number,
type: {
_: string, // 'auth.sentCodeTypeSms',
length: number
},
phone_code_hash: string,
phone_number: string
} = null;
const EDITONSAMEPAGE = false;
export default async(_authCode: typeof authCode) => {
authCode = _authCode;
//let LottieLoader = (await import('../lib/lottieLoader')).default;
let pageElement = document.body.getElementsByClassName('page-authCode')[0] as HTMLDivElement;
pageElement.style.display = '';
let headerElement = pageElement.getElementsByClassName('phone')[0] as HTMLHeadElement;
headerElement.innerText = authCode.phone_number;
let sentTypeElement = pageElement.getElementsByClassName('sent-type')[0] as HTMLParagraphElement;
switch(authCode.type._) {
case 'auth.sentCodeTypeSms':
sentTypeElement.innerHTML = 'We have sent you an SMS<br>with the code.';
break;
case 'auth.sentCodeTypeApp':
sentTypeElement.innerHTML = 'We have sent you a message in Telegram<br>with the code.';
break;
case 'auth.sentCodeTypeCall':
sentTypeElement.innerHTML = 'We will call you and voice<br>the code.';
break;
default:
sentTypeElement.innerHTML = `Please check everything<br>for a code (type: ${authCode.type._})`;
break;
}
if(installed) return;
installed = true;
let needFrame = 0, lastLength = 0;
let animation: /* AnimationItem */any = undefined;
const CODELENGTH = authCode.type.length;
fetch('assets/img/TwoFactorSetupMonkeyTracking.tgs')
.then(res => res.arrayBuffer())
.then(async(data) => {
let str = await CryptoWorker.gzipUncompress<string>(data, true);
animation = await LottieLoader.loadAnimation({
container: document.body.querySelector('.page-authCode .auth-image'),
renderer: 'svg',
loop: false,
autoplay: false,
animationData: JSON.parse(str)
});
animation.setSpeed(1);
//console.log(animation.getDuration(), animation.getDuration(true));
animation.addEventListener('enterFrame', (e: any) => {
//console.log('enterFrame', e, needFrame);
let currentFrame = Math.round(e.currentTime);
if((e.direction == 1 && currentFrame >= needFrame) ||
(e.direction == -1 && currentFrame <= needFrame)) {
animation.setSpeed(1);
animation.pause();
}
});
});
const codeInput = document.getElementById('code') as HTMLInputElement;
const codeInputLabel = codeInput.nextElementSibling as HTMLLabelElement;
const editButton = document.querySelector('.phone-edit') as HTMLElement;
if(EDITONSAMEPAGE) {
let editable = false;
let changePhonePromise: Promise<unknown>;
let changePhone = () => {
if(changePhonePromise) return;
let phone_number = '+' + headerElement.innerText.replace(/\D/g, '');
if(authCode.phone_number == phone_number) return;
codeInput.setAttribute('disabled', 'true');
changePhonePromise = apiManager.invokeApi('auth.sendCode', {
/* flags: 0, */
phone_number: phone_number,
api_id: Config.App.id,
api_hash: Config.App.hash,
settings: {
_: 'codeSettings', // that's how we sending Type
flags: 0
}
/* lang_code: navigator.language || 'en' */
}).then((code: any) => {
console.log('got code 2', code);
authCode = Object.assign(code, {phone_number});
changePhonePromise = undefined;
codeInput.removeAttribute('disabled');
codeInput.focus();
}).catch(err => {
switch(err.type) {
case 'PHONE_NUMBER_INVALID':
headerElement.classList.add('error');
editable = true;
headerElement.setAttribute('contenteditable', '' + editable);
headerElement.focus();
break;
default:
codeInputLabel.innerText = err.type;
break;
}
changePhonePromise = undefined;
codeInput.removeAttribute('disabled');
});
};
headerElement.addEventListener('keypress', function(this, e) {
if(e.key == 'Enter') {
editable = false;
headerElement.setAttribute('contenteditable', '' + editable);
changePhone();
}
if(/\D/.test(e.key)) {
e.preventDefault();
return false;
}
this.classList.remove('error');
});
editButton.addEventListener('click', function() {
if(changePhonePromise) return;
editable = !editable;
headerElement.setAttribute('contenteditable', '' + editable);
if(!editable) changePhone();
});
} else {
editButton.addEventListener('click', function() {
pageElement.style.display = 'none';
return pageSignIn();
});
}
let submitCode = (code: string) => {
codeInput.setAttribute('disabled', 'true');
let params = {
phone_number: authCode.phone_number,
phone_code_hash: authCode.phone_code_hash,
phone_code: code
};
console.log('invoking auth.signIn with params:', params);
apiManager.invokeApi('auth.signIn', params)
.then((response: any) => {
console.log('auth.signIn response:', response);
switch(response._) {
case 'auth.authorization':
apiManager.setUserAuth({
id: response.user.id
});
pageElement.style.display = 'none';
pageIm();
if(animation) animation.destroy();
break;
case 'auth.authorizationSignUpRequired':
console.log('Registration needed!');
pageElement.style.display = 'none';
pageSignUp({
'phone_number': authCode.phone_number,
'phone_code_hash': authCode.phone_code_hash
});
if(animation) animation.destroy();
break;
default:
codeInput.innerText = response._;
break;
}
}).catch(err => {
codeInput.removeAttribute('disabled');
switch(err.type) {
case 'SESSION_PASSWORD_NEEDED':
console.warn('pageAuthCode: SESSION_PASSWORD_NEEDED');
err.handled = true;
pageElement.style.display = 'none';
if(animation) animation.destroy();
pagePassword();
break;
case 'PHONE_CODE_EMPTY':
case 'PHONE_CODE_INVALID':
codeInput.classList.add('error');
codeInputLabel.innerText = 'Invalid Code';
break;
default:
codeInputLabel.innerText = err.type;
break;
}
});
};
const max = 45;
// 1st symbol = frame 15
// end symbol = frame 165
codeInput.addEventListener('input', function(this: typeof codeInput, e) {
this.classList.remove('error');
this.value = this.value.replace(/\D/g, '');
if(this.value.length > CODELENGTH) {
this.value = this.value.slice(0, CODELENGTH);
}
let length = this.value.length;
if(length == CODELENGTH) { // submit code
submitCode(this.value);
} else if(length == lastLength) {
return;
}
lastLength = length;
if(!animation) return;
let frame: number;
if(length) frame = Math.round((length > max ? max : length) * (165 / max) + 11.33);
else frame = 0;
//animation.playSegments([1, 2]);
let direction = needFrame > frame ? -1 : 1;
//console.log('keydown', length, frame, direction);
// @ts-ignore
animation.setDirection(direction);
if(needFrame != 0 && frame == 0) {
animation.setSpeed(7);
}
/* let diff = Math.abs(needFrame - frame * direction);
if((diff / 20) > 1) animation.setSpeed(diff / 20 | 0); */
needFrame = frame;
animation.play();
/* animation.goToAndStop(15, true); */
//animation.goToAndStop(length / max * );
});
};
import pageSignIn from './pageSignIn';
import pageSignUp from './pageSignUp';
import pageIm from './pageIm';
import pagePassword from './pagePassword';
import CryptoWorker from '../lib/crypto/cryptoworker';
import LottieLoader from '../lib/lottieLoader';
import apiManager from '../lib/mtproto/apiManager';
import Page from './page';
let authCode: {
_: string, // 'auth.sentCode'
pFlags: any, // {}
flags: number,
type: {
_: string, // 'auth.sentCodeTypeSms',
length: number
},
phone_code_hash: string,
phone_number: string
} = null;
const EDITONSAMEPAGE = false;
let headerElement: HTMLHeadElement = null;
let sentTypeElement: HTMLParagraphElement = null;
let onFirstMount = () => {
let needFrame = 0, lastLength = 0;
let animation: /* AnimationItem */any = undefined;
const CODELENGTH = authCode.type.length;
fetch('assets/img/TwoFactorSetupMonkeyTracking.tgs')
.then(res => res.arrayBuffer())
.then(async(data) => {
let str = await CryptoWorker.gzipUncompress<string>(data, true);
animation = await LottieLoader.loadAnimation({
container: page.pageEl.querySelector('.auth-image'),
renderer: 'svg',
loop: false,
autoplay: false,
animationData: JSON.parse(str)
});
animation.setSpeed(1);
//console.log(animation.getDuration(), animation.getDuration(true));
animation.addEventListener('enterFrame', (e: any) => {
//console.log('enterFrame', e, needFrame);
let currentFrame = Math.round(e.currentTime);
if((e.direction == 1 && currentFrame >= needFrame) ||
(e.direction == -1 && currentFrame <= needFrame)) {
animation.setSpeed(1);
animation.pause();
}
});
});
const codeInput = page.pageEl.querySelector('#code') as HTMLInputElement;
const codeInputLabel = codeInput.nextElementSibling as HTMLLabelElement;
const editButton = page.pageEl.querySelector('.phone-edit') as HTMLElement;
if(EDITONSAMEPAGE) {
let editable = false;
let changePhonePromise: Promise<unknown>;
let changePhone = () => {
if(changePhonePromise) return;
let phone_number = '+' + headerElement.innerText.replace(/\D/g, '');
if(authCode.phone_number == phone_number) return;
codeInput.setAttribute('disabled', 'true');
changePhonePromise = apiManager.invokeApi('auth.sendCode', {
/* flags: 0, */
phone_number: phone_number,
api_id: Config.App.id,
api_hash: Config.App.hash,
settings: {
_: 'codeSettings', // that's how we sending Type
flags: 0
}
/* lang_code: navigator.language || 'en' */
}).then((code: any) => {
console.log('got code 2', code);
authCode = Object.assign(code, {phone_number});
changePhonePromise = undefined;
codeInput.removeAttribute('disabled');
codeInput.focus();
}).catch(err => {
switch(err.type) {
case 'PHONE_NUMBER_INVALID':
headerElement.classList.add('error');
editable = true;
headerElement.setAttribute('contenteditable', '' + editable);
headerElement.focus();
break;
default:
codeInputLabel.innerText = err.type;
break;
}
changePhonePromise = undefined;
codeInput.removeAttribute('disabled');
});
};
headerElement.addEventListener('keypress', function(this, e) {
if(e.key == 'Enter') {
editable = false;
headerElement.setAttribute('contenteditable', '' + editable);
changePhone();
}
if(/\D/.test(e.key)) {
e.preventDefault();
return false;
}
this.classList.remove('error');
});
editButton.addEventListener('click', function() {
if(changePhonePromise) return;
editable = !editable;
headerElement.setAttribute('contenteditable', '' + editable);
if(!editable) changePhone();
});
} else {
editButton.addEventListener('click', function() {
return pageSignIn.mount();
});
}
let submitCode = (code: string) => {
codeInput.setAttribute('disabled', 'true');
let params = {
phone_number: authCode.phone_number,
phone_code_hash: authCode.phone_code_hash,
phone_code: code
};
console.log('invoking auth.signIn with params:', params);
apiManager.invokeApi('auth.signIn', params)
.then((response: any) => {
console.log('auth.signIn response:', response);
switch(response._) {
case 'auth.authorization':
apiManager.setUserAuth({
id: response.user.id
});
pageIm.mount();
if(animation) animation.destroy();
break;
case 'auth.authorizationSignUpRequired':
console.log('Registration needed!');
pageSignUp.mount({
'phone_number': authCode.phone_number,
'phone_code_hash': authCode.phone_code_hash
});
if(animation) animation.destroy();
break;
default:
codeInput.innerText = response._;
break;
}
}).catch(err => {
codeInput.removeAttribute('disabled');
switch(err.type) {
case 'SESSION_PASSWORD_NEEDED':
console.warn('pageAuthCode: SESSION_PASSWORD_NEEDED');
err.handled = true;
if(animation) animation.destroy();
pagePassword.mount();
break;
case 'PHONE_CODE_EMPTY':
case 'PHONE_CODE_INVALID':
codeInput.classList.add('error');
codeInputLabel.innerText = 'Invalid Code';
break;
default:
codeInputLabel.innerText = err.type;
break;
}
});
};
const max = 45;
// 1st symbol = frame 15
// end symbol = frame 165
codeInput.addEventListener('input', function(this: typeof codeInput, e) {
this.classList.remove('error');
this.value = this.value.replace(/\D/g, '');
if(this.value.length > CODELENGTH) {
this.value = this.value.slice(0, CODELENGTH);
}
let length = this.value.length;
if(length == CODELENGTH) { // submit code
submitCode(this.value);
} else if(length == lastLength) {
return;
}
lastLength = length;
if(!animation) return;
let frame: number;
if(length) frame = Math.round((length > max ? max : length) * (165 / max) + 11.33);
else frame = 0;
//animation.playSegments([1, 2]);
let direction = needFrame > frame ? -1 : 1;
//console.log('keydown', length, frame, direction);
animation.setDirection(direction);
if(needFrame != 0 && frame == 0) {
animation.setSpeed(7);
}
/* let diff = Math.abs(needFrame - frame * direction);
if((diff / 20) > 1) animation.setSpeed(diff / 20 | 0); */
needFrame = frame;
animation.play();
/* animation.goToAndStop(15, true); */
//animation.goToAndStop(length / max * );
});
};
const page = new Page('page-authCode', true, onFirstMount, (_authCode: typeof authCode) => {
authCode = _authCode;
if(!headerElement) {
headerElement = page.pageEl.getElementsByClassName('phone')[0] as HTMLHeadElement;
sentTypeElement = page.pageEl.getElementsByClassName('sent-type')[0] as HTMLParagraphElement;
}
//let LottieLoader = (await import('../lib/lottieLoader')).default;
headerElement.innerText = authCode.phone_number;
switch(authCode.type._) {
case 'auth.sentCodeTypeSms':
sentTypeElement.innerHTML = 'We have sent you an SMS<br>with the code.';
break;
case 'auth.sentCodeTypeApp':
sentTypeElement.innerHTML = 'We have sent you a message in Telegram<br>with the code.';
break;
case 'auth.sentCodeTypeCall':
sentTypeElement.innerHTML = 'We will call you and voice<br>the code.';
break;
default:
sentTypeElement.innerHTML = `Please check everything<br>for a code (type: ${authCode.type._})`;
break;
}
});
export default page;

111
src/pages/pageIm.ts

@ -0,0 +1,111 @@ @@ -0,0 +1,111 @@
import { openBtnMenu, ripple } from "../components/misc";
//import {stackBlurImage} from '../lib/StackBlur';
import Page from "./page";
//import appImManager from '../lib/appManagers/appImManager';
let onFirstMount = () => import('../lib/appManagers/appImManager').then(() => {//import('../lib/services').then(services => {
//console.log('included services', services);
//export default () => {
/*
loadDialogs().then(result => {
//appImManager.setScroll(chatScroll);
});
return;
*/
/* function placeCaretAfterNode(node: HTMLElement) {
if (typeof window.getSelection != "undefined") {
var range = document.createRange();
range.setStartAfter(node);
range.collapse(true);
var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
}
}
messageInput.onclick = (e) => {
let target = e.target as HTMLElement;
if(target.classList.contains('emoji-inner')) {
placeCaretAfterNode(target.parentElement);
} else if(target.classList.contains('emoji-sizer')) {
placeCaretAfterNode(target);
}
console.log('lol', target);
}; */
/* window.addEventListener('click', function(this, e) {
// @ts-ignore
let isInput = e.target.tagName == 'INPUT';
if(!isInput && !window.getSelection().toString()) {
console.log('click');
messageInput.focus();
}
}); */
/* fetch('assets/img/camomile.jpg')
.then(res => res.blob())
.then(blob => {
let img = new Image();
let url = URL.createObjectURL(blob);
img.src = url;
img.onload = () => {
let id = 'chat-background-canvas';
var canvas = document.getElementById(id) as HTMLCanvasElement;
//URL.revokeObjectURL(url);
let elements = ['.chat-container'].map(selector => {
return document.querySelector(selector) as HTMLDivElement;
});
stackBlurImage(img, id, 15, 0);
canvas.toBlob(blob => {
//let dataUrl = canvas.toDataURL('image/jpeg', 1);
let dataUrl = URL.createObjectURL(blob);
elements.forEach(el => {
el.style.backgroundImage = 'url(' + dataUrl + ')';
});
}, 'image/jpeg', 1);
};
}); */
/* toggleEmoticons.onclick = (e) => {
if(!emoticonsDropdown) {
emoticonsDropdown = initEmoticonsDropdown(pageEl, appImManager,
appMessagesManager, messageInput, toggleEmoticons);
} else {
emoticonsDropdown.classList.toggle('active');
}
toggleEmoticons.classList.toggle('active');
}; */
(Array.from(document.getElementsByClassName('rp')) as HTMLElement[]).forEach(el => ripple(el));
Array.from(document.getElementsByClassName('btn-menu-toggle')).forEach((el) => {
el.addEventListener('click', (e) => {
//console.log('click pageIm');
if(!el.classList.contains('btn-menu-toggle')) return false;
//window.removeEventListener('mousemove', onMouseMove);
let openedMenu = el.querySelector('.btn-menu') as HTMLDivElement;
e.cancelBubble = true;
if(el.classList.contains('menu-open')) {
el.classList.remove('menu-open');
openedMenu.classList.remove('active');
} else {
openBtnMenu(openedMenu);
}
});
});
});
const page = new Page('page-chats', false, onFirstMount);
export default page;

267
src/components/pagePassword.ts → src/pages/pagePassword.ts

@ -1,136 +1,131 @@ @@ -1,136 +1,131 @@
import pageIm from './pageIm';
import CryptoWorker from '../lib/crypto/cryptoworker';
import { putPreloader } from './misc';
import LottieLoader from '../lib/lottieLoader';
import passwordManager from '../lib/mtproto/passwordManager';
import apiManager from '../lib/mtproto/apiManager';
let installed = false;
export default async() => {
//let LottieLoader = (await import('../lib/lottieLoader')).default;
if(installed) return;
installed = true;
let needFrame = 0;
let animation: /* AnimationItem */any = undefined;
let passwordVisible = false;
let pageElement = document.body.getElementsByClassName('page-password')[0] as HTMLDivElement;
pageElement.style.display = '';
fetch('assets/img/TwoFactorSetupMonkeyClose.tgs')
.then(res => res.arrayBuffer())
.then(async(data) => {
let str = await CryptoWorker.gzipUncompress<string>(data, true);
animation = await LottieLoader.loadAnimation({
container: pageElement.querySelector('.auth-image'),
renderer: 'svg',
loop: false,
autoplay: false,
animationData: JSON.parse(str)
});
console.log(animation.getDuration(true));
//animation.goToAndStop(822);
animation.addEventListener('enterFrame', (e: any) => {
//console.log('enterFrame', e, needFrame);
let currentFrame = Math.round(e.currentTime);
if((e.direction == 1 && currentFrame >= needFrame) ||
(e.direction == -1 && currentFrame <= needFrame)) {
animation.setSpeed(1);
animation.pause();
}
});
needFrame = 49;
animation.play();
});
const btnNext = pageElement.querySelector('button') as HTMLButtonElement;
const passwordInput = document.getElementById('password') as HTMLInputElement;
//const passwordInputLabel = passwordInput.nextElementSibling as HTMLLabelElement;
const toggleVisible = pageElement.querySelector('.toggle-visible') as HTMLSpanElement;
let handleError = (err: any) => {
btnNext.removeAttribute('disabled');
switch(err.type) {
default:
btnNext.innerText = err.type;
break;
}
};
toggleVisible.addEventListener('click', function(this, e) {
if(!passwordVisible) {
this.classList.add('tgico-eye2');
passwordInput.setAttribute('type', 'text');
animation.setDirection(-1);
needFrame = 0;
animation.play();
} else {
this.classList.remove('tgico-eye2');
passwordInput.setAttribute('type', 'password');
animation.setDirection(1);
needFrame = 49;
animation.play();
}
passwordVisible = !passwordVisible;
});
btnNext.addEventListener('click', function(this, e) {
if(!passwordInput.value.length) {
passwordInput.classList.add('error');
return;
}
this.setAttribute('disabled', 'true');
let value = passwordInput.value;
this.textContent = 'PLEASE WAIT...';
putPreloader(this);
passwordManager.getState()
.then(state => {
console.log(state);
passwordManager.check(state, value).then((response: any) => {
console.log('passwordManager response:', response);
switch(response._) {
case 'auth.authorization':
apiManager.setUserAuth({
id: response.user.id
});
pageElement.style.display = 'none';
pageIm();
if(animation) animation.destroy();
break;
default:
btnNext.removeAttribute('disabled');
btnNext.innerText = response._;
break;
}
}).catch(handleError);
}).catch(handleError);
});
passwordInput.addEventListener('keypress', function(this, e) {
this.classList.remove('error');
if(e.key == 'Enter') {
return btnNext.click();
}
});
/* passwordInput.addEventListener('input', function(this, e) {
}); */
};
import pageIm from './pageIm';
import CryptoWorker from '../lib/crypto/cryptoworker';
import { putPreloader } from '../components/misc';
import LottieLoader from '../lib/lottieLoader';
import passwordManager from '../lib/mtproto/passwordManager';
import apiManager from '../lib/mtproto/apiManager';
import Page from './page';
let onFirstMount = () => {
let needFrame = 0;
let animation: /* AnimationItem */any = undefined;
let passwordVisible = false;
fetch('assets/img/TwoFactorSetupMonkeyClose.tgs')
.then(res => res.arrayBuffer())
.then(async(data) => {
let str = await CryptoWorker.gzipUncompress<string>(data, true);
animation = await LottieLoader.loadAnimation({
container: page.pageEl.querySelector('.auth-image'),
renderer: 'svg',
loop: false,
autoplay: false,
animationData: JSON.parse(str)
});
console.log(animation.getDuration(true));
//animation.goToAndStop(822);
animation.addEventListener('enterFrame', (e: any) => {
//console.log('enterFrame', e, needFrame);
let currentFrame = Math.round(e.currentTime);
if((e.direction == 1 && currentFrame >= needFrame) ||
(e.direction == -1 && currentFrame <= needFrame)) {
animation.setSpeed(1);
animation.pause();
}
});
needFrame = 49;
animation.play();
});
const btnNext = page.pageEl.querySelector('button') as HTMLButtonElement;
const passwordInput = document.getElementById('password') as HTMLInputElement;
//const passwordInputLabel = passwordInput.nextElementSibling as HTMLLabelElement;
const toggleVisible = page.pageEl.querySelector('.toggle-visible') as HTMLSpanElement;
let handleError = (err: any) => {
btnNext.removeAttribute('disabled');
switch(err.type) {
default:
btnNext.innerText = err.type;
break;
}
};
toggleVisible.addEventListener('click', function(this, e) {
if(!passwordVisible) {
this.classList.add('tgico-eye2');
passwordInput.setAttribute('type', 'text');
animation.setDirection(-1);
needFrame = 0;
animation.play();
} else {
this.classList.remove('tgico-eye2');
passwordInput.setAttribute('type', 'password');
animation.setDirection(1);
needFrame = 49;
animation.play();
}
passwordVisible = !passwordVisible;
});
btnNext.addEventListener('click', function(this, e) {
if(!passwordInput.value.length) {
passwordInput.classList.add('error');
return;
}
this.setAttribute('disabled', 'true');
let value = passwordInput.value;
this.textContent = 'PLEASE WAIT...';
putPreloader(this);
passwordManager.getState()
.then(state => {
console.log(state);
passwordManager.check(state, value).then((response: any) => {
console.log('passwordManager response:', response);
switch(response._) {
case 'auth.authorization':
apiManager.setUserAuth({
id: response.user.id
});
pageIm.mount();
if(animation) animation.destroy();
break;
default:
btnNext.removeAttribute('disabled');
btnNext.innerText = response._;
break;
}
}).catch(handleError);
}).catch(handleError);
});
passwordInput.addEventListener('keypress', function(this, e) {
this.classList.remove('error');
if(e.key == 'Enter') {
return btnNext.click();
}
});
/* passwordInput.addEventListener('input', function(this, e) {
}); */
};
const page = new Page('page-password', true, onFirstMount);
export default page;

518
src/components/pageSignIn.ts → src/pages/pageSignIn.ts

@ -1,263 +1,255 @@ @@ -1,263 +1,255 @@
import { putPreloader, formatPhoneNumber } from "./misc";
import Scrollable from './scrollable';
import {RichTextProcessor} from '../lib/richtextprocessor';
import * as Config from '../lib/config';
import { findUpTag } from "../lib/utils";
import pageAuthCode from "./pageAuthCode";
import apiManager from "../lib/mtproto/apiManager";
let installed = false;
type Country = {
name: string,
code: string,
phoneCode: string,
pattern: string,
emoji: string,
li?: HTMLLIElement[]
};
//import _countries from '../countries_pretty.json';
export default () => {
//export default () => import('../countries.json').then(_countries => {
//let pageAuthCode = await import('./pageAuthCode');
//Array.from(document.querySelectorAll('body > .whole:not(.page-authCode)')).forEach(div => div.style.display = 'none');
const pageEl = document.body.getElementsByClassName('page-sign')[0] as HTMLDivElement;
pageEl.style.display = '';
let btnNext = pageEl.querySelector('button');
if(installed) {
btnNext.textContent = 'NEXT';
btnNext.removeAttribute('disabled');
return;
}
installed = true;
//const countries: Country[] = _countries.default.filter(c => c.emoji);
const countries: Country[] = Config.Countries.filter(c => c.emoji).sort((a, b) => a.name.localeCompare(b.name));
let lastCountrySelected = '';
var selectCountryCode = pageEl.querySelector('input[name="countryCode"]')! as HTMLInputElement;
var parent = selectCountryCode.parentElement;
var wrapper = document.createElement('div');
wrapper.classList.add('select-wrapper', 'z-depth-4');
var list = document.createElement('ul');
wrapper.appendChild(list);
//let wrapperScroll = OverlayScrollbars(wrapper, (window as any).scrollbarOptions);
let scroll = new Scrollable(wrapper);
let initedSelect = false;
selectCountryCode.addEventListener('focus', function(this: typeof selectCountryCode, e) {
/* this.removeAttribute('readonly'); */
if(!initedSelect) {
countries.forEach((c) => {
initedSelect = true;
/* let unified = unifiedCountryCodeEmoji(c.code);
let emoji = unified.split('-').reduce((prev, curr) => prev + String.fromCodePoint(parseInt(curr, 16)), ''); */
//let emoji = countryCodeEmoji(c.code);
let emoji = c.emoji;
let liArr: Array<HTMLLIElement> = [];
c.phoneCode.split(' and ').forEach((phoneCode: string) => {
let li = document.createElement('li');
var spanEmoji = document.createElement('span');
/* spanEmoji.innerHTML = countryCodeEmoji(c.code); */
//spanEmoji.classList.add('emoji-outer', 'emoji-sizer');
//spanEmoji.innerHTML = `<span class="emoji-inner" style="background: url(${sheetUrl}${sheetNo}.png);background-position:${xPos}% ${yPos}%;background-size:${sizeX}% ${sizeY}%" data-codepoints="${unified}"></span>`;
let kek = RichTextProcessor.wrapRichText(emoji);
//console.log(c.name, emoji, kek, spanEmoji.innerHTML);
li.appendChild(spanEmoji);
spanEmoji.outerHTML = kek;
li.append(c.name);
var span = document.createElement('span');
span.classList.add('phone-code');
span.innerText = '+' + phoneCode;
li.appendChild(span);
liArr.push(li);
list.append(li);
});
c.li = liArr;
});
list.addEventListener('mousedown', function(e) {
let target = e.target as HTMLElement;
if(target.tagName != 'LI') target = findUpTag(target, 'LI');
let countryName = target.childNodes[1].textContent;//target.innerText.split('\n').shift();
let phoneCode = target.querySelector<HTMLElement>('.phone-code').innerText;
selectCountryCode.value = countryName;
lastCountrySelected = countryName;
telEl.value = phoneCode;
setTimeout(() => telEl.focus(), 0);
console.log('clicked', e, countryName, phoneCode);
});
}
parent.appendChild(wrapper);
}/* , {once: true} */);
selectCountryCode.addEventListener('blur', function(this: typeof selectCountryCode, e) {
parent.removeChild(wrapper);
e.cancelBubble = true;
}, {capture: true});
selectCountryCode.addEventListener('keyup', function(this: typeof selectCountryCode, e) {
if(e.ctrlKey || e.key == 'Control') return false;
//let i = new RegExp('^' + this.value, 'i');
let _value = this.value.toLowerCase();
let matches: Country[] = [];
countries.forEach((c) => {
let good = c.name.toLowerCase().indexOf(_value) !== -1/* == 0 */;//i.test(c.name);
c.li.forEach(li => li.style.display = good ? '' : 'none');
if(good) matches.push(c);
});
if(matches.length == 1 && matches[0].li.length == 1) {
if(matches[0].name == lastCountrySelected) return false;
console.log('clicking', matches[0]);
var clickEvent = document.createEvent('MouseEvents');
clickEvent.initEvent('mousedown', true, true);
matches[0].li[0].dispatchEvent(clickEvent);
return false;
} else if(matches.length == 0) {
countries.forEach((c) => {
c.li.forEach(li => li.style.display = '');
});
}
});
let arrowDown = pageEl.querySelector('.arrow-down') as HTMLSpanElement;
arrowDown.addEventListener('mousedown', function(this: typeof arrowDown, e) {
e.cancelBubble = true;
e.preventDefault();
if(selectCountryCode.matches(':focus')) selectCountryCode.blur();
else selectCountryCode.focus();
});
let sortedCountries = countries.slice().sort((a, b) => b.phoneCode.length - a.phoneCode.length);
let telEl = pageEl.querySelector('input[name="phone"]') as HTMLInputElement;
telEl.addEventListener('input', function(this: typeof telEl, e) {
this.classList.remove('error');
let {formatted, country} = formatPhoneNumber(this.value);
this.value = formatted ? '+' + formatted : '';
console.log(formatted, country);
let countryName = country ? country.name : ''/* 'Unknown' */;
if(countryName != selectCountryCode.value) {
selectCountryCode.value = countryName;
lastCountrySelected = countryName;
}
if(country && (this.value.length - 1) >= (country.pattern ? country.pattern.length : 9)) {
btnNext.style.visibility = '';
} else {
btnNext.style.visibility = 'hidden';
}
});
telEl.addEventListener('keypress', function(this: typeof telEl, e) {
if(this.value.length >= 9 && e.key == 'Enter') {
return btnNext.click();
} else if(/\D/.test(e.key)) {
e.preventDefault();
return false;
}
});
/* telEl.addEventListener('focus', function(this: typeof telEl, e) {
this.removeAttribute('readonly'); // fix autocomplete
});*/
/* authorizer.auth(2);
networkerFactory.startAll(); */
btnNext.addEventListener('click', function(this: HTMLElement, e) {
this.setAttribute('disabled', 'true');
this.textContent = 'PLEASE WAIT...';
putPreloader(this);
//this.innerHTML = 'PLEASE WAIT...';
let phone_number = telEl.value;
apiManager.invokeApi('auth.sendCode', {
/* flags: 0, */
phone_number: phone_number,
api_id: Config.App.id,
api_hash: Config.App.hash,
settings: {
_: 'codeSettings', // that's how we sending Type
flags: 0
}
/* lang_code: navigator.language || 'en' */
}).then((code: any) => {
console.log('got code', code);
pageEl.style.display = 'none';
// @ts-ignore
pageAuthCode(Object.assign(code, {phone_number: phone_number}));
}).catch(err => {
this.removeAttribute('disabled');
this.innerText = 'NEXT';
switch(err.type) {
case 'PHONE_NUMBER_INVALID':
telEl.classList.add('error');
break;
default:
this.innerText = err.type;
break;
}
});
});
let tryAgain = () => {
apiManager.invokeApi('help.getNearestDc').then((nearestDcResult: any) => {
if(nearestDcResult.nearest_dc != nearestDcResult.this_dc) {
//MTProto.apiManager.baseDcID = nearestDcResult.nearest_dc;
apiManager.getNetworker(nearestDcResult.nearest_dc);
}
return nearestDcResult;
}).then((nearestDcResult: any) => {
let country = countries.find((c) => c.code == nearestDcResult.country);
if(country) {
if(!selectCountryCode.value.length && !telEl.value.length) {
selectCountryCode.value = country.name;
lastCountrySelected = country.name;
telEl.value = '+' + country.phoneCode.split(' and ').shift();
}
}
return console.log('woohoo', nearestDcResult, country);
})//.catch(tryAgain);
};
tryAgain();
};
import { putPreloader, formatPhoneNumber } from "../components/misc";
import Scrollable from '../components/scrollable';
import {RichTextProcessor} from '../lib/richtextprocessor';
import * as Config from '../lib/config';
import { findUpTag } from "../lib/utils";
import pageAuthCode from "./pageAuthCode";
import apiManager from "../lib/mtproto/apiManager";
import Page from "./page";
type Country = {
name: string,
code: string,
phoneCode: string,
pattern: string,
emoji: string,
li?: HTMLLIElement[]
};
//import _countries from '../countries_pretty.json';
let btnNext: HTMLButtonElement = null;
let onFirstMount = () => {
//const countries: Country[] = _countries.default.filter(c => c.emoji);
const countries: Country[] = Config.Countries.filter(c => c.emoji).sort((a, b) => a.name.localeCompare(b.name));
let lastCountrySelected = '';
var selectCountryCode = page.pageEl.querySelector('input[name="countryCode"]')! as HTMLInputElement;
var parent = selectCountryCode.parentElement;
var wrapper = document.createElement('div');
wrapper.classList.add('select-wrapper', 'z-depth-4');
var list = document.createElement('ul');
wrapper.appendChild(list);
//let wrapperScroll = OverlayScrollbars(wrapper, (window as any).scrollbarOptions);
let scroll = new Scrollable(wrapper);
let initedSelect = false;
selectCountryCode.addEventListener('focus', function(this: typeof selectCountryCode, e) {
/* this.removeAttribute('readonly'); */
if(!initedSelect) {
countries.forEach((c) => {
initedSelect = true;
/* let unified = unifiedCountryCodeEmoji(c.code);
let emoji = unified.split('-').reduce((prev, curr) => prev + String.fromCodePoint(parseInt(curr, 16)), ''); */
//let emoji = countryCodeEmoji(c.code);
let emoji = c.emoji;
let liArr: Array<HTMLLIElement> = [];
c.phoneCode.split(' and ').forEach((phoneCode: string) => {
let li = document.createElement('li');
var spanEmoji = document.createElement('span');
/* spanEmoji.innerHTML = countryCodeEmoji(c.code); */
//spanEmoji.classList.add('emoji-outer', 'emoji-sizer');
//spanEmoji.innerHTML = `<span class="emoji-inner" style="background: url(${sheetUrl}${sheetNo}.png);background-position:${xPos}% ${yPos}%;background-size:${sizeX}% ${sizeY}%" data-codepoints="${unified}"></span>`;
let kek = RichTextProcessor.wrapRichText(emoji);
//console.log(c.name, emoji, kek, spanEmoji.innerHTML);
li.appendChild(spanEmoji);
spanEmoji.outerHTML = kek;
li.append(c.name);
var span = document.createElement('span');
span.classList.add('phone-code');
span.innerText = '+' + phoneCode;
li.appendChild(span);
liArr.push(li);
list.append(li);
});
c.li = liArr;
});
list.addEventListener('mousedown', function(e) {
let target = e.target as HTMLElement;
if(target.tagName != 'LI') target = findUpTag(target, 'LI');
let countryName = target.childNodes[1].textContent;//target.innerText.split('\n').shift();
let phoneCode = target.querySelector<HTMLElement>('.phone-code').innerText;
selectCountryCode.value = countryName;
lastCountrySelected = countryName;
telEl.value = phoneCode;
setTimeout(() => telEl.focus(), 0);
console.log('clicked', e, countryName, phoneCode);
});
}
parent.appendChild(wrapper);
}/* , {once: true} */);
selectCountryCode.addEventListener('blur', function(this: typeof selectCountryCode, e) {
parent.removeChild(wrapper);
e.cancelBubble = true;
}, {capture: true});
selectCountryCode.addEventListener('keyup', function(this: typeof selectCountryCode, e) {
if(e.ctrlKey || e.key == 'Control') return false;
//let i = new RegExp('^' + this.value, 'i');
let _value = this.value.toLowerCase();
let matches: Country[] = [];
countries.forEach((c) => {
let good = c.name.toLowerCase().indexOf(_value) !== -1/* == 0 */;//i.test(c.name);
c.li.forEach(li => li.style.display = good ? '' : 'none');
if(good) matches.push(c);
});
if(matches.length == 1 && matches[0].li.length == 1) {
if(matches[0].name == lastCountrySelected) return false;
console.log('clicking', matches[0]);
var clickEvent = document.createEvent('MouseEvents');
clickEvent.initEvent('mousedown', true, true);
matches[0].li[0].dispatchEvent(clickEvent);
return false;
} else if(matches.length == 0) {
countries.forEach((c) => {
c.li.forEach(li => li.style.display = '');
});
}
});
let arrowDown = page.pageEl.querySelector('.arrow-down') as HTMLSpanElement;
arrowDown.addEventListener('mousedown', function(this: typeof arrowDown, e) {
e.cancelBubble = true;
e.preventDefault();
if(selectCountryCode.matches(':focus')) selectCountryCode.blur();
else selectCountryCode.focus();
});
let sortedCountries = countries.slice().sort((a, b) => b.phoneCode.length - a.phoneCode.length);
let telEl = page.pageEl.querySelector('input[name="phone"]') as HTMLInputElement;
telEl.addEventListener('input', function(this: typeof telEl, e) {
this.classList.remove('error');
let {formatted, country} = formatPhoneNumber(this.value);
this.value = formatted ? '+' + formatted : '';
console.log(formatted, country);
let countryName = country ? country.name : ''/* 'Unknown' */;
if(countryName != selectCountryCode.value) {
selectCountryCode.value = countryName;
lastCountrySelected = countryName;
}
if(country && (this.value.length - 1) >= (country.pattern ? country.pattern.length : 9)) {
btnNext.style.visibility = '';
} else {
btnNext.style.visibility = 'hidden';
}
});
telEl.addEventListener('keypress', function(this: typeof telEl, e) {
if(this.value.length >= 9 && e.key == 'Enter') {
return btnNext.click();
} else if(/\D/.test(e.key)) {
e.preventDefault();
return false;
}
});
/* telEl.addEventListener('focus', function(this: typeof telEl, e) {
this.removeAttribute('readonly'); // fix autocomplete
});*/
/* authorizer.auth(2);
networkerFactory.startAll(); */
btnNext.addEventListener('click', function(this: HTMLElement, e) {
this.setAttribute('disabled', 'true');
this.textContent = 'PLEASE WAIT...';
putPreloader(this);
//this.innerHTML = 'PLEASE WAIT...';
let phone_number = telEl.value;
apiManager.invokeApi('auth.sendCode', {
/* flags: 0, */
phone_number: phone_number,
api_id: Config.App.id,
api_hash: Config.App.hash,
settings: {
_: 'codeSettings', // that's how we sending Type
flags: 0
}
/* lang_code: navigator.language || 'en' */
}).then((code: any) => {
console.log('got code', code);
pageAuthCode.mount(Object.assign(code, {phone_number: phone_number}));
}).catch(err => {
this.removeAttribute('disabled');
this.innerText = 'NEXT';
switch(err.type) {
case 'PHONE_NUMBER_INVALID':
telEl.classList.add('error');
break;
default:
console.error('auth.sendCode error:', err);
this.innerText = err.type;
break;
}
});
});
let tryAgain = () => {
apiManager.invokeApi('help.getNearestDc').then((nearestDcResult: any) => {
if(nearestDcResult.nearest_dc != nearestDcResult.this_dc) {
//MTProto.apiManager.baseDcID = nearestDcResult.nearest_dc;
apiManager.getNetworker(nearestDcResult.nearest_dc);
}
return nearestDcResult;
}).then((nearestDcResult: any) => {
let country = countries.find((c) => c.code == nearestDcResult.country);
if(country) {
if(!selectCountryCode.value.length && !telEl.value.length) {
selectCountryCode.value = country.name;
lastCountrySelected = country.name;
telEl.value = '+' + country.phoneCode.split(' and ').shift();
}
}
return console.log('woohoo', nearestDcResult, country);
})//.catch(tryAgain);
};
tryAgain();
};
const page = new Page('page-sign', true, onFirstMount, () => {
if(!btnNext) {
btnNext = page.pageEl.querySelector('button');
}
btnNext.textContent = 'NEXT';
btnNext.removeAttribute('disabled');
});
export default page;

393
src/components/pageSignUp.ts → src/pages/pageSignUp.ts

@ -1,198 +1,195 @@ @@ -1,198 +1,195 @@
import {putPreloader} from './misc';
let installed = false;
let authCode: {
'phone_number': string,
'phone_code_hash': string
} = null;
import resizeableImage from '../lib/cropper';
import pageIm from './pageIm';
import apiManager from '../lib/mtproto/apiManager';
import apiFileManager from '../lib/mtproto/apiFileManager';
export default (_authCode: typeof authCode) => {
authCode = _authCode;
if(installed) return;
installed = true;
let pageElement = document.body.getElementsByClassName('page-signUp')[0] as HTMLDivElement;
pageElement.style.display = '';
const avatarInput = document.getElementById('avatar-input') as HTMLInputElement;
const avatarPopup = pageElement.getElementsByClassName('popup-avatar')[0];
const avatarPreview = pageElement.querySelector('#canvas-avatar') as HTMLCanvasElement;
const cropContainer = avatarPopup.getElementsByClassName('crop')[0];
let avatarImage = new Image();
cropContainer.append(avatarImage);
let avatarBlob: Blob;
(avatarPopup.getElementsByClassName('popup-close')[0] as HTMLButtonElement)
.addEventListener('click', function(this, e) {
/* let popup = findUpClassName(this, 'popup');
popup.classList.remove('active'); */
setTimeout(() => {
cropper.removeHandlers();
if(avatarImage) {
avatarImage.remove();
}
}, 200);
/* e.cancelBubble = true;
return false; */
});
let cropper = {
crop: () => {},
removeHandlers: () => {}
};
// apply
avatarPopup.getElementsByClassName('btn-crop')[0].addEventListener('click', () => {
cropper.crop();
avatarPopup.classList.remove('active');
cropper.removeHandlers();
avatarPreview.toBlob(blob => {
avatarBlob = blob; // save blob to send after reg
// darken
let ctx = avatarPreview.getContext('2d');
ctx.fillStyle = "rgba(0, 0, 0, 0.3)";
ctx.fillRect(0, 0, avatarPreview.width, avatarPreview.height);
}, 'image/jpeg', 1);
avatarImage.remove();
});
avatarInput.addEventListener('change', (e: any) => {
var file = e.target.files[0];
if(!file) {
return;
}
var reader = new FileReader();
reader.onload = (e) => {
var contents = e.target.result as string;
avatarImage = new Image();
cropContainer.append(avatarImage);
avatarImage.src = contents;
avatarImage.onload = () => {
cropper = resizeableImage(avatarImage, avatarPreview);
avatarInput.value = '';
};
avatarPopup.classList.add('active');
};
reader.readAsDataURL(file);
}, false);
pageElement.querySelector('.auth-image').addEventListener('click', () => {
avatarInput.click();
});
const headerName = pageElement.getElementsByClassName('fullName')[0] as HTMLHeadingElement;
let handleInput = function(this: typeof fieldName, e: Event) {
let name = fieldName.value || '';
let lastName = fieldLastName.value || '';
let fullName = name || lastName
? (name + ' ' + lastName).trim()
: 'Your Name';
if(headerName.innerText != fullName) headerName.innerText = fullName;
this.classList.remove('error');
};
let sendAvatar = () => new Promise((resolve, reject) => {
if(!avatarBlob) {
console.log('User has not selected avatar');
return resolve();
}
console.log('invoking uploadFile...');
apiFileManager.uploadFile(avatarBlob).then((inputFile: any) => {
console.log('uploaded smthn', inputFile);
apiManager.invokeApi('photos.uploadProfilePhoto', {
file: inputFile
}).then((updateResult) => {
console.log('updated photo!');
resolve();
}, reject);
}, reject);
});
const fieldName = document.getElementById('name') as HTMLInputElement;
fieldName.addEventListener('input', handleInput);
const fieldLastName = document.getElementById('lastName') as HTMLInputElement;
fieldLastName.addEventListener('input', handleInput);
const signUpButton = document.getElementById('signUp') as HTMLButtonElement;
signUpButton.addEventListener('click', function(this: typeof signUpButton, e) {
this.setAttribute('disabled', 'true');
if(!fieldName.value.length) {
fieldName.classList.add('error');
return false;
}
let name = fieldName.value;
let lastName = fieldLastName.value;
let params = {
'phone_number': authCode.phone_number,
'phone_code_hash': authCode.phone_code_hash,
'first_name': name,
'last_name': lastName
};
console.log('invoking auth.signUp with params:', params);
this.textContent = 'PLEASE WAIT...';
putPreloader(this);
apiManager.invokeApi('auth.signUp', params)
.then((response: any) => {
console.log('auth.signUp response:', response);
switch(response._) {
case 'auth.authorization': // success
apiManager.setUserAuth({ // warning
id: response.user.id
});
sendAvatar().then(() => {
pageElement.style.display = 'none';
pageIm();
}, () => {
pageElement.style.display = 'none';
pageIm();
});
break;
default:
this.innerText = response._;
break;
}
/* (document.body.getElementsByClassName('page-sign')[0] as HTMLDivElement).style.display = 'none';
pageAuthCode(Object.assign(code, {phoneNumber})); */
}).catch(err => {
this.removeAttribute('disabled');
switch(err.type) {
default:
this.innerText = err.type;
break;
}
});
});
};
import {putPreloader} from '../components/misc';
import resizeableImage from '../lib/cropper';
import pageIm from './pageIm';
import apiManager from '../lib/mtproto/apiManager';
import apiFileManager from '../lib/mtproto/apiFileManager';
import Page from './page';
let authCode: {
'phone_number': string,
'phone_code_hash': string
} = null;
let onFirstMount = () => {
const pageElement = page.pageEl;
const avatarInput = document.getElementById('avatar-input') as HTMLInputElement;
const avatarPopup = pageElement.getElementsByClassName('popup-avatar')[0];
const avatarPreview = pageElement.querySelector('#canvas-avatar') as HTMLCanvasElement;
const cropContainer = avatarPopup.getElementsByClassName('crop')[0];
let avatarImage = new Image();
cropContainer.append(avatarImage);
let avatarBlob: Blob;
(avatarPopup.getElementsByClassName('popup-close')[0] as HTMLButtonElement)
.addEventListener('click', function(this, e) {
/* let popup = findUpClassName(this, 'popup');
popup.classList.remove('active'); */
setTimeout(() => {
cropper.removeHandlers();
if(avatarImage) {
avatarImage.remove();
}
}, 200);
/* e.cancelBubble = true;
return false; */
});
let cropper = {
crop: () => {},
removeHandlers: () => {}
};
// apply
avatarPopup.getElementsByClassName('btn-crop')[0].addEventListener('click', () => {
cropper.crop();
avatarPopup.classList.remove('active');
cropper.removeHandlers();
avatarPreview.toBlob(blob => {
avatarBlob = blob; // save blob to send after reg
// darken
let ctx = avatarPreview.getContext('2d');
ctx.fillStyle = "rgba(0, 0, 0, 0.3)";
ctx.fillRect(0, 0, avatarPreview.width, avatarPreview.height);
}, 'image/jpeg', 1);
avatarImage.remove();
});
avatarInput.addEventListener('change', (e: any) => {
var file = e.target.files[0];
if(!file) {
return;
}
var reader = new FileReader();
reader.onload = (e) => {
var contents = e.target.result as string;
avatarImage = new Image();
cropContainer.append(avatarImage);
avatarImage.src = contents;
avatarImage.onload = () => {
cropper = resizeableImage(avatarImage, avatarPreview);
avatarInput.value = '';
};
avatarPopup.classList.add('active');
};
reader.readAsDataURL(file);
}, false);
pageElement.querySelector('.auth-image').addEventListener('click', () => {
avatarInput.click();
});
const headerName = pageElement.getElementsByClassName('fullName')[0] as HTMLHeadingElement;
let handleInput = function(this: typeof fieldName, e: Event) {
let name = fieldName.value || '';
let lastName = fieldLastName.value || '';
let fullName = name || lastName
? (name + ' ' + lastName).trim()
: 'Your Name';
if(headerName.innerText != fullName) headerName.innerText = fullName;
this.classList.remove('error');
};
let sendAvatar = () => new Promise((resolve, reject) => {
if(!avatarBlob) {
console.log('User has not selected avatar');
return resolve();
}
console.log('invoking uploadFile...');
apiFileManager.uploadFile(avatarBlob).then((inputFile: any) => {
console.log('uploaded smthn', inputFile);
apiManager.invokeApi('photos.uploadProfilePhoto', {
file: inputFile
}).then((updateResult) => {
console.log('updated photo!');
resolve();
}, reject);
}, reject);
});
const fieldName = document.getElementById('name') as HTMLInputElement;
fieldName.addEventListener('input', handleInput);
const fieldLastName = document.getElementById('lastName') as HTMLInputElement;
fieldLastName.addEventListener('input', handleInput);
const signUpButton = document.getElementById('signUp') as HTMLButtonElement;
signUpButton.addEventListener('click', function(this: typeof signUpButton, e) {
this.setAttribute('disabled', 'true');
if(!fieldName.value.length) {
fieldName.classList.add('error');
return false;
}
let name = fieldName.value;
let lastName = fieldLastName.value;
let params = {
'phone_number': authCode.phone_number,
'phone_code_hash': authCode.phone_code_hash,
'first_name': name,
'last_name': lastName
};
console.log('invoking auth.signUp with params:', params);
this.textContent = 'PLEASE WAIT...';
putPreloader(this);
apiManager.invokeApi('auth.signUp', params)
.then((response: any) => {
console.log('auth.signUp response:', response);
switch(response._) {
case 'auth.authorization': // success
apiManager.setUserAuth({ // warning
id: response.user.id
});
sendAvatar().then(() => {
pageIm.mount();
}, () => {
pageIm.mount();
});
break;
default:
this.innerText = response._;
break;
}
/* (document.body.getElementsByClassName('page-sign')[0] as HTMLDivElement).style.display = 'none';
pageAuthCode(Object.assign(code, {phoneNumber})); */
}).catch(err => {
this.removeAttribute('disabled');
switch(err.type) {
default:
this.innerText = err.type;
break;
}
});
});
};
const page = new Page('page-signUp', true, onFirstMount, (_authCode: typeof authCode) => {
authCode = _authCode;
});
export default page;

37
src/pages/pagesManager.ts

@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
import Page from "./page";
import { whichChild } from "../lib/utils";
import { horizontalMenu } from "../components/misc";
class PagesManager {
private pageID = -1;
private selectTab: ReturnType<typeof horizontalMenu>;
public pagesDiv: HTMLDivElement;
constructor() {
this.pagesDiv = document.getElementById('auth-pages') as HTMLDivElement;
this.selectTab = horizontalMenu(null, this.pagesDiv.firstElementChild as HTMLDivElement, null, null, 420);
}
public setPage(page: Page) {
if(page.isAuthPage) {
this.pagesDiv.style.display = '';
let id = whichChild(page.pageEl);
if(this.pageID == id) return;
this.selectTab(id);
this.pageID = id;
} else {
this.pagesDiv.style.display = 'none';
page.pageEl.style.display = '';
this.pageID = -1;
}
}
}
const pagesManager = new PagesManager();
(window as any).pagesManager = pagesManager;
export default pagesManager;

2
src/scss/partials/_leftSidebar.scss

@ -62,7 +62,7 @@ @@ -62,7 +62,7 @@
}
&.active {
margin-top: 1px;
//margin-top: 1px;
opacity: 1;
visibility: visible;
color: #707579;

35
src/scss/style.scss

@ -133,8 +133,8 @@ input { @@ -133,8 +133,8 @@ input {
.btn-icon {
text-align: center;
font-size: 1.65rem;
line-height: 1.65rem;
font-size: 1.5rem;
line-height: 1.5rem;
border-radius: 50%;
-webkit-transition: background-color .15s ease-out;
transition: background-color .15s ease-out;
@ -496,6 +496,32 @@ input { @@ -496,6 +496,32 @@ input {
}
}
#auth-pages {
max-width: 720px; // 360 + 360 / 2
overflow: hidden;
.tabs-container {
&.animated {
transition: .42s transform;
}
> div {
justify-content: center;
/* &.active {
flex-direction: row;
} */
> div {
padding: 0;
overflow: visible;
/* display: flex;
flex-direction: column;
justify-content: center; */
}
}
}
}
.page-sign {
.auth-image {
width: 160px;
@ -1302,7 +1328,7 @@ div.scrollable::-webkit-scrollbar-thumb { @@ -1302,7 +1328,7 @@ div.scrollable::-webkit-scrollbar-thumb {
max-height: 100%;
//position: relative;
will-change: transform;
//will-change: transform;
transform: translateZ(0);
-webkit-transform: translateZ(0);
@ -1412,12 +1438,13 @@ div.scrollable::-webkit-scrollbar-thumb { @@ -1412,12 +1438,13 @@ div.scrollable::-webkit-scrollbar-thumb {
.tabs-container {
min-width: 100%;
width: 100%;
display: flex;
/* overflow: hidden; */
overflow-x: hidden;
&.animated {
transition: .2s margin-left;
transition: .3s transform;
}
> div {

Loading…
Cancel
Save