add key for all messages list so we can scroll to them programnatically
This commit is contained in:
parent
8766cf3f8a
commit
12ff3379e1
|
@ -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}
|
||||
>
|
||||
<SessionIcon
|
||||
iconType={SessionIconType.Upload}
|
||||
|
|
|
@ -15,7 +15,7 @@ export const GroupInvitation = (props: PropsForGroupInvitation) => {
|
|||
const openGroupInvitation = window.i18n('openGroupInvitation');
|
||||
|
||||
return (
|
||||
<div className="group-invitation-container">
|
||||
<div className="group-invitation-container" id={props.messageId}>
|
||||
<div className={classNames(classes)}>
|
||||
<div className="contents">
|
||||
<SessionIconButton
|
||||
|
|
|
@ -91,7 +91,7 @@ function renderChange(change: PropsForGroupUpdateType) {
|
|||
export const GroupNotification = (props: PropsForGroupUpdate) => {
|
||||
const { changes } = props;
|
||||
return (
|
||||
<div className="module-group-notification">
|
||||
<div className="module-group-notification" id={props.messageId}>
|
||||
{(changes || []).map((change, index) => (
|
||||
<div key={index} className="module-group-notification__change">
|
||||
{renderChange(change)}
|
||||
|
|
|
@ -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<Props, State> {
|
|||
window.inboxStore?.dispatch(
|
||||
messageExpired({ messageId: this.props.id, conversationKey: this.props.convoId })
|
||||
);
|
||||
getConversationController()
|
||||
.get(this.props.convoId)
|
||||
?.updateLastMessage();
|
||||
};
|
||||
this.expiredTimeout = setTimeout(setExpired, EXPIRED_DELAY);
|
||||
}
|
||||
|
|
|
@ -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 = (
|
||||
<span key={`external-${phoneNumber}`} className="module-timer-notification__contact">
|
||||
{profileName || phoneNumber}
|
||||
</span>
|
||||
);
|
||||
const contact = (
|
||||
<span key={`external-${phoneNumber}`} className="module-timer-notification__contact">
|
||||
{profileName || phoneNumber}
|
||||
</span>
|
||||
);
|
||||
|
||||
switch (type) {
|
||||
case 'fromOther':
|
||||
return <Intl id={changeKey} components={[contact, timespan]} />;
|
||||
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 <Intl id={changeKey} components={[contact, timespan]} />;
|
||||
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 (
|
||||
<div className="module-timer-notification">
|
||||
<div className="module-timer-notification" id={props.messageId}>
|
||||
<div className="module-timer-notification__message">
|
||||
<div>
|
||||
<SessionIcon
|
||||
iconType={SessionIconType.Stopwatch}
|
||||
iconSize={SessionIconSize.Small}
|
||||
iconColor={'#ABABAB'}
|
||||
theme={themeContext}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>{renderContents()}</div>
|
||||
<div>
|
||||
<TimerNotificationContent {...props} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -32,7 +32,6 @@ export const SessionMessagesList = (props: {
|
|||
<GroupUpdateItem
|
||||
key={messageProps.propsForMessage.id}
|
||||
groupNotificationProps={groupNotificationProps}
|
||||
messageId={messageProps.propsForMessage.id}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -42,7 +41,6 @@ export const SessionMessagesList = (props: {
|
|||
<GroupInvitationItem
|
||||
key={messageProps.propsForMessage.id}
|
||||
propsForGroupInvitation={propsForGroupInvitation}
|
||||
messageId={messageProps.propsForMessage.id}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -52,18 +50,13 @@ export const SessionMessagesList = (props: {
|
|||
<DataExtractionNotificationItem
|
||||
key={messageProps.propsForMessage.id}
|
||||
propsForDataExtractionNotification={propsForDataExtractionNotification}
|
||||
messageId={messageProps.propsForMessage.id}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (timerProps) {
|
||||
return (
|
||||
<TimerNotificationItem
|
||||
key={messageProps.propsForMessage.id}
|
||||
timerProps={timerProps}
|
||||
messageId={messageProps.propsForMessage.id}
|
||||
/>
|
||||
<TimerNotificationItem key={messageProps.propsForMessage.id} timerProps={timerProps} />
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -269,7 +269,6 @@ class SessionMessagesListContainerInner extends React.Component<Props> {
|
|||
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<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
|
|
|
@ -31,56 +31,54 @@ export const UnreadIndicator = (props: { messageId: string }) => {
|
|||
return <SessionLastSeenIndicator key={`unread-indicator-${props.messageId}`} />;
|
||||
};
|
||||
|
||||
export const GroupUpdateItem = (props: {
|
||||
messageId: string;
|
||||
groupNotificationProps: PropsForGroupUpdate;
|
||||
}) => {
|
||||
export const GroupUpdateItem = (props: { groupNotificationProps: PropsForGroupUpdate }) => {
|
||||
return (
|
||||
<React.Fragment key={props.messageId}>
|
||||
<GroupNotification key={props.messageId} {...props.groupNotificationProps} />
|
||||
<UnreadIndicator messageId={props.messageId} />
|
||||
<React.Fragment key={props.groupNotificationProps.messageId}>
|
||||
<GroupNotification
|
||||
key={props.groupNotificationProps.messageId}
|
||||
{...props.groupNotificationProps}
|
||||
/>
|
||||
<UnreadIndicator messageId={props.groupNotificationProps.messageId} />
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export const GroupInvitationItem = (props: {
|
||||
messageId: string;
|
||||
propsForGroupInvitation: PropsForGroupInvitation;
|
||||
}) => {
|
||||
return (
|
||||
<React.Fragment key={props.messageId}>
|
||||
<GroupInvitation key={props.messageId} {...props.propsForGroupInvitation} />
|
||||
<React.Fragment key={props.propsForGroupInvitation.messageId}>
|
||||
<GroupInvitation
|
||||
key={props.propsForGroupInvitation.messageId}
|
||||
{...props.propsForGroupInvitation}
|
||||
/>
|
||||
|
||||
<UnreadIndicator messageId={props.messageId} />
|
||||
<UnreadIndicator messageId={props.propsForGroupInvitation.messageId} />
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export const DataExtractionNotificationItem = (props: {
|
||||
messageId: string;
|
||||
propsForDataExtractionNotification: PropsForDataExtractionNotification;
|
||||
}) => {
|
||||
return (
|
||||
<React.Fragment key={props.messageId}>
|
||||
<React.Fragment key={props.propsForDataExtractionNotification.messageId}>
|
||||
<DataExtractionNotification
|
||||
key={props.messageId}
|
||||
key={props.propsForDataExtractionNotification.messageId}
|
||||
{...props.propsForDataExtractionNotification}
|
||||
/>
|
||||
|
||||
<UnreadIndicator messageId={props.messageId} />
|
||||
<UnreadIndicator messageId={props.propsForDataExtractionNotification.messageId} />
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export const TimerNotificationItem = (props: {
|
||||
messageId: string;
|
||||
timerProps: PropsForExpirationTimer;
|
||||
}) => {
|
||||
export const TimerNotificationItem = (props: { timerProps: PropsForExpirationTimer }) => {
|
||||
return (
|
||||
<React.Fragment key={props.messageId}>
|
||||
<TimerNotification key={props.messageId} {...props.timerProps} />
|
||||
<React.Fragment key={props.timerProps.messageId}>
|
||||
<TimerNotification key={props.timerProps.messageId} {...props.timerProps} />
|
||||
|
||||
<UnreadIndicator messageId={props.messageId} />
|
||||
<UnreadIndicator messageId={props.timerProps.messageId} />
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -298,6 +298,7 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
|
|||
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<MessageAttributes> {
|
|||
return {
|
||||
...dataExtractionNotification,
|
||||
name: contact.profileName || contact.name || dataExtractionNotification.source,
|
||||
messageId: this.id,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -462,6 +464,7 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
|
|||
|
||||
return {
|
||||
changes,
|
||||
messageId: this.id,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -111,6 +111,7 @@ export interface DataExtractionNotificationMsg {
|
|||
|
||||
export type PropsForDataExtractionNotification = DataExtractionNotificationMsg & {
|
||||
name: string;
|
||||
messageId: string;
|
||||
};
|
||||
|
||||
export interface MessageAttributesOptionals {
|
||||
|
|
|
@ -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<PropsForGroupUpdateType>;
|
|||
|
||||
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,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue