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…
	
	Add table
		Add a link
		
	
		Reference in a new issue