[Perf] Composer: Avoid querying DOM while rendering

This commit is contained in:
Alexander Zinchuk 2023-01-22 18:12:43 +01:00
parent f17f1f533e
commit 07e7253b02
4 changed files with 18 additions and 9 deletions

View File

@ -36,7 +36,7 @@ export default function useCustomEmojiTooltip(
}
}, [updateCacheBuster]);
useOnSelectionChange(document.querySelector<HTMLDivElement>(inputSelector), handleSelectionChange);
useOnSelectionChange(inputSelector, handleSelectionChange);
useEffect(() => {
if (!html) {

View File

@ -86,6 +86,10 @@ export default function useInlineBotTooltip(
}
function parseBotQuery(html: string) {
if (!html.startsWith('@')) {
return MEMO_NO_RESULT;
}
const text = getPlainText(html);
const result = text.match(INLINE_BOT_QUERY_REGEXP);
if (!result) {

View File

@ -75,7 +75,7 @@ export default function useMentionTooltip(
}
}, [updateCacheBuster]);
useOnSelectionChange(document.querySelector<HTMLDivElement>(inputSelector), handleSelectionChange);
useOnSelectionChange(inputSelector, handleSelectionChange);
useEffect(() => {
setHtmlBeforeSelection(getHtmlBeforeSelection(document.querySelector<HTMLDivElement>(inputSelector)!));

View File

@ -1,23 +1,28 @@
import { useEffect } from '../lib/teact/teact';
export default function useOnSelectionChange(container: HTMLElement | null, callback: (range: Range) => void) {
export default function useOnSelectionChange(
inputSelector: string, callback: (range: Range) => void,
) {
useEffect(() => {
if (!container) return undefined;
const onSelectionChange = () => {
function onSelectionChange() {
const selection = window.getSelection();
if (!selection) return;
const inputEl = document.querySelector(inputSelector);
if (!inputEl) {
return;
}
for (let i = 0; i < selection.rangeCount; i++) {
const range = selection.getRangeAt(i);
const ancestor = range.commonAncestorContainer;
if (container.contains(ancestor)) {
if (inputEl.contains(ancestor)) {
callback(range);
}
}
};
}
document.addEventListener('selectionchange', onSelectionChange);
return () => document.removeEventListener('selectionchange', onSelectionChange);
}, [callback, container]);
}, [callback, inputSelector]);
}