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.
164 lines
4.5 KiB
164 lines
4.5 KiB
![]()
3 years ago
|
/*
|
||
|
* https://github.com/morethanwords/tweb
|
||
|
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||
|
*/
|
||
|
|
||
|
import { attachClickEvent } from "./dom/clickEvent";
|
||
|
import findUpAsChild from "./dom/findUpAsChild";
|
||
|
import EventListenerBase from "./eventListenerBase";
|
||
|
import ListenerSetter from "./listenerSetter";
|
||
|
import { safeAssign } from "./object";
|
||
|
import { isTouchSupported } from "./touchSupport";
|
||
|
|
||
|
const KEEP_OPEN = false;
|
||
|
const TOGGLE_TIMEOUT = 200;
|
||
|
const ANIMATION_DURATION = 200;
|
||
|
|
||
|
export default class DropdownHover extends EventListenerBase<{
|
||
|
open: () => Promise<any> | void,
|
||
|
opened: () => any,
|
||
|
close: () => any,
|
||
|
closed: () => any
|
||
|
}> {
|
||
|
protected element: HTMLElement;
|
||
|
protected displayTimeout: number;
|
||
|
protected forceClose = false;
|
||
|
protected inited = false;
|
||
|
|
||
|
constructor(options: {
|
||
|
element: DropdownHover['element']
|
||
|
}) {
|
||
|
super(false);
|
||
|
safeAssign(this, options);
|
||
|
}
|
||
|
|
||
|
public attachButtonListener(button: HTMLElement, listenerSetter: ListenerSetter) {
|
||
|
let firstTime = true;
|
||
|
if(isTouchSupported) {
|
||
|
attachClickEvent(button, () => {
|
||
|
if(firstTime) {
|
||
|
firstTime = false;
|
||
|
this.toggle(true);
|
||
|
} else {
|
||
|
this.toggle();
|
||
|
}
|
||
|
}, {listenerSetter});
|
||
|
} else {
|
||
|
listenerSetter.add(button, 'mouseover', (e) => {
|
||
|
//console.log('onmouseover button');
|
||
|
if(firstTime) {
|
||
|
listenerSetter.add(button, 'mouseout', this.onMouseOut);
|
||
|
firstTime = false;
|
||
|
}
|
||
|
|
||
|
clearTimeout(this.displayTimeout);
|
||
|
this.displayTimeout = window.setTimeout(() => {
|
||
|
this.toggle(true);
|
||
|
}, TOGGLE_TIMEOUT);
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private onMouseOut = (e: MouseEvent) => {
|
||
|
if(KEEP_OPEN) return;
|
||
|
clearTimeout(this.displayTimeout);
|
||
|
if(!this.isActive()) return;
|
||
|
|
||
|
const toElement = (e as any).toElement as Element;
|
||
|
if(toElement && findUpAsChild(toElement, this.element)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
this.displayTimeout = window.setTimeout(() => {
|
||
|
this.toggle(false);
|
||
|
}, TOGGLE_TIMEOUT);
|
||
|
};
|
||
|
|
||
|
protected init() {
|
||
|
if(!isTouchSupported) {
|
||
|
this.element.onmouseout = this.onMouseOut;
|
||
|
this.element.onmouseover = (e) => {
|
||
|
if(this.forceClose) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//console.log('onmouseover element');
|
||
|
clearTimeout(this.displayTimeout);
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public toggle = async(enable?: boolean) => {
|
||
|
//if(!this.element) return;
|
||
|
const willBeActive = (!!this.element.style.display && enable === undefined) || enable;
|
||
|
if(this.init) {
|
||
|
if(willBeActive) {
|
||
|
this.init();
|
||
|
this.init = null;
|
||
|
} else {
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(willBeActive === this.isActive()) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if((this.element.style.display && enable === undefined) || enable) {
|
||
|
const res = this.dispatchEvent('open');
|
||
|
await Promise.all(res);
|
||
|
|
||
|
this.element.style.display = '';
|
||
|
void this.element.offsetLeft; // reflow
|
||
|
this.element.classList.add('active');
|
||
|
|
||
|
clearTimeout(this.displayTimeout);
|
||
|
this.displayTimeout = window.setTimeout(() => {
|
||
|
this.forceClose = false;
|
||
|
this.dispatchEvent('opened');
|
||
|
}, isTouchSupported ? 0 : ANIMATION_DURATION);
|
||
|
|
||
|
// ! can't use together with resizeObserver
|
||
|
/* if(isTouchSupported) {
|
||
|
const height = this.element.scrollHeight + appImManager.chat.input.inputContainer.scrollHeight - 10;
|
||
|
console.log('[ESG]: toggle: enable height', height);
|
||
|
appImManager.chat.bubbles.scrollable.scrollTop += height;
|
||
|
} */
|
||
|
|
||
|
/* if(touchSupport) {
|
||
|
this.restoreScroll();
|
||
|
} */
|
||
|
} else {
|
||
|
this.dispatchEvent('close');
|
||
|
|
||
|
this.element.classList.remove('active');
|
||
|
|
||
|
clearTimeout(this.displayTimeout);
|
||
|
this.displayTimeout = window.setTimeout(() => {
|
||
|
this.element.style.display = 'none';
|
||
|
this.forceClose = false;
|
||
|
this.dispatchEvent('closed');
|
||
|
}, isTouchSupported ? 0 : ANIMATION_DURATION);
|
||
|
|
||
|
/* if(isTouchSupported) {
|
||
|
const scrollHeight = this.container.scrollHeight;
|
||
|
if(scrollHeight) {
|
||
|
const height = this.container.scrollHeight + appImManager.chat.input.inputContainer.scrollHeight - 10;
|
||
|
appImManager.chat.bubbles.scrollable.scrollTop -= height;
|
||
|
}
|
||
|
} */
|
||
|
|
||
|
/* if(touchSupport) {
|
||
|
this.restoreScroll();
|
||
|
} */
|
||
|
}
|
||
|
|
||
|
//animationIntersector.checkAnimations(false, EMOTICONSSTICKERGROUP);
|
||
|
};
|
||
|
|
||
|
public isActive() {
|
||
|
return this.element.classList.contains('active');
|
||
|
}
|
||
|
}
|