Skip to content

Commit

Permalink
fix: review
Browse files Browse the repository at this point in the history
Co-authored-by: gabriellsh <[email protected]>
  • Loading branch information
dougfabris and gabriellsh committed Dec 11, 2024
1 parent ced342f commit 4e000f1
Show file tree
Hide file tree
Showing 10 changed files with 76 additions and 69 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createContext, useCallback, useContext } from 'react';
import { createContext, useCallback, useContext, useEffect } from 'react';
import { useSyncExternalStore } from 'use-sync-external-store/shim';

import { selectedMessageStore } from '../../providers/SelectedMessagesProvider';
Expand All @@ -21,7 +21,19 @@ export const useIsSelectedMessage = (mid: string): boolean => {

const getSnapshot = (): boolean => selectedMessageStore.isSelected(mid);

return useSyncExternalStore(subscribe, getSnapshot);
const isSelected = useSyncExternalStore(subscribe, getSnapshot);

useEffect(() => {
if (isSelected) {
return;
}

selectedMessageStore.addAvailableMessage(mid);

return () => selectedMessageStore.removeAvailableMessage(mid);
}, [mid, selectedMessageStore, isSelected]);

return isSelected;
};

export const useIsSelecting = (): boolean => {
Expand Down Expand Up @@ -71,15 +83,15 @@ export const useCountSelected = (): number => {
return useSyncExternalStore(subscribe, getSnapshot);
};

export const useSelectedMessages = (): string[] => {
export const useAvailableMessagesCount = () => {
const { selectedMessageStore } = useContext(SelectedMessageContext);

const subscribe = useCallback(
(callback: () => void): (() => void) => selectedMessageStore.on('change', callback),
[selectedMessageStore],
);

const getSnapshot = () => selectedMessageStore.getSelectedMessages();
const getSnapshot = () => selectedMessageStore.availableMessagesCount();

return useSyncExternalStore(subscribe, getSnapshot);
};
8 changes: 5 additions & 3 deletions apps/meteor/client/views/room/body/RoomBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import { useListIsAtBottom } from './hooks/useListIsAtBottom';
import { useQuoteMessageByUrl } from './hooks/useQuoteMessageByUrl';
import { useReadMessageWindowEvents } from './hooks/useReadMessageWindowEvents';
import { useRestoreScrollPosition } from './hooks/useRestoreScrollPosition';
import { useSelectAllAndScrollToTop } from './hooks/useSelectAllAndScrollToTop';
import { useHandleUnread } from './hooks/useUnreadMessages';

const RoomBody = (): ReactElement => {
Expand Down Expand Up @@ -102,7 +103,7 @@ const RoomBody = (): ReactElement => {

const { innerRef: isAtBottomInnerRef, atBottomRef, sendToBottom, sendToBottomIfNecessary, isAtBottom } = useListIsAtBottom();

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

const { wrapperRef: leaderBannerWrapperRef, hideLeaderHeader, innerRef: leaderBannerInnerRef } = useLeaderBanner();

Expand All @@ -116,6 +117,7 @@ const RoomBody = (): ReactElement => {
const { innerRef: restoreScrollPositionInnerRef } = useRestoreScrollPosition(room._id);

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

const { handleNewMessageButtonClick, handleJumpToRecentButtonClick, handleComposerResize, hasNewMessages, newMessagesScrollRef } =
useHasNewMessages(room._id, user?._id, atBottomRef, {
Expand All @@ -133,7 +135,7 @@ const RoomBody = (): ReactElement => {
leaderBannerInnerRef,
unreadBarInnerRef,
getMoreInnerRef,

selectAndScrollRef,
messageListRef,
);

Expand Down Expand Up @@ -313,7 +315,7 @@ const RoomBody = (): ReactElement => {
onNavigateToPreviousMessage={handleNavigateToPreviousMessage}
onNavigateToNextMessage={handleNavigateToNextMessage}
onUploadFiles={handleUploadFiles}
onGetMore={handleGetMore}
onClickSelectAll={selectAllAndScrollToTop}
// TODO: send previewUrls param
// previewUrls={}
/>
Expand Down
8 changes: 5 additions & 3 deletions apps/meteor/client/views/room/body/RoomBodyV2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { useListIsAtBottom } from './hooks/useListIsAtBottom';
import { useQuoteMessageByUrl } from './hooks/useQuoteMessageByUrl';
import { useReadMessageWindowEvents } from './hooks/useReadMessageWindowEvents';
import { useRestoreScrollPosition } from './hooks/useRestoreScrollPosition';
import { useSelectAllAndScrollToTop } from './hooks/useSelectAllAndScrollToTop';
import { useHandleUnread } from './hooks/useUnreadMessages';

const RoomBody = (): ReactElement => {
Expand Down Expand Up @@ -97,7 +98,7 @@ const RoomBody = (): ReactElement => {

const { innerRef: isAtBottomInnerRef, atBottomRef, sendToBottom, sendToBottomIfNecessary, isAtBottom } = useListIsAtBottom();

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

const { wrapperRef: sectionWrapperRef, hideSection, innerRef: sectionScrollRef } = useBannerSection();

Expand All @@ -111,6 +112,7 @@ const RoomBody = (): ReactElement => {
const { innerRef: restoreScrollPositionInnerRef } = useRestoreScrollPosition(room._id);

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

const { handleNewMessageButtonClick, handleJumpToRecentButtonClick, handleComposerResize, hasNewMessages, newMessagesScrollRef } =
useHasNewMessages(room._id, user?._id, atBottomRef, {
Expand All @@ -128,7 +130,7 @@ const RoomBody = (): ReactElement => {
sectionScrollRef,
unreadBarInnerRef,
getMoreInnerRef,

selectAndScrollRef,
messageListRef,
);

Expand Down Expand Up @@ -285,7 +287,7 @@ const RoomBody = (): ReactElement => {
onNavigateToPreviousMessage={handleNavigateToPreviousMessage}
onNavigateToNextMessage={handleNavigateToNextMessage}
onUploadFiles={handleUploadFiles}
onGetMore={handleGetMore}
onClickSelectAll={selectAllAndScrollToTop}
// TODO: send previewUrls param
// previewUrls={}
/>
Expand Down
13 changes: 1 addition & 12 deletions apps/meteor/client/views/room/body/hooks/useGetMore.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,17 @@
import type { MutableRefObject } from 'react';
import { useCallback, useRef } from 'react';
import { useCallback } from 'react';

import { RoomHistoryManager } from '../../../../../app/ui-utils/client';
import { withThrottling } from '../../../../../lib/utils/highOrderFunctions';
import { useToggleSelectAll } from '../../MessageList/contexts/SelectedMessagesContext';

export const useGetMore = (rid: string, atBottomRef: MutableRefObject<boolean>) => {
const ref: MutableRefObject<HTMLElement | null> = useRef(null);
const handleToggleAll = useToggleSelectAll();

const handleGetMore = () => {
ref.current?.scrollTo({ top: 0, behavior: 'smooth' });
handleToggleAll();
};

return {
handleGetMore,
innerRef: useCallback(
(wrapper: HTMLElement | null) => {
if (!wrapper) {
return;
}

ref.current = wrapper;
let lastScrollTopRef = 0;

wrapper.addEventListener(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { useRef } from 'react';

import { useToggleSelectAll } from '../../MessageList/contexts/SelectedMessagesContext';

export const useSelectAllAndScrollToTop = () => {
const ref = useRef<HTMLElement>(null);
const handleToggleAll = useToggleSelectAll();

const selectAllAndScrollToTop = () => {
ref.current?.scrollTo({ top: 0, behavior: 'smooth' });
handleToggleAll();
};

return { innerRef: ref, selectAllAndScrollToTop };
};
2 changes: 1 addition & 1 deletion apps/meteor/client/views/room/composer/ComposerMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export type ComposerMessageProps = {
onNavigateToNextMessage?: () => void;
onNavigateToPreviousMessage?: () => void;
onUploadFiles?: (files: readonly File[]) => void;
onGetMore?: () => void;
onClickSelectAll?: () => void;
};

const ComposerMessage = ({ tmid, onSend, ...props }: ComposerMessageProps): ReactElement => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
import { Button, ButtonGroup } from '@rocket.chat/fuselage';
import { MessageFooterCallout, MessageFooterCalloutContent } from '@rocket.chat/ui-composer';
import type { ReactElement } from 'react';
import React, { useContext } from 'react';
import React from 'react';
import { useTranslation } from 'react-i18next';

import type { ComposerMessageProps } from './ComposerMessage';
import { useCountSelected, useClearSelection, SelectedMessageContext } from '../MessageList/contexts/SelectedMessagesContext';
import { useCountSelected, useClearSelection, useAvailableMessagesCount } from '../MessageList/contexts/SelectedMessagesContext';

const ComposerSelectMessages = ({ onGetMore }: ComposerMessageProps): ReactElement => {
const ComposerSelectMessages = ({ onClickSelectAll }: ComposerMessageProps): ReactElement => {
const { t } = useTranslation();

const { selectedMessageStore } = useContext(SelectedMessageContext);
const clearSelection = useClearSelection();
const countSelected = useCountSelected();
const countAvailable = selectedMessageStore.availableMessages.size;
const noMessagesAvailable = countAvailable <= countSelected;
const countAvailable = useAvailableMessagesCount();

return (
<MessageFooterCallout>
<MessageFooterCalloutContent textAlign='left'>{t('number_messages_selected', { count: countSelected })}</MessageFooterCalloutContent>
<MessageFooterCalloutContent textAlign='left'>
{t('__count__messages_selected', { count: countSelected })}
</MessageFooterCalloutContent>
<ButtonGroup>
<Button small disabled={countSelected === 0} onClick={clearSelection}>
{t('Clear_selection')}
</Button>
<Button icon='arrow-up' small primary disabled={noMessagesAvailable} onClick={onGetMore}>
{t('Select_number_messages', { count: countAvailable - countSelected })}
<Button icon='arrow-up' small primary disabled={countAvailable === 0} onClick={onClickSelectAll}>
{t('Select__count__messages', { count: countAvailable })}
</Button>
</ButtonGroup>
</MessageFooterCallout>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {
} from '../../../../components/Contextualbar';
import UserAutoCompleteMultiple from '../../../../components/UserAutoCompleteMultiple';
import { roomCoordinator } from '../../../../lib/rooms/roomCoordinator';
import { SelectedMessageContext, useSelectedMessages } from '../../MessageList/contexts/SelectedMessagesContext';
import { SelectedMessageContext, useCountSelected } from '../../MessageList/contexts/SelectedMessagesContext';
import { useRoom } from '../../contexts/RoomContext';
import { useRoomToolbox } from '../../contexts/RoomToolboxContext';

Expand Down Expand Up @@ -102,7 +102,7 @@ const ExportMessages = () => {
const downloadExportMutation = useDownloadExportMutation();

const { selectedMessageStore } = useContext(SelectedMessageContext);
const messages = useSelectedMessages();
const messageCount = useCountSelected();

const { type, toUsers } = watch();

Expand All @@ -125,10 +125,12 @@ const ExportMessages = () => {
setValue('format', 'json');
}

setValue('messagesCount', messages.length);
}, [type, setValue, messages.length]);
setValue('messagesCount', messageCount);
}, [type, setValue, messageCount]);

const handleExport = async ({ type, toUsers, dateFrom, dateTo, format, subject, additionalEmails }: ExportMessagesFormValues) => {
const messages = selectedMessageStore.getSelectedMessages();

if (type === 'download') {
return downloadExportMutation.mutateAsync({
mids: messages,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
import { Emitter } from '@rocket.chat/emitter';
import type { ReactNode } from 'react';
import React, { useEffect, useMemo } from 'react';
import React, { useMemo } from 'react';

import { SelectedMessageContext } from '../MessageList/contexts/SelectedMessagesContext';
import { useMessages } from '../MessageList/hooks/useMessages';
import { useRoom } from '../contexts/RoomContext';

// data-qa-select

export const selectedMessageStore = new (class SelectMessageStore extends Emitter<
{
Expand All @@ -16,17 +12,18 @@ export const selectedMessageStore = new (class SelectMessageStore extends Emitte
> {
store = new Set<string>();

private storeArray = Array.from(this.store);

availableMessages = new Set<string>();

isSelecting = false;

constructor() {
super();
this.on('change', () => {
this.storeArray = Array.from(this.store);
});
addAvailableMessage(mid: string): void {
this.availableMessages.add(mid);
this.emit('change');
}

removeAvailableMessage(mid: string): void {
this.availableMessages.delete(mid);
this.emit('change');
}

setIsSelecting(isSelecting: boolean): void {
Expand All @@ -43,7 +40,7 @@ export const selectedMessageStore = new (class SelectMessageStore extends Emitte
}

getSelectedMessages(): string[] {
return this.storeArray;
return Array.from(this.store);
}

toggle(mid: string): void {
Expand All @@ -58,20 +55,14 @@ export const selectedMessageStore = new (class SelectMessageStore extends Emitte
this.emit('change');
}

select(mid: string): void {
if (this.store.has(mid)) {
return;
}

this.store.add(mid);
this.emit(mid, true);
this.emit('change');
}

count(): number {
return this.store.size;
}

availableMessagesCount(): number {
return this.availableMessages.size;
}

clearStore(): void {
const selectedMessages = this.getSelectedMessages();
this.store.clear();
Expand All @@ -86,7 +77,8 @@ export const selectedMessageStore = new (class SelectMessageStore extends Emitte
}

toggleAll(mids: string[]): void {
mids.forEach((mid) => this.select(mid));
this.store = new Set([...this.store, ...mids]);
this.emit('change');
}
})();

Expand All @@ -95,13 +87,6 @@ type SelectedMessagesProviderProps = {
};

export const SelectedMessagesProvider = ({ children }: SelectedMessagesProviderProps) => {
const room = useRoom();
const messages = useMessages({ rid: room._id });

useEffect(() => {
selectedMessageStore.availableMessages = new Set(messages.map((message) => message._id));
}, [messages]);

const value = useMemo(
() => ({
selectedMessageStore,
Expand Down
4 changes: 2 additions & 2 deletions packages/i18n/src/locales/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -3775,7 +3775,7 @@
"Message_VideoRecorderEnabledDescription": "Requires 'video/webm' files to be an accepted media type within 'File Upload' settings.",
"messages": "messages",
"Messages": "Messages",
"number_messages_selected": "{{count}} messages selected",
"__count__messages_selected": "{{count}} messages selected",
"Messages_exported_successfully": "Messages exported successfully",
"Messages_sent": "Messages sent",
"Message_sent": "Message sent",
Expand Down Expand Up @@ -6688,7 +6688,7 @@
"Go_to_href": "Go to: {{href}}",
"Anyone_can_send_new_messages": "Anyone can send new messages",
"Select_messages_to_hide": "Select messages to hide",
"Select_number_messages": "Select {{count}} messages",
"Select__count__messages": "Select {{count}} messages",
"Name_cannot_have_special_characters": "Name cannot have spaces or special characters",
"Resize": "Resize",
"Zoom_out": "Zoom out",
Expand Down

0 comments on commit 4e000f1

Please sign in to comment.