diff --git a/frontend/apps/remark42/app/components/auth/auth.hooks.ts b/frontend/apps/remark42/app/components/auth/auth.hooks.ts index c5e62e65e1..1ea009d234 100644 --- a/frontend/apps/remark42/app/components/auth/auth.hooks.ts +++ b/frontend/apps/remark42/app/components/auth/auth.hooks.ts @@ -76,11 +76,11 @@ export function useDropdown(disableClosing?: boolean) { handleChangeIframeSize(dropdownElement); - const observer = new MutationObserver(() => { + const observer = new ResizeObserver(() => { handleChangeIframeSize(dropdownElement); }); - observer.observe(dropdownElement, { attributes: true, childList: true, subtree: true }); + observer.observe(dropdownElement); return () => { document.body.style.removeProperty('min-height'); diff --git a/frontend/apps/remark42/app/components/comment-form/comment-form.tsx b/frontend/apps/remark42/app/components/comment-form/comment-form.tsx index 26724553d7..bdc8f01103 100644 --- a/frontend/apps/remark42/app/components/comment-form/comment-form.tsx +++ b/frontend/apps/remark42/app/components/comment-form/comment-form.tsx @@ -19,7 +19,6 @@ import { SubscribeByRSS } from './__subscribe-by-rss'; import { MarkdownToolbar } from './markdown-toolbar'; import { TextExpander } from './text-expander'; import { updatePersistedComments, getPersistedComment, removePersistedComment } from './comment-form.persist'; -import { updateIframeHeight } from 'utils/post-message'; export type Props = { id: string; @@ -453,7 +452,6 @@ export class CommentForm extends Component { disabled={isDisabled} autofocus={!!autofocus} spellcheck={true} - onResize={updateIframeHeight} /> {charactersLeft < 100 && {charactersLeft}} diff --git a/frontend/apps/remark42/app/components/root/root.tsx b/frontend/apps/remark42/app/components/root/root.tsx index 9c9b978bd3..cf4989d96b 100644 --- a/frontend/apps/remark42/app/components/root/root.tsx +++ b/frontend/apps/remark42/app/components/root/root.tsx @@ -1,5 +1,5 @@ import { h, Component, Fragment } from 'preact'; -import { useEffect, useRef } from 'preact/hooks'; +import { useEffect } from 'preact/hooks'; import { useSelector } from 'react-redux'; import b from 'bem-react-helper'; import { IntlShape, useIntl, FormattedMessage, defineMessages } from 'react-intl'; @@ -36,12 +36,19 @@ import { ConnectedComment as Comment } from 'components/comment/connected-commen import { uploadImage, getPreview } from 'common/api'; import { isUserAnonymous } from 'utils/isUserAnonymous'; import { bindActions } from 'utils/actionBinder'; -import { postMessageToParent, parseMessage, updateIframeHeight } from 'utils/post-message'; +import { postMessageToParent, parseMessage } from 'utils/post-message'; import { useActions } from 'hooks/useAction'; import { setCollapse } from 'store/thread/actions'; import styles from './root.module.css'; +/** + * Sends size of the iframe to parent window + */ +export function updateIframeHeight() { + postMessageToParent({ height: document.body.offsetHeight }); +} + const mapStateToProps = (state: StoreState) => ({ sort: state.comments.sort, isCommentsLoading: state.comments.isFetching, @@ -294,33 +301,12 @@ interface CommentsProps { showMore(): void; } function Comments({ isLoading, topComments, commentsShown, showMore }: CommentsProps) { - const rootRef = useRef(null); - - useEffect(() => { - if (!rootRef.current) { - return; - } - - updateIframeHeight(); - // TODO: throttle updates - const observer = new MutationObserver(() => { - // a hacky way to force iframe height update when new image is rendered and loaded - rootRef.current?.querySelectorAll('img').forEach((img) => { - img.addEventListener('load', updateIframeHeight); - }); - }); - - observer.observe(rootRef.current, { attributes: true, childList: true, subtree: true }); - - return () => observer.disconnect(); - }, []); - const renderComments = IS_MOBILE && commentsShown < topComments.length ? topComments.slice(0, commentsShown) : topComments; const isShowMoreButtonVisible = IS_MOBILE && commentsShown < topComments.length; return ( -
+
{isLoading ? ( ) : ( @@ -358,6 +344,14 @@ export function ConnectedRoot() { const props = useSelector(mapStateToProps); const actions = useActions(boundActions); + useEffect(() => { + const observer = new ResizeObserver(updateIframeHeight); + + updateIframeHeight(); + observer.observe(document.body); + return () => observer.disconnect(); + }, []); + if (!window.remark_config) { throw new Error('Remark42: Config object is undefined'); } diff --git a/frontend/apps/remark42/app/components/textarea-autosize.tsx b/frontend/apps/remark42/app/components/textarea-autosize.tsx index ca9ea6c8a8..d8e33785cc 100644 --- a/frontend/apps/remark42/app/components/textarea-autosize.tsx +++ b/frontend/apps/remark42/app/components/textarea-autosize.tsx @@ -5,40 +5,33 @@ import { useEffect, useRef } from 'preact/hooks'; function autoResize(textarea: HTMLTextAreaElement, onResize?: () => void) { textarea.style.height = ''; textarea.style.height = `${textarea.scrollHeight}px`; - // Call on rezie callback after textarea height is changed - if (onResize) { - window.requestAnimationFrame(onResize); - } } type Props = Omit, 'onInput'> & { onInput?(evt: JSX.TargetedEvent): void; - onResize?(): void; }; -export const TextareaAutosize = forwardRef( - ({ onInput, value, onResize, ...props }, externalRef) => { - const localRef = useRef(null); - const ref = externalRef || localRef; +export const TextareaAutosize = forwardRef(({ onInput, value, ...props }, externalRef) => { + const localRef = useRef(null); + const ref = externalRef || localRef; - const handleInput: JSX.GenericEventHandler = (evt) => { - if (!ref.current) { - return; - } + const handleInput: JSX.GenericEventHandler = (evt) => { + if (!ref.current) { + return; + } - if (onInput) { - return onInput(evt); - } + if (onInput) { + return onInput(evt); + } - autoResize(ref.current, onResize); - }; + autoResize(ref.current); + }; - useEffect(() => { - if (ref.current) { - autoResize(ref.current, onResize); - } - }, [onResize, value, ref]); + useEffect(() => { + if (ref.current) { + autoResize(ref.current); + } + }, [value, ref]); - return