From dad9e5297cc387a54f9064661bcea24259252130 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 2 Nov 2020 14:03:11 +1100 Subject: [PATCH] make the last seen indicator work as expected --- js/models/conversations.d.ts | 2 +- js/models/conversations.js | 2 +- .../conversation/SessionConversation.tsx | 21 ++++--- .../SessionConversationMessagesList.tsx | 57 ++++++++++++------- ts/receiver/dataMessage.ts | 6 +- 5 files changed, 58 insertions(+), 30 deletions(-) diff --git a/js/models/conversations.d.ts b/js/models/conversations.d.ts index e591b17c4..0a7e28311 100644 --- a/js/models/conversations.d.ts +++ b/js/models/conversations.d.ts @@ -84,7 +84,7 @@ export interface ConversationModel getNumber: any; getProfileName: any; getAvatarPath: any; - markRead: any; + markRead: (timestamp: number) => Promise; showChannelLightbox: any; deletePublicMessages: any; getMessagesWithTimestamp: any; diff --git a/js/models/conversations.js b/js/models/conversations.js index e5d73c2a6..01e10a651 100644 --- a/js/models/conversations.js +++ b/js/models/conversations.js @@ -1891,7 +1891,7 @@ this.set({ unreadCount: 0 }); this.commit(); } else { - window.log.info('markRead(): nothing newly read.'); + // window.log.info('markRead(): nothing newly read.'); } return; } diff --git a/ts/components/session/conversation/SessionConversation.tsx b/ts/components/session/conversation/SessionConversation.tsx index 1fa6796d5..9bff56b7d 100644 --- a/ts/components/session/conversation/SessionConversation.tsx +++ b/ts/components/session/conversation/SessionConversation.tsx @@ -162,10 +162,14 @@ export class SessionConversation extends React.Component { public componentWillUnmount() { const { conversationKey } = this.props; - const conversationModel = window.ConversationController.getOrThrow( - conversationKey - ); - conversationModel.off('change', this.refreshMessages); + try { + const conversationModel = window.ConversationController.getOrThrow( + conversationKey + ); + conversationModel.off('change', this.refreshMessages); + } catch (e) { + window.log.error(e); + } const div = this.messageContainerRef.current; div?.removeEventListener('dragenter', this.handleDragIn); div?.removeEventListener('dragleave', this.handleDragOut); @@ -213,6 +217,8 @@ export class SessionConversation extends React.Component { quotedMessageProps, lightBoxOptions, selectedMessages, + isDraggingFile, + stagedAttachments, } = this.state; const selectionMode = !!selectedMessages.length; @@ -227,7 +233,6 @@ export class SessionConversation extends React.Component { const shouldRenderGroupSettings = !conversationModel.isPrivate() && !conversationModel.isRss(); - const groupSettingsProps = this.getGroupSettingsProps(); const showSafetyNumber = this.state.infoViewState === 'safetyNumber'; const showMessageDetails = this.state.infoViewState === 'messageDetails'; @@ -273,13 +278,13 @@ export class SessionConversation extends React.Component { {showRecordingView && (
)} - {this.state.isDraggingFile && } + {isDraggingFile && }
{!isRss && ( { showOptionsPane && 'show' )} > - + )} diff --git a/ts/components/session/conversation/SessionConversationMessagesList.tsx b/ts/components/session/conversation/SessionConversationMessagesList.tsx index aa306869b..16d4cc305 100644 --- a/ts/components/session/conversation/SessionConversationMessagesList.tsx +++ b/ts/components/session/conversation/SessionConversationMessagesList.tsx @@ -74,7 +74,7 @@ export class SessionConversationMessagesList extends React.Component< prevProps.conversationKey !== this.props.conversationKey || (prevProps.messages.length === 0 && this.props.messages.length !== 0) ) { - // we have a bit of cleaning to do here + // displayed conversation changed. We have a bit of cleaning to do here this.setState( { isScrolledToBottom: false, @@ -114,9 +114,11 @@ export class SessionConversationMessagesList extends React.Component< public renderMessages(messages: Array) { const { conversation } = this.props; + const { isScrolledToBottom } = this.state; + const { unreadCount } = conversation; const multiSelectMode = Boolean(this.props.selectedMessages.length); - let lastMessageIsUnread = true; + let currentMessageIndex = 0; return ( <> {messages.map((message: MessageModel) => { @@ -129,14 +131,15 @@ export class SessionConversationMessagesList extends React.Component< const groupNotificationProps = message.propsForGroupNotification; let unreadIndicator = null; - // FIXME a sending message does not have the isUnread function yet. - const isMessageUnread = message.isUnread && message.isUnread(); - // if there is some unread messages - if (lastMessageIsUnread && !isMessageUnread && unreadCount > 0) { + if ( + unreadCount > 0 && + currentMessageIndex === unreadCount && + !isScrolledToBottom + ) { unreadIndicator = ; - lastMessageIsUnread = false; } + currentMessageIndex = currentMessageIndex + 1; if (groupNotificationProps) { return ( @@ -229,8 +232,6 @@ export class SessionConversationMessagesList extends React.Component< const { messages, conversationKey } = this.props; const { isScrolledToBottom } = this.state; - let unread; - if (!messages || messages.length === 0) { return; } @@ -244,13 +245,7 @@ export class SessionConversationMessagesList extends React.Component< } if (isScrolledToBottom) { - unread = messages[0]; - } else { - unread = null; - } - - if (unread) { - conversation.markRead(unread.attributes.received_at); + void conversation.markRead(messages[0].attributes.received_at); } } @@ -339,15 +334,39 @@ export class SessionConversationMessagesList extends React.Component< } if (!this.state.doneInitialScroll) { - this.setState({ - doneInitialScroll: true, - }); + this.setState( + { + doneInitialScroll: true, + }, + () => { + this.updateReadMessages(); + } + ); } } public scrollToMessage(messageId: string) { const topUnreadMessage = document.getElementById(messageId); topUnreadMessage?.scrollIntoView(); + + // if the scroll container is not scrollable as it's not tall enough, we have to update + // the isScrollToBottom ourself + + const messageContainer = this.messageContainerRef.current; + if (!messageContainer) { + return; + } + + const scrollTop = messageContainer.scrollTop; + const scrollHeight = messageContainer.scrollHeight; + const clientHeight = messageContainer.clientHeight; + + const scrollOffsetPx = scrollHeight - scrollTop - clientHeight; + const scrollOffsetPc = scrollOffsetPx / clientHeight; + + if (scrollOffsetPc === 0 && this.state.doneInitialScroll) { + this.setState({ isScrolledToBottom: true }); + } } public scrollToBottom() { diff --git a/ts/receiver/dataMessage.ts b/ts/receiver/dataMessage.ts index 9d393d79c..6e29ed11d 100644 --- a/ts/receiver/dataMessage.ts +++ b/ts/receiver/dataMessage.ts @@ -474,9 +474,13 @@ export function initIncomingMessage(data: MessageCreationData): MessageModel { const type = 'incoming'; const messageGroupId = message?.group?.id; - const groupId = + let groupId = messageGroupId && messageGroupId.length > 0 ? messageGroupId : null; + if (groupId) { + groupId = groupId.replace(PubKey.PREFIX_GROUP_TEXTSECURE, ''); + } + const messageData: any = { source, sourceDevice,