Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions apps/meteor/app/ui-utils/client/lib/LegacyRoomManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ function close(typeName: string) {

if (rid) {
RoomManager.close(rid);
return RoomHistoryManager.clear(rid);
return RoomHistoryManager.close(rid);
}
}
}
Expand Down Expand Up @@ -93,8 +93,6 @@ const computation = Tracker.autorun(() => {

const room = roomCoordinator.getRoomDirectives(type).findRoom(name);

void RoomHistoryManager.getMoreIfIsEmpty(record.rid);

if (room) {
if (record.streamActive !== true) {
void sdk
Expand Down
20 changes: 18 additions & 2 deletions apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ class RoomHistoryManagerClass extends Emitter {
return setTimeout(fn, 500 - difference);
}

public isLoaded(rid: IRoom['_id']) {
const room = this.getRoom(rid);
return room.loaded !== undefined;
}

private unqueue() {
const requestId = this.requestsList.pop();
if (!requestId) {
Expand Down Expand Up @@ -286,10 +291,15 @@ class RoomHistoryManagerClass extends Emitter {
return room.isLoading.get();
}

public close(rid: IRoom['_id']) {
Messages.remove({ rid });
delete this.histories[rid];
}

public clear(rid: IRoom['_id']) {
const room = this.getRoom(rid);
Messages.remove({ rid });
room.isLoading.set(true);
room.isLoading.set(false);
room.hasMore.set(true);
room.hasMoreNext.set(false);
room.oldestTs = undefined;
Expand All @@ -308,15 +318,21 @@ class RoomHistoryManagerClass extends Emitter {
}

const room = this.getRoom(message.rid);
this.clear(message.rid);

const subscription = Subscriptions.findOne({ rid: message.rid });

const result = await callWithErrorHandling('loadSurroundingMessages', message, defaultLimit);

this.clear(message.rid);

if (!result) {
return;
}
const { messages = [] } = result;

if (messages.length > 0) {
room.oldestTs = messages[messages.length - 1].ts;
}

await upsertMessageBulk({ msgs: Array.from(result.messages).filter((msg) => msg.t !== 'command'), subscription });

Expand Down
17 changes: 17 additions & 0 deletions apps/meteor/app/ui/client/views/app/lib/scrolling.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
export function isAtBottom(element: HTMLElement, scrollThreshold = 0): boolean {
return element.scrollTop + scrollThreshold >= element.scrollHeight - element.clientHeight;
}

// Mainly used for allow mock during testing

export const getBoundingClientRect = (ref: HTMLElement) => {
const { top, bottom, left, right } = ref.getBoundingClientRect();
const { scrollTop, scrollHeight, clientHeight } = ref;

return {
top,
bottom,
left,
right,
scrollTop,
scrollHeight,
clientHeight,
};
};
3 changes: 2 additions & 1 deletion apps/meteor/client/lib/utils/legacyJumpToMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export const legacyJumpToMessage = async (message: IMessage) => {
if (tab === 'thread' && (context === message.tmid || context === message._id)) {
return;
}

router.navigate(
{
name: router.getRouteName()!,
Expand All @@ -32,6 +31,8 @@ export const legacyJumpToMessage = async (message: IMessage) => {
},
{ replace: false },
);
await RoomHistoryManager.getSurroundingMessages(message);
Comment thread
kody-ai[bot] marked this conversation as resolved.

return;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,44 @@
import type { IMessage } from '@rocket.chat/core-typings';
import { useMergedRefs } from '@rocket.chat/fuselage-hooks';
import { useSafeRefCallback } from '@rocket.chat/ui-client';
import { useRouter } from '@rocket.chat/ui-contexts';
import { useCallback } from 'react';
import { useCallback, useRef } from 'react';

import { useMessageListJumpToMessageParam, useMessageListRef } from '../../../../components/message/list/MessageListContext';
import { setRef } from '../../composer/hooks/useMessageComposerMergedRefs';
import { setHighlightMessage, clearHighlightMessage } from '../providers/messageHighlightSubscription';

// this is an arbitrary value so that there's a gap between the header and the message;
/**
* That is completely messy, CustomScrollbars force us to initialize the scrollbars inside an effect
* all refCallbacks happen before the effect, more than that, the scrollbars also reset the scroll position
* so we need to check if the scrollbars are initialized and if there is any message to be highlighted
*/
Comment thread
MartinSchoeler marked this conversation as resolved.

export const useJumpToMessageImperative = () => {
const jumpToRef = useRef<HTMLDivElement>(null);
const containerRef = useRef<HTMLDivElement>(null);

const jumpToRefAction = useCallback(() => {
if (!jumpToRef.current || !containerRef.current) {
return;
}
jumpToRef.current.scrollIntoView({
block: 'center',
});
}, []);

return {
jumpToRef: useMergedRefs(jumpToRef, jumpToRefAction),
innerRef: useMergedRefs(containerRef, jumpToRefAction),
};
};

/**
* `listRef` is a reference to the message node in the message list.
* its shared between other hooks like `useLoadSurroundingMessages`, `useJumpToMessage`, `useGetMore`, `useListIsAtBottom` and `useRestoreScrollPosition`
* since each hook has a different concern, this ref helps each other aware if a message is being highlighted which changes the scroll position

*/

export const useJumpToMessage = (messageId: IMessage['_id']) => {
const jumpToMessageParam = useMessageListJumpToMessageParam();
Expand All @@ -27,10 +58,6 @@ export const useJumpToMessage = (messageId: IMessage['_id']) => {

setRef(listRef, node);

node.scrollIntoView({
behavior: 'smooth',
block: 'center',
});
const handleScroll = () => {
const { msg: _, ...search } = router.getSearchParameters();
router.navigate(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
import type { IMessage } from '@rocket.chat/core-typings';
import { useEndpoint } from '@rocket.chat/ui-contexts';
import { useEndpoint, useSearchParameter } from '@rocket.chat/ui-contexts';
import { useQueryClient } from '@tanstack/react-query';
import { useEffect } from 'react';
import { useEffect, useRef } from 'react';

import { legacyJumpToMessage } from '../../../../lib/utils/legacyJumpToMessage';

export const useLoadSurroundingMessages = (msgId?: IMessage['_id']) => {
export const useLoadSurroundingMessages = () => {
Comment thread
ggazzo marked this conversation as resolved.
const msgId = useSearchParameter('msg');
const jumpToRef = useRef<HTMLElement>(undefined);

const queryClient = useQueryClient();
const getMessage = useEndpoint('GET', '/v1/chat.getMessage');

useEffect(() => {
if (!msgId) {
return;
}

if (jumpToRef.current) {
return;
}

const abort = new AbortController();

queryClient
Expand All @@ -36,4 +44,6 @@ export const useLoadSurroundingMessages = (msgId?: IMessage['_id']) => {
abort.abort();
};
}, [msgId, queryClient, getMessage]);

return { jumpToRef };
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { useChat } from '../../contexts/ChatContext';
import { useRoom, useRoomSubscription } from '../../contexts/RoomContext';
import { useAutoTranslate } from '../hooks/useAutoTranslate';
import { useKatex } from '../hooks/useKatex';
import { useLoadSurroundingMessages } from '../hooks/useLoadSurroundingMessages';

type MessageListProviderProps = {
children: ReactNode;
Expand Down Expand Up @@ -62,8 +61,6 @@ const MessageListProvider = ({ children, messageListRef, attachmentDimension }:
const hasSubscription = Boolean(subscription);
const msgParameter = useSearchParameter('msg');

useLoadSurroundingMessages(msgParameter);

const chat = useChat();

const context: MessageListContextValue = useMemo(
Expand Down
21 changes: 17 additions & 4 deletions apps/meteor/client/views/room/body/RoomBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import { useListIsAtBottom } from './hooks/useListIsAtBottom';
import { useQuoteMessageByUrl } from './hooks/useQuoteMessageByUrl';
import { useRestoreScrollPosition } from './hooks/useRestoreScrollPosition';
import { useHandleUnread } from './hooks/useUnreadMessages';
import { useJumpToMessageImperative } from '../MessageList/hooks/useJumpToMessage';
import { useLoadSurroundingMessages } from '../MessageList/hooks/useLoadSurroundingMessages';

const RoomBody = (): ReactElement => {
const chat = useChat();
Expand Down Expand Up @@ -81,6 +83,10 @@ const RoomBody = (): ReactElement => {
return subscribed;
}, [allowAnonymousRead, canPreviewChannelRoom, room, subscribed]);

const { jumpToRef: jumpToRefGetMoreImperative, innerRef: jumpToRefGetMoreImperativeInnerRef } = useJumpToMessageImperative();

const { jumpToRef: surroundingMessagesJumpTpRef } = useLoadSurroundingMessages();

const {
wrapperRef: unreadBarWrapperRef,
innerRef: unreadBarInnerRef,
Expand All @@ -102,7 +108,15 @@ const RoomBody = (): ReactElement => {

const { innerRef: getMoreInnerRef, jumpToRef: jumpToRefGetMore } = useGetMore(room._id, atBottomRef);

const jumpToRef = useMergedRefs(jumpToRefGetMore, jumpToRefIsAtBottom);
const { innerRef: restoreScrollPositionInnerRef, jumpToRef: jumpToRefRestoreScrollPosition } = useRestoreScrollPosition(room._id);

const jumpToRef = useMergedRefs(
jumpToRefGetMore,
jumpToRefIsAtBottom,
jumpToRefRestoreScrollPosition,
surroundingMessagesJumpTpRef,
jumpToRefGetMoreImperative,
);

const {
uploads,
Expand All @@ -111,8 +125,6 @@ const RoomBody = (): ReactElement => {
targeDrop: [fileUploadTriggerProps, fileUploadOverlayProps],
} = useFileUpload();

const { innerRef: restoreScrollPositionInnerRef } = useRestoreScrollPosition();

const { messageListRef } = useMessageListNavigation();
const { innerRef: selectAndScrollRef, selectAllAndScrollToTop } = useSelectAllAndScrollToTop();

Expand All @@ -132,6 +144,7 @@ const RoomBody = (): ReactElement => {
getMoreInnerRef,
selectAndScrollRef,
messageListRef,
jumpToRefGetMoreImperativeInnerRef,
);

const wrapperBoxRefs = useMergedRefs(unreadBarWrapperRef);
Expand Down Expand Up @@ -237,7 +250,7 @@ const RoomBody = (): ReactElement => {
.join(' ')}
>
<MessageListErrorBoundary>
<CustomScrollbars ref={innerRef}>
<CustomScrollbars ref={innerRef} key={room._id}>
<ul className='messages-list' aria-label={t('Message_list')} aria-busy={isLoadingMoreMessages}>
{canPreview ? (
<>
Expand Down
21 changes: 17 additions & 4 deletions apps/meteor/client/views/room/body/RoomBodyV2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import { useListIsAtBottom } from './hooks/useListIsAtBottom';
import { useRestoreScrollPosition } from './hooks/useRestoreScrollPosition';
import { useSelectAllAndScrollToTop } from './hooks/useSelectAllAndScrollToTop';
import { useHandleUnread } from './hooks/useUnreadMessages';
import { useJumpToMessageImperative } from '../MessageList/hooks/useJumpToMessage';
import { useLoadSurroundingMessages } from '../MessageList/hooks/useLoadSurroundingMessages';

const RoomBody = (): ReactElement => {
const chat = useChat();
Expand Down Expand Up @@ -81,6 +83,10 @@ const RoomBody = (): ReactElement => {
return subscribed;
}, [allowAnonymousRead, canPreviewChannelRoom, room, subscribed]);

const { jumpToRef: jumpToRefGetMoreImperative, innerRef: jumpToRefGetMoreImperativeInnerRef } = useJumpToMessageImperative();

const { jumpToRef: surroundingMessagesJumpTpRef } = useLoadSurroundingMessages();

const {
wrapperRef,
innerRef: unreadBarInnerRef,
Expand All @@ -102,7 +108,15 @@ const RoomBody = (): ReactElement => {

const { innerRef: getMoreInnerRef, jumpToRef: jumpToRefGetMore } = useGetMore(room._id, atBottomRef);

const jumpToRef = useMergedRefs(jumpToRefIsAtBottom, jumpToRefGetMore);
const { innerRef: restoreScrollPositionInnerRef, jumpToRef: jumpToRefRestoreScrollPosition } = useRestoreScrollPosition(room._id);

const jumpToRef = useMergedRefs(
jumpToRefIsAtBottom,
jumpToRefGetMore,
jumpToRefRestoreScrollPosition,
jumpToRefGetMoreImperative,
surroundingMessagesJumpTpRef,
);

const {
uploads,
Expand All @@ -111,8 +125,6 @@ const RoomBody = (): ReactElement => {
targeDrop: [fileUploadTriggerProps, fileUploadOverlayProps],
} = useFileUpload();

const { innerRef: restoreScrollPositionInnerRef } = useRestoreScrollPosition();

const { messageListRef } = useMessageListNavigation();
const { innerRef: selectAndScrollRef, selectAllAndScrollToTop } = useSelectAllAndScrollToTop();

Expand All @@ -132,6 +144,7 @@ const RoomBody = (): ReactElement => {
getMoreInnerRef,
selectAndScrollRef,
messageListRef,
jumpToRefGetMoreImperativeInnerRef,
);

const handleNavigateToPreviousMessage = useCallback((): void => {
Expand Down Expand Up @@ -240,7 +253,7 @@ const RoomBody = (): ReactElement => {
.join(' ')}
>
<MessageListErrorBoundary>
<CustomScrollbars ref={innerRef}>
<CustomScrollbars ref={innerRef} key={room._id}>
<ul className='messages-list' aria-label={t('Message_list')} aria-busy={isLoadingMoreMessages}>
{canPreview ? (
<>
Expand Down
Loading