{"version":3,"file":"554.7d2b9a9c4096088ac7e1.chunk.js","mappings":"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","sources":["webpack://tweb/./src/components/appNavigationController.ts","webpack://tweb/./src/components/button.ts","webpack://tweb/./src/components/misc.ts","webpack://tweb/./src/components/ripple.ts","webpack://tweb/./src/helpers/dom/clickEvent.ts","webpack://tweb/./src/helpers/dom/dispatchEvent.ts","webpack://tweb/./src/helpers/dom/isSwipingBackSafari.ts","webpack://tweb/./src/helpers/sequentialDom.ts"],"sourcesContent":["/*\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 blurActiveElement from \"../helpers/dom/blurActiveElement\";\r\nimport { cancelEvent } from \"../helpers/dom/cancelEvent\";\r\nimport isSwipingBackSafari from \"../helpers/dom/isSwipingBackSafari\";\r\nimport indexOfAndSplice from \"../helpers/array/indexOfAndSplice\";\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' | 'filters',\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 = [];\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 private onItemAdded(item: NavigationItem) {\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 public pushItem(item: NavigationItem) {\r\n this.navigations.push(item);\r\n this.onItemAdded(item);\r\n }\r\n\r\n public unshiftItem(item: NavigationItem) {\r\n this.navigations.unshift(item);\r\n this.onItemAdded(item);\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\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 \r\n \r\n `;\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) {\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\nexport type MenuPositionPadding = {\r\n top?: number, \r\n right?: number, \r\n bottom?: number, \r\n left?: number\r\n};\r\n\r\nconst PADDING_TOP = 8;\r\nconst PADDING_BOTTOM = PADDING_TOP;\r\nconst PADDING_LEFT = 8;\r\nconst PADDING_RIGHT = PADDING_LEFT;\r\nexport function positionMenu({pageX, pageY}: MouseEvent | Touch, elem: HTMLElement, side?: 'left' | 'right' | 'center', additionalPadding?: MenuPositionPadding) {\r\n //let {clientX, clientY} = e;\r\n\r\n // * side mean the OPEN side\r\n\r\n const getScrollWidthFromElement = (Array.from(elem.children) as HTMLElement[]).find(element => element.classList.contains('btn-menu-item') && !element.classList.contains('hide')) || elem;\r\n\r\n let {scrollWidth: menuWidth} = getScrollWidthFromElement;\r\n let {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 let paddingTop = PADDING_TOP, paddingRight = PADDING_RIGHT, paddingBottom = PADDING_BOTTOM, paddingLeft = PADDING_LEFT;\r\n if(additionalPadding) {\r\n if(additionalPadding.top) paddingTop += additionalPadding.top;\r\n if(additionalPadding.right) paddingRight += additionalPadding.right;\r\n if(additionalPadding.bottom) paddingBottom += additionalPadding.bottom;\r\n if(additionalPadding.left) paddingLeft += additionalPadding.left;\r\n }\r\n\r\n side = mediaSizes.isMobile ? 'right' : 'left';\r\n let verticalSide: 'top' /* | 'bottom' */ | 'center' = 'top';\r\n\r\n const maxTop = windowHeight - menuHeight - paddingBottom;\r\n const maxLeft = windowWidth - menuWidth - paddingRight;\r\n const minTop = paddingTop;\r\n const minLeft = paddingLeft;\r\n\r\n const getSides = () => {\r\n return {\r\n x: {\r\n left: pageX,\r\n right: Math.min(maxLeft, pageX - menuWidth)\r\n },\r\n intermediateX: side === 'right' ? minLeft : maxLeft,\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' ? paddingTop : windowHeight - menuHeight - paddingTop,\r\n // intermediateY: pageY < (windowHeight / 2) ? paddingTop : windowHeight - menuHeight - paddingBottom,\r\n intermediateY: maxTop,\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 + paddingRight) <= windowWidth,\r\n right: sides.x.right >= paddingLeft\r\n },\r\n y: {\r\n top: (sides.y.top + menuHeight + paddingBottom) <= windowHeight,\r\n bottom: (sides.y.bottom - paddingBottom) >= paddingBottom\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 return {\r\n width: menuWidth,\r\n height: menuHeight\r\n };\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 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 = () => 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;\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 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","export default function simulateEvent(elem: EventTarget, name: string) {\n const event = new Event(name, {bubbles: true, cancelable: true});\n elem.dispatchEvent(event);\n}\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","/*\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,\r\n write: CancellablePromise\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();\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 isConnected = isInDOM(element);\r\n const promise = isConnected ? this.mutate() : Promise.resolve();\r\n\r\n if(callback !== undefined) {\r\n if(isConnected) {\r\n callback();\r\n } else {\r\n promise.then(() => callback());\r\n }\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"],"names":["appNavigationController","constructor","navigations","id","Date","now","manual","log","debug","currentHash","window","location","hash","isPossibleSwipe","addEventListener","e","this","onHashChange","replaceState","state","pushState","item","pop","handleItem","length","key","onEscape","back","type","capture","passive","IS_MOBILE_SAFARI","options","touches","setTimeout","once","history","scrollRestoration","good","onPop","undefined","pushItem","noBlurOnPop","findItemByType","i","index","ret","backByItem","indexOf","splice","onItemAdded","noHistory","push","unshiftItem","unshift","origin","pathname","removeItem","removeByType","single","className","button","document","createElement","asDiv","icon","noRipple","rippleSquare","classList","add","ripple","onlyMobile","disabled","setAttribute","text","append","i18n","putPreloader","elem","returnDiv","html","div","innerHTML","appendChild","insertAdjacentHTML","lastElementChild","setButtonLoader","remove","removeAttribute","onMouseMove","rect","openedMenu","getBoundingClientRect","clientX","clientY","diffX","right","left","diffY","bottom","top","closeBtnMenu","onClick","parentElement","menuOverlay","openedMenuOnClose","IS_TOUCH_SUPPORTED","removeEventListener","openBtnMenu","menuElement","onClose","canAnimate","insertBefore","positionMenu","pageX","pageY","side","additionalPadding","getScrollWidthFromElement","Array","from","children","find","element","contains","scrollWidth","menuWidth","scrollHeight","menuHeight","body","windowWidth","width","windowHeight","height","paddingTop","paddingRight","paddingBottom","paddingLeft","verticalSide","maxTop","maxLeft","minLeft","sides","x","Math","min","intermediateX","y","intermediateY","possibleSides","style","replace","_cancelContextMenuOpening","_cancelContextMenuOpeningTimeout","cancelContextMenuOpening","clearTimeout","attachContextMenuListener","callback","listenerSetter","bind","removeManual","IS_APPLE","timeout","onCancel","rippleClickId","Promise","resolve","onEnd","prepend","attachListenerTo","querySelector","handler","r","drawRipple","startTime","clickId","duration","getComputedStyle","getPropertyValue","elapsedTime","cb","delay","max","touchStartFired","requestAnimationFrame","clickX","clickY","size","sqrt","abs","isRippleUnneeded","target","includes","tagName","touchEnd","cancelBubble","stopPropagation","dataset","CLICK_EVENT_NAME","attachClickEvent","touchMouseDown","detachClickEvent","simulateClickEvent","simulateEvent","name","event","Event","bubbles","cancelable","dispatchEvent","isSwipingBackSafari","TouchEvent","sequentialDom","promises","raf","scheduled","do","kind","promise","scheduleFlush","then","measure","mutate","mutateElement","isConnected","read","write"],"sourceRoot":""}