Input label animation fix
This commit is contained in:
parent
482bba88ce
commit
2cd69f7d98
@ -24,7 +24,7 @@ import animationIntersector from "../animationIntersector";
|
|||||||
import { months } from "../../helpers/date";
|
import { months } from "../../helpers/date";
|
||||||
import RichTextProcessor from "../../lib/richtextprocessor";
|
import RichTextProcessor from "../../lib/richtextprocessor";
|
||||||
import mediaSizes from "../../helpers/mediaSizes";
|
import mediaSizes from "../../helpers/mediaSizes";
|
||||||
import { isAndroid, isApple, isSafari } from "../../helpers/userAgent";
|
import { isAndroid, isApple, isSafari, isAppleMobile } from "../../helpers/userAgent";
|
||||||
import { langPack } from "../../lib/langPack";
|
import { langPack } from "../../lib/langPack";
|
||||||
import AvatarElement from "../avatar";
|
import AvatarElement from "../avatar";
|
||||||
import { formatPhoneNumber } from "../misc";
|
import { formatPhoneNumber } from "../misc";
|
||||||
@ -2428,9 +2428,11 @@ export default class ChatBubbles {
|
|||||||
//this.scrollable.scrollTop = this.scrollable.scrollHeight;
|
//this.scrollable.scrollTop = this.scrollable.scrollHeight;
|
||||||
isTouchSupported && isApple && (this.scrollable.container.style.overflow = '');
|
isTouchSupported && isApple && (this.scrollable.container.style.overflow = '');
|
||||||
|
|
||||||
this.scrollable.container.style.display = 'none';
|
if(isSafari && !isAppleMobile) { // * fix blinking and jumping
|
||||||
void this.scrollable.container.offsetLeft; // reflow
|
this.scrollable.container.style.display = 'none';
|
||||||
this.scrollable.container.style.display = '';
|
void this.scrollable.container.offsetLeft; // reflow
|
||||||
|
this.scrollable.container.style.display = '';
|
||||||
|
}
|
||||||
|
|
||||||
/* if(DEBUG) {
|
/* if(DEBUG) {
|
||||||
this.log('performHistoryResult: have set up scrollTop:', newScrollTop, this.scrollable.scrollTop, this.isHeavyAnimationInProgress);
|
this.log('performHistoryResult: have set up scrollTop:', newScrollTop, this.scrollable.scrollTop, this.isHeavyAnimationInProgress);
|
||||||
@ -2707,14 +2709,18 @@ export default class ChatBubbles {
|
|||||||
const promises = [topRes.animationPromise, middleRes.animationPromise, bottomRes.animationPromise];
|
const promises = [topRes.animationPromise, middleRes.animationPromise, bottomRes.animationPromise];
|
||||||
const delays: number[] = [topRes.lastMsDelay, middleRes.lastMsDelay, bottomRes.lastMsDelay];
|
const delays: number[] = [topRes.lastMsDelay, middleRes.lastMsDelay, bottomRes.lastMsDelay];
|
||||||
|
|
||||||
|
let promise: Promise<any>;
|
||||||
if(topIds.length || middleIds.length || bottomIds.length) {
|
if(topIds.length || middleIds.length || bottomIds.length) {
|
||||||
dispatchHeavyAnimationEvent(Promise.all(promises), Math.max(...delays) + 200); // * 200 - transition time
|
promise = Promise.all(promises);
|
||||||
|
dispatchHeavyAnimationEvent(promise, Math.max(...delays) + 200); // * 200 - transition time
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(() => {
|
(promise || Promise.resolve()).then(() => {
|
||||||
this.loadMoreHistory(true, true);
|
setTimeout(() => { // preload messages
|
||||||
}, 0);
|
this.loadMoreHistory(reverse, true);
|
||||||
|
}, 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,25 +39,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<h4>Sign in to Telegram</h4>
|
<h4>Sign in to Telegram</h4>
|
||||||
<p class="subtitle">Please confirm your country and<br> enter your phone number.</p>
|
<p class="subtitle">Please confirm your country and<br> enter your phone number.</p>
|
||||||
<div class="input-wrapper">
|
|
||||||
{{!-- <form action=""> --}}
|
|
||||||
<div class="input-field input-select">
|
|
||||||
<input type="text" name="countryCode" id="countryCode" autocomplete="rrRandomRR" required />
|
|
||||||
<label for="countryCode">Country</label>
|
|
||||||
<span class="arrow arrow-down"></span>
|
|
||||||
</div>
|
|
||||||
<div class="input-field">
|
|
||||||
<input type="tel" name="phone" id="phone" autocomplete="rr55RandomRR55" required />
|
|
||||||
<label for="phone">Phone Number</label>
|
|
||||||
</div>
|
|
||||||
<label class="checkbox-field">
|
|
||||||
<input type="checkbox" id="keepSigned" checked="checked">
|
|
||||||
<span>Keep me signed in</span>
|
|
||||||
</label>
|
|
||||||
<button class="btn-primary rp" style="visibility: hidden;">NEXT</button>
|
|
||||||
{{!-- </form> --}}
|
|
||||||
<div class="qr"><a href="#" class="a-qr">Quick log in using QR code</a></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="page-signQR">
|
<div class="page-signQR">
|
||||||
@ -78,12 +59,7 @@
|
|||||||
<span class="phone-edit tgico-edit"></span>
|
<span class="phone-edit tgico-edit"></span>
|
||||||
</div>
|
</div>
|
||||||
<p class="subtitle sent-type"></p>
|
<p class="subtitle sent-type"></p>
|
||||||
<div class="input-wrapper">
|
<div class="input-wrapper"></div>
|
||||||
<div class="input-field">
|
|
||||||
<input type="tel" name="code" id="code" autocomplete="off" required />
|
|
||||||
<label for="code">Code</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="page-password">
|
<div class="page-password">
|
||||||
@ -91,14 +67,7 @@
|
|||||||
<div class="auth-image"></div>
|
<div class="auth-image"></div>
|
||||||
<h4 class="phone">Enter Your Password</h4>
|
<h4 class="phone">Enter Your Password</h4>
|
||||||
<p class="subtitle">Your account is protected with<br>an additional password</p>
|
<p class="subtitle">Your account is protected with<br>an additional password</p>
|
||||||
<div class="input-wrapper">
|
<div class="input-wrapper"></div>
|
||||||
<div class="input-field">
|
|
||||||
<input type="password" name="password" id="password" autocomplete="off" required />
|
|
||||||
<label for="password">Password</label>
|
|
||||||
<span class="toggle-visible tgico"></span>
|
|
||||||
</div>
|
|
||||||
<button class="btn-primary rp">NEXT</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="page-signUp">
|
<div class="page-signUp">
|
||||||
|
@ -10,6 +10,7 @@ import CryptoWorker from "../crypto/cryptoworker";
|
|||||||
|
|
||||||
import { logger, LogLevels } from "../logger";
|
import { logger, LogLevels } from "../logger";
|
||||||
import { bytesCmp, bytesToHex, bytesFromHex, bytesXor } from "../../helpers/bytes";
|
import { bytesCmp, bytesToHex, bytesFromHex, bytesXor } from "../../helpers/bytes";
|
||||||
|
import { DEBUG } from "./mtproto_config";
|
||||||
//import { bigInt2str, greater, int2bigInt, one, powMod, str2bigInt, sub } from "../../vendor/leemon";
|
//import { bigInt2str, greater, int2bigInt, one, powMod, str2bigInt, sub } from "../../vendor/leemon";
|
||||||
|
|
||||||
/* let fNewNonce: any = bytesFromHex('8761970c24cb2329b5b2459752c502f3057cb7e8dbab200e526e8767fdc73b3c').reverse();
|
/* let fNewNonce: any = bytesFromHex('8761970c24cb2329b5b2459752c502f3057cb7e8dbab200e526e8767fdc73b3c').reverse();
|
||||||
@ -100,10 +101,14 @@ export class Authorizer {
|
|||||||
transport: transport
|
transport: transport
|
||||||
};
|
};
|
||||||
|
|
||||||
this.log('mtpSendPlainRequest: creating requestPromise');
|
if(DEBUG) {
|
||||||
|
this.log('mtpSendPlainRequest: creating requestPromise');
|
||||||
|
}
|
||||||
|
|
||||||
return transport.send(resultArray).then(result => {
|
return transport.send(resultArray).then(result => {
|
||||||
this.log('mtpSendPlainRequest: in good sector', result);
|
if(DEBUG) {
|
||||||
|
this.log('mtpSendPlainRequest: in good sector', result);
|
||||||
|
}
|
||||||
|
|
||||||
if(!result || !result.byteLength) {
|
if(!result || !result.byteLength) {
|
||||||
return Promise.reject(baseError);
|
return Promise.reject(baseError);
|
||||||
@ -148,7 +153,9 @@ export class Authorizer {
|
|||||||
// need
|
// need
|
||||||
rsaKeysManager.prepare().then(() => {});
|
rsaKeysManager.prepare().then(() => {});
|
||||||
|
|
||||||
this.log('Send req_pq', auth.nonce.hex);
|
if(DEBUG) {
|
||||||
|
this.log('Send req_pq', auth.nonce.hex);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
var deserializer = await this.mtpSendPlainRequest(auth.dcId, request.getBytes(true));
|
var deserializer = await this.mtpSendPlainRequest(auth.dcId, request.getBytes(true));
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
@ -172,7 +179,9 @@ export class Authorizer {
|
|||||||
auth.pq = response.pq;
|
auth.pq = response.pq;
|
||||||
auth.fingerprints = response.server_public_key_fingerprints;
|
auth.fingerprints = response.server_public_key_fingerprints;
|
||||||
|
|
||||||
this.log('Got ResPQ', bytesToHex(auth.serverNonce), bytesToHex(auth.pq), auth.fingerprints);
|
if(DEBUG) {
|
||||||
|
this.log('Got ResPQ', bytesToHex(auth.serverNonce), bytesToHex(auth.pq), auth.fingerprints);
|
||||||
|
}
|
||||||
|
|
||||||
let publicKey = await rsaKeysManager.select(auth.fingerprints);
|
let publicKey = await rsaKeysManager.select(auth.fingerprints);
|
||||||
if(!publicKey) {
|
if(!publicKey) {
|
||||||
@ -181,7 +190,9 @@ export class Authorizer {
|
|||||||
|
|
||||||
auth.publicKey = publicKey;
|
auth.publicKey = publicKey;
|
||||||
|
|
||||||
this.log('PQ factorization start', auth.pq);
|
if(DEBUG) {
|
||||||
|
this.log('PQ factorization start', auth.pq);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var pAndQ = await CryptoWorker.factorize(auth.pq);
|
var pAndQ = await CryptoWorker.factorize(auth.pq);
|
||||||
@ -193,7 +204,9 @@ export class Authorizer {
|
|||||||
auth.p = pAndQ[0];
|
auth.p = pAndQ[0];
|
||||||
auth.q = pAndQ[1];
|
auth.q = pAndQ[1];
|
||||||
|
|
||||||
this.log('PQ factorization done', pAndQ);
|
if(DEBUG) {
|
||||||
|
this.log('PQ factorization done', pAndQ);
|
||||||
|
}
|
||||||
/* let p = new Uint32Array(new Uint8Array(auth.p).buffer)[0];
|
/* let p = new Uint32Array(new Uint8Array(auth.p).buffer)[0];
|
||||||
let q = new Uint32Array(new Uint8Array(auth.q).buffer)[0];
|
let q = new Uint32Array(new Uint8Array(auth.q).buffer)[0];
|
||||||
console.log(dT(), 'PQ factorization done', pAndQ, p.toString(16), q.toString(16)); */
|
console.log(dT(), 'PQ factorization done', pAndQ, p.toString(16), q.toString(16)); */
|
||||||
@ -258,18 +271,22 @@ export class Authorizer {
|
|||||||
|
|
||||||
let requestBytes = request.getBytes(true);
|
let requestBytes = request.getBytes(true);
|
||||||
|
|
||||||
this.log('Send req_DH_params', req_DH_params/* , requestBytes.hex */);
|
if(DEBUG) {
|
||||||
|
this.log('Send req_DH_params', req_DH_params/* , requestBytes.hex */);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var deserializer = await this.mtpSendPlainRequest(auth.dcId, requestBytes);
|
var deserializer = await this.mtpSendPlainRequest(auth.dcId, requestBytes);
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
this.log('Send req_DH_params FAIL!', error);
|
this.log.error('Send req_DH_params FAIL!', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
var response = deserializer.fetchObject('Server_DH_Params', 'RESPONSE');
|
var response = deserializer.fetchObject('Server_DH_Params', 'RESPONSE');
|
||||||
|
|
||||||
this.log('Sent req_DH_params, response:', response);
|
if(DEBUG) {
|
||||||
|
this.log('Sent req_DH_params, response:', response);
|
||||||
|
}
|
||||||
|
|
||||||
if(response._ != 'server_DH_params_fail' && response._ != 'server_DH_params_ok') {
|
if(response._ != 'server_DH_params_fail' && response._ != 'server_DH_params_ok') {
|
||||||
throw new Error('[MT] Server_DH_Params response invalid: ' + response._);
|
throw new Error('[MT] Server_DH_Params response invalid: ' + response._);
|
||||||
@ -347,7 +364,9 @@ export class Authorizer {
|
|||||||
throw new Error('[MT] server_DH_inner_data serverNonce mismatch');
|
throw new Error('[MT] server_DH_inner_data serverNonce mismatch');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.log('Done decrypting answer');
|
if(DEBUG) {
|
||||||
|
this.log('Done decrypting answer');
|
||||||
|
}
|
||||||
auth.g = response.g;
|
auth.g = response.g;
|
||||||
auth.dhPrime = response.dh_prime;
|
auth.dhPrime = response.dh_prime;
|
||||||
auth.gA = response.g_a;
|
auth.gA = response.g_a;
|
||||||
@ -367,13 +386,19 @@ export class Authorizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public mtpVerifyDhParams(g: number, dhPrime: Uint8Array, gA: Uint8Array) {
|
public mtpVerifyDhParams(g: number, dhPrime: Uint8Array, gA: Uint8Array) {
|
||||||
this.log('Verifying DH params', g, dhPrime, gA);
|
if(DEBUG) {
|
||||||
|
this.log('Verifying DH params', g, dhPrime, gA);
|
||||||
|
}
|
||||||
|
|
||||||
var dhPrimeHex = bytesToHex(dhPrime);
|
var dhPrimeHex = bytesToHex(dhPrime);
|
||||||
if(g != 3 || dhPrimeHex !== 'c71caeb9c6b1c9048e6c522f70f13f73980d40238e3e21c14934d037563d930f48198a0aa7c14058229493d22530f4dbfa336f6e0ac925139543aed44cce7c3720fd51f69458705ac68cd4fe6b6b13abdc9746512969328454f18faf8c595f642477fe96bb2a941d5bcd1d4ac8cc49880708fa9b378e3c4f3a9060bee67cf9a4a4a695811051907e162753b56b0f6b410dba74d8a84b2a14b3144e0ef1284754fd17ed950d5965b4b9dd46582db1178d169c6bc465b0d6ff9ca3928fef5b9ae4e418fc15e83ebea0f87fa9ff5eed70050ded2849f47bf959d956850ce929851f0d8115f635b105ee2e4e15d04b2454bf6f4fadf034b10403119cd8e3b92fcc5b') {
|
if(g != 3 || dhPrimeHex !== 'c71caeb9c6b1c9048e6c522f70f13f73980d40238e3e21c14934d037563d930f48198a0aa7c14058229493d22530f4dbfa336f6e0ac925139543aed44cce7c3720fd51f69458705ac68cd4fe6b6b13abdc9746512969328454f18faf8c595f642477fe96bb2a941d5bcd1d4ac8cc49880708fa9b378e3c4f3a9060bee67cf9a4a4a695811051907e162753b56b0f6b410dba74d8a84b2a14b3144e0ef1284754fd17ed950d5965b4b9dd46582db1178d169c6bc465b0d6ff9ca3928fef5b9ae4e418fc15e83ebea0f87fa9ff5eed70050ded2849f47bf959d956850ce929851f0d8115f635b105ee2e4e15d04b2454bf6f4fadf034b10403119cd8e3b92fcc5b') {
|
||||||
// The verified value is from https://core.telegram.org/mtproto/security_guidelines
|
// The verified value is from https://core.telegram.org/mtproto/security_guidelines
|
||||||
throw new Error('[MT] DH params are not verified: unknown dhPrime');
|
throw new Error('[MT] DH params are not verified: unknown dhPrime');
|
||||||
}
|
}
|
||||||
this.log('dhPrime cmp OK');
|
|
||||||
|
if(DEBUG) {
|
||||||
|
this.log('dhPrime cmp OK');
|
||||||
|
}
|
||||||
|
|
||||||
var gABigInt = new BigInteger(bytesToHex(gA), 16);
|
var gABigInt = new BigInteger(bytesToHex(gA), 16);
|
||||||
//const _gABigInt = str2bigInt(bytesToHex(gA), 16);
|
//const _gABigInt = str2bigInt(bytesToHex(gA), 16);
|
||||||
@ -392,7 +417,10 @@ export class Authorizer {
|
|||||||
//if(greater(gABigInt, sub(_dhPrimeBigInt, one))) {
|
//if(greater(gABigInt, sub(_dhPrimeBigInt, one))) {
|
||||||
throw new Error('[MT] DH params are not verified: gA >= dhPrime - 1');
|
throw new Error('[MT] DH params are not verified: gA >= dhPrime - 1');
|
||||||
}
|
}
|
||||||
this.log('1 < gA < dhPrime-1 OK');
|
|
||||||
|
if(DEBUG) {
|
||||||
|
this.log('1 < gA < dhPrime-1 OK');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var two = new BigInteger(/* null */'');
|
var two = new BigInteger(/* null */'');
|
||||||
@ -410,7 +438,10 @@ export class Authorizer {
|
|||||||
if(gABigInt.compareTo(dhPrimeBigInt.subtract(twoPow)) >= 0) {
|
if(gABigInt.compareTo(dhPrimeBigInt.subtract(twoPow)) >= 0) {
|
||||||
throw new Error('[MT] DH params are not verified: gA > dhPrime - 2^{2048-64}');
|
throw new Error('[MT] DH params are not verified: gA > dhPrime - 2^{2048-64}');
|
||||||
}
|
}
|
||||||
this.log('2^{2048-64} < gA < dhPrime-2^{2048-64} OK');
|
|
||||||
|
if(DEBUG) {
|
||||||
|
this.log('2^{2048-64} < gA < dhPrime-2^{2048-64} OK');
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -450,7 +481,9 @@ export class Authorizer {
|
|||||||
encrypted_data: encryptedData
|
encrypted_data: encryptedData
|
||||||
});
|
});
|
||||||
|
|
||||||
this.log('Send set_client_DH_params');
|
if(DEBUG) {
|
||||||
|
this.log('Send set_client_DH_params');
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var deserializer = await this.mtpSendPlainRequest(auth.dcId, request.getBytes(true));
|
var deserializer = await this.mtpSendPlainRequest(auth.dcId, request.getBytes(true));
|
||||||
@ -483,7 +516,9 @@ export class Authorizer {
|
|||||||
authKeyAux = authKeyHash.slice(0, 8),
|
authKeyAux = authKeyHash.slice(0, 8),
|
||||||
authKeyId = authKeyHash.slice(-8);
|
authKeyId = authKeyHash.slice(-8);
|
||||||
|
|
||||||
this.log('Got Set_client_DH_params_answer', response._, authKey);
|
if(DEBUG) {
|
||||||
|
this.log('Got Set_client_DH_params_answer', response._, authKey);
|
||||||
|
}
|
||||||
switch(response._) {
|
switch(response._) {
|
||||||
case 'dh_gen_ok':
|
case 'dh_gen_ok':
|
||||||
var newNonceHash1 = (await CryptoWorker.sha1Hash(auth.newNonce.concat([1], authKeyAux))).slice(-16);
|
var newNonceHash1 = (await CryptoWorker.sha1Hash(auth.newNonce.concat([1], authKeyAux))).slice(-16);
|
||||||
@ -494,7 +529,9 @@ export class Authorizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var serverSalt = bytesXor(auth.newNonce.slice(0, 8), auth.serverNonce.slice(0, 8));
|
var serverSalt = bytesXor(auth.newNonce.slice(0, 8), auth.serverNonce.slice(0, 8));
|
||||||
this.log('Auth successfull!', authKeyId, authKey, serverSalt);
|
if(DEBUG) {
|
||||||
|
this.log('Auth successfull!', authKeyId, authKey, serverSalt);
|
||||||
|
}
|
||||||
|
|
||||||
auth.authKeyId = authKeyId;
|
auth.authKeyId = authKeyId;
|
||||||
auth.authKey = authKey;
|
auth.authKey = authKey;
|
||||||
|
@ -109,7 +109,7 @@ ctx.addEventListener('message', async(e) => {
|
|||||||
case 'gzipUncompress':
|
case 'gzipUncompress':
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return cryptoWorker[task.task].apply(cryptoWorker, task.args).then(result => {
|
return cryptoWorker[task.task].apply(cryptoWorker, task.args).then(result => {
|
||||||
respond({taskId: taskId, result: result});
|
respond({taskId, result});
|
||||||
});
|
});
|
||||||
|
|
||||||
case 'setQueueId':
|
case 'setQueueId':
|
||||||
@ -127,16 +127,18 @@ ctx.addEventListener('message', async(e) => {
|
|||||||
result = await result;
|
result = await result;
|
||||||
}
|
}
|
||||||
|
|
||||||
respond({taskId: taskId, result: result});
|
respond({taskId, result});
|
||||||
} catch(err) {
|
} catch(error) {
|
||||||
respond({taskId: taskId, error: err});
|
respond({taskId, error});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'getNetworker': {
|
case 'getNetworker': {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
apiManager[task.task].apply(apiManager, task.args);
|
apiManager[task.task].apply(apiManager, task.args).finally(() => {
|
||||||
respond({taskId: taskId, result: null});
|
respond({taskId, result: null});
|
||||||
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,9 +151,9 @@ ctx.addEventListener('message', async(e) => {
|
|||||||
result = await result;
|
result = await result;
|
||||||
}
|
}
|
||||||
|
|
||||||
respond({taskId: taskId, result: result});
|
respond({taskId, result});
|
||||||
} catch(err) {
|
} catch(error) {
|
||||||
respond({taskId: taskId, error: err});
|
respond({taskId, error});
|
||||||
}
|
}
|
||||||
|
|
||||||
//throw new Error('Unknown task: ' + task.task);
|
//throw new Error('Unknown task: ' + task.task);
|
||||||
|
@ -11,6 +11,7 @@ import pageIm from './pageIm';
|
|||||||
import pagePassword from './pagePassword';
|
import pagePassword from './pagePassword';
|
||||||
import pageSignIn from './pageSignIn';
|
import pageSignIn from './pageSignIn';
|
||||||
import pageSignUp from './pageSignUp';
|
import pageSignUp from './pageSignUp';
|
||||||
|
import InputField from '../components/inputField';
|
||||||
|
|
||||||
let authCode: AuthSentCode.authSentCode = null;
|
let authCode: AuthSentCode.authSentCode = null;
|
||||||
|
|
||||||
@ -28,7 +29,19 @@ let onFirstMount = (): Promise<any> => {
|
|||||||
|
|
||||||
const CODELENGTH = (authCode.type as AuthSentCodeType.authSentCodeTypeApp).length;
|
const CODELENGTH = (authCode.type as AuthSentCodeType.authSentCodeTypeApp).length;
|
||||||
|
|
||||||
codeInput = page.pageEl.querySelector('#code') as HTMLInputElement;
|
const codeInputField = new InputField({
|
||||||
|
label: 'Code',
|
||||||
|
name: 'code',
|
||||||
|
plainText: true
|
||||||
|
});
|
||||||
|
|
||||||
|
codeInput = codeInputField.input as HTMLInputElement;
|
||||||
|
codeInput.type = 'tel';
|
||||||
|
codeInput.setAttribute('required', '');
|
||||||
|
codeInput.autocomplete = 'off';
|
||||||
|
|
||||||
|
page.pageEl.querySelector('.input-wrapper').append(codeInputField.container);
|
||||||
|
|
||||||
const codeInputLabel = codeInput.nextElementSibling as HTMLLabelElement;
|
const codeInputLabel = codeInput.nextElementSibling as HTMLLabelElement;
|
||||||
const editButton = page.pageEl.querySelector('.phone-edit') as HTMLElement;
|
const editButton = page.pageEl.querySelector('.phone-edit') as HTMLElement;
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@ import passwordManager from '../lib/mtproto/passwordManager';
|
|||||||
import { cancelEvent } from '../helpers/dom';
|
import { cancelEvent } from '../helpers/dom';
|
||||||
import Page from './page';
|
import Page from './page';
|
||||||
import pageIm from './pageIm';
|
import pageIm from './pageIm';
|
||||||
|
import InputField from '../components/inputField';
|
||||||
|
import Button from '../components/button';
|
||||||
|
|
||||||
const TEST = false;
|
const TEST = false;
|
||||||
let passwordInput: HTMLInputElement;
|
let passwordInput: HTMLInputElement;
|
||||||
@ -22,10 +24,28 @@ let onFirstMount = (): Promise<any> => {
|
|||||||
|
|
||||||
let passwordVisible = false;
|
let passwordVisible = false;
|
||||||
|
|
||||||
const btnNext = page.pageEl.querySelector('button') as HTMLButtonElement;
|
const btnNext = Button('btn-primary', {text: 'NEXT'});
|
||||||
passwordInput = document.getElementById('password') as HTMLInputElement;
|
|
||||||
|
const passwordInputField = new InputField({
|
||||||
|
label: 'Password',
|
||||||
|
name: 'password',
|
||||||
|
plainText: true
|
||||||
|
});
|
||||||
|
|
||||||
|
passwordInput = passwordInputField.input as HTMLInputElement;
|
||||||
|
passwordInput.type = 'password';
|
||||||
|
passwordInput.setAttribute('required', '');
|
||||||
|
passwordInput.autocomplete = 'off';
|
||||||
|
|
||||||
const passwordInputLabel = passwordInput.nextElementSibling as HTMLLabelElement;
|
const passwordInputLabel = passwordInput.nextElementSibling as HTMLLabelElement;
|
||||||
const toggleVisible = page.pageEl.querySelector('.toggle-visible') as HTMLSpanElement;
|
|
||||||
|
const toggleVisible = document.createElement('span');
|
||||||
|
toggleVisible.classList.add('toggle-visible', 'tgico');
|
||||||
|
|
||||||
|
passwordInputField.container.append(toggleVisible);
|
||||||
|
|
||||||
|
page.pageEl.querySelector('.input-wrapper').append(passwordInputField.container, btnNext);
|
||||||
|
|
||||||
let getStateInterval: number;
|
let getStateInterval: number;
|
||||||
|
|
||||||
let getState = () => {
|
let getState = () => {
|
||||||
|
@ -9,6 +9,10 @@ import { findUpTag } from "../helpers/dom";
|
|||||||
import Page from "./page";
|
import Page from "./page";
|
||||||
import pageAuthCode from "./pageAuthCode";
|
import pageAuthCode from "./pageAuthCode";
|
||||||
import pageSignQR from './pageSignQR';
|
import pageSignQR from './pageSignQR';
|
||||||
|
import InputField from "../components/inputField";
|
||||||
|
import CheckboxField from "../components/checkbox";
|
||||||
|
import Button from "../components/button";
|
||||||
|
import { isAppleMobile } from "../helpers/userAgent";
|
||||||
|
|
||||||
type Country = _Country & {
|
type Country = _Country & {
|
||||||
li?: HTMLLIElement[]
|
li?: HTMLLIElement[]
|
||||||
@ -35,24 +39,34 @@ let onFirstMount = () => {
|
|||||||
|
|
||||||
let lastCountrySelected: Country = null;
|
let lastCountrySelected: Country = null;
|
||||||
|
|
||||||
var selectCountryCode = page.pageEl.querySelector('input[name="countryCode"]')! as HTMLInputElement;
|
const inputWrapper = document.createElement('div');
|
||||||
var parent = selectCountryCode.parentElement;
|
inputWrapper.classList.add('input-wrapper');
|
||||||
|
|
||||||
var wrapper = document.createElement('div');
|
const countryInputField = new InputField({
|
||||||
wrapper.classList.add('select-wrapper', 'z-depth-3', 'hide');
|
label: 'Country',
|
||||||
|
name: 'countryCode',
|
||||||
|
plainText: true
|
||||||
|
});
|
||||||
|
|
||||||
var list = document.createElement('ul');
|
countryInputField.container.classList.add('input-select');
|
||||||
wrapper.appendChild(list);
|
|
||||||
|
|
||||||
//let wrapperScroll = OverlayScrollbars(wrapper, (window as any).scrollbarOptions);
|
const countryInput = countryInputField.input as HTMLInputElement;
|
||||||
let scroll = new Scrollable(wrapper);
|
countryInput.autocomplete = 'rrRandomRR';
|
||||||
|
|
||||||
|
const selectWrapper = document.createElement('div');
|
||||||
|
selectWrapper.classList.add('select-wrapper', 'z-depth-3', 'hide');
|
||||||
|
|
||||||
|
const arrowDown = document.createElement('span');
|
||||||
|
arrowDown.classList.add('arrow', 'arrow-down');
|
||||||
|
countryInputField.container.append(arrowDown);
|
||||||
|
|
||||||
|
const selectList = document.createElement('ul');
|
||||||
|
selectWrapper.appendChild(selectList);
|
||||||
|
|
||||||
|
const scroll = new Scrollable(selectWrapper);
|
||||||
|
|
||||||
let initedSelect = false;
|
let initedSelect = false;
|
||||||
|
|
||||||
page.pageEl.querySelector('.a-qr').addEventListener('click', () => {
|
|
||||||
pageSignQR.mount();
|
|
||||||
});
|
|
||||||
|
|
||||||
let initSelect = () => {
|
let initSelect = () => {
|
||||||
initSelect = null;
|
initSelect = null;
|
||||||
|
|
||||||
@ -88,20 +102,20 @@ let onFirstMount = () => {
|
|||||||
li.appendChild(span);
|
li.appendChild(span);
|
||||||
|
|
||||||
liArr.push(li);
|
liArr.push(li);
|
||||||
list.append(li);
|
selectList.append(li);
|
||||||
});
|
});
|
||||||
|
|
||||||
c.li = liArr;
|
c.li = liArr;
|
||||||
});
|
});
|
||||||
|
|
||||||
list.addEventListener('mousedown', function(e) {
|
selectList.addEventListener('mousedown', function(e) {
|
||||||
let target = e.target as HTMLElement;
|
let target = e.target as HTMLElement;
|
||||||
if(target.tagName != 'LI') target = findUpTag(target, 'LI');
|
if(target.tagName != 'LI') target = findUpTag(target, 'LI');
|
||||||
|
|
||||||
let countryName = target.childNodes[1].textContent;//target.innerText.split('\n').shift();
|
let countryName = target.childNodes[1].textContent;//target.innerText.split('\n').shift();
|
||||||
let phoneCode = target.querySelector<HTMLElement>('.phone-code').innerText;
|
let phoneCode = target.querySelector<HTMLElement>('.phone-code').innerText;
|
||||||
|
|
||||||
selectCountryCode.value = countryName;
|
countryInput.value = countryName;
|
||||||
lastCountrySelected = countries.find(c => c.name == countryName);
|
lastCountrySelected = countries.find(c => c.name == countryName);
|
||||||
|
|
||||||
telEl.value = lastValue = phoneCode;
|
telEl.value = lastValue = phoneCode;
|
||||||
@ -109,14 +123,14 @@ let onFirstMount = () => {
|
|||||||
//console.log('clicked', e, countryName, phoneCode);
|
//console.log('clicked', e, countryName, phoneCode);
|
||||||
});
|
});
|
||||||
|
|
||||||
parent.appendChild(wrapper);
|
countryInputField.container.appendChild(selectWrapper);
|
||||||
};
|
};
|
||||||
|
|
||||||
initSelect();
|
initSelect();
|
||||||
|
|
||||||
let hideTimeout: number;
|
let hideTimeout: number;
|
||||||
|
|
||||||
selectCountryCode.addEventListener('focus', function(this: typeof selectCountryCode, e) {
|
countryInput.addEventListener('focus', function(this: typeof countryInput, e) {
|
||||||
if(initSelect) {
|
if(initSelect) {
|
||||||
initSelect();
|
initSelect();
|
||||||
} else {
|
} else {
|
||||||
@ -127,20 +141,20 @@ let onFirstMount = () => {
|
|||||||
|
|
||||||
clearTimeout(hideTimeout);
|
clearTimeout(hideTimeout);
|
||||||
|
|
||||||
wrapper.classList.remove('hide');
|
selectWrapper.classList.remove('hide');
|
||||||
void wrapper.offsetWidth; // reflow
|
void selectWrapper.offsetWidth; // reflow
|
||||||
wrapper.classList.add('active');
|
selectWrapper.classList.add('active');
|
||||||
});
|
});
|
||||||
selectCountryCode.addEventListener('blur', function(this: typeof selectCountryCode, e) {
|
countryInput.addEventListener('blur', function(this: typeof countryInput, e) {
|
||||||
wrapper.classList.remove('active');
|
selectWrapper.classList.remove('active');
|
||||||
hideTimeout = window.setTimeout(() => {
|
hideTimeout = window.setTimeout(() => {
|
||||||
wrapper.classList.add('hide');
|
selectWrapper.classList.add('hide');
|
||||||
}, 200);
|
}, 200);
|
||||||
|
|
||||||
e.cancelBubble = true;
|
e.cancelBubble = true;
|
||||||
}, {capture: true});
|
}, {capture: true});
|
||||||
|
|
||||||
selectCountryCode.addEventListener('keyup', function(this: typeof selectCountryCode, e) {
|
countryInput.addEventListener('keyup', function(this: typeof countryInput, e) {
|
||||||
if(e.ctrlKey || e.key == 'Control') return false;
|
if(e.ctrlKey || e.key == 'Control') return false;
|
||||||
|
|
||||||
//let i = new RegExp('^' + this.value, 'i');
|
//let i = new RegExp('^' + this.value, 'i');
|
||||||
@ -169,24 +183,31 @@ let onFirstMount = () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let arrowDown = page.pageEl.querySelector('.arrow-down') as HTMLSpanElement;
|
|
||||||
arrowDown.addEventListener('mousedown', function(this: typeof arrowDown, e) {
|
arrowDown.addEventListener('mousedown', function(this: typeof arrowDown, e) {
|
||||||
e.cancelBubble = true;
|
e.cancelBubble = true;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if(selectCountryCode.matches(':focus')) selectCountryCode.blur();
|
if(countryInput.matches(':focus')) countryInput.blur();
|
||||||
else selectCountryCode.focus();
|
else countryInput.focus();
|
||||||
});
|
});
|
||||||
|
|
||||||
let pasted = false;
|
let pasted = false;
|
||||||
let lastValue = '';
|
let lastValue = '';
|
||||||
let telEl = page.pageEl.querySelector('input[name="phone"]') as HTMLInputElement;
|
|
||||||
|
const telInputField = new InputField({
|
||||||
|
label: 'Phone Number',
|
||||||
|
plainText: true,
|
||||||
|
name: 'phone'
|
||||||
|
});
|
||||||
|
let telEl = telInputField.input as HTMLInputElement;
|
||||||
|
telEl.type = 'tel';
|
||||||
|
telEl.autocomplete = 'rr55RandomRR55';
|
||||||
const telLabel = telEl.nextElementSibling as HTMLLabelElement;
|
const telLabel = telEl.nextElementSibling as HTMLLabelElement;
|
||||||
telEl.addEventListener('input', function(this: typeof telEl, e) {
|
telEl.addEventListener('input', function(this: typeof telEl, e) {
|
||||||
//console.log('input', this.value);
|
//console.log('input', this.value);
|
||||||
this.classList.remove('error');
|
this.classList.remove('error');
|
||||||
|
|
||||||
const diff = Math.abs(this.value.length - lastValue.length);
|
const diff = Math.abs(this.value.length - lastValue.length);
|
||||||
if(diff > 1 && !pasted) {
|
if(diff > 1 && !pasted && isAppleMobile) {
|
||||||
this.value = lastValue + this.value;
|
this.value = lastValue + this.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,8 +221,8 @@ let onFirstMount = () => {
|
|||||||
//console.log(formatted, country);
|
//console.log(formatted, country);
|
||||||
|
|
||||||
let countryName = country ? country.name : ''/* 'Unknown' */;
|
let countryName = country ? country.name : ''/* 'Unknown' */;
|
||||||
if(countryName != selectCountryCode.value && (!lastCountrySelected || !country || lastCountrySelected.phoneCode != country.phoneCode)) {
|
if(countryName != countryInput.value && (!lastCountrySelected || !country || lastCountrySelected.phoneCode != country.phoneCode)) {
|
||||||
selectCountryCode.value = countryName;
|
countryInput.value = countryName;
|
||||||
lastCountrySelected = country;
|
lastCountrySelected = country;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,7 +247,7 @@ let onFirstMount = () => {
|
|||||||
//console.log('keypress', this.value);
|
//console.log('keypress', this.value);
|
||||||
if(!btnNext.style.visibility &&/* this.value.length >= 9 && */ e.key == 'Enter') {
|
if(!btnNext.style.visibility &&/* this.value.length >= 9 && */ e.key == 'Enter') {
|
||||||
return btnNext.click();
|
return btnNext.click();
|
||||||
} else if(/\D/.test(e.key)) {
|
} else if(/\D/.test(e.key) && !(e.metaKey || e.ctrlKey)) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -236,8 +257,11 @@ let onFirstMount = () => {
|
|||||||
this.removeAttribute('readonly'); // fix autocomplete
|
this.removeAttribute('readonly'); // fix autocomplete
|
||||||
});*/
|
});*/
|
||||||
|
|
||||||
/* authorizer.auth(2);
|
const signedCheckboxField = CheckboxField('Keep me signed in', 'keepSession');
|
||||||
networkerFactory.startAll(); */
|
signedCheckboxField.input.checked = true;
|
||||||
|
|
||||||
|
btnNext = Button('btn-primary', {text: 'NEXT'});
|
||||||
|
btnNext.style.visibility = 'hidden';
|
||||||
|
|
||||||
btnNext.addEventListener('click', function(this: HTMLElement, e) {
|
btnNext.addEventListener('click', function(this: HTMLElement, e) {
|
||||||
this.setAttribute('disabled', 'true');
|
this.setAttribute('disabled', 'true');
|
||||||
@ -277,33 +301,56 @@ let onFirstMount = () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const qrDiv = document.createElement('div');
|
||||||
|
qrDiv.classList.add('qr');
|
||||||
|
|
||||||
|
const qrLink = document.createElement('a');
|
||||||
|
qrLink.href = '#';
|
||||||
|
qrLink.classList.add('a-qr');
|
||||||
|
qrLink.innerText = 'Quick log in using QR code';
|
||||||
|
|
||||||
|
qrDiv.append(qrLink);
|
||||||
|
|
||||||
|
qrLink.addEventListener('click', () => {
|
||||||
|
pageSignQR.mount();
|
||||||
|
});
|
||||||
|
|
||||||
|
inputWrapper.append(countryInputField.container, telInputField.container, signedCheckboxField.label, btnNext, qrDiv);
|
||||||
|
|
||||||
|
page.pageEl.querySelector('.container').append(inputWrapper);
|
||||||
|
|
||||||
let tryAgain = () => {
|
let tryAgain = () => {
|
||||||
apiManager.invokeApi('help.getNearestDc').then((nearestDcResult) => {
|
apiManager.invokeApi('help.getNearestDc').then((nearestDcResult) => {
|
||||||
const dcs = [1, 2, 3, 4, 5];
|
const dcs = [1, 2, 3, 4, 5];
|
||||||
//dcs.splice(nearestDcResult.this_dc - 1, 1);
|
const done: number[] = [nearestDcResult.this_dc];
|
||||||
|
|
||||||
let promise: Promise<any>;
|
let promise: Promise<any>;
|
||||||
if(nearestDcResult.nearest_dc != nearestDcResult.this_dc) {
|
if(nearestDcResult.nearest_dc != nearestDcResult.this_dc) {
|
||||||
//MTProto.apiManager.baseDcID = nearestDcResult.nearest_dc;
|
|
||||||
|
|
||||||
promise = apiManager.getNetworker(nearestDcResult.nearest_dc).then(() => {
|
promise = apiManager.getNetworker(nearestDcResult.nearest_dc).then(() => {
|
||||||
|
done.push(nearestDcResult.nearest_dc)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
(promise || Promise.resolve()).then(() => {
|
(promise || Promise.resolve()).then(() => {
|
||||||
dcs.forEach(dcId => {
|
const g = () => {
|
||||||
apiManager.getNetworker(dcId, {fileDownload: true});
|
const dcId = dcs.shift();
|
||||||
});
|
if(!dcId) return;
|
||||||
|
|
||||||
|
setTimeout(() => { // * если одновременно запросить все нетворкеры, не будет проходить запрос на код
|
||||||
|
apiManager.getNetworker(dcId, {fileDownload: true}).finally(g);
|
||||||
|
}, done.includes(dcId) ? 0 : 3000);
|
||||||
|
};
|
||||||
|
|
||||||
|
g();
|
||||||
});
|
});
|
||||||
|
|
||||||
return nearestDcResult;
|
return nearestDcResult;
|
||||||
}).then((nearestDcResult) => {
|
}).then((nearestDcResult) => {
|
||||||
let country = countries.find((c) => c.code == nearestDcResult.country);
|
let country = countries.find((c) => c.code === nearestDcResult.country);
|
||||||
if(country) {
|
if(country) {
|
||||||
if(!selectCountryCode.value.length && !telEl.value.length) {
|
if(!countryInput.value.length && !telEl.value.length) {
|
||||||
selectCountryCode.value = country.name;
|
countryInput.value = country.name;
|
||||||
lastCountrySelected = country;
|
lastCountrySelected = country;
|
||||||
telEl.value = lastValue = '+' + country.phoneCode.split(' and ').shift();
|
telEl.value = lastValue = '+' + country.phoneCode.split(' and ').shift();
|
||||||
}
|
}
|
||||||
@ -317,12 +364,10 @@ let onFirstMount = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const page = new Page('page-sign', true, onFirstMount, () => {
|
const page = new Page('page-sign', true, onFirstMount, () => {
|
||||||
if(!btnNext) {
|
if(btnNext) {
|
||||||
btnNext = page.pageEl.querySelector('button');
|
btnNext.textContent = 'NEXT';
|
||||||
|
btnNext.removeAttribute('disabled');
|
||||||
}
|
}
|
||||||
|
|
||||||
btnNext.textContent = 'NEXT';
|
|
||||||
btnNext.removeAttribute('disabled');
|
|
||||||
|
|
||||||
appStateManager.pushToState('authState', {_: 'authStateSignIn'});
|
appStateManager.pushToState('authState', {_: 'authStateSignIn'});
|
||||||
appStateManager.saveState();
|
appStateManager.saveState();
|
||||||
|
@ -4,7 +4,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.input-field {
|
.input-field {
|
||||||
|
--height: 54px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
@include respond-to(handhelds) {
|
||||||
|
--height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
.arrow-down {
|
.arrow-down {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -35,24 +40,24 @@
|
|||||||
label {
|
label {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
color: $placeholder-color;
|
color: $placeholder-color;
|
||||||
|
top: 0;
|
||||||
left: 1rem;
|
left: 1rem;
|
||||||
right: auto;
|
right: auto;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
top: 50%;
|
|
||||||
height: 1.5rem;
|
height: 1.5rem;
|
||||||
transform: translateY(-50%);
|
transform: translate(0, 0);
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
transition: .2s transform, .2s padding, .1s opacity, .2s top, .2s left;
|
transition: .2s transform, .2s padding, .1s opacity;
|
||||||
transform-origin: left center;
|
transform-origin: left center;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
margin-top: calc((var(--height) - 1.5rem) / 2); // * Center of first line
|
||||||
|
|
||||||
body.animation-level-0 & {
|
body.animation-level-0 & {
|
||||||
transition: none;
|
transition: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input, &-input {
|
&-input {
|
||||||
--height: 54px;
|
|
||||||
--padding: 1rem;
|
--padding: 1rem;
|
||||||
--border-width: 1px;
|
--border-width: 1px;
|
||||||
--border-width-top: 2px;
|
--border-width-top: 2px;
|
||||||
@ -80,9 +85,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@include respond-to(handhelds) {
|
|
||||||
--height: 50px;
|
|
||||||
}
|
|
||||||
/* font-weight: 500; */
|
/* font-weight: 500; */
|
||||||
|
|
||||||
/* &:hover {
|
/* &:hover {
|
||||||
@ -133,13 +135,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&:focus ~ label, &:valid ~ label, &:not(:empty) ~ label, &:disabled ~ label {
|
&:focus ~ label, &:valid ~ label, &:not(:empty) ~ label, &:disabled ~ label {
|
||||||
//transform: translate(-.3125rem, -2.375rem) scale(.75);
|
transform: translate(-.25rem, calc(var(--height) / -2 + .125rem)) scale(.75);
|
||||||
//transform: translate(-.3125rem, -50%) scale(.75);
|
|
||||||
transform: translateY(-50%) scale(.75);
|
|
||||||
top: 1px;
|
|
||||||
padding: 0 6px;
|
padding: 0 6px;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
left: .75rem;
|
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user