Skip to content

Commit 22892d5

Browse files
authored
[UK-767]Implement scroll to message (#17)
* Implement js logic to scroll to message * Add CSS highlight for scroll to message
1 parent 228c03f commit 22892d5

File tree

11 files changed

+124
-24
lines changed

11 files changed

+124
-24
lines changed

src/index.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,10 @@ interface RenderChatItemProps {
316316
message: Sendbird.UserMessage
317317
) => void,
318318
);
319+
onScrollToMessage(
320+
createdAt: number,
321+
messageId: number,
322+
);
319323
onResendMessage: (
320324
failedMessage: SendBird.AdminMessage | SendBird.UserMessage | SendBird.FileMessage
321325
) => void;

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export default class ConversationScroll extends Component {
7979
scrollRef,
8080
membersMap,
8181
allMessages,
82+
scrollToMessage,
8283
useReaction,
8384
emojiAllMap,
8485
editDisabled,
@@ -150,6 +151,7 @@ export default class ConversationScroll extends Component {
150151
onDeleteMessage: deleteMessage,
151152
onUpdateMessage: updateMessage,
152153
onResendMessage: resendMessage,
154+
onScrollToMessage: scrollToMessage,
153155
emojiContainer,
154156
chainTop,
155157
chainBottom,
@@ -169,6 +171,7 @@ export default class ConversationScroll extends Component {
169171
userId={userId}
170172
// show status for pending/failed messages
171173
message={m}
174+
scrollToMessage={scrollToMessage}
172175
currentGroupChannel={currentGroupChannel}
173176
disabled={disabled}
174177
membersMap={membersMap}
@@ -246,6 +249,7 @@ ConversationScroll.propTypes = {
246249
]),
247250
renderChatItem: PropTypes.element,
248251
renderCustomMessage: PropTypes.func,
252+
scrollToMessage: PropTypes.func,
249253
useReaction: PropTypes.bool,
250254
showScrollBot: PropTypes.bool,
251255
onClickScrollBot: PropTypes.func,
@@ -271,6 +275,7 @@ ConversationScroll.defaultProps = {
271275
emojiContainer: {},
272276
showScrollBot: false,
273277
onClickScrollBot: () => {},
278+
scrollToMessage: () => {},
274279
emojiAllMap: new Map(),
275280
membersMap: new Map(),
276281
useMessageGrouping: true,

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export default function MessageHoc({
2222
hasSeparator,
2323
deleteMessage,
2424
updateMessage,
25+
scrollToMessage,
2526
resendMessage,
2627
useReaction,
2728
chainTop,
@@ -60,7 +61,7 @@ export default function MessageHoc({
6061
if (renderCustomMessage) {
6162
return renderCustomMessage(message, currentGroupChannel, chainTop, chainBottom);
6263
// TODO: Let's change this to object type on next major version up
63-
// and add params 'hasSeparator' and 'menuDisabled'
64+
// and add params 'hasSeparator' and 'menuDisabled', scrollToMessage
6465
}
6566
return null;
6667
}, [message, message.message, renderCustomMessage]);
@@ -75,7 +76,7 @@ export default function MessageHoc({
7576
ref={useMessageScrollRef}
7677
className={`
7778
sendbird-msg-hoc sendbird-msg--scroll-ref
78-
${isAnimated ? 'sendbird-msg-hoc__highlighted' : ''}
79+
${isAnimated ? 'sendbird-msg-hoc__animated' : ''}
7980
`}
8081
>
8182
{/* date-separator */}
@@ -130,6 +131,7 @@ export default function MessageHoc({
130131
<MessageContent
131132
className="sendbird-message-hoc__message-content"
132133
userId={userId}
134+
scrollToMessage={scrollToMessage}
133135
channel={currentGroupChannel}
134136
message={message}
135137
disabled={disabled}
@@ -201,6 +203,7 @@ MessageHoc.propTypes = {
201203
disabled: PropTypes.bool,
202204
editDisabled: PropTypes.bool,
203205
deleteMessage: PropTypes.func.isRequired,
206+
scrollToMessage: PropTypes.func,
204207
updateMessage: PropTypes.func.isRequired,
205208
resendMessage: PropTypes.func.isRequired,
206209
useReaction: PropTypes.bool.isRequired,
@@ -228,5 +231,6 @@ MessageHoc.defaultProps = {
228231
disabled: false,
229232
highLightedMessageId: null,
230233
toggleReaction: () => { },
234+
scrollToMessage: () => { },
231235
emojiContainer: {},
232236
};
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { useCallback } from 'react';
2+
import { SendbirdTypes } from '../../../types';
3+
import { Logger } from '../../../index';
4+
5+
interface useScrollToMessageDynamicParams {
6+
setIntialTimeStamp(ts: number): null;
7+
setHighLightedMessageId(id: number): null;
8+
allMessages: SendbirdTypes['BaseMessageInstance'][];
9+
}
10+
11+
interface useScrollToMessageStaticParams {
12+
logger: Logger;
13+
}
14+
15+
function useScrollToMessage({
16+
setIntialTimeStamp,
17+
setHighLightedMessageId,
18+
allMessages,
19+
}: useScrollToMessageDynamicParams, {
20+
logger,
21+
}: useScrollToMessageStaticParams): (createdAt: number, messageId: number) => void {
22+
return useCallback(
23+
(createdAt: number, messageId: number) => {
24+
const isPresent = allMessages.find((m) => (
25+
m.messageId === messageId
26+
));
27+
setHighLightedMessageId(null);
28+
setTimeout(() => {
29+
if (isPresent) {
30+
logger.info('Channel: scroll to message - message is present');
31+
setHighLightedMessageId(messageId);
32+
} else {
33+
logger.info('Channel: scroll to message - fetching older messages');
34+
setIntialTimeStamp(null);
35+
setIntialTimeStamp(createdAt);
36+
setHighLightedMessageId(messageId);
37+
}
38+
});
39+
}, [
40+
setIntialTimeStamp,
41+
setHighLightedMessageId,
42+
allMessages,
43+
],
44+
);
45+
}
46+
47+
export default useScrollToMessage;

src/smart-components/Conversation/index.jsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import useSendMessageCallback from './hooks/useSendMessageCallback';
2929
import useSendFileMessageCallback from './hooks/useSendFileMessageCallback';
3030
import useMemoizedEmojiListItems from './hooks/useMemoizedEmojiListItems';
3131
import useToggleReactionCallback from './hooks/useToggleReactionCallback';
32+
import useScrollToMessage from './hooks/useScrollToMessage';
3233

3334
import ConversationScroll from './components/ConversationScroll';
3435
import Notification from './components/Notification';
@@ -150,6 +151,12 @@ export const ConversationPanel = (props) => {
150151
sdk,
151152
});
152153

154+
const scrollToMessage = useScrollToMessage({
155+
setIntialTimeStamp,
156+
setHighLightedMessageId,
157+
allMessages,
158+
}, { logger });
159+
153160
// onScrollDownCallback is added for navigation to different timestamps on messageSearch
154161
// hasMoreToBottom, onScrollDownCallback -> scroll down
155162
// hasMore, onScrollCallback -> scroll up(default behavior)
@@ -344,6 +351,7 @@ export const ConversationPanel = (props) => {
344351
readStatus={readStatus}
345352
useReaction={usingReaction}
346353
allMessages={allMessages}
354+
scrollToMessage={scrollToMessage}
347355
emojiAllMap={emojiAllMap}
348356
membersMap={nicknamesMap}
349357
editDisabled={utils.isDisabledBecauseFrozen(currentGroupChannel)}

src/smart-components/Conversation/index.scss

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -47,31 +47,47 @@
4747
}
4848
}
4949

50-
.sendbird-msg-hoc__animated {
51-
.sendbird-user-message__text-balloon {
52-
.sendbird-user-message__text-balloon__inner {
53-
animation-name: sbHighlight;
54-
animation-duration: 1.6s;
55-
animation-fill-mode: forwards;
56-
}
57-
.sendbird-user-message__text-balloon__inner__text-place {
58-
.sendbird-label {
59-
animation-name: sbTextHighlight;
60-
animation-duration: 1.6s;
61-
animation-fill-mode: forwards;
62-
}
63-
}
50+
@keyframes sbHighlightBlock {
51+
0% {
52+
opacity: 0.5;
53+
background-color: #FFF2B6;
54+
}
55+
99% {
56+
opacity: 0.5;
57+
background-color: #FFF2B6;
6458
}
59+
}
6560

66-
.sendbird-file-message__tooltip {
61+
.sendbird-msg-hoc__animated {
62+
.sendbird-text-message-item-body,
63+
.sendbird-file-message-item-body {
6764
animation-name: sbHighlight;
6865
animation-duration: 1.6s;
6966
animation-fill-mode: forwards;
70-
.sendbird-file-message__tooltip__inner .sendbird-label {
71-
animation-name: sbTextHighlight;
72-
animation-duration: 1.6s;
73-
animation-fill-mode: forwards;
74-
}
67+
}
68+
69+
.sendbird-text-message-item-body__message,
70+
.sendbird-file-message-item-body__file-name__text {
71+
animation-name: sbTextHighlight;
72+
animation-duration: 1.6s;
73+
animation-fill-mode: forwards;
74+
}
75+
76+
77+
.sendbird-thumbnail-message-item-body
78+
.sendbird-thumbnail-message-item-body__image-cover {
79+
display: block;
80+
animation-name: sbHighlightBlock;
81+
animation-duration: 1.6s;
82+
animation-fill-mode: forwards;
83+
}
84+
85+
.sendbird-og-message-item-body
86+
.sendbird-og-message-item-body__cover {
87+
display: block;
88+
animation-name: sbHighlightBlock;
89+
animation-duration: 1.6s;
90+
animation-fill-mode: forwards;
7591
}
7692
}
7793

src/ui/MessageContent/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ interface Props {
4646
useReplying?: boolean;
4747
nicknamesMap?: Map<string, string>;
4848
emojiContainer?: EmojiContainer;
49+
scrollToMessage?: (createdAt: number, messageId: number) => void;
4950
showEdit?: (bool: boolean) => void;
5051
showRemove?: (bool: boolean) => void;
5152
showFileViewer?: (bool: boolean) => void;
@@ -61,6 +62,7 @@ export default function MessageContent({
6162
chainTop = false,
6263
chainBottom = false,
6364
useReaction,
65+
// scrollToMessage,
6466
// useReplying,
6567
nicknamesMap,
6668
emojiContainer,
@@ -177,7 +179,7 @@ export default function MessageContent({
177179
</Label>
178180
)}
179181
{/* {useReplying && (
180-
<ReplyingMessageAttachment replyingMessage={replyingMessage} />
182+
<ReplyingMessageAttachment scrollToMessage={scrollToMessage} replyingMessage={replyingMessage} />
181183
)} */}
182184
{/*
183185
A ReplyingMessage should have an another interface

src/ui/OGMessageItemBody/__tests__/__snapshots__/OGMessageItemBody.spec.js.snap

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,8 @@ exports[`OGMessageItemBody should do a snapshot test of the OGMessageItemBody DO
5252
className="sendbird-og-message-item-body__description"
5353
onClick={[Function]}
5454
/>
55+
<div
56+
className="sendbird-og-message-item-body__cover"
57+
/>
5558
</div>
5659
`;

src/ui/OGMessageItemBody/index.scss

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,14 @@
9292
}
9393
}
9494
}
95+
96+
.sendbird-og-message-item-body__cover {
97+
display: none;
98+
position: absolute;
99+
top: 0%;
100+
left: 0;
101+
width: 100%;
102+
height: 100%;
103+
border-radius: 16px 16px 0px 0px;
104+
}
95105
}

src/ui/OGMessageItemBody/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ export default function OGMessageItemBody({
134134
</Label>
135135
)}
136136
</div>
137+
<div className="sendbird-og-message-item-body__cover" />
137138
</div>
138139
);
139140
}

0 commit comments

Comments
 (0)