Remove refs to MessageModel in conversations.ts
This commit is contained in:
parent
2550af9c91
commit
cc6ff0b554
17 changed files with 312 additions and 357 deletions
18
ts/groups.ts
18
ts/groups.ts
|
@ -2025,13 +2025,12 @@ export async function createGroupV2(
|
|||
forceSave: true,
|
||||
ourAci,
|
||||
});
|
||||
let model = new window.Whisper.Message(createdTheGroupMessage);
|
||||
model = window.MessageCache.__DEPRECATED$register(
|
||||
model.id,
|
||||
model,
|
||||
window.MessageCache.__DEPRECATED$register(
|
||||
createdTheGroupMessage.id,
|
||||
new window.Whisper.Message(createdTheGroupMessage),
|
||||
'createGroupV2'
|
||||
);
|
||||
conversation.trigger('newmessage', model);
|
||||
conversation.trigger('newmessage', createdTheGroupMessage);
|
||||
|
||||
if (expireTimer) {
|
||||
await conversation.updateExpirationTimer(expireTimer, {
|
||||
|
@ -3435,13 +3434,12 @@ async function appendChangeMessages(
|
|||
continue;
|
||||
}
|
||||
|
||||
let model = new window.Whisper.Message(changeMessage);
|
||||
model = window.MessageCache.__DEPRECATED$register(
|
||||
model.id,
|
||||
model,
|
||||
window.MessageCache.__DEPRECATED$register(
|
||||
changeMessage.id,
|
||||
new window.Whisper.Message(changeMessage),
|
||||
'appendChangeMessages'
|
||||
);
|
||||
conversation.trigger('newmessage', model);
|
||||
conversation.trigger('newmessage', changeMessage);
|
||||
newMessages += 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -341,13 +341,12 @@ export async function sendReaction(
|
|||
forceSave: true,
|
||||
});
|
||||
|
||||
void conversation.addSingleMessage(
|
||||
window.MessageCache.__DEPRECATED$register(
|
||||
reactionMessage.id,
|
||||
reactionMessage,
|
||||
'sendReaction'
|
||||
)
|
||||
window.MessageCache.__DEPRECATED$register(
|
||||
reactionMessage.id,
|
||||
reactionMessage,
|
||||
'sendReaction'
|
||||
);
|
||||
void conversation.addSingleMessage(reactionMessage.attributes);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,8 +4,10 @@
|
|||
import { z } from 'zod';
|
||||
import { groupBy } from 'lodash';
|
||||
|
||||
import type { MessageModel } from '../models/messages';
|
||||
import type { MessageAttributesType } from '../model-types.d';
|
||||
import type {
|
||||
MessageAttributesType,
|
||||
ReadonlyMessageAttributesType,
|
||||
} from '../model-types.d';
|
||||
import type { SendStateByConversationId } from '../messages/MessageSendState';
|
||||
import { isOutgoing, isStory } from '../state/selectors/message';
|
||||
import { getOwn } from '../util/getOwn';
|
||||
|
@ -376,7 +378,7 @@ const wasDeliveredWithSealedSender = (
|
|||
|
||||
const shouldDropReceipt = (
|
||||
receipt: MessageReceiptAttributesType,
|
||||
message: MessageAttributesType
|
||||
message: ReadonlyMessageAttributesType
|
||||
): boolean => {
|
||||
const { type } = receipt.receiptSync;
|
||||
switch (type) {
|
||||
|
@ -395,25 +397,25 @@ const shouldDropReceipt = (
|
|||
};
|
||||
|
||||
export async function forMessage(
|
||||
message: MessageModel
|
||||
message: ReadonlyMessageAttributesType
|
||||
): Promise<Array<MessageReceiptAttributesType>> {
|
||||
if (!isOutgoing(message.attributes) && !isStory(message.attributes)) {
|
||||
if (!isOutgoing(message) && !isStory(message)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const logId = `MessageReceipts.forMessage(${getMessageIdForLogging(
|
||||
message.attributes
|
||||
message
|
||||
)})`;
|
||||
|
||||
const ourAci = window.textsecure.storage.user.getCheckedAci();
|
||||
const sourceServiceId = getSourceServiceId(message.attributes);
|
||||
const sourceServiceId = getSourceServiceId(message);
|
||||
if (ourAci !== sourceServiceId) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const receiptValues = Array.from(cachedReceipts.values());
|
||||
|
||||
const sentAt = getMessageSentTimestamp(message.attributes, { log });
|
||||
const sentAt = getMessageSentTimestamp(message, { log });
|
||||
const result = receiptValues.filter(
|
||||
item => item.receiptSync.messageSentAt === sentAt
|
||||
);
|
||||
|
@ -427,7 +429,7 @@ export async function forMessage(
|
|||
}
|
||||
|
||||
return result.filter(receipt => {
|
||||
if (shouldDropReceipt(receipt, message.attributes)) {
|
||||
if (shouldDropReceipt(receipt, message)) {
|
||||
log.info(
|
||||
`${logId}: Dropping an early receipt ${receipt.receiptSync.type} for message ${sentAt}`
|
||||
);
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { AciString } from '../types/ServiceId';
|
||||
import type { MessageAttributesType } from '../model-types.d';
|
||||
import type {
|
||||
MessageAttributesType,
|
||||
ReadonlyMessageAttributesType,
|
||||
} from '../model-types.d';
|
||||
import type { MessageModel } from '../models/messages';
|
||||
import type { ReactionSource } from '../reactions/ReactionSource';
|
||||
import { DataReader } from '../sql/Client';
|
||||
|
@ -41,11 +44,11 @@ function remove(reaction: ReactionAttributesType): void {
|
|||
}
|
||||
|
||||
export function findReactionsForMessage(
|
||||
message: MessageModel
|
||||
message: ReadonlyMessageAttributesType
|
||||
): Array<ReactionAttributesType> {
|
||||
const matchingReactions = Array.from(reactions.values()).filter(reaction => {
|
||||
return isMessageAMatchForReaction({
|
||||
message: message.attributes,
|
||||
message,
|
||||
targetTimestamp: reaction.targetTimestamp,
|
||||
targetAuthorAci: reaction.targetAuthorAci,
|
||||
reactionSenderConversationId: reaction.fromId,
|
||||
|
@ -99,7 +102,7 @@ function isMessageAMatchForReaction({
|
|||
targetAuthorAci,
|
||||
reactionSenderConversationId,
|
||||
}: {
|
||||
message: MessageAttributesType;
|
||||
message: ReadonlyMessageAttributesType;
|
||||
targetTimestamp: number;
|
||||
targetAuthorAci: string;
|
||||
reactionSenderConversationId: string;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import { z } from 'zod';
|
||||
|
||||
import type { MessageModel } from '../models/messages';
|
||||
import type { ReadonlyMessageAttributesType } from '../model-types.d';
|
||||
import * as Errors from '../types/errors';
|
||||
import * as log from '../logging/log';
|
||||
import { StartupQueue } from '../util/StartupQueue';
|
||||
|
@ -88,18 +88,16 @@ async function maybeItIsAReactionReadSync(
|
|||
}
|
||||
|
||||
export async function forMessage(
|
||||
message: MessageModel
|
||||
message: ReadonlyMessageAttributesType
|
||||
): Promise<ReadSyncAttributesType | null> {
|
||||
const logId = `ReadSyncs.forMessage(${getMessageIdForLogging(
|
||||
message.attributes
|
||||
)})`;
|
||||
const logId = `ReadSyncs.forMessage(${getMessageIdForLogging(message)})`;
|
||||
|
||||
const sender = window.ConversationController.lookupOrCreate({
|
||||
e164: message.get('source'),
|
||||
serviceId: message.get('sourceServiceId'),
|
||||
e164: message.source,
|
||||
serviceId: message.sourceServiceId,
|
||||
reason: logId,
|
||||
});
|
||||
const messageTimestamp = getMessageSentTimestamp(message.attributes, {
|
||||
const messageTimestamp = getMessageSentTimestamp(message, {
|
||||
log,
|
||||
});
|
||||
const readSyncValues = Array.from(readSyncs.values());
|
||||
|
@ -169,7 +167,9 @@ export async function onSync(sync: ReadSyncAttributesType): Promise<void> {
|
|||
// onReadMessage may result in messages older than this one being
|
||||
// marked read. We want those messages to have the same expire timer
|
||||
// start time as this one, so we pass the readAt value through.
|
||||
drop(conversation.onReadMessage(message, readAt, newestSentAt));
|
||||
drop(
|
||||
conversation.onReadMessage(message.attributes, readAt, newestSentAt)
|
||||
);
|
||||
};
|
||||
|
||||
// only available during initialization
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { AciString } from '../types/ServiceId';
|
||||
import type { MessageModel } from '../models/messages';
|
||||
import type { ReadonlyMessageAttributesType } from '../model-types.d';
|
||||
import { DataReader } from '../sql/Client';
|
||||
import * as Errors from '../types/errors';
|
||||
import * as log from '../logging/log';
|
||||
|
@ -23,18 +23,18 @@ function remove(sync: ViewOnceOpenSyncAttributesType): void {
|
|||
}
|
||||
|
||||
export function forMessage(
|
||||
message: MessageModel
|
||||
message: ReadonlyMessageAttributesType
|
||||
): ViewOnceOpenSyncAttributesType | null {
|
||||
const logId = `ViewOnceOpenSyncs.forMessage(${getMessageIdForLogging(
|
||||
message.attributes
|
||||
message
|
||||
)})`;
|
||||
|
||||
const viewOnceSyncValues = Array.from(viewOnceSyncs.values());
|
||||
|
||||
const syncBySourceServiceId = viewOnceSyncValues.find(item => {
|
||||
return (
|
||||
item.sourceAci === message.get('sourceServiceId') &&
|
||||
item.timestamp === message.get('sent_at')
|
||||
item.sourceAci === message.sourceServiceId &&
|
||||
item.timestamp === message.sent_at
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -45,10 +45,7 @@ export function forMessage(
|
|||
}
|
||||
|
||||
const syncBySource = viewOnceSyncValues.find(item => {
|
||||
return (
|
||||
item.source === message.get('source') &&
|
||||
item.timestamp === message.get('sent_at')
|
||||
);
|
||||
return item.source === message.source && item.timestamp === message.sent_at;
|
||||
});
|
||||
if (syncBySource) {
|
||||
log.info(`${logId}: Found early view once open sync for message`);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import { z } from 'zod';
|
||||
|
||||
import type { MessageModel } from '../models/messages';
|
||||
import type { ReadonlyMessageAttributesType } from '../model-types.d';
|
||||
import * as Errors from '../types/errors';
|
||||
import * as log from '../logging/log';
|
||||
import { GiftBadgeStates } from '../components/conversation/Message';
|
||||
|
@ -44,18 +44,16 @@ async function remove(sync: ViewSyncAttributesType): Promise<void> {
|
|||
}
|
||||
|
||||
export async function forMessage(
|
||||
message: MessageModel
|
||||
message: ReadonlyMessageAttributesType
|
||||
): Promise<Array<ViewSyncAttributesType>> {
|
||||
const logId = `ViewSyncs.forMessage(${getMessageIdForLogging(
|
||||
message.attributes
|
||||
)})`;
|
||||
const logId = `ViewSyncs.forMessage(${getMessageIdForLogging(message)})`;
|
||||
|
||||
const sender = window.ConversationController.lookupOrCreate({
|
||||
e164: message.get('source'),
|
||||
serviceId: message.get('sourceServiceId'),
|
||||
e164: message.source,
|
||||
serviceId: message.sourceServiceId,
|
||||
reason: logId,
|
||||
});
|
||||
const messageTimestamp = getMessageSentTimestamp(message.attributes, {
|
||||
const messageTimestamp = getMessageSentTimestamp(message, {
|
||||
log,
|
||||
});
|
||||
|
||||
|
|
|
@ -22,6 +22,9 @@ import { isShallowEqual } from '../util/isShallowEqual';
|
|||
import { getInitials } from '../util/getInitials';
|
||||
import { clearTimeoutIfNecessary } from '../util/clearTimeoutIfNecessary';
|
||||
import { getMessageSentTimestamp } from '../util/getMessageSentTimestamp';
|
||||
import { getNotificationTextForMessage } from '../util/getNotificationTextForMessage';
|
||||
import { getNotificationDataForMessage } from '../util/getNotificationDataForMessage';
|
||||
import type { ProfileNameChangeType } from '../util/getStringForProfileChange';
|
||||
import type { AttachmentType, ThumbnailType } from '../types/Attachment';
|
||||
import { toDayMillis } from '../util/timestamp';
|
||||
import { areWeAdmin } from '../util/areWeAdmin';
|
||||
|
@ -35,6 +38,7 @@ import {
|
|||
import { getDraftPreview } from '../util/getDraftPreview';
|
||||
import { hasDraft } from '../util/hasDraft';
|
||||
import { missingCaseError } from '../util/missingCaseError';
|
||||
import { hydrateStoryContext } from '../util/hydrateStoryContext';
|
||||
import * as Conversation from '../types/Conversation';
|
||||
import type { StickerType, StickerWithHydratedData } from '../types/Stickers';
|
||||
import * as Stickers from '../types/Stickers';
|
||||
|
@ -56,7 +60,6 @@ import type {
|
|||
ConversationColorType,
|
||||
CustomColorType,
|
||||
} from '../types/Colors';
|
||||
import type { MessageModel } from './messages';
|
||||
import { getAuthor } from '../messages/helpers';
|
||||
import { strictAssert } from '../util/assert';
|
||||
import { isConversationMuted } from '../util/isConversationMuted';
|
||||
|
@ -173,6 +176,7 @@ import OS from '../util/os/osMain';
|
|||
import { getMessageAuthorText } from '../util/getMessageAuthorText';
|
||||
import { downscaleOutgoingAttachment } from '../util/attachments';
|
||||
import { MessageRequestResponseEvent } from '../types/MessageRequestResponseEvent';
|
||||
import { hasExpiration } from '../types/Message2';
|
||||
import type { MessageToDelete } from '../textsecure/messageReceiverEvents';
|
||||
import {
|
||||
getConversationToDelete,
|
||||
|
@ -399,7 +403,7 @@ export class ConversationModel extends window.Backbone
|
|||
// result in refresh via a getProps() call. See format() below.
|
||||
this.on(
|
||||
'change',
|
||||
(_model: MessageModel, options: { force?: boolean } = {}) => {
|
||||
(_model: ConversationModel, options: { force?: boolean } = {}) => {
|
||||
const changedKeys = Object.keys(this.changed || {});
|
||||
const isPropsCacheStillValid =
|
||||
!options.force &&
|
||||
|
@ -1395,10 +1399,8 @@ export class ConversationModel extends window.Backbone
|
|||
});
|
||||
}
|
||||
|
||||
async onNewMessage(message: MessageModel): Promise<void> {
|
||||
const serviceId = message.get('sourceServiceId');
|
||||
const e164 = message.get('source');
|
||||
const sourceDevice = message.get('sourceDevice');
|
||||
async onNewMessage(message: MessageAttributesType): Promise<void> {
|
||||
const { sourceServiceId: serviceId, source: e164, sourceDevice } = message;
|
||||
|
||||
const source = window.ConversationController.lookupOrCreate({
|
||||
serviceId,
|
||||
|
@ -1414,16 +1416,15 @@ export class ConversationModel extends window.Backbone
|
|||
|
||||
// If it's a group story reply or a story message, we don't want to update
|
||||
// the last message or add new messages to redux.
|
||||
const isGroupStoryReply =
|
||||
isGroup(this.attributes) && message.get('storyId');
|
||||
if (isGroupStoryReply || isStory(message.attributes)) {
|
||||
const isGroupStoryReply = isGroup(this.attributes) && message.storyId;
|
||||
if (isGroupStoryReply || isStory(message)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Change to message request state if contact was removed and sent message.
|
||||
if (
|
||||
this.get('removalStage') === 'justNotification' &&
|
||||
isIncoming(message.attributes)
|
||||
isIncoming(message)
|
||||
) {
|
||||
this.set({
|
||||
removalStage: 'messageRequest',
|
||||
|
@ -1438,7 +1439,7 @@ export class ConversationModel extends window.Backbone
|
|||
// New messages might arrive while we're in the middle of a bulk fetch from the
|
||||
// database. We'll wait until that is done before moving forward.
|
||||
async addSingleMessage(
|
||||
message: MessageModel,
|
||||
message: MessageAttributesType,
|
||||
{ isJustSent }: { isJustSent: boolean } = { isJustSent: false }
|
||||
): Promise<void> {
|
||||
await this.beforeAddSingleMessage(message);
|
||||
|
@ -1446,8 +1447,10 @@ export class ConversationModel extends window.Backbone
|
|||
this.debouncedUpdateLastMessage();
|
||||
}
|
||||
|
||||
private async beforeAddSingleMessage(message: MessageModel): Promise<void> {
|
||||
await message.hydrateStoryContext(undefined, { shouldSave: true });
|
||||
private async beforeAddSingleMessage(
|
||||
message: MessageAttributesType
|
||||
): Promise<void> {
|
||||
await hydrateStoryContext(message.id, undefined, { shouldSave: true });
|
||||
|
||||
if (!this.newMessageQueue) {
|
||||
this.newMessageQueue = new PQueue({
|
||||
|
@ -1463,7 +1466,7 @@ export class ConversationModel extends window.Backbone
|
|||
}
|
||||
|
||||
private doAddSingleMessage(
|
||||
message: MessageModel,
|
||||
message: MessageAttributesType,
|
||||
{ isJustSent }: { isJustSent: boolean }
|
||||
): void {
|
||||
const { messagesAdded } = window.reduxActions.conversations;
|
||||
|
@ -1486,12 +1489,12 @@ export class ConversationModel extends window.Backbone
|
|||
} else if (
|
||||
// The message has to be not a story or has to be a story reply in direct
|
||||
// conversation.
|
||||
!isStory(message.attributes) &&
|
||||
(message.get('storyId') == null || isDirectConversation(this.attributes))
|
||||
!isStory(message) &&
|
||||
(message.storyId == null || isDirectConversation(this.attributes))
|
||||
) {
|
||||
messagesAdded({
|
||||
conversationId,
|
||||
messages: [{ ...message.attributes }],
|
||||
messages: [{ ...message }],
|
||||
isActive: window.SignalContext.activeWindowService.isActive(),
|
||||
isJustSent,
|
||||
isNewMessage: true,
|
||||
|
@ -1598,13 +1601,13 @@ export class ConversationModel extends window.Backbone
|
|||
storyId: undefined,
|
||||
});
|
||||
|
||||
const cleaned: Array<MessageModel> = await this.cleanModels(messages);
|
||||
const cleaned = await this.cleanAttributes(messages);
|
||||
const scrollToMessageId =
|
||||
setFocus && metrics.newest ? metrics.newest.id : undefined;
|
||||
|
||||
log.info(
|
||||
`${logId}: loaded ${cleaned.length} messages, ` +
|
||||
`latest timestamp=${cleaned.at(-1)?.get('sent_at')}`
|
||||
`latest timestamp=${cleaned.at(-1)?.sent_at}`
|
||||
);
|
||||
|
||||
// Because our `getOlderMessages` fetch above didn't specify a receivedAt, we got
|
||||
|
@ -1615,9 +1618,7 @@ export class ConversationModel extends window.Backbone
|
|||
const unboundedFetch = true;
|
||||
messagesReset({
|
||||
conversationId,
|
||||
messages: cleaned.map((messageModel: MessageModel) => ({
|
||||
...messageModel.attributes,
|
||||
})),
|
||||
messages: cleaned,
|
||||
metrics,
|
||||
scrollToMessageId,
|
||||
unboundedFetch,
|
||||
|
@ -1666,18 +1667,16 @@ export class ConversationModel extends window.Backbone
|
|||
return;
|
||||
}
|
||||
|
||||
const cleaned = await this.cleanModels(models);
|
||||
const cleaned = await this.cleanAttributes(models);
|
||||
|
||||
log.info(
|
||||
`${logId}: loaded ${cleaned.length} messages, ` +
|
||||
`first timestamp=${cleaned.at(0)?.get('sent_at')}`
|
||||
`first timestamp=${cleaned.at(0)?.sent_at}`
|
||||
);
|
||||
|
||||
messagesAdded({
|
||||
conversationId,
|
||||
messages: cleaned.map((messageModel: MessageModel) => ({
|
||||
...messageModel.attributes,
|
||||
})),
|
||||
messages: cleaned,
|
||||
isActive: window.SignalContext.activeWindowService.isActive(),
|
||||
isJustSent: false,
|
||||
isNewMessage: false,
|
||||
|
@ -1726,12 +1725,10 @@ export class ConversationModel extends window.Backbone
|
|||
return;
|
||||
}
|
||||
|
||||
const cleaned = await this.cleanModels(models);
|
||||
const cleaned = await this.cleanAttributes(models);
|
||||
messagesAdded({
|
||||
conversationId,
|
||||
messages: cleaned.map((messageModel: MessageModel) => ({
|
||||
...messageModel.attributes,
|
||||
})),
|
||||
messages: cleaned,
|
||||
isActive: window.SignalContext.activeWindowService.isActive(),
|
||||
isJustSent: false,
|
||||
isNewMessage: false,
|
||||
|
@ -1780,15 +1777,13 @@ export class ConversationModel extends window.Backbone
|
|||
});
|
||||
const all = [...older, message, ...newer];
|
||||
|
||||
const cleaned: Array<MessageModel> = await this.cleanModels(all);
|
||||
const cleaned = await this.cleanAttributes(all);
|
||||
const scrollToMessageId =
|
||||
options && options.disableScroll ? undefined : messageId;
|
||||
|
||||
messagesReset({
|
||||
conversationId,
|
||||
messages: cleaned.map((messageModel: MessageModel) => ({
|
||||
...messageModel.attributes,
|
||||
})),
|
||||
messages: cleaned,
|
||||
metrics,
|
||||
scrollToMessageId,
|
||||
});
|
||||
|
@ -1800,52 +1795,53 @@ export class ConversationModel extends window.Backbone
|
|||
}
|
||||
}
|
||||
|
||||
async cleanModels(
|
||||
async cleanAttributes(
|
||||
messages: ReadonlyArray<MessageAttributesType>
|
||||
): Promise<Array<MessageModel>> {
|
||||
const result = messages
|
||||
.filter(message => Boolean(message.id))
|
||||
.map(message =>
|
||||
window.MessageCache.__DEPRECATED$register(
|
||||
message.id,
|
||||
message,
|
||||
'cleanModels'
|
||||
)
|
||||
);
|
||||
): Promise<Array<MessageAttributesType>> {
|
||||
const present = messages.filter(message => Boolean(message.id));
|
||||
|
||||
const eliminated = messages.length - result.length;
|
||||
const eliminated = messages.length - present.length;
|
||||
if (eliminated > 0) {
|
||||
log.warn(`cleanModels: Eliminated ${eliminated} messages without an id`);
|
||||
log.warn(
|
||||
`cleanAttributes: Eliminated ${eliminated} messages without an id`
|
||||
);
|
||||
}
|
||||
const ourAci = window.textsecure.storage.user.getCheckedAci();
|
||||
|
||||
let upgraded = 0;
|
||||
for (let max = result.length, i = 0; i < max; i += 1) {
|
||||
const message = result[i];
|
||||
const { attributes } = message;
|
||||
const { schemaVersion } = attributes;
|
||||
const hydrated = await Promise.all(
|
||||
present.map(async message => {
|
||||
const { schemaVersion } = message;
|
||||
|
||||
if ((schemaVersion || 0) < Message.VERSION_NEEDED_FOR_DISPLAY) {
|
||||
// Yep, we really do want to wait for each of these
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const upgradedMessage = await upgradeMessageSchema(attributes);
|
||||
message.set(upgradedMessage);
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await DataWriter.saveMessage(upgradedMessage, { ourAci });
|
||||
upgraded += 1;
|
||||
}
|
||||
}
|
||||
if (upgraded > 0) {
|
||||
log.warn(`cleanModels: Upgraded schema of ${upgraded} messages`);
|
||||
}
|
||||
const model = window.MessageCache.__DEPRECATED$register(
|
||||
message.id,
|
||||
message,
|
||||
'cleanAttributes'
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
result.map(model =>
|
||||
model.hydrateStoryContext(undefined, { shouldSave: true })
|
||||
)
|
||||
let upgradedMessage = message;
|
||||
if ((schemaVersion || 0) < Message.VERSION_NEEDED_FOR_DISPLAY) {
|
||||
// Yep, we really do want to wait for each of these
|
||||
upgradedMessage = await upgradeMessageSchema(message);
|
||||
model.set(upgradedMessage);
|
||||
await DataWriter.saveMessage(upgradedMessage, { ourAci });
|
||||
upgraded += 1;
|
||||
}
|
||||
|
||||
const patch = await hydrateStoryContext(message.id, undefined, {
|
||||
shouldSave: true,
|
||||
});
|
||||
if (patch) {
|
||||
return { ...upgradedMessage, ...patch };
|
||||
}
|
||||
return upgradedMessage;
|
||||
})
|
||||
);
|
||||
if (upgraded > 0) {
|
||||
log.warn(`cleanAttributes: Upgraded schema of ${upgraded} messages`);
|
||||
}
|
||||
|
||||
return result;
|
||||
return hydrated;
|
||||
}
|
||||
|
||||
format(): ConversationType {
|
||||
|
@ -2178,16 +2174,12 @@ export class ConversationModel extends window.Backbone
|
|||
messageRequestResponseEvent: event,
|
||||
};
|
||||
|
||||
const id = await DataWriter.saveMessage(message, {
|
||||
await DataWriter.saveMessage(message, {
|
||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||
forceSave: true,
|
||||
});
|
||||
const model = new window.Whisper.Message({
|
||||
...message,
|
||||
id,
|
||||
});
|
||||
window.MessageCache.toMessageAttributes(model.attributes);
|
||||
this.trigger('newmessage', model);
|
||||
window.MessageCache.toMessageAttributes(message);
|
||||
this.trigger('newmessage', message);
|
||||
drop(this.updateLastMessage());
|
||||
}
|
||||
|
||||
|
@ -2926,31 +2918,28 @@ export class ConversationModel extends window.Backbone
|
|||
receivedAt,
|
||||
});
|
||||
|
||||
const message = {
|
||||
const message: MessageAttributesType = {
|
||||
id: generateGuid(),
|
||||
conversationId: this.id,
|
||||
type: 'chat-session-refreshed',
|
||||
timestamp: receivedAt,
|
||||
sent_at: receivedAt,
|
||||
received_at: receivedAtCounter,
|
||||
received_at_ms: receivedAt,
|
||||
readStatus: ReadStatus.Unread,
|
||||
seenStatus: SeenStatus.Unseen,
|
||||
// TODO: DESKTOP-722
|
||||
// this type does not fully implement the interface it is expected to
|
||||
} as unknown as MessageAttributesType;
|
||||
};
|
||||
|
||||
const id = await DataWriter.saveMessage(message, {
|
||||
await DataWriter.saveMessage(message, {
|
||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||
});
|
||||
const model = window.MessageCache.__DEPRECATED$register(
|
||||
id,
|
||||
new window.Whisper.Message({
|
||||
...message,
|
||||
id,
|
||||
}),
|
||||
window.MessageCache.__DEPRECATED$register(
|
||||
message.id,
|
||||
message,
|
||||
'addChatSessionRefreshed'
|
||||
);
|
||||
|
||||
this.trigger('newmessage', model);
|
||||
this.trigger('newmessage', message);
|
||||
void this.updateUnread();
|
||||
}
|
||||
|
||||
|
@ -2977,34 +2966,31 @@ export class ConversationModel extends window.Backbone
|
|||
return;
|
||||
}
|
||||
|
||||
const message = {
|
||||
const message: MessageAttributesType = {
|
||||
id: generateGuid(),
|
||||
conversationId: this.id,
|
||||
type: 'delivery-issue',
|
||||
sourceServiceId: senderAci,
|
||||
sent_at: receivedAt,
|
||||
received_at: receivedAtCounter,
|
||||
received_at_ms: receivedAt,
|
||||
timestamp: receivedAt,
|
||||
readStatus: ReadStatus.Unread,
|
||||
seenStatus: SeenStatus.Unseen,
|
||||
// TODO: DESKTOP-722
|
||||
// this type does not fully implement the interface it is expected to
|
||||
} as unknown as MessageAttributesType;
|
||||
};
|
||||
|
||||
const id = await DataWriter.saveMessage(message, {
|
||||
await DataWriter.saveMessage(message, {
|
||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||
});
|
||||
const model = window.MessageCache.__DEPRECATED$register(
|
||||
id,
|
||||
new window.Whisper.Message({
|
||||
...message,
|
||||
id,
|
||||
}),
|
||||
window.MessageCache.__DEPRECATED$register(
|
||||
message.id,
|
||||
message,
|
||||
'addDeliveryIssue'
|
||||
);
|
||||
|
||||
this.trigger('newmessage', model);
|
||||
this.trigger('newmessage', message);
|
||||
|
||||
await this.notify(model);
|
||||
await this.notify(message);
|
||||
void this.updateUnread();
|
||||
}
|
||||
|
||||
|
@ -3048,13 +3034,13 @@ export class ConversationModel extends window.Backbone
|
|||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||
forceSave: true,
|
||||
});
|
||||
const model = window.MessageCache.__DEPRECATED$register(
|
||||
window.MessageCache.__DEPRECATED$register(
|
||||
message.id,
|
||||
new window.Whisper.Message(message),
|
||||
message,
|
||||
'addKeyChange'
|
||||
);
|
||||
|
||||
this.trigger('newmessage', model);
|
||||
this.trigger('newmessage', message);
|
||||
|
||||
const serviceId = this.getServiceId();
|
||||
|
||||
|
@ -3108,20 +3094,17 @@ export class ConversationModel extends window.Backbone
|
|||
schemaVersion: Message.VERSION_NEEDED_FOR_DISPLAY,
|
||||
};
|
||||
|
||||
const id = await DataWriter.saveMessage(message, {
|
||||
await DataWriter.saveMessage(message, {
|
||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||
forceSave: true,
|
||||
});
|
||||
const model = window.MessageCache.__DEPRECATED$register(
|
||||
id,
|
||||
new window.Whisper.Message({
|
||||
...message,
|
||||
id,
|
||||
}),
|
||||
window.MessageCache.__DEPRECATED$register(
|
||||
message.id,
|
||||
message,
|
||||
'addConversationMerge'
|
||||
);
|
||||
|
||||
this.trigger('newmessage', model);
|
||||
this.trigger('newmessage', message);
|
||||
}
|
||||
|
||||
async addPhoneNumberDiscoveryIfNeeded(originalPni: PniString): Promise<void> {
|
||||
|
@ -3160,20 +3143,17 @@ export class ConversationModel extends window.Backbone
|
|||
schemaVersion: Message.VERSION_NEEDED_FOR_DISPLAY,
|
||||
};
|
||||
|
||||
const id = await DataWriter.saveMessage(message, {
|
||||
await DataWriter.saveMessage(message, {
|
||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||
forceSave: true,
|
||||
});
|
||||
const model = window.MessageCache.__DEPRECATED$register(
|
||||
id,
|
||||
new window.Whisper.Message({
|
||||
...message,
|
||||
id,
|
||||
}),
|
||||
window.MessageCache.__DEPRECATED$register(
|
||||
message.id,
|
||||
message,
|
||||
'addPhoneNumberDiscoveryIfNeeded'
|
||||
);
|
||||
|
||||
this.trigger('newmessage', model);
|
||||
this.trigger('newmessage', message);
|
||||
}
|
||||
|
||||
async addVerifiedChange(
|
||||
|
@ -3215,13 +3195,13 @@ export class ConversationModel extends window.Backbone
|
|||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||
forceSave: true,
|
||||
});
|
||||
const model = window.MessageCache.__DEPRECATED$register(
|
||||
window.MessageCache.__DEPRECATED$register(
|
||||
message.id,
|
||||
new window.Whisper.Message(message),
|
||||
message,
|
||||
'addVerifiedChange'
|
||||
);
|
||||
|
||||
this.trigger('newmessage', model);
|
||||
this.trigger('newmessage', message);
|
||||
drop(this.updateUnread());
|
||||
|
||||
const serviceId = this.getServiceId();
|
||||
|
@ -3237,11 +3217,12 @@ export class ConversationModel extends window.Backbone
|
|||
}
|
||||
|
||||
async addProfileChange(
|
||||
profileChange: unknown,
|
||||
profileChange: ProfileNameChangeType,
|
||||
conversationId?: string
|
||||
): Promise<void> {
|
||||
const now = Date.now();
|
||||
const message = {
|
||||
const message: MessageAttributesType = {
|
||||
id: generateGuid(),
|
||||
conversationId: this.id,
|
||||
type: 'profile-change',
|
||||
sent_at: now,
|
||||
|
@ -3249,24 +3230,21 @@ export class ConversationModel extends window.Backbone
|
|||
received_at_ms: now,
|
||||
readStatus: ReadStatus.Read,
|
||||
seenStatus: SeenStatus.NotApplicable,
|
||||
timestamp: now,
|
||||
changedId: conversationId || this.id,
|
||||
profileChange,
|
||||
// TODO: DESKTOP-722
|
||||
} as unknown as MessageAttributesType;
|
||||
};
|
||||
|
||||
const id = await DataWriter.saveMessage(message, {
|
||||
await DataWriter.saveMessage(message, {
|
||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||
});
|
||||
const model = window.MessageCache.__DEPRECATED$register(
|
||||
id,
|
||||
new window.Whisper.Message({
|
||||
...message,
|
||||
id,
|
||||
}),
|
||||
window.MessageCache.__DEPRECATED$register(
|
||||
message.id,
|
||||
message,
|
||||
'addProfileChange'
|
||||
);
|
||||
|
||||
this.trigger('newmessage', model);
|
||||
this.trigger('newmessage', message);
|
||||
|
||||
const serviceId = this.getServiceId();
|
||||
if (isDirectConversation(this.attributes) && serviceId) {
|
||||
|
@ -3287,37 +3265,33 @@ export class ConversationModel extends window.Backbone
|
|||
extra: Partial<MessageAttributesType> = {}
|
||||
): Promise<string> {
|
||||
const now = Date.now();
|
||||
const message: Partial<MessageAttributesType> = {
|
||||
const message: MessageAttributesType = {
|
||||
id: generateGuid(),
|
||||
conversationId: this.id,
|
||||
type,
|
||||
sent_at: now,
|
||||
received_at: incrementMessageCounter(),
|
||||
received_at_ms: now,
|
||||
timestamp: now,
|
||||
|
||||
readStatus: ReadStatus.Read,
|
||||
seenStatus: SeenStatus.NotApplicable,
|
||||
|
||||
...extra,
|
||||
};
|
||||
|
||||
const id = await DataWriter.saveMessage(
|
||||
// TODO: DESKTOP-722
|
||||
await DataWriter.saveMessage(message, {
|
||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||
});
|
||||
window.MessageCache.__DEPRECATED$register(
|
||||
message.id,
|
||||
message as MessageAttributesType,
|
||||
{
|
||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||
}
|
||||
);
|
||||
const model = window.MessageCache.__DEPRECATED$register(
|
||||
id,
|
||||
new window.Whisper.Message({
|
||||
...(message as MessageAttributesType),
|
||||
id,
|
||||
}),
|
||||
'addNotification'
|
||||
);
|
||||
|
||||
this.trigger('newmessage', model);
|
||||
this.trigger('newmessage', message);
|
||||
|
||||
return id;
|
||||
return message.id;
|
||||
}
|
||||
|
||||
async maybeSetPendingUniversalTimer(
|
||||
|
@ -3489,7 +3463,7 @@ export class ConversationModel extends window.Backbone
|
|||
}
|
||||
|
||||
async onReadMessage(
|
||||
message: MessageModel,
|
||||
message: MessageAttributesType,
|
||||
readAt?: number,
|
||||
newestSentAt?: number
|
||||
): Promise<void> {
|
||||
|
@ -3506,8 +3480,8 @@ export class ConversationModel extends window.Backbone
|
|||
// sync. That's a notification explosion we don't need.
|
||||
return this.queueJob('onReadMessage', () =>
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
this.markRead(message.get('received_at')!, {
|
||||
newestSentAt: newestSentAt || message.get('sent_at'),
|
||||
this.markRead(message.received_at!, {
|
||||
newestSentAt: newestSentAt || message.sent_at,
|
||||
sendReadReceipts: false,
|
||||
readAt,
|
||||
})
|
||||
|
@ -3781,7 +3755,7 @@ export class ConversationModel extends window.Backbone
|
|||
now,
|
||||
extraReduxActions,
|
||||
}: {
|
||||
message: MessageModel;
|
||||
message: MessageAttributesType;
|
||||
dontAddMessage: boolean;
|
||||
dontClearDraft: boolean;
|
||||
now: number;
|
||||
|
@ -3802,7 +3776,7 @@ export class ConversationModel extends window.Backbone
|
|||
if (!dontAddMessage) {
|
||||
this.doAddSingleMessage(message, { isJustSent: true });
|
||||
}
|
||||
const notificationData = message.getNotificationData();
|
||||
const notificationData = getNotificationDataForMessage(message);
|
||||
const draftProperties = dontClearDraft
|
||||
? {}
|
||||
: {
|
||||
|
@ -3811,14 +3785,16 @@ export class ConversationModel extends window.Backbone
|
|||
draftBodyRanges: [],
|
||||
draftTimestamp: null,
|
||||
quotedMessageId: undefined,
|
||||
lastMessageAuthor: getMessageAuthorText(message.attributes),
|
||||
lastMessageBodyRanges: message.get('bodyRanges'),
|
||||
lastMessageAuthor: getMessageAuthorText(message),
|
||||
lastMessageBodyRanges: message.bodyRanges,
|
||||
lastMessage:
|
||||
notificationData?.text || message.getNotificationText() || '',
|
||||
notificationData?.text ||
|
||||
getNotificationTextForMessage(message) ||
|
||||
'',
|
||||
lastMessageStatus: 'sending' as const,
|
||||
};
|
||||
|
||||
const isEditMessage = Boolean(message.get('editHistory'));
|
||||
const isEditMessage = Boolean(message.editHistory);
|
||||
|
||||
this.set({
|
||||
...draftProperties,
|
||||
|
@ -3988,17 +3964,16 @@ export class ConversationModel extends window.Backbone
|
|||
storyId,
|
||||
});
|
||||
|
||||
const model = new window.Whisper.Message(attributes);
|
||||
const message = window.MessageCache.__DEPRECATED$register(
|
||||
model.id,
|
||||
model,
|
||||
window.MessageCache.__DEPRECATED$register(
|
||||
attributes.id,
|
||||
attributes,
|
||||
'enqueueMessageForSend'
|
||||
);
|
||||
|
||||
const dbStart = Date.now();
|
||||
|
||||
strictAssert(
|
||||
typeof message.attributes.timestamp === 'number',
|
||||
typeof attributes.timestamp === 'number',
|
||||
'Expected a timestamp'
|
||||
);
|
||||
|
||||
|
@ -4006,14 +3981,14 @@ export class ConversationModel extends window.Backbone
|
|||
{
|
||||
type: conversationQueueJobEnum.enum.NormalMessage,
|
||||
conversationId: this.id,
|
||||
messageId: message.id,
|
||||
messageId: attributes.id,
|
||||
revision: this.get('revision'),
|
||||
},
|
||||
async jobToInsert => {
|
||||
log.info(
|
||||
`enqueueMessageForSend: saving message ${message.id} and job ${jobToInsert.id}`
|
||||
`enqueueMessageForSend: saving message ${attributes.id} and job ${jobToInsert.id}`
|
||||
);
|
||||
await DataWriter.saveMessage(message.attributes, {
|
||||
await DataWriter.saveMessage(attributes, {
|
||||
jobToInsert,
|
||||
forceSave: true,
|
||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||
|
@ -4032,14 +4007,14 @@ export class ConversationModel extends window.Backbone
|
|||
const renderStart = Date.now();
|
||||
|
||||
// Perform asynchronous tasks before entering the batching mode
|
||||
await this.beforeAddSingleMessage(model);
|
||||
await this.beforeAddSingleMessage(attributes);
|
||||
|
||||
if (sticker) {
|
||||
await addStickerPackReference(model.id, sticker.packId);
|
||||
await addStickerPackReference(attributes.id, sticker.packId);
|
||||
}
|
||||
|
||||
this.beforeMessageSend({
|
||||
message: model,
|
||||
message: attributes,
|
||||
dontClearDraft,
|
||||
dontAddMessage: false,
|
||||
now,
|
||||
|
@ -4184,35 +4159,27 @@ export class ConversationModel extends window.Backbone
|
|||
)
|
||||
);
|
||||
|
||||
const { preview, activity } = stats;
|
||||
let previewMessage: MessageModel | undefined;
|
||||
let activityMessage: MessageModel | undefined;
|
||||
let { preview, activity } = stats;
|
||||
|
||||
// Register the message with MessageCache so that if it already exists
|
||||
// Get the in-memory message from MessageCache so that if it already exists
|
||||
// in memory we use that data instead of the data from the db which may
|
||||
// be out of date.
|
||||
if (preview) {
|
||||
previewMessage = window.MessageCache.__DEPRECATED$register(
|
||||
preview.id,
|
||||
preview,
|
||||
'previewMessage'
|
||||
);
|
||||
const inMemory = window.MessageCache.accessAttributes(preview.id);
|
||||
preview = inMemory || preview;
|
||||
}
|
||||
|
||||
if (activity) {
|
||||
activityMessage = window.MessageCache.__DEPRECATED$register(
|
||||
activity.id,
|
||||
activity,
|
||||
'activityMessage'
|
||||
);
|
||||
const inMemory = window.MessageCache.accessAttributes(activity.id);
|
||||
activity = inMemory || activity;
|
||||
}
|
||||
|
||||
if (
|
||||
this.hasDraft() &&
|
||||
this.get('draftTimestamp') &&
|
||||
(!previewMessage ||
|
||||
(!preview ||
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
previewMessage.get('sent_at') < this.get('draftTimestamp')!)
|
||||
preview.sent_at < this.get('draftTimestamp')!)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
@ -4220,38 +4187,37 @@ export class ConversationModel extends window.Backbone
|
|||
let timestamp = this.get('timestamp') || null;
|
||||
let lastMessageReceivedAt = this.get('lastMessageReceivedAt');
|
||||
let lastMessageReceivedAtMs = this.get('lastMessageReceivedAtMs');
|
||||
if (activityMessage) {
|
||||
const callId = activityMessage.get('callId');
|
||||
if (activity) {
|
||||
const { callId } = activity;
|
||||
const callHistory = callId
|
||||
? getCallHistorySelector(window.reduxStore.getState())(callId)
|
||||
: undefined;
|
||||
|
||||
timestamp =
|
||||
callHistory?.timestamp || activityMessage.get('sent_at') || timestamp;
|
||||
lastMessageReceivedAt =
|
||||
activityMessage.get('received_at') || lastMessageReceivedAt;
|
||||
timestamp = callHistory?.timestamp || activity.sent_at || timestamp;
|
||||
lastMessageReceivedAt = activity.received_at || lastMessageReceivedAt;
|
||||
lastMessageReceivedAtMs =
|
||||
activityMessage.get('received_at_ms') || lastMessageReceivedAtMs;
|
||||
activity.received_at_ms || lastMessageReceivedAtMs;
|
||||
}
|
||||
|
||||
const notificationData = previewMessage?.getNotificationData();
|
||||
const notificationData = preview
|
||||
? getNotificationDataForMessage(preview)
|
||||
: undefined;
|
||||
|
||||
this.set({
|
||||
lastMessage:
|
||||
notificationData?.text || previewMessage?.getNotificationText() || '',
|
||||
notificationData?.text ||
|
||||
(preview ? getNotificationTextForMessage(preview) : undefined) ||
|
||||
'',
|
||||
lastMessageBodyRanges: notificationData?.bodyRanges,
|
||||
lastMessagePrefix: notificationData?.emoji,
|
||||
lastMessageAuthor: getMessageAuthorText(previewMessage?.attributes),
|
||||
lastMessageAuthor: getMessageAuthorText(preview),
|
||||
lastMessageStatus:
|
||||
(previewMessage
|
||||
? getMessagePropStatus(previewMessage.attributes, ourConversationId)
|
||||
: null) || null,
|
||||
(preview ? getMessagePropStatus(preview, ourConversationId) : null) ||
|
||||
null,
|
||||
lastMessageReceivedAt,
|
||||
lastMessageReceivedAtMs,
|
||||
timestamp,
|
||||
lastMessageDeletedForEveryone: previewMessage
|
||||
? previewMessage.get('deletedForEveryone')
|
||||
: false,
|
||||
lastMessageDeletedForEveryone: preview?.deletedForEveryone || false,
|
||||
});
|
||||
|
||||
await DataWriter.updateConversation(this.attributes);
|
||||
|
@ -4481,7 +4447,7 @@ export class ConversationModel extends window.Backbone
|
|||
fromSync?: boolean;
|
||||
isInitialSync?: boolean;
|
||||
}
|
||||
): Promise<boolean | null | MessageModel | void> {
|
||||
): Promise<void> {
|
||||
const isSetByOther = providedSource || providedSentAt !== undefined;
|
||||
|
||||
if (isSignalConversation(this.attributes)) {
|
||||
|
@ -4500,7 +4466,7 @@ export class ConversationModel extends window.Backbone
|
|||
createGroupChange: () =>
|
||||
this.updateExpirationTimerInGroupV2(providedExpireTimer),
|
||||
});
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isSetByOther && this.isGroupV1AndDisabled()) {
|
||||
|
@ -4512,7 +4478,7 @@ export class ConversationModel extends window.Backbone
|
|||
let expireTimer: DurationInSeconds | undefined = providedExpireTimer;
|
||||
let source = providedSource;
|
||||
if (this.get('left')) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!expireTimer) {
|
||||
|
@ -4522,7 +4488,7 @@ export class ConversationModel extends window.Backbone
|
|||
this.get('expireTimer') === expireTimer ||
|
||||
(!expireTimer && !this.get('expireTimer'))
|
||||
) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
const logId =
|
||||
|
@ -4599,20 +4565,18 @@ export class ConversationModel extends window.Backbone
|
|||
forceSave: true,
|
||||
});
|
||||
|
||||
const message = window.MessageCache.__DEPRECATED$register(
|
||||
window.MessageCache.__DEPRECATED$register(
|
||||
id,
|
||||
new window.Whisper.Message(attributes),
|
||||
attributes,
|
||||
'updateExpirationTimer'
|
||||
);
|
||||
|
||||
void this.addSingleMessage(message);
|
||||
void this.addSingleMessage(attributes);
|
||||
void this.updateUnread();
|
||||
|
||||
log.info(
|
||||
`${logId}: added a notification received_at=${message.get('received_at')}`
|
||||
`${logId}: added a notification received_at=${attributes.received_at}`
|
||||
);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
isSealedSenderDisabled(): boolean {
|
||||
|
@ -4754,10 +4718,10 @@ export class ConversationModel extends window.Backbone
|
|||
// first/last name in their profile data.
|
||||
const nameChanged = oldName !== newName;
|
||||
if (!isMe(this.attributes) && hadPreviousName && nameChanged) {
|
||||
const change = {
|
||||
const change: ProfileNameChangeType = {
|
||||
type: 'name',
|
||||
oldName,
|
||||
newName,
|
||||
oldName: oldName ?? '',
|
||||
newName: newName ?? '',
|
||||
};
|
||||
|
||||
await this.addProfileChange(change);
|
||||
|
@ -5247,7 +5211,7 @@ export class ConversationModel extends window.Backbone
|
|||
}
|
||||
|
||||
async notify(
|
||||
message: Readonly<MessageModel>,
|
||||
message: Readonly<MessageAttributesType>,
|
||||
reaction?: Readonly<ReactionAttributesType>
|
||||
): Promise<void> {
|
||||
// As a performance optimization don't perform any work if notifications are
|
||||
|
@ -5265,7 +5229,7 @@ export class ConversationModel extends window.Backbone
|
|||
const ourPni = window.textsecure.storage.user.getCheckedPni();
|
||||
const ourServiceIds: Set<ServiceIdString> = new Set([ourAci, ourPni]);
|
||||
|
||||
const mentionsMe = (message.get('bodyRanges') || []).some(bodyRange => {
|
||||
const mentionsMe = (message.bodyRanges || []).some(bodyRange => {
|
||||
if (!BodyRange.isMention(bodyRange)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -5278,7 +5242,7 @@ export class ConversationModel extends window.Backbone
|
|||
}
|
||||
}
|
||||
|
||||
if (!isIncoming(message.attributes) && !reaction) {
|
||||
if (!isIncoming(message) && !reaction) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -5287,7 +5251,7 @@ export class ConversationModel extends window.Backbone
|
|||
|
||||
const sender = reaction
|
||||
? window.ConversationController.get(reaction.fromId)
|
||||
: getAuthor(message.attributes);
|
||||
: getAuthor(message);
|
||||
const senderName = sender
|
||||
? sender.getTitle()
|
||||
: window.i18n('icu:unknownContact');
|
||||
|
@ -5300,20 +5264,17 @@ export class ConversationModel extends window.Backbone
|
|||
|
||||
const { url, absolutePath } = await this.getAvatarOrIdenticon();
|
||||
|
||||
const messageJSON = message.toJSON();
|
||||
const messageId = message.id;
|
||||
const isExpiringMessage = Message.hasExpiration(messageJSON);
|
||||
const isExpiringMessage = hasExpiration(message);
|
||||
|
||||
notificationService.add({
|
||||
senderTitle,
|
||||
conversationId,
|
||||
storyId: isMessageInDirectConversation
|
||||
? undefined
|
||||
: message.get('storyId'),
|
||||
storyId: isMessageInDirectConversation ? undefined : message.storyId,
|
||||
notificationIconUrl: url,
|
||||
notificationIconAbsolutePath: absolutePath,
|
||||
isExpiringMessage,
|
||||
message: message.getNotificationText(),
|
||||
message: getNotificationTextForMessage(message),
|
||||
messageId,
|
||||
reaction: reaction
|
||||
? {
|
||||
|
@ -5322,7 +5283,7 @@ export class ConversationModel extends window.Backbone
|
|||
targetTimestamp: reaction.targetTimestamp,
|
||||
}
|
||||
: undefined,
|
||||
sentAt: message.get('timestamp'),
|
||||
sentAt: message.timestamp,
|
||||
type: reaction ? NotificationType.Reaction : NotificationType.Message,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2126,10 +2126,10 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
return;
|
||||
}
|
||||
|
||||
conversation.trigger('newmessage', this);
|
||||
conversation.trigger('newmessage', this.attributes);
|
||||
|
||||
if (await shouldReplyNotifyUser(this.attributes, conversation)) {
|
||||
await conversation.notify(this);
|
||||
await conversation.notify(this.attributes);
|
||||
}
|
||||
|
||||
// Increment the sent message count if this is an outgoing message
|
||||
|
@ -2306,16 +2306,18 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
timestamp: reaction.timestamp,
|
||||
});
|
||||
|
||||
const messageToAdd = window.MessageCache.__DEPRECATED$register(
|
||||
window.MessageCache.__DEPRECATED$register(
|
||||
generatedMessage.id,
|
||||
generatedMessage,
|
||||
'generatedMessage'
|
||||
);
|
||||
if (isDirectConversation(targetConversation.attributes)) {
|
||||
await targetConversation.addSingleMessage(messageToAdd);
|
||||
await targetConversation.addSingleMessage(
|
||||
generatedMessage.attributes
|
||||
);
|
||||
if (!targetConversation.get('active_at')) {
|
||||
targetConversation.set({
|
||||
active_at: messageToAdd.get('timestamp'),
|
||||
active_at: generatedMessage.attributes.timestamp,
|
||||
});
|
||||
await DataWriter.updateConversation(targetConversation.attributes);
|
||||
}
|
||||
|
@ -2328,11 +2330,11 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
);
|
||||
if (
|
||||
await shouldReplyNotifyUser(
|
||||
messageToAdd.attributes,
|
||||
generatedMessage.attributes,
|
||||
targetConversation
|
||||
)
|
||||
) {
|
||||
drop(targetConversation.notify(messageToAdd));
|
||||
drop(targetConversation.notify(generatedMessage.attributes));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2403,7 +2405,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
this.set({ reactions });
|
||||
|
||||
if (isOutgoing(this.attributes) && isFromSomeoneElse) {
|
||||
void conversation.notify(this, reaction);
|
||||
void conversation.notify(this.attributes, reaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2465,14 +2467,14 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
forceSave: true,
|
||||
});
|
||||
|
||||
void conversation.addSingleMessage(
|
||||
window.MessageCache.__DEPRECATED$register(
|
||||
generatedMessage.id,
|
||||
generatedMessage,
|
||||
'generatedMessage2'
|
||||
)
|
||||
window.MessageCache.__DEPRECATED$register(
|
||||
generatedMessage.id,
|
||||
generatedMessage,
|
||||
'generatedMessage2'
|
||||
);
|
||||
|
||||
void conversation.addSingleMessage(generatedMessage.attributes);
|
||||
|
||||
jobData = {
|
||||
type: conversationQueueJobEnum.enum.NormalMessage,
|
||||
conversationId: conversation.id,
|
||||
|
|
|
@ -13,11 +13,9 @@ export function getMentionsRegex(): RegExp {
|
|||
}
|
||||
|
||||
export type Message = (
|
||||
| UserMessage
|
||||
| VerifiedChangeMessage
|
||||
| ProfileChangeNotificationMessage
|
||||
) & { deletedForEveryone?: boolean };
|
||||
export type UserMessage = IncomingMessage | OutgoingMessage;
|
||||
|
||||
export type IncomingMessage = Readonly<
|
||||
{
|
||||
|
@ -109,16 +107,3 @@ export type MessageSchemaVersion6 = Partial<
|
|||
contact: Array<EmbeddedContactType>;
|
||||
}>
|
||||
>;
|
||||
|
||||
export const isUserMessage = (message: Message): message is UserMessage =>
|
||||
message.type === 'incoming' || message.type === 'outgoing';
|
||||
|
||||
export const hasExpiration = (message: Message): boolean => {
|
||||
if (!isUserMessage(message)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const { expireTimer } = message;
|
||||
|
||||
return typeof expireTimer === 'number' && expireTimer > 0;
|
||||
};
|
||||
|
|
|
@ -46,8 +46,6 @@ import {
|
|||
import { encryptLegacyAttachment } from '../util/encryptLegacyAttachment';
|
||||
import { deepClone } from '../util/deepClone';
|
||||
|
||||
export { hasExpiration } from './Message';
|
||||
|
||||
export const GROUP = 'group';
|
||||
export const PRIVATE = 'private';
|
||||
|
||||
|
@ -1039,3 +1037,16 @@ async function deletePreviews(
|
|||
})
|
||||
);
|
||||
}
|
||||
|
||||
export const isUserMessage = (message: MessageAttributesType): boolean =>
|
||||
message.type === 'incoming' || message.type === 'outgoing';
|
||||
|
||||
export const hasExpiration = (message: MessageAttributesType): boolean => {
|
||||
if (!isUserMessage(message)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const { expireTimer } = message;
|
||||
|
||||
return typeof expireTimer === 'number' && expireTimer > 0;
|
||||
};
|
||||
|
|
|
@ -1153,19 +1153,16 @@ async function saveCallHistory({
|
|||
callId: callHistory.callId,
|
||||
};
|
||||
|
||||
const id = await DataWriter.saveMessage(message, {
|
||||
message.id = await DataWriter.saveMessage(message, {
|
||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||
// We don't want to force save if we're updating an existing message
|
||||
forceSave: prevMessage == null,
|
||||
});
|
||||
log.info('saveCallHistory: Saved call history message:', id);
|
||||
log.info('saveCallHistory: Saved call history message:', message.id);
|
||||
|
||||
const model = window.MessageCache.__DEPRECATED$register(
|
||||
id,
|
||||
new window.Whisper.Message({
|
||||
...message,
|
||||
id,
|
||||
}),
|
||||
window.MessageCache.__DEPRECATED$register(
|
||||
message.id,
|
||||
message,
|
||||
'callDisposition'
|
||||
);
|
||||
|
||||
|
@ -1175,7 +1172,7 @@ async function saveCallHistory({
|
|||
} else {
|
||||
conversation.incrementMessageCount();
|
||||
}
|
||||
conversation.trigger('newmessage', model);
|
||||
conversation.trigger('newmessage', message);
|
||||
}
|
||||
|
||||
await conversation.updateLastMessage().catch(error => {
|
||||
|
|
|
@ -50,17 +50,20 @@ export function getTargetOfThisEditTimestamp({
|
|||
return originalTimestamp;
|
||||
}
|
||||
|
||||
export function getPropForTimestamp<T extends keyof EditHistoryType>({
|
||||
export function getPropForTimestamp<
|
||||
Attrs extends ReadonlyMessageAttributesType,
|
||||
T extends keyof EditHistoryType,
|
||||
>({
|
||||
log,
|
||||
message,
|
||||
prop,
|
||||
targetTimestamp,
|
||||
}: {
|
||||
log: LoggerType;
|
||||
message: MessageAttributesType;
|
||||
message: Attrs;
|
||||
prop: T;
|
||||
targetTimestamp: number;
|
||||
}): EditHistoryType[T] {
|
||||
}): Attrs[T] {
|
||||
const logId = `getPropForTimestamp(${targetTimestamp}})`;
|
||||
|
||||
const { editHistory } = message;
|
||||
|
@ -74,7 +77,7 @@ export function getPropForTimestamp<T extends keyof EditHistoryType>({
|
|||
return message[prop];
|
||||
}
|
||||
|
||||
return targetEdit[prop];
|
||||
return targetEdit[prop] as Attrs[T];
|
||||
}
|
||||
|
||||
export function getChangesForPropAtTimestamp<T extends keyof EditHistoryType>({
|
||||
|
|
|
@ -19,7 +19,7 @@ export async function hydrateStoryContext(
|
|||
shouldSave?: boolean;
|
||||
isStoryErased?: boolean;
|
||||
} = {}
|
||||
): Promise<void> {
|
||||
): Promise<Partial<MessageAttributesType> | undefined> {
|
||||
let messageAttributes: MessageAttributesType;
|
||||
try {
|
||||
messageAttributes = await window.MessageCache.resolveAttributes(
|
||||
|
@ -27,12 +27,12 @@ export async function hydrateStoryContext(
|
|||
messageId
|
||||
);
|
||||
} catch {
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const { storyId } = messageAttributes;
|
||||
if (!storyId) {
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const { storyReplyContext: context } = messageAttributes;
|
||||
|
@ -42,7 +42,7 @@ export async function hydrateStoryContext(
|
|||
context &&
|
||||
(context.attachment?.url || !context.messageId)
|
||||
) {
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let storyMessage: MessageAttributesType | undefined;
|
||||
|
@ -88,7 +88,7 @@ export async function hydrateStoryContext(
|
|||
});
|
||||
}
|
||||
|
||||
return;
|
||||
return newMessageAttributes;
|
||||
}
|
||||
|
||||
const attachments = getAttachmentsForMessage({ ...storyMessage });
|
||||
|
@ -119,4 +119,5 @@ export async function hydrateStoryContext(
|
|||
skipSaveToDatabase: true,
|
||||
});
|
||||
}
|
||||
return newMessageAttributes;
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ export async function modifyTargetMessage(
|
|||
}
|
||||
|
||||
if (type === 'outgoing' || (type === 'story' && ourAci === sourceServiceId)) {
|
||||
const receipts = await MessageReceipts.forMessage(message);
|
||||
const receipts = await MessageReceipts.forMessage(message.attributes);
|
||||
const sendActions = receipts.map(({ receiptSync }) => {
|
||||
let sendActionType: SendActionType;
|
||||
const receiptType = receiptSync.type;
|
||||
|
@ -164,10 +164,10 @@ export async function modifyTargetMessage(
|
|||
if (type === 'incoming') {
|
||||
// In a followup (see DESKTOP-2100), we want to make `ReadSyncs#forMessage` return
|
||||
// an array, not an object. This array wrapping makes that future a bit easier.
|
||||
const maybeSingleReadSync = await ReadSyncs.forMessage(message);
|
||||
const maybeSingleReadSync = await ReadSyncs.forMessage(message.attributes);
|
||||
const readSyncs = maybeSingleReadSync ? [maybeSingleReadSync] : [];
|
||||
|
||||
const viewSyncs = await ViewSyncs.forMessage(message);
|
||||
const viewSyncs = await ViewSyncs.forMessage(message.attributes);
|
||||
|
||||
const isGroupStoryReply =
|
||||
isGroup(conversation.attributes) && message.get('storyId');
|
||||
|
@ -233,13 +233,13 @@ export async function modifyTargetMessage(
|
|||
drop(
|
||||
message
|
||||
.getConversation()
|
||||
?.onReadMessage(message, markReadAt, newestSentAt)
|
||||
?.onReadMessage(message.attributes, markReadAt, newestSentAt)
|
||||
);
|
||||
}
|
||||
|
||||
// Check for out-of-order view once open syncs
|
||||
if (isTapToView(message.attributes)) {
|
||||
const viewOnceOpenSync = ViewOnceOpenSyncs.forMessage(message);
|
||||
const viewOnceOpenSync = ViewOnceOpenSyncs.forMessage(message.attributes);
|
||||
if (viewOnceOpenSync) {
|
||||
await message.markViewOnceMessageViewed({ fromSync: true });
|
||||
changed = true;
|
||||
|
@ -248,7 +248,7 @@ export async function modifyTargetMessage(
|
|||
}
|
||||
|
||||
if (isStory(message.attributes)) {
|
||||
const viewSyncs = await ViewSyncs.forMessage(message);
|
||||
const viewSyncs = await ViewSyncs.forMessage(message.attributes);
|
||||
|
||||
if (viewSyncs.length !== 0) {
|
||||
message.set({
|
||||
|
@ -277,7 +277,7 @@ export async function modifyTargetMessage(
|
|||
}
|
||||
|
||||
// Does message message have any pending, previously-received associated reactions?
|
||||
const reactions = Reactions.findReactionsForMessage(message);
|
||||
const reactions = Reactions.findReactionsForMessage(message.attributes);
|
||||
|
||||
log.info(
|
||||
`${logId}: Found ${reactions.length} early reaction(s) for ${message.attributes.type} message`
|
||||
|
|
|
@ -239,7 +239,7 @@ export async function sendEditedMessage(
|
|||
SEND_REPORT_THRESHOLD_MS,
|
||||
async () => {
|
||||
conversation.beforeMessageSend({
|
||||
message: targetMessage,
|
||||
message: targetMessage.attributes,
|
||||
dontClearDraft: false,
|
||||
dontAddMessage: true,
|
||||
now: timestamp,
|
||||
|
|
|
@ -307,20 +307,17 @@ export async function sendStoryMessage(
|
|||
// * Save the message model
|
||||
// * Add the message to the conversation
|
||||
await Promise.all(
|
||||
distributionListMessages.map(messageAttributes => {
|
||||
const model = new window.Whisper.Message(messageAttributes);
|
||||
const message = window.MessageCache.__DEPRECATED$register(
|
||||
model.id,
|
||||
model,
|
||||
distributionListMessages.map(message => {
|
||||
window.MessageCache.__DEPRECATED$register(
|
||||
message.id,
|
||||
new window.Whisper.Message(message),
|
||||
'sendStoryMessage'
|
||||
);
|
||||
|
||||
void ourConversation.addSingleMessage(model, { isJustSent: true });
|
||||
void ourConversation.addSingleMessage(message, { isJustSent: true });
|
||||
|
||||
log.info(
|
||||
`stories.sendStoryMessage: saving message ${messageAttributes.timestamp}`
|
||||
);
|
||||
return DataWriter.saveMessage(message.attributes, {
|
||||
log.info(`stories.sendStoryMessage: saving message ${message.timestamp}`);
|
||||
return DataWriter.saveMessage(message, {
|
||||
forceSave: true,
|
||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||
});
|
||||
|
@ -362,20 +359,21 @@ export async function sendStoryMessage(
|
|||
timestamp: messageAttributes.timestamp,
|
||||
},
|
||||
async jobToInsert => {
|
||||
const model = new window.Whisper.Message(messageAttributes);
|
||||
const message = window.MessageCache.__DEPRECATED$register(
|
||||
model.id,
|
||||
model,
|
||||
window.MessageCache.__DEPRECATED$register(
|
||||
messageAttributes.id,
|
||||
new window.Whisper.Message(messageAttributes),
|
||||
'sendStoryMessage'
|
||||
);
|
||||
|
||||
const conversation = message.getConversation();
|
||||
void conversation?.addSingleMessage(model, { isJustSent: true });
|
||||
const conversation =
|
||||
window.ConversationController.get(conversationId);
|
||||
void conversation?.addSingleMessage(messageAttributes, {
|
||||
isJustSent: true,
|
||||
});
|
||||
|
||||
log.info(
|
||||
`stories.sendStoryMessage: saving message ${messageAttributes.timestamp}`
|
||||
);
|
||||
await DataWriter.saveMessage(message.attributes, {
|
||||
await DataWriter.saveMessage(messageAttributes, {
|
||||
forceSave: true,
|
||||
jobToInsert,
|
||||
ourAci: window.textsecure.storage.user.getCheckedAci(),
|
||||
|
|
Loading…
Reference in a new issue