diff --git a/app/markdown/lib/parser/marked/marked.js b/app/markdown/lib/parser/marked/marked.js index e6923893b335d..f930a3369bb92 100644 --- a/app/markdown/lib/parser/marked/marked.js +++ b/app/markdown/lib/parser/marked/marked.js @@ -103,7 +103,6 @@ export const marked = (message, { smartLists, smartypants, renderer, - sanitize: true, highlight, }); diff --git a/app/ui/client/views/app/room.js b/app/ui/client/views/app/room.js index 0b5f67f5aa330..ece88045b661b 100644 --- a/app/ui/client/views/app/room.js +++ b/app/ui/client/views/app/room.js @@ -766,7 +766,7 @@ Meteor.startup(() => { } }; - this.sendToBottomIfNecessaryDebounced = () => {}; + this.sendToBottomIfNecessaryDebounced = _.debounce(this.sendToBottomIfNecessary, 10); }); // Update message to re-render DOM Template.roomOld.onDestroyed(function() { @@ -820,7 +820,6 @@ Meteor.startup(() => { template.atBottom = template.isAtBottom(100); }; - template.sendToBottomIfNecessaryDebounced = _.debounce(template.sendToBottomIfNecessary, 150); if (window.MutationObserver) { template.observer = new MutationObserver(() => template.sendToBottomIfNecessaryDebounced()); diff --git a/client/components/Message/Attachments/index.tsx b/client/components/Message/Attachments/index.tsx index 44740f535c1a6..7b0ab3b6406ab 100644 --- a/client/components/Message/Attachments/index.tsx +++ b/client/components/Message/Attachments/index.tsx @@ -3,6 +3,7 @@ import React, { FC, memo } from 'react'; import { QuoteAttachment, QuoteAttachmentProps } from './QuoteAttachment'; import { FileAttachmentProps, isFileAttachment, FileAttachment } from './Files'; import { DefaultAttachment, DefaultAttachmentProps } from './DefaultAttachment'; +import { useBlockRendered } from '../hooks/useBlockRendered'; export type FileProp = { _id: string; @@ -28,6 +29,9 @@ const Item: FC<{attachment: AttachmentProps; file?: FileProp }> = memo(({ attach return ; }); -const Attachments: FC<{ attachments: Array; file?: FileProp}> = ({ attachments = null, file }): any => attachments && attachments.map((attachment, index) => ); +const Attachments: FC<{ attachments: Array; file?: FileProp}> = ({ attachments = null, file }): any => { + const { className, ref } = useBlockRendered(); + return <>
{attachments && attachments.map((attachment, index) => )}; +}; export default Attachments; diff --git a/client/components/Message/Metrics/Broadcast.tsx b/client/components/Message/Metrics/Broadcast.tsx index 2849884913fc3..a445dbfe7e78a 100644 --- a/client/components/Message/Metrics/Broadcast.tsx +++ b/client/components/Message/Metrics/Broadcast.tsx @@ -2,6 +2,7 @@ import React, { FC } from 'react'; import { useTranslation } from '../../../contexts/TranslationContext'; import { Reply, Content } from '..'; +import { useBlockRendered } from '../hooks/useBlockRendered'; type BroadcastOptions = { @@ -12,7 +13,10 @@ type BroadcastOptions = { const BroadcastMetric: FC = ({ username, mid, replyBroadcast }) => { const t = useTranslation(); + const { className, ref } = useBlockRendered(); + return +
{t('Reply')} ; }; diff --git a/client/components/Message/Metrics/Discussion.tsx b/client/components/Message/Metrics/Discussion.tsx index 630e7138151ba..bc526daafcac9 100644 --- a/client/components/Message/Metrics/Discussion.tsx +++ b/client/components/Message/Metrics/Discussion.tsx @@ -3,6 +3,7 @@ import React, { FC } from 'react'; import { useTranslation } from '../../../contexts/TranslationContext'; import { useTimeAgo } from '../../../hooks/useTimeAgo'; import Metrics, { Reply, Content } from '..'; +import { useBlockRendered } from '../hooks/useBlockRendered'; type DicussionOptions = { @@ -16,7 +17,10 @@ type DicussionOptions = { const DiscussionMetric: FC = ({ lm, count, rid, drid, openDiscussion }) => { const t = useTranslation(); const format = useTimeAgo(); + const { className, ref } = useBlockRendered(); + return +
{count ? t('message_counter', { counter: count, count }) : t('Reply')} diff --git a/client/components/Message/Metrics/Thread.tsx b/client/components/Message/Metrics/Thread.tsx index 73e3d22182192..89b2aebabd4b8 100644 --- a/client/components/Message/Metrics/Thread.tsx +++ b/client/components/Message/Metrics/Thread.tsx @@ -6,6 +6,7 @@ import { useTimeAgo } from '../../../hooks/useTimeAgo'; import * as NotificationStatus from '../NotificationStatus'; import { followStyle, anchor } from '../helpers/followSyle'; import Metrics, { Reply, Content } from '..'; +import { useBlockRendered } from '../hooks/useBlockRendered'; type ThreadReplyOptions = { @@ -24,6 +25,8 @@ type ThreadReplyOptions = { const ThreadMetric: FC = ({ unread, mention, all, rid, mid, counter, participants, following, lm, openThread }) => { const t = useTranslation(); + const { className, ref } = useBlockRendered(); + const followMessage = useEndpoint('POST', 'chat.followMessage'); const unfollowMessage = useEndpoint('POST', 'chat.unfollowMessage'); const format = useTimeAgo(); @@ -31,6 +34,7 @@ const ThreadMetric: FC = ({ unread, mention, all, rid, mid, const handleFollow = useCallback(() => (following ? unfollowMessage({ mid }) : followMessage({ mid })), [followMessage, following, mid, unfollowMessage]); return +
{t('Reply')} diff --git a/client/components/Message/hooks/useBlockRendered.js b/client/components/Message/hooks/useBlockRendered.js new file mode 100644 index 0000000000000..f5032aac52411 --- /dev/null +++ b/client/components/Message/hooks/useBlockRendered.js @@ -0,0 +1,9 @@ +import { useRef, useEffect } from 'react'; + +export const useBlockRendered = () => { + const ref = useRef(); + useEffect(() => { + ref.current.dispatchEvent(new Event('rendered')); + }, []); + return { className: 'js-block-wrapper', ref }; +};