1 line
70 KiB
Plaintext
1 line
70 KiB
Plaintext
{"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":""} |