Telegram Web K with changes to work inside I2P
https://web.telegram.i2p/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
4.6 KiB
168 lines
4.6 KiB
/* |
|
* https://github.com/morethanwords/tweb |
|
* Copyright (C) 2019-2021 Eduard Kuzmenko |
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE |
|
*/ |
|
|
|
import attachListNavigation from "../../helpers/dom/attachListNavigation"; |
|
import EventListenerBase from "../../helpers/eventListenerBase"; |
|
import { IS_MOBILE } from "../../environment/userAgent"; |
|
import rootScope from "../../lib/rootScope"; |
|
import appNavigationController, { NavigationItem } from "../appNavigationController"; |
|
import SetTransition from "../singleTransition"; |
|
import AutocompleteHelperController from "./autocompleteHelperController"; |
|
import safeAssign from "../../helpers/object/safeAssign"; |
|
|
|
export default class AutocompleteHelper extends EventListenerBase<{ |
|
hidden: () => void, |
|
visible: () => void, |
|
hiding: () => void |
|
}> { |
|
protected hidden = true; |
|
protected container: HTMLElement; |
|
protected list: HTMLElement; |
|
protected resetTarget: () => void; |
|
protected attach: () => void; |
|
protected detach: () => void; |
|
protected init?(): void; |
|
|
|
protected controller: AutocompleteHelperController; |
|
protected listType: 'xy' | 'x' | 'y'; |
|
protected onSelect: (target: Element) => boolean | void; |
|
protected waitForKey?: string[]; |
|
|
|
protected navigationItem: NavigationItem; |
|
|
|
constructor(options: { |
|
appendTo: HTMLElement, |
|
controller?: AutocompleteHelper['controller'], |
|
listType: AutocompleteHelper['listType'], |
|
onSelect: AutocompleteHelper['onSelect'], |
|
waitForKey?: AutocompleteHelper['waitForKey'] |
|
}) { |
|
super(false); |
|
|
|
safeAssign(this, options); |
|
|
|
this.container = document.createElement('div'); |
|
this.container.classList.add('autocomplete-helper', 'z-depth-1'); |
|
|
|
options.appendTo.append(this.container); |
|
|
|
this.attachNavigation(); |
|
|
|
this.controller && this.controller.addHelper(this); |
|
} |
|
|
|
public toggleListNavigation(enabled: boolean) { |
|
if(enabled) { |
|
this.attach && this.attach(); |
|
} else { |
|
this.detach && this.detach(); |
|
} |
|
} |
|
|
|
protected onVisible = () => { |
|
if(this.detach) { // it can be so because 'visible' calls before animation's end |
|
this.detach(); |
|
} |
|
|
|
const list = this.list; |
|
const {attach, detach, resetTarget} = attachListNavigation({ |
|
list, |
|
type: this.listType, |
|
onSelect: this.onSelect, |
|
once: true, |
|
waitForKey: this.waitForKey |
|
}); |
|
|
|
this.attach = attach; |
|
this.detach = detach; |
|
this.resetTarget = resetTarget; |
|
if(!IS_MOBILE && !this.navigationItem) { |
|
this.navigationItem = { |
|
type: 'autocomplete-helper', |
|
onPop: () => { |
|
this.navigationItem = undefined; |
|
this.toggle(true); |
|
}, |
|
noBlurOnPop: true |
|
}; |
|
|
|
appNavigationController.pushItem(this.navigationItem); |
|
} |
|
|
|
this.addEventListener('hidden', () => { |
|
this.resetTarget = undefined; |
|
this.attach = undefined; |
|
this.detach = undefined; |
|
|
|
list.innerHTML = ''; |
|
detach(); |
|
|
|
if(this.navigationItem) { |
|
appNavigationController.removeItem(this.navigationItem); |
|
this.navigationItem = undefined; |
|
} |
|
}, {once: true}); |
|
}; |
|
|
|
protected attachNavigation() { |
|
this.addEventListener('visible', this.onVisible); |
|
} |
|
|
|
public toggle(hide?: boolean, fromController = false, skipAnimation?: boolean) { |
|
if(this.init) { |
|
return; |
|
} |
|
|
|
if(hide === undefined) { |
|
hide = this.container.classList.contains('is-visible') && !this.container.classList.contains('backwards'); |
|
} |
|
|
|
if(this.hidden === hide) { |
|
if(!hide) { |
|
this.dispatchEvent('visible'); // reset target and listener |
|
} |
|
|
|
return; |
|
} |
|
|
|
this.hidden = hide; |
|
|
|
if(!hide) { |
|
this.controller && this.controller.hideOtherHelpers(this); |
|
this.dispatchEvent('visible'); // fire it before so target will be set |
|
} else { |
|
if(this.navigationItem) { |
|
appNavigationController.removeItem(this.navigationItem); |
|
this.navigationItem = undefined; |
|
} |
|
|
|
if(!fromController && this.controller) { |
|
this.controller.hideOtherHelpers(); |
|
} |
|
|
|
if(this.detach) { // force detach here |
|
this.detach(); |
|
} |
|
} |
|
|
|
const useRafs = this.controller || hide ? 0 : 2; |
|
|
|
if(hide) { |
|
this.dispatchEvent('hiding'); |
|
} |
|
|
|
SetTransition( |
|
this.container, |
|
'is-visible', |
|
!hide, |
|
rootScope.settings.animationsEnabled && !skipAnimation ? 300 : 0, |
|
() => { |
|
this.hidden && this.dispatchEvent('hidden'); |
|
}, |
|
useRafs |
|
); |
|
} |
|
}
|
|
|