Skip to content

Commit

Permalink
new approach for live composer
Browse files Browse the repository at this point in the history
  • Loading branch information
imf-ali committed Feb 11, 2024
1 parent 789544f commit 67f71d1
Show file tree
Hide file tree
Showing 13 changed files with 506 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { QuillComposerAPI } from '../../../../client/lib/chats/ChatAPI';

const attributesMap = {
bold: '*',
italic: '_',
strike: '~',
};

export const createQuillComposerAPI = (): QuillComposerAPI => {
let text = '';

const setQuillDeltaToText = (getDelta: any) => {
const delta = getDelta();
delta.ops.forEach((op: any) => {
const mdStack: string[] = [];
if (op.attributes) {
Object.keys(op.attributes).forEach((attribute: string) => {
mdStack.push(attribute);
text += attributesMap[attribute as keyof typeof attributesMap];
});
}
text += op.insert;
while (mdStack.length) {
text += attributesMap[mdStack.pop() as keyof typeof attributesMap];
}
});
};

return {
get text(): string {
return text;
},
setQuillDeltaToText,
};
};
8 changes: 7 additions & 1 deletion apps/meteor/app/ui/client/lib/ChatMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { isVideoConfMessage } from '@rocket.chat/core-typings';
import type { IActionManager } from '@rocket.chat/ui-contexts';
import type { UIEvent } from 'react';

