From 12ff3379e1a35262ffaaab4127d9a896dd67d14a Mon Sep 17 00:00:00 2001 From: audric Date: Thu, 22 Jul 2021 15:04:46 +1000 Subject: [PATCH] add key for all messages list so we can scroll to them programnatically --- .../DataExtractionNotification.tsx | 3 +- .../conversation/GroupInvitation.tsx | 2 +- .../conversation/GroupNotification.tsx | 2 +- ts/components/conversation/Message.tsx | 4 ++ .../conversation/TimerNotification.tsx | 58 +++++++++---------- .../conversation/SessionMessagesList.tsx | 9 +-- .../SessionMessagesListContainer.tsx | 14 ++--- .../conversation/SessionMessagesTypes.tsx | 42 +++++++------- ts/models/message.ts | 3 + ts/models/messageType.ts | 1 + ts/state/ducks/conversations.ts | 6 +- 11 files changed, 71 insertions(+), 73 deletions(-) diff --git a/ts/components/conversation/DataExtractionNotification.tsx b/ts/components/conversation/DataExtractionNotification.tsx index 7c23e2919..a92de9afb 100644 --- a/ts/components/conversation/DataExtractionNotification.tsx +++ b/ts/components/conversation/DataExtractionNotification.tsx @@ -8,7 +8,7 @@ import { SpacerXS, Text } from '../basic/Text'; export const DataExtractionNotification = (props: PropsForDataExtractionNotification) => { const theme = useTheme(); - const { name, type, source } = props; + const { name, type, source, messageId } = props; let contentText: string; if (type === SignalService.DataExtractionNotification.Type.MEDIA_SAVED) { @@ -23,6 +23,7 @@ export const DataExtractionNotification = (props: PropsForDataExtractionNotifica flexDirection="column" alignItems="center" margin={theme.common.margins.sm} + id={messageId} > { const openGroupInvitation = window.i18n('openGroupInvitation'); return ( -
+
{ const { changes } = props; return ( -
+
{(changes || []).map((change, index) => (
{renderChange(change)} diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx index 7c3252cac..ecade58fb 100644 --- a/ts/components/conversation/Message.tsx +++ b/ts/components/conversation/Message.tsx @@ -54,6 +54,7 @@ import { MessageContextMenu } from './MessageContextMenu'; import { ReadableMessage } from './ReadableMessage'; import { remote } from 'electron'; import { isElectronWindowFocused } from '../../session/utils/WindowUtils'; +import { getConversationController } from '../../session/conversations'; // Same as MIN_WIDTH in ImageGrid.tsx const MINIMUM_LINK_PREVIEW_IMAGE_WIDTH = 200; @@ -176,6 +177,9 @@ class MessageInner extends React.PureComponent { window.inboxStore?.dispatch( messageExpired({ messageId: this.props.id, conversationKey: this.props.convoId }) ); + getConversationController() + .get(this.props.convoId) + ?.updateLastMessage(); }; this.expiredTimeout = setTimeout(setExpired, EXPIRED_DELAY); } diff --git a/ts/components/conversation/TimerNotification.tsx b/ts/components/conversation/TimerNotification.tsx index 41fdc4dd6..ac6ef8bed 100644 --- a/ts/components/conversation/TimerNotification.tsx +++ b/ts/components/conversation/TimerNotification.tsx @@ -1,52 +1,52 @@ -import React, { useContext } from 'react'; +import React from 'react'; import { Intl } from '../Intl'; import { missingCaseError } from '../../util/missingCaseError'; import { SessionIcon, SessionIconSize, SessionIconType } from '../session/icon'; -import { ThemeContext } from 'styled-components'; import { PropsForExpirationTimer } from '../../state/ducks/conversations'; -export const TimerNotification = (props: PropsForExpirationTimer) => { - function renderContents() { - const { phoneNumber, profileName, timespan, type, disabled } = props; - const changeKey = disabled ? 'disabledDisappearingMessages' : 'theyChangedTheTimer'; +const TimerNotificationContent = (props: PropsForExpirationTimer) => { + const { phoneNumber, profileName, timespan, type, disabled } = props; + const changeKey = disabled ? 'disabledDisappearingMessages' : 'theyChangedTheTimer'; - const contact = ( - - {profileName || phoneNumber} - - ); + const contact = ( + + {profileName || phoneNumber} + + ); - switch (type) { - case 'fromOther': - return ; - case 'fromMe': - return disabled - ? window.i18n('youDisabledDisappearingMessages') - : window.i18n('youChangedTheTimer', [timespan]); - case 'fromSync': - return disabled - ? window.i18n('disappearingMessagesDisabled') - : window.i18n('timerSetOnSync', [timespan]); - default: - throw missingCaseError(type); - } + switch (type) { + case 'fromOther': + return ; + case 'fromMe': + return disabled + ? window.i18n('youDisabledDisappearingMessages') + : window.i18n('youChangedTheTimer', [timespan]); + case 'fromSync': + return disabled + ? window.i18n('disappearingMessagesDisabled') + : window.i18n('timerSetOnSync', [timespan]); + default: + throw missingCaseError(type); } - const themeContext = useContext(ThemeContext); +}; + +export const TimerNotification = (props: PropsForExpirationTimer) => { return ( -
+
-
{renderContents()}
+
+ +
); diff --git a/ts/components/session/conversation/SessionMessagesList.tsx b/ts/components/session/conversation/SessionMessagesList.tsx index 952e81c75..8456132e9 100644 --- a/ts/components/session/conversation/SessionMessagesList.tsx +++ b/ts/components/session/conversation/SessionMessagesList.tsx @@ -32,7 +32,6 @@ export const SessionMessagesList = (props: { ); } @@ -42,7 +41,6 @@ export const SessionMessagesList = (props: { ); } @@ -52,18 +50,13 @@ export const SessionMessagesList = (props: { ); } if (timerProps) { return ( - + ); } diff --git a/ts/components/session/conversation/SessionMessagesListContainer.tsx b/ts/components/session/conversation/SessionMessagesListContainer.tsx index bd1879d02..f01693140 100644 --- a/ts/components/session/conversation/SessionMessagesListContainer.tsx +++ b/ts/components/session/conversation/SessionMessagesListContainer.tsx @@ -269,7 +269,6 @@ class SessionMessagesListContainerInner extends React.Component { topTopMessage > containerTop - 10 && !this.props.areMoreMessagesBeingFetched; if (shouldFetchMore) { - console.warn('shouldFetchMore', shouldFetchMore); const { messagesProps } = this.props; const oldLen = messagesProps.length; @@ -344,23 +343,18 @@ class SessionMessagesListContainerInner extends React.Component { } } - private scrollToMessage(messageId: string, smooth: boolean = false, alignOnTop = false) { + private scrollToMessage(messageId: string, scrollIsQuote: boolean = false) { const messageElementDom = document.getElementById(messageId); messageElementDom?.scrollIntoView({ behavior: 'auto', - block: alignOnTop ? 'start' : 'center', + block: 'center', }); - // we consider that a `smooth` set to true, means it's a quoted message, so highlight this message on the UI - if (smooth) { + // we consider that a `scrollIsQuote` set to true, means it's a quoted message, so highlight this message on the UI + if (scrollIsQuote) { window.inboxStore?.dispatch(quotedMessageToAnimate(messageId)); this.setupTimeoutResetQuotedHighlightedMessage(messageId); } - - const messageContainer = this.props.messageContainerRef.current; - if (!messageContainer) { - return; - } } private scrollToBottom() { diff --git a/ts/components/session/conversation/SessionMessagesTypes.tsx b/ts/components/session/conversation/SessionMessagesTypes.tsx index 84cac731d..5fde65948 100644 --- a/ts/components/session/conversation/SessionMessagesTypes.tsx +++ b/ts/components/session/conversation/SessionMessagesTypes.tsx @@ -31,56 +31,54 @@ export const UnreadIndicator = (props: { messageId: string }) => { return ; }; -export const GroupUpdateItem = (props: { - messageId: string; - groupNotificationProps: PropsForGroupUpdate; -}) => { +export const GroupUpdateItem = (props: { groupNotificationProps: PropsForGroupUpdate }) => { return ( - - - + + + ); }; export const GroupInvitationItem = (props: { - messageId: string; propsForGroupInvitation: PropsForGroupInvitation; }) => { return ( - - + + - + ); }; export const DataExtractionNotificationItem = (props: { - messageId: string; propsForDataExtractionNotification: PropsForDataExtractionNotification; }) => { return ( - + - + ); }; -export const TimerNotificationItem = (props: { - messageId: string; - timerProps: PropsForExpirationTimer; -}) => { +export const TimerNotificationItem = (props: { timerProps: PropsForExpirationTimer }) => { return ( - - + + - + ); }; diff --git a/ts/models/message.ts b/ts/models/message.ts index 95b28e920..c6982effd 100644 --- a/ts/models/message.ts +++ b/ts/models/message.ts @@ -298,6 +298,7 @@ export class MessageModel extends Backbone.Model { timespan, disabled, type: fromSync ? 'fromSync' : UserUtils.isUsFromCache(source) ? 'fromMe' : 'fromOther', + messageId: this.id, }; return basicProps; @@ -347,6 +348,7 @@ export class MessageModel extends Backbone.Model { return { ...dataExtractionNotification, name: contact.profileName || contact.name || dataExtractionNotification.source, + messageId: this.id, }; } @@ -462,6 +464,7 @@ export class MessageModel extends Backbone.Model { return { changes, + messageId: this.id, }; } diff --git a/ts/models/messageType.ts b/ts/models/messageType.ts index 34e5cb2cb..1420387b4 100644 --- a/ts/models/messageType.ts +++ b/ts/models/messageType.ts @@ -111,6 +111,7 @@ export interface DataExtractionNotificationMsg { export type PropsForDataExtractionNotification = DataExtractionNotificationMsg & { name: string; + messageId: string; }; export interface MessageAttributesOptionals { diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index 8e2e6f75a..9015b0118 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -66,6 +66,7 @@ export type PropsForExpirationTimer = { profileName: string | null; title: string | null; type: 'fromMe' | 'fromSync' | 'fromOther'; + messageId: string; }; export type PropsForGroupUpdateGeneral = { @@ -105,6 +106,7 @@ export type PropsForGroupUpdateArray = Array; export type PropsForGroupUpdate = { changes: PropsForGroupUpdateArray; + messageId: string; }; export type PropsForGroupInvitation = { @@ -391,7 +393,7 @@ function handleMessageExpiredOrDeleted( messageId: string; conversationKey: string; }> -) { +): ConversationsStateType { const { conversationKey, messageId } = action.payload; if (conversationKey === state.selectedConversation) { // search if we find this message id. @@ -412,6 +414,8 @@ function handleMessageExpiredOrDeleted( return { ...state, messages: editedMessages, + firstUnreadMessageId: + state.firstUnreadMessageId === messageId ? undefined : state.firstUnreadMessageId, }; }