Migrate schema to service ids
This commit is contained in:
parent
71958f8a01
commit
8b0da36caa
258 changed files with 4795 additions and 2613 deletions
|
@ -56,7 +56,7 @@
|
|||
};
|
||||
|
||||
window.ConversationController = window.ConversationController || {};
|
||||
window.ConversationController.isSignalConversation = () => false;
|
||||
window.ConversationController.isSignalConversationId = () => false;
|
||||
window.ConversationController.onConvoMessageMount = noop;
|
||||
window.getPreferredSystemLocales = () => ['en'];
|
||||
window.getResolvedMessagesLocaleDirection = () => 'ltr';
|
||||
|
|
|
@ -92,8 +92,9 @@
|
|||
"@react-aria/utils": "3.16.0",
|
||||
"@react-spring/web": "9.5.5",
|
||||
"@signalapp/better-sqlite3": "8.4.3",
|
||||
"@signalapp/libsignal-client": "0.29.1",
|
||||
"@signalapp/libsignal-client": "0.30.2",
|
||||
"@signalapp/ringrtc": "2.30.0",
|
||||
"@signalapp/windows-dummy-keystroke": "1.0.0",
|
||||
"@types/fabric": "4.5.3",
|
||||
"backbone": "1.4.0",
|
||||
"blob-util": "2.0.2",
|
||||
|
@ -180,7 +181,6 @@
|
|||
"uuid": "3.3.2",
|
||||
"uuid-browser": "3.1.0",
|
||||
"websocket": "1.0.34",
|
||||
"@signalapp/windows-dummy-keystroke": "1.0.0",
|
||||
"zod": "3.21.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -195,7 +195,7 @@
|
|||
"@electron/fuses": "1.5.0",
|
||||
"@formatjs/intl": "2.6.7",
|
||||
"@mixer/parallel-prettier": "2.0.3",
|
||||
"@signalapp/mock-server": "3.2.3",
|
||||
"@signalapp/mock-server": "4.0.1",
|
||||
"@storybook/addon-a11y": "6.5.6",
|
||||
"@storybook/addon-actions": "6.5.6",
|
||||
"@storybook/addon-controls": "6.5.6",
|
||||
|
|
|
@ -188,7 +188,7 @@ message GroupChange {
|
|||
}
|
||||
|
||||
|
||||
bytes sourceUuid = 1; // Who made the change
|
||||
bytes sourceUserId = 1; // Who made the change
|
||||
uint32 version = 2; // The change version number
|
||||
repeated AddMemberAction addMembers = 3; // Members added
|
||||
repeated DeleteMemberAction deleteMembers = 4; // Members deleted
|
||||
|
|
|
@ -136,7 +136,7 @@ message AccountRecord {
|
|||
|
||||
message PinnedConversation {
|
||||
message Contact {
|
||||
optional string uuid = 1;
|
||||
optional string serviceId = 1;
|
||||
optional string e164 = 2;
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,9 @@ export async function populateConversationWithMessages({
|
|||
schemaVersion: window.Signal.Types.Message.CURRENT_SCHEMA_VERSION,
|
||||
received_at: incrementMessageCounter(),
|
||||
readStatus: isUnread ? ReadStatus.Unread : ReadStatus.Read,
|
||||
sourceUuid: isIncoming ? conversation.getCheckedServiceId('CI') : ourAci,
|
||||
sourceServiceId: isIncoming
|
||||
? conversation.getCheckedServiceId('CI')
|
||||
: ourAci,
|
||||
...(isIncoming
|
||||
? {}
|
||||
: {
|
||||
|
|
|
@ -22,11 +22,12 @@ import { maybeDeriveGroupV2Id } from './groups';
|
|||
import { assertDev, strictAssert } from './util/assert';
|
||||
import { drop } from './util/drop';
|
||||
import { isGroupV1, isGroupV2 } from './util/whatTypeOfConversation';
|
||||
import type { ServiceIdString } from './types/ServiceId';
|
||||
import type { ServiceIdString, AciString, PniString } from './types/ServiceId';
|
||||
import {
|
||||
isServiceIdString,
|
||||
normalizeAci,
|
||||
normalizePni,
|
||||
normalizeServiceId,
|
||||
} from './types/ServiceId';
|
||||
import { sleep } from './util/sleep';
|
||||
import { isNotNil } from './util/isNotNil';
|
||||
|
@ -40,7 +41,7 @@ import { countAllConversationsUnreadStats } from './util/countUnreadStats';
|
|||
|
||||
type ConvoMatchType =
|
||||
| {
|
||||
key: 'uuid' | 'pni';
|
||||
key: 'serviceId' | 'pni';
|
||||
value: ServiceIdString | undefined;
|
||||
match: ConversationModel | undefined;
|
||||
}
|
||||
|
@ -55,7 +56,7 @@ const { hasOwnProperty } = Object.prototype;
|
|||
function applyChangeToConversation(
|
||||
conversation: ConversationModel,
|
||||
suggestedChange: Partial<
|
||||
Pick<ConversationAttributesType, 'uuid' | 'e164' | 'pni'>
|
||||
Pick<ConversationAttributesType, 'serviceId' | 'e164' | 'pni'>
|
||||
>
|
||||
) {
|
||||
const change = { ...suggestedChange };
|
||||
|
@ -65,29 +66,29 @@ function applyChangeToConversation(
|
|||
change.pni = undefined;
|
||||
}
|
||||
|
||||
// If we have a PNI but not an ACI, then the PNI will go in the UUID field
|
||||
// Tricky: We need a special check here, because the PNI can be in the uuid slot
|
||||
// If we have a PNI but not an ACI, then the PNI will go in the serviceId field
|
||||
// Tricky: We need a special check here, because the PNI can be in the serviceId slot
|
||||
if (
|
||||
change.pni &&
|
||||
!change.uuid &&
|
||||
(!conversation.get('uuid') ||
|
||||
conversation.get('uuid') === conversation.get('pni'))
|
||||
!change.serviceId &&
|
||||
(!conversation.getServiceId() ||
|
||||
conversation.getServiceId() === conversation.getPni())
|
||||
) {
|
||||
change.uuid = change.pni;
|
||||
change.serviceId = change.pni;
|
||||
}
|
||||
|
||||
// If we're clearing a PNI, but we didn't have an ACI - we need to clear UUID field
|
||||
// If we're clearing a PNI, but we didn't have an ACI - we need to clear serviceId field
|
||||
if (
|
||||
!change.uuid &&
|
||||
!change.serviceId &&
|
||||
hasOwnProperty.call(change, 'pni') &&
|
||||
!change.pni &&
|
||||
conversation.get('uuid') === conversation.get('pni')
|
||||
conversation.getServiceId() === conversation.getPni()
|
||||
) {
|
||||
change.uuid = undefined;
|
||||
change.serviceId = undefined;
|
||||
}
|
||||
|
||||
if (hasOwnProperty.call(change, 'uuid')) {
|
||||
conversation.updateUuid(change.uuid);
|
||||
if (hasOwnProperty.call(change, 'serviceId')) {
|
||||
conversation.updateServiceId(change.serviceId);
|
||||
}
|
||||
if (hasOwnProperty.call(change, 'e164')) {
|
||||
conversation.updateE164(change.e164);
|
||||
|
@ -289,7 +290,7 @@ export class ConversationController {
|
|||
if (type === 'group') {
|
||||
conversation = this._conversations.add({
|
||||
id,
|
||||
uuid: undefined,
|
||||
serviceId: undefined,
|
||||
e164: undefined,
|
||||
groupId: identifier,
|
||||
type,
|
||||
|
@ -299,7 +300,7 @@ export class ConversationController {
|
|||
} else if (isServiceIdString(identifier)) {
|
||||
conversation = this._conversations.add({
|
||||
id,
|
||||
uuid: identifier,
|
||||
serviceId: identifier,
|
||||
e164: undefined,
|
||||
groupId: undefined,
|
||||
type,
|
||||
|
@ -309,7 +310,7 @@ export class ConversationController {
|
|||
} else {
|
||||
conversation = this._conversations.add({
|
||||
id,
|
||||
uuid: undefined,
|
||||
serviceId: undefined,
|
||||
e164: identifier,
|
||||
groupId: undefined,
|
||||
type,
|
||||
|
@ -455,12 +456,8 @@ export class ConversationController {
|
|||
return conversation;
|
||||
}
|
||||
|
||||
isSignalConversation(uuidOrId: string): boolean {
|
||||
if (uuidOrId === SIGNAL_ACI) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return this._signalConversationId === uuidOrId;
|
||||
isSignalConversationId(conversationId: string): boolean {
|
||||
return this._signalConversationId === conversationId;
|
||||
}
|
||||
|
||||
areWePrimaryDevice(): boolean {
|
||||
|
@ -469,7 +466,7 @@ export class ConversationController {
|
|||
return ourDeviceId === 1;
|
||||
}
|
||||
|
||||
// Note: If you don't know what kind of UUID it is, put it in the 'aci' param.
|
||||
// Note: If you don't know what kind of serviceId it is, put it in the 'aci' param.
|
||||
maybeMergeContacts({
|
||||
aci: providedAci,
|
||||
e164,
|
||||
|
@ -478,9 +475,9 @@ export class ConversationController {
|
|||
fromPniSignature,
|
||||
mergeOldAndNew = safeCombineConversations,
|
||||
}: {
|
||||
aci?: string;
|
||||
aci?: AciString;
|
||||
e164?: string;
|
||||
pni?: string;
|
||||
pni?: PniString;
|
||||
reason: string;
|
||||
fromPniSignature?: boolean;
|
||||
mergeOldAndNew?: (options: SafeCombineConversationsParams) => Promise<void>;
|
||||
|
@ -500,8 +497,7 @@ export class ConversationController {
|
|||
}
|
||||
const logId = `maybeMergeContacts/${reason}/${dataProvided.join(',')}`;
|
||||
|
||||
const aci =
|
||||
providedAci && providedAci !== providedPni
|
||||
const aci = providedAci
|
||||
? normalizeAci(providedAci, 'maybeMergeContacts.aci')
|
||||
: undefined;
|
||||
const pni = providedPni
|
||||
|
@ -517,7 +513,7 @@ export class ConversationController {
|
|||
|
||||
const matches: Array<ConvoMatchType> = [
|
||||
{
|
||||
key: 'uuid',
|
||||
key: 'serviceId',
|
||||
value: aci,
|
||||
match: window.ConversationController.get(aci),
|
||||
},
|
||||
|
@ -568,26 +564,26 @@ export class ConversationController {
|
|||
);
|
||||
targetConversation = match;
|
||||
}
|
||||
// Tricky: PNI can end up in UUID slot, so we need to special-case it
|
||||
// Tricky: PNI can end up in serviceId slot, so we need to special-case it
|
||||
if (
|
||||
!targetConversation &&
|
||||
unused.key === 'uuid' &&
|
||||
unused.key === 'serviceId' &&
|
||||
match.get(unused.key) === pni
|
||||
) {
|
||||
log.info(
|
||||
`${logId}: Match on ${key} has uuid matching incoming pni, ` +
|
||||
`${logId}: Match on ${key} has serviceId matching incoming pni, ` +
|
||||
`so it will be our target conversation - ${match.idForLogging()}`
|
||||
);
|
||||
targetConversation = match;
|
||||
}
|
||||
// Tricky: PNI can end up in UUID slot, so we need to special-case it
|
||||
// Tricky: PNI can end up in serviceId slot, so we need to special-case it
|
||||
if (
|
||||
!targetConversation &&
|
||||
unused.key === 'uuid' &&
|
||||
match.get(unused.key) === match.get('pni')
|
||||
unused.key === 'serviceId' &&
|
||||
match.get(unused.key) === match.getPni()
|
||||
) {
|
||||
log.info(
|
||||
`${logId}: Match on ${key} has pni/uuid which are the same value, ` +
|
||||
`${logId}: Match on ${key} has pni/serviceId which are the same value, ` +
|
||||
`so it will be our target conversation - ${match.idForLogging()}`
|
||||
);
|
||||
targetConversation = match;
|
||||
|
@ -640,20 +636,21 @@ export class ConversationController {
|
|||
);
|
||||
const change: Pick<
|
||||
Partial<ConversationAttributesType>,
|
||||
'uuid' | 'e164' | 'pni'
|
||||
'serviceId' | 'e164' | 'pni'
|
||||
> = {
|
||||
[key]: undefined,
|
||||
};
|
||||
// When the PNI is being used in the uuid field alone, we need to clear it
|
||||
if ((key === 'pni' || key === 'e164') && match.get('uuid') === pni) {
|
||||
change.uuid = undefined;
|
||||
// When the PNI is being used in the serviceId field alone, we need to clear it
|
||||
if ((key === 'pni' || key === 'e164') && match.getServiceId() === pni) {
|
||||
change.serviceId = undefined;
|
||||
}
|
||||
applyChangeToConversation(match, change);
|
||||
|
||||
// Note: The PNI check here is just to be bulletproof; if we know a UUID is a PNI,
|
||||
// then that should be put in the UUID field as well!
|
||||
// Note: The PNI check here is just to be bulletproof; if we know a
|
||||
// serviceId is a PNI, then that should be put in the serviceId field
|
||||
// as well!
|
||||
const willMerge =
|
||||
!match.get('uuid') && !match.get('e164') && !match.get('pni');
|
||||
!match.getServiceId() && !match.get('e164') && !match.getPni();
|
||||
|
||||
applyChangeToConversation(targetConversation, {
|
||||
[key]: value,
|
||||
|
@ -705,7 +702,7 @@ export class ConversationController {
|
|||
log.info(`${logId}: Creating a new conversation with all inputs`);
|
||||
|
||||
// This is not our precedence for lookup, but it ensures that the PNI gets into the
|
||||
// uuid slot if we have no ACI.
|
||||
// serviceId slot if we have no ACI.
|
||||
const identifier = aci || pni || e164;
|
||||
strictAssert(identifier, `${logId}: identifier must be truthy!`);
|
||||
|
||||
|
@ -716,73 +713,75 @@ export class ConversationController {
|
|||
}
|
||||
|
||||
/**
|
||||
* Given a UUID and/or an E164, returns a string representing the local
|
||||
* Given a serviceId and/or an E164, returns a string representing the local
|
||||
* database id of the given contact. Will create a new conversation if none exists;
|
||||
* otherwise will return whatever is found.
|
||||
*/
|
||||
lookupOrCreate({
|
||||
e164,
|
||||
uuid,
|
||||
serviceId,
|
||||
reason,
|
||||
}: {
|
||||
e164?: string | null;
|
||||
uuid?: string | null;
|
||||
serviceId?: ServiceIdString | null;
|
||||
reason: string;
|
||||
}): ConversationModel | undefined {
|
||||
const normalizedUuid = uuid ? uuid.toLowerCase() : undefined;
|
||||
const identifier = normalizedUuid || e164;
|
||||
const normalizedServiceId = serviceId
|
||||
? normalizeServiceId(serviceId, 'ConversationController.lookupOrCreate')
|
||||
: undefined;
|
||||
const identifier = normalizedServiceId || e164;
|
||||
|
||||
if ((!e164 && !uuid) || !identifier) {
|
||||
if ((!e164 && !serviceId) || !identifier) {
|
||||
log.warn(
|
||||
`lookupOrCreate: Called with neither e164 nor uuid! reason: ${reason}`
|
||||
`lookupOrCreate: Called with neither e164 nor serviceId! reason: ${reason}`
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const convoE164 = this.get(e164);
|
||||
const convoUuid = this.get(normalizedUuid);
|
||||
const convoServiceId = this.get(normalizedServiceId);
|
||||
|
||||
// 1. Handle no match at all
|
||||
if (!convoE164 && !convoUuid) {
|
||||
if (!convoE164 && !convoServiceId) {
|
||||
log.info('lookupOrCreate: Creating new contact, no matches found');
|
||||
const newConvo = this.getOrCreate(identifier, 'private');
|
||||
|
||||
// `identifier` would resolve to uuid if we had both, so fix up e164
|
||||
if (normalizedUuid && e164) {
|
||||
// `identifier` would resolve to serviceId if we had both, so fix up e164
|
||||
if (normalizedServiceId && e164) {
|
||||
newConvo.updateE164(e164);
|
||||
}
|
||||
|
||||
return newConvo;
|
||||
}
|
||||
|
||||
// 2. Handle match on only UUID
|
||||
if (!convoE164 && convoUuid) {
|
||||
return convoUuid;
|
||||
// 2. Handle match on only service id
|
||||
if (!convoE164 && convoServiceId) {
|
||||
return convoServiceId;
|
||||
}
|
||||
|
||||
// 3. Handle match on only E164
|
||||
if (convoE164 && !convoUuid) {
|
||||
if (convoE164 && !convoServiceId) {
|
||||
return convoE164;
|
||||
}
|
||||
|
||||
// For some reason, TypeScript doesn't believe that we can trust that these two values
|
||||
// are truthy by this point. So we'll throw if that isn't the case.
|
||||
if (!convoE164 || !convoUuid) {
|
||||
if (!convoE164 || !convoServiceId) {
|
||||
throw new Error(
|
||||
`lookupOrCreate: convoE164 or convoUuid are falsey but should both be true! reason: ${reason}`
|
||||
`lookupOrCreate: convoE164 or convoServiceId are falsey but should both be true! reason: ${reason}`
|
||||
);
|
||||
}
|
||||
|
||||
// 4. If the two lookups agree, return that conversation
|
||||
if (convoE164 === convoUuid) {
|
||||
return convoUuid;
|
||||
if (convoE164 === convoServiceId) {
|
||||
return convoServiceId;
|
||||
}
|
||||
|
||||
// 5. If the two lookups disagree, log and return the UUID match
|
||||
// 5. If the two lookups disagree, log and return the service id match
|
||||
log.warn(
|
||||
`lookupOrCreate: Found a split contact - UUID ${normalizedUuid} and E164 ${e164}. Returning UUID match. reason: ${reason}`
|
||||
`lookupOrCreate: Found a split contact - service id ${normalizedServiceId} and E164 ${e164}. Returning service id match. reason: ${reason}`
|
||||
);
|
||||
return convoUuid;
|
||||
return convoServiceId;
|
||||
}
|
||||
|
||||
checkForConflicts(): Promise<void> {
|
||||
|
@ -795,7 +794,7 @@ export class ConversationController {
|
|||
// run on `_combineConversationsQueue` queue and we don't want deadlocks.
|
||||
private async doCheckForConflicts(): Promise<void> {
|
||||
log.info('checkForConflicts: starting...');
|
||||
const byUuid = Object.create(null);
|
||||
const byServiceId = Object.create(null);
|
||||
const byE164 = Object.create(null);
|
||||
const byGroupV2Id = Object.create(null);
|
||||
// We also want to find duplicate GV1 IDs. You might expect to see a "byGroupV1Id" map
|
||||
|
@ -812,16 +811,18 @@ export class ConversationController {
|
|||
'Expected conversation to be found in array during iteration'
|
||||
);
|
||||
|
||||
const uuid = conversation.get('uuid');
|
||||
const pni = conversation.get('pni');
|
||||
const serviceId = conversation.getServiceId();
|
||||
const pni = conversation.getPni();
|
||||
const e164 = conversation.get('e164');
|
||||
|
||||
if (uuid) {
|
||||
const existing = byUuid[uuid];
|
||||
if (serviceId) {
|
||||
const existing = byServiceId[serviceId];
|
||||
if (!existing) {
|
||||
byUuid[uuid] = conversation;
|
||||
byServiceId[serviceId] = conversation;
|
||||
} else {
|
||||
log.warn(`checkForConflicts: Found conflict with uuid ${uuid}`);
|
||||
log.warn(
|
||||
`checkForConflicts: Found conflict with serviceId ${serviceId}`
|
||||
);
|
||||
|
||||
// Keep the newer one if it has an e164, otherwise keep existing
|
||||
if (conversation.get('e164')) {
|
||||
|
@ -831,7 +832,7 @@ export class ConversationController {
|
|||
current: conversation,
|
||||
obsolete: existing,
|
||||
});
|
||||
byUuid[uuid] = conversation;
|
||||
byServiceId[serviceId] = conversation;
|
||||
} else {
|
||||
// Keep existing - note that this applies if neither had an e164
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
|
@ -844,28 +845,28 @@ export class ConversationController {
|
|||
}
|
||||
|
||||
if (pni) {
|
||||
const existing = byUuid[pni];
|
||||
const existing = byServiceId[pni];
|
||||
if (!existing) {
|
||||
byUuid[pni] = conversation;
|
||||
byServiceId[pni] = conversation;
|
||||
} else if (existing === conversation) {
|
||||
// Conversation has both uuid and pni set to the same value. This
|
||||
// Conversation has both service id and pni set to the same value. This
|
||||
// happens when starting a conversation by E164.
|
||||
assertDev(
|
||||
pni === uuid,
|
||||
'checkForConflicts: expected PNI to be equal to UUID'
|
||||
pni === serviceId,
|
||||
'checkForConflicts: expected PNI to be equal to serviceId'
|
||||
);
|
||||
} else {
|
||||
log.warn(`checkForConflicts: Found conflict with pni ${pni}`);
|
||||
|
||||
// Keep the newer one if it has additional data, otherwise keep existing
|
||||
if (conversation.get('e164') || conversation.get('pni')) {
|
||||
if (conversation.get('e164') || conversation.getPni()) {
|
||||
// Keep new one
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await this.doCombineConversations({
|
||||
current: conversation,
|
||||
obsolete: existing,
|
||||
});
|
||||
byUuid[pni] = conversation;
|
||||
byServiceId[pni] = conversation;
|
||||
} else {
|
||||
// Keep existing - note that this applies if neither had an e164
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
|
@ -882,15 +883,15 @@ export class ConversationController {
|
|||
if (!existing) {
|
||||
byE164[e164] = conversation;
|
||||
} else {
|
||||
// If we have two contacts with the same e164 but different truthy UUIDs, then
|
||||
// we'll delete the e164 on the older one
|
||||
// If we have two contacts with the same e164 but different truthy
|
||||
// service ids, then we'll delete the e164 on the older one
|
||||
if (
|
||||
conversation.get('uuid') &&
|
||||
existing.get('uuid') &&
|
||||
conversation.get('uuid') !== existing.get('uuid')
|
||||
conversation.getServiceId() &&
|
||||
existing.getServiceId() &&
|
||||
conversation.getServiceId() !== existing.getServiceId()
|
||||
) {
|
||||
log.warn(
|
||||
`checkForConflicts: Found two matches on e164 ${e164} with different truthy UUIDs. Dropping e164 on older.`
|
||||
`checkForConflicts: Found two matches on e164 ${e164} with different truthy service ids. Dropping e164 on older.`
|
||||
);
|
||||
|
||||
existing.set({ e164: undefined });
|
||||
|
@ -903,8 +904,8 @@ export class ConversationController {
|
|||
|
||||
log.warn(`checkForConflicts: Found conflict with e164 ${e164}`);
|
||||
|
||||
// Keep the newer one if it has a UUID, otherwise keep existing
|
||||
if (conversation.get('uuid')) {
|
||||
// Keep the newer one if it has a service id, otherwise keep existing
|
||||
if (conversation.getServiceId()) {
|
||||
// Keep new one
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await this.doCombineConversations({
|
||||
|
@ -913,7 +914,7 @@ export class ConversationController {
|
|||
});
|
||||
byE164[e164] = conversation;
|
||||
} else {
|
||||
// Keep existing - note that this applies if neither had a UUID
|
||||
// Keep existing - note that this applies if neither had a service id
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await this.doCombineConversations({
|
||||
current: existing,
|
||||
|
@ -1073,7 +1074,7 @@ export class ConversationController {
|
|||
}
|
||||
|
||||
log.warn(`${logId}: Delete all sessions tied to old conversationId`);
|
||||
// Note: we use the conversationId here in case we've already lost our uuid.
|
||||
// Note: we use the conversationId here in case we've already lost our service id.
|
||||
await window.textsecure.storage.protocol.removeSessionsByConversation(
|
||||
obsoleteId
|
||||
);
|
||||
|
@ -1301,9 +1302,9 @@ export class ConversationController {
|
|||
async _forgetE164(e164: string): Promise<void> {
|
||||
const { server } = window.textsecure;
|
||||
strictAssert(server, 'Server must be initialized');
|
||||
const uuidMap = await getServiceIdsForE164s(server, [e164]);
|
||||
const serviceIdMap = await getServiceIdsForE164s(server, [e164]);
|
||||
|
||||
const pni = uuidMap.get(e164)?.pni;
|
||||
const pni = serviceIdMap.get(e164)?.pni;
|
||||
|
||||
log.info(`ConversationController: forgetting e164=${e164} pni=${pni}`);
|
||||
|
||||
|
@ -1382,14 +1383,16 @@ export class ConversationController {
|
|||
updateConversation(conversation.attributes);
|
||||
}
|
||||
|
||||
// Clean up the conversations that have UUID as their e164.
|
||||
// Clean up the conversations that have service id as their e164.
|
||||
const e164 = conversation.get('e164');
|
||||
const uuid = conversation.get('uuid');
|
||||
if (e164 && isServiceIdString(e164) && uuid) {
|
||||
const serviceId = conversation.getServiceId();
|
||||
if (e164 && isServiceIdString(e164) && serviceId) {
|
||||
conversation.set({ e164: undefined });
|
||||
updateConversation(conversation.attributes);
|
||||
|
||||
log.info(`Cleaning up conversation(${uuid}) with invalid e164`);
|
||||
log.info(
|
||||
`Cleaning up conversation(${serviceId}) with invalid e164`
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
log.error(
|
||||
|
|
|
@ -423,7 +423,8 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
.map(item => item.fromDB)
|
||||
.filter(
|
||||
item =>
|
||||
item.ourUuid === ourServiceId && item.isLastResort === isLastResort
|
||||
item.ourServiceId === ourServiceId &&
|
||||
item.isLastResort === isLastResort
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -479,7 +480,7 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
isConfirmed: key.isConfirmed,
|
||||
isLastResort: key.isLastResort,
|
||||
keyId: key.keyId,
|
||||
ourUuid: ourServiceId,
|
||||
ourServiceId,
|
||||
};
|
||||
|
||||
toSave.push(kyberPreKey);
|
||||
|
@ -589,7 +590,7 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
const entries = Array.from(this.preKeys.values());
|
||||
return entries
|
||||
.map(item => item.fromDB)
|
||||
.filter(item => item.ourUuid === ourServiceId);
|
||||
.filter(item => item.ourServiceId === ourServiceId);
|
||||
}
|
||||
|
||||
async storePreKeys(
|
||||
|
@ -613,7 +614,7 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
const preKey = {
|
||||
id,
|
||||
keyId: key.keyId,
|
||||
ourUuid: ourServiceId,
|
||||
ourServiceId,
|
||||
publicKey: key.keyPair.pubKey,
|
||||
privateKey: key.keyPair.privKey,
|
||||
createdAt: now,
|
||||
|
@ -705,7 +706,7 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
|
||||
const entries = Array.from(this.signedPreKeys.values());
|
||||
return entries
|
||||
.filter(({ fromDB }) => fromDB.ourUuid === ourServiceId)
|
||||
.filter(({ fromDB }) => fromDB.ourServiceId === ourServiceId)
|
||||
.map(entry => {
|
||||
const preKey = entry.fromDB;
|
||||
return {
|
||||
|
@ -760,7 +761,7 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
|
||||
const fromDB = {
|
||||
id,
|
||||
ourUuid: ourServiceId,
|
||||
ourServiceId,
|
||||
keyId,
|
||||
publicKey: keyPair.pubKey,
|
||||
privateKey: keyPair.privKey,
|
||||
|
@ -1335,7 +1336,7 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
throw new Error('_maybeMigrateSession: Unknown session version type!');
|
||||
}
|
||||
|
||||
const ourServiceId = session.ourUuid;
|
||||
const { ourServiceId } = session;
|
||||
|
||||
const keyPair = this.getIdentityKeyPair(ourServiceId);
|
||||
if (!keyPair) {
|
||||
|
@ -1384,7 +1385,7 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
const { serviceId, deviceId } = qualifiedAddress;
|
||||
|
||||
const conversation = window.ConversationController.lookupOrCreate({
|
||||
uuid: serviceId,
|
||||
serviceId,
|
||||
reason: 'SignalProtocolStore.storeSession',
|
||||
});
|
||||
strictAssert(
|
||||
|
@ -1397,9 +1398,9 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
const fromDB = {
|
||||
id,
|
||||
version: 2,
|
||||
ourUuid: qualifiedAddress.ourServiceId,
|
||||
ourServiceId: qualifiedAddress.ourServiceId,
|
||||
conversationId: conversation.id,
|
||||
uuid: serviceId,
|
||||
serviceId,
|
||||
deviceId,
|
||||
record: record.serialize().toString('base64'),
|
||||
};
|
||||
|
@ -1448,7 +1449,8 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
const allSessions = this._getAllSessions();
|
||||
const entries = allSessions.filter(
|
||||
({ fromDB }) =>
|
||||
fromDB.ourUuid === ourServiceId && serviceIdSet.has(fromDB.uuid)
|
||||
fromDB.ourServiceId === ourServiceId &&
|
||||
serviceIdSet.has(fromDB.serviceId)
|
||||
);
|
||||
const openEntries: Array<
|
||||
| undefined
|
||||
|
@ -1485,15 +1487,15 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
}
|
||||
const { entry, record } = item;
|
||||
|
||||
const { uuid } = entry.fromDB;
|
||||
serviceIdSet.delete(uuid);
|
||||
const { serviceId } = entry.fromDB;
|
||||
serviceIdSet.delete(serviceId);
|
||||
|
||||
const id = entry.fromDB.deviceId;
|
||||
|
||||
const registrationId = record.remoteRegistrationId();
|
||||
|
||||
return {
|
||||
serviceId: uuid,
|
||||
serviceId,
|
||||
id,
|
||||
registrationId,
|
||||
};
|
||||
|
@ -1601,7 +1603,7 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
|
||||
for (let i = 0, max = entries.length; i < max; i += 1) {
|
||||
const entry = entries[i];
|
||||
if (entry.fromDB.uuid === serviceId) {
|
||||
if (entry.fromDB.serviceId === serviceId) {
|
||||
this.sessions.delete(entry.fromDB.id);
|
||||
this.pendingSessions.delete(entry.fromDB.id);
|
||||
}
|
||||
|
@ -1675,7 +1677,8 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
const allEntries = this._getAllSessions();
|
||||
const entries = allEntries.filter(
|
||||
entry =>
|
||||
entry.fromDB.uuid === serviceId && entry.fromDB.deviceId !== deviceId
|
||||
entry.fromDB.serviceId === serviceId &&
|
||||
entry.fromDB.deviceId !== deviceId
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
|
@ -1696,7 +1699,7 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
|
||||
const allEntries = this._getAllSessions();
|
||||
const entries = allEntries.filter(
|
||||
entry => entry.fromDB.uuid === serviceId
|
||||
entry => entry.fromDB.serviceId === serviceId
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
|
@ -1743,7 +1746,7 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
|
||||
// First, fetch this conversation
|
||||
const conversation = window.ConversationController.lookupOrCreate({
|
||||
uuid: serviceId,
|
||||
serviceId,
|
||||
reason: 'SignalProtocolStore.lightSessionReset',
|
||||
});
|
||||
assertDev(conversation, `lightSessionReset/${id}: missing conversation`);
|
||||
|
@ -2584,7 +2587,7 @@ export class SignalProtocolStore extends EventEmitter {
|
|||
isConfirmed: true,
|
||||
isLastResort: true,
|
||||
keyId: lastResortKyberPreKey.id(),
|
||||
ourUuid: pni,
|
||||
ourServiceId: pni,
|
||||
},
|
||||
])
|
||||
: undefined,
|
||||
|
|
|
@ -1081,7 +1081,7 @@ export async function startApp(): Promise<void> {
|
|||
`retryPlaceholders/interval: Found ${expired.length} expired items`
|
||||
);
|
||||
expired.forEach(item => {
|
||||
const { conversationId, senderUuid, sentAt } = item;
|
||||
const { conversationId, senderAci, sentAt } = item;
|
||||
const conversation =
|
||||
window.ConversationController.get(conversationId);
|
||||
if (conversation) {
|
||||
|
@ -1092,7 +1092,7 @@ export async function startApp(): Promise<void> {
|
|||
conversation.addDeliveryIssue({
|
||||
receivedAt,
|
||||
receivedAtCounter,
|
||||
senderUuid,
|
||||
senderAci,
|
||||
sentAt,
|
||||
})
|
||||
)
|
||||
|
@ -2469,7 +2469,7 @@ export async function startApp(): Promise<void> {
|
|||
remove: reaction.remove,
|
||||
source: ReactionSource.FromSomeoneElse,
|
||||
storyReactionMessage: message,
|
||||
targetAuthorUuid: targetAuthorAci,
|
||||
targetAuthorAci,
|
||||
targetTimestamp: reaction.targetTimestamp,
|
||||
timestamp,
|
||||
};
|
||||
|
@ -2679,7 +2679,7 @@ export async function startApp(): Promise<void> {
|
|||
serverTimestamp: data.serverTimestamp,
|
||||
source: window.textsecure.storage.user.getNumber(),
|
||||
sourceDevice: data.device,
|
||||
sourceUuid: window.textsecure.storage.user.getAci(),
|
||||
sourceServiceId: window.textsecure.storage.user.getAci(),
|
||||
timestamp,
|
||||
type: data.message.isStory ? 'story' : 'outgoing',
|
||||
storyDistributionListId: data.storyDistributionListId,
|
||||
|
@ -2755,8 +2755,8 @@ export async function startApp(): Promise<void> {
|
|||
const { data, confirm } = event;
|
||||
|
||||
const source = window.textsecure.storage.user.getNumber();
|
||||
const sourceUuid = window.textsecure.storage.user.getAci();
|
||||
strictAssert(source && sourceUuid, 'Missing user number and uuid');
|
||||
const sourceServiceId = window.textsecure.storage.user.getAci();
|
||||
strictAssert(source && sourceServiceId, 'Missing user number and uuid');
|
||||
|
||||
const messageDescriptor = getMessageDescriptor({
|
||||
...data,
|
||||
|
@ -2804,7 +2804,7 @@ export async function startApp(): Promise<void> {
|
|||
remove: reaction.remove,
|
||||
source: ReactionSource.FromSync,
|
||||
storyReactionMessage: message,
|
||||
targetAuthorUuid: targetAuthorAci,
|
||||
targetAuthorAci,
|
||||
targetTimestamp: reaction.targetTimestamp,
|
||||
timestamp,
|
||||
};
|
||||
|
@ -2900,7 +2900,7 @@ export async function startApp(): Promise<void> {
|
|||
serverTimestamp: data.serverTimestamp,
|
||||
source: data.source,
|
||||
sourceDevice: data.sourceDevice,
|
||||
sourceUuid: data.sourceAci,
|
||||
sourceServiceId: data.sourceAci,
|
||||
timestamp: data.timestamp,
|
||||
type: data.message.isStory ? 'story' : 'incoming',
|
||||
unidentifiedDeliveryReceived: data.unidentifiedDeliveryReceived,
|
||||
|
@ -3174,7 +3174,7 @@ export async function startApp(): Promise<void> {
|
|||
wasSentEncrypted,
|
||||
} = event.receipt;
|
||||
const sourceConversation = window.ConversationController.lookupOrCreate({
|
||||
uuid: sourceServiceId,
|
||||
serviceId: sourceServiceId,
|
||||
e164: source,
|
||||
reason: `onReadOrViewReceipt(${envelopeTimestamp})`,
|
||||
});
|
||||
|
@ -3305,7 +3305,7 @@ export async function startApp(): Promise<void> {
|
|||
ev.confirm();
|
||||
|
||||
const sourceConversation = window.ConversationController.lookupOrCreate({
|
||||
uuid: sourceServiceId,
|
||||
serviceId: sourceServiceId,
|
||||
e164: source,
|
||||
reason: `onDeliveryReceipt(${envelopeTimestamp})`,
|
||||
});
|
||||
|
|
|
@ -26,7 +26,7 @@ import { SizeObserver } from '../hooks/useSizeObserver';
|
|||
type OwnProps = {
|
||||
i18n: LocalizerType;
|
||||
theme: ThemeType;
|
||||
contact: Pick<ConversationType, 'id' | 'title' | 'uuid'>;
|
||||
contact: Pick<ConversationType, 'id' | 'title' | 'serviceId' | 'pni'>;
|
||||
candidateConversations: ReadonlyArray<ConversationType>;
|
||||
regionCode: string | undefined;
|
||||
};
|
||||
|
@ -119,11 +119,12 @@ export function AddUserToAnotherGroupModal({
|
|||
|
||||
let disabledReason;
|
||||
|
||||
if (memberships.some(c => c.uuid === contact.uuid)) {
|
||||
if (memberships.some(c => c.aci === contact.serviceId)) {
|
||||
disabledReason = DisabledReason.AlreadyMember;
|
||||
} else if (
|
||||
pendingApprovalMemberships.some(c => c.uuid === contact.uuid) ||
|
||||
pendingMemberships.some(c => c.uuid === contact.uuid)
|
||||
pendingApprovalMemberships.some(c => c.aci === contact.serviceId) ||
|
||||
pendingMemberships.some(c => c.serviceId === contact.serviceId) ||
|
||||
pendingMemberships.some(c => c.serviceId === contact.pni)
|
||||
) {
|
||||
disabledReason = DisabledReason.Pending;
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ const createProps = (storyProps: Partial<PropsType> = {}): PropsType => ({
|
|||
),
|
||||
title: text('Caller Title', 'Morty Smith'),
|
||||
}),
|
||||
uuid: generateAci(),
|
||||
serviceId: generateAci(),
|
||||
},
|
||||
notifyForCall: action('notify-for-call'),
|
||||
openSystemPreferencesAction: action('open-system-preferences-action'),
|
||||
|
|
|
@ -274,7 +274,7 @@ function ActiveCallManager({
|
|||
<CallingParticipantsList
|
||||
i18n={i18n}
|
||||
onClose={toggleParticipants}
|
||||
ourUuid={me.uuid}
|
||||
ourServiceId={me.serviceId}
|
||||
participants={peekedParticipants}
|
||||
/>
|
||||
) : null}
|
||||
|
@ -359,7 +359,7 @@ function ActiveCallManager({
|
|||
<CallingParticipantsList
|
||||
i18n={i18n}
|
||||
onClose={toggleParticipants}
|
||||
ourUuid={me.uuid}
|
||||
ourServiceId={me.serviceId}
|
||||
participants={groupCallParticipantsForParticipantsList}
|
||||
/>
|
||||
) : null}
|
||||
|
|
|
@ -23,7 +23,7 @@ import { setupI18n } from '../util/setupI18n';
|
|||
import { missingCaseError } from '../util/missingCaseError';
|
||||
import {
|
||||
getDefaultConversation,
|
||||
getDefaultConversationWithUuid,
|
||||
getDefaultConversationWithServiceId,
|
||||
} from '../test-both/helpers/getDefaultConversation';
|
||||
import { fakeGetGroupCallVideoFrameSource } from '../test-both/helpers/fakeGetGroupCallVideoFrameSource';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
@ -175,7 +175,7 @@ const createProps = (
|
|||
name: 'Morty Smith',
|
||||
profileName: 'Morty Smith',
|
||||
title: 'Morty Smith',
|
||||
uuid: generateAci(),
|
||||
serviceId: generateAci(),
|
||||
}),
|
||||
openSystemPreferencesAction: action('open-system-preferences-action'),
|
||||
setGroupCallVideoRequest: action('set-group-call-video-request'),
|
||||
|
@ -312,7 +312,7 @@ export function GroupCall1(): JSX.Element {
|
|||
videoAspectRatio: 1.3,
|
||||
...getDefaultConversation({
|
||||
isBlocked: false,
|
||||
uuid: generateAci(),
|
||||
serviceId: generateAci(),
|
||||
title: 'Tyler',
|
||||
}),
|
||||
},
|
||||
|
@ -334,7 +334,7 @@ const allRemoteParticipants = times(MAX_PARTICIPANTS).map(index => ({
|
|||
presenting: false,
|
||||
sharingScreen: false,
|
||||
videoAspectRatio: 1.3,
|
||||
...getDefaultConversationWithUuid({
|
||||
...getDefaultConversationWithServiceId({
|
||||
isBlocked: index === 10 || index === MAX_PARTICIPANTS - 1,
|
||||
title: `Participant ${index + 1}`,
|
||||
}),
|
||||
|
@ -380,7 +380,7 @@ export function GroupCallReconnecting(): JSX.Element {
|
|||
...getDefaultConversation({
|
||||
isBlocked: false,
|
||||
title: 'Tyler',
|
||||
uuid: generateAci(),
|
||||
serviceId: generateAci(),
|
||||
}),
|
||||
},
|
||||
],
|
||||
|
|
|
@ -16,7 +16,7 @@ import { generateAci } from '../types/ServiceId';
|
|||
import enMessages from '../../_locales/en/messages.json';
|
||||
import {
|
||||
getDefaultConversation,
|
||||
getDefaultConversationWithUuid,
|
||||
getDefaultConversationWithServiceId,
|
||||
} from '../test-both/helpers/getDefaultConversation';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
@ -67,7 +67,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => {
|
|||
getDefaultConversation({
|
||||
color: AvatarColors[0],
|
||||
id: generateUuid(),
|
||||
uuid: generateAci(),
|
||||
serviceId: generateAci(),
|
||||
}),
|
||||
onCallCanceled: action('on-call-canceled'),
|
||||
onJoinCall: action('on-join-call'),
|
||||
|
@ -87,7 +87,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => {
|
|||
};
|
||||
|
||||
const fakePeekedParticipant = (conversationProps: Partial<ConversationType>) =>
|
||||
getDefaultConversationWithUuid({
|
||||
getDefaultConversationWithServiceId({
|
||||
...conversationProps,
|
||||
});
|
||||
|
||||
|
@ -118,7 +118,7 @@ export function NoCameraLocalAvatar(): JSX.Element {
|
|||
avatarPath: '/fixtures/kitten-4-112-112.jpg',
|
||||
color: AvatarColors[0],
|
||||
id: generateUuid(),
|
||||
uuid: generateAci(),
|
||||
serviceId: generateAci(),
|
||||
}),
|
||||
});
|
||||
return <CallingLobby {...props} />;
|
||||
|
@ -168,14 +168,14 @@ GroupCall1PeekedParticipant.story = {
|
|||
};
|
||||
|
||||
export function GroupCall1PeekedParticipantSelf(): JSX.Element {
|
||||
const uuid = generateAci();
|
||||
const serviceId = generateAci();
|
||||
const props = createProps({
|
||||
isGroupCall: true,
|
||||
me: getDefaultConversation({
|
||||
id: generateUuid(),
|
||||
uuid,
|
||||
serviceId,
|
||||
}),
|
||||
peekedParticipants: [fakePeekedParticipant({ title: 'Ash', uuid })],
|
||||
peekedParticipants: [fakePeekedParticipant({ title: 'Ash', serviceId })],
|
||||
});
|
||||
return <CallingLobby {...props} />;
|
||||
}
|
||||
|
|
|
@ -49,7 +49,9 @@ export type PropsType = {
|
|||
isGroupCall: boolean;
|
||||
isGroupCallOutboundRingEnabled: boolean;
|
||||
isCallFull?: boolean;
|
||||
me: Readonly<Pick<ConversationType, 'avatarPath' | 'color' | 'id' | 'uuid'>>;
|
||||
me: Readonly<
|
||||
Pick<ConversationType, 'avatarPath' | 'color' | 'id' | 'serviceId'>
|
||||
>;
|
||||
onCallCanceled: () => void;
|
||||
onJoinCall: () => void;
|
||||
outgoingRing: boolean;
|
||||
|
|
|
@ -9,7 +9,8 @@ import type { PropsType } from './CallingParticipantsList';
|
|||
import { CallingParticipantsList } from './CallingParticipantsList';
|
||||
import { AvatarColors } from '../types/Colors';
|
||||
import type { GroupCallRemoteParticipantType } from '../types/Calling';
|
||||
import { getDefaultConversationWithUuid } from '../test-both/helpers/getDefaultConversation';
|
||||
import { generateAci } from '../types/ServiceId';
|
||||
import { getDefaultConversationWithServiceId } from '../test-both/helpers/getDefaultConversation';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
||||
|
@ -25,7 +26,7 @@ function createParticipant(
|
|||
presenting: Boolean(participantProps.presenting),
|
||||
sharingScreen: Boolean(participantProps.sharingScreen),
|
||||
videoAspectRatio: 1.3,
|
||||
...getDefaultConversationWithUuid({
|
||||
...getDefaultConversationWithServiceId({
|
||||
avatarPath: participantProps.avatarPath,
|
||||
color: sample(AvatarColors),
|
||||
isBlocked: Boolean(participantProps.isBlocked),
|
||||
|
@ -39,7 +40,7 @@ function createParticipant(
|
|||
const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
||||
i18n,
|
||||
onClose: action('on-close'),
|
||||
ourUuid: 'cf085e6a-e70b-41ec-a310-c198248af13f',
|
||||
ourServiceId: generateAci(),
|
||||
participants: overrideProps.participants || [],
|
||||
});
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import { Avatar, AvatarSize } from './Avatar';
|
|||
import { ContactName } from './conversation/ContactName';
|
||||
import { InContactsIcon } from './InContactsIcon';
|
||||
import type { LocalizerType } from '../types/Util';
|
||||
import type { ServiceIdString } from '../types/ServiceId';
|
||||
import { sortByTitle } from '../util/sortByTitle';
|
||||
import type { ConversationType } from '../state/ducks/conversations';
|
||||
import { isInSystemContacts } from '../util/isInSystemContacts';
|
||||
|
@ -25,7 +26,7 @@ type ParticipantType = ConversationType & {
|
|||
export type PropsType = {
|
||||
readonly i18n: LocalizerType;
|
||||
readonly onClose: () => void;
|
||||
readonly ourUuid: string | undefined;
|
||||
readonly ourServiceId: ServiceIdString | undefined;
|
||||
readonly participants: Array<ParticipantType>;
|
||||
};
|
||||
|
||||
|
@ -33,7 +34,7 @@ export const CallingParticipantsList = React.memo(
|
|||
function CallingParticipantsListInner({
|
||||
i18n,
|
||||
onClose,
|
||||
ourUuid,
|
||||
ourServiceId,
|
||||
participants,
|
||||
}: PropsType) {
|
||||
const [root, setRoot] = React.useState<HTMLElement | null>(null);
|
||||
|
@ -101,9 +102,9 @@ export const CallingParticipantsList = React.memo(
|
|||
(participant: ParticipantType, index: number) => (
|
||||
<li
|
||||
className="module-calling-participants-list__contact"
|
||||
// It's tempting to use `participant.uuid` as the `key` here, but that
|
||||
// can result in duplicate keys for participants who have joined on
|
||||
// multiple devices.
|
||||
// It's tempting to use `participant.serviceId` as the `key`
|
||||
// here, but that can result in duplicate keys for
|
||||
// participants who have joined on multiple devices.
|
||||
key={index}
|
||||
>
|
||||
<div>
|
||||
|
@ -122,7 +123,8 @@ export const CallingParticipantsList = React.memo(
|
|||
sharedGroupNames={participant.sharedGroupNames}
|
||||
size={AvatarSize.THIRTY_TWO}
|
||||
/>
|
||||
{ourUuid && participant.uuid === ourUuid ? (
|
||||
{ourServiceId &&
|
||||
participant.serviceId === ourServiceId ? (
|
||||
<span className="module-calling-participants-list__name">
|
||||
{i18n('icu:you')}
|
||||
</span>
|
||||
|
|
|
@ -30,14 +30,14 @@ type PropsType = {
|
|||
| 'unblurredAvatarPath'
|
||||
>;
|
||||
i18n: LocalizerType;
|
||||
me: Pick<ConversationType, 'id' | 'uuid'>;
|
||||
me: Pick<ConversationType, 'id' | 'serviceId'>;
|
||||
ringMode: RingMode;
|
||||
|
||||
// The following should only be set for group conversations.
|
||||
groupMembers?: Array<Pick<ConversationType, 'id' | 'firstName' | 'title'>>;
|
||||
isCallFull?: boolean;
|
||||
peekedParticipants?: Array<
|
||||
Pick<ConversationType, 'firstName' | 'title' | 'uuid'>
|
||||
Pick<ConversationType, 'firstName' | 'title' | 'serviceId'>
|
||||
>;
|
||||
};
|
||||
|
||||
|
@ -61,7 +61,7 @@ export function CallingPreCallInfo({
|
|||
// device.
|
||||
let hasYou = false;
|
||||
const participantNames = peekedParticipants.map(participant => {
|
||||
if (participant.uuid === me.uuid) {
|
||||
if (participant.serviceId === me.serviceId) {
|
||||
hasYou = true;
|
||||
return i18n('icu:you');
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import type {
|
|||
InMemoryAttachmentDraftType,
|
||||
} from '../types/Attachment';
|
||||
import { isImageAttachment, isVoiceMessage } from '../types/Attachment';
|
||||
import type { AciString } from '../types/ServiceId';
|
||||
import { AudioCapture } from './conversation/AudioCapture';
|
||||
import { CompositionUpload } from './CompositionUpload';
|
||||
import type {
|
||||
|
@ -87,7 +88,6 @@ export type OwnProps = Readonly<{
|
|||
conversationId: string;
|
||||
discardEditMessage: (id: string) => unknown;
|
||||
draftEditMessage?: DraftEditMessageType;
|
||||
uuid?: string;
|
||||
draftAttachments: ReadonlyArray<AttachmentDraftType>;
|
||||
errorDialogAudioRecorderType?: ErrorDialogAudioRecorderType;
|
||||
errorRecording: (e: ErrorDialogAudioRecorderType) => unknown;
|
||||
|
@ -131,7 +131,7 @@ export type OwnProps = Readonly<{
|
|||
options: {
|
||||
bodyRanges?: DraftBodyRanges;
|
||||
message?: string;
|
||||
quoteAuthorUuid?: string;
|
||||
quoteAuthorAci?: AciString;
|
||||
quoteSentAt?: number;
|
||||
targetMessageId: string;
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ export type OwnProps = Readonly<{
|
|||
'i18n' | 'onClick' | 'onClose' | 'withContentAbove' | 'isCompose'
|
||||
>
|
||||
>;
|
||||
quotedMessageAuthorUuid?: string;
|
||||
quotedMessageAuthorAci?: AciString;
|
||||
quotedMessageSentAt?: number;
|
||||
|
||||
removeAttachment: (conversationId: string, filePath: string) => unknown;
|
||||
|
@ -256,7 +256,7 @@ export function CompositionArea({
|
|||
// Quote
|
||||
quotedMessageId,
|
||||
quotedMessageProps,
|
||||
quotedMessageAuthorUuid,
|
||||
quotedMessageAuthorAci,
|
||||
quotedMessageSentAt,
|
||||
scrollToMessage,
|
||||
// MediaQualitySelector
|
||||
|
@ -356,7 +356,7 @@ export function CompositionArea({
|
|||
message,
|
||||
// sent timestamp for the quote
|
||||
quoteSentAt: quotedMessageSentAt,
|
||||
quoteAuthorUuid: quotedMessageAuthorUuid,
|
||||
quoteAuthorAci: quotedMessageAuthorAci,
|
||||
targetMessageId: editedMessageId,
|
||||
});
|
||||
} else {
|
||||
|
@ -374,7 +374,7 @@ export function CompositionArea({
|
|||
draftAttachments,
|
||||
editedMessageId,
|
||||
quotedMessageSentAt,
|
||||
quotedMessageAuthorUuid,
|
||||
quotedMessageAuthorAci,
|
||||
sendEditedMessage,
|
||||
sendMultiMediaMessage,
|
||||
setLarge,
|
||||
|
|
|
@ -138,7 +138,7 @@ export function Mentions(): JSX.Element {
|
|||
{
|
||||
start: 5,
|
||||
length: 1,
|
||||
mentionUuid: generateAci(),
|
||||
mentionAci: generateAci(),
|
||||
conversationID: 'k',
|
||||
replacementText: 'Kate Beaton',
|
||||
},
|
||||
|
|
|
@ -26,7 +26,7 @@ import { BodyRange, collapseRangeTree, insertRange } from '../types/BodyRange';
|
|||
import type { LocalizerType, ThemeType } from '../types/Util';
|
||||
import type { ConversationType } from '../state/ducks/conversations';
|
||||
import type { PreferredBadgeSelectorType } from '../state/selectors/badges';
|
||||
import { isServiceIdString } from '../types/ServiceId';
|
||||
import { isAciString } from '../types/ServiceId';
|
||||
import { MentionBlot } from '../quill/mentions/blot';
|
||||
import {
|
||||
matchEmojiImage,
|
||||
|
@ -678,15 +678,12 @@ export function CompositionInput(props: Props): React.ReactElement {
|
|||
return;
|
||||
}
|
||||
|
||||
const currentMemberServiceIds = currentMembers
|
||||
.map(m => m.uuid)
|
||||
const currentMemberAcis = currentMembers
|
||||
.map(m => m.serviceId)
|
||||
.filter(isNotNil)
|
||||
.filter(isServiceIdString);
|
||||
.filter(isAciString);
|
||||
|
||||
const newDelta = getDeltaToRemoveStaleMentions(
|
||||
ops,
|
||||
currentMemberServiceIds
|
||||
);
|
||||
const newDelta = getDeltaToRemoveStaleMentions(ops, currentMemberAcis);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
quill.updateContents(newDelta as any);
|
||||
|
|
|
@ -374,7 +374,7 @@ export function ConversationList({
|
|||
'unblurredAvatarPath',
|
||||
'unreadCount',
|
||||
'unreadMentionsCount',
|
||||
'uuid',
|
||||
'serviceId',
|
||||
]);
|
||||
const { badges, title, unreadCount, lastMessage } = itemProps;
|
||||
result = (
|
||||
|
|
|
@ -8,7 +8,7 @@ import { action } from '@storybook/addon-actions';
|
|||
|
||||
import { GroupCallOverflowArea } from './GroupCallOverflowArea';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
import { getDefaultConversationWithUuid } from '../test-both/helpers/getDefaultConversation';
|
||||
import { getDefaultConversationWithServiceId } from '../test-both/helpers/getDefaultConversation';
|
||||
import { fakeGetGroupCallVideoFrameSource } from '../test-both/helpers/fakeGetGroupCallVideoFrameSource';
|
||||
import { FRAME_BUFFER_SIZE } from '../calling/constants';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
|
@ -24,7 +24,7 @@ const allRemoteParticipants = times(MAX_PARTICIPANTS).map(index => ({
|
|||
presenting: false,
|
||||
sharingScreen: false,
|
||||
videoAspectRatio: 1.3,
|
||||
...getDefaultConversationWithUuid({
|
||||
...getDefaultConversationWithServiceId({
|
||||
isBlocked: index === 10 || index === MAX_PARTICIPANTS - 1,
|
||||
title: `Participant ${index + 1}`,
|
||||
}),
|
||||
|
|
|
@ -61,7 +61,7 @@ const createProps = (
|
|||
isBlocked: Boolean(isBlocked),
|
||||
title:
|
||||
'Pablo Diego José Francisco de Paula Juan Nepomuceno María de los Remedios Cipriano de la Santísima Trinidad Ruiz y Picasso',
|
||||
uuid: generateAci(),
|
||||
serviceId: generateAci(),
|
||||
}),
|
||||
},
|
||||
remoteParticipantsCount: 1,
|
||||
|
|
|
@ -310,7 +310,9 @@ function ContactSection({
|
|||
}
|
||||
|
||||
const { distributionId } = section.story;
|
||||
const uuids = section.contacts.map(contact => contact.uuid).filter(isNotNil);
|
||||
const serviceIds = section.contacts
|
||||
.map(contact => contact.serviceId)
|
||||
.filter(isNotNil);
|
||||
const sectionName =
|
||||
distributionId === MY_STORY_ID
|
||||
? i18n('icu:Stories__mine')
|
||||
|
@ -322,17 +324,17 @@ function ContactSection({
|
|||
<div className="module-SafetyNumberChangeDialog__row__story-name">
|
||||
{sectionName}
|
||||
</div>
|
||||
{distributionId && removeFromStory && uuids.length > 1 && (
|
||||
{distributionId && removeFromStory && serviceIds.length > 1 && (
|
||||
<SectionButtonWithMenu
|
||||
ariaLabel={i18n('icu:safetyNumberChangeDialog__actions-story', {
|
||||
story: sectionName,
|
||||
})}
|
||||
i18n={i18n}
|
||||
memberCount={uuids.length}
|
||||
memberCount={serviceIds.length}
|
||||
storyName={sectionName}
|
||||
theme={theme}
|
||||
removeFromStory={() => {
|
||||
removeFromStory(distributionId, uuids);
|
||||
removeFromStory(distributionId, serviceIds);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
@ -443,7 +445,7 @@ function ContactRow({
|
|||
shouldShowNumber: boolean;
|
||||
theme: ThemeType;
|
||||
}>) {
|
||||
const { uuid } = contact;
|
||||
const { serviceId } = contact;
|
||||
|
||||
return (
|
||||
<li className="module-SafetyNumberChangeDialog__row" key={contact.id}>
|
||||
|
@ -493,14 +495,14 @@ function ContactRow({
|
|||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
{distributionId && removeFromStory && uuid ? (
|
||||
{distributionId && removeFromStory && serviceId ? (
|
||||
<RowButtonWithMenu
|
||||
ariaLabel={i18n('icu:safetyNumberChangeDialog__actions-contact', {
|
||||
contact: contact.title,
|
||||
})}
|
||||
i18n={i18n}
|
||||
theme={theme}
|
||||
removeFromStory={() => removeFromStory(distributionId, [uuid])}
|
||||
removeFromStory={() => removeFromStory(distributionId, [serviceId])}
|
||||
verifyContact={() => setSelectedContact(contact)}
|
||||
/>
|
||||
) : (
|
||||
|
|
|
@ -59,7 +59,7 @@ export type PropsType = {
|
|||
onDeleteList: (listId: StoryDistributionIdString) => unknown;
|
||||
onDistributionListCreated: (
|
||||
name: string,
|
||||
viewerUuids: Array<ServiceIdString>
|
||||
viewerServiceIds: Array<ServiceIdString>
|
||||
) => Promise<StoryDistributionIdString>;
|
||||
onSelectedStoryList: (options: {
|
||||
conversationId: string;
|
||||
|
@ -107,15 +107,15 @@ function getListMemberServiceIds(
|
|||
signalConnections: Array<ConversationType>
|
||||
): Array<ServiceIdString> {
|
||||
const memberServiceIds = list.members
|
||||
.map(({ uuid }) => uuid)
|
||||
.map(({ serviceId }) => serviceId)
|
||||
.filter(isNotNil);
|
||||
|
||||
if (list.id === MY_STORY_ID && list.isBlockList) {
|
||||
const excludeUuids = new Set<string>(memberServiceIds);
|
||||
const excludeServiceIds = new Set<ServiceIdString>(memberServiceIds);
|
||||
return signalConnections
|
||||
.map(conversation => conversation.uuid)
|
||||
.map(conversation => conversation.serviceId)
|
||||
.filter(isNotNil)
|
||||
.filter(uuid => !excludeUuids.has(uuid));
|
||||
.filter(serviceId => !excludeServiceIds.has(serviceId));
|
||||
}
|
||||
|
||||
return memberServiceIds;
|
||||
|
@ -242,7 +242,7 @@ export function SendStoryModal({
|
|||
return distributionLists.find(list => list.id === listIdToEdit);
|
||||
}, [distributionLists, listIdToEdit]);
|
||||
|
||||
// myStoriesPrivacy, myStoriesPrivacyUuids, and myStories are only used
|
||||
// myStoriesPrivacy, myStoriesPrivacyServiceIds, and myStories are only used
|
||||
// during the first time posting to My Stories experience where we have
|
||||
// to select the privacy settings.
|
||||
const ogMyStories = useMemo(
|
||||
|
@ -310,18 +310,18 @@ export function SendStoryModal({
|
|||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
const uuids = stagedMyStories.members
|
||||
.map(convo => convo.uuid)
|
||||
const serviceIds = stagedMyStories.members
|
||||
.map(convo => convo.serviceId)
|
||||
.filter(isNotNil);
|
||||
|
||||
if (stagedMyStories.isBlockList) {
|
||||
if (stagedMyStories.members.length) {
|
||||
onHideMyStoriesFrom(uuids);
|
||||
onHideMyStoriesFrom(serviceIds);
|
||||
} else {
|
||||
setMyStoriesToAllSignalConnections();
|
||||
}
|
||||
} else {
|
||||
onViewersUpdated(MY_STORY_ID, uuids);
|
||||
onViewersUpdated(MY_STORY_ID, serviceIds);
|
||||
}
|
||||
|
||||
setSelectedContacts([]);
|
||||
|
@ -425,10 +425,10 @@ export function SendStoryModal({
|
|||
candidateConversations={candidateConversations}
|
||||
getPreferredBadge={getPreferredBadge}
|
||||
i18n={i18n}
|
||||
onCreateList={async (name, uuids) => {
|
||||
onCreateList={async (name, serviceIds) => {
|
||||
const newDistributionListId = await onDistributionListCreated(
|
||||
name,
|
||||
uuids
|
||||
serviceIds
|
||||
);
|
||||
|
||||
setSelectedContacts([]);
|
||||
|
@ -438,19 +438,19 @@ export function SendStoryModal({
|
|||
|
||||
setPage(Page.SendStory);
|
||||
}}
|
||||
onViewersUpdated={uuids => {
|
||||
onViewersUpdated={serviceIds => {
|
||||
if (listIdToEdit && page === Page.AddViewer) {
|
||||
onViewersUpdated(listIdToEdit, uuids);
|
||||
onViewersUpdated(listIdToEdit, serviceIds);
|
||||
setPage(Page.EditingDistributionList);
|
||||
} else if (page === Page.ChooseViewers) {
|
||||
setPage(Page.NameStory);
|
||||
} else if (listIdToEdit && page === Page.HideStoryFrom) {
|
||||
onHideMyStoriesFrom(uuids);
|
||||
onHideMyStoriesFrom(serviceIds);
|
||||
setPage(Page.SendStory);
|
||||
} else if (page === Page.HideStoryFrom || page === Page.AddViewer) {
|
||||
const uuidsSet = new Set(uuids);
|
||||
const serviceIdSet = new Set(serviceIds);
|
||||
const members = candidateConversations.filter(convo =>
|
||||
convo.uuid ? uuidsSet.has(convo.uuid) : false
|
||||
convo.serviceId ? serviceIdSet.has(convo.serviceId) : false
|
||||
);
|
||||
setStagedMyStories(myStories => ({
|
||||
...myStories,
|
||||
|
@ -800,7 +800,7 @@ export function SendStoryModal({
|
|||
onSelectedStoryList({
|
||||
conversationId: group.id,
|
||||
distributionId: undefined,
|
||||
serviceIds: group.memberships.map(({ uuid }) => uuid),
|
||||
serviceIds: group.memberships.map(({ aci }) => aci),
|
||||
});
|
||||
}
|
||||
}}
|
||||
|
|
|
@ -54,7 +54,7 @@ export default {
|
|||
setMyStoriesToAllSignalConnections: { action: true },
|
||||
toggleSignalConnectionsModal: { action: true },
|
||||
setStoriesDisabled: { action: true },
|
||||
getConversationByUuid: {
|
||||
getConversationByServiceId: {
|
||||
defaultValue: () => getDefaultGroup(),
|
||||
},
|
||||
},
|
||||
|
|
|
@ -52,25 +52,28 @@ export type PropsType = {
|
|||
toggleGroupsForStorySend: (groupIds: Array<string>) => unknown;
|
||||
onDistributionListCreated: (
|
||||
name: string,
|
||||
viewerUuids: Array<ServiceIdString>
|
||||
viewerServiceIds: Array<ServiceIdString>
|
||||
) => Promise<string>;
|
||||
onHideMyStoriesFrom: (viewerUuids: Array<ServiceIdString>) => unknown;
|
||||
onRemoveMembers: (listId: string, uuids: Array<ServiceIdString>) => unknown;
|
||||
onHideMyStoriesFrom: (viewerServiceIds: Array<ServiceIdString>) => unknown;
|
||||
onRemoveMembers: (
|
||||
listId: string,
|
||||
serviceIds: Array<ServiceIdString>
|
||||
) => unknown;
|
||||
onRepliesNReactionsChanged: (
|
||||
listId: string,
|
||||
allowsReplies: boolean
|
||||
) => unknown;
|
||||
onViewersUpdated: (
|
||||
listId: string,
|
||||
viewerUuids: Array<ServiceIdString>
|
||||
viewerServiceIds: Array<ServiceIdString>
|
||||
) => unknown;
|
||||
setMyStoriesToAllSignalConnections: () => unknown;
|
||||
storyViewReceiptsEnabled: boolean;
|
||||
theme: ThemeType;
|
||||
toggleSignalConnectionsModal: () => unknown;
|
||||
setStoriesDisabled: (value: boolean) => void;
|
||||
getConversationByUuid: (
|
||||
uuid: ServiceIdString
|
||||
getConversationByServiceId: (
|
||||
serviceId: ServiceIdString
|
||||
) => ConversationType | undefined;
|
||||
};
|
||||
|
||||
|
@ -90,7 +93,7 @@ function filterConversations(
|
|||
conversations,
|
||||
searchTerm,
|
||||
undefined
|
||||
).filter(conversation => conversation.uuid);
|
||||
).filter(conversation => conversation.serviceId);
|
||||
}
|
||||
|
||||
const modalCommonProps: Pick<ModalPropsType, 'hasXButton' | 'moduleClassName'> =
|
||||
|
@ -258,7 +261,7 @@ export function StoriesSettingsModal({
|
|||
toggleSignalConnectionsModal,
|
||||
theme,
|
||||
setStoriesDisabled,
|
||||
getConversationByUuid,
|
||||
getConversationByServiceId,
|
||||
}: PropsType): JSX.Element {
|
||||
const [confirmDiscardModal, confirmDiscardIf] = useConfirmDiscard(i18n);
|
||||
|
||||
|
@ -311,8 +314,8 @@ export function StoriesSettingsModal({
|
|||
i18n={i18n}
|
||||
page={page}
|
||||
onClose={onClose}
|
||||
onCreateList={(name, uuids) => {
|
||||
void onDistributionListCreated(name, uuids);
|
||||
onCreateList={(name, serviceIds) => {
|
||||
void onDistributionListCreated(name, serviceIds);
|
||||
resetChooseViewersScreen();
|
||||
}}
|
||||
onBackButtonClick={() =>
|
||||
|
@ -330,9 +333,9 @@ export function StoriesSettingsModal({
|
|||
}
|
||||
})
|
||||
}
|
||||
onViewersUpdated={uuids => {
|
||||
onViewersUpdated={serviceIds => {
|
||||
if (listToEditId && page === Page.AddViewer) {
|
||||
onViewersUpdated(listToEditId, uuids);
|
||||
onViewersUpdated(listToEditId, serviceIds);
|
||||
resetChooseViewersScreen();
|
||||
}
|
||||
|
||||
|
@ -341,7 +344,7 @@ export function StoriesSettingsModal({
|
|||
}
|
||||
|
||||
if (page === Page.HideStoryFrom) {
|
||||
onHideMyStoriesFrom(uuids);
|
||||
onHideMyStoriesFrom(serviceIds);
|
||||
resetChooseViewersScreen();
|
||||
}
|
||||
}}
|
||||
|
@ -377,7 +380,7 @@ export function StoriesSettingsModal({
|
|||
group={groupToView}
|
||||
onClose={onClose}
|
||||
onBackButtonClick={() => setGroupToViewId(null)}
|
||||
getConversationByUuid={getConversationByUuid}
|
||||
getConversationByServiceId={getConversationByServiceId}
|
||||
onRemoveGroup={group => {
|
||||
setConfirmRemoveGroup({
|
||||
id: group.id,
|
||||
|
@ -583,7 +586,7 @@ export function DistributionListSettingsModal({
|
|||
| {
|
||||
listId: string;
|
||||
title: string;
|
||||
uuid: ServiceIdString;
|
||||
serviceId: ServiceIdString;
|
||||
}
|
||||
>();
|
||||
|
||||
|
@ -695,11 +698,14 @@ export function DistributionListSettingsModal({
|
|||
})}
|
||||
className="StoriesSettingsModal__list__delete"
|
||||
onClick={() => {
|
||||
strictAssert(member.uuid, 'Story member was missing uuid');
|
||||
strictAssert(
|
||||
member.serviceId,
|
||||
'Story member was missing service id'
|
||||
);
|
||||
setConfirmRemoveMember({
|
||||
listId: listToEdit.id,
|
||||
title: member.title,
|
||||
uuid: member.uuid,
|
||||
serviceId: member.serviceId,
|
||||
});
|
||||
}}
|
||||
type="button"
|
||||
|
@ -747,7 +753,7 @@ export function DistributionListSettingsModal({
|
|||
{
|
||||
action: () =>
|
||||
onRemoveMembers(confirmRemoveMember.listId, [
|
||||
confirmRemoveMember.uuid,
|
||||
confirmRemoveMember.serviceId,
|
||||
]),
|
||||
style: 'negative',
|
||||
text: i18n('icu:StoriesSettings__remove--action'),
|
||||
|
@ -950,8 +956,11 @@ export function EditMyStoryPrivacy({
|
|||
}
|
||||
|
||||
type EditDistributionListModalPropsType = {
|
||||
onCreateList: (name: string, viewerUuids: Array<ServiceIdString>) => unknown;
|
||||
onViewersUpdated: (viewerUuids: Array<ServiceIdString>) => unknown;
|
||||
onCreateList: (
|
||||
name: string,
|
||||
viewerServiceIds: Array<ServiceIdString>
|
||||
) => unknown;
|
||||
onViewersUpdated: (viewerServiceIds: Array<ServiceIdString>) => unknown;
|
||||
page:
|
||||
| Page.AddViewer
|
||||
| Page.ChooseViewers
|
||||
|
@ -1007,7 +1016,9 @@ export function EditDistributionListModal({
|
|||
|
||||
const selectConversationServiceIds: Set<ServiceIdString> = useMemo(
|
||||
() =>
|
||||
new Set(selectedContacts.map(contact => contact.uuid).filter(isNotNil)),
|
||||
new Set(
|
||||
selectedContacts.map(contact => contact.serviceId).filter(isNotNil)
|
||||
),
|
||||
[selectedContacts]
|
||||
);
|
||||
|
||||
|
@ -1108,11 +1119,11 @@ export function EditDistributionListModal({
|
|||
const rowCount = filteredConversations.length;
|
||||
const getRow = (index: number): undefined | Row => {
|
||||
const contact = filteredConversations[index];
|
||||
if (!contact || !contact.uuid) {
|
||||
if (!contact || !contact.serviceId) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const isSelected = selectConversationServiceIds.has(contact.uuid);
|
||||
const isSelected = selectConversationServiceIds.has(contact.serviceId);
|
||||
|
||||
return {
|
||||
type: RowType.ContactCheckbox,
|
||||
|
@ -1243,7 +1254,9 @@ type GroupStorySettingsModalProps = {
|
|||
group: ConversationType;
|
||||
onClose(): void;
|
||||
onBackButtonClick(): void;
|
||||
getConversationByUuid(uuid: ServiceIdString): ConversationType | undefined;
|
||||
getConversationByServiceId(
|
||||
serviceId: ServiceIdString
|
||||
): ConversationType | undefined;
|
||||
onRemoveGroup(group: ConversationType): void;
|
||||
};
|
||||
|
||||
|
@ -1252,10 +1265,13 @@ export function GroupStorySettingsModal({
|
|||
group,
|
||||
onClose,
|
||||
onBackButtonClick,
|
||||
getConversationByUuid,
|
||||
getConversationByServiceId,
|
||||
onRemoveGroup,
|
||||
}: GroupStorySettingsModalProps): JSX.Element {
|
||||
const groupMemberships = getGroupMemberships(group, getConversationByUuid);
|
||||
const groupMemberships = getGroupMemberships(
|
||||
group,
|
||||
getConversationByServiceId
|
||||
);
|
||||
return (
|
||||
<ModalPage
|
||||
modalName="GroupStorySettingsModal"
|
||||
|
|
|
@ -103,7 +103,7 @@ export function StoryListItem({
|
|||
|
||||
const { firstName, title } = sender;
|
||||
|
||||
const isSignalOfficial = sender.uuid === SIGNAL_ACI;
|
||||
const isSignalOfficial = sender.serviceId === SIGNAL_ACI;
|
||||
|
||||
let avatarStoryRing: HasStories | undefined;
|
||||
if (attachment) {
|
||||
|
|
|
@ -40,21 +40,21 @@ export function MultipleMentions(): JSX.Element {
|
|||
{
|
||||
start: 4,
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_1,
|
||||
mentionAci: SERVICE_ID_1,
|
||||
replacementText: 'Professor Farnsworth',
|
||||
conversationID: 'x',
|
||||
},
|
||||
{
|
||||
start: 2,
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_2,
|
||||
mentionAci: SERVICE_ID_2,
|
||||
replacementText: 'Philip J Fry',
|
||||
conversationID: 'x',
|
||||
},
|
||||
{
|
||||
start: 0,
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_3,
|
||||
mentionAci: SERVICE_ID_3,
|
||||
replacementText: 'Yancy Fry',
|
||||
conversationID: 'x',
|
||||
},
|
||||
|
@ -73,21 +73,21 @@ export function ComplexMentions(): JSX.Element {
|
|||
{
|
||||
start: 80,
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_4,
|
||||
mentionAci: SERVICE_ID_4,
|
||||
replacementText: 'Cereal Killer',
|
||||
conversationID: 'x',
|
||||
},
|
||||
{
|
||||
start: 78,
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_5,
|
||||
mentionAci: SERVICE_ID_5,
|
||||
replacementText: 'Acid Burn',
|
||||
conversationID: 'x',
|
||||
},
|
||||
{
|
||||
start: 4,
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_6,
|
||||
mentionAci: SERVICE_ID_6,
|
||||
replacementText: 'Zero Cool',
|
||||
conversationID: 'x',
|
||||
},
|
||||
|
@ -109,7 +109,7 @@ export function WithOddCharacter(): JSX.Element {
|
|||
{
|
||||
start: 4,
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_6,
|
||||
mentionAci: SERVICE_ID_6,
|
||||
replacementText: 'Zero Cool',
|
||||
conversationID: 'x',
|
||||
},
|
||||
|
|
|
@ -45,7 +45,7 @@ const getCommonProps = (options: {
|
|||
? GroupCallStatus.GenericGroupCall
|
||||
: DirectCallStatus.Pending,
|
||||
callCreator = getDefaultConversation({
|
||||
uuid: generateAci(),
|
||||
serviceId: generateAci(),
|
||||
isMe: direction === CallDirection.Outgoing,
|
||||
}),
|
||||
callExternalState = CallExternalState.Active,
|
||||
|
@ -63,7 +63,7 @@ const getCommonProps = (options: {
|
|||
callHistory: {
|
||||
callId: '123',
|
||||
peerId: conversation.id,
|
||||
ringerId: callCreator?.uuid ?? null,
|
||||
ringerId: callCreator?.serviceId ?? null,
|
||||
mode,
|
||||
type,
|
||||
direction,
|
||||
|
|
|
@ -44,7 +44,7 @@ const renderChange = (
|
|||
areWeAdmin = true,
|
||||
}: {
|
||||
groupMemberships?: ReadonlyArray<{
|
||||
uuid: AciString;
|
||||
aci: AciString;
|
||||
isAdmin: boolean;
|
||||
}>;
|
||||
groupBannedMemberships?: ReadonlyArray<ServiceIdString>;
|
||||
|
@ -92,7 +92,7 @@ export function Multiple(): JSX.Element {
|
|||
},
|
||||
{
|
||||
type: 'member-add',
|
||||
uuid: OUR_ACI,
|
||||
aci: OUR_ACI,
|
||||
},
|
||||
{
|
||||
type: 'description',
|
||||
|
@ -100,7 +100,7 @@ export function Multiple(): JSX.Element {
|
|||
},
|
||||
{
|
||||
type: 'member-privilege',
|
||||
uuid: OUR_ACI,
|
||||
aci: OUR_ACI,
|
||||
newPrivilege: RoleEnum.ADMINISTRATOR,
|
||||
},
|
||||
],
|
||||
|
@ -451,7 +451,7 @@ export function MemberAdd(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add',
|
||||
uuid: OUR_ACI,
|
||||
aci: OUR_ACI,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -460,7 +460,7 @@ export function MemberAdd(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add',
|
||||
uuid: OUR_ACI,
|
||||
aci: OUR_ACI,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -468,7 +468,7 @@ export function MemberAdd(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add',
|
||||
uuid: OUR_ACI,
|
||||
aci: OUR_ACI,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -477,7 +477,7 @@ export function MemberAdd(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -486,7 +486,7 @@ export function MemberAdd(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -494,7 +494,7 @@ export function MemberAdd(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -511,7 +511,7 @@ export function MemberAddFromInvited(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add-from-invite',
|
||||
uuid: OUR_ACI,
|
||||
aci: OUR_ACI,
|
||||
inviter: CONTACT_B,
|
||||
},
|
||||
],
|
||||
|
@ -520,7 +520,7 @@ export function MemberAddFromInvited(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add-from-invite',
|
||||
uuid: OUR_ACI,
|
||||
aci: OUR_ACI,
|
||||
inviter: CONTACT_A,
|
||||
},
|
||||
],
|
||||
|
@ -531,7 +531,7 @@ export function MemberAddFromInvited(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add-from-invite',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
inviter: CONTACT_B,
|
||||
},
|
||||
],
|
||||
|
@ -541,7 +541,7 @@ export function MemberAddFromInvited(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add-from-invite',
|
||||
uuid: CONTACT_B,
|
||||
aci: CONTACT_B,
|
||||
inviter: CONTACT_C,
|
||||
},
|
||||
],
|
||||
|
@ -550,7 +550,7 @@ export function MemberAddFromInvited(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add-from-invite',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
inviter: CONTACT_B,
|
||||
},
|
||||
],
|
||||
|
@ -561,7 +561,7 @@ export function MemberAddFromInvited(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add-from-invite',
|
||||
uuid: OUR_ACI,
|
||||
aci: OUR_ACI,
|
||||
inviter: CONTACT_A,
|
||||
},
|
||||
],
|
||||
|
@ -571,7 +571,7 @@ export function MemberAddFromInvited(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add-from-invite',
|
||||
uuid: OUR_ACI,
|
||||
aci: OUR_ACI,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -580,7 +580,7 @@ export function MemberAddFromInvited(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add-from-invite',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
inviter: OUR_ACI,
|
||||
},
|
||||
],
|
||||
|
@ -590,7 +590,7 @@ export function MemberAddFromInvited(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add-from-invite',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
inviter: CONTACT_B,
|
||||
},
|
||||
],
|
||||
|
@ -600,7 +600,7 @@ export function MemberAddFromInvited(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add-from-invite',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -610,7 +610,7 @@ export function MemberAddFromInvited(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add-from-invite',
|
||||
uuid: OUR_ACI,
|
||||
aci: OUR_ACI,
|
||||
inviter: CONTACT_B,
|
||||
},
|
||||
],
|
||||
|
@ -631,7 +631,7 @@ export function MemberAddFromLink(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add-from-link',
|
||||
uuid: OUR_ACI,
|
||||
aci: OUR_ACI,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -640,7 +640,7 @@ export function MemberAddFromLink(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add-from-link',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -648,7 +648,7 @@ export function MemberAddFromLink(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add-from-link',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -668,7 +668,7 @@ export function MemberAddFromAdminApproval(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add-from-admin-approval',
|
||||
uuid: OUR_ACI,
|
||||
aci: OUR_ACI,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -676,7 +676,7 @@ export function MemberAddFromAdminApproval(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add-from-admin-approval',
|
||||
uuid: OUR_ACI,
|
||||
aci: OUR_ACI,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -685,7 +685,7 @@ export function MemberAddFromAdminApproval(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add-from-admin-approval',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -694,7 +694,7 @@ export function MemberAddFromAdminApproval(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add-from-admin-approval',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -702,7 +702,7 @@ export function MemberAddFromAdminApproval(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-add-from-admin-approval',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -722,7 +722,7 @@ export function MemberRemove(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-remove',
|
||||
uuid: OUR_ACI,
|
||||
aci: OUR_ACI,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -731,7 +731,7 @@ export function MemberRemove(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-remove',
|
||||
uuid: OUR_ACI,
|
||||
aci: OUR_ACI,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -739,7 +739,7 @@ export function MemberRemove(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-remove',
|
||||
uuid: OUR_ACI,
|
||||
aci: OUR_ACI,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -748,7 +748,7 @@ export function MemberRemove(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-remove',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -757,7 +757,7 @@ export function MemberRemove(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-remove',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -766,7 +766,7 @@ export function MemberRemove(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-remove',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -774,7 +774,7 @@ export function MemberRemove(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-remove',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -790,7 +790,7 @@ export function MemberPrivilege(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-privilege',
|
||||
uuid: OUR_ACI,
|
||||
aci: OUR_ACI,
|
||||
newPrivilege: RoleEnum.ADMINISTRATOR,
|
||||
},
|
||||
],
|
||||
|
@ -799,7 +799,7 @@ export function MemberPrivilege(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-privilege',
|
||||
uuid: OUR_ACI,
|
||||
aci: OUR_ACI,
|
||||
newPrivilege: RoleEnum.ADMINISTRATOR,
|
||||
},
|
||||
],
|
||||
|
@ -809,7 +809,7 @@ export function MemberPrivilege(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-privilege',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
newPrivilege: RoleEnum.ADMINISTRATOR,
|
||||
},
|
||||
],
|
||||
|
@ -819,7 +819,7 @@ export function MemberPrivilege(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-privilege',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
newPrivilege: RoleEnum.ADMINISTRATOR,
|
||||
},
|
||||
],
|
||||
|
@ -828,7 +828,7 @@ export function MemberPrivilege(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-privilege',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
newPrivilege: RoleEnum.ADMINISTRATOR,
|
||||
},
|
||||
],
|
||||
|
@ -838,7 +838,7 @@ export function MemberPrivilege(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-privilege',
|
||||
uuid: OUR_ACI,
|
||||
aci: OUR_ACI,
|
||||
newPrivilege: RoleEnum.DEFAULT,
|
||||
},
|
||||
],
|
||||
|
@ -847,7 +847,7 @@ export function MemberPrivilege(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-privilege',
|
||||
uuid: OUR_ACI,
|
||||
aci: OUR_ACI,
|
||||
newPrivilege: RoleEnum.DEFAULT,
|
||||
},
|
||||
],
|
||||
|
@ -857,7 +857,7 @@ export function MemberPrivilege(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-privilege',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
newPrivilege: RoleEnum.DEFAULT,
|
||||
},
|
||||
],
|
||||
|
@ -867,7 +867,7 @@ export function MemberPrivilege(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-privilege',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
newPrivilege: RoleEnum.DEFAULT,
|
||||
},
|
||||
],
|
||||
|
@ -876,7 +876,7 @@ export function MemberPrivilege(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'member-privilege',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
newPrivilege: RoleEnum.DEFAULT,
|
||||
},
|
||||
],
|
||||
|
@ -893,7 +893,7 @@ export function PendingAddOne(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'pending-add-one',
|
||||
uuid: OUR_ACI,
|
||||
serviceId: OUR_ACI,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -901,7 +901,7 @@ export function PendingAddOne(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'pending-add-one',
|
||||
uuid: OUR_ACI,
|
||||
serviceId: OUR_ACI,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -910,7 +910,7 @@ export function PendingAddOne(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'pending-add-one',
|
||||
uuid: INVITEE_A,
|
||||
serviceId: INVITEE_A,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -919,7 +919,7 @@ export function PendingAddOne(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'pending-add-one',
|
||||
uuid: INVITEE_A,
|
||||
serviceId: INVITEE_A,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -927,7 +927,7 @@ export function PendingAddOne(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'pending-add-one',
|
||||
uuid: INVITEE_A,
|
||||
serviceId: INVITEE_A,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -984,7 +984,7 @@ export function PendingRemoveOne(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'pending-remove-one',
|
||||
uuid: INVITEE_A,
|
||||
serviceId: INVITEE_A,
|
||||
inviter: OUR_ACI,
|
||||
},
|
||||
],
|
||||
|
@ -994,7 +994,7 @@ export function PendingRemoveOne(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'pending-remove-one',
|
||||
uuid: INVITEE_A,
|
||||
serviceId: INVITEE_A,
|
||||
inviter: OUR_ACI,
|
||||
},
|
||||
],
|
||||
|
@ -1004,7 +1004,7 @@ export function PendingRemoveOne(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'pending-remove-one',
|
||||
uuid: INVITEE_A,
|
||||
serviceId: INVITEE_A,
|
||||
inviter: OUR_ACI,
|
||||
},
|
||||
],
|
||||
|
@ -1013,7 +1013,7 @@ export function PendingRemoveOne(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'pending-remove-one',
|
||||
uuid: INVITEE_A,
|
||||
serviceId: INVITEE_A,
|
||||
inviter: OUR_ACI,
|
||||
},
|
||||
],
|
||||
|
@ -1023,7 +1023,7 @@ export function PendingRemoveOne(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'pending-remove-one',
|
||||
uuid: INVITEE_A,
|
||||
serviceId: INVITEE_A,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -1032,7 +1032,7 @@ export function PendingRemoveOne(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'pending-remove-one',
|
||||
uuid: INVITEE_A,
|
||||
serviceId: INVITEE_A,
|
||||
inviter: CONTACT_B,
|
||||
},
|
||||
],
|
||||
|
@ -1043,7 +1043,7 @@ export function PendingRemoveOne(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'pending-remove-one',
|
||||
uuid: OUR_ACI,
|
||||
serviceId: OUR_ACI,
|
||||
inviter: CONTACT_B,
|
||||
},
|
||||
],
|
||||
|
@ -1053,7 +1053,7 @@ export function PendingRemoveOne(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'pending-remove-one',
|
||||
uuid: CONTACT_B,
|
||||
serviceId: CONTACT_B,
|
||||
inviter: CONTACT_A,
|
||||
},
|
||||
],
|
||||
|
@ -1064,7 +1064,7 @@ export function PendingRemoveOne(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'pending-remove-one',
|
||||
uuid: INVITEE_A,
|
||||
serviceId: INVITEE_A,
|
||||
inviter: CONTACT_B,
|
||||
},
|
||||
],
|
||||
|
@ -1074,7 +1074,7 @@ export function PendingRemoveOne(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'pending-remove-one',
|
||||
uuid: INVITEE_A,
|
||||
serviceId: INVITEE_A,
|
||||
inviter: CONTACT_B,
|
||||
},
|
||||
],
|
||||
|
@ -1083,7 +1083,7 @@ export function PendingRemoveOne(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'pending-remove-one',
|
||||
uuid: INVITEE_A,
|
||||
serviceId: INVITEE_A,
|
||||
inviter: CONTACT_B,
|
||||
},
|
||||
],
|
||||
|
@ -1094,7 +1094,7 @@ export function PendingRemoveOne(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'pending-remove-one',
|
||||
uuid: INVITEE_A,
|
||||
serviceId: INVITEE_A,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -1103,7 +1103,7 @@ export function PendingRemoveOne(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'pending-remove-one',
|
||||
uuid: INVITEE_A,
|
||||
serviceId: INVITEE_A,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -1111,7 +1111,7 @@ export function PendingRemoveOne(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'pending-remove-one',
|
||||
uuid: INVITEE_A,
|
||||
serviceId: INVITEE_A,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -1226,7 +1226,7 @@ export function AdminApprovalAdd(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'admin-approval-add-one',
|
||||
uuid: OUR_ACI,
|
||||
aci: OUR_ACI,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -1234,7 +1234,7 @@ export function AdminApprovalAdd(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'admin-approval-add-one',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -1254,7 +1254,7 @@ export function AdminApprovalRemove(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'admin-approval-remove-one',
|
||||
uuid: OUR_ACI,
|
||||
aci: OUR_ACI,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -1262,7 +1262,7 @@ export function AdminApprovalRemove(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'admin-approval-remove-one',
|
||||
uuid: OUR_ACI,
|
||||
aci: OUR_ACI,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -1271,7 +1271,7 @@ export function AdminApprovalRemove(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'admin-approval-remove-one',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
},
|
||||
],
|
||||
})}
|
||||
|
@ -1294,14 +1294,14 @@ export function AdminApprovalBounce(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'admin-approval-bounce',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
times: 1,
|
||||
isApprovalPending: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
groupMemberships: [{ uuid: CONTACT_C, isAdmin: false }],
|
||||
groupMemberships: [{ aci: CONTACT_C, isAdmin: false }],
|
||||
groupBannedMemberships: [CONTACT_B],
|
||||
}
|
||||
)}
|
||||
|
@ -1311,14 +1311,14 @@ export function AdminApprovalBounce(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'admin-approval-bounce',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
times: 1,
|
||||
isApprovalPending: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
groupMemberships: [{ uuid: CONTACT_C, isAdmin: false }],
|
||||
groupMemberships: [{ aci: CONTACT_C, isAdmin: false }],
|
||||
groupBannedMemberships: [CONTACT_B],
|
||||
}
|
||||
)}
|
||||
|
@ -1326,7 +1326,7 @@ export function AdminApprovalBounce(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'admin-approval-bounce',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
times: 1,
|
||||
isApprovalPending: false,
|
||||
},
|
||||
|
@ -1340,7 +1340,7 @@ export function AdminApprovalBounce(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'admin-approval-bounce',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
times: 1,
|
||||
isApprovalPending: false,
|
||||
},
|
||||
|
@ -1356,13 +1356,13 @@ export function AdminApprovalBounce(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'admin-approval-bounce',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
times: 1,
|
||||
isApprovalPending: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{ groupMemberships: [{ uuid: CONTACT_A, isAdmin: false }] }
|
||||
{ groupMemberships: [{ aci: CONTACT_A, isAdmin: false }] }
|
||||
)}
|
||||
Would show button, but user is already banned:
|
||||
{renderChange(
|
||||
|
@ -1371,7 +1371,7 @@ export function AdminApprovalBounce(): JSX.Element {
|
|||
details: [
|
||||
{
|
||||
type: 'admin-approval-bounce',
|
||||
uuid: CONTACT_A,
|
||||
aci: CONTACT_A,
|
||||
times: 1,
|
||||
isApprovalPending: false,
|
||||
},
|
||||
|
|
|
@ -30,7 +30,7 @@ export type PropsDataType = {
|
|||
areWeAdmin: boolean;
|
||||
conversationId: string;
|
||||
groupMemberships?: ReadonlyArray<{
|
||||
uuid: AciString;
|
||||
aci: AciString;
|
||||
isAdmin: boolean;
|
||||
}>;
|
||||
groupBannedMemberships?: ReadonlyArray<ServiceIdString>;
|
||||
|
@ -116,7 +116,7 @@ function getIcon(
|
|||
): GroupIconType {
|
||||
const changeType = detail.type;
|
||||
let possibleIcon = changeToIconMap.get(changeType);
|
||||
const isSameId = fromId === get(detail, 'uuid', null);
|
||||
const isSameId = fromId === get(detail, 'aci', null);
|
||||
if (isSameId) {
|
||||
if (changeType === 'member-remove') {
|
||||
possibleIcon = 'group-leave';
|
||||
|
@ -154,13 +154,13 @@ function GroupV2Detail({
|
|||
areWeAdmin: boolean;
|
||||
blockGroupLinkRequests: (
|
||||
conversationId: string,
|
||||
uuid: ServiceIdString
|
||||
serviceId: ServiceIdString
|
||||
) => unknown;
|
||||
conversationId: string;
|
||||
detail: GroupV2ChangeDetailType;
|
||||
isLastText: boolean;
|
||||
groupMemberships?: ReadonlyArray<{
|
||||
uuid: AciString;
|
||||
aci: AciString;
|
||||
isAdmin: boolean;
|
||||
}>;
|
||||
groupBannedMemberships?: ReadonlyArray<ServiceIdString>;
|
||||
|
@ -206,10 +206,10 @@ function GroupV2Detail({
|
|||
if (
|
||||
!isLastText ||
|
||||
detail.type !== 'admin-approval-bounce' ||
|
||||
!detail.uuid
|
||||
!detail.aci
|
||||
) {
|
||||
log.warn(
|
||||
'GroupV2Detail: ConfirmingblockGroupLinkRequests but missing uuid or wrong change type'
|
||||
'GroupV2Detail: ConfirmingblockGroupLinkRequests but missing aci or wrong change type'
|
||||
);
|
||||
modalNode = undefined;
|
||||
break;
|
||||
|
@ -221,7 +221,7 @@ function GroupV2Detail({
|
|||
title={i18n('icu:PendingRequests--block--title')}
|
||||
actions={[
|
||||
{
|
||||
action: () => blockGroupLinkRequests(conversationId, detail.uuid),
|
||||
action: () => blockGroupLinkRequests(conversationId, detail.aci),
|
||||
text: i18n('icu:PendingRequests--block--confirm'),
|
||||
style: 'affirmative',
|
||||
},
|
||||
|
@ -233,7 +233,7 @@ function GroupV2Detail({
|
|||
id="icu:PendingRequests--block--contents"
|
||||
i18n={i18n}
|
||||
components={{
|
||||
name: renderContact(detail.uuid),
|
||||
name: renderContact(detail.aci),
|
||||
}}
|
||||
/>
|
||||
</ConfirmationDialog>
|
||||
|
@ -261,11 +261,11 @@ function GroupV2Detail({
|
|||
isLastText &&
|
||||
detail.type === 'admin-approval-bounce' &&
|
||||
areWeAdmin &&
|
||||
detail.uuid &&
|
||||
detail.uuid !== ourAci &&
|
||||
(!fromId || fromId === detail.uuid) &&
|
||||
!groupMemberships?.some(item => item.uuid === detail.uuid) &&
|
||||
!groupBannedMemberships?.some(uuid => uuid === detail.uuid)
|
||||
detail.aci &&
|
||||
detail.aci !== ourAci &&
|
||||
(!fromId || fromId === detail.aci) &&
|
||||
!groupMemberships?.some(item => item.aci === detail.aci) &&
|
||||
!groupBannedMemberships?.some(serviceId => serviceId === detail.aci)
|
||||
) {
|
||||
buttonNode = (
|
||||
<Button
|
||||
|
|
|
@ -319,7 +319,7 @@ export type PropsActions = {
|
|||
messageExpanded: (id: string, displayLimit: number) => unknown;
|
||||
checkForAccount: (phoneNumber: string) => unknown;
|
||||
|
||||
startConversation: (e164: string, uuid: ServiceIdString) => void;
|
||||
startConversation: (e164: string, serviceId: ServiceIdString) => void;
|
||||
showConversation: ShowConversationType;
|
||||
openGiftBadge: (messageId: string) => void;
|
||||
pushPanelForConversation: PushPanelForConversationActionType;
|
||||
|
@ -516,7 +516,7 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
}
|
||||
|
||||
const { contact, checkForAccount } = this.props;
|
||||
if (contact && contact.firstNumber && !contact.uuid) {
|
||||
if (contact && contact.firstNumber && !contact.serviceId) {
|
||||
checkForAccount(contact.firstNumber);
|
||||
}
|
||||
|
||||
|
@ -1637,7 +1637,7 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
this.getMetadataPlacement() !== MetadataPlacement.NotRendered;
|
||||
|
||||
const otherContent =
|
||||
(contact && contact.firstNumber && contact.uuid) || withCaption;
|
||||
(contact && contact.firstNumber && contact.serviceId) || withCaption;
|
||||
const tabIndex = otherContent ? 0 : -1;
|
||||
|
||||
return (
|
||||
|
@ -1647,10 +1647,10 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
i18n={i18n}
|
||||
onClick={() => {
|
||||
const signalAccount =
|
||||
contact.firstNumber && contact.uuid
|
||||
contact.firstNumber && contact.serviceId
|
||||
? {
|
||||
phoneNumber: contact.firstNumber,
|
||||
uuid: contact.uuid,
|
||||
serviceId: contact.serviceId,
|
||||
}
|
||||
: undefined;
|
||||
|
||||
|
@ -1678,8 +1678,8 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
if (!contact) {
|
||||
return null;
|
||||
}
|
||||
const { firstNumber, uuid } = contact;
|
||||
if (!firstNumber || !uuid) {
|
||||
const { firstNumber, serviceId } = contact;
|
||||
if (!firstNumber || !serviceId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1689,7 +1689,7 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
onClick={e => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
startConversation(firstNumber, uuid);
|
||||
startConversation(firstNumber, serviceId);
|
||||
}}
|
||||
className={classNames(
|
||||
'module-message__send-message-button',
|
||||
|
@ -2456,8 +2456,8 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
return;
|
||||
}
|
||||
|
||||
if (contact && contact.firstNumber && contact.uuid) {
|
||||
startConversation(contact.firstNumber, contact.uuid);
|
||||
if (contact && contact.firstNumber && contact.serviceId) {
|
||||
startConversation(contact.firstNumber, contact.serviceId);
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
@ -2466,10 +2466,10 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
|
||||
if (contact) {
|
||||
const signalAccount =
|
||||
contact.firstNumber && contact.uuid
|
||||
contact.firstNumber && contact.serviceId
|
||||
? {
|
||||
phoneNumber: contact.firstNumber,
|
||||
uuid: contact.uuid,
|
||||
serviceId: contact.serviceId,
|
||||
}
|
||||
: undefined;
|
||||
pushPanelForConversation({
|
||||
|
|
|
@ -128,7 +128,7 @@ export function Mention(): JSX.Element {
|
|||
{
|
||||
start: 5,
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_1,
|
||||
mentionAci: SERVICE_ID_1,
|
||||
replacementText: 'Bender B Rodriguez 🤖',
|
||||
conversationID: 'x',
|
||||
},
|
||||
|
@ -150,21 +150,21 @@ export function MultipleMentions(): JSX.Element {
|
|||
{
|
||||
start: 2,
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_2,
|
||||
mentionAci: SERVICE_ID_2,
|
||||
replacementText: 'Philip J Fry',
|
||||
conversationID: 'x',
|
||||
},
|
||||
{
|
||||
start: 4,
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_3,
|
||||
mentionAci: SERVICE_ID_3,
|
||||
replacementText: 'Professor Farnsworth',
|
||||
conversationID: 'x',
|
||||
},
|
||||
{
|
||||
start: 0,
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_4,
|
||||
mentionAci: SERVICE_ID_4,
|
||||
replacementText: 'Yancy Fry',
|
||||
conversationID: 'x',
|
||||
},
|
||||
|
@ -192,21 +192,21 @@ export function ComplexMessageBody(): JSX.Element {
|
|||
{
|
||||
start: 78,
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_5,
|
||||
mentionAci: SERVICE_ID_5,
|
||||
replacementText: 'Acid Burn',
|
||||
conversationID: 'x',
|
||||
},
|
||||
{
|
||||
start: 80,
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_6,
|
||||
mentionAci: SERVICE_ID_6,
|
||||
replacementText: 'Cereal Killer',
|
||||
conversationID: 'x',
|
||||
},
|
||||
{
|
||||
start: 4,
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_6,
|
||||
mentionAci: SERVICE_ID_6,
|
||||
replacementText: 'Zero Cool',
|
||||
conversationID: 'x',
|
||||
},
|
||||
|
@ -324,14 +324,14 @@ export function FormattingSpoiler(): JSX.Element {
|
|||
{
|
||||
start: 54,
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_7,
|
||||
mentionAci: SERVICE_ID_7,
|
||||
conversationID: 'a',
|
||||
replacementText: '🅰️ Alice',
|
||||
},
|
||||
{
|
||||
start: 60,
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_8,
|
||||
mentionAci: SERVICE_ID_8,
|
||||
conversationID: 'b',
|
||||
replacementText: '🅱️ Bob',
|
||||
},
|
||||
|
@ -384,35 +384,35 @@ export function FormattingNesting(): JSX.Element {
|
|||
{
|
||||
start: 29,
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_7,
|
||||
mentionAci: SERVICE_ID_7,
|
||||
conversationID: 'a',
|
||||
replacementText: '🅰️ Alice',
|
||||
},
|
||||
{
|
||||
start: 61,
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_8,
|
||||
mentionAci: SERVICE_ID_8,
|
||||
conversationID: 'b',
|
||||
replacementText: '🅱️ Bob',
|
||||
},
|
||||
{
|
||||
start: 68,
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_9,
|
||||
mentionAci: SERVICE_ID_9,
|
||||
conversationID: 'c',
|
||||
replacementText: 'Charlie',
|
||||
},
|
||||
{
|
||||
start: 80,
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_10,
|
||||
mentionAci: SERVICE_ID_10,
|
||||
conversationID: 'd',
|
||||
replacementText: 'Dan',
|
||||
},
|
||||
{
|
||||
start: 105,
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_11,
|
||||
mentionAci: SERVICE_ID_11,
|
||||
conversationID: 'e',
|
||||
replacementText: 'Eve',
|
||||
},
|
||||
|
@ -452,7 +452,7 @@ export function FormattingComplex(): JSX.Element {
|
|||
{
|
||||
start: 24,
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_3,
|
||||
mentionAci: SERVICE_ID_3,
|
||||
conversationID: 'x',
|
||||
replacementText: '🤖 Hello',
|
||||
},
|
||||
|
@ -484,7 +484,7 @@ export function FormattingComplex(): JSX.Element {
|
|||
{
|
||||
start: 491,
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_3,
|
||||
mentionAci: SERVICE_ID_3,
|
||||
conversationID: 'x',
|
||||
replacementText: '🤖 Hello',
|
||||
},
|
||||
|
|
|
@ -92,7 +92,7 @@ export function LongTextWithMention(): JSX.Element {
|
|||
{
|
||||
start: 800,
|
||||
length: 1,
|
||||
mentionUuid: generateAci(),
|
||||
mentionAci: generateAci(),
|
||||
conversationID: 'x',
|
||||
replacementText: 'Alice',
|
||||
},
|
||||
|
|
|
@ -267,8 +267,8 @@ const actions = () => ({
|
|||
),
|
||||
blockGroupLinkRequests: action('blockGroupLinkRequests'),
|
||||
checkForAccount: action('checkForAccount'),
|
||||
clearInvitedUuidsForNewlyCreatedGroup: action(
|
||||
'clearInvitedUuidsForNewlyCreatedGroup'
|
||||
clearInvitedServiceIdsForNewlyCreatedGroup: action(
|
||||
'clearInvitedServiceIdsForNewlyCreatedGroup'
|
||||
),
|
||||
setIsNearBottom: action('setIsNearBottom'),
|
||||
loadOlderMessages: action('loadOlderMessages'),
|
||||
|
|
|
@ -148,7 +148,7 @@ export type PropsActionsType = {
|
|||
conversationId: string,
|
||||
groupNameCollisions: ReadonlyDeep<GroupNameCollisionsWithIdsByTitle>
|
||||
) => void;
|
||||
clearInvitedUuidsForNewlyCreatedGroup: () => void;
|
||||
clearInvitedServiceIdsForNewlyCreatedGroup: () => void;
|
||||
clearTargetedMessage: () => unknown;
|
||||
closeContactSpoofingReview: () => void;
|
||||
loadOlderMessages: (conversationId: string, messageId: string) => unknown;
|
||||
|
@ -743,7 +743,7 @@ export class Timeline extends React.Component<
|
|||
public override render(): JSX.Element | null {
|
||||
const {
|
||||
acknowledgeGroupMemberNameCollisions,
|
||||
clearInvitedUuidsForNewlyCreatedGroup,
|
||||
clearInvitedServiceIdsForNewlyCreatedGroup,
|
||||
closeContactSpoofingReview,
|
||||
contactSpoofingReview,
|
||||
getPreferredBadge,
|
||||
|
@ -1139,7 +1139,7 @@ export class Timeline extends React.Component<
|
|||
contacts={invitedContactsForNewlyCreatedGroup}
|
||||
getPreferredBadge={getPreferredBadge}
|
||||
i18n={i18n}
|
||||
onClose={clearInvitedUuidsForNewlyCreatedGroup}
|
||||
onClose={clearInvitedServiceIdsForNewlyCreatedGroup}
|
||||
theme={theme}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -1676,7 +1676,7 @@ Mentions.args = {
|
|||
{
|
||||
start: 0,
|
||||
length: 1,
|
||||
mentionUuid: generateAci(),
|
||||
mentionAci: generateAci(),
|
||||
replacementText: 'Zapp Brannigan',
|
||||
conversationID: 'x',
|
||||
},
|
||||
|
@ -1944,7 +1944,7 @@ EmbeddedContactWithSendMessage.args = {
|
|||
contact: {
|
||||
...fullContact,
|
||||
firstNumber: fullContact.number[0].value,
|
||||
uuid: generateAci(),
|
||||
serviceId: generateAci(),
|
||||
},
|
||||
direction: 'incoming',
|
||||
};
|
||||
|
|
|
@ -234,7 +234,7 @@ export function WithCallHistoryGroup(): JSX.Element {
|
|||
<ConversationDetails
|
||||
{...props}
|
||||
callHistoryGroup={{
|
||||
peerId: props.conversation?.uuid ?? '',
|
||||
peerId: props.conversation?.serviceId ?? '',
|
||||
mode: CallMode.Direct,
|
||||
type: CallType.Video,
|
||||
direction: CallDirection.Incoming,
|
||||
|
|
|
@ -292,7 +292,8 @@ function getConfirmationMessage({
|
|||
}
|
||||
|
||||
const inviter = members.find(
|
||||
({ uuid }) => uuid === firstPendingMembership.metadata.addedByUserId
|
||||
({ serviceId }) =>
|
||||
serviceId === firstPendingMembership.metadata.addedByUserId
|
||||
);
|
||||
|
||||
if (inviter === undefined) {
|
||||
|
@ -412,13 +413,16 @@ function MembersPendingProfileKey({
|
|||
groupedPendingMemberships;
|
||||
|
||||
const otherPendingMemberships = Object.keys(otherPendingMembershipGroups)
|
||||
.map(id => members.find(member => member.uuid === id))
|
||||
.map(id => members.find(member => member.serviceId === id))
|
||||
.filter((member): member is ConversationType => member !== undefined)
|
||||
.map(member => {
|
||||
assertDev(member.uuid, 'We just verified that member has uuid above');
|
||||
assertDev(
|
||||
member.serviceId,
|
||||
'We just verified that member has serviceId above'
|
||||
);
|
||||
return {
|
||||
member,
|
||||
pendingMemberships: otherPendingMembershipGroups[member.uuid],
|
||||
pendingMemberships: otherPendingMembershipGroups[member.serviceId],
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ type PropsType = {
|
|||
| 'sharedGroupNames'
|
||||
| 'title'
|
||||
| 'unblurredAvatarPath'
|
||||
| 'uuid'
|
||||
| 'serviceId'
|
||||
> &
|
||||
(
|
||||
| { badge?: undefined; theme?: ThemeType }
|
||||
|
@ -109,12 +109,12 @@ export const BaseConversationListItem: FunctionComponent<PropsType> =
|
|||
unblurredAvatarPath,
|
||||
unreadCount,
|
||||
unreadMentionsCount,
|
||||
uuid,
|
||||
serviceId,
|
||||
} = props;
|
||||
|
||||
const identifier = id ? cleanId(id) : undefined;
|
||||
const htmlId = useMemo(() => generateUuid(), []);
|
||||
const testId = overrideTestId || groupId || uuid;
|
||||
const testId = overrideTestId || groupId || serviceId;
|
||||
const isUnread = isConversationUnread({ markedUnread, unreadCount });
|
||||
|
||||
const isAvatarNoteToSelf = isBoolean(isNoteToSelf)
|
||||
|
|
|
@ -38,7 +38,7 @@ export type PropsDataType = {
|
|||
| 'title'
|
||||
| 'type'
|
||||
| 'unblurredAvatarPath'
|
||||
| 'uuid'
|
||||
| 'serviceId'
|
||||
>;
|
||||
|
||||
type PropsHousekeepingType = {
|
||||
|
|
|
@ -39,7 +39,7 @@ export type ContactListItemConversationType = Pick<
|
|||
| 'unblurredAvatarPath'
|
||||
| 'username'
|
||||
| 'e164'
|
||||
| 'uuid'
|
||||
| 'serviceId'
|
||||
>;
|
||||
|
||||
type PropsDataType = ContactListItemConversationType & {
|
||||
|
@ -85,7 +85,7 @@ export const ContactListItem: FunctionComponent<PropsType> = React.memo(
|
|||
title,
|
||||
type,
|
||||
unblurredAvatarPath,
|
||||
uuid,
|
||||
serviceId,
|
||||
}) {
|
||||
const [isConfirmingBlocking, setConfirmingBlocking] = useState(false);
|
||||
const [isConfirmingRemoving, setConfirmingRemoving] = useState(false);
|
||||
|
@ -149,7 +149,7 @@ export const ContactListItem: FunctionComponent<PropsType> = React.memo(
|
|||
/>
|
||||
) : (
|
||||
<ContactName
|
||||
isSignalConversation={isSignalConversation({ id, uuid })}
|
||||
isSignalConversation={isSignalConversation({ id, serviceId })}
|
||||
module={HEADER_CONTACT_NAME_CLASS_NAME}
|
||||
title={title}
|
||||
/>
|
||||
|
|
|
@ -64,7 +64,7 @@ export type PropsData = Pick<
|
|||
| 'unblurredAvatarPath'
|
||||
| 'unreadCount'
|
||||
| 'unreadMentionsCount'
|
||||
| 'uuid'
|
||||
| 'serviceId'
|
||||
> & {
|
||||
badge?: BadgeType;
|
||||
};
|
||||
|
@ -108,7 +108,7 @@ export const ConversationListItem: FunctionComponent<Props> = React.memo(
|
|||
unblurredAvatarPath,
|
||||
unreadCount,
|
||||
unreadMentionsCount,
|
||||
uuid,
|
||||
serviceId,
|
||||
}) {
|
||||
const isMuted = Boolean(muteExpiresAt && Date.now() < muteExpiresAt);
|
||||
const headerName = (
|
||||
|
@ -122,7 +122,7 @@ export const ConversationListItem: FunctionComponent<Props> = React.memo(
|
|||
) : (
|
||||
<ContactName
|
||||
module={HEADER_CONTACT_NAME_CLASS_NAME}
|
||||
isSignalConversation={isSignalConversation({ id, uuid })}
|
||||
isSignalConversation={isSignalConversation({ id, serviceId })}
|
||||
title={title}
|
||||
/>
|
||||
)}
|
||||
|
@ -221,7 +221,7 @@ export const ConversationListItem: FunctionComponent<Props> = React.memo(
|
|||
unreadCount={unreadCount}
|
||||
unreadMentionsCount={unreadMentionsCount}
|
||||
unblurredAvatarPath={unblurredAvatarPath}
|
||||
uuid={uuid}
|
||||
serviceId={serviceId}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ export type GroupListItemConversationType = Pick<
|
|||
disabledReason: DisabledReason | undefined;
|
||||
membersCount: number;
|
||||
memberships: ReadonlyArray<{
|
||||
uuid: AciString;
|
||||
aci: AciString;
|
||||
isAdmin: boolean;
|
||||
}>;
|
||||
};
|
||||
|
|
|
@ -203,14 +203,14 @@ export function Mention(): JSX.Element {
|
|||
bodyRanges: [
|
||||
{
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_3,
|
||||
mentionAci: SERVICE_ID_3,
|
||||
replacementText: 'Shoe',
|
||||
conversationID: 'x',
|
||||
start: 113,
|
||||
},
|
||||
{
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_3,
|
||||
mentionAci: SERVICE_ID_3,
|
||||
replacementText: 'Shoe',
|
||||
conversationID: 'x',
|
||||
start: 237,
|
||||
|
@ -235,7 +235,7 @@ export function MentionRegexp(): JSX.Element {
|
|||
bodyRanges: [
|
||||
{
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_3,
|
||||
mentionAci: SERVICE_ID_3,
|
||||
replacementText: 'RegExp',
|
||||
conversationID: 'x',
|
||||
start: 0,
|
||||
|
@ -260,7 +260,7 @@ export function MentionNoMatches(): JSX.Element {
|
|||
bodyRanges: [
|
||||
{
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_3,
|
||||
mentionAci: SERVICE_ID_3,
|
||||
replacementText: 'Neo',
|
||||
conversationID: 'x',
|
||||
start: 0,
|
||||
|
@ -284,14 +284,14 @@ export const _MentionNoMatches = (): JSX.Element => {
|
|||
bodyRanges: [
|
||||
{
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_3,
|
||||
mentionAci: SERVICE_ID_3,
|
||||
replacementText: 'Shoe',
|
||||
conversationID: 'x',
|
||||
start: 113,
|
||||
},
|
||||
{
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_3,
|
||||
mentionAci: SERVICE_ID_3,
|
||||
replacementText: 'Shoe',
|
||||
conversationID: 'x',
|
||||
start: 237,
|
||||
|
@ -316,14 +316,14 @@ export function DoubleMention(): JSX.Element {
|
|||
bodyRanges: [
|
||||
{
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_2,
|
||||
mentionAci: SERVICE_ID_2,
|
||||
replacementText: 'Alice',
|
||||
conversationID: 'x',
|
||||
start: 4,
|
||||
},
|
||||
{
|
||||
length: 1,
|
||||
mentionUuid: SERVICE_ID_1,
|
||||
mentionAci: SERVICE_ID_1,
|
||||
replacementText: 'Bob',
|
||||
conversationID: 'x',
|
||||
start: 6,
|
||||
|
|
|
@ -86,13 +86,15 @@ export function renderChangeDetail<T>(
|
|||
return renderString(id, localizer, components);
|
||||
}
|
||||
|
||||
const isOurUuid = (uuid?: ServiceIdString): boolean => {
|
||||
if (!uuid) {
|
||||
const isOurServiceId = (serviceId?: ServiceIdString): boolean => {
|
||||
if (!serviceId) {
|
||||
return false;
|
||||
}
|
||||
return Boolean((ourAci && uuid === ourAci) || (ourPni && uuid === ourPni));
|
||||
return Boolean(
|
||||
(ourAci && serviceId === ourAci) || (ourPni && serviceId === ourPni)
|
||||
);
|
||||
};
|
||||
const fromYou = isOurUuid(from);
|
||||
const fromYou = isOurServiceId(from);
|
||||
|
||||
if (detail.type === 'create') {
|
||||
if (fromYou) {
|
||||
|
@ -249,8 +251,8 @@ export function renderChangeDetail<T>(
|
|||
return '';
|
||||
}
|
||||
if (detail.type === 'member-add') {
|
||||
const { uuid } = detail;
|
||||
const weAreJoiner = isOurUuid(uuid);
|
||||
const { aci } = detail;
|
||||
const weAreJoiner = isOurServiceId(aci);
|
||||
|
||||
if (weAreJoiner) {
|
||||
if (fromYou) {
|
||||
|
@ -265,25 +267,25 @@ export function renderChangeDetail<T>(
|
|||
}
|
||||
if (fromYou) {
|
||||
return i18n('icu:GroupV2--member-add--other--you', {
|
||||
memberName: renderContact(uuid),
|
||||
memberName: renderContact(aci),
|
||||
});
|
||||
}
|
||||
if (from) {
|
||||
return i18n('icu:GroupV2--member-add--other--other', {
|
||||
adderName: renderContact(from),
|
||||
addeeName: renderContact(uuid),
|
||||
addeeName: renderContact(aci),
|
||||
});
|
||||
}
|
||||
return i18n('icu:GroupV2--member-add--other--unknown', {
|
||||
memberName: renderContact(uuid),
|
||||
memberName: renderContact(aci),
|
||||
});
|
||||
}
|
||||
if (detail.type === 'member-add-from-invite') {
|
||||
const { uuid, inviter } = detail;
|
||||
const weAreJoiner = isOurUuid(uuid);
|
||||
const weAreInviter = isOurUuid(inviter);
|
||||
const { aci, inviter } = detail;
|
||||
const weAreJoiner = isOurServiceId(aci);
|
||||
const weAreInviter = isOurServiceId(inviter);
|
||||
|
||||
if (!from || from !== uuid) {
|
||||
if (!from || from !== aci) {
|
||||
if (weAreJoiner) {
|
||||
// They can't be the same, no fromYou check here
|
||||
if (from) {
|
||||
|
@ -296,17 +298,17 @@ export function renderChangeDetail<T>(
|
|||
|
||||
if (fromYou) {
|
||||
return i18n('icu:GroupV2--member-add--invited--you', {
|
||||
inviteeName: renderContact(uuid),
|
||||
inviteeName: renderContact(aci),
|
||||
});
|
||||
}
|
||||
if (from) {
|
||||
return i18n('icu:GroupV2--member-add--invited--other', {
|
||||
memberName: renderContact(from),
|
||||
inviteeName: renderContact(uuid),
|
||||
inviteeName: renderContact(aci),
|
||||
});
|
||||
}
|
||||
return i18n('icu:GroupV2--member-add--invited--unknown', {
|
||||
inviteeName: renderContact(uuid),
|
||||
inviteeName: renderContact(aci),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -320,12 +322,12 @@ export function renderChangeDetail<T>(
|
|||
}
|
||||
if (weAreInviter) {
|
||||
return i18n('icu:GroupV2--member-add--from-invite--from-you', {
|
||||
inviteeName: renderContact(uuid),
|
||||
inviteeName: renderContact(aci),
|
||||
});
|
||||
}
|
||||
if (inviter) {
|
||||
return i18n('icu:GroupV2--member-add--from-invite--other', {
|
||||
inviteeName: renderContact(uuid),
|
||||
inviteeName: renderContact(aci),
|
||||
inviterName: renderContact(inviter),
|
||||
});
|
||||
}
|
||||
|
@ -333,17 +335,17 @@ export function renderChangeDetail<T>(
|
|||
'icu:GroupV2--member-add--from-invite--other-no-from',
|
||||
|
||||
{
|
||||
inviteeName: renderContact(uuid),
|
||||
inviteeName: renderContact(aci),
|
||||
}
|
||||
);
|
||||
}
|
||||
if (detail.type === 'member-add-from-link') {
|
||||
const { uuid } = detail;
|
||||
const { aci } = detail;
|
||||
|
||||
if (fromYou && isOurUuid(uuid)) {
|
||||
if (fromYou && isOurServiceId(aci)) {
|
||||
return i18n('icu:GroupV2--member-add-from-link--you--you');
|
||||
}
|
||||
if (from && uuid === from) {
|
||||
if (from && aci === from) {
|
||||
return i18n('icu:GroupV2--member-add-from-link--other', {
|
||||
memberName: renderContact(from),
|
||||
});
|
||||
|
@ -353,12 +355,12 @@ export function renderChangeDetail<T>(
|
|||
// from group change events, which always have a sender.
|
||||
log.warn('member-add-from-link change type; we have no from!');
|
||||
return i18n('icu:GroupV2--member-add--other--unknown', {
|
||||
memberName: renderContact(uuid),
|
||||
memberName: renderContact(aci),
|
||||
});
|
||||
}
|
||||
if (detail.type === 'member-add-from-admin-approval') {
|
||||
const { uuid } = detail;
|
||||
const weAreJoiner = isOurUuid(uuid);
|
||||
const { aci } = detail;
|
||||
const weAreJoiner = isOurServiceId(aci);
|
||||
|
||||
if (weAreJoiner) {
|
||||
if (from) {
|
||||
|
@ -381,7 +383,7 @@ export function renderChangeDetail<T>(
|
|||
return i18n(
|
||||
'icu:GroupV2--member-add-from-admin-approval--other--you',
|
||||
|
||||
{ joinerName: renderContact(uuid) }
|
||||
{ joinerName: renderContact(aci) }
|
||||
);
|
||||
}
|
||||
if (from) {
|
||||
|
@ -390,7 +392,7 @@ export function renderChangeDetail<T>(
|
|||
|
||||
{
|
||||
adminName: renderContact(from),
|
||||
joinerName: renderContact(uuid),
|
||||
joinerName: renderContact(aci),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -401,12 +403,12 @@ export function renderChangeDetail<T>(
|
|||
return i18n(
|
||||
'icu:GroupV2--member-add-from-admin-approval--other--unknown',
|
||||
|
||||
{ joinerName: renderContact(uuid) }
|
||||
{ joinerName: renderContact(aci) }
|
||||
);
|
||||
}
|
||||
if (detail.type === 'member-remove') {
|
||||
const { uuid } = detail;
|
||||
const weAreLeaver = isOurUuid(uuid);
|
||||
const { aci } = detail;
|
||||
const weAreLeaver = isOurServiceId(aci);
|
||||
|
||||
if (weAreLeaver) {
|
||||
if (fromYou) {
|
||||
|
@ -422,10 +424,10 @@ export function renderChangeDetail<T>(
|
|||
|
||||
if (fromYou) {
|
||||
return i18n('icu:GroupV2--member-remove--other--you', {
|
||||
memberName: renderContact(uuid),
|
||||
memberName: renderContact(aci),
|
||||
});
|
||||
}
|
||||
if (from && from === uuid) {
|
||||
if (from && from === aci) {
|
||||
return i18n('icu:GroupV2--member-remove--other--self', {
|
||||
memberName: renderContact(from),
|
||||
});
|
||||
|
@ -433,16 +435,16 @@ export function renderChangeDetail<T>(
|
|||
if (from) {
|
||||
return i18n('icu:GroupV2--member-remove--other--other', {
|
||||
adminName: renderContact(from),
|
||||
memberName: renderContact(uuid),
|
||||
memberName: renderContact(aci),
|
||||
});
|
||||
}
|
||||
return i18n('icu:GroupV2--member-remove--other--unknown', {
|
||||
memberName: renderContact(uuid),
|
||||
memberName: renderContact(aci),
|
||||
});
|
||||
}
|
||||
if (detail.type === 'member-privilege') {
|
||||
const { uuid, newPrivilege } = detail;
|
||||
const weAreMember = isOurUuid(uuid);
|
||||
const { aci, newPrivilege } = detail;
|
||||
const weAreMember = isOurServiceId(aci);
|
||||
|
||||
if (newPrivilege === RoleEnum.ADMINISTRATOR) {
|
||||
if (weAreMember) {
|
||||
|
@ -459,17 +461,17 @@ export function renderChangeDetail<T>(
|
|||
|
||||
if (fromYou) {
|
||||
return i18n('icu:GroupV2--member-privilege--promote--other--you', {
|
||||
memberName: renderContact(uuid),
|
||||
memberName: renderContact(aci),
|
||||
});
|
||||
}
|
||||
if (from) {
|
||||
return i18n('icu:GroupV2--member-privilege--promote--other--other', {
|
||||
adminName: renderContact(from),
|
||||
memberName: renderContact(uuid),
|
||||
memberName: renderContact(aci),
|
||||
});
|
||||
}
|
||||
return i18n('icu:GroupV2--member-privilege--promote--other--unknown', {
|
||||
memberName: renderContact(uuid),
|
||||
memberName: renderContact(aci),
|
||||
});
|
||||
}
|
||||
if (newPrivilege === RoleEnum.DEFAULT) {
|
||||
|
@ -484,7 +486,7 @@ export function renderChangeDetail<T>(
|
|||
|
||||
if (fromYou) {
|
||||
return i18n('icu:GroupV2--member-privilege--demote--other--you', {
|
||||
memberName: renderContact(uuid),
|
||||
memberName: renderContact(aci),
|
||||
});
|
||||
}
|
||||
if (from) {
|
||||
|
@ -493,14 +495,14 @@ export function renderChangeDetail<T>(
|
|||
|
||||
{
|
||||
adminName: renderContact(from),
|
||||
memberName: renderContact(uuid),
|
||||
memberName: renderContact(aci),
|
||||
}
|
||||
);
|
||||
}
|
||||
return i18n(
|
||||
'icu:GroupV2--member-privilege--demote--other--unknown',
|
||||
|
||||
{ memberName: renderContact(uuid) }
|
||||
{ memberName: renderContact(aci) }
|
||||
);
|
||||
}
|
||||
log.warn(
|
||||
|
@ -509,8 +511,8 @@ export function renderChangeDetail<T>(
|
|||
return '';
|
||||
}
|
||||
if (detail.type === 'pending-add-one') {
|
||||
const { uuid } = detail;
|
||||
const weAreInvited = isOurUuid(uuid);
|
||||
const { serviceId } = detail;
|
||||
const weAreInvited = isOurServiceId(serviceId);
|
||||
if (weAreInvited) {
|
||||
if (from) {
|
||||
return i18n('icu:GroupV2--pending-add--one--you--other', {
|
||||
|
@ -521,7 +523,7 @@ export function renderChangeDetail<T>(
|
|||
}
|
||||
if (fromYou) {
|
||||
return i18n('icu:GroupV2--pending-add--one--other--you', {
|
||||
inviteeName: renderContact(uuid),
|
||||
inviteeName: renderContact(serviceId),
|
||||
});
|
||||
}
|
||||
if (from) {
|
||||
|
@ -550,23 +552,23 @@ export function renderChangeDetail<T>(
|
|||
});
|
||||
}
|
||||
if (detail.type === 'pending-remove-one') {
|
||||
const { inviter, uuid } = detail;
|
||||
const weAreInviter = isOurUuid(inviter);
|
||||
const weAreInvited = isOurUuid(uuid);
|
||||
const sentByInvited = Boolean(from && from === uuid);
|
||||
const { inviter, serviceId } = detail;
|
||||
const weAreInviter = isOurServiceId(inviter);
|
||||
const weAreInvited = isOurServiceId(serviceId);
|
||||
const sentByInvited = Boolean(from && from === serviceId);
|
||||
const sentByInviter = Boolean(from && inviter && from === inviter);
|
||||
|
||||
if (weAreInviter) {
|
||||
if (sentByInvited) {
|
||||
return i18n('icu:GroupV2--pending-remove--decline--you', {
|
||||
inviteeName: renderContact(uuid),
|
||||
inviteeName: renderContact(serviceId),
|
||||
});
|
||||
}
|
||||
if (fromYou) {
|
||||
return i18n(
|
||||
'icu:GroupV2--pending-remove--revoke-invite-from-you--one--you',
|
||||
|
||||
{ inviteeName: renderContact(uuid) }
|
||||
{ inviteeName: renderContact(serviceId) }
|
||||
);
|
||||
}
|
||||
if (from) {
|
||||
|
@ -575,14 +577,14 @@ export function renderChangeDetail<T>(
|
|||
|
||||
{
|
||||
adminName: renderContact(from),
|
||||
inviteeName: renderContact(uuid),
|
||||
inviteeName: renderContact(serviceId),
|
||||
}
|
||||
);
|
||||
}
|
||||
return i18n(
|
||||
'icu:GroupV2--pending-remove--revoke-invite-from-you--one--unknown',
|
||||
|
||||
{ inviteeName: renderContact(uuid) }
|
||||
{ inviteeName: renderContact(serviceId) }
|
||||
);
|
||||
}
|
||||
if (sentByInvited) {
|
||||
|
@ -646,7 +648,7 @@ export function renderChangeDetail<T>(
|
|||
}
|
||||
if (detail.type === 'pending-remove-many') {
|
||||
const { count, inviter } = detail;
|
||||
const weAreInviter = isOurUuid(inviter);
|
||||
const weAreInviter = isOurServiceId(inviter);
|
||||
|
||||
if (weAreInviter) {
|
||||
if (fromYou) {
|
||||
|
@ -725,19 +727,19 @@ export function renderChangeDetail<T>(
|
|||
);
|
||||
}
|
||||
if (detail.type === 'admin-approval-add-one') {
|
||||
const { uuid } = detail;
|
||||
const weAreJoiner = isOurUuid(uuid);
|
||||
const { aci } = detail;
|
||||
const weAreJoiner = isOurServiceId(aci);
|
||||
|
||||
if (weAreJoiner) {
|
||||
return i18n('icu:GroupV2--admin-approval-add-one--you');
|
||||
}
|
||||
return i18n('icu:GroupV2--admin-approval-add-one--other', {
|
||||
joinerName: renderContact(uuid),
|
||||
joinerName: renderContact(aci),
|
||||
});
|
||||
}
|
||||
if (detail.type === 'admin-approval-remove-one') {
|
||||
const { uuid } = detail;
|
||||
const weAreJoiner = isOurUuid(uuid);
|
||||
const { aci } = detail;
|
||||
const weAreJoiner = isOurServiceId(aci);
|
||||
|
||||
if (weAreJoiner) {
|
||||
if (fromYou) {
|
||||
|
@ -750,14 +752,14 @@ export function renderChangeDetail<T>(
|
|||
return i18n(
|
||||
'icu:GroupV2--admin-approval-remove-one--other--you',
|
||||
|
||||
{ joinerName: renderContact(uuid) }
|
||||
{ joinerName: renderContact(aci) }
|
||||
);
|
||||
}
|
||||
if (from && from === uuid) {
|
||||
if (from && from === aci) {
|
||||
return i18n(
|
||||
'icu:GroupV2--admin-approval-remove-one--other--own',
|
||||
|
||||
{ joinerName: renderContact(uuid) }
|
||||
{ joinerName: renderContact(aci) }
|
||||
);
|
||||
}
|
||||
if (from) {
|
||||
|
@ -766,7 +768,7 @@ export function renderChangeDetail<T>(
|
|||
|
||||
{
|
||||
adminName: renderContact(from),
|
||||
joinerName: renderContact(uuid),
|
||||
joinerName: renderContact(aci),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -776,20 +778,20 @@ export function renderChangeDetail<T>(
|
|||
return i18n(
|
||||
'icu:GroupV2--admin-approval-remove-one--other--own',
|
||||
|
||||
{ joinerName: renderContact(uuid) }
|
||||
{ joinerName: renderContact(aci) }
|
||||
);
|
||||
}
|
||||
if (detail.type === 'admin-approval-bounce') {
|
||||
const { uuid, times, isApprovalPending } = detail;
|
||||
const { aci, times, isApprovalPending } = detail;
|
||||
|
||||
let firstMessage: T | string;
|
||||
if (times === 1) {
|
||||
firstMessage = i18n('icu:GroupV2--admin-approval-bounce--one', {
|
||||
joinerName: renderContact(uuid),
|
||||
joinerName: renderContact(aci),
|
||||
});
|
||||
} else {
|
||||
firstMessage = i18n('icu:GroupV2--admin-approval-bounce', {
|
||||
joinerName: renderContact(uuid),
|
||||
joinerName: renderContact(aci),
|
||||
numberOfRequests: times,
|
||||
});
|
||||
}
|
||||
|
@ -801,7 +803,7 @@ export function renderChangeDetail<T>(
|
|||
const secondMessage = renderChangeDetail(
|
||||
{
|
||||
type: 'admin-approval-add-one',
|
||||
uuid,
|
||||
aci,
|
||||
},
|
||||
options
|
||||
);
|
||||
|
|
583
ts/groups.ts
583
ts/groups.ts
File diff suppressed because it is too large
Load diff
|
@ -2,13 +2,14 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { useEffect } from 'react';
|
||||
import type { AciString } from '../types/ServiceId';
|
||||
import { usePrevious } from './usePrevious';
|
||||
|
||||
type RemoteParticipant = {
|
||||
hasRemoteVideo: boolean;
|
||||
presenting: boolean;
|
||||
title: string;
|
||||
uuid?: string;
|
||||
aci?: AciString;
|
||||
};
|
||||
|
||||
export function useActivateSpeakerViewOnPresenting({
|
||||
|
@ -20,20 +21,20 @@ export function useActivateSpeakerViewOnPresenting({
|
|||
switchToPresentationView: () => void;
|
||||
switchFromPresentationView: () => void;
|
||||
}): void {
|
||||
const presenterUuid = remoteParticipants.find(
|
||||
const presenterAci = remoteParticipants.find(
|
||||
participant => participant.presenting
|
||||
)?.uuid;
|
||||
const prevPresenterUuid = usePrevious(presenterUuid, presenterUuid);
|
||||
)?.aci;
|
||||
const prevPresenterAci = usePrevious(presenterAci, presenterAci);
|
||||
|
||||
useEffect(() => {
|
||||
if (prevPresenterUuid !== presenterUuid && presenterUuid) {
|
||||
if (prevPresenterAci !== presenterAci && presenterAci) {
|
||||
switchToPresentationView();
|
||||
} else if (prevPresenterUuid && !presenterUuid) {
|
||||
} else if (prevPresenterAci && !presenterAci) {
|
||||
switchFromPresentationView();
|
||||
}
|
||||
}, [
|
||||
presenterUuid,
|
||||
prevPresenterUuid,
|
||||
presenterAci,
|
||||
prevPresenterAci,
|
||||
switchToPresentationView,
|
||||
switchFromPresentationView,
|
||||
]);
|
||||
|
|
|
@ -39,6 +39,7 @@ import type { ServiceIdString } from '../types/ServiceId';
|
|||
import { commonShouldJobContinue } from './helpers/commonShouldJobContinue';
|
||||
import { sleeper } from '../util/sleeper';
|
||||
import { receiptSchema, ReceiptType } from '../types/Receipt';
|
||||
import { serviceIdSchema, aciSchema } from '../types/ServiceId';
|
||||
import { sendResendRequest } from './helpers/sendResendRequest';
|
||||
import { sendNullMessage } from './helpers/sendNullMessage';
|
||||
import { sendSenderKeyDistribution } from './helpers/sendSenderKeyDistribution';
|
||||
|
@ -82,12 +83,7 @@ const deleteStoryForEveryoneJobDataSchema = z.object({
|
|||
updatedStoryRecipients: z
|
||||
.array(
|
||||
z.object({
|
||||
// TODO: DESKTOP-5630
|
||||
destinationUuid: z.string().optional(),
|
||||
legacyDestinationUuid: z.string().optional(),
|
||||
|
||||
destinationAci: z.string().optional(),
|
||||
destinationPni: z.string().optional(),
|
||||
destinationServiceId: serviceIdSchema.optional(),
|
||||
distributionListIds: z.array(z.string()),
|
||||
isAllowedToReply: z.boolean(),
|
||||
})
|
||||
|
@ -162,7 +158,7 @@ const resendRequestJobDataSchema = z.object({
|
|||
plaintext: z.string(),
|
||||
receivedAtCounter: z.number(),
|
||||
receivedAtDate: z.number(),
|
||||
senderUuid: z.string(),
|
||||
senderAci: aciSchema,
|
||||
senderDevice: z.number(),
|
||||
timestamp: z.number(),
|
||||
});
|
||||
|
|
|
@ -5,6 +5,7 @@ import { assertDev } from '../../util/assert';
|
|||
import { isDirectConversation } from '../../util/whatTypeOfConversation';
|
||||
import * as log from '../../logging/log';
|
||||
import type { ConversationAttributesType } from '../../model-types.d';
|
||||
import { isAciString } from '../../types/ServiceId';
|
||||
import type { reportSpamJobQueue } from '../reportSpamJobQueue';
|
||||
|
||||
export async function addReportSpamJob({
|
||||
|
@ -13,7 +14,10 @@ export async function addReportSpamJob({
|
|||
jobQueue,
|
||||
}: Readonly<{
|
||||
conversation: Readonly<
|
||||
Pick<ConversationAttributesType, 'id' | 'type' | 'uuid' | 'reportingToken'>
|
||||
Pick<
|
||||
ConversationAttributesType,
|
||||
'id' | 'type' | 'serviceId' | 'reportingToken'
|
||||
>
|
||||
>;
|
||||
getMessageServerGuidsForSpam: (
|
||||
conversationId: string
|
||||
|
@ -25,10 +29,10 @@ export async function addReportSpamJob({
|
|||
'addReportSpamJob: cannot report spam for non-direct conversations'
|
||||
);
|
||||
|
||||
const { uuid } = conversation;
|
||||
if (!uuid) {
|
||||
const { serviceId: aci } = conversation;
|
||||
if (!aci || !isAciString(aci)) {
|
||||
log.info(
|
||||
'addReportSpamJob got a conversation with no UUID, which the server does not support. Doing nothing'
|
||||
'addReportSpamJob got a conversation with no aci, which the server does not support. Doing nothing'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
@ -44,5 +48,5 @@ export async function addReportSpamJob({
|
|||
return;
|
||||
}
|
||||
|
||||
await jobQueue.add({ uuid, serverGuids, token: conversation.reportingToken });
|
||||
await jobQueue.add({ aci, serverGuids, token: conversation.reportingToken });
|
||||
}
|
||||
|
|
|
@ -243,7 +243,7 @@ export async function sendDeleteStoryForEveryone(
|
|||
destination: undefined,
|
||||
destinationServiceId,
|
||||
storyMessageRecipients: updatedStoryRecipients?.map(
|
||||
({ destinationUuid: legacyDestinationUuid, ...rest }) => {
|
||||
({ destinationServiceId: legacyDestinationUuid, ...rest }) => {
|
||||
return {
|
||||
// The field was renamed.
|
||||
legacyDestinationUuid,
|
||||
|
|
|
@ -559,12 +559,11 @@ async function getMessageSendData({
|
|||
});
|
||||
|
||||
const storyReaction = message.get('storyReaction');
|
||||
const storySourceUuid = storyMessage?.get('sourceUuid');
|
||||
const storySourceServiceId = storyMessage?.get('sourceServiceId');
|
||||
|
||||
let reactionForSend: ReactionType | undefined;
|
||||
if (storyReaction) {
|
||||
const { targetAuthorUuid: targetAuthorAci, ...restOfReaction } =
|
||||
storyReaction;
|
||||
const { targetAuthorAci, ...restOfReaction } = storyReaction;
|
||||
|
||||
reactionForSend = {
|
||||
...restOfReaction,
|
||||
|
@ -592,9 +591,9 @@ async function getMessageSendData({
|
|||
storyMessage,
|
||||
storyContext: storyMessage
|
||||
? {
|
||||
authorAci: storySourceUuid
|
||||
authorAci: storySourceServiceId
|
||||
? normalizeAci(
|
||||
storySourceUuid,
|
||||
storySourceServiceId,
|
||||
'sendNormalMessage.storyContext.authorAci'
|
||||
)
|
||||
: undefined,
|
||||
|
@ -716,11 +715,8 @@ async function uploadMessageQuote(
|
|||
return {
|
||||
isGiftBadge: loadedQuote.isGiftBadge,
|
||||
id: loadedQuote.id,
|
||||
authorAci: loadedQuote.authorUuid
|
||||
? normalizeAci(
|
||||
loadedQuote.authorUuid,
|
||||
'sendNormalMessage.quote.authorUuid'
|
||||
)
|
||||
authorAci: loadedQuote.authorAci
|
||||
? normalizeAci(loadedQuote.authorAci, 'sendNormalMessage.quote.authorAci')
|
||||
: undefined,
|
||||
text: loadedQuote.text,
|
||||
bodyRanges: loadedQuote.bodyRanges,
|
||||
|
|
|
@ -136,11 +136,8 @@ export async function sendReaction(
|
|||
? await ourProfileKeyService.get()
|
||||
: undefined;
|
||||
|
||||
const {
|
||||
emoji,
|
||||
targetAuthorUuid: targetAuthorAci,
|
||||
...restOfPendingReaction
|
||||
} = pendingReaction;
|
||||
const { emoji, targetAuthorAci, ...restOfPendingReaction } =
|
||||
pendingReaction;
|
||||
|
||||
const reactionForSend = {
|
||||
...restOfPendingReaction,
|
||||
|
|
|
@ -26,7 +26,6 @@ import { drop } from '../../util/drop';
|
|||
import { strictAssert } from '../../util/assert';
|
||||
import type { DecryptionErrorEventData } from '../../textsecure/messageReceiverEvents';
|
||||
import type { LoggerType } from '../../types/Logging';
|
||||
import { isAciString } from '../../types/ServiceId';
|
||||
import { startAutomaticSessionReset } from '../../util/handleRetry';
|
||||
|
||||
function failoverToLocalReset(
|
||||
|
@ -49,9 +48,8 @@ export async function sendResendRequest(
|
|||
timeRemaining,
|
||||
log,
|
||||
}: ConversationQueueJobBundle,
|
||||
{ senderUuid: senderAci, ...restOfData }: ResendRequestJobData
|
||||
{ senderAci, ...restOfData }: ResendRequestJobData
|
||||
): Promise<void> {
|
||||
strictAssert(isAciString(senderAci), 'senderUuid is not an ACI');
|
||||
const data = {
|
||||
...restOfData,
|
||||
senderAci,
|
||||
|
@ -90,9 +88,8 @@ export async function sendResendRequest(
|
|||
// Note: we will send to blocked users, to those still in message request state, etc.
|
||||
// Any needed blocking should still apply once the decryption error is fixed.
|
||||
|
||||
const senderUuid = conversation.get('uuid');
|
||||
if (!senderUuid) {
|
||||
log.error('conversation was missing a uuid, cancelling job.');
|
||||
if (conversation.getAci() !== senderAci) {
|
||||
log.error('conversation was missing a aci, cancelling job.');
|
||||
failoverToLocalReset(log, data);
|
||||
return;
|
||||
}
|
||||
|
@ -113,7 +110,7 @@ export async function sendResendRequest(
|
|||
await handleMessageSend(
|
||||
messaging.sendMessageProtoAndWait({
|
||||
timestamp,
|
||||
recipients: [senderUuid],
|
||||
recipients: [senderAci],
|
||||
proto: plaintext,
|
||||
contentHint: ContentHint.DEFAULT,
|
||||
groupId,
|
||||
|
@ -141,7 +138,7 @@ export async function sendResendRequest(
|
|||
receivedAt: receivedAtDate,
|
||||
receivedAtCounter,
|
||||
sentAt: timestamp,
|
||||
senderUuid,
|
||||
senderAci,
|
||||
wasOpened,
|
||||
});
|
||||
|
||||
|
@ -162,7 +159,7 @@ export async function sendResendRequest(
|
|||
await conversation.addDeliveryIssue({
|
||||
receivedAt: receivedAtDate,
|
||||
receivedAtCounter,
|
||||
senderUuid,
|
||||
senderAci,
|
||||
sentAt: timestamp,
|
||||
});
|
||||
})
|
||||
|
|
|
@ -57,10 +57,10 @@ export async function sendSavedProto(
|
|||
return;
|
||||
}
|
||||
|
||||
const uuid = conversation.get('uuid');
|
||||
if (!uuid) {
|
||||
const serviceId = conversation.getServiceId();
|
||||
if (!serviceId) {
|
||||
log.info(
|
||||
`conversation ${conversation.idForLogging()} was missing uuid, cancelling job.`
|
||||
`conversation ${conversation.idForLogging()} was missing serviceId, cancelling job.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ export async function sendSavedProto(
|
|||
groupId,
|
||||
options: sendOptions,
|
||||
proto,
|
||||
recipients: [uuid],
|
||||
recipients: [serviceId],
|
||||
timestamp: originalTimestamp,
|
||||
urgent,
|
||||
story,
|
||||
|
|
|
@ -206,7 +206,7 @@ export async function sendStory(
|
|||
serviceId: ServiceIdString,
|
||||
canReply?: boolean
|
||||
): void {
|
||||
if (conversation.get('uuid') === serviceId) {
|
||||
if (conversation.getServiceId() === serviceId) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
import { chunk } from 'lodash';
|
||||
import type { LoggerType } from '../../types/Logging';
|
||||
import type { AciString } from '../../types/ServiceId';
|
||||
import { normalizeAci } from '../../types/ServiceId';
|
||||
import { getSendOptions } from '../../util/getSendOptions';
|
||||
import type { SendTypesType } from '../../util/handleMessageSend';
|
||||
|
@ -21,7 +22,7 @@ const CHUNK_SIZE = 100;
|
|||
export type SyncType = {
|
||||
messageId?: string;
|
||||
senderE164?: string;
|
||||
senderUuid?: string;
|
||||
senderAci?: AciString;
|
||||
timestamp: number;
|
||||
};
|
||||
export enum SyncTypeList {
|
||||
|
@ -41,13 +42,18 @@ export function parseRawSyncDataArray(value: unknown): Array<SyncType> {
|
|||
return value.map((item: unknown) => {
|
||||
strictAssert(isRecord(item), 'sync is not an object');
|
||||
|
||||
const { messageId, senderE164, senderUuid, timestamp } = item;
|
||||
const { messageId, senderE164, timestamp } = item;
|
||||
strictAssert(typeof timestamp === 'number', 'timestamp should be a number');
|
||||
|
||||
const rawSenderAci = parseOptionalString('senderAci', item.senderAci);
|
||||
const senderAci = rawSenderAci
|
||||
? normalizeAci(rawSenderAci, 'parseRawSyncDataArray')
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
messageId: parseOptionalString('messageId', messageId),
|
||||
senderE164: parseOptionalString('senderE164', senderE164),
|
||||
senderUuid: parseOptionalString('senderUuid', senderUuid),
|
||||
senderAci,
|
||||
timestamp,
|
||||
};
|
||||
});
|
||||
|
@ -148,11 +154,11 @@ export async function runSyncJob({
|
|||
}
|
||||
}
|
||||
|
||||
const aciSyncs = syncs.map(({ senderUuid, ...rest }) => {
|
||||
const aciSyncs = syncs.map(({ senderAci, ...rest }) => {
|
||||
return {
|
||||
...rest,
|
||||
senderAci: senderUuid
|
||||
? normalizeAci(senderUuid, 'syncHelpers.senderUuid')
|
||||
senderAci: senderAci
|
||||
? normalizeAci(senderAci, 'syncHelpers.senderAci')
|
||||
: undefined,
|
||||
};
|
||||
});
|
||||
|
|
|
@ -7,6 +7,7 @@ import { strictAssert } from '../util/assert';
|
|||
import { waitForOnline } from '../util/waitForOnline';
|
||||
import { isDone as isDeviceLinked } from '../util/registration';
|
||||
import type { LoggerType } from '../types/Logging';
|
||||
import { aciSchema } from '../types/ServiceId';
|
||||
import { map } from '../util/iterables';
|
||||
|
||||
import { JobQueue } from './JobQueue';
|
||||
|
@ -27,7 +28,7 @@ const isRetriable4xxStatus = (code: number): boolean =>
|
|||
RETRYABLE_4XX_FAILURE_STATUSES.has(code);
|
||||
|
||||
const reportSpamJobDataSchema = z.object({
|
||||
uuid: z.string().min(1),
|
||||
aci: aciSchema,
|
||||
token: z.string().optional(),
|
||||
serverGuids: z.string().array().min(1).max(1000),
|
||||
});
|
||||
|
@ -49,7 +50,7 @@ export class ReportSpamJobQueue extends JobQueue<ReportSpamJobData> {
|
|||
{ data }: Readonly<{ data: ReportSpamJobData }>,
|
||||
{ log }: Readonly<{ log: LoggerType }>
|
||||
): Promise<void> {
|
||||
const { uuid: senderUuid, token, serverGuids } = data;
|
||||
const { aci: senderAci, token, serverGuids } = data;
|
||||
|
||||
await new Promise<void>(resolve => {
|
||||
window.storage.onready(resolve);
|
||||
|
@ -68,7 +69,7 @@ export class ReportSpamJobQueue extends JobQueue<ReportSpamJobData> {
|
|||
try {
|
||||
await Promise.all(
|
||||
map(serverGuids, serverGuid =>
|
||||
server.reportMessage({ senderUuid, serverGuid, token })
|
||||
server.reportMessage({ senderAci, serverGuid, token })
|
||||
)
|
||||
);
|
||||
} catch (err: unknown) {
|
||||
|
|
|
@ -67,7 +67,7 @@ export class SingleProtoJobQueue extends JobQueue<SingleProtoJobData> {
|
|||
|
||||
const {
|
||||
contentHint,
|
||||
identifier,
|
||||
serviceId,
|
||||
isSyncMessage,
|
||||
messageIds = [],
|
||||
protoBase64,
|
||||
|
@ -75,14 +75,12 @@ export class SingleProtoJobQueue extends JobQueue<SingleProtoJobData> {
|
|||
urgent,
|
||||
} = data;
|
||||
log.info(
|
||||
`starting ${type} send to ${identifier} with timestamp ${timestamp}`
|
||||
`starting ${type} send to ${serviceId} with timestamp ${timestamp}`
|
||||
);
|
||||
|
||||
const conversation = window.ConversationController.get(identifier);
|
||||
const conversation = window.ConversationController.get(serviceId);
|
||||
if (!conversation) {
|
||||
throw new Error(
|
||||
`Failed to get conversation for identifier ${identifier}`
|
||||
);
|
||||
throw new Error(`Failed to get conversation for serviceId ${serviceId}`);
|
||||
}
|
||||
|
||||
if (!isConversationAccepted(conversation.attributes)) {
|
||||
|
@ -103,13 +101,6 @@ export class SingleProtoJobQueue extends JobQueue<SingleProtoJobData> {
|
|||
);
|
||||
return;
|
||||
}
|
||||
const serviceId = conversation.getServiceId();
|
||||
if (!serviceId) {
|
||||
log.info(
|
||||
`conversation ${conversation.idForLogging()} has no serviceId; refusing to send`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const proto = Proto.Content.decode(Bytes.fromBase64(protoBase64));
|
||||
const options = await getSendOptions(conversation.attributes, {
|
||||
|
|
|
@ -28,7 +28,7 @@ export function forMessage(
|
|||
| 'editMessageTimestamp'
|
||||
| 'sent_at'
|
||||
| 'source'
|
||||
| 'sourceUuid'
|
||||
| 'sourceServiceId'
|
||||
| 'timestamp'
|
||||
| 'type'
|
||||
>
|
||||
|
|
|
@ -23,7 +23,7 @@ import {
|
|||
import type { DeleteSentProtoRecipientOptionsType } from '../sql/Interface';
|
||||
import dataInterface from '../sql/Client';
|
||||
import * as log from '../logging/log';
|
||||
import { getSourceUuid } from '../messages/helpers';
|
||||
import { getSourceServiceId } from '../messages/helpers';
|
||||
import { queueUpdateMessage } from '../util/messageBatcher';
|
||||
import { getMessageSentTimestamp } from '../util/getMessageSentTimestamp';
|
||||
|
||||
|
@ -61,8 +61,8 @@ const deleteSentProtoBatcher = createWaitBatcher({
|
|||
items
|
||||
);
|
||||
|
||||
for (const uuid of successfulPhoneNumberShares) {
|
||||
const convo = window.ConversationController.get(uuid);
|
||||
for (const serviceId of successfulPhoneNumberShares) {
|
||||
const convo = window.ConversationController.get(serviceId);
|
||||
if (!convo) {
|
||||
continue;
|
||||
}
|
||||
|
@ -158,8 +158,8 @@ export class MessageReceipts extends Collection<MessageReceiptModel> {
|
|||
}
|
||||
|
||||
const ourAci = window.textsecure.storage.user.getCheckedAci();
|
||||
const sourceUuid = getSourceUuid(message.attributes);
|
||||
if (ourAci !== sourceUuid) {
|
||||
const sourceServiceId = getSourceServiceId(message.attributes);
|
||||
if (ourAci !== sourceServiceId) {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
@ -327,7 +327,7 @@ export class MessageReceipts extends Collection<MessageReceiptModel> {
|
|||
]);
|
||||
} else {
|
||||
log.warn(
|
||||
`MessageReceipts.onReceipt: Missing uuid or deviceId for deliveredTo ${sourceConversationId}`
|
||||
`MessageReceipts.onReceipt: Missing serviceId or deviceId for deliveredTo ${sourceConversationId}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,16 +43,16 @@ export class MessageRequests extends Collection<MessageRequestModel> {
|
|||
}
|
||||
}
|
||||
|
||||
if (conversation.get('uuid')) {
|
||||
const syncByUuid = this.findWhere({
|
||||
threadAci: conversation.get('uuid'),
|
||||
if (conversation.getServiceId()) {
|
||||
const syncByAci = this.findWhere({
|
||||
threadAci: conversation.getServiceId(),
|
||||
});
|
||||
if (syncByUuid) {
|
||||
if (syncByAci) {
|
||||
log.info(
|
||||
`Found early message request response for UUID ${conversation.idForLogging()}`
|
||||
`Found early message request response for aci ${conversation.idForLogging()}`
|
||||
);
|
||||
this.remove(syncByUuid);
|
||||
return syncByUuid;
|
||||
this.remove(syncByAci);
|
||||
return syncByAci;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ export class MessageRequests extends Collection<MessageRequestModel> {
|
|||
if (!conversation && (threadE164 || threadAci)) {
|
||||
conversation = window.ConversationController.lookupOrCreate({
|
||||
e164: threadE164,
|
||||
uuid: threadAci,
|
||||
serviceId: threadAci,
|
||||
reason: 'MessageRequests.onResponse',
|
||||
});
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ export class Reactions extends Collection<ReactionModel> {
|
|||
const senderId = getContactId(message.attributes);
|
||||
const reactionsBySource = this.filter(re => {
|
||||
const targetSender = window.ConversationController.lookupOrCreate({
|
||||
uuid: re.get('targetAuthorUuid'),
|
||||
serviceId: re.get('targetAuthorAci'),
|
||||
reason: 'Reactions.forMessage',
|
||||
});
|
||||
const targetTimestamp = re.get('targetTimestamp');
|
||||
|
@ -92,7 +92,7 @@ export class Reactions extends Collection<ReactionModel> {
|
|||
// to to figure that out.
|
||||
const targetAuthorConversation =
|
||||
window.ConversationController.lookupOrCreate({
|
||||
uuid: reaction.get('targetAuthorUuid'),
|
||||
serviceId: reaction.get('targetAuthorAci'),
|
||||
reason: 'Reactions.onReaction',
|
||||
});
|
||||
const targetConversationId = targetAuthorConversation?.id;
|
||||
|
@ -122,7 +122,7 @@ export class Reactions extends Collection<ReactionModel> {
|
|||
'No message for reaction',
|
||||
reaction.get('timestamp'),
|
||||
'targeting',
|
||||
reaction.get('targetAuthorUuid'),
|
||||
reaction.get('targetAuthorAci'),
|
||||
reaction.get('targetTimestamp')
|
||||
);
|
||||
|
||||
|
@ -147,7 +147,7 @@ export class Reactions extends Collection<ReactionModel> {
|
|||
if (!targetConversation) {
|
||||
log.info(
|
||||
'No target conversation for reaction',
|
||||
reaction.get('targetAuthorUuid'),
|
||||
reaction.get('targetAuthorAci'),
|
||||
reaction.get('targetTimestamp')
|
||||
);
|
||||
return undefined;
|
||||
|
|
|
@ -48,7 +48,7 @@ async function maybeItIsAReactionReadSync(sync: ReadSyncModel): Promise<void> {
|
|||
notificationService.removeBy({
|
||||
conversationId: readReaction.conversationId,
|
||||
emoji: readReaction.emoji,
|
||||
targetAuthorUuid: readReaction.targetAuthorUuid,
|
||||
targetAuthorAci: readReaction.targetAuthorAci,
|
||||
targetTimestamp: readReaction.targetTimestamp,
|
||||
});
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ export class ReadSyncs extends Collection {
|
|||
forMessage(message: MessageModel): ReadSyncModel | null {
|
||||
const sender = window.ConversationController.lookupOrCreate({
|
||||
e164: message.get('source'),
|
||||
uuid: message.get('sourceUuid'),
|
||||
serviceId: message.get('sourceServiceId'),
|
||||
reason: 'ReadSyncs.forMessage',
|
||||
});
|
||||
const messageTimestamp = getMessageSentTimestamp(message.attributes, {
|
||||
|
@ -95,7 +95,7 @@ export class ReadSyncs extends Collection {
|
|||
const found = messages.find(item => {
|
||||
const sender = window.ConversationController.lookupOrCreate({
|
||||
e164: item.source,
|
||||
uuid: item.sourceUuid,
|
||||
serviceId: item.sourceServiceId,
|
||||
reason: 'ReadSyncs.onSync',
|
||||
});
|
||||
|
||||
|
|
|
@ -29,16 +29,16 @@ export class ViewOnceOpenSyncs extends Collection<ViewOnceOpenSyncModel> {
|
|||
}
|
||||
|
||||
forMessage(message: MessageModel): ViewOnceOpenSyncModel | null {
|
||||
const syncBySourceUuid = this.find(item => {
|
||||
const syncBySourceAci = this.find(item => {
|
||||
return (
|
||||
item.get('sourceAci') === message.get('sourceUuid') &&
|
||||
item.get('sourceAci') === message.get('sourceServiceId') &&
|
||||
item.get('timestamp') === message.get('sent_at')
|
||||
);
|
||||
});
|
||||
if (syncBySourceUuid) {
|
||||
if (syncBySourceAci) {
|
||||
log.info('Found early view once open sync for message');
|
||||
this.remove(syncBySourceUuid);
|
||||
return syncBySourceUuid;
|
||||
this.remove(syncBySourceAci);
|
||||
return syncBySourceAci;
|
||||
}
|
||||
|
||||
const syncBySource = this.find(item => {
|
||||
|
@ -63,7 +63,7 @@ export class ViewOnceOpenSyncs extends Collection<ViewOnceOpenSyncModel> {
|
|||
);
|
||||
|
||||
const found = messages.find(item => {
|
||||
const itemSourceAci = item.sourceUuid;
|
||||
const itemSourceAci = item.sourceServiceId;
|
||||
const syncSourceAci = sync.get('sourceAci');
|
||||
const itemSource = item.source;
|
||||
const syncSource = sync.get('source');
|
||||
|
|
|
@ -43,7 +43,7 @@ export class ViewSyncs extends Collection {
|
|||
forMessage(message: MessageModel): Array<ViewSyncModel> {
|
||||
const sender = window.ConversationController.lookupOrCreate({
|
||||
e164: message.get('source'),
|
||||
uuid: message.get('sourceUuid'),
|
||||
serviceId: message.get('sourceServiceId'),
|
||||
reason: 'ViewSyncs.forMessage',
|
||||
});
|
||||
const messageTimestamp = getMessageSentTimestamp(message.attributes, {
|
||||
|
@ -73,7 +73,7 @@ export class ViewSyncs extends Collection {
|
|||
const found = messages.find(item => {
|
||||
const sender = window.ConversationController.lookupOrCreate({
|
||||
e164: item.source,
|
||||
uuid: item.sourceUuid,
|
||||
serviceId: item.sourceServiceId,
|
||||
reason: 'ViewSyncs.onSync',
|
||||
});
|
||||
|
||||
|
|
|
@ -111,16 +111,16 @@ export function getPaymentEventDescription(
|
|||
export function isQuoteAMatch(
|
||||
message: MessageAttributesType | null | undefined,
|
||||
conversationId: string,
|
||||
quote: Pick<QuotedMessageType, 'id' | 'authorUuid' | 'author'>
|
||||
quote: Pick<QuotedMessageType, 'id' | 'authorAci' | 'author'>
|
||||
): message is MessageAttributesType {
|
||||
if (!message) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const { authorUuid, id } = quote;
|
||||
const { authorAci, id } = quote;
|
||||
const authorConversation = window.ConversationController.lookupOrCreate({
|
||||
e164: 'author' in quote ? quote.author : undefined,
|
||||
uuid: authorUuid,
|
||||
serviceId: authorAci,
|
||||
reason: 'helpers.isQuoteAMatch',
|
||||
});
|
||||
|
||||
|
@ -137,18 +137,18 @@ export function isQuoteAMatch(
|
|||
}
|
||||
|
||||
export function getContactId(
|
||||
message: Pick<MessageAttributesType, 'type' | 'source' | 'sourceUuid'>
|
||||
message: Pick<MessageAttributesType, 'type' | 'source' | 'sourceServiceId'>
|
||||
): string | undefined {
|
||||
const source = getSource(message);
|
||||
const sourceUuid = getSourceUuid(message);
|
||||
const sourceServiceId = getSourceServiceId(message);
|
||||
|
||||
if (!source && !sourceUuid) {
|
||||
if (!source && !sourceServiceId) {
|
||||
return window.ConversationController.getOurConversationId();
|
||||
}
|
||||
|
||||
const conversation = window.ConversationController.lookupOrCreate({
|
||||
e164: source,
|
||||
uuid: sourceUuid,
|
||||
serviceId: sourceServiceId,
|
||||
reason: 'helpers.getContactId',
|
||||
});
|
||||
return conversation?.id;
|
||||
|
@ -191,15 +191,15 @@ export function getSourceDevice(
|
|||
return sourceDevice || window.textsecure.storage.user.getDeviceId();
|
||||
}
|
||||
|
||||
export function getSourceUuid(
|
||||
message: Pick<MessageAttributesType, 'type' | 'sourceUuid'>
|
||||
export function getSourceServiceId(
|
||||
message: Pick<MessageAttributesType, 'type' | 'sourceServiceId'>
|
||||
): ServiceIdString | undefined {
|
||||
if (isIncoming(message) || isStory(message)) {
|
||||
return message.sourceUuid;
|
||||
return message.sourceServiceId;
|
||||
}
|
||||
if (!isOutgoing(message)) {
|
||||
log.warn(
|
||||
'Message.getSourceUuid: Called for non-incoming/non-outgoing message'
|
||||
'Message.getSourceServiceId: Called for non-incoming/non-outgoing message'
|
||||
);
|
||||
}
|
||||
|
||||
|
|
47
ts/model-types.d.ts
vendored
47
ts/model-types.d.ts
vendored
|
@ -49,7 +49,7 @@ export type LastMessageStatus =
|
|||
|
||||
export type SenderKeyDeviceType = {
|
||||
id: number;
|
||||
identifier: string;
|
||||
serviceId: ServiceIdString;
|
||||
registrationId: number;
|
||||
};
|
||||
|
||||
|
@ -69,7 +69,7 @@ export type CustomError = Error & {
|
|||
export type GroupMigrationType = {
|
||||
areWeInvited: boolean;
|
||||
droppedMemberIds: Array<string>;
|
||||
invitedMembers: Array<GroupV2PendingMemberType>;
|
||||
invitedMembers: Array<LegacyMigrationPendingMemberType>;
|
||||
};
|
||||
|
||||
export type QuotedAttachment = {
|
||||
|
@ -86,7 +86,7 @@ export type QuotedMessageType = {
|
|||
// `author` is an old attribute that holds the author's E164. We shouldn't use it for
|
||||
// new messages, but old messages might have this attribute.
|
||||
author?: string;
|
||||
authorUuid?: string;
|
||||
authorAci?: AciString;
|
||||
bodyRanges?: ReadonlyArray<RawBodyRange>;
|
||||
id: number;
|
||||
isGiftBadge?: boolean;
|
||||
|
@ -98,17 +98,10 @@ export type QuotedMessageType = {
|
|||
|
||||
type StoryReplyContextType = {
|
||||
attachment?: AttachmentType;
|
||||
authorUuid?: string;
|
||||
authorAci?: AciString;
|
||||
messageId: string;
|
||||
};
|
||||
|
||||
export type RetryOptions = Readonly<{
|
||||
type: 'session-reset';
|
||||
uuid: string;
|
||||
e164: string;
|
||||
now: number;
|
||||
}>;
|
||||
|
||||
export type GroupV1Update = {
|
||||
avatarUpdated?: boolean;
|
||||
joined?: Array<string>;
|
||||
|
@ -119,7 +112,7 @@ export type GroupV1Update = {
|
|||
export type MessageReactionType = {
|
||||
emoji: undefined | string;
|
||||
fromId: string;
|
||||
targetAuthorUuid: AciString;
|
||||
targetAuthorAci: AciString;
|
||||
targetTimestamp: number;
|
||||
timestamp: number;
|
||||
isSentByConversationId?: Record<string, boolean>;
|
||||
|
@ -169,7 +162,6 @@ export type MessageAttributesType = {
|
|||
quote?: QuotedMessageType;
|
||||
reactions?: ReadonlyArray<MessageReactionType>;
|
||||
requiredProtocolVersion?: number;
|
||||
retryOptions?: RetryOptions;
|
||||
sourceDevice?: number;
|
||||
storyDistributionListId?: StoryDistributionIdString;
|
||||
storyId?: string;
|
||||
|
@ -210,7 +202,7 @@ export type MessageAttributesType = {
|
|||
conversationId: string;
|
||||
storyReaction?: {
|
||||
emoji: string;
|
||||
targetAuthorUuid: AciString;
|
||||
targetAuthorAci: AciString;
|
||||
targetTimestamp: number;
|
||||
};
|
||||
giftBadge?: {
|
||||
|
@ -225,7 +217,7 @@ export type MessageAttributesType = {
|
|||
expireTimer?: DurationInSeconds;
|
||||
fromSync?: unknown;
|
||||
source?: string;
|
||||
sourceUuid?: ServiceIdString;
|
||||
sourceServiceId?: ServiceIdString;
|
||||
};
|
||||
conversationMerge?: {
|
||||
renderInfo: ConversationRenderInfoType;
|
||||
|
@ -249,12 +241,12 @@ export type MessageAttributesType = {
|
|||
serverGuid?: string;
|
||||
serverTimestamp?: number;
|
||||
source?: string;
|
||||
sourceUuid?: ServiceIdString;
|
||||
sourceServiceId?: ServiceIdString;
|
||||
|
||||
timestamp: number;
|
||||
|
||||
// Backwards-compatibility with prerelease data schema
|
||||
invitedGV2Members?: Array<GroupV2PendingMemberType>;
|
||||
invitedGV2Members?: Array<LegacyMigrationPendingMemberType>;
|
||||
droppedGV2MemberIds?: Array<string>;
|
||||
|
||||
sendHQImages?: boolean;
|
||||
|
@ -283,7 +275,7 @@ export type ConversationLastProfileType = Readonly<{
|
|||
|
||||
export type ValidateConversationType = Pick<
|
||||
ConversationAttributesType,
|
||||
'e164' | 'uuid' | 'type' | 'groupId'
|
||||
'e164' | 'serviceId' | 'type' | 'groupId'
|
||||
>;
|
||||
|
||||
export type DraftEditMessageType = {
|
||||
|
@ -378,7 +370,7 @@ export type ConversationAttributesType = {
|
|||
version: number;
|
||||
|
||||
// Private core info
|
||||
uuid?: ServiceIdString;
|
||||
serviceId?: ServiceIdString;
|
||||
pni?: PniString;
|
||||
e164?: string;
|
||||
|
||||
|
@ -470,7 +462,7 @@ export type ConversationRenderInfoType = Pick<
|
|||
>;
|
||||
|
||||
export type GroupV2MemberType = {
|
||||
uuid: AciString;
|
||||
aci: AciString;
|
||||
role: MemberRoleEnum;
|
||||
joinedAtVersion: number;
|
||||
|
||||
|
@ -481,20 +473,27 @@ export type GroupV2MemberType = {
|
|||
approvedByAdmin?: boolean;
|
||||
};
|
||||
|
||||
export type LegacyMigrationPendingMemberType = {
|
||||
addedByUserId?: string;
|
||||
uuid: string;
|
||||
timestamp: number;
|
||||
role: MemberRoleEnum;
|
||||
};
|
||||
|
||||
export type GroupV2PendingMemberType = {
|
||||
addedByUserId?: AciString;
|
||||
uuid: ServiceIdString;
|
||||
serviceId: ServiceIdString;
|
||||
timestamp: number;
|
||||
role: MemberRoleEnum;
|
||||
};
|
||||
|
||||
export type GroupV2BannedMemberType = {
|
||||
uuid: ServiceIdString;
|
||||
serviceId: ServiceIdString;
|
||||
timestamp: number;
|
||||
};
|
||||
|
||||
export type GroupV2PendingAdminApprovalType = {
|
||||
uuid: AciString;
|
||||
aci: AciString;
|
||||
timestamp: number;
|
||||
};
|
||||
|
||||
|
@ -517,7 +516,7 @@ export type ReactionAttributesType = {
|
|||
// Necessary to put 1:1 story replies into the right conversation - not the same
|
||||
// conversation as the target message!
|
||||
storyReactionMessage?: MessageModel;
|
||||
targetAuthorUuid: AciString;
|
||||
targetAuthorAci: AciString;
|
||||
targetTimestamp: number;
|
||||
timestamp: number;
|
||||
};
|
||||
|
|
|
@ -82,7 +82,6 @@ import type { DraftBodyRanges } from '../types/BodyRange';
|
|||
import { BodyRange } from '../types/BodyRange';
|
||||
import { migrateColor } from '../util/migrateColor';
|
||||
import { isNotNil } from '../util/isNotNil';
|
||||
import { resolveSenderKeyDevice } from '../util/resolveSenderKeyDevice';
|
||||
import {
|
||||
NotificationType,
|
||||
notificationService,
|
||||
|
@ -304,15 +303,16 @@ export class ConversationModel extends window.Backbone
|
|||
|
||||
// Note that we intentionally don't use `initialize()` method because it
|
||||
// isn't compatible with esnext output of esbuild.
|
||||
const uuid = this.get('uuid');
|
||||
const serviceId = this.getServiceId();
|
||||
const normalizedServiceId =
|
||||
uuid && normalizeServiceId(uuid, 'ConversationModel.initialize');
|
||||
if (uuid && normalizedServiceId !== uuid) {
|
||||
serviceId &&
|
||||
normalizeServiceId(serviceId, 'ConversationModel.initialize');
|
||||
if (serviceId && normalizedServiceId !== serviceId) {
|
||||
log.warn(
|
||||
'ConversationModel.initialize: normalizing serviceId from ' +
|
||||
`${uuid} to ${normalizedServiceId}`
|
||||
`${serviceId} to ${normalizedServiceId}`
|
||||
);
|
||||
this.set('uuid', normalizedServiceId);
|
||||
this.set('serviceId', normalizedServiceId);
|
||||
}
|
||||
|
||||
if (isValidE164(attributes.id, false)) {
|
||||
|
@ -805,8 +805,8 @@ export class ConversationModel extends window.Backbone
|
|||
}
|
||||
|
||||
const e164 = this.get('e164');
|
||||
const pni = this.get('pni');
|
||||
const aci = this.get('uuid');
|
||||
const pni = this.getPni();
|
||||
const aci = this.getServiceId();
|
||||
if (e164 && pni && aci && pni !== aci) {
|
||||
this.updateE164(undefined);
|
||||
this.updatePni(undefined);
|
||||
|
@ -878,9 +878,9 @@ export class ConversationModel extends window.Backbone
|
|||
let blocked = false;
|
||||
const wasBlocked = this.isBlocked();
|
||||
|
||||
const uuid = this.get('uuid');
|
||||
if (uuid) {
|
||||
drop(window.storage.blocked.addBlockedUuid(uuid));
|
||||
const serviceId = this.getServiceId();
|
||||
if (serviceId) {
|
||||
drop(window.storage.blocked.addBlockedServiceId(serviceId));
|
||||
blocked = true;
|
||||
}
|
||||
|
||||
|
@ -910,9 +910,9 @@ export class ConversationModel extends window.Backbone
|
|||
let unblocked = false;
|
||||
const wasBlocked = this.isBlocked();
|
||||
|
||||
const uuid = this.get('uuid');
|
||||
if (uuid) {
|
||||
drop(window.storage.blocked.removeBlockedUuid(uuid));
|
||||
const serviceId = this.getServiceId();
|
||||
if (serviceId) {
|
||||
drop(window.storage.blocked.removeBlockedServiceId(serviceId));
|
||||
unblocked = true;
|
||||
}
|
||||
|
||||
|
@ -977,10 +977,10 @@ export class ConversationModel extends window.Backbone
|
|||
});
|
||||
|
||||
window.reduxActions?.stories.removeAllContactStories(this.id);
|
||||
const uuid = this.get('uuid');
|
||||
if (uuid) {
|
||||
const serviceId = this.getServiceId();
|
||||
if (serviceId) {
|
||||
window.reduxActions?.storyDistributionLists.removeMemberFromAllDistributionLists(
|
||||
uuid
|
||||
serviceId
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1162,7 +1162,7 @@ export class ConversationModel extends window.Backbone
|
|||
);
|
||||
}
|
||||
|
||||
if (!this.get('uuid')) {
|
||||
if (!this.getServiceId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1353,12 +1353,12 @@ export class ConversationModel extends window.Backbone
|
|||
}
|
||||
|
||||
async onNewMessage(message: MessageModel): Promise<void> {
|
||||
const uuid = message.get('sourceUuid');
|
||||
const serviceId = message.get('sourceServiceId');
|
||||
const e164 = message.get('source');
|
||||
const sourceDevice = message.get('sourceDevice');
|
||||
|
||||
const source = window.ConversationController.lookupOrCreate({
|
||||
uuid,
|
||||
serviceId,
|
||||
e164,
|
||||
reason: 'ConversationModel.onNewMessage',
|
||||
});
|
||||
|
@ -1855,27 +1855,29 @@ export class ConversationModel extends window.Backbone
|
|||
this.captureChange('updateE164');
|
||||
}
|
||||
|
||||
updateUuid(uuid?: ServiceIdString): void {
|
||||
const oldValue = this.get('uuid');
|
||||
if (uuid === oldValue) {
|
||||
updateServiceId(serviceId?: ServiceIdString): void {
|
||||
const oldValue = this.getServiceId();
|
||||
if (serviceId === oldValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.set(
|
||||
'uuid',
|
||||
uuid ? normalizeServiceId(uuid, 'Conversation.updateUuid') : undefined
|
||||
'serviceId',
|
||||
serviceId
|
||||
? normalizeServiceId(serviceId, 'Conversation.updateServiceId')
|
||||
: undefined
|
||||
);
|
||||
window.Signal.Data.updateConversation(this.attributes);
|
||||
this.trigger('idUpdated', this, 'uuid', oldValue);
|
||||
this.trigger('idUpdated', this, 'serviceId', oldValue);
|
||||
|
||||
// We should delete the old sessions and identity information in all situations except
|
||||
// for the case where we need to do old and new PNI comparisons. We'll wait
|
||||
// for the PNI update to do that.
|
||||
if (oldValue && oldValue !== this.get('pni')) {
|
||||
if (oldValue && oldValue !== this.getPni()) {
|
||||
drop(window.textsecure.storage.protocol.removeIdentityKey(oldValue));
|
||||
}
|
||||
|
||||
this.captureChange('updateUuid');
|
||||
this.captureChange('updateServiceId');
|
||||
}
|
||||
|
||||
trackPreviousIdentityKey(publicKey: Uint8Array): void {
|
||||
|
@ -1902,7 +1904,7 @@ export class ConversationModel extends window.Backbone
|
|||
}
|
||||
|
||||
updatePni(pni?: PniString): void {
|
||||
const oldValue = this.get('pni');
|
||||
const oldValue = this.getPni();
|
||||
if (pni === oldValue) {
|
||||
return;
|
||||
}
|
||||
|
@ -1913,9 +1915,9 @@ export class ConversationModel extends window.Backbone
|
|||
);
|
||||
|
||||
const pniIsPrimaryId =
|
||||
!this.get('uuid') ||
|
||||
this.get('uuid') === oldValue ||
|
||||
this.get('uuid') === pni;
|
||||
!this.getServiceId() ||
|
||||
this.getServiceId() === oldValue ||
|
||||
this.getServiceId() === pni;
|
||||
const haveSentMessage = Boolean(
|
||||
this.get('profileSharing') || this.get('sentMessageCount')
|
||||
);
|
||||
|
@ -1958,9 +1960,9 @@ export class ConversationModel extends window.Backbone
|
|||
drop(window.textsecure.storage.protocol.removeIdentityKey(oldValue));
|
||||
}
|
||||
|
||||
if (pni && !this.get('uuid')) {
|
||||
if (pni && !this.getServiceId()) {
|
||||
log.warn(
|
||||
`updatePni/${this.idForLogging()}: pni field set to ${pni}, but uuid field is empty!`
|
||||
`updatePni/${this.idForLogging()}: pni field set to ${pni}, but service id field is empty!`
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2053,14 +2055,19 @@ export class ConversationModel extends window.Backbone
|
|||
type: conversationQueueJobEnum.enum.Receipts,
|
||||
conversationId: this.get('id'),
|
||||
receiptsType: ReceiptType.Read,
|
||||
receipts: readMessages.map(m => ({
|
||||
receipts: readMessages.map(m => {
|
||||
const { sourceServiceId: senderAci } = m;
|
||||
strictAssert(isAciString(senderAci), "Can't send receipt to PNI");
|
||||
|
||||
return {
|
||||
messageId: m.id,
|
||||
conversationId,
|
||||
senderE164: m.source,
|
||||
senderUuid: m.sourceUuid,
|
||||
senderAci,
|
||||
timestamp: getMessageSentTimestamp(m, { log }),
|
||||
isDirectConversation: isDirectConversation(this.attributes),
|
||||
})),
|
||||
};
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -2266,7 +2273,7 @@ export class ConversationModel extends window.Backbone
|
|||
this.set({
|
||||
pendingAdminApprovalV2: [
|
||||
{
|
||||
uuid: ourAci,
|
||||
aci: ourAci,
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
],
|
||||
|
@ -2828,23 +2835,23 @@ export class ConversationModel extends window.Backbone
|
|||
async addDeliveryIssue({
|
||||
receivedAt,
|
||||
receivedAtCounter,
|
||||
senderUuid,
|
||||
senderAci,
|
||||
sentAt,
|
||||
}: {
|
||||
receivedAt: number;
|
||||
receivedAtCounter: number;
|
||||
senderUuid: string;
|
||||
senderAci: AciString;
|
||||
sentAt: number;
|
||||
}): Promise<void> {
|
||||
log.info(`addDeliveryIssue: adding for ${this.idForLogging()}`, {
|
||||
sentAt,
|
||||
senderUuid,
|
||||
senderAci,
|
||||
});
|
||||
|
||||
const message = {
|
||||
conversationId: this.id,
|
||||
type: 'delivery-issue',
|
||||
sourceUuid: senderUuid,
|
||||
sourceServiceId: senderAci,
|
||||
sent_at: receivedAt,
|
||||
received_at: receivedAtCounter,
|
||||
received_at_ms: receivedAt,
|
||||
|
@ -2945,15 +2952,11 @@ export class ConversationModel extends window.Backbone
|
|||
if (senderKeyInfo) {
|
||||
const updatedSenderKeyInfo = {
|
||||
...senderKeyInfo,
|
||||
memberDevices: senderKeyInfo.memberDevices
|
||||
.map(resolveSenderKeyDevice)
|
||||
.filter(isNotNil)
|
||||
.filter(({ serviceId: memberServiceId }) => {
|
||||
memberDevices: senderKeyInfo.memberDevices.filter(
|
||||
({ serviceId: memberServiceId }) => {
|
||||
return memberServiceId !== keyChangedId;
|
||||
})
|
||||
.map(({ serviceId: memberServiceId, ...rest }) => {
|
||||
return { identifier: memberServiceId, ...rest };
|
||||
}),
|
||||
}
|
||||
),
|
||||
};
|
||||
|
||||
this.set('senderKeyInfo', updatedSenderKeyInfo);
|
||||
|
@ -3267,7 +3270,7 @@ export class ConversationModel extends window.Backbone
|
|||
newValue: string
|
||||
): Promise<void> {
|
||||
const sourceServiceId = this.getCheckedServiceId(
|
||||
'Change number notification without uuid'
|
||||
'Change number notification without service id'
|
||||
);
|
||||
|
||||
const { storage } = window.textsecure;
|
||||
|
@ -3299,7 +3302,7 @@ export class ConversationModel extends window.Backbone
|
|||
return convo.addNotification('change-number-notification', {
|
||||
readStatus: ReadStatus.Read,
|
||||
seenStatus: SeenStatus.Unseen,
|
||||
sourceUuid: sourceServiceId,
|
||||
sourceServiceId,
|
||||
});
|
||||
})
|
||||
);
|
||||
|
@ -3379,7 +3382,7 @@ export class ConversationModel extends window.Backbone
|
|||
}
|
||||
|
||||
const members = this.get('membersV2') || [];
|
||||
const member = members.find(x => x.uuid === serviceId);
|
||||
const member = members.find(x => x.aci === serviceId);
|
||||
if (!member) {
|
||||
return false;
|
||||
}
|
||||
|
@ -3390,7 +3393,7 @@ export class ConversationModel extends window.Backbone
|
|||
}
|
||||
|
||||
getServiceId(): ServiceIdString | undefined {
|
||||
return this.get('uuid');
|
||||
return this.get('serviceId');
|
||||
}
|
||||
|
||||
getCheckedServiceId(reason: string): ServiceIdString {
|
||||
|
@ -3400,7 +3403,7 @@ export class ConversationModel extends window.Backbone
|
|||
}
|
||||
|
||||
getAci(): AciString | undefined {
|
||||
const value = this.get('uuid');
|
||||
const value = this.getServiceId();
|
||||
if (value && isAciString(value)) {
|
||||
return value;
|
||||
}
|
||||
|
@ -4483,7 +4486,7 @@ export class ConversationModel extends window.Backbone
|
|||
|
||||
await Promise.all(
|
||||
conversations.map(conversation =>
|
||||
getProfile(conversation.get('uuid'), conversation.get('e164'))
|
||||
getProfile(conversation.getServiceId(), conversation.get('e164'))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -4653,8 +4656,8 @@ export class ConversationModel extends window.Backbone
|
|||
return;
|
||||
}
|
||||
|
||||
const uuid = this.get('uuid');
|
||||
if (!uuid) {
|
||||
const serviceId = this.getServiceId();
|
||||
if (!serviceId) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -4663,7 +4666,7 @@ export class ConversationModel extends window.Backbone
|
|||
return lastProfile.profileKeyVersion;
|
||||
}
|
||||
|
||||
const profileKeyVersion = deriveProfileKeyVersion(profileKey, uuid);
|
||||
const profileKeyVersion = deriveProfileKeyVersion(profileKey, serviceId);
|
||||
if (!profileKeyVersion) {
|
||||
log.warn(
|
||||
'deriveProfileKeyVersion: Failed to derive profile key version, ' +
|
||||
|
@ -4733,7 +4736,7 @@ export class ConversationModel extends window.Backbone
|
|||
hasMember(serviceId: ServiceIdString): boolean {
|
||||
const members = this.getMembers();
|
||||
|
||||
return members.some(member => member.get('uuid') === serviceId);
|
||||
return members.some(member => member.getServiceId() === serviceId);
|
||||
}
|
||||
|
||||
fetchContacts(): void {
|
||||
|
@ -4818,7 +4821,7 @@ export class ConversationModel extends window.Backbone
|
|||
}
|
||||
|
||||
// Set of items to captureChanges on:
|
||||
// [-] uuid
|
||||
// [-] serviceId
|
||||
// [-] e164
|
||||
// [X] profileKey
|
||||
// [-] identityKey
|
||||
|
@ -4912,14 +4915,14 @@ export class ConversationModel extends window.Backbone
|
|||
|
||||
const ourAci = window.textsecure.storage.user.getCheckedAci();
|
||||
const ourPni = window.textsecure.storage.user.getCheckedPni();
|
||||
const ourUuids: Set<ServiceIdString> = new Set([ourAci, ourPni]);
|
||||
const ourServiceIds: Set<ServiceIdString> = new Set([ourAci, ourPni]);
|
||||
|
||||
const mentionsMe = (message.get('bodyRanges') || []).some(bodyRange => {
|
||||
if (!BodyRange.isMention(bodyRange)) {
|
||||
return false;
|
||||
}
|
||||
return ourUuids.has(
|
||||
normalizeServiceId(bodyRange.mentionUuid, 'notify: mentionsMe check')
|
||||
return ourServiceIds.has(
|
||||
normalizeServiceId(bodyRange.mentionAci, 'notify: mentionsMe check')
|
||||
);
|
||||
});
|
||||
if (!mentionsMe) {
|
||||
|
@ -5281,7 +5284,7 @@ window.Whisper.ConversationCollection = window.Backbone.Collection.extend({
|
|||
|
||||
/**
|
||||
* window.Backbone defines a `_byId` field. Here we set up additional `_byE164`,
|
||||
* `_byUuid`, and `_byGroupId` fields so we can track conversations by more
|
||||
* `_byServiceId`, and `_byGroupId` fields so we can track conversations by more
|
||||
* than just their id.
|
||||
*/
|
||||
initialize() {
|
||||
|
@ -5294,8 +5297,8 @@ window.Whisper.ConversationCollection = window.Backbone.Collection.extend({
|
|||
if (idProp === 'e164') {
|
||||
delete this._byE164[oldValue];
|
||||
}
|
||||
if (idProp === 'uuid') {
|
||||
delete this._byUuid[oldValue];
|
||||
if (idProp === 'serviceId') {
|
||||
delete this._byServiceId[oldValue];
|
||||
}
|
||||
if (idProp === 'pni') {
|
||||
delete this._byPni[oldValue];
|
||||
|
@ -5308,11 +5311,11 @@ window.Whisper.ConversationCollection = window.Backbone.Collection.extend({
|
|||
if (e164) {
|
||||
this._byE164[e164] = model;
|
||||
}
|
||||
const uuid = model.get('uuid');
|
||||
if (uuid) {
|
||||
this._byUuid[uuid] = model;
|
||||
const serviceId = model.getServiceId();
|
||||
if (serviceId) {
|
||||
this._byServiceId[serviceId] = model;
|
||||
}
|
||||
const pni = model.get('pni');
|
||||
const pni = model.getPni();
|
||||
if (pni) {
|
||||
this._byPni[pni] = model;
|
||||
}
|
||||
|
@ -5340,28 +5343,28 @@ window.Whisper.ConversationCollection = window.Backbone.Collection.extend({
|
|||
if (e164) {
|
||||
const existing = this._byE164[e164];
|
||||
|
||||
// Prefer the contact with both e164 and uuid
|
||||
if (!existing || (existing && !existing.get('uuid'))) {
|
||||
// Prefer the contact with both e164 and serviceId
|
||||
if (!existing || (existing && !existing.getServiceId())) {
|
||||
this._byE164[e164] = model;
|
||||
}
|
||||
}
|
||||
|
||||
const uuid = model.get('uuid');
|
||||
if (uuid) {
|
||||
const existing = this._byUuid[uuid];
|
||||
const serviceId = model.getServiceId();
|
||||
if (serviceId) {
|
||||
const existing = this._byServiceId[serviceId];
|
||||
|
||||
// Prefer the contact with both e164 and uuid
|
||||
// Prefer the contact with both e164 and seviceId
|
||||
if (!existing || (existing && !existing.get('e164'))) {
|
||||
this._byUuid[uuid] = model;
|
||||
this._byServiceId[serviceId] = model;
|
||||
}
|
||||
}
|
||||
|
||||
const pni = model.get('pni');
|
||||
const pni = model.getPni();
|
||||
if (pni) {
|
||||
const existing = this._byPni[pni];
|
||||
|
||||
// Prefer the contact with both uuid and pni
|
||||
if (!existing || (existing && !existing.get('uuid'))) {
|
||||
// Prefer the contact with both serviceId and pni
|
||||
if (!existing || (existing && !existing.getServiceId())) {
|
||||
this._byPni[pni] = model;
|
||||
}
|
||||
}
|
||||
|
@ -5375,7 +5378,7 @@ window.Whisper.ConversationCollection = window.Backbone.Collection.extend({
|
|||
|
||||
eraseLookups() {
|
||||
this._byE164 = Object.create(null);
|
||||
this._byUuid = Object.create(null);
|
||||
this._byServiceId = Object.create(null);
|
||||
this._byPni = Object.create(null);
|
||||
this._byGroupId = Object.create(null);
|
||||
},
|
||||
|
@ -5427,7 +5430,7 @@ window.Whisper.ConversationCollection = window.Backbone.Collection.extend({
|
|||
|
||||
/**
|
||||
* window.Backbone collections have a `_byId` field that `get` defers to. Here, we
|
||||
* override `get` to first access our custom `_byE164`, `_byUuid`, and
|
||||
* override `get` to first access our custom `_byE164`, `_byServiceId`, and
|
||||
* `_byGroupId` functions, followed by falling back to the original
|
||||
* window.Backbone implementation.
|
||||
*/
|
||||
|
@ -5435,7 +5438,7 @@ window.Whisper.ConversationCollection = window.Backbone.Collection.extend({
|
|||
return (
|
||||
this._byE164[id] ||
|
||||
this._byE164[`+${id}`] ||
|
||||
this._byUuid[id] ||
|
||||
this._byServiceId[id] ||
|
||||
this._byPni[id] ||
|
||||
this._byGroupId[id] ||
|
||||
window.Backbone.Collection.prototype.get.call(this, id)
|
||||
|
|
|
@ -45,7 +45,7 @@ import { getMessageSentTimestamp } from '../util/getMessageSentTimestamp';
|
|||
|
||||
import type { ReactionType } from '../types/Reactions';
|
||||
import type { ServiceIdString } from '../types/ServiceId';
|
||||
import { normalizeServiceId } from '../types/ServiceId';
|
||||
import { isAciString, normalizeServiceId } from '../types/ServiceId';
|
||||
import * as reactionUtil from '../reactions/util';
|
||||
import * as Stickers from '../types/Stickers';
|
||||
import * as Errors from '../types/errors';
|
||||
|
@ -133,7 +133,7 @@ import { cleanupMessage, deleteMessageData } from '../util/cleanup';
|
|||
import {
|
||||
getContact,
|
||||
getSource,
|
||||
getSourceUuid,
|
||||
getSourceServiceId,
|
||||
isCustomError,
|
||||
messageHasPaymentEvent,
|
||||
isQuoteAMatch,
|
||||
|
@ -294,13 +294,13 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
getSenderIdentifier(): string {
|
||||
const sentAt = this.get('sent_at');
|
||||
const source = this.get('source');
|
||||
const sourceUuid = this.get('sourceUuid');
|
||||
const sourceServiceId = this.get('sourceServiceId');
|
||||
const sourceDevice = this.get('sourceDevice');
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const conversation = window.ConversationController.lookupOrCreate({
|
||||
e164: source,
|
||||
uuid: sourceUuid,
|
||||
serviceId: sourceServiceId,
|
||||
reason: 'MessageModel.getSenderIdentifier',
|
||||
})!;
|
||||
|
||||
|
@ -372,7 +372,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
attachment: undefined,
|
||||
// This is ok to do because story replies only show in 1:1 conversations
|
||||
// so the story that was quoted should be from the same conversation.
|
||||
authorUuid: conversation?.get('uuid'),
|
||||
authorAci: conversation?.getAci(),
|
||||
// No messageId, referenced story not found!
|
||||
messageId: '',
|
||||
},
|
||||
|
@ -389,10 +389,12 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
attachment = undefined;
|
||||
}
|
||||
|
||||
const { sourceServiceId: authorAci } = message;
|
||||
strictAssert(isAciString(authorAci), 'Story message from pni');
|
||||
this.set({
|
||||
storyReplyContext: {
|
||||
attachment,
|
||||
authorUuid: message.sourceUuid,
|
||||
authorAci,
|
||||
messageId: message.id,
|
||||
},
|
||||
});
|
||||
|
@ -510,7 +512,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
}
|
||||
|
||||
if (messageHasPaymentEvent(attributes)) {
|
||||
const sender = findAndFormatContact(attributes.sourceUuid);
|
||||
const sender = findAndFormatContact(attributes.sourceServiceId);
|
||||
const conversation = findAndFormatContact(attributes.conversationId);
|
||||
return {
|
||||
text: getPaymentEventNotificationText(
|
||||
|
@ -850,7 +852,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
|
||||
if (
|
||||
attributes.type === 'incoming' &&
|
||||
attributes.storyReaction.targetAuthorUuid === ourAci
|
||||
attributes.storyReaction.targetAuthorAci === ourAci
|
||||
) {
|
||||
return window.i18n('icu:Quote__story-reaction-notification--incoming', {
|
||||
emoji: attributes.storyReaction.emoji,
|
||||
|
@ -990,11 +992,11 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
|
||||
if (!fromSync) {
|
||||
const senderE164 = getSource(this.attributes);
|
||||
const senderUuid = getSourceUuid(this.attributes);
|
||||
const senderAci = getSourceServiceId(this.attributes);
|
||||
const timestamp = this.get('sent_at');
|
||||
|
||||
if (senderUuid === undefined) {
|
||||
throw new Error('markViewOnceMessageViewed: senderUuid is undefined');
|
||||
if (senderAci === undefined || !isAciString(senderAci)) {
|
||||
throw new Error('markViewOnceMessageViewed: senderAci is undefined');
|
||||
}
|
||||
|
||||
if (window.ConversationController.areWePrimaryDevice()) {
|
||||
|
@ -1009,7 +1011,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
viewOnceOpens: [
|
||||
{
|
||||
senderE164,
|
||||
senderUuid,
|
||||
senderAci,
|
||||
timestamp,
|
||||
},
|
||||
],
|
||||
|
@ -1050,8 +1052,8 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
return;
|
||||
}
|
||||
|
||||
const { authorUuid, author, id: sentAt, referencedMessageNotFound } = quote;
|
||||
const contact = window.ConversationController.get(authorUuid || author);
|
||||
const { authorAci, author, id: sentAt, referencedMessageNotFound } = quote;
|
||||
const contact = window.ConversationController.get(authorAci || author);
|
||||
|
||||
// Is the quote really without a reference? Check with our in memory store
|
||||
// first to make sure it's not there.
|
||||
|
@ -1289,12 +1291,15 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
if (!isIncoming(this.attributes)) {
|
||||
return null;
|
||||
}
|
||||
const sourceUuid = this.get('sourceUuid');
|
||||
if (!sourceUuid) {
|
||||
const sourceServiceId = this.get('sourceServiceId');
|
||||
if (!sourceServiceId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return window.ConversationController.getOrCreate(sourceUuid, 'private');
|
||||
return window.ConversationController.getOrCreate(
|
||||
sourceServiceId,
|
||||
'private'
|
||||
);
|
||||
}
|
||||
|
||||
async retrySend(): Promise<void> {
|
||||
|
@ -1318,7 +1323,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
|
||||
currentConversationRecipients = new Set(
|
||||
storyDistribution.members
|
||||
.map(uuid => window.ConversationController.get(uuid)?.id)
|
||||
.map(serviceId => window.ConversationController.get(serviceId)?.id)
|
||||
.filter(isNotNil)
|
||||
);
|
||||
} else {
|
||||
|
@ -1947,9 +1952,8 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
strictAssert(id, 'Quote must have an id');
|
||||
|
||||
const result: QuotedMessageType = {
|
||||
...omit(quote, 'authorAci'),
|
||||
...quote,
|
||||
|
||||
authorUuid: quote.authorAci,
|
||||
id,
|
||||
|
||||
attachments: quote.attachments.slice(),
|
||||
|
@ -2135,7 +2139,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||
const message = this;
|
||||
const source = message.get('source');
|
||||
const sourceUuid = message.get('sourceUuid');
|
||||
const sourceServiceId = message.get('sourceServiceId');
|
||||
const type = message.get('type');
|
||||
const conversationId = message.get('conversationId');
|
||||
|
||||
|
@ -2210,7 +2214,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
|
||||
const destinationConversation =
|
||||
window.ConversationController.lookupOrCreate({
|
||||
uuid: destinationServiceId,
|
||||
serviceId: destinationServiceId,
|
||||
e164: destination || undefined,
|
||||
reason: `handleDataMessage(${initialMessage.timestamp})`,
|
||||
});
|
||||
|
@ -2344,7 +2348,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const sender = window.ConversationController.lookupOrCreate({
|
||||
e164: source,
|
||||
uuid: sourceUuid,
|
||||
serviceId: sourceServiceId,
|
||||
reason: 'handleDataMessage',
|
||||
})!;
|
||||
const hasGroupV2Prop = Boolean(initialMessage.groupV2);
|
||||
|
@ -2352,7 +2356,8 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
// Drop if from blocked user. Only GroupV2 messages should need to be dropped here.
|
||||
const isBlocked =
|
||||
(source && window.storage.blocked.isBlocked(source)) ||
|
||||
(sourceUuid && window.storage.blocked.isUuidBlocked(sourceUuid));
|
||||
(sourceServiceId &&
|
||||
window.storage.blocked.isServiceIdBlocked(sourceServiceId));
|
||||
if (isBlocked) {
|
||||
log.info(
|
||||
`${idLog}: Dropping message from blocked sender. hasGroupV2Prop: ${hasGroupV2Prop}`
|
||||
|
@ -2371,7 +2376,8 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
type === 'incoming' &&
|
||||
!isDirectConversation(conversation.attributes) &&
|
||||
hasGroupV2Prop &&
|
||||
(!areWeMember || (sourceUuid && !conversation.hasMember(sourceUuid)))
|
||||
(!areWeMember ||
|
||||
(sourceServiceId && !conversation.hasMember(sourceServiceId)))
|
||||
) {
|
||||
log.warn(
|
||||
`${idLog}: Received message destined for group, which we or the sender are not a part of. Dropping.`
|
||||
|
@ -2423,11 +2429,15 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
// The queue can be paused easily.
|
||||
drop(
|
||||
window.Whisper.deliveryReceiptQueue.add(() => {
|
||||
strictAssert(
|
||||
isAciString(sourceServiceId),
|
||||
'Incoming message must be from ACI'
|
||||
);
|
||||
window.Whisper.deliveryReceiptBatcher.add({
|
||||
messageId,
|
||||
conversationId,
|
||||
senderE164: source,
|
||||
senderUuid: sourceUuid,
|
||||
senderAci: sourceServiceId,
|
||||
timestamp: this.get('sent_at'),
|
||||
isDirectConversation: isDirectConversation(
|
||||
conversation.attributes
|
||||
|
@ -2456,7 +2466,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
const sendState = sendStateByConversationId[sender.id];
|
||||
|
||||
const storyQuoteIsFromSelf =
|
||||
candidateQuote.get('sourceUuid') ===
|
||||
candidateQuote.get('sourceServiceId') ===
|
||||
window.storage.user.getCheckedAci();
|
||||
|
||||
if (!storyQuoteIsFromSelf) {
|
||||
|
@ -2573,7 +2583,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
}
|
||||
|
||||
const ourPni = window.textsecure.storage.user.getCheckedPni();
|
||||
const ourUuids: Set<ServiceIdString> = new Set([ourAci, ourPni]);
|
||||
const ourServiceIds: Set<ServiceIdString> = new Set([ourAci, ourPni]);
|
||||
|
||||
message.set({
|
||||
id: messageId,
|
||||
|
@ -2594,9 +2604,9 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
if (!BodyRange.isMention(bodyRange)) {
|
||||
return false;
|
||||
}
|
||||
return ourUuids.has(
|
||||
return ourServiceIds.has(
|
||||
normalizeServiceId(
|
||||
bodyRange.mentionUuid,
|
||||
bodyRange.mentionAci,
|
||||
'handleDataMessage: mentionsMe check'
|
||||
)
|
||||
);
|
||||
|
@ -2675,7 +2685,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
message.set({
|
||||
expirationTimerUpdate: {
|
||||
source,
|
||||
sourceUuid,
|
||||
sourceServiceId,
|
||||
expireTimer: initialMessage.expireTimer,
|
||||
},
|
||||
});
|
||||
|
@ -2697,7 +2707,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
// point and these calls will return early.
|
||||
if (dataMessage.expireTimer) {
|
||||
void conversation.updateExpirationTimer(dataMessage.expireTimer, {
|
||||
source: sourceUuid || source,
|
||||
source: sourceServiceId || source,
|
||||
receivedAt: message.get('received_at'),
|
||||
receivedAtMS: message.get('received_at_ms'),
|
||||
sentAt: message.get('sent_at'),
|
||||
|
@ -2710,7 +2720,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
!isEndSession(message.attributes)
|
||||
) {
|
||||
void conversation.updateExpirationTimer(undefined, {
|
||||
source: sourceUuid || source,
|
||||
source: sourceServiceId || source,
|
||||
receivedAt: message.get('received_at'),
|
||||
receivedAtMS: message.get('received_at_ms'),
|
||||
sentAt: message.get('sent_at'),
|
||||
|
@ -2723,7 +2733,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
const { profileKey } = initialMessage;
|
||||
if (
|
||||
source === window.textsecure.storage.user.getNumber() ||
|
||||
sourceUuid === window.textsecure.storage.user.getAci()
|
||||
sourceServiceId === window.textsecure.storage.user.getAci()
|
||||
) {
|
||||
conversation.set({ profileSharing: true });
|
||||
} else if (isDirectConversation(conversation.attributes)) {
|
||||
|
@ -2731,7 +2741,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
} else {
|
||||
const local = window.ConversationController.lookupOrCreate({
|
||||
e164: source,
|
||||
uuid: sourceUuid,
|
||||
serviceId: sourceServiceId,
|
||||
reason: 'handleDataMessage:setProfileKey',
|
||||
});
|
||||
void local?.setProfileKey(profileKey);
|
||||
|
@ -2952,7 +2962,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
const newReaction: MessageReactionType = {
|
||||
emoji: reaction.get('remove') ? undefined : reaction.get('emoji'),
|
||||
fromId: reaction.get('fromId'),
|
||||
targetAuthorUuid: reaction.get('targetAuthorUuid'),
|
||||
targetAuthorAci: reaction.get('targetAuthorAci'),
|
||||
targetTimestamp: reaction.get('targetTimestamp'),
|
||||
timestamp: reaction.get('timestamp'),
|
||||
isSentByConversationId: isFromThisDevice
|
||||
|
@ -3001,7 +3011,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
storyId: storyMessage.id,
|
||||
storyReaction: {
|
||||
emoji: reaction.get('emoji'),
|
||||
targetAuthorUuid: reaction.get('targetAuthorUuid'),
|
||||
targetAuthorAci: reaction.get('targetAuthorAci'),
|
||||
targetTimestamp: reaction.get('targetTimestamp'),
|
||||
},
|
||||
});
|
||||
|
@ -3097,7 +3107,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
await window.Signal.Data.removeReactionFromConversation({
|
||||
emoji: reaction.get('emoji'),
|
||||
fromId: reaction.get('fromId'),
|
||||
targetAuthorServiceId: reaction.get('targetAuthorUuid'),
|
||||
targetAuthorServiceId: reaction.get('targetAuthorAci'),
|
||||
targetTimestamp: reaction.get('targetTimestamp'),
|
||||
});
|
||||
} else {
|
||||
|
@ -3135,7 +3145,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
fromId: reaction.get('fromId'),
|
||||
messageId: this.id,
|
||||
messageReceivedAt: this.get('received_at'),
|
||||
targetAuthorUuid: reaction.get('targetAuthorUuid'),
|
||||
targetAuthorAci: reaction.get('targetAuthorAci'),
|
||||
targetTimestamp: reaction.get('targetTimestamp'),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import Fuse from 'fuse.js';
|
|||
import { get } from 'lodash';
|
||||
|
||||
import type { ConversationType } from '../state/ducks/conversations';
|
||||
import type { ServiceIdString } from '../types/ServiceId';
|
||||
import { filter, map } from '../util/iterables';
|
||||
import { removeDiacritics } from '../util/removeDiacritics';
|
||||
|
||||
|
@ -67,9 +68,13 @@ export class MemberRepository {
|
|||
: undefined;
|
||||
}
|
||||
|
||||
getMemberByUuid(uuid?: string): ConversationType | undefined {
|
||||
return uuid
|
||||
? this.members.find(({ uuid: memberUuid }) => memberUuid === uuid)
|
||||
getMemberByServiceId(
|
||||
serviceId?: ServiceIdString
|
||||
): ConversationType | undefined {
|
||||
return serviceId
|
||||
? this.members.find(
|
||||
({ serviceId: memberServiceId }) => memberServiceId === serviceId
|
||||
)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,21 +33,21 @@ export class MentionBlot extends Embed {
|
|||
}
|
||||
|
||||
static override value(node: HTMLElement): MentionBlotValue {
|
||||
const { uuid, title } = node.dataset;
|
||||
if (uuid === undefined || title === undefined) {
|
||||
const { aci, title } = node.dataset;
|
||||
if (aci === undefined || title === undefined) {
|
||||
throw new Error(
|
||||
`Failed to make MentionBlot with uuid: ${uuid}, title: ${title}`
|
||||
`Failed to make MentionBlot with aci: ${aci}, title: ${title}`
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
uuid: normalizeAci(uuid, 'quill mention blot'),
|
||||
aci: normalizeAci(aci, 'quill mention blot'),
|
||||
title,
|
||||
};
|
||||
}
|
||||
|
||||
static buildSpan(mention: MentionBlotValue, node: HTMLElement): void {
|
||||
node.setAttribute('data-uuid', mention.uuid || '');
|
||||
node.setAttribute('data-aci', mention.aci || '');
|
||||
node.setAttribute('data-title', mention.title || '');
|
||||
node.setAttribute('contenteditable', 'false');
|
||||
|
||||
|
|
|
@ -261,7 +261,7 @@ export class MentionCompletion {
|
|||
{memberResults.map((member, index) => (
|
||||
<button
|
||||
type="button"
|
||||
key={member.uuid}
|
||||
key={member.serviceId}
|
||||
id={`mention-result--${member.name}`}
|
||||
role="option button"
|
||||
aria-selected={memberResultsIndex === index}
|
||||
|
|
|
@ -5,6 +5,8 @@ import Delta from 'quill-delta';
|
|||
import type { RefObject } from 'react';
|
||||
import type { Matcher, AttributeMap } from 'quill';
|
||||
|
||||
import { assertDev } from '../../util/assert';
|
||||
import { isAciString } from '../../types/ServiceId';
|
||||
import type { MemberRepository } from '../memberRepository';
|
||||
|
||||
export const matchMention: (
|
||||
|
@ -21,12 +23,14 @@ export const matchMention: (
|
|||
const { id } = node.dataset;
|
||||
const conversation = memberRepository.getMemberById(id);
|
||||
|
||||
if (conversation && conversation.uuid) {
|
||||
if (conversation && conversation.serviceId) {
|
||||
const { serviceId: aci } = conversation;
|
||||
assertDev(isAciString(aci), 'Mentioned conversation has no ACI');
|
||||
return new Delta().insert(
|
||||
{
|
||||
mention: {
|
||||
title,
|
||||
uuid: conversation.uuid,
|
||||
aci,
|
||||
},
|
||||
},
|
||||
attributes
|
||||
|
@ -37,15 +41,20 @@ export const matchMention: (
|
|||
}
|
||||
|
||||
if (node.classList.contains('mention-blot')) {
|
||||
const { uuid } = node.dataset;
|
||||
const conversation = memberRepository.getMemberByUuid(uuid);
|
||||
const { aci } = node.dataset;
|
||||
assertDev(isAciString(aci), 'Mentioned blot has invalid ACI');
|
||||
const conversation = memberRepository.getMemberByServiceId(aci);
|
||||
|
||||
if (conversation && conversation.uuid) {
|
||||
if (conversation && conversation.serviceId) {
|
||||
assertDev(
|
||||
conversation.serviceId === aci,
|
||||
'Mentioned conversation has no ACI'
|
||||
);
|
||||
return new Delta().insert(
|
||||
{
|
||||
mention: {
|
||||
title: title || conversation.title,
|
||||
uuid: conversation.uuid,
|
||||
aci,
|
||||
},
|
||||
},
|
||||
attributes
|
||||
|
|
|
@ -18,7 +18,7 @@ import { isNotNil } from '../util/isNotNil';
|
|||
import type { AciString } from '../types/ServiceId';
|
||||
|
||||
export type MentionBlotValue = {
|
||||
uuid: AciString;
|
||||
aci: AciString;
|
||||
title: string;
|
||||
};
|
||||
|
||||
|
@ -185,7 +185,7 @@ export const getTextAndRangesFromOps = (
|
|||
if (isInsertMentionOp(op)) {
|
||||
startingBodyRanges.push({
|
||||
length: 1, // The length of `\uFFFC`
|
||||
mentionUuid: op.insert.mention.uuid,
|
||||
mentionAci: op.insert.mention.aci,
|
||||
replacementText: op.insert.mention.title,
|
||||
start: acc.length,
|
||||
});
|
||||
|
@ -291,13 +291,13 @@ export const getDeltaToRestartMention = (ops: Array<Op>): Delta => {
|
|||
|
||||
export const getDeltaToRemoveStaleMentions = (
|
||||
ops: Array<Op>,
|
||||
memberUuids: Array<string>
|
||||
memberAcis: Array<AciString>
|
||||
): Delta => {
|
||||
const newOps = ops.reduce((memo, op) => {
|
||||
if (op.insert) {
|
||||
if (
|
||||
isInsertMentionOp(op) &&
|
||||
!memberUuids.includes(op.insert.mention.uuid)
|
||||
!memberAcis.includes(op.insert.mention.aci)
|
||||
) {
|
||||
const deleteOp = { delete: 1 };
|
||||
const textOp = { insert: `@${op.insert.mention.title}` };
|
||||
|
@ -360,7 +360,7 @@ export const insertMentionOps = (
|
|||
return;
|
||||
}
|
||||
|
||||
const { start, length, mentionUuid, replacementText } = bodyRange;
|
||||
const { start, length, mentionAci, replacementText } = bodyRange;
|
||||
|
||||
const op = ops.shift();
|
||||
|
||||
|
@ -372,7 +372,7 @@ export const insertMentionOps = (
|
|||
const right = insert.slice(start + length);
|
||||
|
||||
const mention = {
|
||||
uuid: mentionUuid,
|
||||
aci: mentionAci,
|
||||
title: replacementText,
|
||||
};
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import { v4 as generateUuid } from 'uuid';
|
|||
import { ReactionModel } from '../messageModifiers/Reactions';
|
||||
import { ReactionSource } from './ReactionSource';
|
||||
import { getMessageById } from '../messages/getMessageById';
|
||||
import { getSourceUuid, isStory } from '../messages/helpers';
|
||||
import { getSourceServiceId, isStory } from '../messages/helpers';
|
||||
import { strictAssert } from '../util/assert';
|
||||
import { isDirectConversation } from '../util/whatTypeOfConversation';
|
||||
import { incrementMessageCounter } from '../util/incrementMessageCounter';
|
||||
|
@ -28,13 +28,13 @@ export async function enqueueReactionForSend({
|
|||
const message = await getMessageById(messageId);
|
||||
strictAssert(message, 'enqueueReactionForSend: no message found');
|
||||
|
||||
const targetAuthorUuid = getSourceUuid(message.attributes);
|
||||
const targetAuthorAci = getSourceServiceId(message.attributes);
|
||||
strictAssert(
|
||||
targetAuthorUuid,
|
||||
targetAuthorAci,
|
||||
`enqueueReactionForSend: message ${message.idForLogging()} had no source UUID`
|
||||
);
|
||||
strictAssert(
|
||||
isAciString(targetAuthorUuid),
|
||||
isAciString(targetAuthorAci),
|
||||
`enqueueReactionForSend: message ${message.idForLogging()} had no source ACI`
|
||||
);
|
||||
|
||||
|
@ -56,7 +56,7 @@ export async function enqueueReactionForSend({
|
|||
const isMessageAStory = isStory(message.attributes);
|
||||
const targetConversation =
|
||||
isMessageAStory && isDirectConversation(messageConversation.attributes)
|
||||
? window.ConversationController.get(targetAuthorUuid)
|
||||
? window.ConversationController.get(targetAuthorAci)
|
||||
: messageConversation;
|
||||
strictAssert(
|
||||
targetConversation,
|
||||
|
@ -92,7 +92,7 @@ export async function enqueueReactionForSend({
|
|||
storyId: message.id,
|
||||
storyReaction: {
|
||||
emoji,
|
||||
targetAuthorUuid,
|
||||
targetAuthorAci,
|
||||
targetTimestamp,
|
||||
},
|
||||
})
|
||||
|
@ -104,7 +104,7 @@ export async function enqueueReactionForSend({
|
|||
remove,
|
||||
source: ReactionSource.FromThisDevice,
|
||||
storyReactionMessage,
|
||||
targetAuthorUuid,
|
||||
targetAuthorAci,
|
||||
targetTimestamp,
|
||||
timestamp,
|
||||
});
|
||||
|
|
|
@ -136,7 +136,7 @@ export async function routineProfileRefresh({
|
|||
|
||||
totalCount += 1;
|
||||
try {
|
||||
await getProfileFn(conversation.get('uuid'), conversation.get('e164'));
|
||||
await getProfileFn(conversation.getServiceId(), conversation.get('e164'));
|
||||
log.info(
|
||||
`${logId}: refreshed profile for ${conversation.idForLogging()}`
|
||||
);
|
||||
|
@ -203,7 +203,7 @@ function* getFilteredConversations(
|
|||
c =>
|
||||
isDirectConversation(c.attributes) &&
|
||||
!c.isUnregisteredAndStale() &&
|
||||
c.get('uuid')
|
||||
c.getServiceId()
|
||||
);
|
||||
const sorted = sortBy(filtered, c => c.get('profileLastFetchedAt') || 0);
|
||||
|
||||
|
|
|
@ -369,9 +369,9 @@ export class CallingClass {
|
|||
RingRTC.handleGroupCallRingUpdate =
|
||||
this.handleGroupCallRingUpdate.bind(this);
|
||||
|
||||
this.attemptToGiveOurUuidToRingRtc();
|
||||
this.attemptToGiveOurServiceIdToRingRtc();
|
||||
window.Whisper.events.on('userChanged', () => {
|
||||
this.attemptToGiveOurUuidToRingRtc();
|
||||
this.attemptToGiveOurServiceIdToRingRtc();
|
||||
});
|
||||
|
||||
ipcRenderer.on('stop-screen-share', () => {
|
||||
|
@ -381,7 +381,7 @@ export class CallingClass {
|
|||
void this.cleanExpiredGroupCallRingsAndLoop();
|
||||
}
|
||||
|
||||
private attemptToGiveOurUuidToRingRtc(): void {
|
||||
private attemptToGiveOurServiceIdToRingRtc(): void {
|
||||
const ourAci = window.textsecure.storage.user.getAci();
|
||||
if (!ourAci) {
|
||||
// This can happen if we're not linked. It's okay if we hit this case.
|
||||
|
@ -610,7 +610,7 @@ export class CallingClass {
|
|||
return getMembershipList(conversationId).map(
|
||||
member =>
|
||||
new GroupMemberInfo(
|
||||
Buffer.from(uuidToBytes(member.uuid)),
|
||||
Buffer.from(uuidToBytes(member.aci)),
|
||||
Buffer.from(member.uuidCiphertext)
|
||||
)
|
||||
);
|
||||
|
|
|
@ -5,7 +5,7 @@ import PQueue from 'p-queue';
|
|||
|
||||
import type { ContactSyncEvent } from '../textsecure/messageReceiverEvents';
|
||||
import type { ModifiedContactDetails } from '../textsecure/ContactsParser';
|
||||
import { normalizeServiceId } from '../types/ServiceId';
|
||||
import { normalizeAci } from '../types/ServiceId';
|
||||
import * as Conversation from '../types/Conversation';
|
||||
import * as Errors from '../types/errors';
|
||||
import type { ValidateConversationType } from '../model-types.d';
|
||||
|
@ -91,7 +91,7 @@ async function doContactSync({
|
|||
for (const details of contacts) {
|
||||
const partialConversation: ValidateConversationType = {
|
||||
e164: details.number,
|
||||
uuid: normalizeServiceId(details.aci, 'doContactSync'),
|
||||
serviceId: normalizeAci(details.aci, 'doContactSync'),
|
||||
type: 'private',
|
||||
};
|
||||
|
||||
|
@ -106,7 +106,7 @@ async function doContactSync({
|
|||
|
||||
const { conversation } = window.ConversationController.maybeMergeContacts({
|
||||
e164: details.number,
|
||||
aci: details.aci,
|
||||
aci: normalizeAci(details.aci, 'contactSync.aci'),
|
||||
reason: logId,
|
||||
});
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import * as durations from '../util/durations';
|
|||
import { BackOff } from '../util/BackOff';
|
||||
import { sleep } from '../util/sleep';
|
||||
import { toDayMillis } from '../util/timestamp';
|
||||
import { toAciObject, toPniObject, toTaggedPni } from '../types/ServiceId';
|
||||
import * as log from '../logging/log';
|
||||
|
||||
export const GROUP_CREDENTIALS_KEY = 'groupCredentials';
|
||||
|
@ -150,10 +151,15 @@ export async function maybeFetchNewCredentials(): Promise<void> {
|
|||
serverPublicParamsBase64
|
||||
);
|
||||
|
||||
const { pni, credentials: rawCredentials } = await server.getGroupCredentials(
|
||||
{ startDayInMs, endDayInMs }
|
||||
// Received credentials depend on us knowing up-to-date PNI. Use the latest
|
||||
// value from the server and log error on mismatch.
|
||||
const { pni: untaggedPni, credentials: rawCredentials } =
|
||||
await server.getGroupCredentials({ startDayInMs, endDayInMs });
|
||||
strictAssert(
|
||||
untaggedPni,
|
||||
'Server must give pni along with group credentials'
|
||||
);
|
||||
strictAssert(pni, 'Server must give pni along with group credentials');
|
||||
const pni = toTaggedPni(untaggedPni);
|
||||
|
||||
const localPni = window.storage.user.getPni();
|
||||
if (pni !== localPni) {
|
||||
|
@ -163,9 +169,9 @@ export async function maybeFetchNewCredentials(): Promise<void> {
|
|||
const newCredentials = sortCredentials(rawCredentials).map(
|
||||
(item: GroupCredentialType) => {
|
||||
const authCredential =
|
||||
clientZKAuthOperations.receiveAuthCredentialWithPni(
|
||||
aci,
|
||||
pni,
|
||||
clientZKAuthOperations.receiveAuthCredentialWithPniAsServiceId(
|
||||
toAciObject(aci),
|
||||
toPniObject(pni),
|
||||
item.redemptionTime,
|
||||
new AuthCredentialWithPniResponse(
|
||||
Buffer.from(item.credential, 'base64')
|
||||
|
|
|
@ -23,7 +23,7 @@ type NotificationDataType = Readonly<{
|
|||
notificationIconAbsolutePath?: undefined | string;
|
||||
reaction?: {
|
||||
emoji: string;
|
||||
targetAuthorUuid: string;
|
||||
targetAuthorAci: string;
|
||||
targetTimestamp: number;
|
||||
};
|
||||
senderTitle: string;
|
||||
|
@ -240,18 +240,18 @@ class NotificationService extends EventEmitter {
|
|||
// Remove the last notification if both conditions hold:
|
||||
//
|
||||
// 1. Either `conversationId` or `messageId` matches (if present)
|
||||
// 2. `emoji`, `targetAuthorUuid`, `targetTimestamp` matches (if present)
|
||||
// 2. `emoji`, `targetAuthorAci`, `targetTimestamp` matches (if present)
|
||||
public removeBy({
|
||||
conversationId,
|
||||
messageId,
|
||||
emoji,
|
||||
targetAuthorUuid,
|
||||
targetAuthorAci,
|
||||
targetTimestamp,
|
||||
}: Readonly<{
|
||||
conversationId?: string;
|
||||
messageId?: string;
|
||||
emoji?: string;
|
||||
targetAuthorUuid?: string;
|
||||
targetAuthorAci?: string;
|
||||
targetTimestamp?: number;
|
||||
}>): void {
|
||||
if (!this.notificationData) {
|
||||
|
@ -280,10 +280,10 @@ class NotificationService extends EventEmitter {
|
|||
if (
|
||||
reaction &&
|
||||
emoji &&
|
||||
targetAuthorUuid &&
|
||||
targetAuthorAci &&
|
||||
targetTimestamp &&
|
||||
(reaction.emoji !== emoji ||
|
||||
reaction.targetAuthorUuid !== targetAuthorUuid ||
|
||||
reaction.targetAuthorAci !== targetAuthorAci ||
|
||||
reaction.targetTimestamp !== targetTimestamp)
|
||||
) {
|
||||
return;
|
||||
|
|
|
@ -81,7 +81,7 @@ export class ProfileService {
|
|||
);
|
||||
}
|
||||
|
||||
if (window.ConversationController.isSignalConversation(conversationId)) {
|
||||
if (window.ConversationController.isSignalConversationId(conversationId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -252,7 +252,7 @@ async function generateManifest(
|
|||
identifierType = ITEM_TYPE.ACCOUNT;
|
||||
} else if (conversationType === ConversationTypes.Direct) {
|
||||
// Contacts must have UUID
|
||||
if (!conversation.get('uuid')) {
|
||||
if (!conversation.getServiceId()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -335,7 +335,7 @@ export function toAccountRecord(
|
|||
if (pinnedConversation.get('type') === 'private') {
|
||||
pinnedConversationRecord.identifier = 'contact';
|
||||
pinnedConversationRecord.contact = {
|
||||
uuid: pinnedConversation.get('uuid'),
|
||||
serviceId: pinnedConversation.getServiceId(),
|
||||
e164: pinnedConversation.get('e164'),
|
||||
};
|
||||
} else if (isGroupV1(pinnedConversation.attributes)) {
|
||||
|
@ -1000,7 +1000,7 @@ export async function mergeContactRecord(
|
|||
});
|
||||
|
||||
// We're going to ignore this; it's likely a PNI-only contact we've already merged
|
||||
if (conversation.get('uuid') !== serviceId) {
|
||||
if (conversation.getServiceId() !== serviceId) {
|
||||
log.warn(
|
||||
`mergeContactRecord: ${conversation.idForLogging()} ` +
|
||||
`with storageId ${conversation.get('storageID')} ` +
|
||||
|
@ -1319,14 +1319,19 @@ export async function mergeAccountRecord(
|
|||
let conversation: ConversationModel | undefined;
|
||||
|
||||
if (contact) {
|
||||
if (!contact.uuid && !contact.e164) {
|
||||
if (!contact.serviceId && !contact.e164) {
|
||||
log.error(
|
||||
'storageService.mergeAccountRecord: No uuid or e164 on contact'
|
||||
'storageService.mergeAccountRecord: No serviceId or e164 on contact'
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
conversation = window.ConversationController.lookupOrCreate({
|
||||
uuid: contact.uuid,
|
||||
serviceId: contact.serviceId
|
||||
? normalizeServiceId(
|
||||
contact.serviceId,
|
||||
'AccountRecord.pin.serviceId'
|
||||
)
|
||||
: undefined,
|
||||
e164: contact.e164,
|
||||
reason: 'storageService.mergeAccountRecord',
|
||||
});
|
||||
|
@ -1616,13 +1621,13 @@ export async function mergeStoryDistributionListRecord(
|
|||
|
||||
const localMembersListSet = new Set(localStoryDistributionList.members);
|
||||
const toAdd: Array<ServiceIdString> = remoteListMembers.filter(
|
||||
uuid => !localMembersListSet.has(uuid)
|
||||
serviceId => !localMembersListSet.has(serviceId)
|
||||
);
|
||||
|
||||
const remoteMemberListSet = new Set(remoteListMembers);
|
||||
const toRemove: Array<ServiceIdString> =
|
||||
localStoryDistributionList.members.filter(
|
||||
uuid => !remoteMemberListSet.has(uuid)
|
||||
serviceId => !remoteMemberListSet.has(serviceId)
|
||||
);
|
||||
|
||||
details.push('updated');
|
||||
|
|
|
@ -112,7 +112,7 @@ export function getStoryDataFromMessageAttributes(
|
|||
'readStatus',
|
||||
'sendStateByConversationId',
|
||||
'source',
|
||||
'sourceUuid',
|
||||
'sourceServiceId',
|
||||
'storyDistributionListId',
|
||||
'storyRecipientsVersion',
|
||||
'timestamp',
|
||||
|
@ -144,7 +144,7 @@ async function repairUnexpiredStories(): Promise<void> {
|
|||
const storiesWithExpiry = storyData
|
||||
.filter(
|
||||
story =>
|
||||
story.sourceUuid !== SIGNAL_ACI &&
|
||||
story.sourceServiceId !== SIGNAL_ACI &&
|
||||
(!story.expirationStartTimestamp ||
|
||||
!story.expireTimer ||
|
||||
story.expireTimer > DAY_AS_SECONDS)
|
||||
|
|
|
@ -29,7 +29,7 @@ export async function writeProfile(
|
|||
if (!model) {
|
||||
return;
|
||||
}
|
||||
await getProfile(model.get('uuid'), model.get('e164'));
|
||||
await getProfile(model.getServiceId(), model.get('e164'));
|
||||
|
||||
// Encrypt the profile data, update profile, and if needed upload the avatar
|
||||
const {
|
||||
|
|
|
@ -15,7 +15,7 @@ import { assertDev, softAssert } from '../util/assert';
|
|||
import { mapObjectWithSpec } from '../util/mapObjectWithSpec';
|
||||
import type { ObjectMappingSpecType } from '../util/mapObjectWithSpec';
|
||||
import { cleanDataForIpc } from './cleanDataForIpc';
|
||||
import type { AciString } from '../types/ServiceId';
|
||||
import type { AciString, ServiceIdString } from '../types/ServiceId';
|
||||
import createTaskWithTimeout from '../textsecure/TaskWithTimeout';
|
||||
import * as log from '../logging/log';
|
||||
import { isValidUuid } from '../util/isValidUuid';
|
||||
|
@ -514,19 +514,19 @@ function handleSearchMessageJSON(
|
|||
async function searchMessages({
|
||||
query,
|
||||
options,
|
||||
contactUuidsMatchingQuery,
|
||||
contactServiceIdsMatchingQuery,
|
||||
conversationId,
|
||||
}: {
|
||||
query: string;
|
||||
options?: { limit?: number };
|
||||
contactUuidsMatchingQuery?: Array<string>;
|
||||
contactServiceIdsMatchingQuery?: Array<ServiceIdString>;
|
||||
conversationId?: string;
|
||||
}): Promise<Array<ClientSearchResultMessageType>> {
|
||||
const messages = await channels.searchMessages({
|
||||
query,
|
||||
conversationId,
|
||||
options,
|
||||
contactUuidsMatchingQuery,
|
||||
contactServiceIdsMatchingQuery,
|
||||
});
|
||||
|
||||
return handleSearchMessageJSON(messages);
|
||||
|
|
|
@ -14,7 +14,7 @@ import type { AttachmentType } from '../types/Attachment';
|
|||
import type { BytesToStrings } from '../types/Util';
|
||||
import type { QualifiedAddressStringType } from '../types/QualifiedAddress';
|
||||
import type { StoryDistributionIdString } from '../types/StoryDistributionId';
|
||||
import type { AciString, ServiceIdString } from '../types/ServiceId';
|
||||
import type { AciString, PniString, ServiceIdString } from '../types/ServiceId';
|
||||
import type { BadgeType } from '../badges/types';
|
||||
import type { RemoveAllConfiguration } from '../types/RemoveAllConfiguration';
|
||||
import type { LoggerType } from '../types/Logging';
|
||||
|
@ -126,7 +126,7 @@ export type KyberPreKeyType = {
|
|||
isConfirmed: boolean;
|
||||
isLastResort: boolean;
|
||||
keyId: number;
|
||||
ourUuid: ServiceIdString;
|
||||
ourServiceId: ServiceIdString;
|
||||
};
|
||||
export type StoredKyberPreKeyType = KyberPreKeyType & {
|
||||
data: string;
|
||||
|
@ -136,7 +136,7 @@ export type PreKeyType = {
|
|||
|
||||
createdAt: number;
|
||||
keyId: number;
|
||||
ourUuid: ServiceIdString;
|
||||
ourServiceId: ServiceIdString;
|
||||
privateKey: Uint8Array;
|
||||
publicKey: Uint8Array;
|
||||
};
|
||||
|
@ -152,7 +152,7 @@ export type ServerSearchResultMessageType = {
|
|||
ftsSnippet: string | null;
|
||||
|
||||
// Otherwise, a matching mention will be returned
|
||||
mentionUuid: string | null;
|
||||
mentionAci: string | null;
|
||||
mentionStart: number | null;
|
||||
mentionLength: number | null;
|
||||
};
|
||||
|
@ -178,7 +178,7 @@ export type SentMessagesType = Array<string>;
|
|||
// These two are for test only
|
||||
export type SentRecipientsDBType = {
|
||||
payloadId: number;
|
||||
recipientUuid: string;
|
||||
recipientServiceId: ServiceIdString;
|
||||
deviceId: number;
|
||||
};
|
||||
export type SentMessageDBType = {
|
||||
|
@ -199,8 +199,8 @@ export type SenderKeyType = {
|
|||
export type SenderKeyIdType = SenderKeyType['id'];
|
||||
export type SessionType = {
|
||||
id: QualifiedAddressStringType;
|
||||
ourUuid: ServiceIdString;
|
||||
uuid: ServiceIdString;
|
||||
ourServiceId: ServiceIdString;
|
||||
serviceId: ServiceIdString;
|
||||
conversationId: string;
|
||||
deviceId: number;
|
||||
record: string;
|
||||
|
@ -210,7 +210,7 @@ export type SessionIdType = SessionType['id'];
|
|||
export type SignedPreKeyType = {
|
||||
confirmed: boolean;
|
||||
created_at: number;
|
||||
ourUuid: ServiceIdString;
|
||||
ourServiceId: ServiceIdString;
|
||||
id: `${ServiceIdString}:${number}`;
|
||||
keyId: number;
|
||||
privateKey: Uint8Array;
|
||||
|
@ -219,7 +219,7 @@ export type SignedPreKeyType = {
|
|||
export type StoredSignedPreKeyType = {
|
||||
confirmed: boolean;
|
||||
created_at: number;
|
||||
ourUuid: ServiceIdString;
|
||||
ourServiceId: ServiceIdString;
|
||||
id: `${ServiceIdString}:${number}`;
|
||||
keyId: number;
|
||||
privateKey: string;
|
||||
|
@ -305,10 +305,10 @@ export type UnprocessedType = {
|
|||
|
||||
messageAgeSec?: number;
|
||||
source?: string;
|
||||
sourceUuid?: ServiceIdString;
|
||||
sourceServiceId?: ServiceIdString;
|
||||
sourceDevice?: number;
|
||||
destinationUuid?: ServiceIdString;
|
||||
updatedPni?: ServiceIdString;
|
||||
destinationServiceId?: ServiceIdString;
|
||||
updatedPni?: PniString;
|
||||
serverGuid?: string;
|
||||
serverTimestamp?: number;
|
||||
decrypted?: string;
|
||||
|
@ -319,7 +319,7 @@ export type UnprocessedType = {
|
|||
|
||||
export type UnprocessedUpdateType = {
|
||||
source?: string;
|
||||
sourceUuid?: ServiceIdString;
|
||||
sourceServiceId?: ServiceIdString;
|
||||
sourceDevice?: number;
|
||||
serverGuid?: string;
|
||||
serverTimestamp?: number;
|
||||
|
@ -339,7 +339,7 @@ export type DeleteSentProtoRecipientOptionsType = Readonly<{
|
|||
}>;
|
||||
|
||||
export type DeleteSentProtoRecipientResultType = Readonly<{
|
||||
successfulPhoneNumberShares: ReadonlyArray<string>;
|
||||
successfulPhoneNumberShares: ReadonlyArray<ServiceIdString>;
|
||||
}>;
|
||||
|
||||
export type StoryDistributionType = Readonly<{
|
||||
|
@ -353,7 +353,7 @@ export type StoryDistributionType = Readonly<{
|
|||
StorageServiceFieldsType;
|
||||
export type StoryDistributionMemberType = Readonly<{
|
||||
listId: StoryDistributionIdString;
|
||||
uuid: ServiceIdString;
|
||||
serviceId: ServiceIdString;
|
||||
}>;
|
||||
export type StoryDistributionWithMembersType = Readonly<
|
||||
{
|
||||
|
@ -370,7 +370,7 @@ export type StoryReadType = Readonly<{
|
|||
|
||||
export type ReactionResultType = Pick<
|
||||
ReactionType,
|
||||
'targetAuthorUuid' | 'targetTimestamp' | 'messageId'
|
||||
'targetAuthorAci' | 'targetTimestamp' | 'messageId'
|
||||
> & { rowid: number };
|
||||
|
||||
export type GetUnreadByConversationAndMarkReadResultType = Array<
|
||||
|
@ -378,7 +378,7 @@ export type GetUnreadByConversationAndMarkReadResultType = Array<
|
|||
MessageType,
|
||||
| 'id'
|
||||
| 'source'
|
||||
| 'sourceUuid'
|
||||
| 'sourceServiceId'
|
||||
| 'sent_at'
|
||||
| 'type'
|
||||
| 'readStatus'
|
||||
|
@ -593,7 +593,7 @@ export type DataInterface = {
|
|||
_removeAllReactions: () => Promise<void>;
|
||||
getMessageBySender: (options: {
|
||||
source?: string;
|
||||
sourceUuid?: ServiceIdString;
|
||||
sourceServiceId?: ServiceIdString;
|
||||
sourceDevice?: number;
|
||||
sent_at: number;
|
||||
}) => Promise<MessageType | undefined>;
|
||||
|
@ -618,7 +618,7 @@ export type DataInterface = {
|
|||
// getOlderMessagesByConversation is JSON on server, full message on Client
|
||||
getAllStories: (options: {
|
||||
conversationId?: string;
|
||||
sourceUuid?: ServiceIdString;
|
||||
sourceServiceId?: ServiceIdString;
|
||||
}) => Promise<GetAllStoriesResultType>;
|
||||
// getNewerMessagesByConversation is JSON on server, full message on Client
|
||||
getMessageMetricsForConversation: (options: {
|
||||
|
@ -838,12 +838,12 @@ export type ServerInterface = DataInterface & {
|
|||
query,
|
||||
conversationId,
|
||||
options,
|
||||
contactUuidsMatchingQuery,
|
||||
contactServiceIdsMatchingQuery,
|
||||
}: {
|
||||
query: string;
|
||||
conversationId?: string;
|
||||
options?: { limit?: number };
|
||||
contactUuidsMatchingQuery?: Array<string>;
|
||||
contactServiceIdsMatchingQuery?: Array<ServiceIdString>;
|
||||
}) => Promise<Array<ServerSearchResultMessageType>>;
|
||||
|
||||
getRecentStoryReplies(
|
||||
|
@ -938,12 +938,12 @@ export type ClientExclusiveInterface = {
|
|||
query,
|
||||
conversationId,
|
||||
options,
|
||||
contactUuidsMatchingQuery,
|
||||
contactServiceIdsMatchingQuery,
|
||||
}: {
|
||||
query: string;
|
||||
conversationId?: string;
|
||||
options?: { limit?: number };
|
||||
contactUuidsMatchingQuery?: Array<string>;
|
||||
contactServiceIdsMatchingQuery?: Array<ServiceIdString>;
|
||||
}) => Promise<Array<ClientSearchResultMessageType>>;
|
||||
|
||||
getRecentStoryReplies(
|
||||
|
|
218
ts/sql/Server.ts
218
ts/sql/Server.ts
|
@ -716,8 +716,10 @@ async function removeKyberPreKeysByServiceId(
|
|||
serviceId: ServiceIdString
|
||||
): Promise<void> {
|
||||
const db = getInstance();
|
||||
db.prepare<Query>('DELETE FROM kyberPreKeys WHERE ourUuid IS $uuid;').run({
|
||||
uuid: serviceId,
|
||||
db.prepare<Query>(
|
||||
'DELETE FROM kyberPreKeys WHERE ourServiceId IS $serviceId;'
|
||||
).run({
|
||||
serviceId,
|
||||
});
|
||||
}
|
||||
async function removeAllKyberPreKeys(): Promise<void> {
|
||||
|
@ -748,8 +750,10 @@ async function removePreKeysByServiceId(
|
|||
serviceId: ServiceIdString
|
||||
): Promise<void> {
|
||||
const db = getInstance();
|
||||
db.prepare<Query>('DELETE FROM preKeys WHERE ourUuid IS $uuid;').run({
|
||||
uuid: serviceId,
|
||||
db.prepare<Query>(
|
||||
'DELETE FROM preKeys WHERE ourServiceId IS $serviceId;'
|
||||
).run({
|
||||
serviceId,
|
||||
});
|
||||
}
|
||||
async function removeAllPreKeys(): Promise<void> {
|
||||
|
@ -784,8 +788,10 @@ async function removeSignedPreKeysByServiceId(
|
|||
serviceId: ServiceIdString
|
||||
): Promise<void> {
|
||||
const db = getInstance();
|
||||
db.prepare<Query>('DELETE FROM signedPreKeys WHERE ourUuid IS $uuid;').run({
|
||||
uuid: serviceId,
|
||||
db.prepare<Query>(
|
||||
'DELETE FROM signedPreKeys WHERE ourServiceId IS $serviceId;'
|
||||
).run({
|
||||
serviceId,
|
||||
});
|
||||
}
|
||||
async function removeAllSignedPreKeys(): Promise<void> {
|
||||
|
@ -942,11 +948,11 @@ async function insertSentProto(
|
|||
`
|
||||
INSERT INTO sendLogRecipients (
|
||||
payloadId,
|
||||
recipientUuid,
|
||||
recipientServiceId,
|
||||
deviceId
|
||||
) VALUES (
|
||||
$id,
|
||||
$recipientUuid,
|
||||
$recipientServiceId,
|
||||
$deviceId
|
||||
);
|
||||
`
|
||||
|
@ -963,7 +969,7 @@ async function insertSentProto(
|
|||
for (const deviceId of deviceIds) {
|
||||
recipientStatement.run({
|
||||
id,
|
||||
recipientUuid: recipientServiceId,
|
||||
recipientServiceId,
|
||||
deviceId,
|
||||
});
|
||||
}
|
||||
|
@ -1043,11 +1049,11 @@ async function insertProtoRecipients({
|
|||
`
|
||||
INSERT INTO sendLogRecipients (
|
||||
payloadId,
|
||||
recipientUuid,
|
||||
recipientServiceId,
|
||||
deviceId
|
||||
) VALUES (
|
||||
$id,
|
||||
$recipientUuid,
|
||||
$recipientServiceId,
|
||||
$deviceId
|
||||
);
|
||||
`
|
||||
|
@ -1056,7 +1062,7 @@ async function insertProtoRecipients({
|
|||
for (const deviceId of deviceIds) {
|
||||
statement.run({
|
||||
id,
|
||||
recipientUuid: recipientServiceId,
|
||||
recipientServiceId,
|
||||
deviceId,
|
||||
});
|
||||
}
|
||||
|
@ -1076,7 +1082,7 @@ async function deleteSentProtoRecipient(
|
|||
// returned row.
|
||||
|
||||
return db.transaction(() => {
|
||||
const successfulPhoneNumberShares = new Array<string>();
|
||||
const successfulPhoneNumberShares = new Array<ServiceIdString>();
|
||||
|
||||
for (const item of items) {
|
||||
const { timestamp, recipientServiceId, deviceId } = item;
|
||||
|
@ -1091,10 +1097,10 @@ async function deleteSentProtoRecipient(
|
|||
ON sendLogRecipients.payloadId = sendLogPayloads.id
|
||||
WHERE
|
||||
sendLogPayloads.timestamp = $timestamp AND
|
||||
sendLogRecipients.recipientUuid = $recipientUuid AND
|
||||
sendLogRecipients.recipientServiceId = $recipientServiceId AND
|
||||
sendLogRecipients.deviceId = $deviceId;
|
||||
`
|
||||
).all({ timestamp, recipientUuid: recipientServiceId, deviceId });
|
||||
).all({ timestamp, recipientServiceId, deviceId });
|
||||
if (!rows.length) {
|
||||
continue;
|
||||
}
|
||||
|
@ -1114,20 +1120,20 @@ async function deleteSentProtoRecipient(
|
|||
DELETE FROM sendLogRecipients
|
||||
WHERE
|
||||
payloadId = $id AND
|
||||
recipientUuid = $recipientUuid AND
|
||||
recipientServiceId = $recipientServiceId AND
|
||||
deviceId = $deviceId;
|
||||
`
|
||||
).run({ id, recipientUuid: recipientServiceId, deviceId });
|
||||
).run({ id, recipientServiceId, deviceId });
|
||||
|
||||
// 3. See how many more recipient devices there were for this payload.
|
||||
const remainingDevices = prepare(
|
||||
db,
|
||||
`
|
||||
SELECT count(1) FROM sendLogRecipients
|
||||
WHERE payloadId = $id AND recipientUuid = $recipientUuid;
|
||||
WHERE payloadId = $id AND recipientServiceId = $recipientServiceId;
|
||||
`,
|
||||
{ pluck: true }
|
||||
).get({ id, recipientUuid: recipientServiceId });
|
||||
).get({ id, recipientServiceId });
|
||||
|
||||
// 4. If there are no remaining devices for this recipient and we included
|
||||
// the pni signature in the proto - return the recipient to the caller.
|
||||
|
@ -1203,12 +1209,12 @@ async function getSentProtoByRecipient({
|
|||
LEFT JOIN sendLogMessageIds ON sendLogMessageIds.payloadId = sendLogPayloads.id
|
||||
WHERE
|
||||
sendLogPayloads.timestamp = $timestamp AND
|
||||
sendLogRecipients.recipientUuid = $recipientUuid
|
||||
sendLogRecipients.recipientServiceId = $recipientServiceId
|
||||
GROUP BY sendLogPayloads.id;
|
||||
`
|
||||
).get({
|
||||
timestamp,
|
||||
recipientUuid: recipientServiceId,
|
||||
recipientServiceId,
|
||||
});
|
||||
|
||||
if (!row) {
|
||||
|
@ -1265,7 +1271,7 @@ async function _getAllSentProtoMessageIds(): Promise<Array<SentMessageDBType>> {
|
|||
const SESSIONS_TABLE = 'sessions';
|
||||
function createOrUpdateSessionSync(data: SessionType): void {
|
||||
const db = getInstance();
|
||||
const { id, conversationId, ourUuid, uuid } = data;
|
||||
const { id, conversationId, ourServiceId, serviceId } = data;
|
||||
if (!id) {
|
||||
throw new Error(
|
||||
'createOrUpdateSession: Provided data did not have a truthy id'
|
||||
|
@ -1283,22 +1289,22 @@ function createOrUpdateSessionSync(data: SessionType): void {
|
|||
INSERT OR REPLACE INTO sessions (
|
||||
id,
|
||||
conversationId,
|
||||
ourUuid,
|
||||
uuid,
|
||||
ourServiceId,
|
||||
serviceId,
|
||||
json
|
||||
) values (
|
||||
$id,
|
||||
$conversationId,
|
||||
$ourUuid,
|
||||
$uuid,
|
||||
$ourServiceId,
|
||||
$serviceId,
|
||||
$json
|
||||
)
|
||||
`
|
||||
).run({
|
||||
id,
|
||||
conversationId,
|
||||
ourUuid,
|
||||
uuid,
|
||||
ourServiceId,
|
||||
serviceId,
|
||||
json: objectToJSON(data),
|
||||
});
|
||||
}
|
||||
|
@ -1370,10 +1376,10 @@ async function removeSessionsByServiceId(
|
|||
db.prepare<Query>(
|
||||
`
|
||||
DELETE FROM sessions
|
||||
WHERE uuid = $uuid;
|
||||
WHERE serviceId = $serviceId;
|
||||
`
|
||||
).run({
|
||||
uuid: serviceId,
|
||||
serviceId,
|
||||
});
|
||||
}
|
||||
async function removeAllSessions(): Promise<void> {
|
||||
|
@ -1390,7 +1396,7 @@ async function getConversationCount(): Promise<number> {
|
|||
|
||||
function getConversationMembersList({ members, membersV2 }: ConversationType) {
|
||||
if (membersV2) {
|
||||
return membersV2.map((item: GroupV2MemberType) => item.uuid).join(' ');
|
||||
return membersV2.map((item: GroupV2MemberType) => item.aci).join(' ');
|
||||
}
|
||||
if (members) {
|
||||
return members.join(' ');
|
||||
|
@ -1412,7 +1418,7 @@ function saveConversationSync(
|
|||
profileName,
|
||||
profileLastFetchedAt,
|
||||
type,
|
||||
uuid,
|
||||
serviceId,
|
||||
} = data;
|
||||
|
||||
const membersList = getConversationMembersList(data);
|
||||
|
@ -1424,7 +1430,7 @@ function saveConversationSync(
|
|||
json,
|
||||
|
||||
e164,
|
||||
uuid,
|
||||
serviceId,
|
||||
groupId,
|
||||
|
||||
active_at,
|
||||
|
@ -1440,7 +1446,7 @@ function saveConversationSync(
|
|||
$json,
|
||||
|
||||
$e164,
|
||||
$uuid,
|
||||
$serviceId,
|
||||
$groupId,
|
||||
|
||||
$active_at,
|
||||
|
@ -1460,7 +1466,7 @@ function saveConversationSync(
|
|||
),
|
||||
|
||||
e164: e164 || null,
|
||||
uuid: uuid || null,
|
||||
serviceId: serviceId || null,
|
||||
groupId: groupId || null,
|
||||
|
||||
active_at: active_at || null,
|
||||
|
@ -1506,7 +1512,7 @@ function updateConversationSync(
|
|||
profileFamilyName,
|
||||
profileLastFetchedAt,
|
||||
e164,
|
||||
uuid,
|
||||
serviceId,
|
||||
} = data;
|
||||
|
||||
const membersList = getConversationMembersList(data);
|
||||
|
@ -1517,7 +1523,7 @@ function updateConversationSync(
|
|||
json = $json,
|
||||
|
||||
e164 = $e164,
|
||||
uuid = $uuid,
|
||||
serviceId = $serviceId,
|
||||
|
||||
active_at = $active_at,
|
||||
type = $type,
|
||||
|
@ -1536,7 +1542,7 @@ function updateConversationSync(
|
|||
),
|
||||
|
||||
e164: e164 || null,
|
||||
uuid: uuid || null,
|
||||
serviceId: serviceId || null,
|
||||
|
||||
active_at: active_at || null,
|
||||
type,
|
||||
|
@ -1668,12 +1674,12 @@ async function getAllGroupsInvolvingServiceId(
|
|||
SELECT json, profileLastFetchedAt
|
||||
FROM conversations WHERE
|
||||
type = 'group' AND
|
||||
members LIKE $uuid
|
||||
members LIKE $serviceId
|
||||
ORDER BY id ASC;
|
||||
`
|
||||
)
|
||||
.all({
|
||||
uuid: `%${serviceId}%`,
|
||||
serviceId: `%${serviceId}%`,
|
||||
});
|
||||
|
||||
return rows.map(row => rowToConversation(row));
|
||||
|
@ -1683,12 +1689,12 @@ async function searchMessages({
|
|||
query,
|
||||
options,
|
||||
conversationId,
|
||||
contactUuidsMatchingQuery,
|
||||
contactServiceIdsMatchingQuery,
|
||||
}: {
|
||||
query: string;
|
||||
options?: { limit?: number };
|
||||
conversationId?: string;
|
||||
contactUuidsMatchingQuery?: Array<string>;
|
||||
contactServiceIdsMatchingQuery?: Array<ServiceIdString>;
|
||||
}): Promise<Array<ServerSearchResultMessageType>> {
|
||||
const { limit = conversationId ? 100 : 500 } = options ?? {};
|
||||
|
||||
|
@ -1781,12 +1787,12 @@ async function searchMessages({
|
|||
|
||||
let result: Array<ServerSearchResultMessageType>;
|
||||
|
||||
if (!contactUuidsMatchingQuery?.length) {
|
||||
if (!contactServiceIdsMatchingQuery?.length) {
|
||||
const [sqlQuery, params] = sql`${ftsFragment};`;
|
||||
result = db.prepare(sqlQuery).all(params);
|
||||
} else {
|
||||
// If contactUuidsMatchingQuery is not empty, we due an OUTER JOIN between:
|
||||
// 1) the messages that mention at least one of contactUuidsMatchingQuery, and
|
||||
// If contactServiceIdsMatchingQuery is not empty, we due an OUTER JOIN between:
|
||||
// 1) the messages that mention at least one of contactServiceIdsMatchingQuery, and
|
||||
// 2) the messages that match all the search terms via FTS
|
||||
//
|
||||
// Note: this groups the results by rowid, so even if one message mentions multiple
|
||||
|
@ -1798,15 +1804,15 @@ async function searchMessages({
|
|||
COALESCE(messages.sent_at, ftsResults.sent_at) as sent_at,
|
||||
COALESCE(messages.received_at, ftsResults.received_at) as received_at,
|
||||
ftsResults.ftsSnippet,
|
||||
mentionUuid,
|
||||
mentionAci,
|
||||
start as mentionStart,
|
||||
length as mentionLength
|
||||
FROM mentions
|
||||
INNER JOIN messages
|
||||
ON
|
||||
messages.id = mentions.messageId
|
||||
AND mentions.mentionUuid IN (
|
||||
${sqlJoin(contactUuidsMatchingQuery, ', ')}
|
||||
AND mentions.mentionAci IN (
|
||||
${sqlJoin(contactServiceIdsMatchingQuery, ', ')}
|
||||
)
|
||||
AND ${
|
||||
conversationId
|
||||
|
@ -1944,7 +1950,7 @@ function saveMessageSync(
|
|||
sent_at,
|
||||
serverGuid,
|
||||
source,
|
||||
sourceUuid,
|
||||
sourceServiceId,
|
||||
sourceDevice,
|
||||
storyId,
|
||||
callId,
|
||||
|
@ -2002,7 +2008,7 @@ function saveMessageSync(
|
|||
serverGuid: serverGuid || null,
|
||||
sent_at: sent_at || null,
|
||||
source: source || null,
|
||||
sourceUuid: sourceUuid || null,
|
||||
sourceServiceId: sourceServiceId || null,
|
||||
sourceDevice: sourceDevice || null,
|
||||
storyId: storyId || null,
|
||||
callId: callId || null,
|
||||
|
@ -2035,7 +2041,7 @@ function saveMessageSync(
|
|||
serverGuid = $serverGuid,
|
||||
sent_at = $sent_at,
|
||||
source = $source,
|
||||
sourceUuid = $sourceUuid,
|
||||
sourceServiceId = $sourceServiceId,
|
||||
sourceDevice = $sourceDevice,
|
||||
storyId = $storyId,
|
||||
callId = $callId,
|
||||
|
@ -2081,7 +2087,7 @@ function saveMessageSync(
|
|||
serverGuid,
|
||||
sent_at,
|
||||
source,
|
||||
sourceUuid,
|
||||
sourceServiceId,
|
||||
sourceDevice,
|
||||
storyId,
|
||||
callId,
|
||||
|
@ -2108,7 +2114,7 @@ function saveMessageSync(
|
|||
$serverGuid,
|
||||
$sent_at,
|
||||
$source,
|
||||
$sourceUuid,
|
||||
$sourceServiceId,
|
||||
$sourceDevice,
|
||||
$storyId,
|
||||
$callId,
|
||||
|
@ -2247,12 +2253,12 @@ async function getAllMessageIds(): Promise<Array<string>> {
|
|||
|
||||
async function getMessageBySender({
|
||||
source,
|
||||
sourceUuid,
|
||||
sourceServiceId,
|
||||
sourceDevice,
|
||||
sent_at,
|
||||
}: {
|
||||
source?: string;
|
||||
sourceUuid?: ServiceIdString;
|
||||
sourceServiceId?: ServiceIdString;
|
||||
sourceDevice?: number;
|
||||
sent_at: number;
|
||||
}): Promise<MessageType | undefined> {
|
||||
|
@ -2261,14 +2267,14 @@ async function getMessageBySender({
|
|||
db,
|
||||
`
|
||||
SELECT json FROM messages WHERE
|
||||
(source = $source OR sourceUuid = $sourceUuid) AND
|
||||
(source = $source OR sourceServiceId = $sourceServiceId) AND
|
||||
sourceDevice = $sourceDevice AND
|
||||
sent_at = $sent_at
|
||||
LIMIT 2;
|
||||
`
|
||||
).all({
|
||||
source: source || null,
|
||||
sourceUuid: sourceUuid || null,
|
||||
sourceServiceId: sourceServiceId || null,
|
||||
sourceDevice: sourceDevice || null,
|
||||
sent_at,
|
||||
});
|
||||
|
@ -2277,7 +2283,7 @@ async function getMessageBySender({
|
|||
log.warn('getMessageBySender: More than one message found for', {
|
||||
sent_at,
|
||||
source,
|
||||
sourceUuid,
|
||||
sourceServiceId,
|
||||
sourceDevice,
|
||||
});
|
||||
}
|
||||
|
@ -2392,7 +2398,7 @@ async function getUnreadByConversationAndMarkRead({
|
|||
'id',
|
||||
'sent_at',
|
||||
'source',
|
||||
'sourceUuid',
|
||||
'sourceServiceId',
|
||||
'type',
|
||||
]),
|
||||
};
|
||||
|
@ -2415,7 +2421,7 @@ async function getUnreadReactionsAndMarkRead({
|
|||
const unreadMessages: Array<ReactionResultType> = db
|
||||
.prepare<Query>(
|
||||
`
|
||||
SELECT reactions.rowid, targetAuthorUuid, targetTimestamp, messageId
|
||||
SELECT reactions.rowid, targetAuthorAci, targetTimestamp, messageId
|
||||
FROM reactions
|
||||
INDEXED BY reactions_unread
|
||||
JOIN messages on messages.id IS reactions.messageId
|
||||
|
@ -2460,7 +2466,7 @@ async function markReactionAsRead(
|
|||
SELECT *
|
||||
FROM reactions
|
||||
WHERE
|
||||
targetAuthorUuid = $targetAuthorUuid AND
|
||||
targetAuthorAci = $targetAuthorAci AND
|
||||
targetTimestamp = $targetTimestamp AND
|
||||
unread = 1
|
||||
ORDER BY rowId DESC
|
||||
|
@ -2468,7 +2474,7 @@ async function markReactionAsRead(
|
|||
`
|
||||
)
|
||||
.get({
|
||||
targetAuthorUuid: targetAuthorServiceId,
|
||||
targetAuthorAci: targetAuthorServiceId,
|
||||
targetTimestamp,
|
||||
});
|
||||
|
||||
|
@ -2476,11 +2482,11 @@ async function markReactionAsRead(
|
|||
`
|
||||
UPDATE reactions SET
|
||||
unread = 0 WHERE
|
||||
targetAuthorUuid = $targetAuthorUuid AND
|
||||
targetAuthorAci = $targetAuthorAci AND
|
||||
targetTimestamp = $targetTimestamp;
|
||||
`
|
||||
).run({
|
||||
targetAuthorUuid: targetAuthorServiceId,
|
||||
targetAuthorAci: targetAuthorServiceId,
|
||||
targetTimestamp,
|
||||
});
|
||||
|
||||
|
@ -2494,7 +2500,7 @@ async function addReaction({
|
|||
fromId,
|
||||
messageId,
|
||||
messageReceivedAt,
|
||||
targetAuthorUuid,
|
||||
targetAuthorAci,
|
||||
targetTimestamp,
|
||||
}: ReactionType): Promise<void> {
|
||||
const db = getInstance();
|
||||
|
@ -2506,7 +2512,7 @@ async function addReaction({
|
|||
fromId,
|
||||
messageId,
|
||||
messageReceivedAt,
|
||||
targetAuthorUuid,
|
||||
targetAuthorAci,
|
||||
targetTimestamp,
|
||||
unread
|
||||
) VALUES (
|
||||
|
@ -2515,7 +2521,7 @@ async function addReaction({
|
|||
$fromId,
|
||||
$messageId,
|
||||
$messageReceivedAt,
|
||||
$targetAuthorUuid,
|
||||
$targetAuthorAci,
|
||||
$targetTimestamp,
|
||||
$unread
|
||||
);`
|
||||
|
@ -2526,7 +2532,7 @@ async function addReaction({
|
|||
fromId,
|
||||
messageId,
|
||||
messageReceivedAt,
|
||||
targetAuthorUuid,
|
||||
targetAuthorAci,
|
||||
targetTimestamp,
|
||||
unread: 1,
|
||||
});
|
||||
|
@ -2549,13 +2555,13 @@ async function removeReactionFromConversation({
|
|||
`DELETE FROM reactions WHERE
|
||||
emoji = $emoji AND
|
||||
fromId = $fromId AND
|
||||
targetAuthorUuid = $targetAuthorUuid AND
|
||||
targetAuthorAci = $targetAuthorAci AND
|
||||
targetTimestamp = $targetTimestamp;`
|
||||
)
|
||||
.run({
|
||||
emoji,
|
||||
fromId,
|
||||
targetAuthorUuid: targetAuthorServiceId,
|
||||
targetAuthorAci: targetAuthorServiceId,
|
||||
targetTimestamp,
|
||||
});
|
||||
}
|
||||
|
@ -2725,10 +2731,10 @@ async function getOlderMessagesByConversation(
|
|||
|
||||
async function getAllStories({
|
||||
conversationId,
|
||||
sourceUuid,
|
||||
sourceServiceId,
|
||||
}: {
|
||||
conversationId?: string;
|
||||
sourceUuid?: ServiceIdString;
|
||||
sourceServiceId?: ServiceIdString;
|
||||
}): Promise<GetAllStoriesResultType> {
|
||||
const db = getInstance();
|
||||
const rows: ReadonlyArray<{
|
||||
|
@ -2756,13 +2762,13 @@ async function getAllStories({
|
|||
WHERE
|
||||
type IS 'story' AND
|
||||
($conversationId IS NULL OR conversationId IS $conversationId) AND
|
||||
($sourceUuid IS NULL OR sourceUuid IS $sourceUuid)
|
||||
($sourceServiceId IS NULL OR sourceServiceId IS $sourceServiceId)
|
||||
ORDER BY received_at ASC, sent_at ASC;
|
||||
`
|
||||
)
|
||||
.all({
|
||||
conversationId: conversationId || null,
|
||||
sourceUuid: sourceUuid || null,
|
||||
sourceServiceId: sourceServiceId || null,
|
||||
});
|
||||
|
||||
return rows.map(row => ({
|
||||
|
@ -3396,7 +3402,7 @@ function getCallHistoryGroupDataSync(
|
|||
const [createTempTable] = sql`
|
||||
CREATE TEMP TABLE temp_callHistory_filtered_conversations (
|
||||
id TEXT,
|
||||
uuid TEXT,
|
||||
serviceId TEXT,
|
||||
groupId TEXT
|
||||
);
|
||||
`;
|
||||
|
@ -3411,8 +3417,8 @@ function getCallHistoryGroupDataSync(
|
|||
|
||||
const [insertQuery, insertParams] = sql`
|
||||
INSERT INTO temp_callHistory_filtered_conversations
|
||||
(id, uuid, groupId)
|
||||
SELECT id, uuid, groupId
|
||||
(id, serviceId, groupId)
|
||||
SELECT id, serviceId, groupId
|
||||
FROM conversations
|
||||
WHERE conversations.id IN (${idList});
|
||||
`;
|
||||
|
@ -3423,11 +3429,11 @@ function getCallHistoryGroupDataSync(
|
|||
|
||||
const innerJoin =
|
||||
conversationIds != null
|
||||
? // peerId can be a conversation id (legacy), a uuid, or a groupId
|
||||
? // peerId can be a conversation id (legacy), a serviceId, or a groupId
|
||||
sqlFragment`
|
||||
INNER JOIN temp_callHistory_filtered_conversations ON (
|
||||
temp_callHistory_filtered_conversations.id IS c.peerId
|
||||
OR temp_callHistory_filtered_conversations.uuid IS c.peerId
|
||||
OR temp_callHistory_filtered_conversations.serviceId IS c.peerId
|
||||
OR temp_callHistory_filtered_conversations.groupId IS c.peerId
|
||||
)
|
||||
`
|
||||
|
@ -3849,7 +3855,7 @@ function saveUnprocessedSync(data: UnprocessedType): string {
|
|||
attempts,
|
||||
envelope,
|
||||
source,
|
||||
sourceUuid,
|
||||
sourceServiceId,
|
||||
sourceDevice,
|
||||
serverGuid,
|
||||
serverTimestamp,
|
||||
|
@ -3872,7 +3878,7 @@ function saveUnprocessedSync(data: UnprocessedType): string {
|
|||
attempts,
|
||||
envelope,
|
||||
source,
|
||||
sourceUuid,
|
||||
sourceServiceId,
|
||||
sourceDevice,
|
||||
serverGuid,
|
||||
serverTimestamp,
|
||||
|
@ -3887,7 +3893,7 @@ function saveUnprocessedSync(data: UnprocessedType): string {
|
|||
$attempts,
|
||||
$envelope,
|
||||
$source,
|
||||
$sourceUuid,
|
||||
$sourceServiceId,
|
||||
$sourceDevice,
|
||||
$serverGuid,
|
||||
$serverTimestamp,
|
||||
|
@ -3904,7 +3910,7 @@ function saveUnprocessedSync(data: UnprocessedType): string {
|
|||
attempts,
|
||||
envelope: envelope || null,
|
||||
source: source || null,
|
||||
sourceUuid: sourceUuid || null,
|
||||
sourceServiceId: sourceServiceId || null,
|
||||
sourceDevice: sourceDevice || null,
|
||||
serverGuid: serverGuid || null,
|
||||
serverTimestamp: serverTimestamp || null,
|
||||
|
@ -3923,7 +3929,7 @@ function updateUnprocessedWithDataSync(
|
|||
const db = getInstance();
|
||||
const {
|
||||
source,
|
||||
sourceUuid,
|
||||
sourceServiceId,
|
||||
sourceDevice,
|
||||
serverGuid,
|
||||
serverTimestamp,
|
||||
|
@ -3935,7 +3941,7 @@ function updateUnprocessedWithDataSync(
|
|||
`
|
||||
UPDATE unprocessed SET
|
||||
source = $source,
|
||||
sourceUuid = $sourceUuid,
|
||||
sourceServiceId = $sourceServiceId,
|
||||
sourceDevice = $sourceDevice,
|
||||
serverGuid = $serverGuid,
|
||||
serverTimestamp = $serverTimestamp,
|
||||
|
@ -3945,7 +3951,7 @@ function updateUnprocessedWithDataSync(
|
|||
).run({
|
||||
id,
|
||||
source: source || null,
|
||||
sourceUuid: sourceUuid || null,
|
||||
sourceServiceId: sourceServiceId || null,
|
||||
sourceDevice: sourceDevice || null,
|
||||
serverGuid: serverGuid || null,
|
||||
serverTimestamp: serverTimestamp || null,
|
||||
|
@ -5238,18 +5244,18 @@ async function createNewStoryDistribution(
|
|||
`
|
||||
INSERT OR REPLACE INTO storyDistributionMembers (
|
||||
listId,
|
||||
uuid
|
||||
serviceId
|
||||
) VALUES (
|
||||
$listId,
|
||||
$uuid
|
||||
$serviceId
|
||||
);
|
||||
`
|
||||
);
|
||||
|
||||
for (const uuid of members) {
|
||||
for (const serviceId of members) {
|
||||
memberInsertStatement.run({
|
||||
listId,
|
||||
uuid,
|
||||
serviceId,
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
@ -5264,7 +5270,7 @@ async function getAllStoryDistributionsWithMembers(): Promise<
|
|||
|
||||
return allDistributions.map(list => ({
|
||||
...list,
|
||||
members: (byListId[list.id] || []).map(member => member.uuid),
|
||||
members: (byListId[list.id] || []).map(member => member.serviceId),
|
||||
}));
|
||||
}
|
||||
async function getStoryDistributionWithMembers(
|
||||
|
@ -5291,7 +5297,7 @@ async function getStoryDistributionWithMembers(
|
|||
|
||||
return {
|
||||
...hydrateStoryDistribution(storyDistribution),
|
||||
members: members.map(({ uuid }) => uuid),
|
||||
members: members.map(({ serviceId }) => serviceId),
|
||||
};
|
||||
}
|
||||
function modifyStoryDistributionSync(
|
||||
|
@ -5341,29 +5347,33 @@ function modifyStoryDistributionMembersSync(
|
|||
`
|
||||
INSERT OR REPLACE INTO storyDistributionMembers (
|
||||
listId,
|
||||
uuid
|
||||
serviceId
|
||||
) VALUES (
|
||||
$listId,
|
||||
$uuid
|
||||
$serviceId
|
||||
);
|
||||
`
|
||||
);
|
||||
|
||||
for (const uuid of toAdd) {
|
||||
for (const serviceId of toAdd) {
|
||||
memberInsertStatement.run({
|
||||
listId,
|
||||
uuid,
|
||||
serviceId,
|
||||
});
|
||||
}
|
||||
|
||||
batchMultiVarQuery(db, toRemove, (uuids: ReadonlyArray<ServiceIdString>) => {
|
||||
db.prepare<ArrayQuery>(
|
||||
`
|
||||
batchMultiVarQuery(
|
||||
db,
|
||||
toRemove,
|
||||
(serviceIds: ReadonlyArray<ServiceIdString>) => {
|
||||
const serviceIdSet = sqlJoin(serviceIds, '?');
|
||||
const [sqlQuery, sqlParams] = sql`
|
||||
DELETE FROM storyDistributionMembers
|
||||
WHERE listId = ? AND uuid IN ( ${uuids.map(() => '?').join(', ')} );
|
||||
`
|
||||
).run([listId, ...uuids]);
|
||||
});
|
||||
WHERE listId = ${listId} AND serviceId IN (${serviceIdSet});
|
||||
`;
|
||||
db.prepare(sqlQuery).run(sqlParams);
|
||||
}
|
||||
);
|
||||
}
|
||||
async function modifyStoryDistributionWithMembers(
|
||||
distribution: StoryDistributionType,
|
||||
|
@ -6372,7 +6382,7 @@ async function getUnreadEditedMessagesAndMarkRead({
|
|||
'id',
|
||||
'sent_at',
|
||||
'source',
|
||||
'sourceUuid',
|
||||
'sourceServiceId',
|
||||
'type',
|
||||
]),
|
||||
// Use the edited message timestamp
|
||||
|
|
|
@ -16,7 +16,22 @@ import {
|
|||
objectToJSON,
|
||||
} from '../util';
|
||||
import type { EmptyQuery, Query } from '../util';
|
||||
import type { MessageType, ConversationType } from '../Interface';
|
||||
|
||||
type MessageType = Readonly<{
|
||||
id: string;
|
||||
sourceUuid: string;
|
||||
groupV2Change?: {
|
||||
from?: string;
|
||||
details: Array<{ type: string }>;
|
||||
};
|
||||
invitedGV2Members?: Array<{ uuid: string }>;
|
||||
}>;
|
||||
|
||||
type ConversationType = Readonly<{
|
||||
id: string;
|
||||
members: Array<string>;
|
||||
membersV2: Array<{ uuid: string }>;
|
||||
}>;
|
||||
|
||||
export default function updateToSchemaVersion43(
|
||||
currentVersion: number,
|
||||
|
|
|
@ -4,10 +4,8 @@
|
|||
import type { Database } from '@signalapp/better-sqlite3';
|
||||
|
||||
import type { LoggerType } from '../../types/Logging';
|
||||
import type { ServiceIdString } from '../../types/ServiceId';
|
||||
import { jsonToObject } from '../util';
|
||||
import type { EmptyQuery } from '../util';
|
||||
import type { ConversationType } from '../Interface';
|
||||
|
||||
export default function updateToSchemaVersion53(
|
||||
currentVersion: number,
|
||||
|
@ -21,7 +19,13 @@ export default function updateToSchemaVersion53(
|
|||
type LegacyConversationType = {
|
||||
id: string;
|
||||
groupId: string;
|
||||
bannedMembersV2?: Array<ServiceIdString>;
|
||||
bannedMembersV2?: Array<string>;
|
||||
};
|
||||
|
||||
type ConversationType = {
|
||||
id: string;
|
||||
groupId: string;
|
||||
bannedMembersV2?: Array<{ uuid: string; timestamp: number }>;
|
||||
};
|
||||
|
||||
const updateConversationStmt = db.prepare(
|
||||
|
|
1254
ts/sql/migrations/88-service-ids.ts
Normal file
1254
ts/sql/migrations/88-service-ids.ts
Normal file
File diff suppressed because it is too large
Load diff
|
@ -63,6 +63,7 @@ import updateToSchemaVersion84 from './84-all-mentions';
|
|||
import updateToSchemaVersion85 from './85-add-kyber-keys';
|
||||
import updateToSchemaVersion86 from './86-story-replies-index';
|
||||
import updateToSchemaVersion87 from './87-calls-history-table';
|
||||
import updateToSchemaVersion88 from './88-service-ids';
|
||||
|
||||
function updateToSchemaVersion1(
|
||||
currentVersion: number,
|
||||
|
@ -1996,6 +1997,7 @@ export const SCHEMA_VERSIONS = [
|
|||
updateToSchemaVersion85,
|
||||
updateToSchemaVersion86,
|
||||
updateToSchemaVersion87,
|
||||
updateToSchemaVersion88,
|
||||
];
|
||||
|
||||
export function updateSchema(db: Database, logger: LoggerType): void {
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -508,7 +508,7 @@ function showGV2MigrationDialog(
|
|||
});
|
||||
|
||||
const invitedMemberIds = pendingMembersV2.map(
|
||||
(item: GroupV2PendingMemberType) => item.uuid
|
||||
(item: GroupV2PendingMemberType) => item.serviceId
|
||||
);
|
||||
|
||||
dispatch({
|
||||
|
|
|
@ -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');
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue