Use POJO instead of MessageModel in ConversationView quote logic
This commit is contained in:
parent
c9b1ce6655
commit
6b2dfeb9f5
8 changed files with 92 additions and 119 deletions
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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'] {
|
||||
|
|
|
@ -7,7 +7,7 @@ import { instance, PhoneNumberFormat } from '../util/libphonenumberInstance';
|
|||
function _format(
|
||||
phoneNumber: string,
|
||||
options: {
|
||||
ourRegionCode: string;
|
||||
ourRegionCode?: string;
|
||||
}
|
||||
) {
|
||||
try {
|
||||
|
|
55
ts/util/findAndFormatContact.ts
Normal file
55
ts/util/findAndFormatContact.ts
Normal 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',
|
||||
};
|
||||
}
|
|
@ -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
26
ts/window.d.ts
vendored
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue