Use POJO instead of MessageModel in ConversationView quote logic

This commit is contained in:
Evan Hahn 2021-06-22 18:16:50 -05:00 committed by GitHub
parent c9b1ce6655
commit 6b2dfeb9f5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 92 additions and 119 deletions

View file

@ -137,7 +137,6 @@ const Errors = require('./types/errors');
const MediaGalleryMessage = require('../../ts/components/conversation/media-gallery/types/Message');
const MessageType = require('./types/message');
const MIME = require('../../ts/types/MIME');
const PhoneNumber = require('../../ts/types/PhoneNumber');
const SettingsType = require('../../ts/types/Settings');
// Views
@ -417,7 +416,6 @@ exports.setup = (options = {}) => {
Errors,
Message: MessageType,
MIME,
PhoneNumber,
Settings: SettingsType,
VisualAttachment,
};

View file

@ -2831,7 +2831,13 @@ export class ConversationModel extends window.Backbone
return null;
}
return number.error || 'Invalid phone number';
let errorMessage: undefined | string;
if (number.error instanceof Error) {
errorMessage = number.error.message;
} else if (typeof number.error === 'string') {
errorMessage = number.error;
}
return errorMessage || 'Invalid phone number';
}
return null;

View file

@ -13,7 +13,6 @@ import {
import { find } from '../util/iterables';
import { DataMessageClass } from '../textsecure.d';
import { ConversationModel } from './conversations';
import { ConversationType } from '../state/ducks/conversations';
import { MessageStatusType } from '../components/conversation/Message';
import {
OwnProps as SmartMessageDetailPropsType,
@ -36,6 +35,7 @@ import {
} from '../util/whatTypeOfConversation';
import { handleMessageSend } from '../util/handleMessageSend';
import { getSendOptions } from '../util/getSendOptions';
import { findAndFormatContact } from '../util/findAndFormatContact';
import {
getLastChallengeError,
getMessagePropStatus,
@ -83,27 +83,6 @@ type PropsForMessageDetail = Pick<
'sentAt' | 'receivedAt' | 'message' | 'errors' | 'contacts'
>;
type FormattedContact = Partial<ConversationType> &
Pick<
ConversationType,
| 'acceptedMessageRequest'
| 'id'
| 'isMe'
| 'sharedGroupNames'
| 'title'
| 'type'
| 'unblurredAvatarPath'
>;
export const PLACEHOLDER_CONTACT: FormattedContact = {
acceptedMessageRequest: false,
id: 'placeholder-contact',
isMe: false,
sharedGroupNames: [],
title: window.i18n('unknownContact'),
type: 'direct',
};
declare const _: typeof window._;
window.Whisper = window.Whisper || {};
@ -113,7 +92,6 @@ const {
Attachment,
MIME,
Contact,
PhoneNumber,
Errors,
} = window.Signal.Types;
const {
@ -181,9 +159,6 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
isSelected?: boolean;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
quotedMessage: any;
syncPromise?: Promise<unknown>;
initialize(attributes: unknown): void {
@ -203,7 +178,6 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
this.OUR_NUMBER = window.textsecure.storage.user.getNumber();
this.OUR_UUID = window.textsecure.storage.user.getUuid();
this.on('unload', this.unload);
this.on('change', this.notifyRedux);
}
@ -327,7 +301,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
this.isUnidentifiedDelivery(id, unidentifiedLookup);
return {
...this.findAndFormatContact(id),
...findAndFormatContact(id),
status: this.getStatus(id),
errors: errorsForContact,
@ -363,7 +337,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
receivedAt: this.getReceivedAt(),
message: getPropsForMessage(
this.attributes,
(id?: string | undefined) => this.findAndFormatContact(id),
findAndFormatContact,
window.ConversationController.getOurConversationIdOrThrow(),
this.OUR_NUMBER,
this.OUR_UUID,
@ -383,44 +357,6 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
}
// Dependencies of prop-generation functions
findAndFormatContact(identifier?: string): FormattedContact {
if (!identifier) {
return PLACEHOLDER_CONTACT;
}
const contactModel = this.findContact(identifier);
if (contactModel) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return contactModel.format()!;
}
const { format, isValidNumber } = PhoneNumber;
const regionCode = window.storage.get('regionCode');
if (!isValidNumber(identifier, { regionCode })) {
return PLACEHOLDER_CONTACT;
}
const phoneNumber = format(identifier, {
ourRegionCode: regionCode,
});
return {
acceptedMessageRequest: false,
id: 'phone-only',
isMe: false,
phoneNumber,
sharedGroupNames: [],
title: phoneNumber,
type: 'direct',
};
}
// eslint-disable-next-line class-methods-use-this
findContact(identifier?: string): ConversationModel | undefined {
return window.ConversationController.get(identifier);
}
getConversation(): ConversationModel | undefined {
return window.ConversationController.get(this.get('conversationId'));
}
@ -484,7 +420,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
if (isProfileChange(attributes)) {
const change = this.get('profileChange');
const changedId = this.get('changedId');
const changedContact = this.findAndFormatContact(changedId);
const changedContact = findAndFormatContact(changedId);
if (!change) {
throw new Error('getNotificationData: profileChange was missing!');
}
@ -694,7 +630,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
const state = window.reduxStore.getState();
const callingNotification = getPropsForCallHistory(
attributes,
(id?: string | undefined) => this.findAndFormatContact(id),
findAndFormatContact,
getCallSelector(state),
getActiveCall(state)
);
@ -724,7 +660,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
if (isKeyChange(attributes)) {
const identifier = this.get('key_changed');
const conversation = this.findContact(identifier);
const conversation = window.ConversationController.get(identifier);
return {
text: window.i18n('safetyNumberChangedGroup', [
conversation ? conversation.getTitle() : null,
@ -752,7 +688,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
const bodyRanges = processBodyRanges(
attributes.bodyRanges,
(id?: string | undefined) => this.findAndFormatContact(id)
findAndFormatContact
);
if (bodyRanges) {
return getTextWithMentions(bodyRanges, body);
@ -769,7 +705,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
const bodyRanges = processBodyRanges(
attributes.bodyRanges,
(id?: string | undefined) => this.findAndFormatContact(id)
findAndFormatContact
);
if (bodyRanges && bodyRanges.length) {
@ -839,7 +775,6 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
this.getConversation()?.debouncedUpdateLastMessage?.();
window.MessageController.unregister(this.id);
this.unload();
await this.deleteData();
}
@ -963,7 +898,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
}
const { authorUuid, author, id: sentAt, referencedMessageNotFound } = quote;
const contact = this.findContact(authorUuid || author);
const contact = window.ConversationController.get(authorUuid || author);
// Is the quote really without a reference? Check with our in memory store
// first to make sure it's not there.
@ -1114,12 +1049,6 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
return !hasSomethingToDisplay;
}
unload(): void {
if (this.quotedMessage) {
this.quotedMessage = null;
}
}
isUnidentifiedDelivery(
contactId: string,
lookup: Record<string, unknown>

View file

@ -291,7 +291,7 @@ export function getContact(
}
export function getConversation(
message: MessageAttributesType,
message: Pick<MessageAttributesType, 'conversationId'>,
conversationSelector: GetConversationByIdType
): ConversationType {
return conversationSelector(message.conversationId);
@ -987,7 +987,7 @@ function getPropsForPreview(
}
export function getPropsForQuote(
message: MessageAttributesType,
message: Pick<MessageAttributesType, 'conversationId' | 'quote'>,
conversationSelector: GetConversationByIdType,
ourConversationId: string | undefined
): PropsData['quote'] {

View file

@ -7,7 +7,7 @@ import { instance, PhoneNumberFormat } from '../util/libphonenumberInstance';
function _format(
phoneNumber: string,
options: {
ourRegionCode: string;
ourRegionCode?: string;
}
) {
try {

View file

@ -0,0 +1,55 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { ConversationType } from '../state/ducks/conversations';
import { format, isValidNumber } from '../types/PhoneNumber';
type FormattedContact = Partial<ConversationType> &
Pick<
ConversationType,
| 'acceptedMessageRequest'
| 'id'
| 'isMe'
| 'sharedGroupNames'
| 'title'
| 'type'
| 'unblurredAvatarPath'
>;
const PLACEHOLDER_CONTACT: FormattedContact = {
acceptedMessageRequest: false,
id: 'placeholder-contact',
isMe: false,
sharedGroupNames: [],
title: window.i18n('unknownContact'),
type: 'direct',
};
export function findAndFormatContact(identifier?: string): FormattedContact {
if (!identifier) {
return PLACEHOLDER_CONTACT;
}
const contactModel = window.ConversationController.get(identifier);
if (contactModel) {
return contactModel.format();
}
const regionCode = window.storage.get('regionCode');
if (!isValidNumber(identifier, { regionCode })) {
return PLACEHOLDER_CONTACT;
}
const phoneNumber = format(identifier, { ourRegionCode: regionCode });
return {
acceptedMessageRequest: false,
id: 'phone-only',
isMe: false,
phoneNumber,
sharedGroupNames: [],
title: phoneNumber,
type: 'direct',
};
}

View file

@ -23,6 +23,7 @@ import {
isGroupV1,
isMe,
} from '../util/whatTypeOfConversation';
import { findAndFormatContact } from '../util/findAndFormatContact';
import * as Bytes from '../Bytes';
import {
canReply,
@ -3745,12 +3746,7 @@ Whisper.ConversationView = Whisper.View.extend({
})
: undefined;
if (
message &&
!canReply(message.attributes, (id?: string) =>
message.findAndFormatContact(id)
)
) {
if (message && !canReply(message.attributes, findAndFormatContact)) {
return;
}
@ -3760,7 +3756,6 @@ Whisper.ConversationView = Whisper.View.extend({
this.quote = null;
this.quotedMessage = null;
this.quoteHolder = null;
const existing = model.get('quotedMessageId');
if (existing !== messageId) {
@ -3806,16 +3801,12 @@ Whisper.ConversationView = Whisper.View.extend({
return;
}
const message = new Whisper.Message({
conversationId: model.id,
quote: this.quote,
} as any);
message.quotedMessage = this.quotedMessage;
this.quoteHolder = message;
const props = getPropsForQuote(
message.attributes,
(id?: string) => message.findAndFormatContact(id),
{
conversationId: model.id,
quote: this.quote,
},
findAndFormatContact,
window.ConversationController.getOurConversationIdOrThrow()
);
@ -3829,7 +3820,7 @@ Whisper.ConversationView = Whisper.View.extend({
props: {
...props,
withContentAbove: true,
onClick: () => this.scrollToMessage(message.quotedMessage.id),
onClick: () => this.scrollToMessage(this.quotedMessage.id),
onClose: () => {
// This can't be the normal 'onClose' because that is always run when this
// view is removed from the DOM, and would clear the draft quote.

26
ts/window.d.ts vendored
View file

@ -220,8 +220,16 @@ declare global {
getRegionCodeForNumber: (number: string) => string;
parseNumber: (
e164: string,
regionCode: string
) => typeof window.Signal.Types.PhoneNumber;
defaultRegionCode: string
) =>
| { isValidNumber: false; error: unknown }
| {
isValidNumber: true;
regionCode: string | undefined;
countryCode: string;
nationalNumber: string;
e164: string;
};
};
parse: (number: string) => string;
getRegionCodeForNumber: (number: string) => string;
@ -400,20 +408,6 @@ declare global {
options: unknown
) => Promise<WhatIsThis>;
};
PhoneNumber: {
format: (
identifier: string,
options: Record<string, unknown>
) => string;
isValidNumber(
phoneNumber: string,
options?: {
regionCode?: string;
}
): boolean;
e164: string;
error: string;
};
Errors: typeof Errors;
Message: {
CURRENT_SCHEMA_VERSION: number;