Skip to content

Commit 9e5147a

Browse files
chore: messagebox split
1 parent f79f20b commit 9e5147a

4 files changed

Lines changed: 344 additions & 348 deletions

File tree

apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx

Lines changed: 40 additions & 170 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,34 @@
11
/* eslint-disable complexity */
22
import { isRoomFederated, isRoomNativeFederated, type IMessage, type ISubscription } from '@rocket.chat/core-typings';
33
import { useContentBoxSize, useStableCallback, useMediaQuery, useSafeRefCallback } from '@rocket.chat/fuselage-hooks';
4-
import {
5-
MessageComposerAction,
6-
MessageComposerToolbarActions,
7-
MessageComposer,
8-
MessageComposerToolbar,
9-
MessageComposerActionsDivider,
10-
MessageComposerToolbarSubmit,
11-
MessageComposerButton,
12-
MessageComposerInputExpandable,
13-
} from '@rocket.chat/ui-composer';
4+
import { MessageComposerInputExpandable } from '@rocket.chat/ui-composer';
145
import { useTranslation, useUserPreference, useLayout, useSetting } from '@rocket.chat/ui-contexts';
156
import { useMutation } from '@tanstack/react-query';
167
import type { MouseEvent, ClipboardEvent, ChangeEvent } from 'react';
178
import { memo, useRef, useReducer, useCallback, useSyncExternalStore } from 'react';
189

19-
import MessageBoxActionsToolbar from './MessageBoxActionsToolbar';
20-
import MessageBoxFormattingToolbar from './MessageBoxFormattingToolbar';
21-
import MessageBoxHint from './MessageBoxHint';
22-
import MessageBoxReplies from './MessageBoxReplies';
10+
import MessageBoxBase from './MessageBoxBase';
2311
import MessageComposerFiles from './MessageComposerFiles';
12+
import {
13+
emptySubscribe,
14+
getEmptyFalse,
15+
getEmptyArray,
16+
handleFormattingShortcut,
17+
extractImageFilesFromClipboard,
18+
} from './messageBoxHelpers';
2419
import { handleSelectionWrapping } from './wrapSelection';
2520
import { emoji } from '../../../../../app/emoji/client';
2621
import { createComposerAPI } from '../../../../../app/ui-message/client/messageBox/createComposerAPI';
27-
import type { FormattingButton } from '../../../../../app/ui-message/client/messageBox/messageBoxFormatting';
2822
import { formattingButtons } from '../../../../../app/ui-message/client/messageBox/messageBoxFormatting';
29-
import { getImageExtensionFromMime } from '../../../../../lib/getImageExtensionFromMime';
3023
import { useFormatDateAndTime } from '../../../../hooks/useFormatDateAndTime';
3124
import { useIsFederationEnabled } from '../../../../hooks/useIsFederationEnabled';
32-
import type { ComposerAPI } from '../../../../lib/chats/ChatAPI';
3325
import { roomCoordinator } from '../../../../lib/rooms/roomCoordinator';
3426
import { keyCodes } from '../../../../lib/utils/keyCodes';
3527
import { Subscriptions } from '../../../../stores';
36-
import AudioMessageRecorder from '../../../composer/AudioMessageRecorder';
37-
import VideoMessageRecorder from '../../../composer/VideoMessageRecorder';
3828
import { useFileUpload } from '../../body/hooks/useFileUpload';
3929
import { useChat } from '../../contexts/ChatContext';
4030
import { useComposerPopupOptions } from '../../contexts/ComposerPopupContext';
4131
import { useRoom, useRoomSubscription } from '../../contexts/RoomContext';
42-
import ComposerBoxPopup from '../ComposerBoxPopup';
43-
import ComposerBoxPopupPreview from '../ComposerBoxPopupPreview';
44-
import ComposerUserActionIndicator from '../ComposerUserActionIndicator';
4532
import { useAutoGrow } from '../RoomComposer/hooks/useAutoGrow';
4633
import { useComposerBoxPopup } from '../hooks/useComposerBoxPopup';
4734
import { useEnablePopupPreview } from '../hooks/useEnablePopupPreview';
@@ -56,31 +43,6 @@ const reducer = (_: unknown, event: ChangeEvent<HTMLInputElement>): boolean => {
5643
return Boolean(target.value.trim());
5744
};
5845