import type { ChatAPI, ComposerAPI, DataAPI, UploadsAPI } from '../../../../client/lib/chats/ChatAPI';
import type { ChatAPI, ComposerAPI, DataAPI, QuillComposerAPI, UploadsAPI } from '../../../../client/lib/chats/ChatAPI';
import { createDataAPI } from '../../../../client/lib/chats/data';
import { processMessageEditing } from '../../../../client/lib/chats/flows/processMessageEditing';
import { processSetReaction } from '../../../../client/lib/chats/flows/processSetReaction';
Expand Down Expand Up @@ -32,11 +32,17 @@ export class ChatMessages implements ChatAPI {

public composer: ComposerAPI | undefined;

public quillComposer?: QuillComposerAPI | undefined;

public setComposerAPI = (composer: ComposerAPI): void => {
this.composer?.release();
this.composer = composer;
};

public setQuillComposerAPI = (quillComposer: QuillComposerAPI): void => {
this.quillComposer = quillComposer;
};

public data: DataAPI;

public readStateManager: ReadStateManager;
Expand Down
7 changes: 7 additions & 0 deletions apps/meteor/client/lib/chats/ChatAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ export type ComposerAPI = {
readonly formatters: Subscribable<FormattingButton[]>;
};

export type QuillComposerAPI = {
text: string;
setQuillDeltaToText(getDelta: any): void;
};

export type DataAPI = {
composeMessage(
text: string,
Expand Down Expand Up @@ -107,7 +112,9 @@ export type UploadsAPI = {
export type ChatAPI = {
readonly uid: string | null;
readonly composer?: ComposerAPI;
readonly quillComposer?: QuillComposerAPI;
readonly setComposerAPI: (composer: ComposerAPI) => void;
readonly setQuillComposerAPI: (quillComposer: QuillComposerAPI) => void;
readonly data: DataAPI;
readonly uploads: UploadsAPI;
readonly readStateManager: ReadStateManager;
Expand Down
66 changes: 48 additions & 18 deletions apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import {
MessageComposerAction,
MessageComposerToolbarActions,
MessageComposer,
MessageComposerInput,
// MessageComposerInput,
MessageComposerToolbar,
MessageComposerActionsDivider,
MessageComposerToolbarSubmit,
MessageComposerHint,
MessageComposerButton,
MessageComposerQuillInput,
} from '@rocket.chat/ui-composer';
import { useTranslation, useUserPreference, useLayout } from '@rocket.chat/ui-contexts';
import { useTranslation, useUserPreference, useLayout, useQuill } from '@rocket.chat/ui-contexts';
import { useMutation } from '@tanstack/react-query';
import type {
ReactElement,
Expand All @@ -22,12 +23,14 @@ import type {
KeyboardEvent,
ClipboardEventHandler,
MouseEvent,
Ref,
} from 'react';
import React, { memo, useRef, useReducer, useCallback } from 'react';
import { Trans } from 'react-i18next';
import { useSubscription } from 'use-subscription';

import { createComposerAPI } from '../../../../../app/ui-message/client/messageBox/createComposerAPI';
import { createQuillComposerAPI } from '../../../../../app/ui-message/client/messageBox/createQuillComposerAPI';
import type { FormattingButton } from '../../../../../app/ui-message/client/messageBox/messageBoxFormatting';
import { formattingButtons } from '../../../../../app/ui-message/client/messageBox/messageBoxFormatting';
import { getImageExtensionFromMime } from '../../../../../lib/getImageExtensionFromMime';
Expand All @@ -53,6 +56,7 @@ import MessageBoxFormattingToolbar from './MessageBoxFormattingToolbar';
import MessageBoxReplies from './MessageBoxReplies';
import { useMessageBoxAutoFocus } from './hooks/useMessageBoxAutoFocus';
import { useMessageBoxPlaceholder } from './hooks/useMessageBoxPlaceholder';
import './MessageBoxQuill.css';

const reducer = (_: unknown, event: FormEvent<HTMLInputElement>): boolean => {
const target = event.target as HTMLInputElement;
Expand Down Expand Up @@ -139,6 +143,8 @@ const MessageBox = ({
const messageComposerRef = useRef<HTMLElement>(null);
const shadowRef = useRef<HTMLDivElement>(null);

const { quillRef, getDelta } = useQuill();

const storageID = `messagebox_${room._id}${tmid ? `-${tmid}` : ''}`;

const callbackRef = useCallback(
Expand All @@ -151,6 +157,16 @@ const MessageBox = ({
[chat, storageID],
);

const quillCallbackRef = useCallback(
(node: HTMLDivElement) => {
if (node === null || chat.quillComposer) {
return;
}
chat.setQuillComposerAPI(createQuillComposerAPI());
},
[chat],
);

const autofocusRef = useMessageBoxAutoFocus(!isMobile);

const useEmojis = useUserPreference<boolean>('useEmojis');
Expand All @@ -168,7 +184,8 @@ const MessageBox = ({
});

const handleSendMessage = useMutableCallback(() => {
const text = chat.composer?.text ?? '';
chat.quillComposer?.setQuillDeltaToText(getDelta);
const text = chat.quillComposer?.text ?? '';
chat.composer?.clear();
clearPopup();

Expand Down Expand Up @@ -353,7 +370,8 @@ const MessageBox = ({
configurations: composerPopupConfig,
});

const mergedRefs = useMessageComposerMergedRefs(c, textareaRef, callbackRef, autofocusRef);
// const mergedRefs = useMessageComposerMergedRefs(c, textareaRef, quillRef, callbackRef, autofocusRef, quillCallbackRef);
const qillMergedRefs = useMessageComposerMergedRefs(c, quillRef, callbackRef, autofocusRef, quillCallbackRef);

const shouldPopupPreview = useEnablePopupPreview(filter, popup);

Expand Down Expand Up @@ -399,7 +417,7 @@ const MessageBox = ({
{isRecordingVideo && <VideoMessageRecorder reference={messageComposerRef} rid={room._id} tmid={tmid} />}
<MessageComposer ref={messageComposerRef} variant={isEditing ? 'editing' : undefined}>
{isRecordingAudio && <AudioMessageRecorder rid={room._id} isMicrophoneDenied={isMicrophoneDenied} />}
<MessageComposerInput
{/* <MessageComposerInput
ref={mergedRefs}
aria-label={composerPlaceholder}
name='msg'
Expand All @@ -410,6 +428,18 @@ const MessageBox = ({
onKeyDown={handler}
onPaste={handlePaste}
aria-activedescendant={ariaActiveDescendant}
/> */}
<MessageComposerQuillInput
ref={qillMergedRefs as unknown as Ref<any>}
aria-label={composerPlaceholder}
name='msg'
disabled={isRecording || !canSend}
onChange={setTyping}
style={textAreaStyle}
placeholder={composerPlaceholder}
onKeyDown={handler}
onPaste={handlePaste}
aria-activedescendant={ariaActiveDescendant}
/>
<div ref={shadowRef} style={shadowStyle} />
<MessageComposerToolbar>
Expand Down Expand Up @@ -445,19 +475,19 @@ const MessageBox = ({
{t('Join')}
</MessageComposerButton>
)}
{canSend && (
<>
{isEditing && <MessageComposerButton onClick={closeEditing}>{t('Cancel')}</MessageComposerButton>}
<MessageComposerAction
aria-label={t('Send')}
icon='send'
disabled={!canSend || (!typing && !isEditing)}
onClick={handleSendMessage}
secondary={typing || isEditing}
info={typing || isEditing}
/>
</>
)}
{/* {canSend && ( */}
<>
{isEditing && <MessageComposerButton onClick={closeEditing}>{t('Cancel')}</MessageComposerButton>}
<MessageComposerAction
aria-label={t('Send')}
icon='send'
// disabled={!canSend || (!typing && !isEditing)}
onClick={handleSendMessage}
secondary={typing || isEditing}
info={typing || isEditing}
/>
</>
{/* )} */}
</MessageComposerToolbarSubmit>
</MessageComposerToolbar>
</MessageComposer>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Box } from '@rocket.chat/fuselage';
import { MessageComposerAction } from '@rocket.chat/ui-composer';
import { useTranslation } from '@rocket.chat/ui-contexts';
import React, { memo } from 'react';
Expand All @@ -21,7 +22,7 @@ const MessageBoxFormattingToolbar = ({ items, variant = 'large', composer, disab
const featuredFormatter = collapsedItems.splice(0, 1)[0];

return (
<>
<Box id='toolbar'>
{'icon' in featuredFormatter && (
<MessageComposerAction
onClick={() => composer.wrapSelection(featuredFormatter.pattern)}
Expand All @@ -30,12 +31,12 @@ const MessageBoxFormattingToolbar = ({ items, variant = 'large', composer, disab
/>
)}
<FormattingToolbarDropdown composer={composer} items={collapsedItems} disabled={disabled} />
</>
</Box>
);
}

return (
<>
<Box id='toolbar'>
{items.map((formatter) =>
'icon' in formatter ? (
<MessageComposerAction
Expand Down Expand Up @@ -65,7 +66,7 @@ const MessageBoxFormattingToolbar = ({ items, variant = 'large', composer, disab
</span>
),
)}
</>
</Box>
);
};

Expand Down
Loading

0 comments on commit 67f71d1

Please sign in to comment.