Migrate schema to service ids

This commit is contained in:
Fedor Indutny
2023-08-16 22:54:39 +02:00
committed by Jamie Kyle
parent 71958f8a01
commit 8b0da36caa
258 changed files with 4795 additions and 2613 deletions

View File

@@ -62,9 +62,9 @@ function checkForAccount(
}
const conversation = window.ConversationController.get(phoneNumber);
if (conversation && conversation.get('uuid')) {
if (conversation && conversation.getServiceId()) {
log.info(`checkForAccount: found ${phoneNumber} in existing contacts`);
const serviceId = conversation.get('uuid');
const serviceId = conversation.getServiceId();
dispatch({
type: 'accounts/UPDATE',
@@ -93,8 +93,10 @@ function checkForAccount(
log.info(`checkForAccount: looking ${phoneNumber} up on server`);
try {
const uuidLookup = await getServiceIdsForE164s(server, [phoneNumber]);
const maybePair = uuidLookup.get(phoneNumber);
const serviceIdLookup = await getServiceIdsForE164s(server, [
phoneNumber,
]);
const maybePair = serviceIdLookup.get(phoneNumber);
if (maybePair) {
const { conversation: maybeMerged } =
@@ -104,7 +106,7 @@ function checkForAccount(
e164: phoneNumber,
reason: 'checkForAccount',
});
serviceId = maybeMerged.get('uuid');
serviceId = maybeMerged.getServiceId();
}
} catch (error) {
log.error('checkForAccount:', Errors.toLogFormat(error));

View File

@@ -936,7 +936,7 @@ function keyChanged(
if (activeCall.callMode === CallMode.Group) {
const acisChanged = new Set(activeCallState.safetyNumberChangedAcis);
// Iterate over each participant to ensure that the uuid passed in
// Iterate over each participant to ensure that the service id passed in
// matches one of the participants in the group call.
activeCall.remoteParticipants.forEach(participant => {
if (participant.aci === payload.aci) {

View File

@@ -35,6 +35,7 @@ import {
REMOVE_PREVIEW as REMOVE_LINK_PREVIEW,
} from './linkPreviews';
import { LinkPreviewSourceType } from '../../types/LinkPreview';
import type { AciString } from '../../types/ServiceId';
import { completeRecording } from './audioRecorder';
import { RecordingState } from '../../types/AudioRecorder';
import { SHOW_TOAST } from './toast';
@@ -526,7 +527,7 @@ function sendEditedMessage(
conversationId: string,
options: WithPreSendChecksOptions & {
targetMessageId: string;
quoteAuthorUuid?: string;
quoteAuthorAci?: AciString;
quoteSentAt?: number;
}
): ThunkAction<
@@ -545,7 +546,7 @@ function sendEditedMessage(
message = '',
bodyRanges,
quoteSentAt,
quoteAuthorUuid,
quoteAuthorAci,
targetMessageId,
} = options;
@@ -559,7 +560,7 @@ function sendEditedMessage(
body: message,
bodyRanges,
preview: getLinkPreviewForSend(message),
quoteAuthorUuid,
quoteAuthorAci,
quoteSentAt,
targetMessageId,
});

View File

@@ -219,7 +219,7 @@ export type DraftPreviewType = ReadonlyDeep<{
export type ConversationType = ReadonlyDeep<
{
id: string;
uuid?: ServiceIdString;
serviceId?: ServiceIdString;
pni?: PniString;
e164?: string;
name?: string;
@@ -274,15 +274,15 @@ export type ConversationType = ReadonlyDeep<
announcementsOnlyReady?: boolean;
expireTimer?: DurationInSeconds;
memberships?: ReadonlyArray<{
uuid: AciString;
aci: AciString;
isAdmin: boolean;
}>;
pendingMemberships?: ReadonlyArray<{
uuid: ServiceIdString;
serviceId: ServiceIdString;
addedByUserId?: AciString;
}>;
pendingApprovalMemberships?: ReadonlyArray<{
uuid: AciString;
aci: AciString;
}>;
bannedMemberships?: ReadonlyArray<ServiceIdString>;
muteExpiresAt?: number;
@@ -474,7 +474,7 @@ export type ConversationsStateType = Readonly<{
invitedServiceIdsForNewlyCreatedGroup?: ReadonlyArray<ServiceIdString>;
conversationLookup: ConversationLookupType;
conversationsByE164: ConversationLookupType;
conversationsByUuid: ConversationLookupType;
conversationsByServiceId: ConversationLookupType;
conversationsByGroupId: ConversationLookupType;
conversationsByUsername: ConversationLookupType;
selectedConversationId?: string;
@@ -576,7 +576,7 @@ export type CancelVerificationDataByConversationActionType = ReadonlyDeep<{
type ClearGroupCreationErrorActionType = ReadonlyDeep<{
type: 'CLEAR_GROUP_CREATION_ERROR';
}>;
type ClearInvitedUuidsForNewlyCreatedGroupActionType = ReadonlyDeep<{
type ClearInvitedServiceIdsForNewlyCreatedGroupActionType = ReadonlyDeep<{
type: 'CLEAR_INVITED_SERVICE_IDS_FOR_NEWLY_CREATED_GROUP';
}>;
type ClearVerificationDataByConversationActionType = ReadonlyDeep<{
@@ -944,7 +944,7 @@ export type ConversationActionType =
| CancelVerificationDataByConversationActionType
| ClearCancelledVerificationActionType
| ClearGroupCreationErrorActionType
| ClearInvitedUuidsForNewlyCreatedGroupActionType
| ClearInvitedServiceIdsForNewlyCreatedGroupActionType
| ClearTargetedMessageActionType
| ClearUnreadMetricsActionType
| ClearVerificationDataByConversationActionType
@@ -1022,7 +1022,7 @@ export const actions = {
changeHasGroupLink,
clearCancelledConversationVerification,
clearGroupCreationError,
clearInvitedUuidsForNewlyCreatedGroup,
clearInvitedServiceIdsForNewlyCreatedGroup,
clearTargetedMessage,
clearUnreadMetrics,
closeContactSpoofingReview,
@@ -1863,7 +1863,11 @@ export const markViewed = (messageId: string): void => {
}
const senderE164 = message.get('source');
const senderUuid = message.get('sourceUuid');
const senderAci = message.get('sourceServiceId');
strictAssert(
isAciString(senderAci),
'Message sourceServiceId must be an ACI'
);
const timestamp = getMessageSentTimestamp(message.attributes, { log });
message.set(messageUpdaterMarkViewed(message.attributes, Date.now()));
@@ -1881,7 +1885,7 @@ export const markViewed = (messageId: string): void => {
messageId,
conversationId,
senderE164,
senderUuid,
senderAci,
timestamp,
isDirectConversation: convoAttributes
? isDirectConversation(convoAttributes)
@@ -1898,7 +1902,7 @@ export const markViewed = (messageId: string): void => {
{
messageId,
senderE164,
senderUuid,
senderAci,
timestamp,
},
],
@@ -2578,7 +2582,7 @@ function createGroup(
type: 'CREATE_GROUP_FULFILLED',
payload: {
invitedServiceIds: (conversation.get('pendingMembersV2') || []).map(
member => member.uuid
member => member.serviceId
),
},
});
@@ -2706,11 +2710,11 @@ function conversationStoppedByMissingVerification(payload: {
untrustedServiceIds: ReadonlyArray<ServiceIdString>;
}): ConversationStoppedByMissingVerificationActionType {
// Fetching profiles to ensure that we have their latest identity key in storage
payload.untrustedServiceIds.forEach(uuid => {
const conversation = window.ConversationController.get(uuid);
payload.untrustedServiceIds.forEach(serviceId => {
const conversation = window.ConversationController.get(serviceId);
if (!conversation) {
log.error(
`conversationStoppedByMissingVerification: uuid ${uuid} not found!`
`conversationStoppedByMissingVerification: serviceId ${serviceId} not found!`
);
return;
}
@@ -3405,8 +3409,8 @@ function loadRecentMediaItems(
message: {
attachments: message.attachments || [],
conversationId:
window.ConversationController.get(message.sourceUuid)?.id ||
message.conversationId,
window.ConversationController.get(message.sourceServiceId)
?.id || message.conversationId,
id: message.id,
received_at: message.received_at,
received_at_ms: Number(message.received_at_ms),
@@ -3501,7 +3505,7 @@ export function saveAttachmentFromMessage(
};
}
function clearInvitedUuidsForNewlyCreatedGroup(): ClearInvitedUuidsForNewlyCreatedGroupActionType {
function clearInvitedServiceIdsForNewlyCreatedGroup(): ClearInvitedServiceIdsForNewlyCreatedGroupActionType {
return { type: 'CLEAR_INVITED_SERVICE_IDS_FOR_NEWLY_CREATED_GROUP' };
}
function clearGroupCreationError(): ClearGroupCreationErrorActionType {
@@ -4130,7 +4134,7 @@ export function getEmptyState(): ConversationsStateType {
return {
conversationLookup: {},
conversationsByE164: {},
conversationsByUuid: {},
conversationsByServiceId: {},
conversationsByGroupId: {},
conversationsByUsername: {},
verificationDataByConversation: {},
@@ -4158,13 +4162,13 @@ export function updateConversationLookups(
): Pick<
ConversationsStateType,
| 'conversationsByE164'
| 'conversationsByUuid'
| 'conversationsByServiceId'
| 'conversationsByGroupId'
| 'conversationsByUsername'
> {
const result = {
conversationsByE164: state.conversationsByE164,
conversationsByUuid: state.conversationsByUuid,
conversationsByServiceId: state.conversationsByServiceId,
conversationsByGroupId: state.conversationsByGroupId,
conversationsByUsername: state.conversationsByUsername,
};
@@ -4172,11 +4176,17 @@ export function updateConversationLookups(
if (removed && removed.e164) {
result.conversationsByE164 = omit(result.conversationsByE164, removed.e164);
}
if (removed && removed.uuid) {
result.conversationsByUuid = omit(result.conversationsByUuid, removed.uuid);
if (removed && removed.serviceId) {
result.conversationsByServiceId = omit(
result.conversationsByServiceId,
removed.serviceId
);
}
if (removed && removed.pni) {
result.conversationsByUuid = omit(result.conversationsByUuid, removed.pni);
result.conversationsByServiceId = omit(
result.conversationsByServiceId,
removed.pni
);
}
if (removed && removed.groupId) {
result.conversationsByGroupId = omit(
@@ -4197,15 +4207,15 @@ export function updateConversationLookups(
[added.e164]: added,
};
}
if (added && added.uuid) {
result.conversationsByUuid = {
...result.conversationsByUuid,
[added.uuid]: added,
if (added && added.serviceId) {
result.conversationsByServiceId = {
...result.conversationsByServiceId,
[added.serviceId]: added,
};
}
if (added && added.pni) {
result.conversationsByUuid = {
...result.conversationsByUuid,
result.conversationsByServiceId = {
...result.conversationsByServiceId,
[added.pni]: added,
};
}
@@ -4285,12 +4295,14 @@ function getVerificationDataForConversation({
};
}
const existingUuids = distributionId
const existingServiceIds = distributionId
? existing.byDistributionId?.[distributionId]?.serviceIdsNeedingVerification
: existing.serviceIdsNeedingVerification;
const serviceIdsNeedingVerification: ReadonlyArray<ServiceIdString> =
Array.from(new Set([...(existingUuids || []), ...untrustedServiceIds]));
Array.from(
new Set([...(existingServiceIds || []), ...untrustedServiceIds])
);
return {
[conversationId]: {
@@ -4800,7 +4812,9 @@ export function reducer(
membersToRemove,
membersToAdd,
} = action.payload;
const removedUuids = new Set(isBlockList ? membersToAdd : membersToRemove);
const removedServiceIds = new Set(
isBlockList ? membersToAdd : membersToRemove
);
const nextVerificationData = visitListsInVerificationData(
state.verificationDataByConversation,
@@ -4808,7 +4822,7 @@ export function reducer(
if (listId === id) {
const serviceIdsNeedingVerification =
data.serviceIdsNeedingVerification.filter(
uuid => !removedUuids.has(uuid)
serviceId => !removedServiceIds.has(serviceId)
);
if (!serviceIdsNeedingVerification.length) {
@@ -4857,7 +4871,7 @@ export function reducer(
};
}
if (action.type === HIDE_MY_STORIES_FROM) {
const removedUuids = new Set(action.payload);
const removedServiceIds = new Set(action.payload);
const nextVerificationData = visitListsInVerificationData(
state.verificationDataByConversation,
@@ -4865,7 +4879,7 @@ export function reducer(
if (MY_STORY_ID === id) {
const serviceIdsNeedingVerification =
data.serviceIdsNeedingVerification.filter(
uuid => !removedUuids.has(uuid)
serviceId => !removedServiceIds.has(serviceId)
);
if (!serviceIdsNeedingVerification.length) {
@@ -4893,15 +4907,15 @@ export function reducer(
}
if (action.type === VIEWERS_CHANGED) {
const { listId, memberServiceIds } = action.payload;
const newUuids = new Set(memberServiceIds);
const newServiceIds = new Set(memberServiceIds);
const nextVerificationData = visitListsInVerificationData(
state.verificationDataByConversation,
(id, data): DistributionVerificationData | undefined => {
if (listId === id) {
const serviceIdsNeedingVerification =
data.serviceIdsNeedingVerification.filter(uuid =>
newUuids.has(uuid)
data.serviceIdsNeedingVerification.filter(serviceId =>
newServiceIds.has(serviceId)
);
if (!serviceIdsNeedingVerification.length) {
@@ -5928,7 +5942,7 @@ export function reducer(
if (!composer) {
assertDev(
false,
'Setting compose uuid fetch state with the composer closed is a no-op'
'Setting compose serviceId fetch state with the composer closed is a no-op'
);
return state;
}
@@ -5938,7 +5952,7 @@ export function reducer(
) {
assertDev(
false,
'Setting compose uuid fetch state at this step is a no-op'
'Setting compose serviceId fetch state at this step is a no-op'
);
return state;
}

View File

@@ -508,7 +508,7 @@ function showGV2MigrationDialog(
});
const invitedMemberIds = pendingMembersV2.map(
(item: GroupV2PendingMemberType) => item.uuid
(item: GroupV2PendingMemberType) => item.serviceId
);
dispatch({

View File

@@ -264,7 +264,7 @@ function showLightbox(opts: {
const authorId =
window.ConversationController.lookupOrCreate({
uuid: message.get('sourceUuid'),
serviceId: message.get('sourceServiceId'),
e164: message.get('source'),
reason: 'conversation_view.showLightBox',
})?.id || message.get('conversationId');

View File

@@ -142,7 +142,7 @@ function loadMediaItems(
attachments: message.attachments || [],
conversationId:
window.ConversationController.lookupOrCreate({
uuid: message.sourceUuid,
serviceId: message.sourceServiceId,
e164: message.source,
reason: 'conversation_view.showAllMedia',
})?.id || message.conversationId,

View File

@@ -14,6 +14,8 @@ import type {
} from '../../sql/Interface';
import dataInterface from '../../sql/Client';
import { makeLookup } from '../../util/makeLookup';
import { isNotNil } from '../../util/isNotNil';
import type { ServiceIdString } from '../../types/ServiceId';
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
import { useBoundActions } from '../../hooks/useBoundActions';
@@ -234,21 +236,19 @@ const doSearch = debounce(
const queryWords = [...segmenter.segment(query)]
.filter(word => word.isWordLike)
.map(word => word.segment);
const contactUuidsMatchingQuery = searchConversationTitles(
const contactServiceIdsMatchingQuery = searchConversationTitles(
allConversations,
queryWords
)
.filter(
conversation =>
isDirectConversation(conversation) && Boolean(conversation.uuid)
)
.map(conversation => conversation.uuid as string)
.filter(conversation => isDirectConversation(conversation))
.map(conversation => conversation.serviceId)
.filter(isNotNil)
.slice(0, MAX_MATCHING_CONTACTS);
const messages = await queryMessages({
query,
searchConversationId,
contactUuidsMatchingQuery,
contactServiceIdsMatchingQuery,
});
dispatch({
@@ -287,11 +287,11 @@ const doSearch = debounce(
async function queryMessages({
query,
searchConversationId,
contactUuidsMatchingQuery,
contactServiceIdsMatchingQuery,
}: {
query: string;
searchConversationId?: string;
contactUuidsMatchingQuery?: Array<string>;
contactServiceIdsMatchingQuery?: Array<ServiceIdString>;
}): Promise<Array<ClientSearchResultMessageType>> {
try {
const normalized = cleanSearchTerm(query);
@@ -303,13 +303,13 @@ async function queryMessages({
return dataSearchMessages({
query: normalized,
conversationId: searchConversationId,
contactUuidsMatchingQuery,
contactServiceIdsMatchingQuery,
});
}
return dataSearchMessages({
query: normalized,
contactUuidsMatchingQuery,
contactServiceIdsMatchingQuery,
});
} catch (e) {
return [];

View File

@@ -21,6 +21,7 @@ import type { StoryViewTargetType, StoryViewType } from '../../types/Stories';
import type { SyncType } from '../../jobs/helpers/syncHelpers';
import type { StoryDistributionIdString } from '../../types/StoryDistributionId';
import type { ServiceIdString } from '../../types/ServiceId';
import { isAciString } from '../../types/ServiceId';
import * as log from '../../logging/log';
import { TARGETED_CONVERSATION_CHANGED } from './conversations';
import { SIGNAL_ACI } from '../../types/SignalConversation';
@@ -87,7 +88,7 @@ export type StoryDataType = ReadonlyDeep<
| 'readStatus'
| 'sendStateByConversationId'
| 'source'
| 'sourceUuid'
| 'sourceServiceId'
| 'storyDistributionListId'
| 'timestamp'
| 'type'
@@ -393,13 +394,17 @@ function markStoryRead(
return;
}
const authorId = message.attributes.sourceUuid;
const authorId = message.attributes.sourceServiceId;
strictAssert(
authorId,
'markStoryRead: The message needs a sender to mark it read!'
);
strictAssert(
isAciString(authorId),
'markStoryRead: The message needs a sender ACI to mark it read!'
);
const isSignalOnboardingStory = message.get('sourceUuid') === SIGNAL_ACI;
const isSignalOnboardingStory = authorId === SIGNAL_ACI;
if (isSignalOnboardingStory) {
const updatedMessages = await markOnboardingStoryAsRead();
@@ -426,7 +431,7 @@ function markStoryRead(
messageId,
conversationId,
senderE164: message.attributes.source,
senderUuid: message.attributes.sourceUuid,
senderAci: authorId,
timestamp: message.attributes.sent_at,
isDirectConversation: false,
};
@@ -832,7 +837,7 @@ const getSelectedStoryDataForConversationId = (
item =>
item.conversationId === conversationId &&
!item.deletedForEveryone &&
(!onlyFromSelf || item.sourceUuid === ourAci)
(!onlyFromSelf || item.sourceServiceId === ourAci)
);
// Find the index of the storyId provided, or if none provided then find the
@@ -1528,7 +1533,7 @@ export function reducer(
'readStatus',
'sendStateByConversationId',
'source',
'sourceUuid',
'sourceServiceId',
'sourceDevice',
'storyDistributionListId',
'timestamp',

View File

@@ -287,7 +287,7 @@ function hideMyStoriesFrom(
},
{
toAdd: Array.from(toAdd),
toRemove: myStories.members.filter(uuid => !toAdd.has(uuid)),
toRemove: myStories.members.filter(serviceId => !toAdd.has(serviceId)),
}
);
@@ -309,7 +309,7 @@ function removeMembersFromDistributionList(
return async dispatch => {
if (!memberServiceIds.length) {
log.warn(
'storyDistributionLists.removeMembersFromDistributionList cannot remove a member without uuid',
'storyDistributionLists.removeMembersFromDistributionList cannot remove a member without serviceId',
listId
);
return;
@@ -436,21 +436,23 @@ function updateStoryViewers(
return;
}
const existingUuids = new Set<ServiceIdString>(storyDistribution.members);
const existingServiceIds = new Set<ServiceIdString>(
storyDistribution.members
);
const toAdd: Array<ServiceIdString> = [];
memberServiceIds.forEach(uuid => {
if (!existingUuids.has(uuid)) {
toAdd.push(uuid);
memberServiceIds.forEach(serviceId => {
if (!existingServiceIds.has(serviceId)) {
toAdd.push(serviceId);
}
});
const updatedUuids = new Set<ServiceIdString>(memberServiceIds);
const updatedServiceIds = new Set<ServiceIdString>(memberServiceIds);
const toRemove: Array<ServiceIdString> = [];
storyDistribution.members.forEach(uuid => {
if (!updatedUuids.has(uuid)) {
toRemove.push(uuid);
storyDistribution.members.forEach(serviceId => {
if (!updatedServiceIds.has(serviceId)) {
toRemove.push(serviceId);
}
});
@@ -562,8 +564,8 @@ export function reducer(
const memberServiceIds = new Set<ServiceIdString>(
existingDistributionList.memberServiceIds
);
membersToAdd.forEach(uuid => memberServiceIds.add(uuid));
membersToRemove.forEach(uuid => memberServiceIds.delete(uuid));
membersToAdd.forEach(serviceId => memberServiceIds.add(serviceId));
membersToRemove.forEach(serviceId => memberServiceIds.delete(serviceId));
return {
distributionLists: replaceIndex(state.distributionLists, listIndex, {

View File

@@ -98,8 +98,8 @@ export function getInitialState({
...conversations(),
conversationLookup: makeLookup(formattedConversations, 'id'),
conversationsByE164: makeLookup(formattedConversations, 'e164'),
conversationsByUuid: {
...makeLookup(formattedConversations, 'uuid'),
conversationsByServiceId: {
...makeLookup(formattedConversations, 'serviceId'),
...makeLookup(formattedConversations, 'pni'),
},
conversationsByGroupId: makeLookup(formattedConversations, 'groupId'),

View File

@@ -12,7 +12,7 @@ import {
getAttachmentUrlForPath,
getMessagePropStatus,
getSource,
getSourceUuid,
getSourceServiceId,
} from './message';
import {
getConversationByIdSelector,
@@ -36,7 +36,7 @@ export type VoiceNoteForPlayback = {
url: string | undefined;
type: 'incoming' | 'outgoing';
source: string | undefined;
sourceUuid: ServiceIdString | undefined;
sourceServiceId: ServiceIdString | undefined;
isPlayed: boolean;
messageIdForLogging: string;
timestamp: number;
@@ -60,15 +60,18 @@ export const selectVoiceNoteTitle = createSelector(
getIntl,
(ourNumber, ourAci, ourConversationId, conversationSelector, i18n) => {
return (
message: Pick<MessageAttributesType, 'type' | 'source' | 'sourceUuid'>
message: Pick<
MessageAttributesType,
'type' | 'source' | 'sourceServiceId'
>
) => {
const source = getSource(message, ourNumber);
const sourceUuid = getSourceUuid(message, ourAci);
const sourceServiceId = getSourceServiceId(message, ourAci);
const conversation =
!source && !sourceUuid
!source && !sourceServiceId
? conversationSelector(ourConversationId)
: conversationSelector(sourceUuid || source);
: conversationSelector(sourceServiceId || source);
return conversation.isMe ? i18n('icu:you') : conversation.title;
};
@@ -103,7 +106,7 @@ export function extractVoiceNoteForPlayback(
messageIdForLogging: getMessageIdForLogging(message),
timestamp: message.timestamp,
source: message.source,
sourceUuid: message.sourceUuid,
sourceServiceId: message.sourceServiceId,
};
}

View File

@@ -56,9 +56,11 @@ export const getByDistributionListConversationsStoppingSend = createSelector(
distributionListSelector(distributionId);
if (!currentDistribution) {
distributionData.serviceIdsNeedingVerification.forEach(uuid => {
conversationServiceIds.add(uuid);
});
distributionData.serviceIdsNeedingVerification.forEach(
serviceId => {
conversationServiceIds.add(serviceId);
}
);
return;
}
@@ -72,7 +74,7 @@ export const getByDistributionListConversationsStoppingSend = createSelector(
name: currentDistribution.name,
},
contacts: distributionData.serviceIdsNeedingVerification.map(
uuid => conversationSelector(uuid)
serviceId => conversationSelector(serviceId)
),
});
}
@@ -88,8 +90,8 @@ export const getByDistributionListConversationsStoppingSend = createSelector(
name: currentConversation.title,
}
: undefined,
contacts: Array.from(conversationServiceIds).map(uuid =>
conversationSelector(uuid)
contacts: Array.from(conversationServiceIds).map(serviceId =>
conversationSelector(serviceId)
),
});
}

View File

@@ -37,7 +37,7 @@ import {
import type { ContactNameColorType } from '../../types/Colors';
import { ContactNameColors } from '../../types/Colors';
import type { AvatarDataType } from '../../types/Avatar';
import type { ServiceIdString } from '../../types/ServiceId';
import type { AciString, ServiceIdString } from '../../types/ServiceId';
import { isInSystemContacts } from '../../util/isInSystemContacts';
import { isSignalConnection } from '../../util/getSignalConnections';
import { sortByTitle } from '../../util/sortByTitle';
@@ -109,10 +109,10 @@ export const getConversationLookup = createSelector(
}
);
export const getConversationsByUuid = createSelector(
export const getConversationsByServiceId = createSelector(
getConversations,
(state: ConversationsStateType): ConversationLookupType => {
return state.conversationsByUuid;
return state.conversationsByServiceId;
}
);
@@ -687,7 +687,10 @@ export const getFilteredComposeGroups = createSelector(
ConversationType & {
membersCount: number;
disabledReason: undefined;
memberships: ReadonlyArray<unknown>;
memberships: ReadonlyArray<{
aci: AciString;
isAdmin: boolean;
}>;
}
> => {
return filterAndSortConversationsAlphabetically(
@@ -801,13 +804,13 @@ export type GetConversationByIdType = (id?: string) => ConversationType;
export const getConversationSelector = createSelector(
getCachedSelectorForConversation,
getConversationLookup,
getConversationsByUuid,
getConversationsByServiceId,
getConversationsByE164,
getConversationsByGroupId,
(
selector: CachedConversationSelectorType,
byId: ConversationLookupType,
byUuid: ConversationLookupType,
byServiceId: ConversationLookupType,
byE164: ConversationLookupType,
byGroupId: ConversationLookupType
): GetConversationByIdType => {
@@ -816,9 +819,12 @@ export const getConversationSelector = createSelector(
return selector(undefined);
}
const onUuid = getOwn(byUuid, id.toLowerCase ? id.toLowerCase() : id);
if (onUuid) {
return selector(onUuid);
const onServiceId = getOwn(
byServiceId,
id.toLowerCase ? id.toLowerCase() : id
);
if (onServiceId) {
return selector(onServiceId);
}
const onE164 = getOwn(byE164, id);
if (onE164) {
@@ -847,11 +853,11 @@ export const getConversationByIdSelector = createSelector(
getOwn(conversationLookup, id)
);
export const getConversationByUuidSelector = createSelector(
getConversationsByUuid,
conversationsByUuid =>
(uuid: ServiceIdString): undefined | ConversationType =>
getOwn(conversationsByUuid, uuid)
export const getConversationByServiceIdSelector = createSelector(
getConversationsByServiceId,
conversationsByServiceId =>
(serviceId: ServiceIdString): undefined | ConversationType =>
getOwn(conversationsByServiceId, serviceId)
);
const getCachedConversationMemberColorsSelector = createSelector(
@@ -880,7 +886,7 @@ const getCachedConversationMemberColorsSelector = createSelector(
[...sortedGroupMembers]
.sort((left, right) =>
String(left.uuid) > String(right.uuid) ? 1 : -1
String(left.serviceId) > String(right.serviceId) ? 1 : -1
)
.forEach((member, i) => {
contactNameColors.set(
@@ -1017,7 +1023,7 @@ export const getConversationMessagesSelector = createSelector(
);
export const getInvitedContactsForNewlyCreatedGroup = createSelector(
getConversationsByUuid,
getConversationsByServiceId,
getConversations,
(
conversationLookup,
@@ -1075,7 +1081,7 @@ export const getGroupAdminsSelector = createSelector(
const admins: Array<ConversationType> = [];
memberships.forEach(membership => {
if (membership.isAdmin) {
const admin = conversationSelector(membership.uuid);
const admin = conversationSelector(membership.aci);
admins.push(admin);
}
});
@@ -1088,7 +1094,7 @@ export const getContactSelector = createSelector(
getConversationSelector,
conversationSelector => {
return (contactId: string) =>
pick(conversationSelector(contactId), 'id', 'title', 'uuid');
pick(conversationSelector(contactId), 'id', 'title', 'serviceId');
}
);

View File

@@ -60,10 +60,10 @@ const isRemoteConfigBucketEnabled = (
config: Readonly<ConfigMapType>,
name: ConfigKeyType,
e164: string | undefined,
uuid: AciString | undefined
aci: AciString | undefined
): boolean => {
const flagValue = config[name]?.value;
return innerIsBucketValueEnabled(name, flagValue, e164, uuid);
return innerIsBucketValueEnabled(name, flagValue, e164, aci);
};
export const getRemoteConfig = createSelector(

View File

@@ -216,16 +216,16 @@ export function getSourceDevice(
return sourceDevice || ourDeviceId;
}
export function getSourceUuid(
message: Pick<MessageAttributesType, 'type' | 'sourceUuid'>,
export function getSourceServiceId(
message: Pick<MessageAttributesType, 'type' | 'sourceServiceId'>,
ourAci: AciString | undefined
): ServiceIdString | undefined {
if (isIncoming(message)) {
return message.sourceUuid;
return message.sourceServiceId;
}
if (!isOutgoing(message)) {
log.warn(
'message.getSourceUuid: Called for non-incoming/non-outoing message'
'message.getSourceServiceId: Called for non-incoming/non-outoing message'
);
}
@@ -247,13 +247,13 @@ export function getContactId(
}: GetContactOptions
): string | undefined {
const source = getSource(message, ourNumber);
const sourceUuid = getSourceUuid(message, ourAci);
const sourceServiceId = getSourceServiceId(message, ourAci);
if (!source && !sourceUuid) {
if (!source && !sourceServiceId) {
return ourConversationId;
}
const conversation = conversationSelector(sourceUuid || source);
const conversation = conversationSelector(sourceServiceId || source);
return conversation.id;
}
@@ -268,13 +268,13 @@ export function getContact(
}: GetContactOptions
): ConversationType {
const source = getSource(message, ourNumber);
const sourceUuid = getSourceUuid(message, ourAci);
const sourceServiceId = getSourceServiceId(message, ourAci);
if (!source && !sourceUuid) {
if (!source && !sourceServiceId) {
return conversationSelector(ourConversationId);
}
return conversationSelector(sourceUuid || source);
return conversationSelector(sourceServiceId || source);
}
export function getConversation(
@@ -341,7 +341,7 @@ export const extractHydratedMentions = (
.filter(BodyRange.isMention)
.map(range => {
const { conversationSelector } = options;
const conversation = conversationSelector(range.mentionUuid);
const conversation = conversationSelector(range.mentionAci);
return {
...range,
@@ -484,7 +484,7 @@ const getPropsForStoryReplyContext = (
return undefined;
}
const contact = conversationSelector(storyReplyContext.authorUuid);
const contact = conversationSelector(storyReplyContext.authorAci);
const authorTitle = contact.firstName || contact.title;
const isFromMe = contact.id === ourConversationId;
@@ -527,7 +527,7 @@ export const getPropsForQuote = (
const {
author,
authorUuid,
authorAci,
id: sentAt,
isViewOnce,
isGiftBadge: isTargetGiftBadge,
@@ -536,7 +536,7 @@ export const getPropsForQuote = (
text = '',
} = quote;
const contact = conversationSelector(authorUuid || author);
const contact = conversationSelector(authorAci || author);
const authorId = contact.id;
const authorName = contact.name;
@@ -960,7 +960,7 @@ function getPropsForPaymentEvent(
{ conversationSelector }: GetPropsForBubbleOptions
): Omit<PaymentEventNotificationPropsType, 'i18n'> {
return {
sender: conversationSelector(message.sourceUuid),
sender: conversationSelector(message.sourceServiceId),
conversation: getConversation(message, conversationSelector),
event: message.payment,
};
@@ -1104,9 +1104,9 @@ function getPropsForTimerNotification(
);
}
const { expireTimer, fromSync, source, sourceUuid } = timerUpdate;
const { expireTimer, fromSync, source, sourceServiceId } = timerUpdate;
const disabled = !expireTimer;
const sourceId = sourceUuid || source;
const sourceId = sourceServiceId || source;
const { id: formattedContactId, title } = conversationSelector(sourceId);
// Pacify typescript
@@ -1447,7 +1447,7 @@ function getPropsForChangeNumberNotification(
{ conversationSelector }: GetPropsForBubbleOptions
): ChangeNumberNotificationProps {
return {
sender: conversationSelector(message.sourceUuid),
sender: conversationSelector(message.sourceServiceId),
timestamp: message.sent_at,
};
}
@@ -1500,7 +1500,7 @@ function getPropsForDeliveryIssue(
message: MessageWithUIFieldsType,
{ conversationSelector }: GetPropsForBubbleOptions
): DeliveryIssuePropsType {
const sender = conversationSelector(message.sourceUuid);
const sender = conversationSelector(message.sourceServiceId);
const conversation = getConversation(message, conversationSelector);
return {
@@ -1631,7 +1631,7 @@ export function getPropsForEmbeddedContact(
regionCode,
getAbsoluteAttachmentPath: getAttachmentUrlForPath,
firstNumber,
uuid: accountSelector(firstNumber),
serviceId: accountSelector(firstNumber),
});
}

View File

@@ -227,12 +227,12 @@ export const getMessageSearchResultSelector = createSelector(
return undefined;
}
const { conversationId, source, sourceUuid, type } = message;
const { conversationId, source, sourceServiceId, type } = message;
let from: ConversationType;
let to: ConversationType;
if (type === 'incoming') {
from = conversationSelector(sourceUuid || source);
from = conversationSelector(sourceServiceId || source);
to = conversationSelector(conversationId);
if (from === to) {
to = conversationSelector(ourConversationId);

View File

@@ -68,14 +68,14 @@ function sortByRecencyAndUnread(
storyB: ConversationStoryType
): number {
if (
storyA.storyView.sender.uuid === SIGNAL_ACI &&
storyA.storyView.sender.serviceId === SIGNAL_ACI &&
storyA.storyView.isUnread
) {
return -1;
}
if (
storyB.storyView.sender.uuid === SIGNAL_ACI &&
storyB.storyView.sender.serviceId === SIGNAL_ACI &&
storyB.storyView.isUnread
) {
return 1;
@@ -161,21 +161,24 @@ export function getStoryView(
ourConversationId: string | undefined,
story: StoryDataType
): StoryViewType {
const sender = pick(conversationSelector(story.sourceUuid || story.source), [
'acceptedMessageRequest',
'avatarPath',
'badges',
'color',
'firstName',
'hideStory',
'id',
'isMe',
'name',
'profileName',
'sharedGroupNames',
'title',
'uuid',
]);
const sender = pick(
conversationSelector(story.sourceServiceId || story.source),
[
'acceptedMessageRequest',
'avatarPath',
'badges',
'color',
'firstName',
'hideStory',
'id',
'isMe',
'name',
'profileName',
'sharedGroupNames',
'title',
'serviceId',
]
);
const {
attachment,
@@ -213,7 +216,7 @@ export function getStoryView(
}
const messageIdForLogging = getMessageIdForLogging({
...pick(story, 'type', 'sourceUuid', 'sourceDevice'),
...pick(story, 'type', 'sourceServiceId', 'sourceDevice'),
sent_at: story.timestamp,
});
@@ -242,9 +245,10 @@ export function getConversationStory(
ourConversationId: string | undefined,
story: StoryDataType
): ConversationStoryType {
const sender = pick(conversationSelector(story.sourceUuid || story.source), [
'id',
]);
const sender = pick(
conversationSelector(story.sourceServiceId || story.source),
['id']
);
const conversation = pick(conversationSelector(story.conversationId), [
'acceptedMessageRequest',
@@ -295,7 +299,7 @@ export const getStoryReplies = createSelector(
const conversation =
reply.type === 'outgoing'
? me
: conversationSelector(reply.sourceUuid || reply.source);
: conversationSelector(reply.sourceServiceId || reply.source);
return {
author: getAvatarData(conversation),
@@ -342,7 +346,7 @@ export const getStories = createSelector(
return;
}
const isSignalStory = story.sourceUuid === SIGNAL_ACI;
const isSignalStory = story.sourceServiceId === SIGNAL_ACI;
// if for some reason this story is already expired (bug)
// log it and skip it. Unless it's the onboarding story, that story
@@ -352,7 +356,7 @@ export const getStories = createSelector(
(calculateExpirationTimestamp(story) ?? 0) < Date.now()
) {
const messageIdForLogging = getMessageIdForLogging({
...pick(story, 'type', 'sourceUuid', 'sourceDevice'),
...pick(story, 'type', 'sourceServiceId', 'sourceDevice'),
sent_at: story.timestamp,
});
log.warn('selectors/getStories: story already expired', {

View File

@@ -17,6 +17,7 @@ import type {
ActiveCallType,
GroupCallRemoteParticipantType,
} from '../../types/Calling';
import { isAciString } from '../../types/ServiceId';
import type { AciString } from '../../types/ServiceId';
import { CallMode, CallState } from '../../types/Calling';
import type { StateType } from '../reducer';
@@ -131,7 +132,7 @@ const mapStateToActiveCallProp = (
(aci: AciString) => undefined | ConversationType
>(aci => {
const convoForAci = window.ConversationController.lookupOrCreate({
uuid: aci,
serviceId: aci,
reason: 'CallManager.mapStateToActiveCallProp',
});
return convoForAci ? conversationSelector(convoForAci.id) : undefined;
@@ -165,6 +166,11 @@ const mapStateToActiveCallProp = (
return;
}
strictAssert(
isAciString(conversation.serviceId),
'Conversation must have aci'
);
return {
...baseResult,
callEndedReason: call.callEndedReason,
@@ -176,7 +182,7 @@ const mapStateToActiveCallProp = (
hasRemoteVideo: Boolean(call.hasRemoteVideo),
presenting: Boolean(call.isSharingScreen),
title: conversation.title,
uuid: conversation.uuid,
serviceId: conversation.serviceId,
},
],
};
@@ -199,9 +205,9 @@ const mapStateToActiveCallProp = (
} = call;
for (let i = 0; i < memberships.length; i += 1) {
const { uuid } = memberships[i];
const { aci } = memberships[i];
const member = conversationSelector(uuid);
const member = conversationSelector(aci);
if (!member) {
log.error('Group member has no corresponding conversation');
continue;

View File

@@ -171,7 +171,7 @@ const mapStateToProps = (state: StateType, props: ExternalProps) => {
ourConversationId: getUserConversationId(state),
})
: undefined,
quotedMessageAuthorUuid: quotedMessage?.quote?.authorUuid,
quotedMessageAuthorAci: quotedMessage?.quote?.authorAci,
quotedMessageSentAt: quotedMessage?.quote?.id,
// Emojis
recentEmojis,
@@ -201,7 +201,7 @@ const mapStateToProps = (state: StateType, props: ExternalProps) => {
draftText: dropNull(draftText),
draftBodyRanges: draftBodyRanges?.map(bodyRange => {
if (BodyRange.isMention(bodyRange)) {
const mentionConvo = conversationSelector(bodyRange.mentionUuid);
const mentionConvo = conversationSelector(bodyRange.mentionAci);
return {
...bodyRange,

View File

@@ -29,7 +29,7 @@ const mapStateToProps = (state: StateType): PropsDataType => {
let isAdmin = false;
if (contact && currentConversation && currentConversation.memberships) {
currentConversation.memberships.forEach(membership => {
if (membership.uuid === contact.uuid) {
if (membership.aci === contact.serviceId) {
isMember = true;
isAdmin = membership.isAdmin;
}

View File

@@ -11,7 +11,7 @@ import type { StateProps } from '../../components/conversation/conversation-deta
import { ConversationDetails } from '../../components/conversation/conversation-details/ConversationDetails';
import {
getConversationByIdSelector,
getConversationByUuidSelector,
getConversationByServiceIdSelector,
getAllComposableConversations,
} from '../selectors/conversations';
import { getGroupMemberships } from '../../util/getGroupMemberships';
@@ -74,10 +74,11 @@ const mapStateToProps = (
Boolean(conversation.groupLink) &&
conversation.accessControlAddFromInviteLink !== ACCESS_ENUM.UNSATISFIABLE;
const conversationByUuidSelector = getConversationByUuidSelector(state);
const conversationByServiceIdSelector =
getConversationByServiceIdSelector(state);
const groupMemberships = getGroupMemberships(
conversation,
conversationByUuidSelector
conversationByServiceIdSelector
);
const badges = getBadgesSelector(state)(conversation.badges);
@@ -88,7 +89,7 @@ const mapStateToProps = (
c =>
c.type === 'group' &&
(c.memberships ?? []).some(
member => member.uuid === conversation.uuid
member => member.aci === conversation.serviceId
)
)
: [];

View File

@@ -12,7 +12,7 @@ import {
} from '../../components/conversation/ConversationHeader';
import { getPreferredBadgeSelector } from '../selectors/badges';
import {
getConversationByUuidSelector,
getConversationByServiceIdSelector,
getConversationSelector,
getHasPanelOpen,
isMissingRequiredProfileSharing,
@@ -113,10 +113,12 @@ export function SmartConversationHeader({ id }: OwnProps): JSX.Element {
const { searchInConversation } = useSearchActions();
const { viewUserStories } = useStoriesActions();
const conversationByUuidSelector = useSelector(getConversationByUuidSelector);
const conversationByServiceIdSelector = useSelector(
getConversationByServiceIdSelector
);
const groupMemberships = getGroupMemberships(
conversation,
conversationByUuidSelector
conversationByServiceIdSelector
);
const cannotLeaveBecauseYouAreLastAdmin =
getCannotLeaveBecauseYouAreLastAdmin(groupMemberships.memberships, isAdmin);

View File

@@ -318,7 +318,10 @@ function PanelElement({
i18n={i18n}
onSendMessage={() => {
if (signalAccount) {
startConversation(signalAccount.phoneNumber, signalAccount.uuid);
startConversation(
signalAccount.phoneNumber,
signalAccount.serviceId
);
}
}}
/>

View File

@@ -9,7 +9,7 @@ import { assertDev } from '../../util/assert';
import { getGroupMemberships } from '../../util/getGroupMemberships';
import {
getConversationByIdSelector,
getConversationByUuidSelector,
getConversationByServiceIdSelector,
} from '../selectors/conversations';
import { getIntl, getTheme } from '../selectors/user';
import { getPreferredBadgeSelector } from '../selectors/badges';
@@ -26,7 +26,9 @@ export function SmartGV1Members({ conversationId }: PropsType): JSX.Element {
const { showContactModal } = useGlobalModalActions();
const conversationSelector = useSelector(getConversationByIdSelector);
const conversationByUuidSelector = useSelector(getConversationByUuidSelector);
const conversationByServiceIdSelector = useSelector(
getConversationByServiceIdSelector
);
const conversation = conversationSelector(conversationId);
assertDev(
@@ -36,7 +38,7 @@ export function SmartGV1Members({ conversationId }: PropsType): JSX.Element {
const { memberships } = getGroupMemberships(
conversation,
conversationByUuidSelector
conversationByServiceIdSelector
);
return (

View File

@@ -11,7 +11,7 @@ import { getIntl, getTheme } from '../selectors/user';
import { getPreferredBadgeSelector } from '../selectors/badges';
import {
getConversationByIdSelector,
getConversationByUuidSelector,
getConversationByServiceIdSelector,
} from '../selectors/conversations';
import { getGroupMemberships } from '../../util/getGroupMemberships';
import { assertDev } from '../../util/assert';
@@ -27,7 +27,8 @@ const mapStateToProps = (
props: SmartPendingInvitesProps
): PropsDataType => {
const conversationSelector = getConversationByIdSelector(state);
const conversationByUuidSelector = getConversationByUuidSelector(state);
const conversationByServiceIdSelector =
getConversationByServiceIdSelector(state);
const conversation = conversationSelector(props.conversationId);
assertDev(
@@ -37,7 +38,7 @@ const mapStateToProps = (
return {
...props,
...getGroupMemberships(conversation, conversationByUuidSelector),
...getGroupMemberships(conversation, conversationByServiceIdSelector),
conversation,
getPreferredBadge: getPreferredBadgeSelector(state),
i18n: getIntl(state),

View File

@@ -10,7 +10,7 @@ import { StoriesSettingsModal } from '../../components/StoriesSettingsModal';
import {
getAllSignalConnections,
getCandidateContactsForNewGroup,
getConversationByUuidSelector,
getConversationByServiceIdSelector,
getGroupStories,
getMe,
} from '../selectors/conversations';
@@ -48,7 +48,9 @@ export function SmartStoriesSettingsModal(): JSX.Element | null {
const distributionLists = useSelector(getDistributionListsWithMembers);
const groupStories = useSelector(getGroupStories);
const getConversationByUuid = useSelector(getConversationByUuidSelector);
const getConversationByServiceId = useSelector(
getConversationByServiceIdSelector
);
const theme = useSelector(getTheme);
return (
@@ -61,7 +63,7 @@ export function SmartStoriesSettingsModal(): JSX.Element | null {
getPreferredBadge={getPreferredBadge}
i18n={i18n}
me={me}
getConversationByUuid={getConversationByUuid}
getConversationByServiceId={getConversationByServiceId}
onDeleteList={deleteDistributionList}
toggleGroupsForStorySend={toggleGroupsForStorySend}
onDistributionListCreated={createDistributionList}

View File

@@ -19,7 +19,7 @@ import type { ConversationType } from '../ducks/conversations';
import { getIntl, getTheme } from '../selectors/user';
import {
getMessages,
getConversationByUuidSelector,
getConversationByServiceIdSelector,
getConversationMessagesSelector,
getConversationSelector,
getConversationsByTitleSelector,
@@ -139,11 +139,12 @@ const getWarning = (
return undefined;
}
const getConversationByUuid = getConversationByUuidSelector(state);
const getConversationByServiceId =
getConversationByServiceIdSelector(state);
const { memberships } = getGroupMemberships(
conversation,
getConversationByUuid
getConversationByServiceId
);
const groupNameCollisions = getCollisionsFromMemberships(memberships);
const hasGroupMembersWithSameName = !isEmpty(groupNameCollisions);
@@ -174,7 +175,7 @@ const getContactSpoofingReview = (
}
const conversationSelector = getConversationSelector(state);
const getConversationByUuid = getConversationByUuidSelector(state);
const getConversationByServiceId = getConversationByServiceIdSelector(state);
const currentConversation = conversationSelector(selectedConversationId);
@@ -194,7 +195,7 @@ const getContactSpoofingReview = (
);
const { memberships } = getGroupMemberships(
currentConversation,
getConversationByUuid
getConversationByServiceId
);
const groupNameCollisions = getCollisionsFromMemberships(memberships);