Skip to content

Commit 6bc47d7

Browse files
authored
[Bugfix] Final QA of message threading (#59)
- Lift restriction of replyType props of App and Channel components - [QU-361] Disable message delete submit button on modal when the message has replies - [QU-382] Do not allow the message grouping to pending and failed messages - [QU-385] Disable the delete button on FileViewer when the message has replies - Clear message input value and quoted message when the current channel is changed - Affect UI components to apply the on thread info updated event - Check if the left user is me
1 parent 4e32041 commit 6bc47d7

File tree

20 files changed

+119
-64
lines changed

20 files changed

+119
-64
lines changed

src/smart-components/App/index.jsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export default function App(props) {
2626
profileUrl,
2727
config = {},
2828
useReaction,
29-
// replyType,
29+
replyType,
3030
useMessageGrouping,
3131
colorSet,
3232
stringSet,
@@ -97,7 +97,7 @@ export default function App(props) {
9797
startingPoint={startingPoint}
9898
highlightedMessage={highlightedMessage}
9999
useReaction={useReaction}
100-
// replyType={replyType}
100+
replyType={replyType}
101101
useMessageGrouping={useMessageGrouping}
102102
/>
103103
</div>
@@ -158,7 +158,7 @@ App.propTypes = {
158158
]),
159159
}),
160160
useReaction: PropTypes.bool,
161-
// replyType: PropTypes.oneOf(['NONE', 'QUOTE_REPLY', 'THREAD']),
161+
replyType: PropTypes.oneOf(['NONE', 'QUOTE_REPLY', 'THREAD']),
162162
showSearchIcon: PropTypes.bool,
163163
useMessageGrouping: PropTypes.bool,
164164
stringSet: PropTypes.objectOf(PropTypes.string),
@@ -189,7 +189,7 @@ App.defaultProps = {
189189
renderUserProfile: null,
190190
config: {},
191191
useReaction: true,
192-
// replyType: 'NONE',
192+
replyType: 'NONE',
193193
useMessageGrouping: true,
194194
stringSet: null,
195195
colorSet: null,

src/smart-components/App/stories/index.stories.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ const array = [
179179
`hoon${age}1`,
180180
`hoon${age}2`,
181181
`hoon${age}3`,
182+
`hoon${age}4`,
182183
`eunseo${age}1`,
183184
];
184185
const addProfile = null; // 'https://static.sendbird.com/sample/profiles/profile_12_512px.png';
@@ -220,6 +221,7 @@ export const user2 = () => fitPageSize(
220221
allowProfileEdit
221222
profileUrl={addProfile}
222223
replyType="QUOTE_REPLY"
224+
useMessageGrouping={false}
223225
imageCompression={{
224226
compressionRate: 0.5,
225227
resizingWidth: 100,
@@ -239,6 +241,19 @@ export const user3 = () => fitPageSize(
239241
replyType="QUOTE_REPLY"
240242
/>
241243
);
244+
export const user4 = () => fitPageSize(
245+
<App
246+
appId={appId}
247+
userId={array[3]}
248+
nickname={array[3]}
249+
theme="dark"
250+
showSearchIcon
251+
allowProfileEdit
252+
useMessageGrouping={false}
253+
profileUrl={addProfile}
254+
replyType="QUOTE_REPLY"
255+
/>
256+
);
242257

243258
const UseSendbirdChannelList = (props) => {
244259
const [queries] = useState({ channelListQuery: { customTypesFilter: ['apple'] } });
@@ -267,8 +282,8 @@ const CustomApp = () => {
267282
return (
268283
<Sendbird
269284
appId={appId}
270-
userId={array[3]}
271-
nickname={array[3]}
285+
userId={array[4]}
286+
nickname={array[4]}
272287
theme="dark"
273288
showSearchIcon
274289
allowProfileEdit

src/smart-components/ChannelList/dux/reducers.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export default function reducer(state, action) {
104104
allChannels: state.allChannels.filter(({ url }) => url !== channel.url),
105105
};
106106
}
107-
const filteredChannels = state.allChannels.filter((c) => c.url !== channel.url);
107+
const filteredChannels = state.allChannels.filter((c) => !(c.url === channel.url && isMe));
108108
return {
109109
...state,
110110
currentChannel: (isMe && (channel.url === state.currentChannel))

src/smart-components/Conversation/components/MessageHOC.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ export default function MessageHoc({
178178
{
179179
showRemove && (
180180
<RemoveMessageModal
181+
message={message}
181182
onCloseModal={() => setShowRemove(false)}
182183
onDeleteMessage={() => {
183184
deleteMessage(message);

src/smart-components/Conversation/components/MessageInputWrapper.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ const MessageInputWrapper = ({
6666
)}
6767
<MessageInput
6868
className="sendbird-message-input-wrapper__message-input"
69+
channelUrl={channel?.url}
6970
placeholder={
7071
(quoteMessage && stringSet.MESSAGE_INPUT__QUOTE_REPLY__PLACE_HOLDER)
7172
|| (utils.isDisabledBecauseFrozen(channel) && stringSet.MESSAGE_INPUT__PLACE_HOLDER__DISABLED)

src/smart-components/Conversation/components/RemoveMessage.jsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,20 @@ import React, { useContext } from 'react';
22
import PropTypes from 'prop-types';
33

44
import Modal from '../../../ui/Modal';
5+
import { ButtonTypes } from '../../../ui/Button';
56
import { LocalizationContext } from '../../../lib/LocalizationContext';
67

78
const RemoveMessage = (props) => {
89
const {
910
onCloseModal,
1011
onDeleteMessage,
12+
message,
1113
} = props;
1214
const { stringSet } = useContext(LocalizationContext);
1315
return (
1416
<Modal
17+
type={ButtonTypes.DANGER}
18+
disabled={message?.threadInfo?.replyCount > 0}
1519
onCancel={onCloseModal}
1620
onSubmit={onDeleteMessage}
1721
submitText="Delete"
@@ -23,6 +27,11 @@ const RemoveMessage = (props) => {
2327
RemoveMessage.propTypes = {
2428
onCloseModal: PropTypes.func.isRequired,
2529
onDeleteMessage: PropTypes.func.isRequired,
30+
message: PropTypes.shape({
31+
threadInfo: PropTypes.shape({
32+
replyCount: PropTypes.number,
33+
}),
34+
}).isRequired,
2635
};
2736

2837
export default RemoveMessage;

src/smart-components/Conversation/index.jsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export const ConversationPanel = (props) => {
6161
startingPoint,
6262
highlightedMessage,
6363
useReaction,
64-
// replyType,
64+
replyType,
6565
showSearchIcon,
6666
onSearchClick,
6767
renderChatItem,
@@ -76,7 +76,6 @@ export const ConversationPanel = (props) => {
7676
onBeforeSendFileMessage,
7777
onBeforeUpdateUserMessage,
7878
} = props;
79-
const replyType = 'NONE'; // TODO: Get back replyType for message threading
8079
const { sdk } = sdkStore;
8180
const { config } = props;
8281
const sdkError = sdkStore.error;
@@ -201,6 +200,10 @@ export const ConversationPanel = (props) => {
201200
{ messagesDispatcher, sdk, logger },
202201
);
203202

203+
useEffect(() => {
204+
setQuoteMessage(null);
205+
}, [channelUrl]);
206+
204207
// Hook to handle ChannelEvents and send values to useReducer using messagesDispatcher
205208
useHandleChannelEvents(
206209
{ currentGroupChannel, sdkInit, hasMoreToBottom },
@@ -509,7 +512,7 @@ ConversationPanel.propTypes = {
509512
onSearchClick: PropTypes.func,
510513
onChatHeaderActionClick: PropTypes.func,
511514
useReaction: PropTypes.bool,
512-
// replyType: PropTypes.oneOf(['NONE', 'QUOTE_REPLY', 'THREAD']),
515+
replyType: PropTypes.oneOf(['NONE', 'QUOTE_REPLY', 'THREAD']),
513516
disableUserProfile: PropTypes.bool,
514517
renderUserProfile: PropTypes.func,
515518
useMessageGrouping: PropTypes.bool,
@@ -528,7 +531,7 @@ ConversationPanel.defaultProps = {
528531
renderMessageInput: null,
529532
renderChatHeader: null,
530533
useReaction: true,
531-
// replyType: 'NONE',
534+
replyType: 'NONE',
532535
showSearchIcon: false,
533536
onSearchClick: noop,
534537
disableUserProfile: false,

src/smart-components/Conversation/utils.js

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ import format from 'date-fns/format';
22
import * as channelActions from './dux/actionTypes';
33
import * as topics from '../../lib/pubSub/topics';
44

5-
import { getSendingMessageStatus, getOutgoingMessageStates } from '../../utils';
5+
import {
6+
getSendingMessageStatus,
7+
getOutgoingMessageStates,
8+
} from '../../utils';
69

710
const MessageStatusType = getOutgoingMessageStates();
811
const UNDEFINED = 'undefined';
@@ -207,12 +210,14 @@ export const compareMessagesForGrouping = (
207210
prevMessage,
208211
currMessage,
209212
nextMessage,
210-
) => (
211-
[
212-
isSameGroup(prevMessage, currMessage),
213-
isSameGroup(currMessage, nextMessage),
214-
]
215-
);
213+
) => {
214+
const sendingStatus = currMessage?.sendingStatus || '';
215+
const isAcceptable = sendingStatus !== 'pending' && sendingStatus !== 'failed';
216+
return [
217+
isSameGroup(prevMessage, currMessage) && isAcceptable,
218+
isSameGroup(currMessage, nextMessage) && isAcceptable,
219+
];
220+
};
216221

217222
export const hasOwnProperty = (property) => (payload) => {
218223
// eslint-disable-next-line no-prototype-builtins

src/ui/Button/index.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
&.sendbird-button__disabled {
2121
cursor: not-allowed;
2222
@include themed() {
23+
border: none;
2324
background-color: t(bg-2);
2425
}
2526
&:hover {

src/ui/Button/stories/Button.stories.js

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@ import { Type, Size } from '../type';
55

66
export default { title: 'UI Components/Button' };
77

8-
export const defaultButton = () => <Button />;
9-
export const primaryButton = () => <Button type={Type.PRIMARY}>PRIMARY</Button>;
10-
export const secondaryButton = () => <Button type={Type.SECONDARY}>SECONDARY</Button>;
11-
export const dangerButton = () => <Button type={Type.DANGER}>DANGER</Button>;
12-
export const disabledButton = () => <Button type={Type.DISABLED}>DISABLED</Button>;
13-
14-
export const smallPrimaryButton = () => <Button type={Type.PRIMARY} size={Size.SMALL}>PRIMARY</Button>;
15-
export const smallSecondaryButton = () => <Button type={Type.SECONDARY} size={Size.SMALL}>SECONDARY</Button>;
16-
export const smallDangerButton = () => <Button type={Type.DANGER} size={Size.SMALL}>DANGER</Button>;
17-
export const smallDisabledButton = () => <Button type={Type.DISABLED} size={Size.SMALL}>DISABLED</Button>;
8+
export const defaultButton = () => [
9+
<Button>DEFAULT</Button>,
10+
<Button type={Type.PRIMARY}>PRIMARY</Button>,
11+
<Button type={Type.SECONDARY}>SECONDARY</Button>,
12+
<Button type={Type.DANGER}>DANGER</Button>,
13+
<Button type={Type.DISABLED}>DISABLED</Button>,
14+
];
15+
export const smallButton = () => [
16+
<Button type={Type.PRIMARY} size={Size.SMALL}>PRIMARY</Button>,
17+
<Button type={Type.SECONDARY} size={Size.SMALL}>SECONDARY</Button>,
18+
<Button type={Type.DANGER} size={Size.SMALL}>DANGER</Button>,
19+
<Button type={Type.DISABLED} size={Size.SMALL}>DISABLED</Button>,
20+
];

0 commit comments

Comments
 (0)