Remove isPrivate, isMe, isGroupV1, isGroupV2 from model
This commit is contained in:
parent
eaf4036fc8
commit
d4875fd8f4
16 changed files with 377 additions and 267 deletions
|
@ -13,6 +13,10 @@ import { SendOptionsType, CallbackResultType } from './textsecure/SendMessage';
|
|||
import { ConversationModel } from './models/conversations';
|
||||
import { maybeDeriveGroupV2Id } from './groups';
|
||||
import { assert } from './util/assert';
|
||||
import { isGroupV1, isGroupV2 } from './util/whatTypeOfConversation';
|
||||
import { deprecated } from './util/deprecated';
|
||||
import { getSendOptions } from './util/getSendOptions';
|
||||
import { handleMessageSend } from './util/handleMessageSend';
|
||||
|
||||
const MAX_MESSAGE_BODY_LENGTH = 64 * 1024;
|
||||
|
||||
|
@ -237,7 +241,7 @@ export class ConversationController {
|
|||
}
|
||||
|
||||
try {
|
||||
if (conversation.isGroupV1()) {
|
||||
if (isGroupV1(conversation.attributes)) {
|
||||
await maybeDeriveGroupV2Id(conversation);
|
||||
}
|
||||
await saveConversation(conversation.attributes);
|
||||
|
@ -556,7 +560,7 @@ export class ConversationController {
|
|||
}
|
||||
|
||||
let groupV2Id: undefined | string;
|
||||
if (conversation.isGroupV1()) {
|
||||
if (isGroupV1(conversation.attributes)) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await maybeDeriveGroupV2Id(conversation);
|
||||
groupV2Id = conversation.get('derivedGroupV2Id');
|
||||
|
@ -564,7 +568,7 @@ export class ConversationController {
|
|||
groupV2Id,
|
||||
'checkForConflicts: expected the group V2 ID to have been derived, but it was falsy'
|
||||
);
|
||||
} else if (conversation.isGroupV2()) {
|
||||
} else if (isGroupV2(conversation.attributes)) {
|
||||
groupV2Id = conversation.get('groupId');
|
||||
}
|
||||
|
||||
|
@ -573,7 +577,7 @@ export class ConversationController {
|
|||
if (!existing) {
|
||||
byGroupV2Id[groupV2Id] = conversation;
|
||||
} else {
|
||||
const logParenthetical = conversation.isGroupV1()
|
||||
const logParenthetical = isGroupV1(conversation.attributes)
|
||||
? ' (derived from a GV1 group ID)'
|
||||
: '';
|
||||
window.log.warn(
|
||||
|
@ -581,7 +585,10 @@ export class ConversationController {
|
|||
);
|
||||
|
||||
// Prefer the GV2 group.
|
||||
if (conversation.isGroupV2() && !existing.isGroupV2()) {
|
||||
if (
|
||||
isGroupV2(conversation.attributes) &&
|
||||
!isGroupV2(existing.attributes)
|
||||
) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await this.combineConversations(conversation, existing);
|
||||
byGroupV2Id[groupV2Id] = conversation;
|
||||
|
@ -730,16 +737,14 @@ export class ConversationController {
|
|||
) => Promise<CallbackResultType | void | null>;
|
||||
sendOptions: SendOptionsType | undefined;
|
||||
}> {
|
||||
deprecated('prepareForSend');
|
||||
// id is any valid conversation identifier
|
||||
const conversation = this.get(id);
|
||||
const sendOptions = conversation
|
||||
? await conversation.getSendOptions(options)
|
||||
? await getSendOptions(conversation.attributes, options)
|
||||
: undefined;
|
||||
const wrap = conversation
|
||||
? conversation.wrapSend.bind(conversation)
|
||||
: async (promise: Promise<CallbackResultType | void | null>) => promise;
|
||||
|
||||
return { wrap, sendOptions };
|
||||
return { wrap: handleMessageSend, sendOptions };
|
||||
}
|
||||
|
||||
async getAllGroupsInvolvingId(
|
||||
|
|
|
@ -43,6 +43,7 @@ import {
|
|||
UnprocessedType,
|
||||
UnprocessedUpdateType,
|
||||
} from './textsecure/Types.d';
|
||||
import { getSendOptions } from './util/getSendOptions';
|
||||
|
||||
const TIMESTAMP_THRESHOLD = 5 * 1000; // 5 seconds
|
||||
|
||||
|
@ -1230,7 +1231,7 @@ export class SignalProtocolStore extends EventsMixin {
|
|||
await this.archiveSession(id);
|
||||
|
||||
// Send a null message with newly-created session
|
||||
const sendOptions = await conversation.getSendOptions();
|
||||
const sendOptions = await getSendOptions(conversation.attributes);
|
||||
await window.textsecure.messaging.sendNullMessage({ uuid }, sendOptions);
|
||||
} catch (error) {
|
||||
// If we failed to do the session reset, then we'll allow another attempt sooner
|
||||
|
|
|
@ -35,6 +35,8 @@ import {
|
|||
} from './textsecure/MessageReceiver';
|
||||
import { connectToServerWithStoredCredentials } from './util/connectToServerWithStoredCredentials';
|
||||
import * as universalExpireTimer from './util/universalExpireTimer';
|
||||
import { isDirectConversation, isGroupV2 } from './util/whatTypeOfConversation';
|
||||
import { getSendOptions } from './util/getSendOptions';
|
||||
|
||||
const MAX_ATTACHMENT_DOWNLOAD_AGE = 3600 * 72 * 1000;
|
||||
|
||||
|
@ -1955,7 +1957,7 @@ export async function startApp(): Promise<void> {
|
|||
.getConversations()
|
||||
.filter(c =>
|
||||
Boolean(
|
||||
c.isPrivate() &&
|
||||
isDirectConversation(c.attributes) &&
|
||||
c.get('e164') &&
|
||||
!c.get('uuid') &&
|
||||
!c.isEverUnregistered()
|
||||
|
@ -2502,7 +2504,10 @@ export async function startApp(): Promise<void> {
|
|||
}
|
||||
|
||||
// We drop typing notifications in groups we're not a part of
|
||||
if (!conversation.isPrivate() && !conversation.hasMember(ourId)) {
|
||||
if (
|
||||
!isDirectConversation(conversation.attributes) &&
|
||||
!conversation.hasMember(ourId)
|
||||
) {
|
||||
window.log.warn(
|
||||
`Received typing indicator for group ${conversation.idForLogging()}, which we're not a part of. Dropping.`
|
||||
);
|
||||
|
@ -2703,7 +2708,7 @@ export async function startApp(): Promise<void> {
|
|||
id,
|
||||
'group'
|
||||
);
|
||||
if (conversation.isGroupV2()) {
|
||||
if (isGroupV2(conversation.attributes)) {
|
||||
window.log.warn(
|
||||
'Got group sync for v2 group: ',
|
||||
conversation.idForLogging()
|
||||
|
@ -3578,7 +3583,7 @@ export async function startApp(): Promise<void> {
|
|||
);
|
||||
|
||||
const plaintext = PlaintextContent.from(message);
|
||||
const options = await conversation.getSendOptions();
|
||||
const options = await getSendOptions(conversation.attributes);
|
||||
const result = await window.textsecure.messaging.sendRetryRequest({
|
||||
plaintext,
|
||||
options,
|
||||
|
|
33
ts/groups.ts
33
ts/groups.ts
|
@ -79,6 +79,13 @@ import { CURRENT_SCHEMA_VERSION as MAX_MESSAGE_SCHEMA } from '../js/modules/type
|
|||
import { ConversationModel } from './models/conversations';
|
||||
import { getGroupSizeHardLimit } from './groups/limits';
|
||||
import { ourProfileKeyService } from './services/ourProfileKey';
|
||||
import {
|
||||
isGroupV1 as getIsGroupV1,
|
||||
isGroupV2 as getIsGroupV2,
|
||||
isMe,
|
||||
} from './util/whatTypeOfConversation';
|
||||
import { handleMessageSend } from './util/handleMessageSend';
|
||||
import { getSendOptions } from './util/getSendOptions';
|
||||
|
||||
export { joinViaLink } from './groups/joinViaLink';
|
||||
|
||||
|
@ -1231,7 +1238,7 @@ export async function modifyGroupV2({
|
|||
}): Promise<void> {
|
||||
const idLog = `${name}/${conversation.idForLogging()}`;
|
||||
|
||||
if (!conversation.isGroupV2()) {
|
||||
if (!getIsGroupV2(conversation.attributes)) {
|
||||
throw new Error(
|
||||
`modifyGroupV2/${idLog}: Called for non-GroupV2 conversation`
|
||||
);
|
||||
|
@ -1297,13 +1304,13 @@ export async function modifyGroupV2({
|
|||
? await ourProfileKeyService.get()
|
||||
: undefined;
|
||||
|
||||
const sendOptions = await conversation.getSendOptions();
|
||||
const sendOptions = await getSendOptions(conversation.attributes);
|
||||
const timestamp = Date.now();
|
||||
const {
|
||||
ContentHint,
|
||||
} = window.textsecure.protobuf.UnidentifiedSenderMessage.Message;
|
||||
|
||||
const promise = conversation.wrapSend(
|
||||
const promise = handleMessageSend(
|
||||
window.Signal.Util.sendToGroup(
|
||||
{
|
||||
groupV2: conversation.getGroupV2Info({
|
||||
|
@ -1676,7 +1683,7 @@ export async function createGroupV2({
|
|||
const {
|
||||
ContentHint,
|
||||
} = window.textsecure.protobuf.UnidentifiedSenderMessage.Message;
|
||||
const sendOptions = await conversation.getSendOptions();
|
||||
const sendOptions = await getSendOptions(conversation.attributes);
|
||||
|
||||
await wrapWithSyncMessageSend({
|
||||
conversation,
|
||||
|
@ -1729,7 +1736,7 @@ export async function hasV1GroupBeenMigrated(
|
|||
conversation: ConversationModel
|
||||
): Promise<boolean> {
|
||||
const logId = conversation.idForLogging();
|
||||
const isGroupV1 = conversation.isGroupV1();
|
||||
const isGroupV1 = getIsGroupV1(conversation.attributes);
|
||||
if (!isGroupV1) {
|
||||
window.log.warn(
|
||||
`checkForGV2Existence/${logId}: Called for non-GroupV1 conversation!`
|
||||
|
@ -1766,7 +1773,7 @@ export async function hasV1GroupBeenMigrated(
|
|||
export async function maybeDeriveGroupV2Id(
|
||||
conversation: ConversationModel
|
||||
): Promise<boolean> {
|
||||
const isGroupV1 = conversation.isGroupV1();
|
||||
const isGroupV1 = getIsGroupV1(conversation.attributes);
|
||||
const groupV1Id = conversation.get('groupId');
|
||||
const derived = conversation.get('derivedGroupV2Id');
|
||||
|
||||
|
@ -1797,7 +1804,7 @@ type MigratePropsType = {
|
|||
export async function isGroupEligibleToMigrate(
|
||||
conversation: ConversationModel
|
||||
): Promise<boolean> {
|
||||
if (!conversation.isGroupV1()) {
|
||||
if (!getIsGroupV1(conversation.attributes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1860,7 +1867,7 @@ export async function getGroupMigrationMembers(
|
|||
`getGroupMigrationMembers/${logId}: membersV2 - missing local contact for ${e164}, skipping.`
|
||||
);
|
||||
}
|
||||
if (!contact.isMe() && window.GV2_MIGRATION_DISABLE_ADD) {
|
||||
if (!isMe(contact.attributes) && window.GV2_MIGRATION_DISABLE_ADD) {
|
||||
window.log.warn(
|
||||
`getGroupMigrationMembers/${logId}: membersV2 - skipping ${e164} due to GV2_MIGRATION_DISABLE_ADD flag`
|
||||
);
|
||||
|
@ -1947,7 +1954,7 @@ export async function getGroupMigrationMembers(
|
|||
return null;
|
||||
}
|
||||
|
||||
if (!contact.isMe() && window.GV2_MIGRATION_DISABLE_INVITE) {
|
||||
if (!isMe(contact.attributes) && window.GV2_MIGRATION_DISABLE_INVITE) {
|
||||
window.log.warn(
|
||||
`getGroupMigrationMembers/${logId}: pendingMembersV2 - skipping ${e164} due to GV2_MIGRATION_DISABLE_INVITE flag`
|
||||
);
|
||||
|
@ -2173,7 +2180,7 @@ export async function initiateMigrationToGroupV2(
|
|||
});
|
||||
} catch (error) {
|
||||
const logId = conversation.idForLogging();
|
||||
if (!conversation.isGroupV1()) {
|
||||
if (!getIsGroupV1(conversation.attributes)) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
|
@ -2203,7 +2210,7 @@ export async function initiateMigrationToGroupV2(
|
|||
const {
|
||||
ContentHint,
|
||||
} = window.textsecure.protobuf.UnidentifiedSenderMessage.Message;
|
||||
const sendOptions = await conversation.getSendOptions();
|
||||
const sendOptions = await getSendOptions(conversation.attributes);
|
||||
|
||||
await wrapWithSyncMessageSend({
|
||||
conversation,
|
||||
|
@ -2361,7 +2368,7 @@ export async function joinGroupV2ViaLinkAndMigrate({
|
|||
inviteLinkPassword: string;
|
||||
revision: number;
|
||||
}): Promise<void> {
|
||||
const isGroupV1 = conversation.isGroupV1();
|
||||
const isGroupV1 = getIsGroupV1(conversation.attributes);
|
||||
const previousGroupV1Id = conversation.get('groupId');
|
||||
|
||||
if (!isGroupV1 || !previousGroupV1Id) {
|
||||
|
@ -2451,7 +2458,7 @@ export async function respondToGroupV2Migration({
|
|||
// Ensure we have the credentials we need before attempting GroupsV2 operations
|
||||
await maybeFetchNewCredentials();
|
||||
|
||||
const isGroupV1 = conversation.isGroupV1();
|
||||
const isGroupV1 = getIsGroupV1(conversation.attributes);
|
||||
const previousGroupV1Id = conversation.get('groupId');
|
||||
|
||||
if (!isGroupV1 || !previousGroupV1Id) {
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
} from '../groups';
|
||||
import { arrayBufferToBase64, base64ToArrayBuffer } from '../Crypto';
|
||||
import { longRunningTaskWrapper } from '../util/longRunningTaskWrapper';
|
||||
import { isGroupV1 } from '../util/whatTypeOfConversation';
|
||||
|
||||
import type { GroupJoinInfoClass } from '../textsecure.d';
|
||||
import type { ConversationAttributesType } from '../model-types.d';
|
||||
|
@ -285,7 +286,7 @@ export async function joinViaLink(hash: string): Promise<void> {
|
|||
);
|
||||
}
|
||||
|
||||
if (targetConversation.isGroupV1()) {
|
||||
if (isGroupV1(targetConversation.attributes)) {
|
||||
await targetConversation.joinGroupV2ViaLinkAndMigrate({
|
||||
approvalRequired,
|
||||
inviteLinkPassword,
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -57,6 +57,14 @@ import { MIMEType } from '../types/MIME';
|
|||
import { LinkPreviewType } from '../types/message/LinkPreviews';
|
||||
import { ourProfileKeyService } from '../services/ourProfileKey';
|
||||
import { markRead, setToExpire } from '../services/MessageUpdater';
|
||||
import {
|
||||
isDirectConversation,
|
||||
isGroupV1,
|
||||
isGroupV2,
|
||||
isMe,
|
||||
} from '../util/whatTypeOfConversation';
|
||||
import { handleMessageSend } from '../util/handleMessageSend';
|
||||
import { getSendOptions } from '../util/getSendOptions';
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
/* eslint-disable more/no-then */
|
||||
|
@ -744,7 +752,9 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
|
||||
getPropsForSafetyNumberNotification(): SafetyNumberNotificationProps {
|
||||
const conversation = this.getConversation();
|
||||
const isGroup = Boolean(conversation && !conversation.isPrivate());
|
||||
const isGroup = Boolean(
|
||||
conversation && !isDirectConversation(conversation.attributes)
|
||||
);
|
||||
const identifier = this.get('key_changed');
|
||||
const contact = this.findAndFormatContact(identifier);
|
||||
|
||||
|
@ -981,7 +991,8 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
: undefined;
|
||||
|
||||
const conversation = this.getConversation();
|
||||
const isGroup = conversation && !conversation.isPrivate();
|
||||
const isGroup =
|
||||
conversation && !isDirectConversation(conversation.attributes);
|
||||
const sticker = this.get('sticker');
|
||||
|
||||
const isTapToView = this.isTapToView();
|
||||
|
@ -1316,7 +1327,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
let authorTitle: string;
|
||||
let isFromMe: boolean;
|
||||
|
||||
if (contact && contact.isPrivate()) {
|
||||
if (contact && isDirectConversation(contact.attributes)) {
|
||||
const contactPhoneNumber = contact.get('e164');
|
||||
|
||||
authorId = contact.id;
|
||||
|
@ -1328,7 +1339,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
: undefined;
|
||||
authorProfileName = contact.getProfileName();
|
||||
authorTitle = contact.getTitle();
|
||||
isFromMe = contact.isMe();
|
||||
isFromMe = isMe(contact.attributes);
|
||||
} else {
|
||||
window.log.warn(
|
||||
'getPropsForQuote: contact was missing. This may indicate a bookkeeping error or bad data from another client. Returning a placeholder contact.'
|
||||
|
@ -1529,7 +1540,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
return { text: '' };
|
||||
}
|
||||
|
||||
if (fromContact.isMe()) {
|
||||
if (isMe(fromContact.attributes)) {
|
||||
messages.push(window.i18n('youUpdatedTheGroup'));
|
||||
} else {
|
||||
messages.push(window.i18n('updatedTheGroup', [fromContact.getTitle()]));
|
||||
|
@ -1540,7 +1551,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
window.ConversationController.getOrCreate(item, 'private')
|
||||
);
|
||||
const joinedWithoutMe = joinedContacts.filter(
|
||||
contact => !contact.isMe()
|
||||
contact => !isMe(contact.attributes)
|
||||
);
|
||||
|
||||
if (joinedContacts.length > 1) {
|
||||
|
@ -1558,7 +1569,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
groupUpdate.joined[0],
|
||||
'private'
|
||||
);
|
||||
if (joinedContact.isMe()) {
|
||||
if (isMe(joinedContact.attributes)) {
|
||||
messages.push(window.i18n('youJoinedTheGroup'));
|
||||
} else {
|
||||
messages.push(
|
||||
|
@ -2282,13 +2293,13 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
}
|
||||
|
||||
let promise;
|
||||
const options = await conversation.getSendOptions();
|
||||
const options = await getSendOptions(conversation.attributes);
|
||||
|
||||
const {
|
||||
ContentHint,
|
||||
} = window.textsecure.protobuf.UnidentifiedSenderMessage.Message;
|
||||
|
||||
if (conversation.isPrivate()) {
|
||||
if (isDirectConversation(conversation.attributes)) {
|
||||
const [identifier] = recipients;
|
||||
promise = window.textsecure.messaging.sendMessageToIdentifier(
|
||||
identifier,
|
||||
|
@ -2351,7 +2362,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
);
|
||||
}
|
||||
|
||||
return this.send(conversation.wrapSend(promise));
|
||||
return this.send(handleMessageSend(promise));
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
|
@ -2534,7 +2545,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
sendOptions,
|
||||
} = await window.ConversationController.prepareForSend(identifier);
|
||||
const group =
|
||||
groupId && parentConversation?.isGroupV1()
|
||||
groupId && isGroupV1(parentConversation?.attributes)
|
||||
? {
|
||||
id: groupId,
|
||||
type: window.textsecure.protobuf.GroupContext.Type.DELIVER,
|
||||
|
@ -2576,7 +2587,9 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
[identifier],
|
||||
contentMessage,
|
||||
ContentHint.RESENDABLE,
|
||||
groupId && parentConversation?.isGroupV2() ? groupId : undefined,
|
||||
groupId && isGroupV2(parentConversation?.attributes)
|
||||
? groupId
|
||||
: undefined,
|
||||
sendOptions
|
||||
);
|
||||
|
||||
|
@ -2767,7 +2780,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
retryOptions: options,
|
||||
});
|
||||
|
||||
const sendOptions = await conv.getSendOptions();
|
||||
const sendOptions = await getSendOptions(conv.attributes);
|
||||
|
||||
// We don't have to check `sent_to` here, because:
|
||||
//
|
||||
|
@ -2776,11 +2789,11 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
// in a single request to the server. So partial success is not
|
||||
// possible.
|
||||
await this.send(
|
||||
conv.wrapSend(
|
||||
handleMessageSend(
|
||||
// TODO: DESKTOP-724
|
||||
// resetSession returns `Array<void>` which is incompatible with the
|
||||
// expected promise return values. `[]` is truthy and wrapSend assumes
|
||||
// it's a valid callback result type
|
||||
// expected promise return values. `[]` is truthy and handleMessageSend
|
||||
// assumes it's a valid callback result type
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
window.textsecure.messaging.resetSession(
|
||||
|
@ -3601,7 +3614,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
// GroupV2
|
||||
|
||||
if (initialMessage.groupV2) {
|
||||
if (conversation.isGroupV1()) {
|
||||
if (isGroupV1(conversation.attributes)) {
|
||||
// If we received a GroupV2 message in a GroupV1 group, we migrate!
|
||||
|
||||
const { revision, groupChange } = initialMessage.groupV2;
|
||||
|
@ -3660,7 +3673,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
e164: source,
|
||||
uuid: sourceUuid,
|
||||
})!;
|
||||
const isGroupV2 = Boolean(initialMessage.groupV2);
|
||||
const hasGroupV2Prop = Boolean(initialMessage.groupV2);
|
||||
const isV1GroupUpdate =
|
||||
initialMessage.group &&
|
||||
initialMessage.group.type !==
|
||||
|
@ -3670,8 +3683,8 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
// after applying the message's associated group changes.
|
||||
if (
|
||||
type === 'incoming' &&
|
||||
!conversation.isPrivate() &&
|
||||
isGroupV2 &&
|
||||
!isDirectConversation(conversation.attributes) &&
|
||||
hasGroupV2Prop &&
|
||||
(conversation.get('left') ||
|
||||
!conversation.hasMember(ourConversationId) ||
|
||||
!conversation.hasMember(senderId))
|
||||
|
@ -3690,8 +3703,8 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
// messages. We detect that via a missing 'members' field.
|
||||
if (
|
||||
type === 'incoming' &&
|
||||
!conversation.isPrivate() &&
|
||||
!isGroupV2 &&
|
||||
!isDirectConversation(conversation.attributes) &&
|
||||
!hasGroupV2Prop &&
|
||||
!isV1GroupUpdate &&
|
||||
conversation.get('members') &&
|
||||
(conversation.get('left') || !conversation.hasMember(ourConversationId))
|
||||
|
@ -3705,7 +3718,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
|
||||
// Because GroupV1 messages can now be multiplexed into GroupV2 conversations, we
|
||||
// drop GroupV1 updates in GroupV2 groups.
|
||||
if (isV1GroupUpdate && conversation.isGroupV2()) {
|
||||
if (isV1GroupUpdate && isGroupV2(conversation.attributes)) {
|
||||
window.log.warn(
|
||||
`Received GroupV1 update in GroupV2 conversation ${conversation.idForLogging()}. Dropping.`
|
||||
);
|
||||
|
@ -3793,7 +3806,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
};
|
||||
|
||||
// GroupV1
|
||||
if (!isGroupV2 && dataMessage.group) {
|
||||
if (!hasGroupV2Prop && dataMessage.group) {
|
||||
const pendingGroupUpdate = [];
|
||||
const memberConversations: Array<ConversationModel> = await Promise.all(
|
||||
dataMessage.group.membersE164.map((e164: string) =>
|
||||
|
@ -3920,7 +3933,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
return;
|
||||
}
|
||||
|
||||
if (sender.isMe()) {
|
||||
if (isMe(sender.attributes)) {
|
||||
attributes.left = true;
|
||||
pendingGroupUpdate.push(['left', 'You']);
|
||||
} else {
|
||||
|
@ -3962,7 +3975,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
message.set({ expireTimer: dataMessage.expireTimer });
|
||||
}
|
||||
|
||||
if (!isGroupV2) {
|
||||
if (!hasGroupV2Prop) {
|
||||
if (message.isExpirationTimerUpdate()) {
|
||||
message.set({
|
||||
expirationTimerUpdate: {
|
||||
|
@ -4023,7 +4036,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
sourceUuid === window.textsecure.storage.user.getUuid()
|
||||
) {
|
||||
conversation.set({ profileSharing: true });
|
||||
} else if (conversation.isPrivate()) {
|
||||
} else if (isDirectConversation(conversation.attributes)) {
|
||||
conversation.setProfileKey(profileKey);
|
||||
} else {
|
||||
const localId = window.ConversationController.ensureContactIds({
|
||||
|
@ -4214,7 +4227,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
}
|
||||
|
||||
// A sync'd message to ourself is automatically considered read/delivered
|
||||
if (isFirstRun && conversation.isMe()) {
|
||||
if (isFirstRun && isMe(conversation.attributes)) {
|
||||
message.set({
|
||||
read_by: conversation.getRecipients(),
|
||||
delivered_to: conversation.getRecipients(),
|
||||
|
|
|
@ -69,6 +69,7 @@ import {
|
|||
REQUESTED_VIDEO_FRAMERATE,
|
||||
} from '../calling/constants';
|
||||
import { notify } from './notify';
|
||||
import { getSendOptions } from '../util/getSendOptions';
|
||||
|
||||
const RINGRTC_HTTP_METHOD_TO_OUR_HTTP_METHOD: Map<
|
||||
HttpMethod,
|
||||
|
@ -783,7 +784,7 @@ export class CallingClass {
|
|||
}
|
||||
|
||||
const groupV2 = conversation.getGroupV2Info();
|
||||
const sendOptions = await conversation.getSendOptions();
|
||||
const sendOptions = await getSendOptions(conversation.attributes);
|
||||
if (!groupV2) {
|
||||
window.log.error(
|
||||
'Unable to send group call update message for conversation that lacks groupV2 info'
|
||||
|
@ -1408,7 +1409,7 @@ export class CallingClass {
|
|||
): Promise<boolean> {
|
||||
const conversation = window.ConversationController.get(remoteUserId);
|
||||
const sendOptions = conversation
|
||||
? await conversation.getSendOptions()
|
||||
? await getSendOptions(conversation.attributes)
|
||||
: undefined;
|
||||
|
||||
if (!window.textsecure.messaging) {
|
||||
|
|
|
@ -35,6 +35,10 @@ import { sleep } from '../util/sleep';
|
|||
import { isMoreRecentThan } from '../util/timestamp';
|
||||
import { isStorageWriteFeatureEnabled } from '../storage/isFeatureEnabled';
|
||||
import { ourProfileKeyService } from './ourProfileKey';
|
||||
import {
|
||||
ConversationTypes,
|
||||
typeofConversation,
|
||||
} from '../util/whatTypeOfConversation';
|
||||
|
||||
const {
|
||||
eraseStorageServiceStateFromConversations,
|
||||
|
@ -152,22 +156,24 @@ async function generateManifest(
|
|||
const identifier = new window.textsecure.protobuf.ManifestRecord.Identifier();
|
||||
|
||||
let storageRecord;
|
||||
if (conversation.isMe()) {
|
||||
|
||||
const conversationType = typeofConversation(conversation.attributes);
|
||||
if (conversationType === ConversationTypes.Me) {
|
||||
storageRecord = new window.textsecure.protobuf.StorageRecord();
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
storageRecord.account = await toAccountRecord(conversation);
|
||||
identifier.type = ITEM_TYPE.ACCOUNT;
|
||||
} else if (conversation.isPrivate()) {
|
||||
} else if (conversationType === ConversationTypes.Direct) {
|
||||
storageRecord = new window.textsecure.protobuf.StorageRecord();
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
storageRecord.contact = await toContactRecord(conversation);
|
||||
identifier.type = ITEM_TYPE.CONTACT;
|
||||
} else if (conversation.isGroupV2()) {
|
||||
} else if (conversationType === ConversationTypes.GroupV2) {
|
||||
storageRecord = new window.textsecure.protobuf.StorageRecord();
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
storageRecord.groupV2 = await toGroupV2Record(conversation);
|
||||
identifier.type = ITEM_TYPE.GROUPV2;
|
||||
} else if (conversation.isGroupV1()) {
|
||||
} else if (conversationType === ConversationTypes.GroupV1) {
|
||||
storageRecord = new window.textsecure.protobuf.StorageRecord();
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
storageRecord.groupV1 = await toGroupV1Record(conversation);
|
||||
|
|
|
@ -43,6 +43,7 @@ import {
|
|||
set as setUniversalExpireTimer,
|
||||
} from '../util/universalExpireTimer';
|
||||
import { ourProfileKeyService } from './ourProfileKey';
|
||||
import { isGroupV1, isGroupV2 } from '../util/whatTypeOfConversation';
|
||||
|
||||
const { updateConversation } = dataInterface;
|
||||
|
||||
|
@ -241,7 +242,7 @@ export async function toAccountRecord(
|
|||
uuid: pinnedConversation.get('uuid'),
|
||||
e164: pinnedConversation.get('e164'),
|
||||
};
|
||||
} else if (pinnedConversation.isGroupV1()) {
|
||||
} else if (isGroupV1(pinnedConversation.attributes)) {
|
||||
pinnedConversationRecord.identifier = 'legacyGroupId';
|
||||
const groupId = pinnedConversation.get('groupId');
|
||||
if (!groupId) {
|
||||
|
@ -252,7 +253,7 @@ export async function toAccountRecord(
|
|||
pinnedConversationRecord.legacyGroupId = fromEncodedBinaryToArrayBuffer(
|
||||
groupId
|
||||
);
|
||||
} else if (pinnedConversation.isGroupV2()) {
|
||||
} else if (isGroupV2(pinnedConversation.attributes)) {
|
||||
pinnedConversationRecord.identifier = 'groupMasterKey';
|
||||
const masterKey = pinnedConversation.get('masterKey');
|
||||
if (!masterKey) {
|
||||
|
@ -508,7 +509,7 @@ export async function mergeGroupV1Record(
|
|||
// where the binary representation of its ID matches a v2 record in memory.
|
||||
// Here we ensure that the record we're about to process is GV1 otherwise
|
||||
// we drop the update.
|
||||
if (conversation && !conversation.isGroupV1()) {
|
||||
if (conversation && !isGroupV1(conversation.attributes)) {
|
||||
throw new Error(
|
||||
`Record has group type mismatch ${conversation.idForLogging()}`
|
||||
);
|
||||
|
@ -565,7 +566,7 @@ export async function mergeGroupV1Record(
|
|||
|
||||
let hasPendingChanges: boolean;
|
||||
|
||||
if (conversation.isGroupV1()) {
|
||||
if (isGroupV1(conversation.attributes)) {
|
||||
addUnknownFields(groupV1Record, conversation);
|
||||
|
||||
hasPendingChanges = doesRecordHavePendingChanges(
|
||||
|
@ -684,7 +685,7 @@ export async function mergeGroupV2Record(
|
|||
const isFirstSync = !window.storage.get('storageFetchComplete');
|
||||
const dropInitialJoinMessage = isFirstSync;
|
||||
|
||||
if (conversation.isGroupV1()) {
|
||||
if (isGroupV1(conversation.attributes)) {
|
||||
// If we found a GroupV1 conversation from this incoming GroupV2 record, we need to
|
||||
// migrate it!
|
||||
|
||||
|
|
11
ts/util/deprecated.ts
Normal file
11
ts/util/deprecated.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { getEnvironment, Environment } from '../environment';
|
||||
import * as log from '../logging/log';
|
||||
|
||||
export function deprecated(message?: string): void {
|
||||
if (getEnvironment() === Environment.Development) {
|
||||
log.error(new Error(`This method is deprecated: ${message}`));
|
||||
}
|
||||
}
|
|
@ -40,9 +40,10 @@ export async function getSendOptions(
|
|||
if (!conversation) {
|
||||
return;
|
||||
}
|
||||
const {
|
||||
sendMetadata: conversationSendMetadata,
|
||||
} = await conversation.getSendOptions(options);
|
||||
const { sendMetadata: conversationSendMetadata } = await getSendOptions(
|
||||
conversation.attributes,
|
||||
options
|
||||
);
|
||||
Object.assign(sendMetadata, conversationSendMetadata || {});
|
||||
})
|
||||
);
|
||||
|
|
|
@ -38,6 +38,7 @@ import {
|
|||
import { ContentClass } from '../textsecure.d';
|
||||
|
||||
import { assert } from './assert';
|
||||
import { isGroupV2 } from './whatTypeOfConversation';
|
||||
|
||||
const ERROR_EXPIRED_OR_MISSING_DEVICES = 409;
|
||||
const ERROR_STALE_DEVICES = 410;
|
||||
|
@ -116,7 +117,7 @@ export async function sendContentMessageToGroup({
|
|||
|
||||
if (
|
||||
ourConversation?.get('capabilities')?.senderKey &&
|
||||
conversation.isGroupV2()
|
||||
isGroupV2(conversation.attributes)
|
||||
) {
|
||||
try {
|
||||
return await sendToGroupViaSenderKey({
|
||||
|
@ -138,7 +139,7 @@ export async function sendContentMessageToGroup({
|
|||
}
|
||||
}
|
||||
|
||||
const groupId = conversation.isGroupV2()
|
||||
const groupId = isGroupV2(conversation.attributes)
|
||||
? conversation.get('groupId')
|
||||
: undefined;
|
||||
return window.textsecure.messaging.sendGroupProto(
|
||||
|
@ -191,7 +192,7 @@ export async function sendToGroupViaSenderKey(options: {
|
|||
}
|
||||
|
||||
const groupId = conversation.get('groupId');
|
||||
if (!groupId || !conversation.isGroupV2()) {
|
||||
if (!groupId || !isGroupV2(conversation.attributes)) {
|
||||
throw new Error(
|
||||
`sendToGroupViaSenderKey/${logId}: Missing groupId or group is not GV2`
|
||||
);
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { ConversationModel } from '../models/conversations';
|
||||
import { isMe } from './whatTypeOfConversation';
|
||||
|
||||
export async function shouldRespondWithProfileKey(
|
||||
sender: ConversationModel
|
||||
): Promise<boolean> {
|
||||
if (sender.isMe() || !sender.getAccepted() || sender.isBlocked()) {
|
||||
if (isMe(sender.attributes) || !sender.getAccepted() || sender.isBlocked()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,14 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { ConversationAttributesType } from '../model-types.d';
|
||||
import { base64ToArrayBuffer, fromEncodedBinaryToArrayBuffer } from '../Crypto';
|
||||
|
||||
export enum ConversationTypes {
|
||||
Me = 'Me',
|
||||
Direct = 'Direct',
|
||||
GroupV1 = 'GroupV1',
|
||||
GroupV2 = 'GroupV2',
|
||||
}
|
||||
|
||||
export function isDirectConversation(
|
||||
conversationAttrs: ConversationAttributesType
|
||||
|
@ -15,3 +23,56 @@ export function isMe(conversationAttrs: ConversationAttributesType): boolean {
|
|||
const ourUuid = window.textsecure.storage.user.getUuid();
|
||||
return Boolean((e164 && e164 === ourNumber) || (uuid && uuid === ourUuid));
|
||||
}
|
||||
|
||||
export function isGroupV1(
|
||||
conversationAttrs: ConversationAttributesType
|
||||
): boolean {
|
||||
const { groupId } = conversationAttrs;
|
||||
if (!groupId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const buffer = fromEncodedBinaryToArrayBuffer(groupId);
|
||||
return buffer.byteLength === window.Signal.Groups.ID_V1_LENGTH;
|
||||
}
|
||||
|
||||
export function isGroupV2(
|
||||
conversationAttrs: ConversationAttributesType
|
||||
): boolean {
|
||||
const { groupId, groupVersion = 0 } = conversationAttrs;
|
||||
if (!groupId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return (
|
||||
groupVersion === 2 &&
|
||||
base64ToArrayBuffer(groupId).byteLength === window.Signal.Groups.ID_LENGTH
|
||||
);
|
||||
} catch (error) {
|
||||
window.log.error('isGroupV2: Failed to process groupId in base64!');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function typeofConversation(
|
||||
conversationAttrs: ConversationAttributesType
|
||||
): ConversationTypes | undefined {
|
||||
if (isMe(conversationAttrs)) {
|
||||
return ConversationTypes.Me;
|
||||
}
|
||||
|
||||
if (isDirectConversation(conversationAttrs)) {
|
||||
return ConversationTypes.Direct;
|
||||
}
|
||||
|
||||
if (isGroupV2(conversationAttrs)) {
|
||||
return ConversationTypes.GroupV2;
|
||||
}
|
||||
|
||||
if (isGroupV1(conversationAttrs)) {
|
||||
return ConversationTypes.GroupV1;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,12 @@ import { maybeParseUrl } from '../util/url';
|
|||
import { addReportSpamJob } from '../jobs/helpers/addReportSpamJob';
|
||||
import { reportSpamJobQueue } from '../jobs/reportSpamJobQueue';
|
||||
import { GroupNameCollisionsWithIdsByTitle } from '../util/groupMemberNameCollisions';
|
||||
import {
|
||||
isDirectConversation,
|
||||
isGroupV1,
|
||||
isGroupV2,
|
||||
isMe,
|
||||
} from '../util/whatTypeOfConversation';
|
||||
|
||||
type GetLinkPreviewImageResult = {
|
||||
data: ArrayBuffer;
|
||||
|
@ -486,7 +492,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
|||
onResetSession: () => this.endSession(),
|
||||
onSearchInConversation: () => {
|
||||
const { searchInConversation } = window.reduxActions.search;
|
||||
const name = this.model.isMe()
|
||||
const name = isMe(this.model.attributes)
|
||||
? window.i18n('noteToSelf')
|
||||
: this.model.getTitle();
|
||||
searchInConversation(this.model.id, name);
|
||||
|
@ -1281,7 +1287,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
|||
async startMigrationToGV2(): Promise<void> {
|
||||
const logId = this.model.idForLogging();
|
||||
|
||||
if (!this.model.isGroupV1()) {
|
||||
if (!isGroupV1(this.model.attributes)) {
|
||||
throw new Error(
|
||||
`startMigrationToGV2/${logId}: Cannot start, not a GroupV1 group`
|
||||
);
|
||||
|
@ -2682,7 +2688,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
|||
|
||||
let model = providedMembers || this.model.contactCollection;
|
||||
|
||||
if (!providedMembers && this.model.isGroupV2()) {
|
||||
if (!providedMembers && isGroupV2(this.model.attributes)) {
|
||||
model = new Whisper.GroupConversationCollection(
|
||||
this.model.get('membersV2').map(({ conversationId, role }: any) => ({
|
||||
conversation: window.ConversationController.get(conversationId),
|
||||
|
@ -2738,7 +2744,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
|||
showSafetyNumber(id: any) {
|
||||
let conversation;
|
||||
|
||||
if (!id && this.model.isPrivate()) {
|
||||
if (!id && isDirectConversation(this.model.attributes)) {
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
conversation = this.model;
|
||||
} else {
|
||||
|
@ -3786,19 +3792,22 @@ Whisper.ConversationView = Whisper.View.extend({
|
|||
ToastView = Whisper.InvalidConversationToast;
|
||||
}
|
||||
if (
|
||||
this.model.isPrivate() &&
|
||||
isDirectConversation(this.model.attributes) &&
|
||||
(window.storage.isBlocked(this.model.get('e164')) ||
|
||||
window.storage.isUuidBlocked(this.model.get('uuid')))
|
||||
) {
|
||||
ToastView = Whisper.BlockedToast;
|
||||
}
|
||||
if (
|
||||
!this.model.isPrivate() &&
|
||||
!isDirectConversation(this.model.attributes) &&
|
||||
window.storage.isGroupBlocked(this.model.get('groupId'))
|
||||
) {
|
||||
ToastView = Whisper.BlockedGroupToast;
|
||||
}
|
||||
if (!this.model.isPrivate() && this.model.get('left')) {
|
||||
if (
|
||||
!isDirectConversation(this.model.attributes) &&
|
||||
this.model.get('left')
|
||||
) {
|
||||
ToastView = Whisper.LeftGroupToast;
|
||||
}
|
||||
if (messageText && messageText.length > MAX_MESSAGE_BODY_LENGTH) {
|
||||
|
|
Loading…
Reference in a new issue