fixup selected message in redux logic
This commit is contained in:
parent
787e3a32d0
commit
4ca5a4f093
|
@ -47,7 +47,7 @@ import { getSelectedMessage } from '../../state/selectors/search';
|
|||
import { connect } from 'react-redux';
|
||||
import { StateType } from '../../state/reducer';
|
||||
import { getSelectedMessageIds } from '../../state/selectors/conversations';
|
||||
import { showMessageDetailsView } from '../../state/ducks/conversations';
|
||||
import { showMessageDetailsView, toggleSelectedMessageId } from '../../state/ducks/conversations';
|
||||
|
||||
// Same as MIN_WIDTH in ImageGrid.tsx
|
||||
const MINIMUM_LINK_PREVIEW_IMAGE_WIDTH = 200;
|
||||
|
@ -813,10 +813,6 @@ class MessageInner extends React.PureComponent<Props, State> {
|
|||
if (target.className === 'text-selectable' || window.contextMenuShown) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (id) {
|
||||
window.inboxStore?.dispatch(toggleSelectedMessageId(id));
|
||||
}
|
||||
}}
|
||||
>
|
||||
{this.renderAuthor()}
|
||||
|
|
|
@ -170,53 +170,10 @@ class SessionMessagesListInner extends React.Component<Props, State> {
|
|||
);
|
||||
}
|
||||
|
||||
private displayUnreadBannerIndex(messages: Array<SortedMessageModelProps>) {
|
||||
const { conversation } = this.props;
|
||||
if (!conversation) {
|
||||
return -1;
|
||||
}
|
||||
if (conversation.unreadCount === 0) {
|
||||
return -1;
|
||||
}
|
||||
// conversation.unreadCount is the number of messages we incoming we did not read yet.
|
||||
// also, unreacCount is updated only when the conversation is marked as read.
|
||||
// So we can have an unreadCount for the conversation not correct based on the real number of unread messages.
|
||||
// some of the messages we have in "messages" are ones we sent ourself (or from another device).
|
||||
// those messages should not be counted to display the unread banner.
|
||||
|
||||
let findFirstUnreadIndex = -1;
|
||||
let incomingMessagesSoFar = 0;
|
||||
const { unreadCount } = conversation;
|
||||
|
||||
// Basically, count the number of incoming messages from the most recent one.
|
||||
for (let index = 0; index <= messages.length - 1; index++) {
|
||||
const message = messages[index];
|
||||
if (message.propsForMessage.direction === 'incoming') {
|
||||
incomingMessagesSoFar++;
|
||||
// message.attributes.unread is !== undefined if the message is unread.
|
||||
if (
|
||||
message.propsForMessage.isUnread !== undefined &&
|
||||
incomingMessagesSoFar >= unreadCount
|
||||
) {
|
||||
findFirstUnreadIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
if (findFirstUnreadIndex === -1 && conversation.unreadCount >= 0) {
|
||||
return conversation.unreadCount - 1;
|
||||
}
|
||||
return findFirstUnreadIndex;
|
||||
}
|
||||
|
||||
private renderMessages() {
|
||||
const { selectedMessages, messagesProps } = this.props;
|
||||
const multiSelectMode = Boolean(selectedMessages.length);
|
||||
let currentMessageIndex = 0;
|
||||
let playableMessageIndex = 0;
|
||||
const displayUnreadBannerIndex = this.displayUnreadBannerIndex(messagesProps);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -228,27 +185,25 @@ class SessionMessagesListInner extends React.Component<Props, State> {
|
|||
|
||||
const groupNotificationProps = messageProps.propsForGroupNotification;
|
||||
|
||||
// IF there are some unread messages
|
||||
// AND we found the last read message
|
||||
// IF we found the last read message
|
||||
// AND we are not scrolled all the way to the bottom
|
||||
// THEN, show the unread banner for the current message
|
||||
const showUnreadIndicator =
|
||||
displayUnreadBannerIndex >= 0 &&
|
||||
currentMessageIndex === displayUnreadBannerIndex &&
|
||||
this.getScrollOffsetBottomPx() !== 0;
|
||||
Boolean(messageProps.firstUnread) && this.getScrollOffsetBottomPx() !== 0;
|
||||
const unreadIndicator = (
|
||||
<SessionLastSeenIndicator
|
||||
count={displayUnreadBannerIndex + 1} // count is used for the 118n of the string
|
||||
show={showUnreadIndicator}
|
||||
key={`unread-indicator-${messageProps.propsForMessage.id}`}
|
||||
/>
|
||||
);
|
||||
currentMessageIndex = currentMessageIndex + 1;
|
||||
|
||||
if (groupNotificationProps) {
|
||||
return (
|
||||
<React.Fragment key={messageProps.propsForMessage.id}>
|
||||
<GroupNotification {...groupNotificationProps} />
|
||||
<React.Fragment>
|
||||
<GroupNotification
|
||||
key={messageProps.propsForMessage.id}
|
||||
{...groupNotificationProps}
|
||||
/>
|
||||
{unreadIndicator}
|
||||
</React.Fragment>
|
||||
);
|
||||
|
|
|
@ -104,10 +104,6 @@ const animation = (props: {
|
|||
return css``;
|
||||
}
|
||||
|
||||
if (props.glowDuration === 10) {
|
||||
console.warn('scake', props);
|
||||
}
|
||||
|
||||
if (props.glowDuration !== undefined && props.glowStartDelay !== undefined && props.iconColor) {
|
||||
return css`
|
||||
${glow(
|
||||
|
|
|
@ -275,23 +275,27 @@ async function getMessages(
|
|||
if (conversation.isPrivate()) {
|
||||
return sortedMessageProps;
|
||||
}
|
||||
return updateFirstMessageOfSeries(sortedMessageProps);
|
||||
return updateFirstMessageOfSeriesAndUnread(sortedMessageProps);
|
||||
}
|
||||
|
||||
export type SortedMessageModelProps = MessageModelProps & {
|
||||
firstMessageOfSeries: boolean;
|
||||
firstUnread?: boolean;
|
||||
};
|
||||
|
||||
const updateFirstMessageOfSeries = (
|
||||
messageModelsProps: Array<MessageModelProps>
|
||||
const updateFirstMessageOfSeriesAndUnread = (
|
||||
messageModelsProps: Array<SortedMessageModelProps>
|
||||
): Array<SortedMessageModelProps> => {
|
||||
// messages are got from the more recent to the oldest, so we need to check if
|
||||
// the next messages in the list is still the same author.
|
||||
// The message is the first of the series if the next message is not from the same author
|
||||
const sortedMessageProps: Array<SortedMessageModelProps> = [];
|
||||
const firstUnreadIndex = getFirstMessageUnreadIndex(messageModelsProps);
|
||||
|
||||
for (let i = 0; i < messageModelsProps.length; i++) {
|
||||
// Handle firstMessageOfSeries for conditional avatar rendering
|
||||
let firstMessageOfSeries = true;
|
||||
let firstUnread = false;
|
||||
const currentSender = messageModelsProps[i].propsForMessage?.authorPhoneNumber;
|
||||
const nextSender =
|
||||
i < messageModelsProps.length - 1
|
||||
|
@ -300,8 +304,11 @@ const updateFirstMessageOfSeries = (
|
|||
if (i >= 0 && currentSender === nextSender) {
|
||||
firstMessageOfSeries = false;
|
||||
}
|
||||
if (i === firstUnreadIndex) {
|
||||
firstUnread = true;
|
||||
}
|
||||
|
||||
sortedMessageProps.push({ ...messageModelsProps[i], firstMessageOfSeries });
|
||||
sortedMessageProps.push({ ...messageModelsProps[i], firstMessageOfSeries, firstUnread });
|
||||
}
|
||||
return sortedMessageProps;
|
||||
};
|
||||
|
@ -311,6 +318,27 @@ type FetchedMessageResults = {
|
|||
messagesProps: Array<SortedMessageModelProps>;
|
||||
};
|
||||
|
||||
const getFirstMessageUnreadIndex = (messages: Array<SortedMessageModelProps>) => {
|
||||
if (!messages || messages.length === 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// iterate over the incoming messages from the oldest one. the first one with isUnread !== undefined is our first unread
|
||||
for (let index = messages.length - 1; index > 0; index--) {
|
||||
const message = messages[index];
|
||||
if (
|
||||
message.propsForMessage.direction === 'incoming' &&
|
||||
message.propsForMessage.isUnread === true
|
||||
) {
|
||||
console.warn('message.propsForMessage', message.propsForMessage);
|
||||
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
export const fetchMessagesForConversation = createAsyncThunk(
|
||||
'messages/fetchByConversationKey',
|
||||
async ({
|
||||
|
@ -322,15 +350,25 @@ export const fetchMessagesForConversation = createAsyncThunk(
|
|||
}): Promise<FetchedMessageResults> => {
|
||||
const beforeTimestamp = Date.now();
|
||||
const messagesProps = await getMessages(conversationKey, count);
|
||||
const firstUnreadIndex = getFirstMessageUnreadIndex(messagesProps);
|
||||
const afterTimestamp = Date.now();
|
||||
|
||||
const time = afterTimestamp - beforeTimestamp;
|
||||
window?.log?.info(`Loading ${messagesProps.length} messages took ${time}ms to load.`);
|
||||
|
||||
const mapped = messagesProps.map(m => {
|
||||
const mapped = messagesProps.map((m, index) => {
|
||||
if (index === firstUnreadIndex) {
|
||||
console.warn('fullfuled firstUnreadIndex', firstUnreadIndex);
|
||||
return {
|
||||
...m,
|
||||
firstMessageOfSeries: true,
|
||||
firstUnread: true,
|
||||
};
|
||||
}
|
||||
return {
|
||||
...m,
|
||||
firstMessageOfSeries: true,
|
||||
firstUnread: false,
|
||||
};
|
||||
});
|
||||
return {
|
||||
|
@ -397,7 +435,7 @@ function handleMessageAdded(
|
|||
|
||||
if (convo) {
|
||||
const sortedMessage = sortMessages(messagesWithNewMessage, isPublic);
|
||||
const updatedWithFirstMessageOfSeries = updateFirstMessageOfSeries(sortedMessage);
|
||||
const updatedWithFirstMessageOfSeries = updateFirstMessageOfSeriesAndUnread(sortedMessage);
|
||||
|
||||
return {
|
||||
...state,
|
||||
|
@ -425,7 +463,7 @@ function handleMessageChanged(state: ConversationsStateType, payload: MessageMod
|
|||
const isPublic = convo?.isPublic || false;
|
||||
// reorder the messages depending on the timestamp (we might have an updated serverTimestamp now)
|
||||
const sortedMessage = sortMessages(editedMessages, isPublic);
|
||||
const updatedWithFirstMessageOfSeries = updateFirstMessageOfSeries(sortedMessage);
|
||||
const updatedWithFirstMessageOfSeries = updateFirstMessageOfSeriesAndUnread(sortedMessage);
|
||||
|
||||
return {
|
||||
...state,
|
||||
|
@ -465,7 +503,7 @@ function handleMessageExpiredOrDeleted(
|
|||
...state.messages.slice(messageInStoreIndex + 1),
|
||||
];
|
||||
|
||||
const updatedWithFirstMessageOfSeries = updateFirstMessageOfSeries(editedMessages);
|
||||
const updatedWithFirstMessageOfSeries = updateFirstMessageOfSeriesAndUnread(editedMessages);
|
||||
|
||||
// FIXME two other thing we have to do:
|
||||
// * update the last message text if the message deleted was the last one
|
||||
|
@ -534,9 +572,12 @@ const conversationsSlice = createSlice({
|
|||
const index = state.selectedMessageIds.findIndex(id => id === action.payload);
|
||||
|
||||
if (index === -1) {
|
||||
return { ...state, selectedMessageIds: [...state.selectedMessageIds, action.payload] };
|
||||
state.selectedMessageIds = [...state.selectedMessageIds, action.payload];
|
||||
} else {
|
||||
state.selectedMessageIds.splice(index, 1);
|
||||
}
|
||||
return { ...state, selectedMessageIds: state.selectedMessageIds.splice(index, 1) };
|
||||
|
||||
return state;
|
||||
},
|
||||
resetSelectedMessageIds(state: ConversationsStateType) {
|
||||
return { ...state, selectedMessageIds: [] };
|
||||
|
@ -710,4 +751,5 @@ export const {
|
|||
closeRightPanel,
|
||||
addMessageIdToSelection,
|
||||
resetSelectedMessageIds,
|
||||
toggleSelectedMessageId,
|
||||
} = actions;
|
||||
|
|
Loading…
Reference in New Issue