fix the scroll to bottom with button and on send message

pull/2142/head
Audric Ackermann 4 years ago
parent 7d9f970b2c
commit 4e638d162d
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -72,6 +72,7 @@ module.exports = {
getNextExpiringMessage, getNextExpiringMessage,
getMessagesByConversation, getMessagesByConversation,
getLastMessagesByConversation, getLastMessagesByConversation,
getOldestMessageInConversation,
getFirstUnreadMessageIdInConversation, getFirstUnreadMessageIdInConversation,
hasConversationOutgoingMessage, hasConversationOutgoingMessage,
trimMessages, trimMessages,
@ -2235,6 +2236,7 @@ function getUnreadCountByConversation(conversationId) {
// Note: Sorting here is necessary for getting the last message (with limit 1) // Note: Sorting here is necessary for getting the last message (with limit 1)
// be sure to update the sorting order to sort messages on redux too (sortMessages) // be sure to update the sorting order to sort messages on redux too (sortMessages)
const orderByClause = 'ORDER BY COALESCE(serverTimestamp, sent_at, received_at) DESC'; const orderByClause = 'ORDER BY COALESCE(serverTimestamp, sent_at, received_at) DESC';
const orderByClauseASC = 'ORDER BY COALESCE(serverTimestamp, sent_at, received_at) ASC';
function getMessagesByConversation(conversationId, { messageId = null } = {}) { function getMessagesByConversation(conversationId, { messageId = null } = {}) {
const absLimit = 20; const absLimit = 20;
@ -2317,6 +2319,23 @@ function getLastMessagesByConversation(conversationId, limit) {
return map(rows, row => jsonToObject(row.json)); return map(rows, row => jsonToObject(row.json));
} }
function getOldestMessageInConversation(conversationId) {
const rows = globalInstance
.prepare(
`
SELECT json FROM ${MESSAGES_TABLE} WHERE
conversationId = $conversationId
${orderByClauseASC}
LIMIT $limit;
`
)
.all({
conversationId,
limit: 1,
});
return map(rows, row => jsonToObject(row.json));
}
function hasConversationOutgoingMessage(conversationId) { function hasConversationOutgoingMessage(conversationId) {
const row = globalInstance const row = globalInstance
.prepare( .prepare(

@ -5,10 +5,6 @@ import { getShowScrollButton } from '../state/selectors/conversations';
import { SessionIconButton } from './icon'; import { SessionIconButton } from './icon';
type Props = {
onClick?: () => any;
};
const SessionScrollButtonDiv = styled.div` const SessionScrollButtonDiv = styled.div`
position: fixed; position: fixed;
z-index: 2; z-index: 2;
@ -16,7 +12,7 @@ const SessionScrollButtonDiv = styled.div`
animation: fadein var(--default-duration); animation: fadein var(--default-duration);
`; `;
export const SessionScrollButton = (props: Props) => { export const SessionScrollButton = (props: { onClickScrollBottom: () => void }) => {
const show = useSelector(getShowScrollButton); const show = useSelector(getShowScrollButton);
return ( return (
@ -25,7 +21,7 @@ export const SessionScrollButton = (props: Props) => {
iconType="chevron" iconType="chevron"
iconSize={'huge'} iconSize={'huge'}
isHidden={!show} isHidden={!show}
onClick={props.onClick} onClick={props.onClickScrollBottom}
/> />
</SessionScrollButtonDiv> </SessionScrollButtonDiv>
); );

@ -18,10 +18,11 @@ import autoBind from 'auto-bind';
import { InConversationCallContainer } from '../calling/InConversationCallContainer'; import { InConversationCallContainer } from '../calling/InConversationCallContainer';
import { SplitViewContainer } from '../SplitViewContainer'; import { SplitViewContainer } from '../SplitViewContainer';
import { LightboxGallery, MediaItemType } from '../lightbox/LightboxGallery'; import { LightboxGallery, MediaItemType } from '../lightbox/LightboxGallery';
import { getPubkeysInPublicConversation } from '../../data/data'; import { getLastMessageInConversation, getPubkeysInPublicConversation } from '../../data/data';
import { getConversationController } from '../../session/conversations'; import { getConversationController } from '../../session/conversations';
import { ToastUtils, UserUtils } from '../../session/utils'; import { ToastUtils, UserUtils } from '../../session/utils';
import { import {
openConversationToSpecificMessage,
quoteMessage, quoteMessage,
ReduxConversationType, ReduxConversationType,
resetSelectedMessageIds, resetSelectedMessageIds,
@ -168,12 +169,9 @@ export class SessionConversation extends React.Component<Props, State> {
return; return;
} }
const sendAndScroll = () => { const sendAndScroll = async () => {
void conversationModel.sendMessage(msg); void conversationModel.sendMessage(msg);
if (this.messageContainerRef.current) { await this.scrollToNow();
(this.messageContainerRef
.current as any).scrollTop = this.messageContainerRef.current?.scrollHeight;
}
}; };
// const recoveryPhrase = window.textsecure.storage.get('mnemonic'); // const recoveryPhrase = window.textsecure.storage.get('mnemonic');
@ -245,7 +243,10 @@ export class SessionConversation extends React.Component<Props, State> {
<SplitViewContainer <SplitViewContainer
top={<InConversationCallContainer />} top={<InConversationCallContainer />}
bottom={ bottom={
<SessionMessagesListContainer messageContainerRef={this.messageContainerRef} /> <SessionMessagesListContainer
messageContainerRef={this.messageContainerRef}
scrollToNow={this.scrollToNow}
/>
} }
disableTop={!this.props.hasOngoingCallWithFocusedConvo} disableTop={!this.props.hasOngoingCallWithFocusedConvo}
/> />
@ -268,6 +269,26 @@ export class SessionConversation extends React.Component<Props, State> {
); );
} }
private async scrollToNow() {
if (!this.props.selectedConversationKey) {
return;
}
const mostNowMessage = await getLastMessageInConversation(this.props.selectedConversationKey);
if (mostNowMessage) {
await openConversationToSpecificMessage({
conversationKey: this.props.selectedConversationKey,
messageIdToNavigateTo: mostNowMessage.id,
shouldHighlightMessage: false,
});
const messageContainer = this.messageContainerRef.current;
if (!messageContainer) {
return;
}
messageContainer.scrollTop = messageContainer.scrollHeight - messageContainer.clientHeight;
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~ KEYBOARD NAVIGATION ~~~~~~~~~~~~ // ~~~~~~~~~~~ KEYBOARD NAVIGATION ~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

@ -23,7 +23,6 @@ import {
getQuotedMessageToAnimate, getQuotedMessageToAnimate,
getSelectedConversation, getSelectedConversation,
getSelectedConversationKey, getSelectedConversationKey,
getShowScrollButton,
getSortedMessagesOfSelectedConversation, getSortedMessagesOfSelectedConversation,
isFirstUnreadMessageIdAbove, isFirstUnreadMessageIdAbove,
} from '../../state/selectors/conversations'; } from '../../state/selectors/conversations';
@ -76,9 +75,9 @@ type Props = SessionMessageListProps & {
messagesProps: Array<SortedMessageModelProps>; messagesProps: Array<SortedMessageModelProps>;
conversation?: ReduxConversationType; conversation?: ReduxConversationType;
showScrollButton: boolean;
animateQuotedMessageId: string | undefined; animateQuotedMessageId: string | undefined;
firstUnreadOnOpen: string | undefined; firstUnreadOnOpen: string | undefined;
scrollToNow: () => Promise<void>;
}; };
class SessionMessagesListContainerInner extends React.Component<Props> { class SessionMessagesListContainerInner extends React.Component<Props> {
@ -162,7 +161,10 @@ class SessionMessagesListContainerInner extends React.Component<Props> {
/> />
</ScrollToLoadedMessageContext.Provider> </ScrollToLoadedMessageContext.Provider>
<SessionScrollButton onClick={this.scrollToMostRecentMessage} key="scroll-down-button" /> <SessionScrollButton
onClickScrollBottom={this.props.scrollToNow}
key="scroll-down-button"
/>
</div> </div>
); );
} }
@ -249,14 +251,6 @@ class SessionMessagesListContainerInner extends React.Component<Props> {
} }
} }
private scrollToMostRecentMessage() {
const messageContainer = this.props.messageContainerRef.current;
if (!messageContainer) {
return;
}
messageContainer.scrollTop = messageContainer.scrollHeight - messageContainer.clientHeight;
}
private scrollPgUp() { private scrollPgUp() {
const messageContainer = this.props.messageContainerRef.current; const messageContainer = this.props.messageContainerRef.current;
if (!messageContainer) { if (!messageContainer) {
@ -326,7 +320,6 @@ const mapStateToProps = (state: StateType) => {
conversationKey: getSelectedConversationKey(state), conversationKey: getSelectedConversationKey(state),
conversation: getSelectedConversation(state), conversation: getSelectedConversation(state),
messagesProps: getSortedMessagesOfSelectedConversation(state), messagesProps: getSortedMessagesOfSelectedConversation(state),
showScrollButton: getShowScrollButton(state),
animateQuotedMessageId: getQuotedMessageToAnimate(state), animateQuotedMessageId: getQuotedMessageToAnimate(state),
firstUnreadOnOpen: getFirstUnreadMessageId(state), firstUnreadOnOpen: getFirstUnreadMessageId(state),
}; };

@ -825,6 +825,7 @@ class CompositionBoxInner extends React.Component<Props, State> {
: undefined; : undefined;
try { try {
// this does not call call removeAllStagedAttachmentsInConvers
const { attachments, previews } = await this.getFiles(linkPreview); const { attachments, previews } = await this.getFiles(linkPreview);
this.props.sendMessage({ this.props.sendMessage({
body: messagePlaintext, body: messagePlaintext,
@ -898,11 +899,6 @@ class CompositionBoxInner extends React.Component<Props, State> {
} }
} }
window.inboxStore?.dispatch(
removeAllStagedAttachmentsInConversation({
conversationKey: this.props.selectedConversationKey,
})
);
return { attachments, previews }; return { attachments, previews };
} }

@ -9,6 +9,7 @@ import {
getMessageContentSelectorProps, getMessageContentSelectorProps,
getMessageTextProps, getMessageTextProps,
getQuotedMessageToAnimate, getQuotedMessageToAnimate,
getShouldHighlightMessage,
} from '../../../../state/selectors/conversations'; } from '../../../../state/selectors/conversations';
import { import {
canDisplayImage, canDisplayImage,
@ -98,6 +99,7 @@ export const IsMessageVisibleContext = createContext(false);
export const MessageContent = (props: Props) => { export const MessageContent = (props: Props) => {
const [flashGreen, setFlashGreen] = useState(false); const [flashGreen, setFlashGreen] = useState(false);
const [didScroll, setDidScroll] = useState(false);
const contentProps = useSelector(state => const contentProps = useSelector(state =>
getMessageContentSelectorProps(state as any, props.messageId) getMessageContentSelectorProps(state as any, props.messageId)
); );
@ -123,20 +125,28 @@ export const MessageContent = (props: Props) => {
}, [setImageBroken]); }, [setImageBroken]);
const quotedMessageToAnimate = useSelector(getQuotedMessageToAnimate); const quotedMessageToAnimate = useSelector(getQuotedMessageToAnimate);
const shouldHighlightMessage = useSelector(getShouldHighlightMessage);
const isQuotedMessageToAnimate = quotedMessageToAnimate === props.messageId; const isQuotedMessageToAnimate = quotedMessageToAnimate === props.messageId;
useLayoutEffect(() => { useLayoutEffect(() => {
if (isQuotedMessageToAnimate) { if (isQuotedMessageToAnimate) {
if (!flashGreen) { if (!flashGreen && !didScroll) {
//scroll to me and flash me //scroll to me and flash me
scrollToLoadedMessage(props.messageId, 'quote-or-search-result'); scrollToLoadedMessage(props.messageId, 'quote-or-search-result');
setFlashGreen(true); setDidScroll(true);
if (shouldHighlightMessage) {
setFlashGreen(true);
}
} }
return; return;
} }
if (flashGreen) { if (flashGreen) {
setFlashGreen(false); setFlashGreen(false);
} }
if (didScroll) {
setDidScroll(false);
}
return; return;
}); });

@ -71,6 +71,7 @@ export const MessageQuote = (props: Props) => {
void openConversationToSpecificMessage({ void openConversationToSpecificMessage({
conversationKey: foundInDb.get('conversationId'), conversationKey: foundInDb.get('conversationId'),
messageIdToNavigateTo: foundInDb.get('id'), messageIdToNavigateTo: foundInDb.get('id'),
shouldHighlightMessage: true,
}); });
}, },
[quote, multiSelectMode, props.messageId] [quote, multiSelectMode, props.messageId]

@ -140,6 +140,7 @@ export const MessageSearchResult = (props: MessageResultProps) => {
void openConversationToSpecificMessage({ void openConversationToSpecificMessage({
conversationKey: conversationId, conversationKey: conversationId,
messageIdToNavigateTo: id, messageIdToNavigateTo: id,
shouldHighlightMessage: true,
}); });
}} }}
className={classNames('module-message-search-result')} className={classNames('module-message-search-result')}

@ -128,6 +128,7 @@ const channelsToMake = {
getNextExpiringMessage, getNextExpiringMessage,
getMessagesByConversation, getMessagesByConversation,
getLastMessagesByConversation, getLastMessagesByConversation,
getOldestMessageInConversation,
getFirstUnreadMessageIdInConversation, getFirstUnreadMessageIdInConversation,
hasConversationOutgoingMessage, hasConversationOutgoingMessage,
getSeenMessagesByHashList, getSeenMessagesByHashList,
@ -799,6 +800,26 @@ export async function getLastMessagesByConversation(
return new MessageCollection(messages); return new MessageCollection(messages);
} }
export async function getLastMessageInConversation(conversationId: string) {
const messages = await channels.getLastMessagesByConversation(conversationId, 1);
for (const message of messages) {
message.skipTimerInit = true;
}
const collection = new MessageCollection(messages);
return collection.length ? collection.models[0] : null;
}
export async function getOldestMessageInConversation(conversationId: string) {
const messages = await channels.getOldestMessageInConversation(conversationId);
for (const message of messages) {
message.skipTimerInit = true;
}
const collection = new MessageCollection(messages);
return collection.length ? collection.models[0] : null;
}
/** /**
* @returns Returns count of all messages in the database * @returns Returns count of all messages in the database
*/ */

@ -218,8 +218,6 @@ async function handleRegularMessage(
const type = message.get('type'); const type = message.get('type');
await copyFromQuotedMessage(message, rawDataMessage.quote); await copyFromQuotedMessage(message, rawDataMessage.quote);
const now = Date.now();
if (rawDataMessage.openGroupInvitation) { if (rawDataMessage.openGroupInvitation) {
message.set({ groupInvitation: rawDataMessage.openGroupInvitation }); message.set({ groupInvitation: rawDataMessage.openGroupInvitation });
} }

@ -1,6 +1,11 @@
import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit'; import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit';
import { getConversationController } from '../../session/conversations'; import { getConversationController } from '../../session/conversations';
import { getFirstUnreadMessageIdInConversation, getMessagesByConversation } from '../../data/data'; import {
getFirstUnreadMessageIdInConversation,
getLastMessageInConversation,
getMessagesByConversation,
getOldestMessageInConversation,
} from '../../data/data';
import { import {
ConversationNotificationSettingType, ConversationNotificationSettingType,
ConversationTypeEnum, ConversationTypeEnum,
@ -279,6 +284,7 @@ export type ConversationsStateType = {
showScrollButton: boolean; showScrollButton: boolean;
animateQuotedMessageId?: string; animateQuotedMessageId?: string;
shouldHighlightMessage: boolean;
nextMessageToPlayId?: string; nextMessageToPlayId?: string;
mentionMembers: MentionsMembersType; mentionMembers: MentionsMembersType;
}; };
@ -321,7 +327,7 @@ type FetchedTopMessageResults = {
conversationKey: string; conversationKey: string;
messagesProps: Array<MessageModelPropsWithoutConvoProps>; messagesProps: Array<MessageModelPropsWithoutConvoProps>;
oldTopMessageId: string | null; oldTopMessageId: string | null;
}; } | null;
export const fetchTopMessagesForConversation = createAsyncThunk( export const fetchTopMessagesForConversation = createAsyncThunk(
'messages/fetchTopByConversationKey', 'messages/fetchTopByConversationKey',
@ -332,6 +338,13 @@ export const fetchTopMessagesForConversation = createAsyncThunk(
conversationKey: string; conversationKey: string;
oldTopMessageId: string | null; oldTopMessageId: string | null;
}): Promise<FetchedTopMessageResults> => { }): Promise<FetchedTopMessageResults> => {
// no need to load more top if we are already at the top
const oldestMessage = await getOldestMessageInConversation(conversationKey);
if (!oldestMessage || oldestMessage.id === oldTopMessageId) {
window.log.info('fetchTopMessagesForConversation: we are already at the top');
return null;
}
const beforeTimestamp = Date.now(); const beforeTimestamp = Date.now();
const messagesProps = await getMessages({ const messagesProps = await getMessages({
conversationKey, conversationKey,
@ -352,7 +365,7 @@ type FetchedBottomMessageResults = {
conversationKey: string; conversationKey: string;
messagesProps: Array<MessageModelPropsWithoutConvoProps>; messagesProps: Array<MessageModelPropsWithoutConvoProps>;
oldBottomMessageId: string | null; oldBottomMessageId: string | null;
}; } | null;
export const fetchBottomMessagesForConversation = createAsyncThunk( export const fetchBottomMessagesForConversation = createAsyncThunk(
'messages/fetchBottomByConversationKey', 'messages/fetchBottomByConversationKey',
@ -364,6 +377,13 @@ export const fetchBottomMessagesForConversation = createAsyncThunk(
oldBottomMessageId: string | null; oldBottomMessageId: string | null;
}): Promise<FetchedBottomMessageResults> => { }): Promise<FetchedBottomMessageResults> => {
const beforeTimestamp = Date.now(); const beforeTimestamp = Date.now();
// no need to load more bottom if we are already at the bottom
const mostRecentMessage = await getLastMessageInConversation(conversationKey);
if (!mostRecentMessage || mostRecentMessage.id === oldBottomMessageId) {
window.log.info('fetchBottomMessagesForConversation: we are already at the bottom');
return null;
}
const messagesProps = await getMessages({ const messagesProps = await getMessages({
conversationKey, conversationKey,
messageId: oldBottomMessageId, messageId: oldBottomMessageId,
@ -395,6 +415,7 @@ export function getEmptyConversationState(): ConversationsStateType {
firstUnreadMessageId: undefined, firstUnreadMessageId: undefined,
oldTopMessageId: null, oldTopMessageId: null,
oldBottomMessageId: null, oldBottomMessageId: null,
shouldHighlightMessage: false,
}; };
} }
@ -439,6 +460,9 @@ function handleMessageChanged(
state: ConversationsStateType, state: ConversationsStateType,
changedMessage: MessageModelPropsWithoutConvoProps changedMessage: MessageModelPropsWithoutConvoProps
) { ) {
if (state.selectedConversation !== changedMessage.propsForMessage.convoId) {
return state;
}
const messageInStoreIndex = state?.messages?.findIndex( const messageInStoreIndex = state?.messages?.findIndex(
m => m.propsForMessage.id === changedMessage.propsForMessage.id m => m.propsForMessage.id === changedMessage.propsForMessage.id
); );
@ -650,13 +674,6 @@ const conversationsSlice = createSlice({
return state; return state;
}, },
messageChanged(
state: ConversationsStateType,
action: PayloadAction<MessageModelPropsWithoutConvoProps>
) {
return handleMessageChanged(state, action.payload);
},
messagesChanged( messagesChanged(
state: ConversationsStateType, state: ConversationsStateType,
action: PayloadAction<Array<MessageModelPropsWithoutConvoProps>> action: PayloadAction<Array<MessageModelPropsWithoutConvoProps>>
@ -696,6 +713,7 @@ const conversationsSlice = createSlice({
// keep the unread visible just like in other apps. It will be shown until the user changes convo // keep the unread visible just like in other apps. It will be shown until the user changes convo
return { return {
...state, ...state,
shouldHighlightMessage: false,
firstUnreadMessageId: undefined, firstUnreadMessageId: undefined,
}; };
}, },
@ -728,6 +746,7 @@ const conversationsSlice = createSlice({
nextMessageToPlay: undefined, nextMessageToPlay: undefined,
showScrollButton: false, showScrollButton: false,
animateQuotedMessageId: undefined, animateQuotedMessageId: undefined,
shouldHighlightMessage: false,
oldTopMessageId: null, oldTopMessageId: null,
oldBottomMessageId: null, oldBottomMessageId: null,
mentionMembers: [], mentionMembers: [],
@ -739,6 +758,7 @@ const conversationsSlice = createSlice({
action: PayloadAction<{ action: PayloadAction<{
conversationKey: string; conversationKey: string;
messageIdToNavigateTo: string; messageIdToNavigateTo: string;
shouldHighlightMessage: boolean;
initialMessages: Array<MessageModelPropsWithoutConvoProps>; initialMessages: Array<MessageModelPropsWithoutConvoProps>;
}> }>
) { ) {
@ -750,6 +770,7 @@ const conversationsSlice = createSlice({
messages: action.payload.initialMessages, messages: action.payload.initialMessages,
showScrollButton: true, showScrollButton: true,
animateQuotedMessageId: action.payload.messageIdToNavigateTo, animateQuotedMessageId: action.payload.messageIdToNavigateTo,
shouldHighlightMessage: action.payload.shouldHighlightMessage,
oldTopMessageId: null, oldTopMessageId: null,
oldBottomMessageId: null, oldBottomMessageId: null,
}; };
@ -785,6 +806,7 @@ const conversationsSlice = createSlice({
action: PayloadAction<string | undefined> action: PayloadAction<string | undefined>
) { ) {
state.animateQuotedMessageId = action.payload; state.animateQuotedMessageId = action.payload;
state.shouldHighlightMessage = Boolean(state.animateQuotedMessageId);
return state; return state;
}, },
setNextMessageToPlayId( setNextMessageToPlayId(
@ -808,6 +830,9 @@ const conversationsSlice = createSlice({
builder.addCase( builder.addCase(
fetchTopMessagesForConversation.fulfilled, fetchTopMessagesForConversation.fulfilled,
(state: ConversationsStateType, action: PayloadAction<FetchedTopMessageResults>) => { (state: ConversationsStateType, action: PayloadAction<FetchedTopMessageResults>) => {
if (!action.payload) {
return state;
}
// this is called once the messages are loaded from the db for the currently selected conversation // this is called once the messages are loaded from the db for the currently selected conversation
const { messagesProps, conversationKey, oldTopMessageId } = action.payload; const { messagesProps, conversationKey, oldTopMessageId } = action.payload;
// double check that this update is for the shown convo // double check that this update is for the shown convo
@ -831,6 +856,9 @@ const conversationsSlice = createSlice({
builder.addCase( builder.addCase(
fetchBottomMessagesForConversation.fulfilled, fetchBottomMessagesForConversation.fulfilled,
(state: ConversationsStateType, action: PayloadAction<FetchedBottomMessageResults>) => { (state: ConversationsStateType, action: PayloadAction<FetchedBottomMessageResults>) => {
if (!action.payload) {
return state;
}
// this is called once the messages are loaded from the db for the currently selected conversation // this is called once the messages are loaded from the db for the currently selected conversation
const { messagesProps, conversationKey, oldBottomMessageId } = action.payload; const { messagesProps, conversationKey, oldBottomMessageId } = action.payload;
// double check that this update is for the shown convo // double check that this update is for the shown convo
@ -893,7 +921,6 @@ export const {
messagesAdded, messagesAdded,
messageDeleted, messageDeleted,
conversationReset, conversationReset,
messageChanged,
messagesChanged, messagesChanged,
resetOldTopMessageId, resetOldTopMessageId,
resetOldBottomMessageId, resetOldBottomMessageId,
@ -938,8 +965,9 @@ export async function openConversationWithMessages(args: {
export async function openConversationToSpecificMessage(args: { export async function openConversationToSpecificMessage(args: {
conversationKey: string; conversationKey: string;
messageIdToNavigateTo: string; messageIdToNavigateTo: string;
shouldHighlightMessage: boolean;
}) { }) {
const { conversationKey, messageIdToNavigateTo } = args; const { conversationKey, messageIdToNavigateTo, shouldHighlightMessage } = args;
const messagesAroundThisMessage = await getMessages({ const messagesAroundThisMessage = await getMessages({
conversationKey, conversationKey,
@ -950,6 +978,7 @@ export async function openConversationToSpecificMessage(args: {
actions.openConversationToSpecificMessage({ actions.openConversationToSpecificMessage({
conversationKey, conversationKey,
messageIdToNavigateTo, messageIdToNavigateTo,
shouldHighlightMessage,
initialMessages: messagesAroundThisMessage, initialMessages: messagesAroundThisMessage,
}) })
); );

@ -612,6 +612,12 @@ export const getQuotedMessageToAnimate = createSelector(
(state: ConversationsStateType): string | undefined => state.animateQuotedMessageId || undefined (state: ConversationsStateType): string | undefined => state.animateQuotedMessageId || undefined
); );
export const getShouldHighlightMessage = createSelector(
getConversations,
(state: ConversationsStateType): boolean =>
Boolean(state.animateQuotedMessageId && state.shouldHighlightMessage)
);
export const getNextMessageToPlayId = createSelector( export const getNextMessageToPlayId = createSelector(
getConversations, getConversations,
(state: ConversationsStateType): string | undefined => state.nextMessageToPlayId || undefined (state: ConversationsStateType): string | undefined => state.nextMessageToPlayId || undefined

Loading…
Cancel
Save