fix: fix the control messages not being marked as read sometimes

pull/3281/head
Audric Ackermann 3 months ago
parent e33f2ed734
commit b3fffc9cae
No known key found for this signature in database

@ -82,8 +82,7 @@ const StyledReadableMessage = styled(ReadableMessage)<{
flex-direction: column;
`;
export interface ExpirableReadableMessageProps
extends Omit<ReadableMessageProps, 'receivedAt' | 'isUnread'> {
export interface ExpirableReadableMessageProps extends Omit<ReadableMessageProps, 'isUnread'> {
messageId: string;
isControlMessage?: boolean;
}
@ -130,7 +129,6 @@ export const ExpirableReadableMessage = (props: ExpirableReadableMessageProps) =
const {
messageId,
direction: _direction,
receivedAt,
isUnread,
expirationDurationMs,
expirationTimestamp,
@ -143,7 +141,6 @@ export const ExpirableReadableMessage = (props: ExpirableReadableMessageProps) =
return (
<StyledReadableMessage
messageId={messageId}
receivedAt={receivedAt}
isUnread={!!isUnread}
isIncoming={isIncoming}
onClick={onClick}

@ -13,11 +13,7 @@ import {
useSelectedIsPrivate,
useSelectedIsPublic,
} from '../../../../state/selectors/selectedConversation';
import {
useMessageInteractionNotification,
useMessageIsUnread,
useMessageReceivedAt,
} from '../../../../state/selectors';
import { useMessageInteractionNotification, useMessageIsUnread } from '../../../../state/selectors';
import type { WithMessageId } from '../../../../session/types/with';
const StyledFailText = styled.div`
@ -32,7 +28,6 @@ export const InteractionNotification = (props: WithMessageId) => {
const isGroup = !useSelectedIsPrivate();
const isCommunity = useSelectedIsPublic();
const isUnread = useMessageIsUnread(messageId) || false;
const receivedAt = useMessageReceivedAt(messageId);
const interactionNotification = useMessageInteractionNotification(messageId);
if (!convoId || !messageId || !interactionNotification) {
@ -80,7 +75,6 @@ export const InteractionNotification = (props: WithMessageId) => {
return (
<ReadableMessage
messageId={messageId}
receivedAt={receivedAt}
isUnread={isUnread}
key={`readable-message-${messageId}`}
dataTestId="interaction-notification"

@ -1,10 +1,6 @@
import { useNicknameOrProfileNameOrShortenedPubkey } from '../../../../hooks/useParamSelector';
import type { WithMessageId } from '../../../../session/types/with';
import {
useMessageAuthorIsUs,
useMessageIsUnread,
useMessageReceivedAt,
} from '../../../../state/selectors';
import { useMessageAuthorIsUs, useMessageIsUnread } from '../../../../state/selectors';
import { useSelectedConversationKey } from '../../../../state/selectors/selectedConversation';
import { Flex } from '../../../basic/Flex';
import { Localizer } from '../../../basic/Localizer';
@ -14,7 +10,6 @@ import { ReadableMessage } from './ReadableMessage';
// Note: this should not respond to the disappearing message conversation setting so we use the ReadableMessage directly
export const MessageRequestResponse = ({ messageId }: WithMessageId) => {
const conversationId = useSelectedConversationKey();
const receivedAt = useMessageReceivedAt(messageId);
const isUnread = useMessageIsUnread(messageId) || false;
const isUs = useMessageAuthorIsUs(messageId);
@ -27,7 +22,6 @@ export const MessageRequestResponse = ({ messageId }: WithMessageId) => {
return (
<ReadableMessage
messageId={messageId}
receivedAt={receivedAt}
isUnread={isUnread}
dataTestId="message-request-response-message"
key={`readable-message-${messageId}`}

@ -31,12 +31,12 @@ import {
} from '../../../../state/selectors/conversations';
import { getIsAppFocused } from '../../../../state/selectors/section';
import { useSelectedConversationKey } from '../../../../state/selectors/selectedConversation';
import type { WithConvoId, WithMessageId } from '../../../../session/types/with';
export type ReadableMessageProps = {
children: ReactNode;
messageId: string;
className?: string;
receivedAt: number | undefined;
isUnread: boolean;
onClick?: MouseEventHandler<HTMLElement>;
onDoubleClickCapture?: MouseEventHandler<HTMLElement>;
@ -70,12 +70,36 @@ const debouncedTriggerLoadMoreBottom = debounce(
100
);
async function markReadFromMessageId({
conversationId,
messageId,
isUnread,
}: WithMessageId & WithConvoId & { isUnread: boolean }) {
// isUnread comes from the redux store in memory, so pretty fast and allows us to fetch from the DB too often
if (!isUnread) {
return;
}
const found = await Data.getMessageById(messageId);
if (!found) {
return;
}
if (found.isUnread()) {
ConvoHub.use()
.get(conversationId)
?.markConversationRead({
newestUnreadDate: found.get('sent_at') || found.get('serverTimestamp') || Date.now(),
fromConfigMessage: false,
});
}
}
export const ReadableMessage = (props: ReadableMessageProps) => {
const {
messageId,
onContextMenu,
className,
receivedAt,
isUnread,
onClick,
onDoubleClickCapture,
@ -127,9 +151,12 @@ export const ReadableMessage = (props: ReadableMessageProps) => {
// make sure the app is focused, because we mark message as read here
if (inView === true && isAppFocused) {
dispatch(showScrollToBottomButton(false));
ConvoHub.use()
.get(selectedConversationKey)
?.markConversationRead({ newestUnreadDate: receivedAt || 0, fromConfigMessage: false }); // TODOLATER this should be `sentAt || serverTimestamp` I think
// TODO this is pretty expensive and should instead use values from the redux store
await markReadFromMessageId({
messageId,
conversationId: selectedConversationKey,
isUnread,
});
dispatch(markConversationFullyRead(selectedConversationKey));
} else if (inView === false) {
@ -147,23 +174,12 @@ export const ReadableMessage = (props: ReadableMessageProps) => {
// this part is just handling the marking of the message as read if needed
if (inView) {
if (isUnread) {
// TODOLATER this is pretty expensive and should instead use values from the redux store
const found = await Data.getMessageById(messageId);
if (found && Boolean(found.get('unread'))) {
const foundSentAt = found.get('sent_at') || found.get('serverTimestamp');
// we should stack those and send them in a single message once every 5secs or something.
// this would be part of an redesign of the sending pipeline
// mark the whole conversation as read until this point.
// this will trigger the expire timer.
if (foundSentAt) {
ConvoHub.use()
.get(selectedConversationKey)
?.markConversationRead({ newestUnreadDate: foundSentAt, fromConfigMessage: false });
}
}
}
// TODO this is pretty expensive and should instead use values from the redux store
await markReadFromMessageId({
messageId,
conversationId: selectedConversationKey,
isUnread,
});
}
},
[
@ -173,10 +189,9 @@ export const ReadableMessage = (props: ReadableMessageProps) => {
oldestMessageId,
fetchingMoreInProgress,
isAppFocused,
receivedAt,
messageId,
isUnread,
youngestMessageId,
isUnread,
]
);

@ -494,6 +494,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
* Fetches from the Database an update of what are the memory only informations like mentionedUs and the unreadCount, etc
*/
public async refreshInMemoryDetails(providedMemoryDetails?: SaveConversationReturn) {
if (!SessionUtilConvoInfoVolatile.isConvoToStoreInWrapper(this)) {
return;
}

@ -129,7 +129,6 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
const propsForGroupUpdateMessage = this.getPropsForGroupUpdateMessage();
const propsForTimerNotification = this.getPropsForTimerNotification();
const isMessageResponse = this.isMessageRequestResponse();
const propsForQuote = this.getPropsForQuote();
const callNotificationType = this.get('callNotificationType');
const interactionNotification = this.getInteractionNotification();
@ -151,9 +150,6 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
if (propsForTimerNotification) {
messageProps.propsForTimerNotification = propsForTimerNotification;
}
if (propsForQuote) {
messageProps.propsForQuote = propsForQuote;
}
if (callNotificationType) {
const propsForCallNotification: PropsForCallNotification = {
@ -198,7 +194,9 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
}
public isUnread() {
return !!this.get('unread');
const unreadField = this.get('unread');
return !!unreadField;
}
// Important to allow for this.set({ unread}), save to db, then fetch()

@ -39,7 +39,6 @@ export type MessageModelPropsWithoutConvoProps = {
propsForGroupUpdateMessage?: PropsForGroupUpdate; // plop: cleaned up
propsForCallNotification?: PropsForCallNotification; // plop: cleaned up
propsForMessageRequestResponse?: PropsForMessageRequestResponse; // plop: cleaned up
propsForQuote?: PropsForQuote;
propsForInteractionNotification?: PropsForInteractionNotification; // plop: cleaned up
};
@ -151,7 +150,7 @@ export type PropsForMessageWithoutConvoProps = {
id: string; // messageId
direction: MessageModelType;
timestamp: number;
sender: string; // this is the sender
sender: string; // this is the sender/author
convoId: string; // this is the conversation in which this message was sent
text?: string;
receivedAt?: number;
@ -170,6 +169,11 @@ export type PropsForMessageWithoutConvoProps = {
expirationDurationMs?: number;
expirationTimestamp?: number | null;
isExpired?: boolean;
/**
* true if the sender of that message is trusted for auto attachment downloads.
* Note: we keep it in the PropsForMessageWithoutConvoProps because it is a per-sender setting
* rather than a per-convo setting (especially for groups)
*/
isTrustedForAttachmentDownload?: boolean;
};

Loading…
Cancel
Save