Skip to content
Closed
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
40 changes: 29 additions & 11 deletions packages/api/src/EmbeddedChatApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -741,7 +741,11 @@ export default class EmbeddedChatApi {
* @param {*} message should be a string or an rc message object
* Refer https://developer.rocket.chat/reference/api/schema-definition/message#message-object
*/
async sendMessage(message: any, threadId: string) {
async sendMessage(
message: any,
threadId: string,
isAlsoSendToChannel: boolean
) {
const messageObj =
typeof message === "string"
? {
Expand All @@ -755,18 +759,32 @@ export default class EmbeddedChatApi {
if (threadId) {
messageObj.tmid = threadId;
}
if (isAlsoSendToChannel) {
messageObj.tshow = true;
}
try {
const { userId, authToken } = (await this.auth.getCurrentUser()) || {};
const response = await fetch(`${this.host}/api/v1/chat.sendMessage`, {
body: JSON.stringify({ message: messageObj }),
headers: {
"Content-Type": "application/json",
"X-Auth-Token": authToken,
"X-User-Id": userId,
},
method: "POST",
});
return await response.json();
const response = await fetch(
`${this.host}/api/v1/method.call/sendMessage`,
{
body: JSON.stringify({
message: JSON.stringify({
msg: "method",
id: null,
method: "sendMessage",
params: [messageObj],
}),
}),
headers: {
"Content-Type": "application/json",
"X-Auth-Token": authToken,
"X-User-Id": userId,
},
method: "POST",
}
);
const result = await response.json();
return result;
} catch (err) {
console.error(err);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ const ChatInput = ({ style }) => {
await RCInstance.logout();
setIsUserAuthenticated(false);
} else {
replaceMessage(pendingMessage._id, res.message);
replaceMessage(pendingMessage._id, res.message.id);
}
} else {
// A message is being edited
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/lib/isMessageSequential.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const isMessageSequential = (current, previous, groupingRange) => {
return false;
}

if (current.t || previous.t) {
if (current.t || previous.t || current.tshow || previous.tshow) {
return false;
}

Expand Down
5 changes: 5 additions & 0 deletions packages/react/src/store/messageStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ const useMessageStore = create((set, get) => ({
threadMessages: upsertMessage(state.threadMessages, message),
}));
}
if (message.tshow) {
set((state) => ({
messages: upsertMessage(state.messages, message),
}));
}
} else {
set((state) => ({
messages: upsertMessage(state.messages, message),
Expand Down
178 changes: 109 additions & 69 deletions packages/react/src/views/ChatInput/ChatInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
useToastBarDispatch,
useComponentOverrides,
useTheme,
CheckBox,
} from '@embeddedchat/ui-elements';
import { useRCContext } from '../../context/RCInstance';
import {
Expand Down Expand Up @@ -57,6 +58,7 @@ const ChatInput = ({ scrollToBottom }) => {
const [showCommandList, setShowCommandList] = useState(false);
const [filteredCommands, setFilteredCommands] = useState([]);
const [isMsgLong, setIsMsgLong] = useState(false);
const [isAlsoSendToChannel, setIsAlsoSendToChannel] = useState(false);

const {
isUserAuthenticated,
Expand Down Expand Up @@ -143,6 +145,8 @@ const ChatInput = ({ scrollToBottom }) => {
setShowMembersList
);

const [isThreadOpen] = useMessageStore((state) => [state.isThreadOpen]);

useEffect(() => {
RCInstance.auth.onAuthChange((user) => {
if (user) {
Expand Down Expand Up @@ -328,10 +332,12 @@ const ChatInput = ({ scrollToBottom }) => {
msg: pendingMessage.msg,
_id: pendingMessage._id,
},
ECOptions.enableThreads ? threadId : undefined
ECOptions.enableThreads ? threadId : undefined,
ECOptions.enableThreads && threadId && isAlsoSendToChannel
);

if (res.success) {
setIsAlsoSendToChannel(false);
clearQuoteMessages();
replaceMessage(pendingMessage, res.message);
}
Expand Down Expand Up @@ -433,6 +439,10 @@ const ChatInput = ({ scrollToBottom }) => {
}
};

const handleAlsoSendToChannel = () => {
setIsAlsoSendToChannel(!isAlsoSendToChannel);
};

const onKeyDown = (e) => {
switch (true) {
case e.ctrlKey && e.code === 'KeyI': {
Expand Down Expand Up @@ -585,79 +595,109 @@ const ChatInput = ({ scrollToBottom }) => {

<TypingUsers />
</Box>

<Box
ref={chatInputContainer}
css={[
styles.inputWithFormattingBox,
(editMessage.msg || editMessage.attachments) && styles.editMessage,
]}
css={css`
display: flex;
flex-direction: column;
width: 100%;
`}
>
<Box css={styles.inputBox}>
<Input
textArea
rows={1}
disabled={
!isUserAuthenticated ||
!canSendMsg ||
isRecordingMessage ||
isChannelArchived
}
placeholder={
isUserAuthenticated
? isChannelArchived
? 'Room archived'
: canSendMsg
? `Message #${channelInfo.name}`
: 'This room is read only'
: 'Sign in to chat'
}
css={css`
${styles.textInput}
${isChannelArchived &&
isUserAuthenticated &&
`text-align: center;`}
`}
onChange={onTextChange}
onBlur={() => {
sendTypingStop();
handleBlur();
}}
onFocus={handleFocus}
onKeyDown={onKeyDown}
ref={messageRef}
/>
{isThreadOpen && (
<Box css={[styles.sendToChannelCheckBox]}>
<CheckBox
onClick={handleAlsoSendToChannel}
checked={isAlsoSendToChannel}
/>
<p
css={css`
display: inline;
`}
>
Also Send to channel
</p>
</Box>
)}

<input type="file" hidden ref={inputRef} onChange={sendAttachment} />
<Box
css={css`
padding: 0.25rem;
`}
>
{isUserAuthenticated ? (
!isChannelArchived ? (
<ActionButton
ghost
size="large"
onClick={() => sendMessage()}
type="primary"
disabled={disableButton || isRecordingMessage}
icon="send"
/>
) : null
) : (
<Button onClick={onJoin} type="primary" disabled={isLoginIn}>
{isLoginIn ? <Throbber /> : 'JOIN'}
</Button>
)}
<Box
ref={chatInputContainer}
css={[
styles.inputWithFormattingBox,
(editMessage.msg || editMessage.attachments) && styles.editMessage,
]}
>
<Box css={styles.inputBox}>
<Input
textArea
rows={1}
disabled={
!isUserAuthenticated ||
!canSendMsg ||
isRecordingMessage ||
isChannelArchived
}
placeholder={
isUserAuthenticated
? isChannelArchived
? 'Room archived'
: canSendMsg
? `Message #${channelInfo.name}`
: 'This room is read only'
: 'Sign in to chat'
}
css={css`
${styles.textInput}
${isChannelArchived &&
isUserAuthenticated &&
`text-align: center;`}
`}
onChange={onTextChange}
onBlur={() => {
sendTypingStop();
handleBlur();
}}
onFocus={handleFocus}
onKeyDown={onKeyDown}
ref={messageRef}
/>

<input
type="file"
hidden
ref={inputRef}
onChange={sendAttachment}
/>
<Box
css={css`
padding: 0.25rem;
`}
>
{isUserAuthenticated ? (
!isChannelArchived ? (
<ActionButton
ghost
size="large"
onClick={() => sendMessage()}
type="primary"
disabled={disableButton || isRecordingMessage}
icon="send"
/>
) : null
) : (
<Button onClick={onJoin} type="primary" disabled={isLoginIn}>
{isLoginIn ? <Throbber /> : 'JOIN'}
</Button>
)}
</Box>
</Box>
{isUserAuthenticated && !isChannelArchived && (
<ChatInputFormattingToolbar
messageRef={messageRef}
inputRef={inputRef}
triggerButton={onTextChange}
/>
)}
</Box>
{isUserAuthenticated && !isChannelArchived && (
<ChatInputFormattingToolbar
messageRef={messageRef}
inputRef={inputRef}
triggerButton={onTextChange}
/>
)}
</Box>
{isMsgLong && (
<Modal
Expand Down
5 changes: 5 additions & 0 deletions packages/react/src/views/ChatInput/ChatInput.styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ import { darken, lighten } from '@embeddedchat/ui-elements';

export const getChatInputStyles = (theme) => {
const styles = {
sendToChannelCheckBox: css`
margin: 0.5rem 0rem 0rem 2rem;
display: flex,
flex-direction: row;
`,
inputWithFormattingBox: css`
border: 1px solid ${theme.colors.border};
border-radius: ${theme.radius};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useRef, useEffect } from 'react';
import React, { useState, useRef } from 'react';
import { css } from '@emotion/react';
import {
Box,
Expand Down
20 changes: 17 additions & 3 deletions packages/react/src/views/Message/Message.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { getMessageStyles } from './Message.styles';
import useBubbleStyles from './BubbleVariant/useBubbleStyles';
import UiKitMessageBlock from './uiKit/UiKitMessageBlock';
import useFetchChatData from '../../hooks/useFetchChatData';
import { ThreadMessagePreview } from './ThreadMessagePreview';

const Message = ({
message,
Expand All @@ -41,6 +42,7 @@ const Message = ({
showRoles = true,
isLinkPreview = true,
isInSidebar = false,
prev,
}) => {
const { classNames, styleOverrides, variantOverrides } =
useComponentOverrides(
Expand All @@ -50,7 +52,9 @@ const Message = ({
);

const { RCInstance, ECOptions } = useContext(RCContext);
showAvatar = ECOptions?.showAvatar && showAvatar;
showAvatar =
type === 'thread' ||
(ECOptions?.showAvatar && showAvatar && !message.tshow);
const { showSidebar, setShowSidebar } = useSidebarStore();
const authenticatedUserId = useUserStore((state) => state.userId);
const authenticatedUserUsername = useUserStore((state) => state.username);
Expand Down Expand Up @@ -221,7 +225,10 @@ const Message = ({

const isStarred = message.starred?.find((u) => u._id === authenticatedUserId);
const isPinned = message.pinned;
const shouldShowHeader = !sequential || (!showAvatar && isStarred);
// const shouldShowHeader = (!sequential || (!showAvatar && isStarred)) && !message.tshow;
const shouldShowHeader =
(type === 'thread' && !sequential) ||
(type === 'default' && !sequential && !message.tshow);

return (
<>
Expand Down Expand Up @@ -260,7 +267,7 @@ const Message = ({
})}
/>
)}
{!message.t ? (
{!message.t && (type === 'thread' || !message.tshow) ? (
<>
<MessageBody
className="ec-message-body"
Expand Down Expand Up @@ -374,6 +381,13 @@ const Message = ({
variantStyles={variantStyles}
/>
) : null}
{!!message.tshow && type !== 'thread' ? (
<ThreadMessagePreview
message={message}
sequential={sequential}
prev={prev}
/>
) : null}
</MessageBodyContainer>
</Box>
</>
Expand Down
Loading
Loading