morethanwords
4 years ago
18 changed files with 1465 additions and 1413 deletions
@ -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); |
||||
}); |
||||
}); |
@ -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); |
||||
} |
||||
} |
@ -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; |
@ -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; |
@ -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; |
@ -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; |
@ -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; |
@ -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; |
Loading…
Reference in new issue