Fix highlight bugs & maybe some perf issues

This commit is contained in:
Lim Chee Aun 2023-11-09 19:11:00 +08:00
parent dc2eb1163f
commit 82a9a7212d

View file

@ -7,7 +7,7 @@ import { useEffect, useMemo, useRef, useState } from 'preact/hooks';
import { useHotkeys } from 'react-hotkeys-hook'; import { useHotkeys } from 'react-hotkeys-hook';
import stringLength from 'string-length'; import stringLength from 'string-length';
import { uid } from 'uid/single'; import { uid } from 'uid/single';
import { useDebouncedCallback } from 'use-debounce'; import { useDebouncedCallback, useThrottledCallback } from 'use-debounce';
import { useSnapshot } from 'valtio'; import { useSnapshot } from 'valtio';
import supportedLanguages from '../data/status-supported-languages'; import supportedLanguages from '../data/status-supported-languages';
@ -132,13 +132,12 @@ function highlightText(text, { maxCharacters = Infinity }) {
let leftoverHTML = ''; let leftoverHTML = '';
if (composerCharacterCount > maxCharacters) { if (composerCharacterCount > maxCharacters) {
const leftoverCount = composerCharacterCount - maxCharacters; const leftoverCount = composerCharacterCount - maxCharacters;
leftoverHTML = html.slice(-leftoverCount);
html = html.slice(0, -leftoverCount);
// Highlight exceeded characters // Highlight exceeded characters
leftoverHTML = leftoverHTML.replace( leftoverHTML =
new RegExp(`(.{${leftoverCount}})$`), '<mark class="compose-highlight-exceeded">' +
'<mark class="compose-highlight-exceeded">$1</mark>', html.slice(-leftoverCount) +
); '</mark>';
html = html.slice(0, -leftoverCount);
} }
html = html html = html
@ -1270,7 +1269,8 @@ function autoResizeTextarea(textarea) {
// NOTE: This check is needed because the offsetHeight return 50000 (really large number) on first render // NOTE: This check is needed because the offsetHeight return 50000 (really large number) on first render
// No idea why it does that, will re-investigate in far future // No idea why it does that, will re-investigate in far future
const offset = offsetHeight - clientHeight; const offset = offsetHeight - clientHeight;
textarea.style.height = value ? scrollHeight + offset + 'px' : null; const height = value ? scrollHeight + offset + 'px' : null;
textarea.style.height = height;
} }
} }
@ -1467,7 +1467,26 @@ const Textarea = forwardRef((props, ref) => {
}; };
}, []); }, []);
useEffect(() => {
// Resize observer for textarea
const textarea = ref.current;
if (!textarea) return;
const resizeObserver = new ResizeObserver(() => {
// Get height of textarea, set height to textExpander
const { height } = textarea.getBoundingClientRect();
textExpanderRef.current.style.height = height + 'px';
});
resizeObserver.observe(textarea);
}, []);
const composeHighlightRef = useRef(); const composeHighlightRef = useRef();
const throttleHighlightText = useThrottledCallback((text) => {
composeHighlightRef.current.innerHTML =
highlightText(text, {
maxCharacters,
}) + '\n';
// Newline to prevent multiple line breaks at the end from being collapsed, no idea why
}, 500);
return ( return (
<text-expander <text-expander
@ -1530,11 +1549,7 @@ const Textarea = forwardRef((props, ref) => {
setText(text); setText(text);
autoResizeTextarea(target); autoResizeTextarea(target);
props.onInput?.(e); props.onInput?.(e);
composeHighlightRef.current.innerHTML = throttleHighlightText(text);
highlightText(text, {
maxCharacters,
}) + '\n';
// Newline to prevent multiple line breaks at the end from being collapsed, no idea why
}} }}
style={{ style={{
width: '100%', width: '100%',