Skip to content

Commit

Permalink
chore: remove hardcoded position for message date (#31866)
Browse files Browse the repository at this point in the history
  • Loading branch information
ggazzo authored Mar 1, 2024
1 parent 299aa15 commit 48d0410
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 45 deletions.
15 changes: 7 additions & 8 deletions apps/meteor/client/views/room/body/RoomBody.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { IMessage, IUser } from '@rocket.chat/core-typings';
import { isEditedMessage } from '@rocket.chat/core-typings';
import { Box, Bubble } from '@rocket.chat/fuselage';
import { useMergedRefs } from '@rocket.chat/fuselage-hooks';
import {
usePermission,
useRole,
Expand Down Expand Up @@ -57,8 +58,6 @@ import { useRestoreScrollPosition } from './hooks/useRestoreScrollPosition';
import { useRetentionPolicy } from './hooks/useRetentionPolicy';
import { useUnreadMessages } from './hooks/useUnreadMessages';

const BUBBLE_OFFSET = 8;

const RoomBody = (): ReactElement => {
const formatDate = useFormatDate();
const t = useTranslation();
Expand All @@ -70,7 +69,7 @@ const RoomBody = (): ReactElement => {
const subscription = useRoomSubscription();

const { list } = useDateListController();
const { listStyle, bubbleDate, onScroll: handleDateOnScroll, showBubble, style: bubbleDateStyle } = useDateScroll(BUBBLE_OFFSET);
const { callbackRef, listStyle, bubbleDate, showBubble, style: bubbleDateStyle } = useDateScroll();

const [lastMessageDate, setLastMessageDate] = useState<Date | undefined>();
const [hideLeaderHeader, setHideLeaderHeader] = useState(false);
Expand Down Expand Up @@ -390,14 +389,12 @@ const RoomBody = (): ReactElement => {

wrapper.addEventListener('scroll', updateUnreadCount);
wrapper.addEventListener('scroll', handleWrapperScroll);
wrapper.addEventListener('scroll', () => handleDateOnScroll(list));

return () => {
wrapper.removeEventListener('scroll', updateUnreadCount);
wrapper.removeEventListener('scroll', handleWrapperScroll);
wrapper.removeEventListener('scroll', () => handleDateOnScroll(list));
};
}, [_isAtBottom, handleDateOnScroll, list, room._id, setUnreadCount]);
}, [_isAtBottom, list, room._id, setUnreadCount]);

useEffect(() => {
const wrapper = wrapperRef.current;
Expand Down Expand Up @@ -549,6 +546,8 @@ const RoomBody = (): ReactElement => {

const { messageListRef, messageListProps } = useMessageListNavigation();

const ref = useMergedRefs(callbackRef, wrapperRef);

return (
<>
{!isLayoutEmbedded && room.announcement && <Announcement announcement={room.announcement} announcementDetails={undefined} />}
Expand All @@ -559,7 +558,7 @@ const RoomBody = (): ReactElement => {
onClick={hideFlexTab && handleCloseFlexTab}
>
<div className='messages-container-wrapper'>
<div className='messages-container-main' {...fileUploadTriggerProps}>
<div className='messages-container-main' ref={callbackRef} {...fileUploadTriggerProps}>
<DropTargetOverlay {...fileUploadOverlayProps} />
<div className={['container-bars', uploads.length && 'show'].filter(isTruthy).join(' ')}>
{uploads.map((upload) => (
Expand Down Expand Up @@ -623,7 +622,7 @@ const RoomBody = (): ReactElement => {
.join(' ')}
>
<MessageListErrorBoundary>
<CustomScrollbars ref={wrapperRef}>
<CustomScrollbars ref={ref}>
<ul
ref={messageListRef}
className='messages-list'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,16 @@ const ThreadChat = ({ mainMessage }: ThreadChatProps) => {
<ContextualbarContent flexShrink={1} flexGrow={1} paddingInline={0} {...fileUploadTriggerProps}>
<DateListProvider>
<DropTargetOverlay {...fileUploadOverlayProps} />
<Box is='section' display='flex' flexDirection='column' flexGrow={1} flexShrink={1} flexBasis='auto' height='full'>
<Box
is='section'
position='relative'
display='flex'
flexDirection='column'
flexGrow={1}
flexShrink={1}
flexBasis='auto'
height='full'
>
<MessageListErrorBoundary>
<ThreadMessageList mainMessage={mainMessage} />
</MessageListErrorBoundary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,11 @@ import { useDateScroll } from '../../../hooks/useDateScroll';
import { useFirstUnreadMessageId } from '../../../hooks/useFirstUnreadMessageId';
import { useMessageListNavigation } from '../../../hooks/useMessageListNavigation';
import { useScrollMessageList } from '../../../hooks/useScrollMessageList';
import { useDateListController } from '../../../providers/DateListProvider';
import { useLegacyThreadMessageJump } from '../hooks/useLegacyThreadMessageJump';
import { useLegacyThreadMessageListScrolling } from '../hooks/useLegacyThreadMessageListScrolling';
import { useLegacyThreadMessages } from '../hooks/useLegacyThreadMessages';
import { ThreadMessageItem } from './ThreadMessageItem';

const BUBBLE_OFFSET = 64;

const isMessageSequential = (current: IMessage, previous: IMessage | undefined, groupingRange: number): boolean => {
if (!previous) {
return false;
Expand Down Expand Up @@ -54,8 +51,7 @@ type ThreadMessageListProps = {

const ThreadMessageList = ({ mainMessage }: ThreadMessageListProps): ReactElement => {
const formatDate = useFormatDate();
const { list } = useDateListController();
const { listStyle, bubbleDate, onScroll: handleDateOnScroll, showBubble, style: bubbleDateStyle } = useDateScroll(BUBBLE_OFFSET);
const { callbackRef, listStyle, bubbleDate, showBubble, style: bubbleDateStyle } = useDateScroll();

const { messages, loading } = useLegacyThreadMessages(mainMessage._id);
const {
Expand All @@ -74,6 +70,8 @@ const ThreadMessageList = ({ mainMessage }: ThreadMessageListProps): ReactElemen
const { messageListRef, messageListProps } = useMessageListNavigation();
const listRef = useMergedRefs<HTMLElement | null>(listScrollRef, listJumpRef, messageListRef);

const scrollRef = useMergedRefs<HTMLElement | null>(callbackRef, listWrapperScrollRef);

return (
<div className={['thread-list js-scroll-thread', hideUsernames && 'hide-usernames'].filter(isTruthy).join(' ')}>
{bubbleDate && (
Expand All @@ -84,10 +82,9 @@ const ThreadMessageList = ({ mainMessage }: ThreadMessageListProps): ReactElemen
</Box>
)}
<CustomScrollbars
ref={listWrapperScrollRef}
ref={scrollRef}
onScroll={(args) => {
handleScroll(args);
handleDateOnScroll(list);
}}
style={{ scrollBehavior: 'smooth', overflowX: 'hidden' }}
>
Expand Down
73 changes: 44 additions & 29 deletions apps/meteor/client/views/room/hooks/useDateScroll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,43 @@ import { useSafely } from '@rocket.chat/fuselage-hooks';
import { useCallback, useState } from 'react';

import { withThrottling } from '../../../../lib/utils/highOrderFunctions';
import { useDateListController } from '../providers/DateListProvider';

type useDateScrollReturn = {
bubbleDate: string | undefined;
onScroll: (list: Set<HTMLElement>) => void;
style: ReturnType<typeof css>;
callbackRef: (node: HTMLElement | null) => void;
style?: ReturnType<typeof css>;
showBubble: boolean;
listStyle?: ReturnType<typeof css>;
};

export const useDateScroll = (offset = 0): useDateScrollReturn => {
export const useDateScroll = (margin = 8): useDateScrollReturn => {
const [bubbleDate, setBubbleDate] = useSafely(
useState<{
date: string;
show: boolean;
style?: ReturnType<typeof css>;
}>({
date: '',
show: false,
style: undefined,
}),
);

const onScroll = useCallback(
withThrottling({ wait: 30 })(
(() => {
const { list } = useDateListController();

const callbackRef = useCallback(
(node: HTMLElement | null) => {
if (!node) {
return;
}
const onScroll = (() => {
let timeout: ReturnType<typeof setTimeout>;
return (elements: Set<HTMLElement>) => {
return (elements: Set<HTMLElement>, offset: number) => {
clearTimeout(timeout);

const bubbleOffset = offset + 56;
const bubbleOffset = offset;

// Gets the first non visible message date and sets the bubble date to it
const [date, message] = [...elements].reduce((ret, message) => {
// Sanitize elements
Expand All @@ -49,16 +58,30 @@ export const useDateScroll = (offset = 0): useDateScrollReturn => {
}, [] as [string, HTMLElement] | []);

// We always keep the previous date if we don't have a new one, so when the bubble disappears it doesn't flicker

setBubbleDate(() => ({
date: '',
...(date && { date }),
show: Boolean(date),
style: css`
position: absolute;
top: ${margin}px;
left: 50%;
translate: -50%;
z-index: 1;
opacity: 0;
transition: opacity 0.6s;
&.bubble-visible {
opacity: 1;
}
`,
}));

if (message) {
const { top } = message.getBoundingClientRect();

if (top - offset > 0) {
if (top < offset && top > 0) {
return;
}
}
Expand All @@ -72,34 +95,26 @@ export const useDateScroll = (offset = 0): useDateScrollReturn => {
1000,
);
};
})(),
),
[offset],
})();
const fn = withThrottling({ wait: 30 })(() => {
const offset = node.getBoundingClientRect().top;
onScroll(list, offset);
});

node.addEventListener('scroll', fn, { passive: true });
},
[list, margin, setBubbleDate],
);

const dateBubbleStyle = css`
position: absolute;
top: ${offset}px;
left: 50%;
translate: -50%;
z-index: 1;
opacity: 0;
transition: opacity 0.6s;
&.bubble-visible {
opacity: 1;
}
`;

const listStyle =
bubbleDate.show && bubbleDate.date
? css`
position: relative;
& [data-time='${bubbleDate.date.replaceAll(/[-T:.]/g, '').substring(0, 8)}'] {
opacity: 0;
}
`
: undefined;

return { listStyle, bubbleDate: bubbleDate.date, onScroll, style: dateBubbleStyle, showBubble: Boolean(bubbleDate.show) };
return { callbackRef, listStyle, bubbleDate: bubbleDate.date, style: bubbleDate.style, showBubble: Boolean(bubbleDate.show) };
};

0 comments on commit 48d0410

Please sign in to comment.