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.
103 lines
3.5 KiB
103 lines
3.5 KiB
/* |
|
* https://github.com/morethanwords/tweb |
|
* Copyright (C) 2019-2021 Eduard Kuzmenko |
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE |
|
*/ |
|
|
|
import {USING_BOMS} from '../helpers/dom/richInputHandler'; |
|
import BOM from '../helpers/string/bom'; |
|
import {_i18n} from '../lib/langPack'; |
|
import InputField, {InputFieldOptions} from './inputField'; |
|
import SetTransition from './singleTransition'; |
|
|
|
const USELESS_REG_EXP = new RegExp(`(<span>${BOM}</span>)|(<br\/?>)`, 'g'); |
|
|
|
export default class InputFieldAnimated extends InputField { |
|
public inputFake: HTMLElement; |
|
public onChangeHeight: (height: number) => void; |
|
|
|
// public onLengthChange: (length: number, isOverflow: boolean) => void; |
|
// protected wasInputFakeClientHeight: number; |
|
// protected showScrollDebounced: () => void; |
|
|
|
constructor(options?: InputFieldOptions) { |
|
super(options); |
|
|
|
this.input.addEventListener('input', () => { |
|
this.updateInnerHTML(); |
|
this.onFakeInput(); |
|
}); |
|
|
|
if(options.placeholder) { |
|
_i18n(this.inputFake, options.placeholder, undefined, 'placeholder'); |
|
} |
|
|
|
this.input.classList.add('scrollable', 'scrollable-y', 'no-scrollbar'); |
|
// this.wasInputFakeClientHeight = 0; |
|
// this.showScrollDebounced = debounce(() => this.input.classList.remove('no-scrollbar'), 150, false, true); |
|
this.inputFake = document.createElement('div'); |
|
// this.inputFake.contentEditable = 'true'; |
|
this.inputFake.contentEditable = 'true'; |
|
this.inputFake.tabIndex = -1; |
|
this.inputFake.className = this.input.className + ' input-field-input-fake'; |
|
} |
|
|
|
public onFakeInput(setHeight = true, noAnimation?: boolean) { |
|
const {scrollHeight: newHeight/* , clientHeight */} = this.inputFake; |
|
/* if(this.wasInputFakeClientHeight && this.wasInputFakeClientHeight !== clientHeight) { |
|
this.input.classList.add('no-scrollbar'); // ! в сафари может вообще не появиться скролл после анимации, так как ему нужен полный reflow блока с overflow. |
|
this.showScrollDebounced(); |
|
} */ |
|
|
|
noAnimation ??= !this.input.isContentEditable; |
|
|
|
const currentHeight = +this.input.style.height.replace('px', ''); |
|
if(currentHeight === newHeight) { |
|
return; |
|
} |
|
|
|
const TRANSITION_DURATION_FACTOR = 50; |
|
const transitionDuration = noAnimation ? 0 : Math.round( |
|
TRANSITION_DURATION_FACTOR * Math.log(Math.abs(newHeight - currentHeight)) |
|
); |
|
|
|
// this.wasInputFakeClientHeight = clientHeight; |
|
this.input.style.transitionDuration = `${transitionDuration}ms`; |
|
|
|
if(setHeight) { |
|
this.onChangeHeight?.(newHeight); |
|
this.input.style.height = newHeight ? newHeight + 'px' : ''; |
|
} |
|
|
|
const className = 'is-changing-height'; |
|
SetTransition({ |
|
element: this.input, |
|
className, |
|
forwards: true, |
|
duration: transitionDuration, |
|
onTransitionEnd: () => { |
|
this.input.classList.remove(className); |
|
} |
|
}); |
|
} |
|
|
|
protected updateInnerHTML(innerHTML = this.input.innerHTML) { |
|
innerHTML = innerHTML.replace(/<custom-emoji-renderer-element.+\/custom-emoji-renderer-element>/, '') |
|
.replace(/(<custom-emoji-element.+?>).+?\/custom-emoji-element>/g, '$1</custom-emoji-element>') |
|
|
|
if(USING_BOMS) { |
|
innerHTML = innerHTML.replace(USELESS_REG_EXP, ''); |
|
} |
|
|
|
this.inputFake.innerHTML = innerHTML; |
|
} |
|
|
|
public setValueSilently(value: Parameters<InputField['setValueSilently']>[0], fromSet?: boolean) { |
|
super.setValueSilently(value, fromSet); |
|
|
|
this.updateInnerHTML(); |
|
if(!fromSet) { |
|
this.onFakeInput(); |
|
} |
|
} |
|
}
|
|
|