tweb/public/18.33a13d3129fb705afcd7.chunk.js.map
Eduard Kuzmenko 10b7307141 Build
2022-01-25 10:36:42 +04:00

1 line
70 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{"version":3,"sources":["webpack:///./src/components/languageChangeButton.ts","webpack:///./src/helpers/fixBase64String.ts","webpack:///./src/components/ripple.ts","webpack:///./src/pages/pageSignQR.ts","webpack:///./src/helpers/dom/clickEvent.ts","webpack:///./src/components/button.ts","webpack:///./src/components/misc.ts","webpack:///./src/components/appNavigationController.ts","webpack:///./src/helpers/bytes.ts","webpack:///./src/helpers/dom/dispatchEvent.ts","webpack:///./src/helpers/sequentialDom.ts","webpack:///./src/lib/mtproto/serverTimeManager.ts","webpack:///./src/helpers/dom/isSwipingBackSafari.ts"],"names":["cachedPromise","set","getLanguageChangeButton","appendTo","getConfig","then","config","suggested_lang_code","lastRequestedLangCode","Promise","all","getStrings","getCacheLangPack","strings","backup","forEach","string","backupString","get","key","push","btnChangeLanguage","text","lastElementChild","classList","remove","window","requestAnimationFrame","append","addEventListener","once","e","disabled","getLangPack","fixBase64String","str","toUrl","replace","rippleClickId","ripple","elem","callback","resolve","onEnd","prepend","attachListenerTo","querySelector","add","r","document","createElement","handler","contains","drawRipple","clientX","clientY","startTime","Date","now","clickId","duration","getComputedStyle","getPropertyValue","elapsedTime","cb","mutate","delay","Math","max","setTimeout","removeEventListener","touchStartFired","rect","getBoundingClientRect","clickX","left","clickY","top","size","sqrt","abs","height","width","x","y","style","isRippleUnneeded","target","includes","tagName","touchEnd","settings","animationsEnabled","touches","length","cancelBubble","stopPropagation","passive","button","dataset","page","imageDiv","pageEl","preloader","inputWrapper","btnBack","container","parentElement","h4","helpList","li","m","default","mount","stop","QRCodeStyling","prevToken","options","ignoreErrors","iterate","isLoop","loginToken","invokeApi","api_id","id","api_hash","hash","except_ids","_","dcId","dc_id","setBaseDcId","token","authorization","setUser","user","encoded","url","documentElement","surfaceColor","trim","textColor","primaryColor","logoUrl","fetch","res","blob","Blob","type","reader","FileReader","onload","result","readAsDataURL","qrCode","devicePixelRatio","data","image","dotsOptions","color","cornersSquareOptions","imageOptions","imageSize","margin","backgroundOptions","qrOptions","errorCorrectionLevel","promise","lastChild","_drawingPromise","race","_canvas","_image","animation","c","children","display","undefined","Array","from","slice","el","timestamp","diff","expires","serverTimeOffset","err","console","warn","handled","error","func","pushToState","CLICK_EVENT_NAME","attachClickEvent","listenerSetter","bind","touchMouseDown","detachClickEvent","simulateClickEvent","className","asDiv","icon","noRipple","rippleSquare","onlyMobile","setAttribute","putPreloader","returnDiv","html","div","innerHTML","appendChild","insertAdjacentHTML","setButtonLoader","removeAttribute","onMouseMove","openedMenu","diffX","right","diffY","bottom","closeBtnMenu","onClick","menuOverlay","dispatchEvent","openedMenuOnClose","removeByType","openBtnMenu","menuElement","onClose","pushItem","onPop","canAnimate","insertBefore","positionMenu","pageX","pageY","side","scrollWidth","menuWidth","scrollHeight","menuHeight","body","windowWidth","windowHeight","isMobile","verticalSide","sides","intermediateX","intermediateY","possibleSides","_cancelContextMenuOpening","_cancelContextMenuOpeningTimeout","cancelContextMenuOpening","clearTimeout","attachContextMenuListener","element","removeManual","timeout","capture","onCancel","appNavigationController","navigations","manual","log","debug","currentHash","location","isPossibleSwipe","this","onHashChange","replaceState","state","pushState","item","pop","handleItem","onEscape","back","history","scrollRestoration","good","noBlurOnPop","i","index","ret","findItemByType","backByItem","indexOf","splice","noHistory","origin","pathname","single","bytesToHex","bytes","arr","toString","join","bytesFromHex","hexString","len","Uint8Array","ceil","start","parseInt","charAt","substr","bytesToBase64","mod3","nLen","nUint24","nIdx","String","fromCharCode","uint6ToBase64","nUint6","bytesCmp","bytes1","bytes2","bytesXor","convertToUint8Array","TextEncoder","encode","bufferConcats","args","reduce","acc","v","byteLength","tmp","lastLength","b","ArrayBuffer","bytesFromWordss","input","o","bytesToWordss","words","Uint32Array","simulateEvent","name","event","Event","bubbles","cancelable","sequentialDom","promises","raf","scheduled","kind","scheduleFlush","do","read","write","serverTimeManager","to","addTaskListener","task","payload","isSwipingBackSafari","TouchEvent"],"mappings":"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","file":"18.33a13d3129fb705afcd7.chunk.js","sourcesContent":["/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { cancelEvent } from \"../helpers/dom/cancelEvent\";\nimport { attachClickEvent } from \"../helpers/dom/clickEvent\";\nimport loadFonts from \"../helpers/dom/loadFonts\";\nimport { Config, LangPackDifference, LangPackString } from \"../layer\";\nimport I18n, { LangPackKey } from \"../lib/langPack\";\nimport apiManager from \"../lib/mtproto/mtprotoworker\";\nimport rootScope from \"../lib/rootScope\";\nimport Button from \"./button\";\nimport { putPreloader } from \"./misc\";\n\nlet set = false;\n\nfunction getLang(): Promise<[Config.config, LangPackString[], LangPackDifference.langPackDifference]> {\n if(cachedPromise) return cachedPromise;\n return cachedPromise = apiManager.getConfig().then(config => {\n if(config.suggested_lang_code !== I18n.lastRequestedLangCode) {\n //I18n.loadLangPack(config.suggested_lang_code);\n\n return Promise.all([\n config,\n I18n.getStrings(config.suggested_lang_code, ['Login.ContinueOnLanguage']),\n I18n.getCacheLangPack()\n ]);\n } else {\n return [] as any;\n }\n });\n}\n\nlet cachedPromise: ReturnType<typeof getLang>;\n\nexport default function getLanguageChangeButton(appendTo: HTMLElement) {\n if(set) return;\n getLang().then(([config, strings]) => {\n if(!config) {\n return;\n }\n\n const backup: LangPackString[] = [];\n strings.forEach(string => {\n const backupString = I18n.strings.get(string.key as LangPackKey);\n if(!backupString) {\n return;\n }\n \n backup.push(backupString);\n I18n.strings.set(string.key as LangPackKey, string);\n });\n\n const btnChangeLanguage = Button('btn-primary btn-secondary btn-primary-transparent primary', {text: 'Login.ContinueOnLanguage'});\n btnChangeLanguage.lastElementChild.classList.remove('i18n'); // prevent changing language\n loadFonts().then(() => {\n window.requestAnimationFrame(() => {\n appendTo.append(btnChangeLanguage);\n });\n });\n\n rootScope.addEventListener('language_change', () => {\n btnChangeLanguage.remove();\n }, {once: true});\n\n backup.forEach(string => {\n I18n.strings.set(string.key as LangPackKey, string);\n });\n \n attachClickEvent(btnChangeLanguage, (e) => {\n cancelEvent(e);\n\n set = true;\n\n btnChangeLanguage.disabled = true;\n putPreloader(btnChangeLanguage);\n\n I18n.getLangPack(config.suggested_lang_code);\n });\n });\n}\n","export default function fixBase64String(str: string, toUrl: boolean) {\n if(toUrl) {\n return str.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/\\=+$/, '');\n } else {\n return str.replace(/-/g, '+').replace(/_/g, '/');\n }\n}\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nimport findUpClassName from \"../helpers/dom/findUpClassName\";\r\nimport sequentialDom from \"../helpers/sequentialDom\";\r\nimport {IS_TOUCH_SUPPORTED} from \"../environment/touchSupport\";\r\nimport rootScope from \"../lib/rootScope\";\r\nimport findUpAsChild from \"../helpers/dom/findUpAsChild\";\r\n\r\nlet rippleClickId = 0;\r\nexport function ripple(\r\n elem: HTMLElement, \r\n callback: (id: number) => Promise<boolean | void> = () => Promise.resolve(), \r\n onEnd: (id: number) => void = null, \r\n prepend = false,\r\n attachListenerTo = elem\r\n) {\r\n //return;\r\n if(elem.querySelector('.c-ripple')) return;\r\n elem.classList.add('rp');\r\n \r\n let r = document.createElement('div');\r\n r.classList.add('c-ripple');\r\n\r\n const isSquare = elem.classList.contains('rp-square');\r\n if(isSquare) {\r\n r.classList.add('is-square');\r\n }\r\n\r\n elem[prepend ? 'prepend' : 'append'](r);\r\n\r\n let handler: () => void;\r\n //let animationEndPromise: Promise<number>;\r\n const drawRipple = (clientX: number, clientY: number) => {\r\n const startTime = Date.now();\r\n const elem = document.createElement('div');\r\n\r\n const clickId = rippleClickId++;\r\n \r\n //console.log('ripple drawRipple');\r\n \r\n const duration = +window.getComputedStyle(r).getPropertyValue('--ripple-duration').replace('s', '') * 1000;\r\n //console.log('ripple duration', duration);\r\n\r\n handler = () => {\r\n //handler = () => animationEndPromise.then((duration) => {\r\n //console.log('ripple animation was:', duration);\r\n\r\n //const duration = isSquare || mediaSizes.isMobile ? 200 : 700;\r\n //return;\r\n let elapsedTime = Date.now() - startTime;\r\n const cb = () => {\r\n //console.log('ripple elapsedTime total pre-remove:', Date.now() - startTime);\r\n sequentialDom.mutate(() => {\r\n elem.remove();\r\n });\r\n \r\n if(onEnd) onEnd(clickId);\r\n };\r\n if(elapsedTime < duration) {\r\n let delay = Math.max(duration - elapsedTime, duration / 2);\r\n setTimeout(() => elem.classList.add('hiding'), Math.max(delay - duration / 2, 0));\r\n\r\n setTimeout(cb, delay);\r\n } else {\r\n elem.classList.add('hiding');\r\n setTimeout(cb, duration / 2);\r\n }\r\n\r\n if(!IS_TOUCH_SUPPORTED) {\r\n window.removeEventListener('contextmenu', handler);\r\n }\r\n\r\n handler = null;\r\n touchStartFired = false;\r\n };\r\n //});\r\n\r\n callback && callback(clickId);\r\n\r\n /* callback().then((bad) => {\r\n if(bad) {\r\n span.remove();\r\n return;\r\n } */\r\n \r\n //console.log('ripple after promise', Date.now() - startTime);\r\n //console.log('ripple tooSlow:', tooSlow);\r\n /* if(tooSlow) {\r\n span.remove();\r\n return;\r\n } */\r\n\r\n window.requestAnimationFrame(() => {\r\n const rect = r.getBoundingClientRect();\r\n elem.classList.add('c-ripple__circle');\r\n\r\n const clickX = clientX - rect.left;\r\n const clickY = clientY - rect.top;\r\n\r\n const radius = Math.sqrt((Math.abs(clickY - rect.height / 2) + rect.height / 2) ** 2 + (Math.abs(clickX - rect.width / 2) + rect.width / 2) ** 2);\r\n const size = radius;\r\n\r\n // center of circle\r\n const x = clickX - size / 2;\r\n const y = clickY - size / 2;\r\n\r\n //console.log('ripple click', offsetFromCenter, size, clickX, clickY);\r\n\r\n elem.style.width = elem.style.height = size + 'px';\r\n elem.style.left = x + 'px';\r\n elem.style.top = y + 'px';\r\n\r\n // нижний код выполняется с задержкой\r\n /* animationEndPromise = new Promise((resolve) => {\r\n span.addEventListener('animationend', () => {\r\n // 713 -> 700\r\n resolve(((Date.now() - startTime) / 100 | 0) * 100);\r\n }, {once: true});\r\n }); */\r\n \r\n // нижний код не всегда включает анимацию ПРИ КЛИКЕ НА ТАЧПАД БЕЗ ТАПТИК ЭНЖИНА\r\n /* span.style.display = 'none';\r\n r.append(span);\r\n duration = +window.getComputedStyle(span).getPropertyValue('animation-duration').replace('s', '') * 1000;\r\n span.style.display = ''; */\r\n\r\n r.append(elem);\r\n\r\n //r.classList.add('active');\r\n //handler();\r\n });\r\n //});\r\n };\r\n\r\n const isRippleUnneeded = (e: Event) => e.target !== elem && (\r\n ['BUTTON', 'A'].includes((e.target as HTMLElement).tagName) \r\n || findUpClassName(e.target as HTMLElement, 'c-ripple') !== r\r\n ) && (\r\n attachListenerTo === elem \r\n || !findUpAsChild(e.target, attachListenerTo)\r\n );\r\n\r\n // TODO: rename this variable\r\n let touchStartFired = false;\r\n if(IS_TOUCH_SUPPORTED) {\r\n let touchEnd = () => {\r\n handler && handler();\r\n };\r\n \r\n attachListenerTo.addEventListener('touchstart', (e) => {\r\n if(!rootScope.settings.animationsEnabled) {\r\n return;\r\n }\r\n\r\n //console.log('ripple touchstart', e);\r\n if(e.touches.length > 1 || touchStartFired || isRippleUnneeded(e)) {\r\n return;\r\n }\r\n \r\n //console.log('touchstart', e);\r\n touchStartFired = true;\r\n \r\n let {clientX, clientY} = e.touches[0];\r\n drawRipple(clientX, clientY);\r\n attachListenerTo.addEventListener('touchend', touchEnd, {once: true});\r\n \r\n window.addEventListener('touchmove', (e) => {\r\n e.cancelBubble = true;\r\n e.stopPropagation();\r\n touchEnd();\r\n attachListenerTo.removeEventListener('touchend', touchEnd);\r\n }, {once: true});\r\n }, {passive: true});\r\n } else {\r\n attachListenerTo.addEventListener('mousedown', (e) => {\r\n if(![0, 2].includes(e.button)) { // only left and right buttons\r\n return;\r\n }\r\n\r\n if(!rootScope.settings.animationsEnabled) {\r\n return;\r\n }\r\n //console.log('ripple mousedown', e, e.target, findUpClassName(e.target as HTMLElement, 'c-ripple') === r);\r\n\r\n if(attachListenerTo.dataset.ripple === '0' || isRippleUnneeded(e)) {\r\n return;\r\n } else if(touchStartFired) {\r\n touchStartFired = false;\r\n return;\r\n }\r\n \r\n let {clientX, clientY} = e;\r\n drawRipple(clientX, clientY);\r\n window.addEventListener('mouseup', handler, {once: true, passive: true});\r\n window.addEventListener('contextmenu', handler, {once: true, passive: true});\r\n }, {passive: true});\r\n }\r\n}\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nimport type { DcId } from '../types';\r\nimport type { ApiError } from '../lib/mtproto/apiManager';\r\nimport apiManager from '../lib/mtproto/mtprotoworker';\r\nimport Page from './page';\r\nimport serverTimeManager from '../lib/mtproto/serverTimeManager';\r\nimport { AuthAuthorization, AuthLoginToken } from '../layer';\r\nimport { bytesCmp, bytesToBase64 } from '../helpers/bytes';\r\nimport App from '../config/app';\r\nimport Button from '../components/button';\r\nimport { _i18n, i18n, LangPackKey } from '../lib/langPack';\r\nimport appStateManager from '../lib/appManagers/appStateManager';\r\nimport rootScope from '../lib/rootScope';\r\nimport { putPreloader } from '../components/misc';\r\nimport getLanguageChangeButton from '../components/languageChangeButton';\r\nimport { pause } from '../helpers/schedulers/pause';\r\nimport fixBase64String from '../helpers/fixBase64String';\r\n\r\nconst FETCH_INTERVAL = 3;\r\n\r\nlet onFirstMount = async() => {\r\n const pageElement = page.pageEl;\r\n const imageDiv = pageElement.querySelector('.auth-image') as HTMLDivElement;\r\n\r\n let preloader = putPreloader(imageDiv, true);\r\n\r\n const inputWrapper = document.createElement('div');\r\n inputWrapper.classList.add('input-wrapper');\r\n\r\n const btnBack = Button('btn-primary btn-secondary btn-primary-transparent primary', {text: 'Login.QR.Cancel'});\r\n inputWrapper.append(btnBack);\r\n\r\n getLanguageChangeButton(inputWrapper);\r\n\r\n const container = imageDiv.parentElement;\r\n\r\n const h4 = document.createElement('h4');\r\n _i18n(h4, 'Login.QR.Title');\r\n\r\n const helpList = document.createElement('ol');\r\n helpList.classList.add('qr-description');\r\n (['Login.QR.Help1', 'Login.QR.Help2', 'Login.QR.Help3'] as LangPackKey[]).forEach((key) => {\r\n const li = document.createElement('li');\r\n li.append(i18n(key));\r\n helpList.append(li);\r\n });\r\n\r\n container.append(h4, helpList, inputWrapper);\r\n\r\n btnBack.addEventListener('click', () => {\r\n import('./pageSignIn').then(m => m.default.mount());\r\n stop = true;\r\n });\r\n \r\n const results = await Promise.all([\r\n import('qr-code-styling' as any)\r\n ]);\r\n const QRCodeStyling = results[0].default;\r\n\r\n let stop = false;\r\n rootScope.addEventListener('user_auth', () => {\r\n stop = true;\r\n cachedPromise = null;\r\n }, {once: true});\r\n \r\n let options: {dcId?: DcId, ignoreErrors: true} = {ignoreErrors: true};\r\n let prevToken: Uint8Array | number[];\r\n\r\n const iterate = async(isLoop: boolean) => {\r\n try {\r\n let loginToken = await apiManager.invokeApi('auth.exportLoginToken', {\r\n api_id: App.id,\r\n api_hash: App.hash,\r\n except_ids: []\r\n }, {ignoreErrors: true});\r\n \r\n if(loginToken._ === 'auth.loginTokenMigrateTo') {\r\n if(!options.dcId) {\r\n options.dcId = loginToken.dc_id as DcId;\r\n apiManager.setBaseDcId(loginToken.dc_id);\r\n //continue;\r\n }\r\n \r\n loginToken = await apiManager.invokeApi('auth.importLoginToken', {\r\n token: loginToken.token\r\n }, options) as AuthLoginToken.authLoginToken;\r\n }\r\n\r\n if(loginToken._ === 'auth.loginTokenSuccess') {\r\n const authorization = loginToken.authorization as any as AuthAuthorization.authAuthorization;\r\n apiManager.setUser(authorization.user);\r\n import('./pageIm').then(m => m.default.mount());\r\n return true;\r\n }\r\n\r\n /* // to base64\r\n var decoder = new TextDecoder('utf8');\r\n var b64encoded = btoa(String.fromCharCode.apply(null, [...loginToken.token])); */\r\n\r\n if(!prevToken || !bytesCmp(prevToken, loginToken.token)) {\r\n prevToken = loginToken.token;\r\n\r\n let encoded = bytesToBase64(loginToken.token);\r\n let url = \"tg://login?token=\" + fixBase64String(encoded, true);\r\n\r\n const style = window.getComputedStyle(document.documentElement);\r\n const surfaceColor = style.getPropertyValue('--surface-color').trim();\r\n const textColor = style.getPropertyValue('--primary-text-color').trim();\r\n const primaryColor = style.getPropertyValue('--primary-color').trim();\r\n\r\n const logoUrl = await fetch('assets/img/logo_padded.svg')\r\n .then(res => res.text())\r\n .then(text => {\r\n text = text.replace(/(fill:).+?(;)/, `$1${primaryColor}$2`);\r\n const blob = new Blob([text], {type: 'image/svg+xml;charset=utf-8'});\r\n\r\n // * because iOS Safari doesn't want to eat objectURL\r\n return new Promise<string>((resolve) => {\r\n const reader = new FileReader();\r\n reader.onload = (e) => {\r\n resolve(e.target.result as string);\r\n };\r\n reader.readAsDataURL(blob);\r\n });\r\n //return URL.createObjectURL(blob);\r\n });\r\n\r\n const qrCode = new QRCodeStyling({\r\n width: 240 * window.devicePixelRatio,\r\n height: 240 * window.devicePixelRatio,\r\n data: url,\r\n image: logoUrl,\r\n dotsOptions: {\r\n color: textColor,\r\n type: 'rounded'\r\n },\r\n cornersSquareOptions: {\r\n type: 'extra-rounded'\r\n },\r\n imageOptions: {\r\n imageSize: 1,\r\n margin: 0\r\n },\r\n backgroundOptions: {\r\n color: surfaceColor\r\n },\r\n qrOptions: {\r\n errorCorrectionLevel: \"L\"\r\n }\r\n });\r\n\r\n qrCode.append(imageDiv);\r\n (imageDiv.lastChild as HTMLCanvasElement).classList.add('qr-canvas');\r\n\r\n let promise: Promise<void>;\r\n if(qrCode._drawingPromise) {\r\n promise = qrCode._drawingPromise;\r\n } else {\r\n promise = Promise.race([\r\n pause(1000),\r\n new Promise<void>((resolve) => {\r\n qrCode._canvas._image.addEventListener('load', () => {\r\n window.requestAnimationFrame(() => resolve());\r\n }, {once: true});\r\n })\r\n ]);\r\n }\r\n\r\n // * это костыль, но библиотека не предоставляет никаких событий\r\n await promise.then(() => {\r\n if(preloader) {\r\n preloader.style.animation = 'hide-icon .4s forwards';\r\n\r\n const c = imageDiv.children[1] as HTMLElement;\r\n c.style.display = 'none';\r\n c.style.animation = 'grow-icon .4s forwards';\r\n setTimeout(() => {\r\n c.style.display = '';\r\n }, 150);\r\n\r\n setTimeout(() => {\r\n c.style.animation = '';\r\n }, 500);\r\n preloader = undefined;\r\n } else {\r\n Array.from(imageDiv.children).slice(0, -1).forEach(el => {\r\n el.remove();\r\n });\r\n }\r\n });\r\n }\r\n\r\n if(isLoop) {\r\n let timestamp = Date.now() / 1000;\r\n let diff = loginToken.expires - timestamp - serverTimeManager.serverTimeOffset;\r\n \r\n await pause(diff > FETCH_INTERVAL ? 1e3 * FETCH_INTERVAL : 1e3 * diff | 0);\r\n }\r\n } catch(err) {\r\n switch((err as ApiError).type) {\r\n case 'SESSION_PASSWORD_NEEDED':\r\n console.warn('pageSignQR: SESSION_PASSWORD_NEEDED');\r\n (err as ApiError).handled = true;\r\n import('./pagePassword').then(m => m.default.mount());\r\n stop = true;\r\n cachedPromise = null;\r\n break;\r\n default:\r\n console.error('pageSignQR: default error:', err);\r\n stop = true;\r\n break;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n return false;\r\n };\r\n\r\n //await iterate(false);\r\n\r\n return async() => {\r\n stop = false;\r\n\r\n do {\r\n if(stop) {\r\n break;\r\n }\r\n \r\n const needBreak = await iterate(true);\r\n if(needBreak) {\r\n break;\r\n }\r\n } while(true);\r\n };\r\n};\r\n\r\nlet cachedPromise: Promise<() => Promise<void>>;\r\nconst page = new Page('page-signQR', true, () => {\r\n return cachedPromise;\r\n}, () => {\r\n //console.log('onMount');\r\n if(!cachedPromise) cachedPromise = onFirstMount();\r\n cachedPromise.then(func => {\r\n func();\r\n });\r\n\r\n appStateManager.pushToState('authState', {_: 'authStateSignQr'});\r\n});\r\n\r\nexport default page;\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nimport type ListenerSetter from \"../listenerSetter\";\r\nimport { IS_TOUCH_SUPPORTED } from \"../../environment/touchSupport\";\r\nimport simulateEvent from \"./dispatchEvent\";\r\n\r\nexport const CLICK_EVENT_NAME: 'mousedown' /* | 'touchend' */ | 'click' = (IS_TOUCH_SUPPORTED ? 'mousedown' : 'click') as any;\r\nexport type AttachClickOptions = AddEventListenerOptions & Partial<{listenerSetter: ListenerSetter, touchMouseDown: true}>;\r\nexport function attachClickEvent(elem: HTMLElement | Window, callback: (e: /* TouchEvent | */MouseEvent) => void, options: AttachClickOptions = {}) {\r\n const add = options.listenerSetter ? options.listenerSetter.add(elem) : elem.addEventListener.bind(elem);\r\n // const remove = options.listenerSetter ? options.listenerSetter.removeManual.bind(options.listenerSetter, elem) : elem.removeEventListener.bind(elem);\r\n\r\n options.touchMouseDown = true;\r\n /* if(options.touchMouseDown && CLICK_EVENT_NAME === 'touchend') {\r\n add('mousedown', callback, options);\r\n } else if(CLICK_EVENT_NAME === 'touchend') {\r\n const o = {...options, once: true};\r\n\r\n const onTouchStart = (e: TouchEvent) => {\r\n const onTouchMove = (e: TouchEvent) => {\r\n remove('touchmove', onTouchMove, o);\r\n remove('touchend', onTouchEnd, o);\r\n };\r\n \r\n const onTouchEnd = (e: TouchEvent) => {\r\n remove('touchmove', onTouchMove, o);\r\n callback(e);\r\n if(options.once) {\r\n remove('touchstart', onTouchStart);\r\n }\r\n };\r\n \r\n add('touchend', onTouchEnd, o);\r\n add('touchmove', onTouchMove, o);\r\n };\r\n\r\n add('touchstart', onTouchStart);\r\n } else {\r\n add(CLICK_EVENT_NAME, callback, options);\r\n } */\r\n add(CLICK_EVENT_NAME, callback, options);\r\n}\r\n\r\nexport function detachClickEvent(elem: HTMLElement, callback: (e: TouchEvent | MouseEvent) => void, options?: AddEventListenerOptions) {\r\n // if(CLICK_EVENT_NAME === 'touchend') {\r\n // elem.removeEventListener('touchstart', callback, options);\r\n // } else {\r\n elem.removeEventListener(CLICK_EVENT_NAME, callback, options);\r\n // }\r\n}\r\n\r\nexport function simulateClickEvent(elem: HTMLElement) {\r\n simulateEvent(elem, CLICK_EVENT_NAME);\r\n}\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nimport { i18n, LangPackKey } from \"../lib/langPack\";\r\nimport { ripple } from \"./ripple\";\r\n\r\nexport type ButtonOptions = Partial<{\r\n noRipple: true, \r\n onlyMobile: true, \r\n icon: string, \r\n rippleSquare: true, \r\n text: LangPackKey, \r\n disabled: boolean,\r\n asDiv: boolean\r\n}>;\r\n\r\nconst Button = (className: string, options: ButtonOptions = {}) => {\r\n const button: HTMLButtonElement = document.createElement(options.asDiv ? 'div' : 'button') as any;\r\n button.className = className + (options.icon ? ' tgico-' + options.icon : '');\r\n\r\n if(!options.noRipple) {\r\n if(options.rippleSquare) {\r\n button.classList.add('rp-square');\r\n }\r\n\r\n ripple(button);\r\n }\r\n\r\n if(options.onlyMobile) {\r\n button.classList.add('only-handhelds');\r\n }\r\n\r\n if(options.disabled) {\r\n button.setAttribute('disabled', 'true');\r\n }\r\n\r\n if(options.text) {\r\n button.append(i18n(options.text));\r\n }\r\n\r\n return button;\r\n};\r\n\r\nexport default Button;\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nimport { MOUNT_CLASS_TO } from \"../config/debug\";\r\nimport { cancelEvent } from \"../helpers/dom/cancelEvent\";\r\nimport { CLICK_EVENT_NAME } from \"../helpers/dom/clickEvent\";\r\nimport ListenerSetter from \"../helpers/listenerSetter\";\r\nimport mediaSizes from \"../helpers/mediaSizes\";\r\nimport { IS_TOUCH_SUPPORTED } from \"../environment/touchSupport\";\r\nimport { IS_APPLE, IS_MOBILE_SAFARI } from \"../environment/userAgent\";\r\nimport rootScope from \"../lib/rootScope\";\r\nimport appNavigationController from \"./appNavigationController\";\r\n\r\nexport function putPreloader(elem: Element, returnDiv = false): HTMLElement {\r\n const html = `\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"preloader-circular\" viewBox=\"25 25 50 50\">\r\n <circle class=\"preloader-path\" cx=\"50\" cy=\"50\" r=\"20\" fill=\"none\" stroke-miterlimit=\"10\"/>\r\n </svg>`;\r\n\r\n if(returnDiv) {\r\n const div = document.createElement('div');\r\n div.classList.add('preloader');\r\n div.innerHTML = html;\r\n\r\n if(elem) {\r\n elem.appendChild(div);\r\n }\r\n\r\n return div;\r\n }\r\n \r\n elem.insertAdjacentHTML('beforeend', html);\r\n return elem.lastElementChild as HTMLElement;\r\n}\r\n\r\nMOUNT_CLASS_TO.putPreloader = putPreloader;\r\n\r\nexport function setButtonLoader(elem: HTMLButtonElement, icon = 'check') {\r\n elem.classList.remove('tgico-' + icon);\r\n elem.disabled = true;\r\n putPreloader(elem);\r\n\r\n return () => {\r\n elem.innerHTML = '';\r\n elem.classList.add('tgico-' + icon);\r\n elem.removeAttribute('disabled');\r\n };\r\n}\r\n\r\n/* export function parseMenuButtonsTo(to: {[name: string]: HTMLElement}, elements: HTMLCollection | NodeListOf<HTMLElement>) {\r\n Array.from(elements).forEach(el => {\r\n const match = el.className.match(/(?:^|\\s)menu-(.+?)(?:$|\\s)/);\r\n if(!match) return;\r\n to[match[1]] = el as HTMLElement;\r\n });\r\n} */\r\n\r\nlet onMouseMove = (e: MouseEvent) => {\r\n let rect = openedMenu.getBoundingClientRect();\r\n let {clientX, clientY} = e;\r\n \r\n let diffX = clientX >= rect.right ? clientX - rect.right : rect.left - clientX;\r\n let diffY = clientY >= rect.bottom ? clientY - rect.bottom : rect.top - clientY;\r\n \r\n if(diffX >= 100 || diffY >= 100) {\r\n closeBtnMenu();\r\n //openedMenu.parentElement.click();\r\n }\r\n //console.log('mousemove', diffX, diffY);\r\n};\r\n\r\nconst onClick = (e: MouseEvent | TouchEvent) => {\r\n //cancelEvent(e);\r\n closeBtnMenu();\r\n};\r\n\r\n// ! no need in this due to the same handler in appNavigationController\r\n/* const onKeyDown = (e: KeyboardEvent) => {\r\n if(e.key === 'Escape') {\r\n closeBtnMenu();\r\n cancelEvent(e);\r\n }\r\n}; */\r\n\r\nexport const closeBtnMenu = () => {\r\n if(openedMenu) {\r\n openedMenu.classList.remove('active');\r\n openedMenu.parentElement.classList.remove('menu-open');\r\n //openedMenu.previousElementSibling.remove(); // remove overlay\r\n if(menuOverlay) menuOverlay.remove();\r\n openedMenu = null;\r\n\r\n rootScope.dispatchEvent('context_menu_toggle', false);\r\n }\r\n \r\n if(openedMenuOnClose) {\r\n openedMenuOnClose();\r\n openedMenuOnClose = null;\r\n }\r\n\r\n if(!IS_TOUCH_SUPPORTED) {\r\n window.removeEventListener('mousemove', onMouseMove);\r\n //window.removeEventListener('keydown', onKeyDown, {capture: true});\r\n window.removeEventListener('contextmenu', onClick);\r\n }\r\n\r\n document.removeEventListener(CLICK_EVENT_NAME, onClick);\r\n\r\n if(!IS_MOBILE_SAFARI) {\r\n appNavigationController.removeByType('menu');\r\n }\r\n};\r\n\r\nwindow.addEventListener('resize', () => {\r\n if(openedMenu) {\r\n closeBtnMenu();\r\n }\r\n \r\n /* if(openedMenu && (openedMenu.style.top || openedMenu.style.left)) {\r\n const rect = openedMenu.getBoundingClientRect();\r\n const {innerWidth, innerHeight} = window;\r\n\r\n console.log(innerWidth, innerHeight, rect);\r\n } */\r\n});\r\n\r\nlet openedMenu: HTMLElement = null, openedMenuOnClose: () => void = null, menuOverlay: HTMLElement = null;\r\nexport function openBtnMenu(menuElement: HTMLElement, onClose?: () => void) {\r\n closeBtnMenu();\r\n\r\n if(!IS_MOBILE_SAFARI) {\r\n appNavigationController.pushItem({\r\n type: 'menu',\r\n onPop: (canAnimate) => {\r\n closeBtnMenu();\r\n }\r\n });\r\n }\r\n \r\n openedMenu = menuElement;\r\n openedMenu.classList.add('active');\r\n openedMenu.parentElement.classList.add('menu-open');\r\n\r\n if(!menuOverlay) {\r\n menuOverlay = document.createElement('div');\r\n menuOverlay.classList.add('btn-menu-overlay');\r\n\r\n // ! because this event must be canceled, and can't cancel on menu click (below)\r\n menuOverlay.addEventListener(CLICK_EVENT_NAME, (e) => {\r\n cancelEvent(e);\r\n onClick(e);\r\n });\r\n }\r\n\r\n openedMenu.parentElement.insertBefore(menuOverlay, openedMenu);\r\n\r\n //document.body.classList.add('disable-hover');\r\n \r\n openedMenuOnClose = onClose;\r\n\r\n if(!IS_TOUCH_SUPPORTED) {\r\n window.addEventListener('mousemove', onMouseMove);\r\n //window.addEventListener('keydown', onKeyDown, {capture: true});\r\n window.addEventListener('contextmenu', onClick, {once: true});\r\n }\r\n\r\n /* // ! because this event must be canceled, and can't cancel on menu click (below)\r\n overlay.addEventListener(CLICK_EVENT_NAME, (e) => {\r\n cancelEvent(e);\r\n onClick(e);\r\n }); */\r\n \r\n // ! safari iOS doesn't handle window click event on overlay, idk why\r\n document.addEventListener(CLICK_EVENT_NAME, onClick);\r\n\r\n rootScope.dispatchEvent('context_menu_toggle', true);\r\n}\r\n\r\nconst PADDING_TOP = 8;\r\nconst PADDING_LEFT = 8;\r\nexport function positionMenu({pageX, pageY}: MouseEvent | Touch, elem: HTMLElement, side?: 'left' | 'right' | 'center') {\r\n //let {clientX, clientY} = e;\r\n\r\n // * side mean the OPEN side\r\n\r\n let {scrollWidth: menuWidth, scrollHeight: menuHeight} = elem;\r\n //let {innerWidth: windowWidth, innerHeight: windowHeight} = window;\r\n const rect = document.body.getBoundingClientRect();\r\n const windowWidth = rect.width;\r\n const windowHeight = rect.height;\r\n\r\n side = mediaSizes.isMobile ? 'right' : 'left';\r\n let verticalSide: 'top' /* | 'bottom' */ | 'center' = 'top';\r\n\r\n const getSides = () => {\r\n return {\r\n x: {\r\n left: pageX,\r\n right: pageX - menuWidth\r\n },\r\n intermediateX: side === 'right' ? PADDING_LEFT : windowWidth - menuWidth - PADDING_LEFT,\r\n //intermediateX: clientX < windowWidth / 2 ? PADDING_LEFT : windowWidth - menuWidth - PADDING_LEFT,\r\n y: {\r\n top: pageY,\r\n bottom: pageY - menuHeight\r\n },\r\n //intermediateY: verticalSide === 'top' ? PADDING_TOP : windowHeight - menuHeight - PADDING_TOP,\r\n intermediateY: pageY < windowHeight / 2 ? PADDING_TOP : windowHeight - menuHeight - PADDING_TOP,\r\n };\r\n };\r\n\r\n const sides = getSides();\r\n\r\n const possibleSides = {\r\n x: {\r\n left: sides.x.left + menuWidth + PADDING_LEFT <= windowWidth,\r\n right: sides.x.right >= PADDING_LEFT\r\n },\r\n y: {\r\n top: sides.y.top + menuHeight + PADDING_TOP <= windowHeight,\r\n bottom: sides.y.bottom - PADDING_TOP >= PADDING_TOP\r\n }\r\n };\r\n\r\n /* if(side === undefined) {\r\n if((clientX + menuWidth + PADDING_LEFT) > windowWidth) {\r\n side = 'right';\r\n }\r\n } */\r\n\r\n {\r\n /* const x = sides.x;\r\n\r\n const s = Object.keys(x) as (keyof typeof possibleSides.x)[];\r\n if(side) {\r\n s.findAndSplice(s => s === side);\r\n s.unshift(side);\r\n }\r\n\r\n const possibleSide = s.find(s => possibleSides.x[s]); */\r\n let left: number;\r\n /* if(possibleSide) {\r\n left = x[possibleSide];\r\n side = possibleSide;\r\n } else {\r\n left = sides.intermediateX;\r\n side = undefined;\r\n } */\r\n left = possibleSides.x[side] ? sides.x[side] : (side = 'center', sides.intermediateX);\r\n \r\n elem.style.left = left + 'px';\r\n }\r\n\r\n /* if((clientY + menuHeight + PADDING_TOP) > windowHeight) {\r\n elem.style.top = clamp(clientY - menuHeight, PADDING_TOP, windowHeight - menuHeight - PADDING_TOP) + 'px';\r\n // elem.style.top = (innerHeight - scrollHeight - PADDING_TOP) + 'px';\r\n verticalSide = 'bottom';\r\n } else {\r\n elem.style.top = Math.max(PADDING_TOP, clientY) + 'px';\r\n verticalSide = 'top';\r\n } */\r\n\r\n {\r\n let top: number;\r\n\r\n top = possibleSides.y[verticalSide] ? sides.y[verticalSide] : (verticalSide = 'center', sides.intermediateY);\r\n \r\n elem.style.top = top + 'px';\r\n }\r\n \r\n elem.className = elem.className.replace(/(top|center|bottom)-(left|center|right)/g, '');\r\n elem.classList.add(\r\n //(verticalSide === 'center' ? verticalSide : (verticalSide === 'bottom' ? 'top' : 'bottom')) +\r\n (verticalSide === 'center' ? verticalSide : 'bottom') +\r\n '-' +\r\n (side === 'center' ? side : (side === 'left' ? 'right' : 'left')));\r\n}\r\n\r\nlet _cancelContextMenuOpening = false, _cancelContextMenuOpeningTimeout = 0;\r\nexport function cancelContextMenuOpening() {\r\n if(_cancelContextMenuOpeningTimeout) {\r\n clearTimeout(_cancelContextMenuOpeningTimeout);\r\n }\r\n \r\n _cancelContextMenuOpeningTimeout = window.setTimeout(() => {\r\n _cancelContextMenuOpeningTimeout = 0;\r\n _cancelContextMenuOpening = false;\r\n }, .4e3);\r\n\r\n _cancelContextMenuOpening = true;\r\n}\r\n\r\nexport function attachContextMenuListener(element: HTMLElement, callback: (e: Touch | MouseEvent) => void, listenerSetter?: ListenerSetter) {\r\n const add = listenerSetter ? listenerSetter.add(element) : element.addEventListener.bind(element);\r\n const remove = listenerSetter ? listenerSetter.removeManual.bind(listenerSetter, element) : element.removeEventListener.bind(element);\r\n\r\n if(IS_APPLE && IS_TOUCH_SUPPORTED) {\r\n let timeout: number;\r\n\r\n const options: EventListenerOptions = {capture: true};\r\n\r\n const onCancel = () => {\r\n clearTimeout(timeout);\r\n // @ts-ignore\r\n remove('touchmove', onCancel, options);\r\n // @ts-ignore\r\n remove('touchend', onCancel, options);\r\n // @ts-ignore\r\n remove('touchcancel', onCancel, options);\r\n };\r\n\r\n add('touchstart', (e: TouchEvent) => {\r\n if(e.touches.length > 1) {\r\n onCancel();\r\n return;\r\n }\r\n \r\n add('touchmove', onCancel, options);\r\n add('touchend', onCancel, options);\r\n add('touchcancel', onCancel, options);\r\n\r\n timeout = window.setTimeout(() => {\r\n if(_cancelContextMenuOpening) {\r\n onCancel();\r\n return;\r\n }\r\n\r\n callback(e.touches[0]);\r\n onCancel();\r\n\r\n if(openedMenu) {\r\n element.addEventListener('touchend', cancelEvent, {once: true}); // * fix instant closing\r\n }\r\n }, .4e3);\r\n });\r\n\r\n /* if(!isSafari) {\r\n add('contextmenu', (e: any) => {\r\n cancelEvent(e);\r\n }, {passive: false, capture: true});\r\n } */\r\n } else {\r\n add('contextmenu', IS_TOUCH_SUPPORTED ? (e: any) => {\r\n callback(e);\r\n\r\n if(openedMenu) {\r\n element.addEventListener('touchend', cancelEvent, {once: true}); // * fix instant closing\r\n }\r\n } : callback);\r\n }\r\n};\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nimport { MOUNT_CLASS_TO } from \"../config/debug\";\r\nimport { IS_MOBILE_SAFARI } from \"../environment/userAgent\";\r\nimport { logger } from \"../lib/logger\";\r\nimport { doubleRaf } from \"../helpers/schedulers\";\r\nimport blurActiveElement from \"../helpers/dom/blurActiveElement\";\r\nimport { cancelEvent } from \"../helpers/dom/cancelEvent\";\r\nimport { indexOfAndSplice } from \"../helpers/array\";\r\nimport isSwipingBackSafari from \"../helpers/dom/isSwipingBackSafari\";\r\n\r\nexport type NavigationItem = {\r\n type: 'left' | 'right' | 'im' | 'chat' | 'popup' | 'media' | 'menu' | \r\n 'esg' | 'multiselect' | 'input-helper' | 'autocomplete-helper' | 'markup' | \r\n 'global-search' | 'voice' | 'mobile-search',\r\n onPop: (canAnimate: boolean) => boolean | void,\r\n onEscape?: () => boolean,\r\n noHistory?: boolean,\r\n noBlurOnPop?: boolean,\r\n};\r\n\r\nexport class AppNavigationController {\r\n private navigations: Array<NavigationItem> = [];\r\n private id = Date.now();\r\n private manual = false;\r\n private log = logger('NC');\r\n private debug = true;\r\n private currentHash = window.location.hash;\r\n public onHashChange: () => void;\r\n\r\n constructor() {\r\n let isPossibleSwipe = false;\r\n window.addEventListener('popstate', (e) => {\r\n this.debug && this.log('popstate', e, isPossibleSwipe);\r\n\r\n if(window.location.hash !== this.currentHash) {\r\n this.onHashChange && this.onHashChange();\r\n this.replaceState();\r\n return;\r\n }\r\n this.currentHash = window.location.hash;\r\n\r\n const id: number = e.state;\r\n if(id !== this.id/* && !this.navigations.length */) {\r\n this.pushState();\r\n return;\r\n }\r\n\r\n const item = this.navigations.pop();\r\n if(!item) {\r\n this.pushState();\r\n return;\r\n }\r\n\r\n this.manual = !isPossibleSwipe;\r\n this.handleItem(item);\r\n //this.pushState(); // * prevent adding forward arrow\r\n });\r\n\r\n window.addEventListener('keydown', (e) => {\r\n const item = this.navigations[this.navigations.length - 1];\r\n if(!item) return;\r\n if(e.key === 'Escape' && (item.onEscape ? item.onEscape() : true)) {\r\n cancelEvent(e);\r\n this.back(item.type);\r\n }\r\n }, {capture: true, passive: false});\r\n\r\n if(IS_MOBILE_SAFARI) {\r\n const options = {passive: true};\r\n window.addEventListener('touchstart', (e) => {\r\n if(e.touches.length > 1) return;\r\n this.debug && this.log('touchstart');\r\n\r\n if(isSwipingBackSafari(e)) {\r\n isPossibleSwipe = true;\r\n\r\n window.addEventListener('touchend', () => {\r\n setTimeout(() => {\r\n isPossibleSwipe = false;\r\n }, 100);\r\n }, {passive: true, once: true});\r\n }\r\n\r\n /* const detach = () => {\r\n window.removeEventListener('touchend', onTouchEnd);\r\n window.removeEventListener('touchmove', onTouchMove);\r\n };\r\n\r\n let moved = false;\r\n const onTouchMove = (e: TouchEvent) => {\r\n this.debug && this.log('touchmove');\r\n if(e.touches.length > 1) {\r\n detach();\r\n return;\r\n }\r\n\r\n moved = true;\r\n };\r\n\r\n const onTouchEnd = (e: TouchEvent) => {\r\n this.debug && this.log('touchend');\r\n if(e.touches.length > 1 || !moved) {\r\n detach();\r\n return;\r\n }\r\n\r\n isPossibleSwipe = true;\r\n doubleRaf().then(() => {\r\n isPossibleSwipe = false;\r\n });\r\n\r\n detach();\r\n };\r\n\r\n window.addEventListener('touchend', onTouchEnd, options);\r\n window.addEventListener('touchmove', onTouchMove, options); */\r\n }, options);\r\n }\r\n\r\n history.scrollRestoration = 'manual';\r\n\r\n this.pushState(); // * push init state\r\n }\r\n\r\n private handleItem(item: NavigationItem) {\r\n const good = item.onPop(!this.manual ? false : undefined);\r\n this.debug && this.log('popstate, navigation:', item, this.navigations);\r\n if(good === false) {\r\n this.pushItem(item);\r\n } else if(!item.noBlurOnPop) {\r\n blurActiveElement(); // no better place for it\r\n }\r\n\r\n this.manual = false;\r\n }\r\n\r\n public findItemByType(type: NavigationItem['type']) {\r\n for(let i = this.navigations.length - 1; i >= 0; --i) {\r\n const item = this.navigations[i];\r\n if(item.type === type) {\r\n return {item, index: i};\r\n }\r\n }\r\n }\r\n\r\n public back(type?: NavigationItem['type']) {\r\n if(type) {\r\n const ret = this.findItemByType(type);\r\n if(ret) {\r\n this.backByItem(ret.item, ret.index);\r\n return;\r\n }\r\n }\r\n\r\n history.back();\r\n }\r\n\r\n public backByItem(item: NavigationItem, index = this.navigations.indexOf(item)) {\r\n this.manual = true;\r\n // ! commented because 'popstate' event will be fired with delay\r\n //if(index !== (this.navigations.length - 1)) {\r\n this.navigations.splice(index, 1);\r\n this.handleItem(item);\r\n //}\r\n }\r\n\r\n public pushItem(item: NavigationItem) {\r\n this.navigations.push(item);\r\n this.debug && this.log('pushstate', item, this.navigations);\r\n\r\n if(!item.noHistory) {\r\n this.pushState();\r\n }\r\n }\r\n\r\n private pushState() {\r\n this.manual = false;\r\n history.pushState(this.id, '');\r\n }\r\n\r\n public replaceState() {\r\n history.replaceState(this.id, '', location.origin + location.pathname);\r\n }\r\n\r\n public removeItem(item: NavigationItem) {\r\n if(!item) {\r\n return;\r\n }\r\n \r\n indexOfAndSplice(this.navigations, item);\r\n }\r\n\r\n public removeByType(type: NavigationItem['type'], single = false) {\r\n for(let i = this.navigations.length - 1; i >= 0; --i) {\r\n const item = this.navigations[i];\r\n if(item.type === type) {\r\n this.navigations.splice(i, 1);\r\n\r\n if(single) {\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\nconst appNavigationController = new AppNavigationController();\r\nMOUNT_CLASS_TO.appNavigationController = appNavigationController;\r\nexport default appNavigationController;\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n * \r\n * Originally from:\r\n * https://github.com/zhukov/webogram\r\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\r\n * https://github.com/zhukov/webogram/blob/master/LICENSE\r\n */\r\n\r\nexport function bytesToHex(bytes: ArrayLike<number>) {\r\n const length = bytes.length;\r\n const arr: string[] = new Array(length);\r\n for(let i = 0; i < length; ++i) {\r\n arr[i] = (bytes[i] < 16 ? '0' : '') + (bytes[i] || 0).toString(16);\r\n }\r\n return arr.join('');\r\n}\r\n\r\nexport function bytesFromHex(hexString: string) {\r\n const len = hexString.length;\r\n const bytes = new Uint8Array(Math.ceil(len / 2));\r\n let start = 0;\r\n\r\n if(len % 2) { // read 0x581 as 0x0581\r\n bytes[start++] = parseInt(hexString.charAt(0), 16);\r\n }\r\n\r\n for(let i = start; i < len; i += 2) {\r\n bytes[start++] = parseInt(hexString.substr(i, 2), 16);\r\n }\r\n\r\n return bytes;\r\n}\r\n\r\nexport function bytesToBase64(bytes: number[] | Uint8Array) {\r\n let mod3: number;\r\n let result = '';\r\n\r\n for(let nLen = bytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; ++nIdx) {\r\n mod3 = nIdx % 3;\r\n nUint24 |= bytes[nIdx] << (16 >>> mod3 & 24);\r\n if(mod3 === 2 || nLen - nIdx === 1) {\r\n result += String.fromCharCode(\r\n uint6ToBase64(nUint24 >>> 18 & 63),\r\n uint6ToBase64(nUint24 >>> 12 & 63),\r\n uint6ToBase64(nUint24 >>> 6 & 63),\r\n uint6ToBase64(nUint24 & 63)\r\n );\r\n nUint24 = 0;\r\n }\r\n }\r\n\r\n return result.replace(/A(?=A$|$)/g, '=');\r\n}\r\n\r\nexport function uint6ToBase64(nUint6: number) {\r\n return nUint6 < 26\r\n ? nUint6 + 65\r\n : nUint6 < 52\r\n ? nUint6 + 71\r\n : nUint6 < 62\r\n ? nUint6 - 4\r\n : nUint6 === 62\r\n ? 43\r\n : nUint6 === 63\r\n ? 47\r\n : 65;\r\n}\r\n\r\nexport function bytesCmp(bytes1: number[] | Uint8Array, bytes2: number[] | Uint8Array) {\r\n const len = bytes1.length;\r\n if(len !== bytes2.length) {\r\n return false;\r\n }\r\n\r\n for(let i = 0; i < len; ++i) {\r\n if(bytes1[i] !== bytes2[i]) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n}\r\n\r\nexport function bytesXor(bytes1: Uint8Array, bytes2: Uint8Array) {\r\n const len = bytes1.length;\r\n const bytes = new Uint8Array(len);\r\n\r\n for(let i = 0; i < len; ++i) {\r\n bytes[i] = bytes1[i] ^ bytes2[i];\r\n }\r\n\r\n return bytes;\r\n}\r\n\r\n/* export function bytesToArrayBuffer(b: number[]) {\r\n return (new Uint8Array(b)).buffer;\r\n}\r\n\r\nexport function convertToArrayBuffer(bytes: any | ArrayBuffer | Uint8Array) {\r\n // Be careful with converting subarrays!!\r\n if(bytes instanceof ArrayBuffer) {\r\n return bytes;\r\n }\r\n if(bytes.buffer !== undefined &&\r\n bytes.buffer.byteLength === bytes.length * bytes.BYTES_PER_ELEMENT) {\r\n return bytes.buffer;\r\n }\r\n return bytesToArrayBuffer(bytes);\r\n} */\r\n\r\nexport function convertToUint8Array(bytes: Uint8Array | ArrayBuffer | number[] | string): Uint8Array {\r\n if(bytes instanceof Uint8Array) {\r\n return bytes;\r\n } else if(typeof(bytes) === 'string') {\r\n return new TextEncoder().encode(bytes);\r\n }\r\n\r\n return new Uint8Array(bytes);\r\n}\r\n\r\n/* export function bytesFromArrayBuffer(buffer: ArrayBuffer) {\r\n const len = buffer.byteLength;\r\n const byteView = new Uint8Array(buffer);\r\n const bytes: number[] = [];\r\n\r\n for(let i = 0; i < len; ++i) {\r\n bytes[i] = byteView[i];\r\n }\r\n\r\n return bytes;\r\n}\r\n\r\nexport function bufferConcat(buffer1: any, buffer2: any) {\r\n const l1 = buffer1.byteLength || buffer1.length;\r\n const l2 = buffer2.byteLength || buffer2.length;\r\n const tmp = new Uint8Array(l1 + l2);\r\n tmp.set(buffer1 instanceof ArrayBuffer ? new Uint8Array(buffer1) : buffer1, 0);\r\n tmp.set(buffer2 instanceof ArrayBuffer ? new Uint8Array(buffer2) : buffer2, l1);\r\n\r\n return tmp.buffer;\r\n} */\r\n\r\nexport function bufferConcats(...args: (ArrayBuffer | Uint8Array | number[])[]) {\r\n const length = args.reduce((acc, v) => acc + ((v as ArrayBuffer).byteLength || (v as Uint8Array).length), 0);\r\n\r\n const tmp = new Uint8Array(length);\r\n \r\n let lastLength = 0;\r\n args.forEach(b => {\r\n tmp.set(b instanceof ArrayBuffer ? new Uint8Array(b) : b, lastLength);\r\n lastLength += (b as ArrayBuffer).byteLength || (b as Uint8Array).length;\r\n });\r\n\r\n return tmp/* .buffer */;\r\n}\r\n\r\nexport function bytesFromWordss(input: Uint32Array) {\r\n const o = new Uint8Array(input.byteLength);\r\n for(let i = 0, length = input.length * 4; i < length; ++i) {\r\n o[i] = ((input[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff);\r\n }\r\n\r\n return o;\r\n}\r\n\r\nexport function bytesToWordss(input: Parameters<typeof convertToUint8Array>[0]) {\r\n const bytes = convertToUint8Array(input);\r\n\r\n const words: number[] = [];\r\n for(let i = 0, len = bytes.length; i < len; ++i) {\r\n words[i >>> 2] |= bytes[i] << (24 - (i % 4) * 8);\r\n }\r\n\r\n return new Uint32Array(words);\r\n}\r\n\r\n// * https://stackoverflow.com/a/52827031\r\n/* export const isBigEndian = (() => {\r\n const array = new Uint8Array(4);\r\n const view = new Uint32Array(array.buffer);\r\n return !((view[0] = 1) & array[0]);\r\n})(); */\r\n","export default function simulateEvent(elem: EventTarget, name: string) {\n const event = new Event(name, {bubbles: true, cancelable: true});\n elem.dispatchEvent(event);\n}\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nimport { fastRaf } from \"./schedulers\";\r\nimport { CancellablePromise, deferredPromise } from \"./cancellablePromise\";\r\nimport { MOUNT_CLASS_TO } from \"../config/debug\";\r\nimport isInDOM from \"./dom/isInDOM\";\r\n\r\nclass SequentialDom {\r\n private promises: Partial<{\r\n read: CancellablePromise<void>,\r\n write: CancellablePromise<void>\r\n }> = {};\r\n private raf = fastRaf.bind(null);\r\n private scheduled = false;\r\n\r\n private do(kind: keyof SequentialDom['promises'], callback?: VoidFunction) {\r\n let promise = this.promises[kind];\r\n if(!promise) {\r\n this.scheduleFlush();\r\n promise = this.promises[kind] = deferredPromise<void>();\r\n }\r\n\r\n if(callback !== undefined) {\r\n promise.then(() => callback());\r\n }\r\n \r\n return promise;\r\n }\r\n\r\n public measure(callback?: VoidFunction) {\r\n return this.do('read', callback);\r\n }\r\n\r\n public mutate(callback?: VoidFunction) {\r\n return this.do('write', callback);\r\n }\r\n\r\n /**\r\n * Will fire instantly if element is not connected\r\n * @param element \r\n * @param callback \r\n */\r\n public mutateElement(element: HTMLElement, callback?: VoidFunction) {\r\n const promise = isInDOM(element) ? this.mutate() : Promise.resolve();\r\n\r\n if(callback !== undefined) {\r\n promise.then(() => callback());\r\n }\r\n\r\n return promise;\r\n }\r\n\r\n private scheduleFlush() {\r\n if(!this.scheduled) {\r\n this.scheduled = true;\r\n\r\n this.raf(() => {\r\n this.promises.read && this.promises.read.resolve();\r\n this.promises.write && this.promises.write.resolve();\r\n\r\n this.scheduled = false;\r\n this.promises = {};\r\n });\r\n }\r\n }\r\n}\r\n\r\nconst sequentialDom = new SequentialDom();\r\nMOUNT_CLASS_TO && (MOUNT_CLASS_TO.sequentialDom = sequentialDom);\r\nexport default sequentialDom;\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n * \r\n * Originally from:\r\n * https://github.com/zhukov/webogram\r\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\r\n * https://github.com/zhukov/webogram/blob/master/LICENSE\r\n */\r\n\r\nimport type { ApplyServerTimeOffsetTask } from './timeManager';\r\nimport { MOUNT_CLASS_TO } from '../../config/debug';\r\n// import { tsNow } from '../../helpers/date';\r\nimport sessionStorage from '../sessionStorage';\r\nimport apiManager from './mtprotoworker';\r\n\r\nexport class ServerTimeManager {\r\n /* private midnightNoOffset: number;\r\n private midnightOffseted: Date;\r\n\r\n private midnightOffset: number; */\r\n\r\n public serverTimeOffset: number; // in seconds\r\n /* private timeParams: {\r\n midnightOffset: number,\r\n serverTimeOffset: number\r\n }; */\r\n\r\n constructor() {\r\n /* const timestampNow = tsNow(true);\r\n this.midnightNoOffset = timestampNow - (timestampNow % 86400);\r\n this.midnightOffseted = new Date();\r\n this.midnightOffseted.setHours(0, 0, 0, 0);\r\n \r\n this.midnightOffset = this.midnightNoOffset - (Math.floor(+this.midnightOffseted / 1000)); */\r\n\r\n this.serverTimeOffset = 0;\r\n /* this.timeParams = {\r\n midnightOffset: this.midnightOffset,\r\n serverTimeOffset: this.serverTimeOffset\r\n }; */\r\n\r\n sessionStorage.get('server_time_offset').then((to) => {\r\n if(to) {\r\n this.serverTimeOffset = to;\r\n // this.timeParams.serverTimeOffset = to;\r\n }\r\n });\r\n\r\n apiManager.addTaskListener('applyServerTimeOffset', (task: ApplyServerTimeOffsetTask) => {\r\n this.serverTimeOffset = task.payload;\r\n });\r\n }\r\n}\r\n\r\nconst serverTimeManager = new ServerTimeManager();\r\nMOUNT_CLASS_TO && (MOUNT_CLASS_TO.serverTimeManager = serverTimeManager);\r\nexport default serverTimeManager;\r\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport { IS_MOBILE_SAFARI } from \"../../environment/userAgent\";\n\nexport default function isSwipingBackSafari(e: TouchEvent | MouseEvent) {\n return IS_MOBILE_SAFARI && e instanceof TouchEvent && e.touches[0].clientX < 30;\n}\n"],"sourceRoot":""}