Skip to content

Commit 0b57263

Browse files
authored
Fix scroll to bottom issue (#71)
- Fix scroll to bottom issue - Add type definition for quotedMessage in Channel component props
1 parent a6af190 commit 0b57263

File tree

7 files changed

+84
-18
lines changed

7 files changed

+84
-18
lines changed

src/index.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,8 +378,8 @@ interface ChannelProps {
378378
onSearchClick?(): void;
379379
highlightedMessage?: string | number;
380380
startingPoint?: number;
381-
onBeforeSendUserMessage?(text: string, quoteMessage?: Sendbird.UserMessage | Sendbird.FileMessage): Sendbird.UserMessageParams;
382-
onBeforeSendFileMessage?(file: File, quoteMessage?: Sendbird.UserMessage | Sendbird.FileMessage): Sendbird.FileMessageParams;
381+
onBeforeSendUserMessage?(text: string, quotedMessage?: Sendbird.UserMessage | Sendbird.FileMessage): Sendbird.UserMessageParams;
382+
onBeforeSendFileMessage?(file: File, quotedMessage?: Sendbird.UserMessage | Sendbird.FileMessage): Sendbird.FileMessageParams;
383383
onBeforeUpdateUserMessage?(text: string): Sendbird.UserMessageParams;
384384
onChatHeaderActionClick?(event: React.MouseEvent<HTMLElement>): void;
385385
renderCustomMessage?: RenderCustomMessage;

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

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,32 @@ const UseSendbirdChannelList = (props) => {
278278
);
279279
};
280280
const SBChannelList = withSendBird(UseSendbirdChannelList);
281+
const SBChannel = withSendBird((props) => {
282+
const {
283+
channelUrl,
284+
onSearchClick,
285+
onChatHeaderActionClick,
286+
showSearchIcon,
287+
} = props;
288+
289+
return (
290+
<Conversation
291+
channelUrl={channelUrl}
292+
showSearchIcon={showSearchIcon}
293+
onSearchClick={onSearchClick}
294+
onChatHeaderActionClick={onChatHeaderActionClick}
295+
// renderCustomMessage={(message) => {
296+
// if (message.messageType === 'user') {
297+
// return () => (
298+
// <CustomMessageItem
299+
// message={message}
300+
// />
301+
// )
302+
// }
303+
// }}
304+
/>
305+
);
306+
});
281307
const CustomApp = () => {
282308
const [channelUrl, setChannelUrl] = useState('');
283309
const [channelSettings, setChannelSettings] = useState(false);
@@ -297,7 +323,7 @@ const CustomApp = () => {
297323
<SBChannelList setChannelUrl={setChannelUrl} />
298324
<div style={{ height: '100%', width: '100%', display: 'inline-flex', flexDirection: 'row' }}>
299325
<div style={{ width: '100%' }}>
300-
<Conversation
326+
<SBChannel
301327
channelUrl={channelUrl}
302328
onChatHeaderActionClick={() => {
303329
setChannelSearch(false);

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

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,26 @@ import { compareMessagesForGrouping } from '../utils';
1010
import PlaceHolder, { PlaceHolderTypes } from '../../../ui/PlaceHolder';
1111
import Icon, { IconTypes, IconColors } from '../../../ui/Icon';
1212

13+
const SCROLL_REF_CLASS_NAME = '.sendbird-msg--scroll-ref';
14+
1315
export default class ConversationScroll extends Component {
16+
constructor(props) {
17+
super(props);
18+
this.state = {};
19+
}
20+
21+
handleScroll = () => {
22+
const { scrollRef } = this?.props;
23+
const current = scrollRef?.current;
24+
if (current) {
25+
const bottom = current.scrollHeight - current.scrollTop - current.offsetHeight;
26+
const { scrollBottom = 0 } = this.state;
27+
if (scrollBottom < bottom) {
28+
current.scrollTop += bottom - scrollBottom;
29+
}
30+
}
31+
}
32+
1433
onScroll = (e) => {
1534
const {
1635
scrollRef,
@@ -31,7 +50,7 @@ export default class ConversationScroll extends Component {
3150
if (!hasMore) {
3251
return;
3352
}
34-
const nodes = scrollRef.current.querySelectorAll('.sendbird-msg--scroll-ref');
53+
const nodes = scrollRef.current.querySelectorAll(SCROLL_REF_CLASS_NAME);
3554
const first = nodes && nodes[0];
3655
onScroll(([messages]) => {
3756
if (messages) {
@@ -46,7 +65,7 @@ export default class ConversationScroll extends Component {
4665
}
4766

4867
if (clientHeight + scrollTop === scrollHeight) {
49-
const nodes = scrollRef.current.querySelectorAll('.sendbird-msg--scroll-ref');
68+
const nodes = scrollRef.current.querySelectorAll(SCROLL_REF_CLASS_NAME);
5069
const last = nodes && nodes[nodes.length - 1];
5170
onScrollDown(([messages]) => {
5271
if (messages) {
@@ -69,6 +88,15 @@ export default class ConversationScroll extends Component {
6988
});
7089
currentGroupChannel.markAsRead();
7190
}
91+
92+
// save the lastest scroll bottom value
93+
if (scrollRef?.current) {
94+
const current = scrollRef?.current;
95+
this.setState((state) => ({
96+
...state,
97+
scrollBottom: current.scrollHeight - current.scrollTop - current.offsetHeight,
98+
}), () => { });
99+
}
72100
}, 500);
73101
}
74102

@@ -113,11 +141,7 @@ export default class ConversationScroll extends Component {
113141

114142
return (
115143
<div className="sendbird-conversation__messages">
116-
<div
117-
ref={scrollRef}
118-
className="sendbird-conversation__scroll-container"
119-
onScroll={this.onScroll}
120-
>
144+
<div className="sendbird-conversation__scroll-container">
121145
<div className="sendbird-conversation__padding" />
122146
{/*
123147
To do: Implement windowing
@@ -126,7 +150,11 @@ export default class ConversationScroll extends Component {
126150
We hesitate to bring one more dependency to our library,
127151
we are planning to implement it inside the library
128152
*/}
129-
<div className="sendbird-conversation__messages-padding">
153+
<div
154+
className="sendbird-conversation__messages-padding"
155+
ref={scrollRef}
156+
onScroll={this.onScroll}
157+
>
130158
{
131159
allMessages.map(
132160
(m, idx) => {
@@ -176,7 +204,7 @@ export default class ConversationScroll extends Component {
176204
renderCustomMessage={renderCustomMessage}
177205
key={m.messageId || m.reqId}
178206
userId={userId}
179-
// show status for pending/failed messages
207+
handleScroll={this.handleScroll}
180208
message={m}
181209
quoteMessage={quoteMessage}
182210
scrollToMessage={scrollToMessage}
@@ -292,8 +320,8 @@ ConversationScroll.defaultProps = {
292320
replyType: 'NONE',
293321
emojiContainer: {},
294322
showScrollBot: false,
295-
onClickScrollBot: () => {},
296-
scrollToMessage: () => {},
323+
onClickScrollBot: () => { },
324+
scrollToMessage: () => { },
297325
emojiAllMap: new Map(),
298326
membersMap: new Map(),
299327
useMessageGrouping: true,

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export default function MessageHoc({
3838
setQuoteMessage,
3939
renderCustomMessage,
4040
currentGroupChannel,
41+
handleScroll,
4142
}) {
4243
const { sender = {} } = message;
4344
const [showEdit, setShowEdit] = useState(false);
@@ -48,6 +49,10 @@ export default function MessageHoc({
4849
const editMessageInputRef = useRef(null);
4950
const useMessageScrollRef = useRef(null);
5051

52+
useLayoutEffect(() => {
53+
handleScroll();
54+
}, [showEdit, message?.reactions?.length]);
55+
5156
useLayoutEffect(() => {
5257
if (highLightedMessageId === message.messageId) {
5358
if (useMessageScrollRef && useMessageScrollRef.current) {
@@ -166,7 +171,9 @@ export default function MessageHoc({
166171
replyType={replyType}
167172
nicknamesMap={membersMap}
168173
emojiContainer={emojiContainer}
169-
showEdit={setShowEdit}
174+
showEdit={() => {
175+
setShowEdit(true);
176+
}}
170177
showRemove={setShowRemove}
171178
showFileViewer={setShowFileViewer}
172179
resendMessage={resendMessage}
@@ -224,6 +231,7 @@ MessageHoc.propTypes = {
224231
sender: PropTypes.shape({ userId: PropTypes.string }),
225232
ogMetaData: PropTypes.shape({}),
226233
parentMessageId: PropTypes.number,
234+
reactions: PropTypes.arrayOf(PropTypes.number),
227235
}),
228236
animatedMessageId: PropTypes.oneOfType([
229237
PropTypes.string,
@@ -260,6 +268,7 @@ MessageHoc.propTypes = {
260268
messageId: PropTypes.string,
261269
}),
262270
setQuoteMessage: PropTypes.func.isRequired,
271+
handleScroll: PropTypes.func.isRequired,
263272
};
264273

265274
MessageHoc.defaultProps = {

src/smart-components/Conversation/components/conversation-scroll.scss

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
.sendbird-conversation__messages-padding {
55
padding-left: 24px;
66
padding-right: 24px;
7+
height: 100%;
8+
overflow: scroll;
79
}
810
.sendbird-separator,
911
.sendbird-admin-message {

src/smart-components/Conversation/utils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export const scrollIntoLast = (intialTry = 0) => {
1818
return;
1919
}
2020
try {
21-
const scrollDOM = document.querySelector('.sendbird-conversation__scroll-container');
21+
const scrollDOM = document.querySelector('.sendbird-conversation__messages-padding');
2222
// eslint-disable-next-line no-multi-assign
2323
scrollDOM.scrollTop = scrollDOM.scrollHeight;
2424
} catch (error) {

src/ui/MessageItemMenu/index.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ interface Props {
2323
isByMe?: boolean;
2424
disabled?: boolean;
2525
replyType?: ReplyType;
26-
showEdit?: (bool: boolean) => void;
26+
showEdit?: () => void;
2727
showRemove?: (bool: boolean) => void;
2828
resendMessage?: (message: UserMessage | FileMessage) => void;
2929
setQuoteMessage?: (message: UserMessage | FileMessage) => void;
@@ -126,7 +126,8 @@ export default function MessageItemMenu({
126126
className="sendbird-message-item-menu__list__menu-item menu-item-edit"
127127
onClick={() => {
128128
if (!disabled) {
129-
showEdit(true);
129+
// showEdit(true);
130+
showEdit();
130131
closeDropdown();
131132
}
132133
}}

0 commit comments

Comments
 (0)