mirror of
https://github.com/oxen-io/session-desktop.git
synced 2023-12-14 02:12:57 +01:00
cleanup scroll to unread of quote or search result on open
This commit is contained in:
parent
d269693544
commit
792c23da87
11 changed files with 169 additions and 138 deletions
|
@ -275,6 +275,9 @@ $session-highlight-message-shadow: 0px 0px 10px 1px $session-color-green;
|
|||
|
||||
@keyframes remove-box-shadow {
|
||||
0% {
|
||||
box-shadow: none;
|
||||
}
|
||||
10% {
|
||||
box-shadow: $session-highlight-message-shadow;
|
||||
}
|
||||
75% {
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import React from 'react';
|
||||
import React, { useContext, useLayoutEffect, useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import styled from 'styled-components';
|
||||
import { getQuotedMessageToAnimate } from '../../state/selectors/conversations';
|
||||
import { ScrollToLoadedMessageContext } from './SessionMessagesListContainer';
|
||||
|
||||
const LastSeenBarContainer = styled.div`
|
||||
padding-bottom: 35px;
|
||||
|
@ -26,14 +29,29 @@ const LastSeenText = styled.div`
|
|||
color: var(--color-last-seen-indicator-text);
|
||||
`;
|
||||
|
||||
export const SessionLastSeenIndicator = () => {
|
||||
const { i18n } = window;
|
||||
const text = i18n('unreadMessages');
|
||||
export const SessionLastSeenIndicator = (props: { messageId: string }) => {
|
||||
// if this unread-indicator is not unique it's going to cause issues
|
||||
const [didScroll, setDidScroll] = useState(false);
|
||||
const quotedMessageToAnimate = useSelector(getQuotedMessageToAnimate);
|
||||
|
||||
const scrollToLoadedMessage = useContext(ScrollToLoadedMessageContext);
|
||||
|
||||
// if this unread-indicator is rendered,
|
||||
// we want to scroll here only if the conversation was not opened to a specific message
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (!quotedMessageToAnimate && !didScroll) {
|
||||
scrollToLoadedMessage(props.messageId, 'unread-indicator');
|
||||
setDidScroll(true);
|
||||
} else if (quotedMessageToAnimate) {
|
||||
setDidScroll(true);
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<LastSeenBarContainer id="unread-indicator">
|
||||
<LastSeenBar>
|
||||
<LastSeenText>{text}</LastSeenText>
|
||||
<LastSeenText>{window.i18n('unreadMessages')}</LastSeenText>
|
||||
</LastSeenBar>
|
||||
</LastSeenBarContainer>
|
||||
);
|
||||
|
|
|
@ -85,7 +85,7 @@ export const SessionMessagesList = (props: {
|
|||
{messagesProps.map(messageProps => {
|
||||
const messageId = messageProps.message.props.messageId;
|
||||
const unreadIndicator = messageProps.showUnreadIndicator ? (
|
||||
<SessionLastSeenIndicator key={`unread-indicator-${messageId}`} />
|
||||
<SessionLastSeenIndicator key={`unread-indicator-${messageId}`} messageId={messageId} />
|
||||
) : null;
|
||||
|
||||
const dateBreak =
|
||||
|
|
|
@ -15,7 +15,6 @@ import {
|
|||
ReduxConversationType,
|
||||
resetOldBottomMessageId,
|
||||
resetOldTopMessageId,
|
||||
showScrollToBottomButton,
|
||||
SortedMessageModelProps,
|
||||
} from '../../state/ducks/conversations';
|
||||
import { StateType } from '../../state/reducer';
|
||||
|
@ -34,9 +33,18 @@ export type SessionMessageListProps = {
|
|||
messageContainerRef: React.RefObject<HTMLDivElement>;
|
||||
};
|
||||
|
||||
export const messageContainerDomID = 'messages-container';
|
||||
|
||||
export type ScrollToLoadedReasons =
|
||||
| 'quote-or-search-result'
|
||||
| 'go-to-bottom'
|
||||
| 'unread-indicator'
|
||||
| 'load-more-top'
|
||||
| 'load-more-bottom';
|
||||
|
||||
export const ScrollToLoadedMessageContext = React.createContext(
|
||||
// tslint:disable-next-line: no-empty
|
||||
(_loadedMessageIdToScrollTo: string) => {}
|
||||
(_loadedMessageIdToScrollTo: string, _reason: ScrollToLoadedReasons) => {}
|
||||
);
|
||||
|
||||
const SessionUnreadAboveIndicator = styled.div`
|
||||
|
@ -85,10 +93,6 @@ class SessionMessagesListContainerInner extends React.Component<Props> {
|
|||
// ~~~~~~~~~~~~~~~~ LIFECYCLES ~~~~~~~~~~~~~~~~
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
public componentDidMount() {
|
||||
this.initialMessageLoadingPosition();
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
if (this.timeoutResetQuotedScroll) {
|
||||
global.clearTimeout(this.timeoutResetQuotedScroll);
|
||||
|
@ -108,7 +112,6 @@ class SessionMessagesListContainerInner extends React.Component<Props> {
|
|||
) {
|
||||
this.setupTimeoutResetQuotedHighlightedMessage(this.props.animateQuotedMessageId);
|
||||
// displayed conversation changed. We have a bit of cleaning to do here
|
||||
this.initialMessageLoadingPosition();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,6 +132,7 @@ class SessionMessagesListContainerInner extends React.Component<Props> {
|
|||
return (
|
||||
<div
|
||||
className="messages-container"
|
||||
id={messageContainerDomID}
|
||||
onScroll={this.handleScroll}
|
||||
ref={this.props.messageContainerRef}
|
||||
data-testid="messages-container"
|
||||
|
@ -143,18 +147,13 @@ class SessionMessagesListContainerInner extends React.Component<Props> {
|
|||
key="typing-bubble"
|
||||
/>
|
||||
|
||||
<ScrollToLoadedMessageContext.Provider value={this.scrollToQuoteMessage}>
|
||||
<ScrollToLoadedMessageContext.Provider value={this.scrollToLoadedMessage}>
|
||||
<SessionMessagesList
|
||||
scrollAfterLoadMore={(
|
||||
messageIdToScrollTo: string,
|
||||
type: 'load-more-top' | 'load-more-bottom'
|
||||
) => {
|
||||
const isLoadMoreTop = type === 'load-more-top';
|
||||
const isLoadMoreBottom = type === 'load-more-bottom';
|
||||
this.scrollToMessage(messageIdToScrollTo, isLoadMoreTop ? 'start' : 'end', {
|
||||
isLoadMoreTop,
|
||||
isLoadMoreBottom,
|
||||
});
|
||||
this.scrollToMessage(messageIdToScrollTo, type);
|
||||
}}
|
||||
onPageDownPressed={this.scrollPgDown}
|
||||
onPageUpPressed={this.scrollPgUp}
|
||||
|
@ -175,43 +174,6 @@ class SessionMessagesListContainerInner extends React.Component<Props> {
|
|||
contextMenu.hideAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Position the list to the middle of the loaded list if the conversation has unread messages and we have some messages loaded
|
||||
*/
|
||||
private initialMessageLoadingPosition() {
|
||||
const { messagesProps, conversation, firstUnreadOnOpen } = this.props;
|
||||
if (!conversation || !messagesProps.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
(conversation.unreadCount && conversation.unreadCount <= 0) ||
|
||||
firstUnreadOnOpen === undefined
|
||||
) {
|
||||
this.scrollToMostRecentMessage();
|
||||
} else {
|
||||
// just assume that this need to be shown by default
|
||||
window.inboxStore?.dispatch(showScrollToBottomButton(true));
|
||||
const firstUnreadIndex = messagesProps.findIndex(
|
||||
m => m.propsForMessage.id === firstUnreadOnOpen
|
||||
);
|
||||
|
||||
if (firstUnreadIndex === -1) {
|
||||
// the first unread message is not in the 30 most recent messages
|
||||
// just scroll to the middle as we don't have enough loaded message nevertheless
|
||||
const middle = Math.floor(messagesProps.length / 2);
|
||||
const idToStringTo = messagesProps[middle].propsForMessage.id;
|
||||
this.scrollToMessage(idToStringTo, 'center');
|
||||
} else {
|
||||
const messageElementDom = document.getElementById('unread-indicator');
|
||||
messageElementDom?.scrollIntoView({
|
||||
behavior: 'auto',
|
||||
block: 'center',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Could not find a better name, but when we click on a quoted message,
|
||||
* the UI takes us there and highlights it.
|
||||
|
@ -233,27 +195,57 @@ class SessionMessagesListContainerInner extends React.Component<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
private scrollToMessage(
|
||||
messageId: string,
|
||||
block: ScrollLogicalPosition | undefined,
|
||||
options?: { isLoadMoreTop: boolean | undefined; isLoadMoreBottom: boolean | undefined }
|
||||
) {
|
||||
private scrollToMessage(messageId: string, reason: ScrollToLoadedReasons) {
|
||||
const messageElementDom = document.getElementById(`msg-${messageId}`);
|
||||
// annoyingly, useLayoutEffect, which is calling this function, is run before ref are set on a react component.
|
||||
// so the only way to scroll in the container at this time, is with the DOM itself
|
||||
const messageContainerDom = document.getElementById(messageContainerDomID);
|
||||
|
||||
messageElementDom?.scrollIntoView({
|
||||
behavior: 'auto',
|
||||
block,
|
||||
});
|
||||
// * if quote or search result we want to scroll to start AND do a -50px
|
||||
// * if scroll-to-unread we want to scroll end AND do a +200px to be really at the end
|
||||
// * if load-more-top or bottom we want to center
|
||||
|
||||
this.props.messageContainerRef.current?.scrollBy({ top: -50 });
|
||||
switch (reason) {
|
||||
case 'load-more-bottom':
|
||||
messageElementDom?.scrollIntoView({
|
||||
behavior: 'auto',
|
||||
block: 'end',
|
||||
});
|
||||
// reset the oldBottomInRedux so that a refresh/new message does not scroll us back here again
|
||||
window.inboxStore?.dispatch(resetOldBottomMessageId());
|
||||
break;
|
||||
case 'load-more-top':
|
||||
messageElementDom?.scrollIntoView({
|
||||
behavior: 'auto',
|
||||
block: 'start',
|
||||
});
|
||||
// reset the oldTopInRedux so that a refresh/new message does not scroll us back here again
|
||||
window.inboxStore?.dispatch(resetOldTopMessageId());
|
||||
break;
|
||||
case 'quote-or-search-result':
|
||||
messageElementDom?.scrollIntoView({
|
||||
behavior: 'auto',
|
||||
block: 'start',
|
||||
});
|
||||
messageContainerDom?.scrollBy({ top: -50 });
|
||||
|
||||
if (options?.isLoadMoreTop) {
|
||||
// reset the oldTopInRedux so that a refresh/new message does not scroll us back here again
|
||||
window.inboxStore?.dispatch(resetOldTopMessageId());
|
||||
}
|
||||
if (options?.isLoadMoreBottom) {
|
||||
// reset the oldBottomInRedux so that a refresh/new message does not scroll us back here again
|
||||
window.inboxStore?.dispatch(resetOldBottomMessageId());
|
||||
break;
|
||||
case 'go-to-bottom':
|
||||
messageElementDom?.scrollIntoView({
|
||||
behavior: 'auto',
|
||||
block: 'end',
|
||||
});
|
||||
messageContainerDom?.scrollBy({ top: 200 });
|
||||
|
||||
break;
|
||||
case 'unread-indicator':
|
||||
messageElementDom?.scrollIntoView({
|
||||
behavior: 'auto',
|
||||
block: 'center',
|
||||
});
|
||||
messageContainerDom?.scrollBy({ top: -50 });
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,8 +299,8 @@ class SessionMessagesListContainerInner extends React.Component<Props> {
|
|||
messageContainer.scrollTo(0, 0);
|
||||
}
|
||||
|
||||
private scrollToQuoteMessage(loadedQuoteMessageToScrollTo: string) {
|
||||
if (!this.props.conversationKey || !loadedQuoteMessageToScrollTo) {
|
||||
private scrollToLoadedMessage(loadedMessageToScrollTo: string, reason: ScrollToLoadedReasons) {
|
||||
if (!this.props.conversationKey || !loadedMessageToScrollTo) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -316,14 +308,16 @@ class SessionMessagesListContainerInner extends React.Component<Props> {
|
|||
|
||||
// If there's no message already in memory, we won't be scrolling. So we'll gather
|
||||
// some more information then show an informative toast to the user.
|
||||
if (!messagesProps.find(m => m.propsForMessage.id === loadedQuoteMessageToScrollTo)) {
|
||||
if (!messagesProps.find(m => m.propsForMessage.id === loadedMessageToScrollTo)) {
|
||||
throw new Error('this message is not loaded');
|
||||
}
|
||||
|
||||
this.scrollToMessage(loadedQuoteMessageToScrollTo, 'start');
|
||||
this.scrollToMessage(loadedMessageToScrollTo, reason);
|
||||
// Highlight this message on the UI
|
||||
window.inboxStore?.dispatch(quotedMessageToAnimate(loadedQuoteMessageToScrollTo));
|
||||
this.setupTimeoutResetQuotedHighlightedMessage(loadedQuoteMessageToScrollTo);
|
||||
if (reason === 'quote-or-search-result') {
|
||||
window.inboxStore?.dispatch(quotedMessageToAnimate(loadedMessageToScrollTo));
|
||||
this.setupTimeoutResetQuotedHighlightedMessage(loadedMessageToScrollTo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ export const MessageContent = (props: Props) => {
|
|||
);
|
||||
const [isMessageVisible, setMessageIsVisible] = useState(false);
|
||||
|
||||
const scrollToMessage = useContext(ScrollToLoadedMessageContext);
|
||||
const scrollToLoadedMessage = useContext(ScrollToLoadedMessageContext);
|
||||
|
||||
const [imageBroken, setImageBroken] = useState(false);
|
||||
|
||||
|
@ -129,7 +129,7 @@ export const MessageContent = (props: Props) => {
|
|||
if (isQuotedMessageToAnimate) {
|
||||
if (!flashGreen) {
|
||||
//scroll to me and flash me
|
||||
scrollToMessage(props.messageId);
|
||||
scrollToLoadedMessage(props.messageId, 'quote-or-search-result');
|
||||
setFlashGreen(true);
|
||||
}
|
||||
return;
|
||||
|
|
|
@ -27,7 +27,6 @@ export const MessageQuote = (props: Props) => {
|
|||
const multiSelectMode = useSelector(isMessageSelectionMode);
|
||||
const isMessageDetailViewMode = useSelector(isMessageDetailView);
|
||||
|
||||
// const scrollToLoadedMessage = useContext(ScrollToLoadedMessageContext);
|
||||
const quote = selected ? selected.quote : undefined;
|
||||
const direction = selected ? selected.direction : undefined;
|
||||
|
||||
|
@ -73,12 +72,6 @@ export const MessageQuote = (props: Props) => {
|
|||
conversationKey: foundInDb.get('conversationId'),
|
||||
messageIdToNavigateTo: foundInDb.get('id'),
|
||||
});
|
||||
|
||||
// scrollToLoadedMessage?.({
|
||||
// quoteAuthor: sender,
|
||||
// quoteId,
|
||||
// referencedMessageNotFound: referencedMessageNotFound || false,
|
||||
// });
|
||||
},
|
||||
[quote, multiSelectMode, props.messageId]
|
||||
);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import _, { noop } from 'lodash';
|
||||
import React, { useCallback } from 'react';
|
||||
import React, { useCallback, useContext, useLayoutEffect, useState } from 'react';
|
||||
import { InView } from 'react-intersection-observer';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { getMessageById } from '../../../../data/data';
|
||||
|
@ -13,13 +13,16 @@ import {
|
|||
import {
|
||||
areMoreBottomMessagesBeingFetched,
|
||||
areMoreTopMessagesBeingFetched,
|
||||
getFirstUnreadMessageId,
|
||||
getLoadedMessagesLength,
|
||||
getMostRecentMessageId,
|
||||
getOldestMessageId,
|
||||
getQuotedMessageToAnimate,
|
||||
getSelectedConversationKey,
|
||||
getYoungestMessageId,
|
||||
} from '../../../../state/selectors/conversations';
|
||||
import { getIsAppFocused } from '../../../../state/selectors/section';
|
||||
import { ScrollToLoadedMessageContext } from '../../SessionMessagesListContainer';
|
||||
|
||||
type ReadableMessageProps = {
|
||||
children: React.ReactNode;
|
||||
|
@ -67,21 +70,44 @@ export const ReadableMessage = (props: ReadableMessageProps) => {
|
|||
const youngestMessageId = useSelector(getYoungestMessageId);
|
||||
const fetchingTopMore = useSelector(areMoreTopMessagesBeingFetched);
|
||||
const fetchingBottomMore = useSelector(areMoreBottomMessagesBeingFetched);
|
||||
const conversationHasUnread = Boolean(useSelector(getFirstUnreadMessageId));
|
||||
const shouldMarkReadWhenVisible = isUnread;
|
||||
|
||||
const [didScroll, setDidScroll] = useState(false);
|
||||
const quotedMessageToAnimate = useSelector(getQuotedMessageToAnimate);
|
||||
|
||||
const scrollToLoadedMessage = useContext(ScrollToLoadedMessageContext);
|
||||
|
||||
// if this unread-indicator is rendered,
|
||||
// we want to scroll here only if the conversation was not opened to a specific message
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (
|
||||
props.messageId === youngestMessageId &&
|
||||
!quotedMessageToAnimate &&
|
||||
!didScroll &&
|
||||
!conversationHasUnread
|
||||
) {
|
||||
scrollToLoadedMessage(props.messageId, 'go-to-bottom');
|
||||
setDidScroll(true);
|
||||
} else if (quotedMessageToAnimate) {
|
||||
setDidScroll(true);
|
||||
}
|
||||
});
|
||||
|
||||
const onVisible = useCallback(
|
||||
// tslint:disable-next-line: cyclomatic-complexity
|
||||
async (inView: boolean | Object) => {
|
||||
// we are the most recent message
|
||||
if (mostRecentMessageId === messageId) {
|
||||
if (mostRecentMessageId === messageId && selectedConversationKey) {
|
||||
// make sure the app is focused, because we mark message as read here
|
||||
if (inView === true && isAppFocused) {
|
||||
dispatch(showScrollToBottomButton(false));
|
||||
void getConversationController()
|
||||
.get(selectedConversationKey as string)
|
||||
.get(selectedConversationKey)
|
||||
?.markRead(receivedAt || 0)
|
||||
.then(() => {
|
||||
dispatch(markConversationFullyRead(selectedConversationKey as string));
|
||||
dispatch(markConversationFullyRead(selectedConversationKey));
|
||||
});
|
||||
} else if (inView === false) {
|
||||
dispatch(showScrollToBottomButton(true));
|
||||
|
|
|
@ -101,7 +101,7 @@ export function useWeAreAdmin(convoId?: string) {
|
|||
|
||||
export function useExpireTimer(convoId?: string) {
|
||||
const convoProps = useConversationPropsById(convoId);
|
||||
return Boolean(convoProps && convoProps.expireTimer);
|
||||
return convoProps && convoProps.expireTimer;
|
||||
}
|
||||
|
||||
export function useIsPinned(convoId?: string) {
|
||||
|
|
|
@ -930,19 +930,21 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
|
|||
await this.setIsApproved(true);
|
||||
}
|
||||
|
||||
// no need to trigger a UI update now, we trigger a messageAdded just below
|
||||
// no need to trigger a UI update now, we trigger a messagesAdded just below
|
||||
const messageId = await model.commit(false);
|
||||
model.set({ id: messageId });
|
||||
|
||||
if (setToExpire) {
|
||||
await model.setToExpire();
|
||||
}
|
||||
// window.inboxStore?.dispatch(
|
||||
// conversationActions.messageAdded({
|
||||
// conversationKey: this.id,
|
||||
// messageModelProps: model.getMessageModelProps(),
|
||||
// })
|
||||
// );
|
||||
window.inboxStore?.dispatch(
|
||||
conversationActions.messagesAdded([
|
||||
{
|
||||
conversationKey: this.id,
|
||||
messageModelProps: model.getMessageModelProps(),
|
||||
},
|
||||
])
|
||||
);
|
||||
const unreadCount = await this.getUnreadCount();
|
||||
this.set({ unreadCount });
|
||||
this.updateLastMessage();
|
||||
|
|
|
@ -3,6 +3,7 @@ import { toNumber } from 'lodash';
|
|||
import { getConversationController } from '../session/conversations';
|
||||
import { ConversationTypeEnum } from '../models/conversation';
|
||||
import { toLogFormat } from '../types/attachments/Errors';
|
||||
import { messagesAdded } from '../state/ducks/conversations';
|
||||
|
||||
export async function onError(ev: any) {
|
||||
const { error } = ev;
|
||||
|
@ -33,12 +34,14 @@ export async function onError(ev: any) {
|
|||
|
||||
conversation.updateLastMessage();
|
||||
await conversation.notify(message);
|
||||
// window.inboxStore?.dispatch(
|
||||
// conversationActions.messageAdded({
|
||||
// conversationKey: conversation.id,
|
||||
// messageModelProps: message.getMessageModelProps(),
|
||||
// })
|
||||
// );
|
||||
window.inboxStore?.dispatch(
|
||||
messagesAdded([
|
||||
{
|
||||
conversationKey: conversation.id,
|
||||
messageModelProps: message.getMessageModelProps(),
|
||||
},
|
||||
])
|
||||
);
|
||||
|
||||
if (ev.confirm) {
|
||||
ev.confirm();
|
||||
|
|
|
@ -406,31 +406,33 @@ function handleMessageAdded(
|
|||
}
|
||||
) {
|
||||
const { messages } = state;
|
||||
const { conversationKey, messageModelProps: addedMessageProps } = payload;
|
||||
if (conversationKey === state.selectedConversation) {
|
||||
const messageInStoreIndex = state?.messages?.findIndex(
|
||||
m => m.propsForMessage.id === addedMessageProps.propsForMessage.id
|
||||
);
|
||||
if (messageInStoreIndex >= 0) {
|
||||
// we cannot edit the array directly, so slice the first part, insert our edited message, and slice the second part
|
||||
const editedMessages = [
|
||||
...state.messages.slice(0, messageInStoreIndex),
|
||||
addedMessageProps,
|
||||
...state.messages.slice(messageInStoreIndex + 1),
|
||||
];
|
||||
|
||||
return {
|
||||
...state,
|
||||
messages: editedMessages,
|
||||
};
|
||||
}
|
||||
const { conversationKey, messageModelProps: addedMessageProps } = payload;
|
||||
if (conversationKey !== state.selectedConversation) {
|
||||
return state;
|
||||
}
|
||||
|
||||
const messageInStoreIndex = state.messages.findIndex(
|
||||
m => m.propsForMessage.id === addedMessageProps.propsForMessage.id
|
||||
);
|
||||
if (messageInStoreIndex >= 0) {
|
||||
// we cannot edit the array directly, so slice the first part, insert our edited message, and slice the second part
|
||||
const editedMessages = [
|
||||
...state.messages.slice(0, messageInStoreIndex),
|
||||
addedMessageProps,
|
||||
...state.messages.slice(messageInStoreIndex + 1),
|
||||
];
|
||||
|
||||
return {
|
||||
...state,
|
||||
messages: [...messages, addedMessageProps], // sorting happens in the selector
|
||||
messages: editedMessages,
|
||||
};
|
||||
}
|
||||
return state;
|
||||
|
||||
return {
|
||||
...state,
|
||||
messages: [...messages, addedMessageProps], // sorting happens in the selector
|
||||
};
|
||||
}
|
||||
|
||||
function handleMessageChanged(
|
||||
|
@ -630,15 +632,6 @@ const conversationsSlice = createSlice({
|
|||
return getEmptyConversationState();
|
||||
},
|
||||
|
||||
messageAdded(
|
||||
state: ConversationsStateType,
|
||||
action: PayloadAction<{
|
||||
conversationKey: string;
|
||||
messageModelProps: MessageModelPropsWithoutConvoProps;
|
||||
}>
|
||||
) {
|
||||
return handleMessageAdded(state, action.payload);
|
||||
},
|
||||
messagesAdded(
|
||||
state: ConversationsStateType,
|
||||
action: PayloadAction<
|
||||
|
@ -741,7 +734,7 @@ const conversationsSlice = createSlice({
|
|||
firstUnreadMessageId: action.payload.firstUnreadIdOnOpen,
|
||||
};
|
||||
},
|
||||
navigateInConversationToMessageId(
|
||||
openConversationToSpecificMessage(
|
||||
state: ConversationsStateType,
|
||||
action: PayloadAction<{
|
||||
conversationKey: string;
|
||||
|
@ -897,7 +890,6 @@ export const {
|
|||
conversationRemoved,
|
||||
removeAllConversations,
|
||||
messageExpired,
|
||||
messageAdded,
|
||||
messagesAdded,
|
||||
messageDeleted,
|
||||
conversationReset,
|
||||
|
@ -955,7 +947,7 @@ export async function openConversationToSpecificMessage(args: {
|
|||
});
|
||||
|
||||
window.inboxStore?.dispatch(
|
||||
actions.navigateInConversationToMessageId({
|
||||
actions.openConversationToSpecificMessage({
|
||||
conversationKey,
|
||||
messageIdToNavigateTo,
|
||||
initialMessages: messagesAroundThisMessage,
|
||||
|
|
Loading…
Reference in a new issue