tweb/src/index.ts

386 lines
12 KiB
TypeScript
Raw Normal View History

2021-04-08 17:13:05 +02:00
/*
* https://github.com/morethanwords/tweb
* Copyright (C) 2019-2021 Eduard Kuzmenko
* https://github.com/morethanwords/tweb/blob/master/LICENSE
*/
import App from './config/app';
import blurActiveElement from './helpers/dom/blurActiveElement';
import { cancelEvent } from './helpers/dom/cancelEvent';
2021-08-24 18:33:04 +02:00
import { IS_STICKY_INPUT_BUGGED } from './helpers/dom/fixSafariStickyInputFocusing';
import loadFonts from './helpers/dom/loadFonts';
import IS_EMOJI_SUPPORTED from './environment/emojiSupport';
import { IS_MOBILE_SAFARI } from './environment/userAgent';
2021-04-08 17:13:05 +02:00
import './materialize.scss';
import './scss/style.scss';
/* import { computeCheck } from './lib/crypto/srp';
import { salt1, salt2, g, p, srp_id, secure_random, srp_B, password } from './mock/srp'; */
//console.log('pineapples are in my head');
/* console.time('get storage1');
import * as a from './lib/config';
import * as b from './lib/mtproto/mtproto_config';
import * as c from './helpers/userAgent';
import * as d from './lib/mtproto/mtprotoworker';
import * as e from './lib/polyfill';
import * as f from './lib/storage';
a && b && c && d && e && f;
console.timeEnd('get storage1'); */
/* Promise.all([
import('./components/pageIm'),
import('./components/pageSignIn'),
import('./components/misc'),
import('./lib/storage')
]).then(imports => {
let [pageIm, pageSignIn, misc, AppStorage] = imports; */
document.addEventListener('DOMContentLoaded', async() => {
//let socket = new Socket(2);
if(!Element.prototype.toggleAttribute) {
Element.prototype.toggleAttribute = function(name, force) {
if(force !== void 0) force = !!force;
if(this.hasAttribute(name)) {
if(force) return true;
this.removeAttribute(name);
return false;
}
if(force === false) return false;
this.setAttribute(name, "");
return true;
};
}
// We listen to the resize event (https://css-tricks.com/the-trick-to-viewport-units-on-mobile/)
// @ts-ignore
const w = window.visualViewport || window; // * handle iOS keyboard
2021-08-26 02:41:13 +02:00
let setViewportVH = false/* , hasFocus = false */;
2021-04-15 10:44:27 +02:00
let lastVH: number;
2021-04-08 17:13:05 +02:00
const setVH = () => {
// @ts-ignore
const vh = (setViewportVH && !rootScope.default.isOverlayActive ? w.height || w.innerHeight : window.innerHeight) * 0.01;
2021-04-15 10:44:27 +02:00
if(lastVH === vh) {
return;
} else if(touchSupport.IS_TOUCH_SUPPORTED && lastVH < vh && (vh - lastVH) > 1) {
2021-08-21 15:01:14 +02:00
blurActiveElement(); // (Android) fix blurring inputs when keyboard is being closed (e.g. closing keyboard by back arrow and touching a bubble)
2021-04-15 10:44:27 +02:00
}
lastVH = vh;
2021-04-08 17:13:05 +02:00
//const vh = document.documentElement.scrollHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
//console.log('setVH', vh, setViewportVH ? w : window);
/* if(setViewportVH && userAgent.isSafari && touchSupport.isTouchSupported && document.activeElement && (document.activeElement as HTMLElement).blur) {
const rect = document.activeElement.getBoundingClientRect();
if(rect.top < 0 || rect.bottom >= (w as any).height) {
fastSmoothScroll(findUpClassName(document.activeElement, 'scrollable-y') || window as any, document.activeElement as HTMLElement, 'center', 4, undefined, FocusDirection.Static);
}
} */
};
// * hook worker constructor to set search parameters (test, debug, etc)
const workerHandler = {
construct(target: any, args: any) {
//console.log(target, args);
const url = args[0] + location.search;
return new target(url);
}
};
const workerProxy = new Proxy(Worker, workerHandler);
Worker = workerProxy;
2021-10-29 17:33:37 +02:00
const [_, touchSupport, userAgent, rootScope, appStateManager, I18n, __/* , ___ */] = await Promise.all([
2021-04-08 17:13:05 +02:00
import('./lib/polyfill'),
import('./environment/touchSupport'),
import('./environment/userAgent'),
2021-04-08 17:13:05 +02:00
import('./lib/rootScope'),
import('./lib/appManagers/appStateManager'),
import('./lib/langPack'),
2021-10-21 15:16:43 +02:00
import('./helpers/peerIdPolyfill'),
2021-10-29 17:33:37 +02:00
// import('./helpers/cacheFunctionPolyfill')
2021-08-26 02:41:13 +02:00
]);
2021-04-08 17:13:05 +02:00
//console.timeEnd('get storage');
2021-08-26 02:41:13 +02:00
window.addEventListener('resize', setVH);
setVH();
2021-04-08 17:13:05 +02:00
//console.log(new Uint8Array([255, 200, 145]).hex);
2021-08-26 02:41:13 +02:00
if(IS_STICKY_INPUT_BUGGED) {
const toggleResizeMode = () => {
setViewportVH = tabId === 1 && IS_STICKY_INPUT_BUGGED && !rootScope.default.isOverlayActive;
setVH();
if(w !== window) {
if(setViewportVH) {
window.removeEventListener('resize', setVH);
w.addEventListener('resize', setVH);
} else {
w.removeEventListener('resize', setVH);
window.addEventListener('resize', setVH);
}
2021-04-08 17:13:05 +02:00
}
2021-08-26 02:41:13 +02:00
};
let tabId: number;
rootScope.default.addEventListener('im_tab_change', (id) => {
const wasTabId = tabId !== undefined;
tabId = id;
if(wasTabId || tabId === 1) {
toggleResizeMode();
}
});
rootScope.default.addEventListener('overlay_toggle', () => {
2021-04-08 17:13:05 +02:00
toggleResizeMode();
2021-08-26 02:41:13 +02:00
});
}
2021-04-08 17:13:05 +02:00
if(userAgent.IS_FIREFOX && !IS_EMOJI_SUPPORTED) {
document.addEventListener('dragstart', (e) => {
const target = e.target as HTMLElement;
if(target.tagName === 'IMG' && target.classList.contains('emoji')) {
cancelEvent(e);
return false;
}
});
}
2021-07-22 13:52:18 +02:00
// prevent firefox image dragging
document.addEventListener('dragstart', (e) => {
if((e.target as HTMLElement)?.tagName === "IMG") {
e.preventDefault();
return false;
}
});
if(userAgent.IS_FIREFOX) {
document.documentElement.classList.add('is-firefox');
}
2022-03-24 15:16:41 +01:00
if(userAgent.IS_MOBILE) {
document.documentElement.classList.add('is-mobile');
}
if(userAgent.IS_APPLE) {
if(userAgent.IS_SAFARI) {
2021-04-08 17:13:05 +02:00
document.documentElement.classList.add('is-safari');
}
// document.documentElement.classList.add('emoji-supported');
2021-04-08 17:13:05 +02:00
if(userAgent.IS_APPLE_MOBILE) {
2021-04-08 17:13:05 +02:00
document.documentElement.classList.add('is-ios');
} else {
document.documentElement.classList.add('is-mac');
2021-04-08 17:13:05 +02:00
}
} else if(userAgent.IS_ANDROID) {
2021-04-08 17:13:05 +02:00
document.documentElement.classList.add('is-android');
2021-08-21 15:01:14 +02:00
2021-08-26 02:41:13 +02:00
/* document.addEventListener('focusin', (e) => {
2021-08-21 15:01:14 +02:00
hasFocus = true;
2021-08-26 02:41:13 +02:00
focusTime = Date.now();
2021-08-21 15:01:14 +02:00
}, {passive: true});
document.addEventListener('focusout', () => {
hasFocus = false;
2021-08-26 02:41:13 +02:00
}, {passive: true}); */
2021-04-08 17:13:05 +02:00
}
if(!touchSupport.IS_TOUCH_SUPPORTED) {
2021-04-08 17:13:05 +02:00
document.documentElement.classList.add('no-touch');
} else {
document.documentElement.classList.add('is-touch');
/* document.addEventListener('touchmove', (event: any) => {
event = event.originalEvent || event;
if(event.scale && event.scale !== 1) {
event.preventDefault();
}
}, {capture: true, passive: false}); */
}
/* if(config.isServiceWorkerSupported) {
await navigator.serviceWorker.ready;
navigator.serviceWorker.controller ? true : await new Promise((resolve, reject) => {
navigator.serviceWorker.addEventListener('controllerchange', resolve);
});
} */
//console.time('get storage');
const perf = performance.now();
//import('./vendor/dateFormat');
const langPromise = I18n.default.getCacheLangPack();
2021-04-08 17:13:05 +02:00
const [state, langPack] = await Promise.all([
appStateManager.default.getState(),
langPromise
]);
//I18n.getCacheLangPack();
//console.log('got auth:', auth);
//console.timeEnd('get storage');
2021-11-13 02:30:37 +01:00
I18n.default.setTimeFormat(state.settings.timeFormat);
rootScope.default.setThemeListener();
2021-04-08 17:13:05 +02:00
if(langPack.appVersion !== App.langPackVersion) {
I18n.default.getLangPack(langPack.lang_code);
}
2021-05-01 16:43:10 +02:00
/**
* won't fire if font is loaded too fast
*/
2021-06-25 14:10:50 +02:00
function fadeInWhenFontsReady(elem: HTMLElement, promise: Promise<any>) {
elem.style.opacity = '0';
promise.then(() => {
window.requestAnimationFrame(() => {
elem.style.opacity = '';
});
});
}
2021-04-08 17:13:05 +02:00
console.log('got state, time:', performance.now() - perf);
const authState = state.authState;
if(authState._ !== 'authStateSignedIn'/* || 1 === 1 */) {
console.log('Will mount auth page:', authState._, Date.now() / 1000);
const el = document.getElementById('auth-pages');
2021-05-01 16:33:08 +02:00
let scrollable: HTMLElement;
if(el) {
2021-05-01 16:33:08 +02:00
scrollable = el.querySelector('.scrollable') as HTMLElement;
if((!touchSupport.IS_TOUCH_SUPPORTED || IS_MOBILE_SAFARI)) {
scrollable.classList.add('no-scrollbar');
}
2021-05-01 16:33:08 +02:00
// * don't remove this line
scrollable.style.opacity = '0';
const placeholder = document.createElement('div');
placeholder.classList.add('auth-placeholder');
scrollable.prepend(placeholder);
scrollable.append(placeholder.cloneNode());
}
2021-06-18 04:30:36 +02:00
try {
2021-06-28 15:41:42 +02:00
await Promise.all([
import('./lib/mtproto/telegramMeWebManager'),
import('./lib/mtproto/webPushApiManager')
]).then(([meModule, pushModule]) => {
meModule.default.setAuthorized(false);
pushModule.default.forceUnsubscribe();
});
2021-06-18 04:30:36 +02:00
} catch(err) {
}
2021-05-01 16:43:10 +02:00
let pagePromise: Promise<void>;
2021-04-08 17:13:05 +02:00
//langPromise.then(async() => {
switch(authState._) {
case 'authStateSignIn':
2021-05-01 16:43:10 +02:00
pagePromise = (await import('./pages/pageSignIn')).default.mount();
2021-04-08 17:13:05 +02:00
break;
case 'authStateSignQr':
2021-05-01 16:43:10 +02:00
pagePromise = (await import('./pages/pageSignQR')).default.mount();
break;
2021-04-08 17:13:05 +02:00
case 'authStateAuthCode':
2021-05-01 16:43:10 +02:00
pagePromise = (await import('./pages/pageAuthCode')).default.mount(authState.sentCode);
2021-04-08 17:13:05 +02:00
break;
case 'authStatePassword':
2021-05-01 16:43:10 +02:00
pagePromise = (await import('./pages/pagePassword')).default.mount();
2021-04-08 17:13:05 +02:00
break;
case 'authStateSignUp':
2021-05-01 16:43:10 +02:00
pagePromise = (await import('./pages/pageSignUp')).default.mount(authState.authCode);
2021-04-08 17:13:05 +02:00
break;
}
//});
2021-05-01 16:33:08 +02:00
if(scrollable) {
2021-05-01 16:43:10 +02:00
// wait for text appear
if(pagePromise) {
await pagePromise;
}
2021-06-25 14:10:50 +02:00
const promise = 'fonts' in document ?
Promise.race([
new Promise((resolve) => setTimeout(resolve, 1e3)),
// @ts-ignore
document.fonts.ready
]) :
Promise.resolve();
2021-05-01 16:33:08 +02:00
fadeInWhenFontsReady(scrollable, promise);
}
2021-04-08 17:13:05 +02:00
/* computeCheck(password, {
current_algo: {
salt1,
salt2,
p,
g
},
srp_id,
srp_B,
secure_random,
}).then(res => {
console.log(res);
}); */
/* setTimeout(async() => {
(await import('./pages/pageAuthCode')).default.mount({
"_": "auth.sentCode",
"pFlags": {},
"flags": 6,
"type": {
"_": "auth.sentCodeTypeSms",
"length": 5
},
"phone_code_hash": "",
"next_type": {
"_": "auth.codeTypeCall"
},
"timeout": 120,
"phone_number": ""
});
}, 500); */
/* setTimeout(async() => {
(await import('./pages/pageSignQR')).default.mount();
}, 500); */
/* setTimeout(async() => {
(await import('./pages/pagePassword')).default.mount();
}, 500); */
/* setTimeout(async() => {
(await import('./pages/pageSignUp')).default.mount({
"phone_code_hash": "",
"phone_number": ""
});
}, 500); */
} else {
console.log('Will mount IM page:', Date.now() / 1000);
fadeInWhenFontsReady(document.getElementById('main-columns'), loadFonts());
2021-04-08 17:13:05 +02:00
(await import('./pages/pageIm')).default.mount();
//getNearestDc();
}
const ripple = (await import('./components/ripple')).ripple;
(Array.from(document.getElementsByClassName('rp')) as HTMLElement[]).forEach(el => ripple(el));
});
//});