Font changed to 16px; sign in page fixes; prepare auth animation
This commit is contained in:
parent
67aca5c877
commit
4c500ada12
6
package-lock.json
generated
6
package-lock.json
generated
@ -1312,6 +1312,12 @@
|
||||
"minimist": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"@cryptography/aes": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@cryptography/aes/-/aes-0.1.1.tgz",
|
||||
"integrity": "sha512-PcYz4FDGblO6tM2kSC+VzhhK62vml6k6/YAkiWtyPvrgJVfnDRoHGDtKn5UiaRRUrvUTTocBpvc2rRgTCqxjsg==",
|
||||
"dev": true
|
||||
},
|
||||
"@cryptography/sha1": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@cryptography/sha1/-/sha1-0.1.0.tgz",
|
||||
|
@ -6,7 +6,7 @@
|
||||
"scripts": {
|
||||
"start": "webpack-dev-server --open --config webpack.dev.js",
|
||||
"start-production": "webpack-dev-server --open --config webpack.prod.js",
|
||||
"serve-serve": "webpack-serve --compress --port 9001 --host localhost --no-watch --static ./public --config webpack.prod.js",
|
||||
"serve": "node server.js",
|
||||
"build": "webpack --config webpack.prod.js",
|
||||
"test": "jest --config=jest.config.js",
|
||||
"profile": "webpack --profile --json > stats.json --config webpack.prod.js"
|
||||
@ -21,6 +21,7 @@
|
||||
"@babel/core": "^7.9.0",
|
||||
"@babel/preset-env": "^7.9.5",
|
||||
"@babel/preset-typescript": "^7.9.0",
|
||||
"@cryptography/aes": "^0.1.1",
|
||||
"@cryptography/sha1": "^0.1.0",
|
||||
"@cryptography/sha256": "^0.2.0",
|
||||
"@types/aes-js": "^3.1.1",
|
||||
|
@ -71,9 +71,9 @@ const initEmoticonsDropdown = (pageEl: HTMLDivElement,
|
||||
|
||||
if(menuScroll) {
|
||||
if(i < heights.length - 4) {
|
||||
menuScroll.container.scrollLeft = (i - 3) * 50;
|
||||
menuScroll.container.scrollLeft = (i - 3) * 47;
|
||||
} else {
|
||||
menuScroll.container.scrollLeft = i * 50;
|
||||
menuScroll.container.scrollLeft = i * 47;
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,7 +85,7 @@ const initEmoticonsDropdown = (pageEl: HTMLDivElement,
|
||||
};
|
||||
|
||||
{
|
||||
let categories = ["Smileys & Emotion", "Animals & Nature", "Food & Drink", "Travel & Places", "Activities", "Objects", "Symbols", "Flags", "Skin Tones"];
|
||||
let categories = ["Smileys & Emotion", "Animals & Nature", "Food & Drink", "Travel & Places", "Activities", "Objects", /* "Symbols", */"Flags", "Skin Tones"];
|
||||
let divs: {
|
||||
[category: string]: HTMLDivElement
|
||||
} = {};
|
||||
@ -100,12 +100,16 @@ const initEmoticonsDropdown = (pageEl: HTMLDivElement,
|
||||
let details = Config.Emoji.emoji[unified];
|
||||
let category = details[keyCategory];
|
||||
|
||||
if(category == 'Symbols') category = 'Objects';
|
||||
|
||||
details.unified = unified;
|
||||
|
||||
if(!sorted[category]) sorted[category] = [];
|
||||
sorted[category][details.sort_order] = details;
|
||||
}
|
||||
|
||||
//console.log('emoticons sorted:', sorted);
|
||||
|
||||
Object.keys(sorted).forEach(c => sorted[c].sort());
|
||||
|
||||
categories.pop();
|
||||
@ -143,20 +147,29 @@ const initEmoticonsDropdown = (pageEl: HTMLDivElement,
|
||||
}
|
||||
//console.timeEnd('emojiParse');
|
||||
|
||||
let contentEmojiDiv = document.getElementById('content-emoji') as HTMLDivElement;
|
||||
let heights: number[] = [0];
|
||||
|
||||
let contentEmojiDiv = document.getElementById('content-emoji') as HTMLDivElement;
|
||||
categories.forEach(category => {
|
||||
let prevCategoryIndex = 1;
|
||||
let menu = contentEmojiDiv.nextElementSibling as HTMLUListElement;
|
||||
let emojiScroll = new Scrollable(contentEmojiDiv, 'y', 500, 'EMOJI', null);
|
||||
emojiScroll.container.addEventListener('scroll', (e) => {
|
||||
prevCategoryIndex = emoticonsContentOnScroll(menu, heights, prevCategoryIndex, emojiScroll.container);
|
||||
});
|
||||
//emojiScroll.setVirtualContainer(emojiScroll.container);
|
||||
|
||||
categories.map(category => {
|
||||
let div = divs[category];
|
||||
|
||||
if(!div) {
|
||||
console.error('no div by category:', category);
|
||||
}
|
||||
|
||||
contentEmojiDiv.append(div);
|
||||
emojiScroll.append(div);
|
||||
return div;
|
||||
}).forEach(div => {
|
||||
//console.log('emoji heights push: ', (heights[heights.length - 1] || 0) + div.scrollHeight, div, div.scrollHeight);
|
||||
heights.push((heights[heights.length - 1] || 0) + div.scrollHeight);
|
||||
|
||||
//console.log(div, div.scrollHeight);
|
||||
});
|
||||
|
||||
contentEmojiDiv.addEventListener('click', function(e) {
|
||||
@ -184,14 +197,6 @@ const initEmoticonsDropdown = (pageEl: HTMLDivElement,
|
||||
btnSend.classList.remove('tgico-microphone2');
|
||||
});
|
||||
|
||||
let prevCategoryIndex = 1;
|
||||
let menu = contentEmojiDiv.nextElementSibling as HTMLUListElement;
|
||||
let emojiScroll = new Scrollable(contentEmojiDiv, 'y', 500, 'EMOJI', contentEmojiDiv);
|
||||
emojiScroll.container.addEventListener('scroll', (e) => {
|
||||
prevCategoryIndex = emoticonsContentOnScroll(menu, heights, prevCategoryIndex, emojiScroll.container);
|
||||
});
|
||||
//emojiScroll.setVirtualContainer(emojiScroll.container);
|
||||
|
||||
emoticonsMenuOnClick(menu, heights, emojiScroll);
|
||||
}
|
||||
|
||||
@ -273,13 +278,15 @@ const initEmoticonsDropdown = (pageEl: HTMLDivElement,
|
||||
heightRAF = window.requestAnimationFrame(() => {
|
||||
heightRAF = 0;
|
||||
|
||||
let paddingTop = parseInt(window.getComputedStyle(stickersScroll.container).getPropertyValue('padding-top')) || 0;
|
||||
|
||||
heights.length = 0;
|
||||
let concated = stickersScroll.hiddenElements.up.concat(stickersScroll.visibleElements, stickersScroll.hiddenElements.down);
|
||||
concated.forEach((el, i) => {
|
||||
heights[i] = (heights[i - 1] || 0) + el.height;
|
||||
heights[i] = (heights[i - 1] || 0) + el.height + (i == 0 ? paddingTop : 0);
|
||||
});
|
||||
|
||||
console.log('stickers concated', concated, heights);
|
||||
//console.log('stickers concated', concated, heights);
|
||||
});
|
||||
|
||||
/* Array.from(stickersDiv.children).forEach((div, i) => {
|
||||
@ -344,11 +351,12 @@ const initEmoticonsDropdown = (pageEl: HTMLDivElement,
|
||||
|
||||
let stickerSet = await appStickersManager.getStickerSet(set);
|
||||
|
||||
if(stickerSet.set.thumb) {
|
||||
let thumb = stickerSet.set.thumb;
|
||||
//console.log('got stickerSet', stickerSet, li);
|
||||
|
||||
if(stickerSet.set.thumb) {
|
||||
appStickersManager.getStickerSetThumb(stickerSet.set).then((blob) => {
|
||||
if(thumb.w == 1 && thumb.h == 1) { // means animated
|
||||
//console.log('setting thumb', stickerSet, blob);
|
||||
if(stickerSet.set.pFlags.animated) { // means animated
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.addEventListener('loadend', async(e) => {
|
||||
|
@ -38,7 +38,7 @@ export default () => {
|
||||
installed = true;
|
||||
|
||||
//const countries: Country[] = _countries.default.filter(c => c.emoji);
|
||||
const countries: Country[] = Config.Countries.filter(c => c.emoji);
|
||||
const countries: Country[] = Config.Countries.filter(c => c.emoji).sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
let lastCountrySelected = '';
|
||||
|
||||
@ -174,9 +174,9 @@ export default () => {
|
||||
}
|
||||
|
||||
if(country && (this.value.length - 1) >= (country.pattern ? country.pattern.length : 9)) {
|
||||
btnNext.style.display = '';
|
||||
btnNext.style.visibility = '';
|
||||
} else {
|
||||
btnNext.style.display = 'none';
|
||||
btnNext.style.visibility = 'hidden';
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -105,6 +105,10 @@ export default class Scrollable {
|
||||
this.container = document.createElement('div');
|
||||
this.container.classList.add('scrollable');
|
||||
|
||||
if(!appendTo) {
|
||||
this.appendTo = this.container;
|
||||
}
|
||||
|
||||
this.log = logger('SCROLL' + (logPrefix ? '-' + logPrefix : ''));
|
||||
|
||||
this.measureMutex = deferredPromise<void>();
|
||||
@ -413,7 +417,7 @@ export default class Scrollable {
|
||||
let appendTo = this.splitUp || this.appendTo;
|
||||
|
||||
clearTimeout(this.disableHoverTimeout);
|
||||
if(this.el != this.appendTo) {
|
||||
if(this.el != this.appendTo && this.appendTo != this.container) {
|
||||
if(!appendTo.classList.contains('disable-hover')) {
|
||||
appendTo.classList.add('disable-hover');
|
||||
}
|
||||
|
@ -543,7 +543,7 @@ export function wrapSticker(doc: MTDocument, div: HTMLDivElement, middleware?: (
|
||||
if(doc.thumbs && !div.firstElementChild && (!doc.downloaded || stickerType == 2)) {
|
||||
let thumb = doc.thumbs[0];
|
||||
|
||||
console.log('wrap sticker', thumb, div);
|
||||
//console.log('wrap sticker', thumb, div);
|
||||
|
||||
if(thumb.bytes) {
|
||||
apiFileManager.saveSmallFile(thumb.location, thumb.bytes);
|
||||
|
@ -1336,7 +1336,7 @@ export class AppImManager {
|
||||
|
||||
this.log('messageMediaDocument', doc, bubble);
|
||||
|
||||
if(doc.sticker && doc.size <= 1e6) {
|
||||
if(doc.sticker/* && doc.size <= 1e6 */) {
|
||||
bubble.classList.add('sticker');
|
||||
|
||||
if(doc.animated) {
|
||||
|
@ -8,6 +8,7 @@ import appMessagesIDsManager from "./appMessagesIDsManager";
|
||||
import appImManager from "./appImManager";
|
||||
import appUsersManager from "./appUsersManager";
|
||||
import { appPeersManager } from "../services";
|
||||
import apiManager from "../mtproto/apiManager";
|
||||
|
||||
let testScroll = false;
|
||||
|
||||
@ -50,6 +51,7 @@ class AppSidebarLeft {
|
||||
private menuEl = this.toolsBtn.querySelector('.btn-menu');
|
||||
private savedBtn = this.menuEl.querySelector('.menu-saved');
|
||||
private archivedBtn = this.menuEl.querySelector('.menu-archive');
|
||||
private logOutBtn = this.menuEl.querySelector('.menu-logout');
|
||||
public archivedCount = this.archivedBtn.querySelector('.archived-count') as HTMLSpanElement;
|
||||
|
||||
private listsContainer: HTMLDivElement = null;
|
||||
@ -131,6 +133,10 @@ class AppSidebarLeft {
|
||||
//this.toolsBtn.classList.add('tgico-back');
|
||||
});
|
||||
|
||||
this.logOutBtn.addEventListener('click', (e) => {
|
||||
apiManager.logOut();
|
||||
});
|
||||
|
||||
if(testScroll) {
|
||||
for(let i = 0; i < 1000; ++i) {
|
||||
let li = document.createElement('li');
|
||||
|
@ -2,6 +2,7 @@ import AppStorage from '../storage';
|
||||
import { MTDocument } from '../../components/wrappers';
|
||||
import apiManager from '../mtproto/apiManager';
|
||||
import apiFileManager from '../mtproto/apiFileManager';
|
||||
import appDocsManager from './appDocsManager';
|
||||
|
||||
export type MTStickerSet = {
|
||||
_: 'stickerSet',
|
||||
@ -27,6 +28,9 @@ export type MTStickerSet = {
|
||||
h: number,
|
||||
size: number
|
||||
},
|
||||
pFlags: {
|
||||
animated?: boolean
|
||||
}
|
||||
thumb_dc_id?: number,
|
||||
count: number,
|
||||
hash: number
|
||||
@ -52,12 +56,23 @@ class appStickersManager {
|
||||
[stickerSetID: string]: MTStickerSetFull
|
||||
}>('stickerSets').then((sets) => {
|
||||
if(sets) {
|
||||
for(let id in sets) {
|
||||
let set = sets[id];
|
||||
set.documents.forEach(doc => {
|
||||
delete doc.downloaded;
|
||||
delete doc.url;
|
||||
|
||||
this.saveSticker(doc);
|
||||
});
|
||||
}
|
||||
|
||||
this.stickerSets = sets;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public saveSticker(doc: MTDocument) {
|
||||
if(this.documents[doc.id]) return this.documents[doc.id];
|
||||
/* Object.keys(doc).forEach(key => {
|
||||
if(doc[key] instanceof Uint8Array) {
|
||||
doc[key] = Array.from(doc[key]);
|
||||
@ -66,7 +81,10 @@ class appStickersManager {
|
||||
|
||||
doc.file_reference = Array.from(doc.file_reference);
|
||||
|
||||
appDocsManager.saveDoc(doc);
|
||||
this.documents[doc.id] = doc;
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
public getSticker(fileID: string) {
|
||||
|
@ -282,7 +282,7 @@ export function longToInts(sLong: string) {
|
||||
return [divRem[0].intValue(), divRem[1].intValue()];
|
||||
}
|
||||
|
||||
export function bytesFromWords(wordArray: any) {
|
||||
export function bytesFromWords(wordArray: {words: number[] | Uint8Array | Uint32Array, sigBytes: number}) {
|
||||
var words = wordArray.words;
|
||||
var sigBytes = wordArray.sigBytes;
|
||||
var bytes = [];
|
||||
@ -294,6 +294,30 @@ export function bytesFromWords(wordArray: any) {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
export function bytesFromWordss(input: Uint32Array) {
|
||||
var o = [];
|
||||
for(var i = 0; i < input.length * 4; i++) {
|
||||
o.push((input[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff);
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
export function bytesToWordss(input: ArrayBuffer | Uint8Array) {
|
||||
let bytes: Uint8Array;
|
||||
if(input instanceof ArrayBuffer) bytes = new Uint8Array(input);
|
||||
else bytes = input;
|
||||
|
||||
var len = bytes.length;
|
||||
var words: number[] = [];
|
||||
var i;
|
||||
for(i = 0; i < len; i++) {
|
||||
words[i >>> 2] |= bytes[i] << (24 - (i % 4) * 8);
|
||||
}
|
||||
|
||||
return new Uint32Array(words);
|
||||
}
|
||||
|
||||
export function longToBytes(sLong: string) {
|
||||
return bytesFromWords({words: longToInts(sLong), sigBytes: 8}).reverse();
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,6 @@
|
||||
import sha1 from '@cryptography/sha1';
|
||||
import sha256 from '@cryptography/sha256';
|
||||
import {IGE} from '@cryptography/aes';
|
||||
|
||||
import {str2bigInt, bpe, equalsInt, greater,
|
||||
copy_, eGCD_, add_, rightShift_, sub_, copyInt_, isZero,
|
||||
@ -9,43 +10,13 @@ import {str2bigInt, bpe, equalsInt, greater,
|
||||
// @ts-ignore
|
||||
import {BigInteger} from 'jsbn';
|
||||
|
||||
import CryptoJS from './crypto.js';
|
||||
import { addPadding, bytesToHex, bytesFromHex, nextRandomInt, bytesFromBigInt, dT, bytesFromWords } from '../bin_utils';
|
||||
import { addPadding, bytesToHex, bytesFromHex, nextRandomInt, bytesFromBigInt, dT, bytesFromWords, bytesToWordss, bytesFromWordss } from '../bin_utils';
|
||||
|
||||
export function bytesFromLeemonBigInt(bigInt: BigInteger) {
|
||||
var str = bigInt2str(bigInt, 16);
|
||||
return bytesFromHex(str);
|
||||
}
|
||||
|
||||
export function bytesToWordss(input: ArrayBuffer | Uint8Array) {
|
||||
let bytes: Uint8Array;
|
||||
if(input instanceof ArrayBuffer) bytes = new Uint8Array(input);
|
||||
else bytes = input;
|
||||
|
||||
var len = bytes.length;
|
||||
var words: number[] = [];
|
||||
var i;
|
||||
for(i = 0; i < len; i++) {
|
||||
words[i >>> 2] |= bytes[i] << (24 - (i % 4) * 8);
|
||||
}
|
||||
|
||||
return new Uint32Array(words);
|
||||
}
|
||||
|
||||
export function bytesToWords(bytes: any) {
|
||||
if(bytes instanceof ArrayBuffer) {
|
||||
bytes = new Uint8Array(bytes);
|
||||
}
|
||||
var len = bytes.length;
|
||||
var words: any = [];
|
||||
var i;
|
||||
for(i = 0; i < len; i++) {
|
||||
words[i >>> 2] |= bytes[i] << (24 - (i % 4) * 8);
|
||||
}
|
||||
|
||||
return new CryptoJS.lib.WordArray.init(words, len);
|
||||
}
|
||||
|
||||
export function sha1HashSync(bytes: number[] | ArrayBuffer | Uint8Array) {
|
||||
//console.trace(dT(), 'SHA-1 hash start', bytes);
|
||||
|
||||
@ -68,54 +39,35 @@ export function sha256HashSync(bytes: Uint8Array | ArrayBuffer) {
|
||||
let words = bytesToWordss(bytes);
|
||||
let hash = sha256(words);
|
||||
|
||||
// bytesFromWords below
|
||||
var o = [];
|
||||
for(var i = 0; i < hash.length * 4; i++) {
|
||||
o.push((hash[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff);
|
||||
}
|
||||
|
||||
//console.log(dT(), 'SHA-256 hash finish');
|
||||
|
||||
return o;
|
||||
return bytesFromWordss(hash);
|
||||
}
|
||||
|
||||
export function aesEncryptSync(bytes: any, keyBytes: any, ivBytes: any) {
|
||||
// console.log(dT(), 'AES encrypt start', len/*, bytesToHex(keyBytes), bytesToHex(ivBytes)*/)
|
||||
export function aesEncryptSync(bytes: ArrayBuffer, keyBytes: ArrayBuffer, ivBytes: ArrayBuffer) {
|
||||
//console.log(dT(), 'AES encrypt start', bytes, keyBytes, ivBytes);
|
||||
// console.log('aes before padding bytes:', bytesToHex(bytes));
|
||||
bytes = addPadding(bytes);
|
||||
// console.log('aes after padding bytes:', bytesToHex(bytes));
|
||||
|
||||
let mode = CryptoJS.mode.IGE;
|
||||
const cipher = new IGE(bytesToWordss(keyBytes), bytesToWordss(ivBytes));
|
||||
const encryptedBytes = cipher.encrypt(bytesToWordss(bytes));
|
||||
//console.log(dT(), 'AES encrypt finish');
|
||||
|
||||
let encryptedWords = CryptoJS.AES.encrypt(bytesToWords(bytes), bytesToWords(keyBytes), {
|
||||
iv: bytesToWords(ivBytes),
|
||||
padding: CryptoJS.pad.NoPadding,
|
||||
mode//: CryptoJS.mode.IGE
|
||||
}).ciphertext;
|
||||
|
||||
let encryptedBytes = bytesFromWords(encryptedWords);
|
||||
// console.log(dT(), 'AES encrypt finish')
|
||||
|
||||
return encryptedBytes;
|
||||
return bytesFromWordss(encryptedBytes);
|
||||
}
|
||||
|
||||
export function aesDecryptSync(encryptedBytes: any, keyBytes: any, ivBytes: any) {
|
||||
export function aesDecryptSync(bytes: Uint8Array, keyBytes: Uint8Array, ivBytes: Uint8Array) {
|
||||
//console.log(dT(), 'AES decrypt start', bytes, keyBytes, ivBytes);
|
||||
|
||||
let mode = CryptoJS.mode.IGE;
|
||||
// console.log(dT(), 'AES decrypt start', encryptedBytes.length)
|
||||
var decryptedWords = CryptoJS.AES.decrypt({ciphertext: bytesToWords(encryptedBytes)}, bytesToWords(keyBytes), {
|
||||
iv: bytesToWords(ivBytes),
|
||||
padding: CryptoJS.pad.NoPadding,
|
||||
mode//: CryptoJS.mode.IGE
|
||||
});
|
||||
const cipher = new IGE(bytesToWordss(keyBytes), bytesToWordss(ivBytes));
|
||||
const decryptedBytes = cipher.decrypt(bytesToWordss(bytes));
|
||||
|
||||
var bytes = bytesFromWords(decryptedWords);
|
||||
// console.log(dT(), 'AES decrypt finish')
|
||||
//console.log(dT(), 'AES decrypt finish');
|
||||
|
||||
return bytes;
|
||||
return bytesFromWordss(decryptedBytes);
|
||||
}
|
||||
|
||||
|
||||
export function rsaEncrypt(publicKey: {modulus: string, exponent: string}, bytes: any): number[] {
|
||||
console.log(dT(), 'RSA encrypt start', publicKey, bytes);
|
||||
|
||||
|
@ -88,36 +88,26 @@ class CryptoWorker {
|
||||
}
|
||||
|
||||
public sha1Hash(bytes: number[] | ArrayBuffer | Uint8Array): Promise<Uint8Array> {
|
||||
//if(this.webWorker) {
|
||||
return this.performTaskWorker<Uint8Array>('sha1-hash', bytes);
|
||||
//}
|
||||
return this.performTaskWorker<Uint8Array>('sha1-hash', bytes);
|
||||
}
|
||||
|
||||
public sha256Hash(bytes: any) {
|
||||
//if(this.webWorker) {
|
||||
return this.performTaskWorker<number[]>('sha256-hash', bytes);
|
||||
//}
|
||||
return this.performTaskWorker<number[]>('sha256-hash', bytes);
|
||||
}
|
||||
|
||||
public pbkdf2(buffer: Uint8Array, salt: Uint8Array, iterations: number) {
|
||||
//if(this.webWorker) {
|
||||
return this.performTaskWorker<ArrayBuffer>('pbkdf2', buffer, salt, iterations);
|
||||
//}
|
||||
return this.performTaskWorker<ArrayBuffer>('pbkdf2', buffer, salt, iterations);
|
||||
}
|
||||
|
||||
public aesEncrypt(bytes: any, keyBytes: any, ivBytes: any) {
|
||||
//if(this.webWorker) {
|
||||
return this.performTaskWorker<ArrayBuffer>('aes-encrypt', convertToArrayBuffer(bytes),
|
||||
convertToArrayBuffer(keyBytes), convertToArrayBuffer(ivBytes));
|
||||
//}
|
||||
return this.performTaskWorker<ArrayBuffer>('aes-encrypt', convertToArrayBuffer(bytes),
|
||||
convertToArrayBuffer(keyBytes), convertToArrayBuffer(ivBytes));
|
||||
}
|
||||
|
||||
public aesDecrypt(encryptedBytes: any, keyBytes: any, ivBytes: any): Promise<ArrayBuffer> {
|
||||
//if(this.webWorker) {
|
||||
return this.performTaskWorker<ArrayBuffer>('aes-decrypt',
|
||||
encryptedBytes, keyBytes, ivBytes)
|
||||
.then(bytes => convertToArrayBuffer(bytes));
|
||||
//}
|
||||
return this.performTaskWorker<ArrayBuffer>('aes-decrypt',
|
||||
encryptedBytes, keyBytes, ivBytes)
|
||||
.then(bytes => convertToArrayBuffer(bytes));
|
||||
}
|
||||
|
||||
public rsaEncrypt(publicKey: {modulus: string, exponent: string}, bytes: any): Promise<number[]> {
|
||||
@ -127,21 +117,15 @@ class CryptoWorker {
|
||||
public factorize(bytes: any) {
|
||||
bytes = convertToByteArray(bytes);
|
||||
|
||||
//if(this.webWorker) {
|
||||
return this.performTaskWorker<[number[], number[], number]>('factorize', bytes);
|
||||
//}
|
||||
return this.performTaskWorker<[number[], number[], number]>('factorize', bytes);
|
||||
}
|
||||
|
||||
public modPow(x: any, y: any, m: any) {
|
||||
//if(this.webWorker) {
|
||||
return this.performTaskWorker<number[]>('mod-pow', x, y, m);
|
||||
//}
|
||||
return this.performTaskWorker<number[]>('mod-pow', x, y, m);
|
||||
}
|
||||
|
||||
public gzipUncompress<T>(bytes: ArrayBuffer, toString?: boolean) {
|
||||
//if(this.webWorker) {
|
||||
return this.performTaskWorker<T>('unzip', bytes, toString);
|
||||
//}
|
||||
return this.performTaskWorker<T>('unzip', bytes, toString);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,14 +78,16 @@ export class ApiManager {
|
||||
AppStorage.remove('dc', 'user_auth', 'stickerSets');
|
||||
this.baseDcID = 0;
|
||||
this.telegramMeNotify(false);
|
||||
return this.mtpClearStorage();
|
||||
this.mtpClearStorage();
|
||||
}, (error) => {
|
||||
storageKeys.push('dc', 'user_auth', 'stickerSets');
|
||||
AppStorage.remove(storageKeys);
|
||||
this.baseDcID = 0;
|
||||
error.handled = true;
|
||||
this.telegramMeNotify(false);
|
||||
return this.mtpClearStorage();
|
||||
this.mtpClearStorage();
|
||||
}).then(() => {
|
||||
location.pathname = '/';
|
||||
});
|
||||
}
|
||||
|
||||
@ -224,17 +226,7 @@ export class ApiManager {
|
||||
setTimeout(() => {
|
||||
if(!error.handled) {
|
||||
if(error.code == 401) {
|
||||
// @ts-ignore WARNING!
|
||||
this.logOut().finally(() => {
|
||||
if(location.protocol == 'http:' &&
|
||||
!Config.Modes.http &&
|
||||
Config.App.domains.indexOf(location.hostname) != -1) {
|
||||
location.href = location.href.replace(/^http:/, 'https:');
|
||||
} else {
|
||||
location.hash = '/login';
|
||||
// AppRuntimeManager.reload(); // WARNING
|
||||
}
|
||||
})
|
||||
this.logOut();
|
||||
} else {
|
||||
// ErrorService.show({error: error}); // WARNING
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { bytesFromHex, addPadding } from "../../bin_utils";
|
||||
//import { bytesFromHex, addPadding } from "../../bin_utils";
|
||||
import { Codec } from "./codec";
|
||||
|
||||
class AbridgedPacketCodec {
|
||||
class AbridgedPacketCodec implements Codec {
|
||||
public tag = 0xef;
|
||||
public obfuscateTag = new Uint8Array([this.tag, this.tag, this.tag, this.tag]);
|
||||
|
||||
@ -9,12 +10,14 @@ class AbridgedPacketCodec {
|
||||
let header: Uint8Array;
|
||||
if(len < 127) {
|
||||
header = new Uint8Array([len]);
|
||||
} else {
|
||||
header = new Uint8Array([0x7f, ...addPadding(bytesFromHex(len.toString(16)).reverse(), 3, true)/* .reverse() */]);
|
||||
} else { // Length: payload length, divided by four, and encoded as 3 length bytes (little endian)
|
||||
//header = new Uint8Array([0x7f, ...addPadding(bytesFromHex(len.toString(16)).reverse(), 3, true)/* .reverse() */]);
|
||||
header = new Uint8Array([0x7f, len & 0xFF, (len >> 8) & 0xFF, (len >> 16) & 0xFF]);
|
||||
//console.log('got nobody cause im braindead', header, len);
|
||||
}
|
||||
|
||||
return new Uint8Array([...header, ...data]);
|
||||
return header.concat(data);
|
||||
//return new Uint8Array([...header, ...data]);
|
||||
}
|
||||
|
||||
public readPacket(data: Uint8Array) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
export interface Codec {
|
||||
tag?: number;
|
||||
obfuscateTag?: Uint8Array;
|
||||
tag: number;
|
||||
obfuscateTag: Uint8Array;
|
||||
|
||||
encodePacket: (data: Uint8Array) => Uint8Array;
|
||||
readPacket: (data: Uint8Array) => Uint8Array;
|
||||
|
49
src/lib/mtproto/transports/intermediate.ts
Normal file
49
src/lib/mtproto/transports/intermediate.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import { nextRandomInt } from "../../bin_utils";
|
||||
import { Codec } from "./codec";
|
||||
|
||||
class IntermediatePacketCodec implements Codec {
|
||||
public tag = 0xee;
|
||||
public obfuscateTag = new Uint8Array([this.tag, this.tag, this.tag, this.tag]);
|
||||
|
||||
public encodePacket(data: Uint8Array) {
|
||||
let len = data.byteLength;
|
||||
let header = new Uint8Array(new Uint32Array([len]).buffer);
|
||||
|
||||
return header.concat(data);
|
||||
}
|
||||
|
||||
public readPacket(data: Uint8Array) {
|
||||
let length = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
|
||||
|
||||
return data.slice(4, 4 + length);
|
||||
}
|
||||
}
|
||||
|
||||
/* Data packets are aligned to 4bytes. This codec adds random bytes of size
|
||||
from 0 to 3 bytes, which are ignored by decoder. */
|
||||
class PaddedIntermediatePacketCodec extends IntermediatePacketCodec {
|
||||
public tag = 0xdd;
|
||||
public obfuscateTag = new Uint8Array([this.tag, this.tag, this.tag, this.tag]);
|
||||
|
||||
public encodePacket(data: Uint8Array) {
|
||||
let padding = new Uint8Array(nextRandomInt(3)).randomize();
|
||||
let len = data.byteLength + padding.byteLength;
|
||||
|
||||
let header = new Uint8Array(new Uint32Array([len]).buffer);
|
||||
console.log('encodePacket', padding, len, data, header);
|
||||
|
||||
return header.concat(data, padding);
|
||||
}
|
||||
|
||||
public readPacket(data: Uint8Array) {
|
||||
let padLength = data.byteLength % 4;
|
||||
if(padLength > 0) {
|
||||
return data.slice(4, -padLength);
|
||||
}
|
||||
|
||||
return data.slice(4);
|
||||
}
|
||||
}
|
||||
|
||||
export default new IntermediatePacketCodec();
|
||||
//export default new PaddedIntermediatePacketCodec();
|
@ -1,15 +1,25 @@
|
||||
import MTTransport from './transport';
|
||||
|
||||
import aesjs from 'aes-js';
|
||||
import abridgetPacketCodec from './abridged';
|
||||
//import aesjs from 'aes-js';
|
||||
import {CTR} from '@cryptography/aes';
|
||||
//import abridgetPacketCodec from './abridged';
|
||||
import intermediatePacketCodec from './intermediate';
|
||||
import {MTPNetworker} from '../networker';
|
||||
import { logger } from '../../polyfill';
|
||||
import { bytesFromWordss } from '../../bin_utils';
|
||||
import { Codec } from './codec';
|
||||
|
||||
/*
|
||||
@cryptography/aes не работает с массивами которые не кратны 4, поэтому использую intermediate а не abridged
|
||||
*/
|
||||
export class Obfuscation {
|
||||
public enc: aesjs.ModeOfOperation.ModeOfOperationCTR;
|
||||
public dec: aesjs.ModeOfOperation.ModeOfOperationCTR;
|
||||
/* public enc: aesjs.ModeOfOperation.ModeOfOperationCTR;
|
||||
public dec: aesjs.ModeOfOperation.ModeOfOperationCTR; */
|
||||
|
||||
public init() {
|
||||
public encNew: CTR;
|
||||
public decNew: CTR;
|
||||
|
||||
public init(codec: Codec) {
|
||||
const initPayload = new Uint8Array(64);
|
||||
initPayload.randomize();
|
||||
|
||||
@ -22,6 +32,7 @@ export class Obfuscation {
|
||||
val != 0x20544547 &&
|
||||
val != 0x4954504f &&
|
||||
val != 0xeeeeeeee &&
|
||||
val != 0xdddddddd &&
|
||||
val2 != 0x00000000) {
|
||||
//initPayload[56] = initPayload[57] = initPayload[58] = initPayload[59] = transport;
|
||||
break;
|
||||
@ -38,10 +49,13 @@ export class Obfuscation {
|
||||
let decKey = reversedPayload.slice(8, 40);
|
||||
let decIv = reversedPayload.slice(40, 56);
|
||||
|
||||
this.enc = new aesjs.ModeOfOperation.ctr(encKey, new aesjs.Counter(encIv as any));
|
||||
this.dec = new aesjs.ModeOfOperation.ctr(decKey, new aesjs.Counter(decIv as any));
|
||||
/* this.enc = new aesjs.ModeOfOperation.ctr(encKey, new aesjs.Counter(encIv as any));
|
||||
this.dec = new aesjs.ModeOfOperation.ctr(decKey, new aesjs.Counter(decIv as any)); */
|
||||
|
||||
initPayload.set(abridgetPacketCodec.obfuscateTag, 56);
|
||||
this.encNew = new CTR(encKey, encIv);
|
||||
this.decNew = new CTR(decKey, decIv);
|
||||
|
||||
initPayload.set(intermediatePacketCodec.obfuscateTag, 56);
|
||||
const encrypted = this.encode(initPayload);
|
||||
|
||||
initPayload.set(encrypted.slice(56, 64), 56);
|
||||
@ -49,12 +63,47 @@ export class Obfuscation {
|
||||
return initPayload;
|
||||
}
|
||||
|
||||
public encode(payload: Uint8Array) {
|
||||
return this.enc.encrypt(payload);
|
||||
/* public encode(payload: Uint8Array) {
|
||||
let res = this.enc.encrypt(payload);
|
||||
|
||||
try {
|
||||
let arr = this.encNew.encrypt(payload);
|
||||
//let resNew = bytesFromWords({words: arr, sigBytes: arr.length});
|
||||
let resNew = new Uint8Array(bytesFromWordss(arr));
|
||||
console.log('Obfuscation: encode comparison:', res, arr, resNew, res.hex == resNew.hex);
|
||||
} catch(err) {
|
||||
console.error('Obfuscation: error:', err);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public decode(data: Uint8Array) {
|
||||
return this.dec.encrypt(data);
|
||||
public decode(payload: Uint8Array) {
|
||||
let res = this.dec.encrypt(payload);
|
||||
|
||||
try {
|
||||
let arr = this.decNew.decrypt(payload);
|
||||
//let resNew = bytesFromWords({words: arr, sigBytes: arr.length});
|
||||
let resNew = new Uint8Array(bytesFromWordss(arr));
|
||||
console.log('Obfuscation: decode comparison:', res, arr, resNew, res.hex == resNew.hex);
|
||||
} catch(err) {
|
||||
console.error('Obfuscation: error:', err);
|
||||
}
|
||||
|
||||
return res;
|
||||
} */
|
||||
public encode(payload: Uint8Array) {
|
||||
let res = this.encNew.encrypt(payload);
|
||||
let bytes = new Uint8Array(bytesFromWordss(res));
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public decode(payload: Uint8Array) {
|
||||
let res = this.decNew.decrypt(payload);
|
||||
let bytes = new Uint8Array(bytesFromWordss(res));
|
||||
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,6 +124,8 @@ export default class Socket extends MTTransport {
|
||||
|
||||
debug = false;
|
||||
|
||||
codec = intermediatePacketCodec;
|
||||
|
||||
constructor(dcID: number, url: string) {
|
||||
super(dcID, url);
|
||||
|
||||
@ -103,7 +154,7 @@ export default class Socket extends MTTransport {
|
||||
handleOpen = () => {
|
||||
this.log('opened');
|
||||
|
||||
this.ws.send(this.obfuscation.init());
|
||||
this.ws.send(this.obfuscation.init(this.codec));
|
||||
this.connected = true;
|
||||
|
||||
this.releasePending();
|
||||
@ -126,7 +177,7 @@ export default class Socket extends MTTransport {
|
||||
this.debug && this.log('<-', 'handleMessage', event);
|
||||
|
||||
let data = this.obfuscation.decode(new Uint8Array(event.data));
|
||||
data = abridgetPacketCodec.readPacket(data);
|
||||
data = this.codec.readPacket(data);
|
||||
|
||||
if(this.networker) { // authenticated!
|
||||
//this.pending = this.pending.filter(p => p.body); // clear pending
|
||||
@ -175,7 +226,7 @@ export default class Socket extends MTTransport {
|
||||
let pending = this.pending[i];
|
||||
let {body} = pending;
|
||||
if(body) {
|
||||
let toEncode = abridgetPacketCodec.encodePacket(body);
|
||||
let toEncode = this.codec.encodePacket(body);
|
||||
|
||||
//console.log('send before obf:', /* body.hex, nonce.hex, */ toEncode.hex);
|
||||
let enc = this.obfuscation.encode(toEncode);
|
||||
|
@ -80,6 +80,10 @@ Uint8Array.prototype.concat = function(...args: Array<Uint8Array | ArrayBuffer |
|
||||
return bufferConcats(this, ...args);
|
||||
};
|
||||
|
||||
Uint8Array.prototype.toString = function() {
|
||||
return String.fromCharCode.apply(null, [...this]);
|
||||
};
|
||||
|
||||
Array.prototype.forEachReverse = function<T>(callback: (value: T, index?: number, array?: Array<T>) => void) {
|
||||
let length = this.length;
|
||||
for(var i = length - 1; i >= 0; --i) {
|
||||
@ -108,7 +112,8 @@ declare global {
|
||||
interface Uint8Array {
|
||||
hex: string;
|
||||
randomize: () => Uint8Array,
|
||||
concat: (...args: Array<Uint8Array | ArrayBuffer | number[]>) => Uint8Array
|
||||
concat: (...args: Array<Uint8Array | ArrayBuffer | number[]>) => Uint8Array,
|
||||
toString: () => string
|
||||
}
|
||||
|
||||
interface Array<T> {
|
||||
|
@ -1,3 +1,5 @@
|
||||
$chat-max-width: 696px;
|
||||
|
||||
.chat-container {
|
||||
display: flex;
|
||||
// padding: 200px;
|
||||
@ -57,7 +59,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
box-shadow: 0 1px 2px 0 rgba(16, 35, 47, 0.07);
|
||||
padding: .5rem 1rem;
|
||||
padding: .5rem 17px;
|
||||
flex: 0 0 auto; /* Forces side columns to stay same width */
|
||||
min-height: 60px;
|
||||
max-height: 60px;
|
||||
@ -71,8 +73,9 @@
|
||||
}
|
||||
|
||||
.content {
|
||||
padding-left: 1rem;
|
||||
flex: 1;
|
||||
padding-left: 17px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.person {
|
||||
@ -93,7 +96,7 @@
|
||||
.bottom {
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
color: $placeholder-color;
|
||||
color: #707579;
|
||||
|
||||
.online {
|
||||
color: $darkblue;
|
||||
@ -220,7 +223,7 @@
|
||||
.bubble {
|
||||
padding-top: 5px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 700px 1fr;
|
||||
grid-template-columns: 1fr $chat-max-width 1fr;
|
||||
grid-row-gap: 0px;
|
||||
|
||||
&:before, &:after {
|
||||
@ -1069,9 +1072,9 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
max-width: 700px;
|
||||
max-width: $chat-max-width;
|
||||
padding-top: .35rem;
|
||||
padding-bottom: 1rem;
|
||||
padding-bottom: 21px;
|
||||
justify-content: space-between;
|
||||
flex: 0 0 auto; /* Forces side columns to stay same width */
|
||||
position: relative;
|
||||
@ -1080,8 +1083,8 @@
|
||||
background: none;
|
||||
border: none;
|
||||
width: 100%;
|
||||
padding: .5rem .5rem;
|
||||
font-size: .95rem;
|
||||
font-size: 16px;
|
||||
padding: 10px 9px;
|
||||
/* height: 100%; */
|
||||
max-height: 30rem;
|
||||
overflow-y: none;
|
||||
@ -1093,7 +1096,7 @@
|
||||
|
||||
[contenteditable=true]:empty:before {
|
||||
content: attr(data-placeholder);
|
||||
color: #9e9e9e;
|
||||
color: #a2acb4;
|
||||
display: block; /* For Firefox By Ariel Flesler */
|
||||
}
|
||||
|
||||
@ -1101,8 +1104,8 @@
|
||||
flex: 0 0 auto;
|
||||
font-size: 1.5rem;
|
||||
line-height: 1.5rem;
|
||||
height: 3.25rem;
|
||||
width: 3.25rem;
|
||||
height: 54px;
|
||||
width: 54px;
|
||||
color: #9e9e9e;
|
||||
background-color: #fff;
|
||||
align-self: flex-end;
|
||||
@ -1130,7 +1133,7 @@
|
||||
margin-right: 9px;
|
||||
padding: 4.5px .5rem;
|
||||
/* padding: 3px .5rem 6px .5rem; */
|
||||
min-height: 3.25rem;
|
||||
min-height: 54px;
|
||||
max-height: 30rem;
|
||||
caret-color: $button-primary-background;
|
||||
flex: 1;
|
||||
@ -1204,12 +1207,14 @@
|
||||
|
||||
.btn-icon {
|
||||
display: block;
|
||||
color: $placeholder-color;
|
||||
font-size: 1.5rem;
|
||||
line-height: 1.5rem;
|
||||
transition: .2s color;
|
||||
flex: 0 0 auto;
|
||||
|
||||
font-size: 24px;
|
||||
line-height: 24px;
|
||||
padding: 10px 7px 9px 7.5px;
|
||||
color: #8d969c;
|
||||
|
||||
&.active {
|
||||
color: $blue;
|
||||
}
|
||||
|
@ -2,18 +2,19 @@
|
||||
.input-search {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
margin-left: 1rem;
|
||||
margin-left: 22px;
|
||||
|
||||
input {
|
||||
background-color: rgba(112, 117, 121, .08);
|
||||
border: 2px solid transparent;
|
||||
height: 3rem;
|
||||
height: 44px;
|
||||
border-radius: 22px;
|
||||
box-sizing: border-box;
|
||||
padding: 0 1.5rem 0 3rem;
|
||||
padding: 0px 1.5rem 0 40px;
|
||||
-webkit-transition: all .15s ease-out;
|
||||
transition: all .15s ease-out;
|
||||
width: 100%;
|
||||
font-size: 16px;
|
||||
|
||||
&:focus {
|
||||
background-color: rgba(112, 117, 121, 0);
|
||||
@ -28,15 +29,19 @@
|
||||
|
||||
.tgico {
|
||||
position: absolute;
|
||||
left: 1rem;
|
||||
left: 12px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
text-align: center;
|
||||
font-size: 1.65rem;
|
||||
font-size: 24px;
|
||||
color: $color-gray;
|
||||
opacity: .6;
|
||||
-webkit-transition: all .15s ease-out;
|
||||
transition: all .15s ease-out;
|
||||
|
||||
&:before {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,8 +74,8 @@
|
||||
flex-direction: row;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
padding: 8px 8.5px;
|
||||
margin: 0 8.5px 0 8px;
|
||||
padding: 7px 8.5px;
|
||||
margin: 0px 8px 2px 7px;
|
||||
overflow: hidden;
|
||||
|
||||
&:hover {
|
||||
@ -84,7 +89,7 @@
|
||||
|
||||
.pinned-delimiter {
|
||||
display: flex;
|
||||
padding: 8px 0 4px;
|
||||
padding: 6px 0 6px;
|
||||
|
||||
span {
|
||||
margin: 0;
|
||||
@ -111,7 +116,9 @@
|
||||
/* span:not(.tgico-pinnedchat):not(.emoji):last-child { */
|
||||
.user-title + span {
|
||||
/* font-size: .9rem; */
|
||||
font-size: .8rem;
|
||||
//font-size: .8rem;
|
||||
font-size: .75rem;
|
||||
padding: 2px 0px 0px 0px;
|
||||
}
|
||||
|
||||
.user-last-message + span:not(.tgico-pinnedchat) {
|
||||
@ -143,7 +150,7 @@
|
||||
overflow: hidden;
|
||||
color: $color-gray;
|
||||
flex: 1 1 auto;
|
||||
padding-right: 6.5px;
|
||||
padding-right: 3.5px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
@ -209,6 +216,7 @@
|
||||
color: #fff;
|
||||
border-radius: 12px;
|
||||
margin-top: 1.5px;
|
||||
margin-right: -2px;
|
||||
}
|
||||
|
||||
.unread, .unread-muted {
|
||||
|
@ -8,7 +8,7 @@
|
||||
height: 420px;
|
||||
background: #fff;
|
||||
box-shadow: 0px 5px 10px 5px rgba(16, 35, 47, 0.14);
|
||||
border-radius: 12px;
|
||||
border-radius: 10px;
|
||||
z-index: 2;
|
||||
/* display: none; */
|
||||
display: flex;
|
||||
@ -25,7 +25,14 @@
|
||||
}
|
||||
|
||||
> .menu-horizontal {
|
||||
padding: 0 3rem;
|
||||
padding: 0px 58px 0px 58px;
|
||||
font-weight: 500;
|
||||
margin-top: 2px;
|
||||
|
||||
> li.active:after {
|
||||
left: 29px;
|
||||
right: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
.emoji-container {
|
||||
@ -35,6 +42,10 @@
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.btn-icon {
|
||||
color: #8d969c;
|
||||
}
|
||||
|
||||
.tabs-container {
|
||||
/* width: 300%; */
|
||||
height: 100%;
|
||||
@ -42,19 +53,27 @@
|
||||
.emoji-category {
|
||||
font-size: 2.25rem;
|
||||
line-height: 2.25rem;
|
||||
margin-top: 1px;
|
||||
padding-top: 1px;
|
||||
|
||||
display: grid;
|
||||
grid-column-gap: 2.44px;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
|
||||
|
||||
&:first-child {
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
> * {
|
||||
margin: 0;
|
||||
padding: 5px 5px;
|
||||
padding: 4px 4px;
|
||||
line-height: inherit;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
|
||||
.emoji {
|
||||
width: 100%;
|
||||
@ -72,7 +91,7 @@
|
||||
} */
|
||||
}
|
||||
|
||||
.emoji-category, .sticker-category {
|
||||
.sticker-category {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
@ -104,6 +123,7 @@
|
||||
padding: 1px 2.5px;
|
||||
justify-content: center;
|
||||
border-radius: 12px;
|
||||
padding: 0;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(112, 117, 121, 0.08);
|
||||
@ -129,7 +149,7 @@
|
||||
> div:first-of-type {
|
||||
flex: 1;
|
||||
padding: 0;
|
||||
padding-top: 10px;
|
||||
//padding-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,9 +166,9 @@
|
||||
|
||||
.emoji-padding, .stickers-padding {
|
||||
.menu-horizontal {
|
||||
height: 50px;
|
||||
height: 47px;
|
||||
border-bottom: none;
|
||||
padding: 0;
|
||||
padding: 2px 2px 2px 2px;
|
||||
width: 100%;
|
||||
|
||||
li {
|
||||
@ -168,9 +188,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* #content-stickers {
|
||||
padding: 0;
|
||||
} */
|
||||
#content-stickers {
|
||||
.scrollable {
|
||||
padding: 15px 5px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.emoji-padding, .stickers-padding {
|
||||
.menu-horizontal > li {
|
||||
|
@ -15,7 +15,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: .5rem 1.25rem;
|
||||
padding: 7.5px 20px 7.5px 15px;
|
||||
min-height: 60px;
|
||||
|
||||
.sidebar-title {
|
||||
|
@ -48,7 +48,7 @@ html, body {
|
||||
}
|
||||
|
||||
html {
|
||||
font-size: 15px;
|
||||
font-size: $text-size;
|
||||
}
|
||||
|
||||
a {
|
||||
@ -83,8 +83,8 @@ h1, h2, h3, h4, h5, h6 {
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 2.28rem;
|
||||
margin: 1.52rem 0 .912rem 0;
|
||||
font-size: 2rem;
|
||||
margin: 1.5rem 0 1rem 0;
|
||||
line-height: 110%;
|
||||
}
|
||||
|
||||
@ -94,7 +94,6 @@ input {
|
||||
|
||||
.subtitle {
|
||||
/* font-weight: 500; */
|
||||
font-size: 1rem;
|
||||
color: $placeholder-color;
|
||||
line-height: 1.25;
|
||||
}
|
||||
@ -103,7 +102,8 @@ input {
|
||||
.page-authCode .input-wrapper,
|
||||
.page-signUp .input-wrapper,
|
||||
.page-password .input-wrapper {
|
||||
margin-top: 3rem;
|
||||
/* margin-top: 3rem; */
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
.page-authCode {
|
||||
@ -281,7 +281,7 @@ input {
|
||||
|
||||
&[class*=" tgico-"] {
|
||||
line-height: 52px;
|
||||
font-size: 1.5rem;
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
path {
|
||||
@ -496,6 +496,14 @@ input {
|
||||
}
|
||||
}
|
||||
|
||||
.page-sign {
|
||||
.auth-image {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
margin-bottom: 45px;
|
||||
}
|
||||
}
|
||||
|
||||
.page-signUp {
|
||||
.auth-image {
|
||||
border-radius: 50%;
|
||||
@ -524,7 +532,7 @@ input {
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
width: 350px;
|
||||
width: 360px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
@ -536,7 +544,7 @@ input {
|
||||
content: " ";
|
||||
top: 50%;
|
||||
bottom: 0;
|
||||
right: 15px;
|
||||
right: 21px;
|
||||
cursor: pointer;
|
||||
|
||||
height: 0;
|
||||
@ -546,12 +554,12 @@ input {
|
||||
border-radius: 1px;
|
||||
border-width: 0 2px 2px 0;
|
||||
display: inline-block;
|
||||
padding: 4px;
|
||||
padding: 5px;
|
||||
vertical-align: middle;
|
||||
|
||||
z-index: 2;
|
||||
|
||||
margin-top: -7px;
|
||||
margin-top: -9px;
|
||||
transform: rotate(45deg);
|
||||
-webkit-transform: rotate(45deg);
|
||||
transition: .2s all;
|
||||
@ -560,13 +568,12 @@ input {
|
||||
label {
|
||||
position: absolute;
|
||||
color: $placeholder-color;
|
||||
left: 12.5px;
|
||||
left: 1rem;
|
||||
right: auto;
|
||||
z-index: 2;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background-color: #fff;
|
||||
font-size: 0.85rem;
|
||||
transition: .2s all, .1s opacity;
|
||||
display: inline-block;
|
||||
cursor: text;
|
||||
@ -574,12 +581,11 @@ input {
|
||||
|
||||
input {
|
||||
border: 1px solid #DADCE0;
|
||||
border-radius: $border-radius;
|
||||
padding: 0 12.5px;
|
||||
border-radius: $border-radius-big;
|
||||
padding: 0 1rem;
|
||||
box-sizing: border-box;
|
||||
font-size: 0.85rem;
|
||||
width: 100%;
|
||||
height: 45px;
|
||||
height: 54px;
|
||||
transition: .2s border-color;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
@ -587,8 +593,8 @@ input {
|
||||
|
||||
&:focus {
|
||||
border-color: $button-primary-background;
|
||||
border-width: 1.5px;
|
||||
padding: 0 12px;
|
||||
border-width: 2px;
|
||||
padding: 0 calc(1rem - 1px);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
@ -606,7 +612,7 @@ input {
|
||||
}
|
||||
|
||||
&:focus ~ .arrow-down {
|
||||
margin-top: -2px;
|
||||
margin-top: -4px;
|
||||
transform: rotate(225deg);
|
||||
-webkit-transform: rotate(225deg);
|
||||
border-color: $button-primary-background;
|
||||
@ -617,21 +623,21 @@ input {
|
||||
}
|
||||
|
||||
&:focus + label, &:valid + label, &:disabled + label {
|
||||
top: -8.5px;
|
||||
top: -.5rem;
|
||||
transform: none;
|
||||
padding: 0 5px;
|
||||
left: 7.5px;
|
||||
font-size: 0.85rem!important;
|
||||
left: .75rem;
|
||||
font-size: 0.75rem!important;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.checkbox-field {
|
||||
margin: 1rem 0;
|
||||
margin: 1.25rem 0;
|
||||
display: block;
|
||||
text-align: left;
|
||||
padding: 0 1rem;
|
||||
padding: 0 19px;
|
||||
/* font-weight: 500; */
|
||||
position: relative;
|
||||
}
|
||||
@ -646,12 +652,11 @@ input {
|
||||
|
||||
& + span {
|
||||
position: relative;
|
||||
padding-left: 35px;
|
||||
padding-left: calc(18px + 2.25rem);
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
font-size: 1rem;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
@ -718,7 +723,7 @@ input {
|
||||
}
|
||||
|
||||
.input-wrapper > * ~ * {
|
||||
margin-top: 1.2rem;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.select-wrapper {
|
||||
@ -726,7 +731,7 @@ input {
|
||||
/* height: auto; */
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: calc(100% + 10px);
|
||||
top: calc(100% + .5rem);
|
||||
left: 0;
|
||||
overflow: hidden;
|
||||
background-color: #fff;
|
||||
@ -737,15 +742,15 @@ input {
|
||||
flex-wrap: wrap;
|
||||
|
||||
ul {
|
||||
margin: 10px 0;
|
||||
margin: .5rem 0;
|
||||
}
|
||||
|
||||
li {
|
||||
/* display: flex; */
|
||||
align-items: center;
|
||||
padding: 0 12.5px;
|
||||
padding: 0 1rem;
|
||||
justify-content: space-between;
|
||||
height: 50px;
|
||||
height: 3.5rem;
|
||||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
|
||||
@ -850,8 +855,7 @@ input:focus, button:focus {
|
||||
border-radius: $border-radius;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 0.85rem;
|
||||
height: 45px;
|
||||
height: 54px;
|
||||
border: none;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
@ -1385,7 +1389,7 @@ div.scrollable::-webkit-scrollbar-thumb {
|
||||
text-align: center;
|
||||
flex: 1;
|
||||
user-select: none;
|
||||
font-size: 16px;
|
||||
font-size: 1rem;
|
||||
|
||||
&.active {
|
||||
position: relative;
|
||||
|
Loading…
x
Reference in New Issue
Block a user