Support phone number sharing flag on profile
This commit is contained in:
parent
23f39a0dc7
commit
d71da5c486
16 changed files with 155 additions and 33 deletions
1
ts/model-types.d.ts
vendored
1
ts/model-types.d.ts
vendored
|
@ -333,6 +333,7 @@ export type ConversationAttributesType = {
|
||||||
messageRequestResponseType?: number;
|
messageRequestResponseType?: number;
|
||||||
muteExpiresAt?: number;
|
muteExpiresAt?: number;
|
||||||
dontNotifyForMentionsIfMuted?: boolean;
|
dontNotifyForMentionsIfMuted?: boolean;
|
||||||
|
notSharingPhoneNumber?: boolean;
|
||||||
profileAvatar?: ContactAvatarType | null;
|
profileAvatar?: ContactAvatarType | null;
|
||||||
profileKeyCredential?: string | null;
|
profileKeyCredential?: string | null;
|
||||||
profileKeyCredentialExpiration?: number | null;
|
profileKeyCredentialExpiration?: number | null;
|
||||||
|
|
|
@ -1858,7 +1858,7 @@ export class ConversationModel extends window.Backbone
|
||||||
this.set('e164', e164 || undefined);
|
this.set('e164', e164 || undefined);
|
||||||
|
|
||||||
// This user changed their phone number
|
// This user changed their phone number
|
||||||
if (oldValue && e164) {
|
if (oldValue && e164 && !this.get('notSharingPhoneNumber')) {
|
||||||
void this.addChangeNumberNotification(oldValue, e164);
|
void this.addChangeNumberNotification(oldValue, e164);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -427,6 +427,24 @@ async function doGetProfile(c: ConversationModel): Promise<void> {
|
||||||
c.unset('aboutEmoji');
|
c.unset('aboutEmoji');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (profile.phoneNumberSharing) {
|
||||||
|
if (decryptionKey) {
|
||||||
|
const decrypted = decryptProfile(
|
||||||
|
Bytes.fromBase64(profile.phoneNumberSharing),
|
||||||
|
decryptionKey
|
||||||
|
);
|
||||||
|
|
||||||
|
// It should be one byte, but be conservative about it and only
|
||||||
|
// set `notSharingPhoneNumber` to `true` in all cases except [0x01].
|
||||||
|
c.set(
|
||||||
|
'notSharingPhoneNumber',
|
||||||
|
decrypted.length !== 1 || decrypted[0] !== 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.unset('notSharingPhoneNumber');
|
||||||
|
}
|
||||||
|
|
||||||
if (profile.paymentAddress && isMe(c.attributes)) {
|
if (profile.paymentAddress && isMe(c.attributes)) {
|
||||||
await window.storage.put('paymentAddress', profile.paymentAddress);
|
await window.storage.put('paymentAddress', profile.paymentAddress);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,18 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import * as Errors from '../types/errors';
|
import * as Errors from '../types/errors';
|
||||||
|
import { getConversation } from '../util/getConversation';
|
||||||
import { DAY } from '../util/durations';
|
import { DAY } from '../util/durations';
|
||||||
import { drop } from '../util/drop';
|
import { drop } from '../util/drop';
|
||||||
import { BackOff, FIBONACCI_TIMEOUTS } from '../util/BackOff';
|
import { BackOff, FIBONACCI_TIMEOUTS } from '../util/BackOff';
|
||||||
import { checkForUsername } from '../util/lookupConversationWithoutServiceId';
|
import { checkForUsername } from '../util/lookupConversationWithoutServiceId';
|
||||||
import { storageJobQueue } from '../util/JobQueue';
|
import { storageJobQueue } from '../util/JobQueue';
|
||||||
|
import { getProfile } from '../util/getProfile';
|
||||||
|
import { isSharingPhoneNumberWithEverybody } from '../util/phoneNumberSharingMode';
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
import { resolveUsernameByLink } from './username';
|
import { resolveUsernameByLink } from './username';
|
||||||
|
import { runStorageServiceSyncJob } from './storage';
|
||||||
|
import { writeProfile } from './writeProfile';
|
||||||
|
|
||||||
const CHECK_INTERVAL = DAY;
|
const CHECK_INTERVAL = DAY;
|
||||||
|
|
||||||
|
@ -59,6 +64,11 @@ class UsernameIntegrityService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async check(): Promise<void> {
|
private async check(): Promise<void> {
|
||||||
|
await this.checkUsername();
|
||||||
|
await this.checkPhoneNumberSharing();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async checkUsername(): Promise<void> {
|
||||||
const me = window.ConversationController.getOurConversationOrThrow();
|
const me = window.ConversationController.getOurConversationOrThrow();
|
||||||
const username = me.get('username');
|
const username = me.get('username');
|
||||||
const aci = me.getAci();
|
const aci = me.getAci();
|
||||||
|
@ -100,6 +110,51 @@ class UsernameIntegrityService {
|
||||||
log.info('usernameIntegrity: check pass');
|
log.info('usernameIntegrity: check pass');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async checkPhoneNumberSharing(): Promise<void> {
|
||||||
|
const me = window.ConversationController.getOurConversationOrThrow();
|
||||||
|
|
||||||
|
await getProfile(me.getServiceId(), me.get('e164'));
|
||||||
|
|
||||||
|
{
|
||||||
|
const localValue = isSharingPhoneNumberWithEverybody();
|
||||||
|
const remoteValue = !me.get('notSharingPhoneNumber');
|
||||||
|
if (localValue === remoteValue) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.warn(
|
||||||
|
'usernameIntegrity: phone number sharing mode conflict, running ' +
|
||||||
|
`storage service sync (local: ${localValue}, remote: ${remoteValue})`
|
||||||
|
);
|
||||||
|
|
||||||
|
runStorageServiceSyncJob();
|
||||||
|
}
|
||||||
|
|
||||||
|
window.Whisper.events.once('storageService:syncComplete', () => {
|
||||||
|
const localValue = isSharingPhoneNumberWithEverybody();
|
||||||
|
const remoteValue = !me.get('notSharingPhoneNumber');
|
||||||
|
if (localValue === remoteValue) {
|
||||||
|
log.info(
|
||||||
|
'usernameIntegrity: phone number sharing mode conflict resolved by ' +
|
||||||
|
'storage service sync'
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.warn(
|
||||||
|
'usernameIntegrity: phone number sharing mode conflict not resolved, ' +
|
||||||
|
'updating profile'
|
||||||
|
);
|
||||||
|
|
||||||
|
drop(
|
||||||
|
writeProfile(getConversation(me), {
|
||||||
|
oldAvatar: undefined,
|
||||||
|
newAvatar: undefined,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const usernameIntegrity = new UsernameIntegrityService();
|
export const usernameIntegrity = new UsernameIntegrityService();
|
||||||
|
|
|
@ -18,9 +18,9 @@ export async function writeProfile(
|
||||||
conversation: ConversationType,
|
conversation: ConversationType,
|
||||||
avatar: AvatarUpdateType
|
avatar: AvatarUpdateType
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const { messaging } = window.textsecure;
|
const { server } = window.textsecure;
|
||||||
if (!messaging) {
|
if (!server) {
|
||||||
throw new Error('messaging is not available!');
|
throw new Error('server is not available!');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Before we write anything we request the user's profile so that we can
|
// Before we write anything we request the user's profile so that we can
|
||||||
|
@ -50,7 +50,7 @@ export async function writeProfile(
|
||||||
conversation,
|
conversation,
|
||||||
avatar
|
avatar
|
||||||
);
|
);
|
||||||
const avatarRequestHeaders = await messaging.putProfile(profileData);
|
const avatarRequestHeaders = await server.putProfile(profileData);
|
||||||
|
|
||||||
// Upload the avatar if provided
|
// Upload the avatar if provided
|
||||||
// delete existing files on disk if avatar has been removed
|
// delete existing files on disk if avatar has been removed
|
||||||
|
@ -68,7 +68,7 @@ export async function writeProfile(
|
||||||
log.info('writeProfile: not updating avatar');
|
log.info('writeProfile: not updating avatar');
|
||||||
} else if (avatarRequestHeaders && encryptedAvatarData && newAvatar) {
|
} else if (avatarRequestHeaders && encryptedAvatarData && newAvatar) {
|
||||||
log.info('writeProfile: uploading new avatar');
|
log.info('writeProfile: uploading new avatar');
|
||||||
const avatarUrl = await messaging.uploadAvatar(
|
const avatarUrl = await server.uploadAvatar(
|
||||||
avatarRequestHeaders,
|
avatarRequestHeaders,
|
||||||
encryptedAvatarData
|
encryptedAvatarData
|
||||||
);
|
);
|
||||||
|
|
|
@ -308,6 +308,7 @@ export type ConversationType = ReadonlyDeep<
|
||||||
typingContactIdTimestamps?: Record<string, number>;
|
typingContactIdTimestamps?: Record<string, number>;
|
||||||
recentMediaItems?: ReadonlyArray<MediaItemType>;
|
recentMediaItems?: ReadonlyArray<MediaItemType>;
|
||||||
profileSharing?: boolean;
|
profileSharing?: boolean;
|
||||||
|
notSharingPhoneNumber?: boolean;
|
||||||
|
|
||||||
shouldShowDraft?: boolean;
|
shouldShowDraft?: boolean;
|
||||||
// Full information for re-hydrating composition area
|
// Full information for re-hydrating composition area
|
||||||
|
|
|
@ -34,9 +34,7 @@ import type {
|
||||||
GetProfileUnauthOptionsType,
|
GetProfileUnauthOptionsType,
|
||||||
GroupCredentialsType,
|
GroupCredentialsType,
|
||||||
GroupLogResponseType,
|
GroupLogResponseType,
|
||||||
ProfileRequestDataType,
|
|
||||||
ProxiedRequestOptionsType,
|
ProxiedRequestOptionsType,
|
||||||
UploadAvatarHeadersType,
|
|
||||||
WebAPIType,
|
WebAPIType,
|
||||||
} from './WebAPI';
|
} from './WebAPI';
|
||||||
import createTaskWithTimeout from './TaskWithTimeout';
|
import createTaskWithTimeout from './TaskWithTimeout';
|
||||||
|
@ -2232,17 +2230,4 @@ export default class MessageSender {
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return this.server.sendChallengeResponse(challengeResponse);
|
return this.server.sendChallengeResponse(challengeResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
async putProfile(
|
|
||||||
jsonData: Readonly<ProfileRequestDataType>
|
|
||||||
): Promise<UploadAvatarHeadersType | undefined> {
|
|
||||||
return this.server.putProfile(jsonData);
|
|
||||||
}
|
|
||||||
|
|
||||||
async uploadAvatar(
|
|
||||||
requestHeaders: Readonly<UploadAvatarHeadersType>,
|
|
||||||
avatarData: Readonly<Uint8Array>
|
|
||||||
): Promise<string> {
|
|
||||||
return this.server.uploadAvatar(requestHeaders, avatarData);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -674,6 +674,7 @@ export type ProfileRequestDataType = {
|
||||||
commitment: string;
|
commitment: string;
|
||||||
name: string;
|
name: string;
|
||||||
paymentAddress: string | null;
|
paymentAddress: string | null;
|
||||||
|
phoneNumberSharing: string | null;
|
||||||
version: string;
|
version: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -706,6 +707,7 @@ export type ProfileType = Readonly<{
|
||||||
about?: string;
|
about?: string;
|
||||||
aboutEmoji?: string;
|
aboutEmoji?: string;
|
||||||
avatar?: string;
|
avatar?: string;
|
||||||
|
phoneNumberSharing?: string;
|
||||||
unidentifiedAccess?: string;
|
unidentifiedAccess?: string;
|
||||||
unrestrictedUnidentifiedAccess?: string;
|
unrestrictedUnidentifiedAccess?: string;
|
||||||
uuid?: string;
|
uuid?: string;
|
||||||
|
|
|
@ -21,6 +21,7 @@ import type { ConversationType } from '../state/ducks/conversations';
|
||||||
import type { AuthorizeArtCreatorDataType } from '../state/ducks/globalModals';
|
import type { AuthorizeArtCreatorDataType } from '../state/ducks/globalModals';
|
||||||
import { calling } from '../services/calling';
|
import { calling } from '../services/calling';
|
||||||
import { resolveUsernameByLinkBase64 } from '../services/username';
|
import { resolveUsernameByLinkBase64 } from '../services/username';
|
||||||
|
import { writeProfile } from '../services/writeProfile';
|
||||||
import { getConversationsWithCustomColorSelector } from '../state/selectors/conversations';
|
import { getConversationsWithCustomColorSelector } from '../state/selectors/conversations';
|
||||||
import { getCustomColors } from '../state/selectors/items';
|
import { getCustomColors } from '../state/selectors/items';
|
||||||
import { themeChanged } from '../shims/themeChanged';
|
import { themeChanged } from '../shims/themeChanged';
|
||||||
|
@ -41,6 +42,7 @@ import type { NotificationClickData } from '../services/notifications';
|
||||||
import { StoryViewModeType, StoryViewTargetType } from '../types/Stories';
|
import { StoryViewModeType, StoryViewTargetType } from '../types/Stories';
|
||||||
import { isValidE164 } from './isValidE164';
|
import { isValidE164 } from './isValidE164';
|
||||||
import { fromWebSafeBase64 } from './webSafeBase64';
|
import { fromWebSafeBase64 } from './webSafeBase64';
|
||||||
|
import { getConversation } from './getConversation';
|
||||||
|
|
||||||
type SentMediaQualityType = 'standard' | 'high';
|
type SentMediaQualityType = 'standard' | 'high';
|
||||||
type ThemeType = 'light' | 'dark' | 'system';
|
type ThemeType = 'light' | 'dark' | 'system';
|
||||||
|
@ -235,6 +237,14 @@ export function createIPCEvents(
|
||||||
setPhoneNumberDiscoverabilitySetting,
|
setPhoneNumberDiscoverabilitySetting,
|
||||||
setPhoneNumberSharingSetting: async (newValue: PhoneNumberSharingMode) => {
|
setPhoneNumberSharingSetting: async (newValue: PhoneNumberSharingMode) => {
|
||||||
const account = window.ConversationController.getOurConversationOrThrow();
|
const account = window.ConversationController.getOurConversationOrThrow();
|
||||||
|
|
||||||
|
// writeProfile fetches the latest profile first so do it before updating
|
||||||
|
// local data to prevent triggering a conflict.
|
||||||
|
await writeProfile(getConversation(account), {
|
||||||
|
oldAvatar: undefined,
|
||||||
|
newAvatar: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
const promises = new Array<Promise<void>>();
|
const promises = new Array<Promise<void>>();
|
||||||
promises.push(window.storage.put('phoneNumberSharingMode', newValue));
|
promises.push(window.storage.put('phoneNumberSharingMode', newValue));
|
||||||
if (newValue === PhoneNumberSharingMode.Everybody) {
|
if (newValue === PhoneNumberSharingMode.Everybody) {
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
} from '../Crypto';
|
} from '../Crypto';
|
||||||
import type { AvatarUpdateType } from '../types/Avatar';
|
import type { AvatarUpdateType } from '../types/Avatar';
|
||||||
import { deriveProfileKeyCommitment, deriveProfileKeyVersion } from './zkgroup';
|
import { deriveProfileKeyCommitment, deriveProfileKeyVersion } from './zkgroup';
|
||||||
|
import { isSharingPhoneNumberWithEverybody } from './phoneNumberSharingMode';
|
||||||
|
|
||||||
export async function encryptProfileData(
|
export async function encryptProfileData(
|
||||||
conversation: ConversationType,
|
conversation: ConversationType,
|
||||||
|
@ -56,6 +57,11 @@ export async function encryptProfileData(
|
||||||
)
|
)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
|
const encryptedPhoneNumberSharing = encryptProfile(
|
||||||
|
new Uint8Array([isSharingPhoneNumberWithEverybody() ? 1 : 0]),
|
||||||
|
keyBuffer
|
||||||
|
);
|
||||||
|
|
||||||
const encryptedAvatarData = newAvatar
|
const encryptedAvatarData = newAvatar
|
||||||
? encryptProfile(newAvatar, keyBuffer)
|
? encryptProfile(newAvatar, keyBuffer)
|
||||||
: undefined;
|
: undefined;
|
||||||
|
@ -72,6 +78,7 @@ export async function encryptProfileData(
|
||||||
avatar: Boolean(newAvatar),
|
avatar: Boolean(newAvatar),
|
||||||
sameAvatar,
|
sameAvatar,
|
||||||
commitment: deriveProfileKeyCommitment(profileKey, serviceId),
|
commitment: deriveProfileKeyCommitment(profileKey, serviceId),
|
||||||
|
phoneNumberSharing: Bytes.toBase64(encryptedPhoneNumberSharing),
|
||||||
};
|
};
|
||||||
|
|
||||||
return [profileData, encryptedAvatarData];
|
return [profileData, encryptedAvatarData];
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { parseAndFormatPhoneNumber } from './libphonenumberInstance';
|
||||||
import { WEEK } from './durations';
|
import { WEEK } from './durations';
|
||||||
import { fuseGetFnRemoveDiacritics, getCachedFuseIndex } from './fuse';
|
import { fuseGetFnRemoveDiacritics, getCachedFuseIndex } from './fuse';
|
||||||
import { countConversationUnreadStats, hasUnread } from './countUnreadStats';
|
import { countConversationUnreadStats, hasUnread } from './countUnreadStats';
|
||||||
|
import { getE164 } from './getE164';
|
||||||
|
|
||||||
// Fuse.js scores have order of 0.01
|
// Fuse.js scores have order of 0.01
|
||||||
const ACTIVE_AT_SCORE_FACTOR = (1 / WEEK) * 0.01;
|
const ACTIVE_AT_SCORE_FACTOR = (1 / WEEK) * 0.01;
|
||||||
|
@ -46,7 +47,13 @@ const FUSE_OPTIONS: Fuse.IFuseOptions<ConversationType> = {
|
||||||
weight: 0.5,
|
weight: 0.5,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
getFn: fuseGetFnRemoveDiacritics,
|
getFn: (convo, path) => {
|
||||||
|
if (path === 'e164' || (path.length === 1 && path[0] === 'e164')) {
|
||||||
|
return getE164(convo) ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return fuseGetFnRemoveDiacritics(convo, path);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
type CommandRunnerType = (
|
type CommandRunnerType = (
|
||||||
|
|
|
@ -210,6 +210,7 @@ export function getConversation(model: ConversationModel): ConversationType {
|
||||||
phoneNumber: getNumber(attributes),
|
phoneNumber: getNumber(attributes),
|
||||||
profileName: getProfileName(attributes),
|
profileName: getProfileName(attributes),
|
||||||
profileSharing: attributes.profileSharing,
|
profileSharing: attributes.profileSharing,
|
||||||
|
notSharingPhoneNumber: attributes.notSharingPhoneNumber,
|
||||||
publicParams: attributes.publicParams,
|
publicParams: attributes.publicParams,
|
||||||
secretParams: attributes.secretParams,
|
secretParams: attributes.secretParams,
|
||||||
shouldShowDraft,
|
shouldShowDraft,
|
||||||
|
|
26
ts/util/getE164.ts
Normal file
26
ts/util/getE164.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
// Copyright 2023 Signal Messenger, LLC
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
import type { ConversationAttributesType } from '../model-types.d';
|
||||||
|
import type { ConversationType } from '../state/ducks/conversations';
|
||||||
|
import { isInSystemContacts } from './isInSystemContacts';
|
||||||
|
|
||||||
|
export function getE164(
|
||||||
|
attributes: Pick<
|
||||||
|
ConversationAttributesType | ConversationType,
|
||||||
|
| 'type'
|
||||||
|
| 'name'
|
||||||
|
| 'systemGivenName'
|
||||||
|
| 'systemFamilyName'
|
||||||
|
| 'e164'
|
||||||
|
| 'notSharingPhoneNumber'
|
||||||
|
>
|
||||||
|
): string | undefined {
|
||||||
|
const { e164, notSharingPhoneNumber = false } = attributes;
|
||||||
|
|
||||||
|
if (notSharingPhoneNumber && !isInSystemContacts(attributes)) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return e164;
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ import type {
|
||||||
import { combineNames } from './combineNames';
|
import { combineNames } from './combineNames';
|
||||||
import { getRegionCodeForNumber } from './libphonenumberUtil';
|
import { getRegionCodeForNumber } from './libphonenumberUtil';
|
||||||
import { isDirectConversation } from './whatTypeOfConversation';
|
import { isDirectConversation } from './whatTypeOfConversation';
|
||||||
|
import { getE164 } from './getE164';
|
||||||
|
|
||||||
export function getTitle(
|
export function getTitle(
|
||||||
attributes: ConversationRenderInfoType,
|
attributes: ConversationRenderInfoType,
|
||||||
|
@ -107,13 +108,16 @@ export function getSystemName(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getNumber(
|
export function getNumber(
|
||||||
attributes: Pick<ConversationAttributesType, 'e164' | 'type'>
|
attributes: Pick<
|
||||||
|
ConversationAttributesType,
|
||||||
|
'e164' | 'type' | 'notSharingPhoneNumber'
|
||||||
|
>
|
||||||
): string | undefined {
|
): string | undefined {
|
||||||
if (!isDirectConversation(attributes)) {
|
if (!isDirectConversation(attributes)) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
const { e164 } = attributes;
|
const e164 = getE164(attributes);
|
||||||
if (!e164) {
|
if (!e164) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import {
|
||||||
getSourceServiceId,
|
getSourceServiceId,
|
||||||
} from '../messages/helpers';
|
} from '../messages/helpers';
|
||||||
import { isDirectConversation, isGroupV2 } from './whatTypeOfConversation';
|
import { isDirectConversation, isGroupV2 } from './whatTypeOfConversation';
|
||||||
|
import { getE164 } from './getE164';
|
||||||
|
|
||||||
export function getMessageIdForLogging(
|
export function getMessageIdForLogging(
|
||||||
message: Pick<
|
message: Pick<
|
||||||
|
@ -29,8 +30,8 @@ export function getConversationIdForLogging(
|
||||||
conversation: ConversationAttributesType
|
conversation: ConversationAttributesType
|
||||||
): string {
|
): string {
|
||||||
if (isDirectConversation(conversation)) {
|
if (isDirectConversation(conversation)) {
|
||||||
const { serviceId, pni, e164, id } = conversation;
|
const { serviceId, pni, id } = conversation;
|
||||||
return `${serviceId || pni || e164} (${id})`;
|
return `${serviceId || pni || getE164(conversation)} (${id})`;
|
||||||
}
|
}
|
||||||
if (isGroupV2(conversation)) {
|
if (isGroupV2(conversation)) {
|
||||||
return `groupv2(${conversation.groupId})`;
|
return `groupv2(${conversation.groupId})`;
|
||||||
|
|
|
@ -19,13 +19,7 @@ export const parsePhoneNumberSharingMode = makeEnumParser(
|
||||||
PhoneNumberSharingMode.Everybody
|
PhoneNumberSharingMode.Everybody
|
||||||
);
|
);
|
||||||
|
|
||||||
export const shouldSharePhoneNumberWith = (
|
export const isSharingPhoneNumberWithEverybody = (): boolean => {
|
||||||
conversation: ConversationAttributesType
|
|
||||||
): boolean => {
|
|
||||||
if (!isDirectConversation(conversation) || isMe(conversation)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const phoneNumberSharingMode = parsePhoneNumberSharingMode(
|
const phoneNumberSharingMode = parsePhoneNumberSharingMode(
|
||||||
window.storage.get('phoneNumberSharingMode')
|
window.storage.get('phoneNumberSharingMode')
|
||||||
);
|
);
|
||||||
|
@ -40,3 +34,13 @@ export const shouldSharePhoneNumberWith = (
|
||||||
throw missingCaseError(phoneNumberSharingMode);
|
throw missingCaseError(phoneNumberSharingMode);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const shouldSharePhoneNumberWith = (
|
||||||
|
conversation: ConversationAttributesType
|
||||||
|
): boolean => {
|
||||||
|
if (!isDirectConversation(conversation) || isMe(conversation)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isSharingPhoneNumberWithEverybody();
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in a new issue