59-
const handleFormattingShortcut = (event: KeyboardEvent, formattingButtons: FormattingButton[], composer: ComposerAPI) => {
60-
const isMacOS = navigator.platform.indexOf('Mac') !== -1;
61-
const isCmdOrCtrlPressed = (isMacOS && event.metaKey) || (!isMacOS && event.ctrlKey);
62-
63-
if (!isCmdOrCtrlPressed) {
64-
return false;
65-
}
66-
67-
const key = event.key.toLowerCase();
68-
69-
const formatter = formattingButtons.find((formatter) => 'command' in formatter && formatter.command === key);
70-
71-
if (!formatter || !('pattern' in formatter)) {
72-
return false;
73-
}
74-
75-
composer.wrapSelection(formatter.pattern);
76-
return true;
77-
};
78-
79-
const emptySubscribe = () => () => undefined;
80-
const getEmptyFalse = () => false;
81-
const a: any[] = [];
82-
const getEmptyArray = () => a;
83-
8446
export type MessageBoxProps = {
8547
tmid?: IMessage['_id'];
8648
onSend?: (params: { value: string; tshow?: boolean; previewUrls?: string[]; isSlashCommandAllowed?: boolean }) => Promise<void>;
@@ -335,38 +297,7 @@ const MessageBox = ({
335297
});
336298

337299
const handlePaste = useStableCallback((event: ClipboardEvent<HTMLTextAreaElement>) => {
338-
const { clipboardData } = event;
339-
340-
if (!clipboardData) {
341-
return;
342-
}
343-
344-
const items = Array.from(clipboardData.items);
345-
346-
if (items.some(({ kind, type }) => kind === 'string' && type === 'text/plain')) {
347-
return;
348-
}
349-
350-
const files = items
351-
.filter((item) => item.kind === 'file' && item.type.indexOf('image/') !== -1)
352-
.map((item) => {
353-
const fileItem = item.getAsFile();
354-
355-
if (!fileItem) {
356-
return;
357-
}
358-
359-
const imageExtension = fileItem ? getImageExtensionFromMime(fileItem.type) : undefined;
360-
361-
const extension = imageExtension ? `.${imageExtension}` : '';
362-
363-
Object.defineProperty(fileItem, 'name', {
364-
writable: true,
365-
value: `Clipboard - ${format(new Date())}${extension}`,
366-
});
367-
return fileItem;
368-
})
369-
.filter((file): file is File => !!file);
300+
const files = extractImageFilesFromClipboard(event, format);
370301

371302
if (files.length) {
372303
event.preventDefault();
@@ -418,45 +349,33 @@ const MessageBox = ({
418349
const shouldPopupPreview = useEnablePopupPreview(popup.filter, popup.option);
419350

420351
return (
421-
<>
422-
{chat.composer?.quotedMessages && <MessageBoxReplies />}
423-
{shouldPopupPreview && popup.option && (
424-
<ComposerBoxPopup
425-
select={popup.select}
426-
items={popup.items}
427-
focused={popup.focused}
428-
title={popup.option.title}
429-
renderItem={popup.option.renderItem}
430-
/>
431-
)}
432-
{/*
433-
SlashCommand Preview popup works in a weird way
434-
There is only one trigger for all the commands: "/"
435-
After that we need to the slashcommand list and check if the command exists and provide the preview
436-
if not the query is `suspend` which means the slashcommand is not found or doesn't have a preview
437-
*/}
438-
{popup.option?.preview && (
439-
<ComposerBoxPopupPreview
440-
select={popup.select}
441-
items={popup.items as any}
442-
focused={popup.focused as any}
443-
title={popup.option.title}
444-
renderItem={popup.option.renderItem}
445-
ref={popup.commandsRef}
446-
rid={room._id}
447-
tmid={tmid}
448-
suspended={popup.suspended}
449-
/>
450-
)}
451-
<MessageBoxHint
452-
isEditing={isEditing}
453-
e2eEnabled={e2eEnabled}
454-
unencryptedMessagesAllowed={unencryptedMessagesAllowed}
455-
isMobile={isMobile}
456-
/>
457-
{isRecordingVideo && <VideoMessageRecorder reference={messageComposerRef} rid={room._id} tmid={tmid} />}
458-
<MessageComposer ref={messageComposerRef} variant={isEditing ? 'editing' : undefined}>
459-
{isRecordingAudio && <AudioMessageRecorder rid={room._id} isMicrophoneDenied={isMicrophoneDenied} />}
352+
<MessageBoxBase
353+
rid={room._id}
354+
tmid={tmid}
355+
composer={chat.composer}
356+
messageComposerRef={messageComposerRef}
357+
popup={popup}
358+
shouldPopupPreview={shouldPopupPreview}
359+
isEditing={isEditing}
360+
isRecording={isRecording}
361+
isRecordingAudio={isRecordingAudio}
362+
isRecordingVideo={isRecordingVideo}
363+
isMicrophoneDenied={isMicrophoneDenied}
364+
formatters={formatters}
365+
canSend={canSend}
366+
useEmojis={useEmojis}
367+
sendEnabled={canSend && !isUploading && !isProcessingUploads && (typing || isEditing || hasUploads)}
368+
sendActive={typing || isEditing || hasUploads}
369+
inlineSize={sizes.inlineSize}
370+
e2eEnabled={e2eEnabled}
371+
unencryptedMessagesAllowed={unencryptedMessagesAllowed}
372+
isMobile={isMobile}
373+
joinPending={joinMutation.isPending}
374+
onEmojiClick={handleOpenEmojiPicker}
375+
onSend={handleSendMessage}
376+
onJoin={onJoin}
377+
closeEditing={closeEditing}
378+
input={
460379
<MessageComposerInputExpandable
461380
dimensions={sizes}
462381
ref={mergedRefs}
@@ -469,58 +388,9 @@ const MessageBox = ({
469388
onPaste={handlePaste}
470389
aria-activedescendant={popup.focused ? `popup-item-${popup.focused._id}` : undefined}
471390
/>
472-
<MessageComposerFiles />
473-
<MessageComposerToolbar>
474-
<MessageComposerToolbarActions aria-label={t('Message_composer_toolbox_primary_actions')}>
475-
<MessageComposerAction
476-
icon='emoji'
477-
disabled={!useEmojis || isRecording || !canSend}
478-
onClick={handleOpenEmojiPicker}
479-
title={t('Emoji')}
480-
/>
481-
<MessageComposerActionsDivider />
482-
{chat.composer && formatters.length > 0 && (
483-
<MessageBoxFormattingToolbar
484-
composer={chat.composer}
485-
variant={sizes.inlineSize < 480 ? 'small' : 'large'}
486-
items={formatters}
487-
disabled={isRecording || !canSend}
488-
/>
489-
)}
490-
<MessageBoxActionsToolbar
491-
canSend={canSend}
492-
isMicrophoneDenied={isMicrophoneDenied}
493-
rid={room._id}
494-
tmid={tmid}
495-
isRecording={isRecording}
496-
variant={sizes.inlineSize < 480 ? 'small' : 'large'}
497-
isEditing={isEditing}
498-
/>
499-
</MessageComposerToolbarActions>
500-
<MessageComposerToolbarSubmit>
501-
{!canSend && (
502-
<MessageComposerButton primary onClick={onJoin} loading={joinMutation.isPending}>
503-
{t('Join')}
504-
</MessageComposerButton>
505-
)}
506-
{canSend && (
507-
<>
508-
{isEditing && <MessageComposerButton onClick={closeEditing}>{t('Cancel')}</MessageComposerButton>}
509-
<MessageComposerAction
510-
aria-label={t('Send')}
511-
icon='send'
512-
disabled={!canSend || isUploading || isProcessingUploads || (!typing && !isEditing && !hasUploads)}
513-
onClick={handleSendMessage}
514-
secondary={typing || isEditing || hasUploads}
515-
info={typing || isEditing || hasUploads}
516-
/>
517-
</>
518-
)}
519-
</MessageComposerToolbarSubmit>
520-
</MessageComposerToolbar>
521-
</MessageComposer>
522-
<ComposerUserActionIndicator rid={room._id} tmid={tmid} />
523-
</>
391+
}
392+
files={<MessageComposerFiles />}
393+
/>
524394
);
525395
};
526396

0 commit comments

Comments
 (0)